~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/sql_list.h

  • Committer: Monty Taylor
  • Date: 2011-02-13 17:26:39 UTC
  • mfrom: (2157.2.2 give-in-to-pkg-config)
  • mto: This revision was merged to the branch mainline in revision 2166.
  • Revision ID: mordred@inaugust.com-20110213172639-nhy7i72sfhoq13ms
Merged in pkg-config fixes.

Show diffs side-by-side

added added

removed removed

Lines of Context:
17
17
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
18
18
 */
19
19
 
20
 
#pragma once
 
20
#ifndef DRIZZLED_SQL_LIST_H
 
21
#define DRIZZLED_SQL_LIST_H
 
22
 
21
23
 
22
24
#include <cstdlib>
23
25
#include <cassert>
24
26
#include <utility>
25
27
#include <algorithm>
26
 
#include <drizzled/memory/sql_alloc.h>
27
 
#include <drizzled/visibility.h>
28
 
 
29
 
namespace drizzled {
30
 
 
31
 
typedef struct st_sql_list 
 
28
#include "drizzled/memory/sql_alloc.h"
 
29
#include "drizzled/visibility.h"
 
30
 
 
31
 
 
32
namespace drizzled
32
33
{
 
34
 
 
35
/** Struct to handle simple linked lists. */
 
36
typedef struct st_sql_list {
33
37
  uint32_t elements;
34
38
  unsigned char *first;
35
39
  unsigned char **next;
36
40
 
37
 
  void clear()
 
41
  st_sql_list() {}                              /* Remove gcc warning */
 
42
  inline void empty()
38
43
  {
39
44
    elements=0;
40
45
    first=0;
41
46
    next= &first;
42
47
  }
43
 
 
44
 
  size_t size() const
45
 
  {
46
 
    return elements;
47
 
  }
48
 
 
49
 
  void link_in_list(unsigned char *element,unsigned char **next_ptr)
 
48
  inline void link_in_list(unsigned char *element,unsigned char **next_ptr)
50
49
  {
51
50
    elements++;
52
51
    (*next)=element;
53
52
    next= next_ptr;
54
53
    *next=0;
55
54
  }
56
 
  void save_and_clear(struct st_sql_list *save)
 
55
  inline void save_and_clear(struct st_sql_list *save)
57
56
  {
58
57
    *save= *this;
59
 
    clear();
 
58
    empty();
60
59
  }
61
 
  void push_front(struct st_sql_list *save)
 
60
  inline void push_front(struct st_sql_list *save)
62
61
  {
63
62
    *save->next= first;                         /* link current list last */
64
63
    first= save->first;
65
64
    elements+= save->elements;
66
65
  }
67
 
  void push_back(struct st_sql_list *save)
 
66
  inline void push_back(struct st_sql_list *save)
68
67
  {
69
68
    if (save->first)
70
69
    {
105
104
  }
106
105
};
107
106
 
 
107
 
108
108
extern DRIZZLED_API list_node end_of_list;
109
109
 
110
110
class base_list :public memory::SqlAlloc
111
111
{
112
112
protected:
113
113
  list_node *first,**last;
 
114
 
 
115
public:
114
116
  uint32_t elements;
115
 
public:
116
117
 
117
 
  void clear() { elements=0; first= &end_of_list; last=&first;}
118
 
  base_list() { clear(); }
 
118
  inline void empty() { elements=0; first= &end_of_list; last=&first;}
 
119
  inline base_list() { empty(); }
119
120
  /**
120
121
    This is a shallow copy constructor that implicitly passes the ownership
121
122
    from the source list to the new instance. The old instance is not
125
126
    relies on this behaviour. This logic is quite tricky: please do not use
126
127
    it in any new code.
127
128
  */
128
 
  base_list(const base_list &tmp) :memory::SqlAlloc()
 
129
  inline base_list(const base_list &tmp) :memory::SqlAlloc()
129
130
  {
130
131
    elements= tmp.elements;
131
132
    first= tmp.first;
132
133
    last= elements ? tmp.last : &first;
133
134
  }
134
 
  base_list(bool) { }
135
 
  void push_back(void *info)
136
 
  {
137
 
    *last = new list_node(info, &end_of_list);
138
 
    last= &(*last)->next;
139
 
    elements++;
140
 
  }
141
 
  void push_back(void *info, memory::Root *mem_root)
142
 
  {
143
 
    *last = new (mem_root) list_node(info, &end_of_list);
144
 
    last= &(*last)->next;
145
 
    elements++;
146
 
  }
147
 
  void push_front(void *info)
 
135
  inline base_list(bool) { }
 
136
  inline bool push_back(void *info)
 
137
  {
 
138
    if (((*last)=new list_node(info, &end_of_list)))
 
139
    {
 
140
      last= &(*last)->next;
 
141
      elements++;
 
142
      return 0;
 
143
    }
 
144
    return 1;
 
145
  }
 
146
  inline bool push_back(void *info, memory::Root *mem_root)
 
147
  {
 
148
    if (((*last)=new (mem_root) list_node(info, &end_of_list)))
 
149
    {
 
150
      last= &(*last)->next;
 
151
      elements++;
 
152
      return 0;
 
153
    }
 
154
    return 1;
 
155
  }
 
156
  inline bool push_front(void *info)
148
157
  {
149
158
    list_node *node=new list_node(info,first);
150
 
    if (last == &first)
151
 
                        last= &node->next;
 
159
    if (node)
 
160
    {
 
161
      if (last == &first)
 
162
        last= &node->next;
152
163
      first=node;
153
164
      elements++;
 
165
      return 0;
 
166
    }
 
167
    return 1;
154
168
  }
155
169
  void remove(list_node **prev)
156
170
  {
162
176
    delete *prev;
163
177
    *prev=node;
164
178
  }
165
 
  void concat(base_list *list)
 
179
  inline void concat(base_list *list)
166
180
  {
167
181
    if (!list->is_empty())
168
182
    {
171
185
      elements+= list->elements;
172
186
    }
173
187
  }
174
 
  void *pop()
 
188
  inline void *pop(void)
175
189
  {
176
190
    if (first == &end_of_list) return 0;
177
191
    list_node *tmp=first;
180
194
      last= &first;
181
195
    return tmp->info;
182
196
  }
183
 
  void disjoin(base_list *list)
 
197
  inline void disjoin(base_list *list)
184
198
  {
185
199
    list_node **prev= &first;
186
200
    list_node *node= first;
195
209
    *prev= *last;
196
210
    last= prev;
197
211
  }
198
 
  void prepand(base_list *list)
 
212
  inline void prepand(base_list *list)
199
213
  {
200
214
    if (!list->is_empty())
201
215
    {
207
221
  /**
208
222
    Swap two lists.
209
223
  */
210
 
  void swap(base_list &rhs)
 
224
  inline void swap(base_list &rhs)
211
225
  {
212
226
    std::swap(first, rhs.first);
213
227
    std::swap(last, rhs.last);
214
228
    std::swap(elements, rhs.elements);
215
229
  }
216
 
  bool is_empty() { return first == &end_of_list ; }
 
230
  inline list_node* last_node() { return *last; }
 
231
  inline list_node* first_node() { return first;}
 
232
  inline void *head() { return first->info; }
 
233
  inline void **head_ref() { return first != &end_of_list ? &first->info : 0; }
 
234
  inline bool is_empty() { return first == &end_of_list ; }
 
235
  inline list_node *last_ref() { return &end_of_list; }
217
236
  friend class base_list_iterator;
 
237
  friend class error_list;
 
238
  friend class error_list_iterator;
218
239
 
219
240
#ifdef LIST_EXTRA_DEBUG
220
241
  /*
276
297
protected:
277
298
  base_list *list;
278
299
  list_node **el,**prev,*current;
279
 
public:
280
300
  void sublist(base_list &ls, uint32_t elm)
281
301
  {
282
302
    ls.first= *el;
283
303
    ls.last= list->last;
284
304
    ls.elements= elm;
285
305
  }
 
306
public:
286
307
  base_list_iterator()
287
308
    :list(0), el(0), prev(0), current(0)
288
309
  {}
289
310
 
290
 
  base_list_iterator(base_list &list_par, list_node** el0)
291
 
    :list(&list_par), el(el0), prev(0), current(0)
292
 
  {
293
 
  }
294
 
 
 
311
  base_list_iterator(base_list &list_par)
 
312
  { init(list_par); }
 
313
 
 
314
  inline void init(base_list &list_par)
 
315
  {
 
316
    list= &list_par;
 
317
    el= &list_par.first;
 
318
    prev= 0;
 
319
    current= 0;
 
320
  }
 
321
 
 
322
  inline void *next(void)
 
323
  {
 
324
    prev=el;
 
325
    current= *el;
 
326
    el= &current->next;
 
327
    return current->info;
 
328
  }
 
329
  inline void *next_fast(void)
 
330
  {
 
331
    list_node *tmp;
 
332
    tmp= *el;
 
333
    el= &tmp->next;
 
334
    return tmp->info;
 
335
  }
 
336
  inline void rewind(void)
 
337
  {
 
338
    el= &list->first;
 
339
  }
 
340
  inline void *replace(void *element)
 
341
  {                                             // Return old element
 
342
    void *tmp=current->info;
 
343
    assert(current->info != 0);
 
344
    current->info=element;
 
345
    return tmp;
 
346
  }
295
347
  void *replace(base_list &new_list)
296
348
  {
297
349
    void *ret_value=current->info;
300
352
      *new_list.last=current->next;
301
353
      current->info=new_list.first->info;
302
354
      current->next=new_list.first->next;
303
 
      if (list->last == &current->next && new_list.elements > 1)
304
 
        list->last= new_list.last;
 
355
      if ((list->last == &current->next) && (new_list.elements > 1))
 
356
        list->last= new_list.last;
305
357
      list->elements+=new_list.elements-1;
306
358
    }
307
359
    return ret_value;                           // return old element
308
360
  }
309
 
  void remove()                 // Remove current
 
361
  inline void remove(void)                      // Remove current
310
362
  {
311
363
    list->remove(prev);
312
364
    el=prev;
318
370
    current=current->next;
319
371
    el= &current->next;
320
372
  }
 
373
  inline void **ref(void)                       // Get reference pointer
 
374
  {
 
375
    return &current->info;
 
376
  }
 
377
  inline bool is_last(void)
 
378
  {
 
379
    return el == &list->last_ref()->next;
 
380
  }
 
381
  friend class error_list_iterator;
321
382
};
322
383
 
323
 
template <class T> class List_iterator;
324
 
 
325
 
template <class T> class List : public base_list
 
384
template <class T> class List :public base_list
326
385
{
327
386
public:
328
 
  typedef List_iterator<T> iterator;
329
 
 
330
 
  friend class List_iterator<T>;
331
 
 
332
 
  List() {}
333
 
  List(const List<T> &tmp) : base_list(tmp) {}
334
 
  List(const List<T> &tmp, memory::Root *mem_root) : base_list(tmp, mem_root) {}
335
 
  void push_back(T *a) { base_list::push_back(a); }
336
 
  void push_back(T *a, memory::Root *mem_root) { base_list::push_back(a, mem_root); }
337
 
  void push_front(T *a) { base_list::push_front(a); }
338
 
  T& front() {return *static_cast<T*>(first->info); }
339
 
  T* pop()  {return static_cast<T*>(base_list::pop()); }
340
 
  void concat(List<T> *list) { base_list::concat(list); }
341
 
  void disjoin(List<T> *list) { base_list::disjoin(list); }
342
 
  void prepand(List<T> *list) { base_list::prepand(list); }
343
 
  void delete_elements()
 
387
  inline List() :base_list() {}
 
388
  inline List(const List<T> &tmp) :base_list(tmp) {}
 
389
  inline List(const List<T> &tmp, memory::Root *mem_root) :
 
390
    base_list(tmp, mem_root) {}
 
391
  inline bool push_back(T *a) { return base_list::push_back(a); }
 
392
  inline bool push_back(T *a, memory::Root *mem_root)
 
393
  { return base_list::push_back(a, mem_root); }
 
394
  inline bool push_front(T *a) { return base_list::push_front(a); }
 
395
  inline T* head() {return (T*) base_list::head(); }
 
396
  inline T** head_ref() {return (T**) base_list::head_ref(); }
 
397
  inline T* pop()  {return (T*) base_list::pop(); }
 
398
  inline void concat(List<T> *list) { base_list::concat(list); }
 
399
  inline void disjoin(List<T> *list) { base_list::disjoin(list); }
 
400
  inline void prepand(List<T> *list) { base_list::prepand(list); }
 
401
  void delete_elements(void)
344
402
  {
345
403
    list_node *element,*next;
346
404
    for (element=first; element != &end_of_list; element=next)
348
406
      next=element->next;
349
407
      delete (T*) element->info;
350
408
    }
351
 
    clear();
352
 
  }
353
 
 
354
 
  iterator begin()
355
 
  {
356
 
    return iterator(*this, &first);
357
 
  }
358
 
 
359
 
  size_t size() const
360
 
  {
361
 
    return elements;
362
 
  }
363
 
 
364
 
  void set_size(size_t v)
365
 
  {
366
 
    elements = v;
367
 
  }
368
 
};
369
 
 
370
 
template <class T> class List_iterator : public base_list_iterator
371
 
{
372
 
public:
373
 
  List_iterator(List<T>& a, list_node** b) : base_list_iterator(a, b) {};
374
 
  List_iterator() {};
375
 
  T *operator++(int) { prev=el; current= *el; el= &current->next; return (T*)current->info; }
376
 
  T *replace(T *a)   { T* old = (T*) current->info; current->info= a; return old; }
377
 
  void replace(List<T> &a) { base_list_iterator::replace(a); }
378
 
  T** ref() { return (T**) &current->info; }
379
 
 
380
 
  T& operator*()
381
 
  {
382
 
    return *(T*)current->info;
383
 
  }
384
 
 
385
 
  T* operator->()
386
 
  {
387
 
    return (T*)current->info;
388
 
  }
389
 
};
 
409
    empty();
 
410
  }
 
411
};
 
412
 
 
413
 
 
414
template <class T> class List_iterator :public base_list_iterator
 
415
{
 
416
public:
 
417
  List_iterator(List<T> &a) : base_list_iterator(a) {}
 
418
  List_iterator() : base_list_iterator() {}
 
419
  inline void init(List<T> &a) { base_list_iterator::init(a); }
 
420
  inline T* operator++(int) { return (T*) base_list_iterator::next(); }
 
421
  inline T *replace(T *a)   { return (T*) base_list_iterator::replace(a); }
 
422
  inline T *replace(List<T> &a) { return (T*) base_list_iterator::replace(a); }
 
423
  inline void rewind(void)  { base_list_iterator::rewind(); }
 
424
  inline void remove()      { base_list_iterator::remove(); }
 
425
  inline void after(T *a)   { base_list_iterator::after(a); }
 
426
  inline T** ref(void)      { return (T**) base_list_iterator::ref(); }
 
427
};
 
428
 
 
429
 
 
430
template <class T> class List_iterator_fast :public base_list_iterator
 
431
{
 
432
protected:
 
433
  inline T *replace(T *)   { return (T*) 0; }
 
434
  inline T *replace(List<T> &) { return (T*) 0; }
 
435
  inline void remove(void)  { }
 
436
  inline void after(T *)   { }
 
437
  inline T** ref(void)      { return (T**) 0; }
 
438
 
 
439
public:
 
440
  inline List_iterator_fast(List<T> &a) : base_list_iterator(a) {}
 
441
  inline List_iterator_fast() : base_list_iterator() {}
 
442
  inline void init(List<T> &a) { base_list_iterator::init(a); }
 
443
  inline T* operator++(int) { return (T*) base_list_iterator::next_fast(); }
 
444
  inline void rewind(void)  { base_list_iterator::rewind(); }
 
445
  void sublist(List<T> &list_arg, uint32_t el_arg)
 
446
  {
 
447
    base_list_iterator::sublist(list_arg, el_arg);
 
448
  }
 
449
};
 
450
 
 
451
 
 
452
/**
 
453
  Make a deep copy of each list element.
 
454
 
 
455
  @note A template function and not a template method of class List
 
456
  is employed because of explicit template instantiation:
 
457
  in server code there are explicit instantiations of List<T> and
 
458
  an explicit instantiation of a template requires that any method
 
459
  of the instantiated class used in the template can be resolved.
 
460
  Evidently not all template arguments have clone() method with
 
461
  the right signature.
 
462
 
 
463
  @return You must query the error state in Session for out-of-memory
 
464
  situation after calling this function.
 
465
*/
 
466
 
 
467
template <typename T>
 
468
inline
 
469
void
 
470
list_copy_and_replace_each_value(List<T> &list, memory::Root *mem_root)
 
471
{
 
472
  /* Make a deep copy of each element */
 
473
  List_iterator<T> it(list);
 
474
  T *el;
 
475
  while ((el= it++))
 
476
    it.replace(el->clone(mem_root));
 
477
}
390
478
 
391
479
} /* namespace drizzled */
392
480
 
 
481
#endif /* DRIZZLED_SQL_LIST_H */