~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/sql_list.h

  • Committer: Monty Taylor
  • Date: 2009-03-03 07:39:39 UTC
  • mto: This revision was merged to the branch mainline in revision 910.
  • Revision ID: mordred@inaugust.com-20090303073939-rfswfdo68klfcp1o
Updated comment version indicators to handle drizzle versions.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/* -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
2
2
 *  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
3
3
 *
4
 
 *  Copyright (C) 2008 Sun Microsystems, Inc.
 
4
 *  Copyright (C) 2008 Sun Microsystems
5
5
 *
6
6
 *  This program is free software; you can redistribute it and/or modify
7
7
 *  it under the terms of the GNU General Public License as published by
20
20
#ifndef DRIZZLED_SQL_LIST_H
21
21
#define DRIZZLED_SQL_LIST_H
22
22
 
23
 
#include <cstdlib>
24
 
#include <cassert>
 
23
 
25
24
#include <utility>
26
25
#include <algorithm>
27
 
#include <drizzled/memory/sql_alloc.h>
28
 
#include <drizzled/visibility.h>
29
 
 
30
 
namespace drizzled {
31
 
 
32
 
typedef struct st_sql_list 
33
 
{
 
26
#include <stdlib.h>
 
27
#include <drizzled/sql_alloc.h>
 
28
 
 
29
/** Struct to handle simple linked lists. */
 
30
typedef struct st_sql_list {
34
31
  uint32_t elements;
35
32
  unsigned char *first;
36
33
  unsigned char **next;
37
34
 
38
 
  inline void clear()
 
35
  st_sql_list() {}                              /* Remove gcc warning */
 
36
  inline void empty()
39
37
  {
40
38
    elements=0;
41
39
    first=0;
51
49
  inline void save_and_clear(struct st_sql_list *save)
52
50
  {
53
51
    *save= *this;
54
 
    clear();
 
52
    empty();
55
53
  }
56
54
  inline void push_front(struct st_sql_list *save)
57
55
  {
86
84
  @note We never call a destructor for instances of this class.
87
85
*/
88
86
 
89
 
struct list_node : public memory::SqlAlloc
 
87
struct list_node :public Sql_alloc
90
88
{
91
89
  list_node *next;
92
90
  void *info;
101
99
};
102
100
 
103
101
 
104
 
extern DRIZZLED_API list_node end_of_list;
 
102
extern list_node end_of_list;
105
103
 
106
 
class base_list :public memory::SqlAlloc
 
104
class base_list :public Sql_alloc
107
105
{
108
106
protected:
109
107
  list_node *first,**last;
111
109
public:
112
110
  uint32_t elements;
113
111
 
114
 
  inline void clear() { elements=0; first= &end_of_list; last=&first;}
115
 
  inline base_list() { clear(); }
 
112
  inline void empty() { elements=0; first= &end_of_list; last=&first;}
 
113
  inline base_list() { empty(); }
116
114
  /**
117
115
    This is a shallow copy constructor that implicitly passes the ownership
118
116
    from the source list to the new instance. The old instance is not
122
120
    relies on this behaviour. This logic is quite tricky: please do not use
123
121
    it in any new code.
124
122
  */
125
 
  inline base_list(const base_list &tmp) :memory::SqlAlloc()
 
123
  inline base_list(const base_list &tmp) :Sql_alloc()
126
124
  {
127
125
    elements= tmp.elements;
128
126
    first= tmp.first;
129
127
    last= elements ? tmp.last : &first;
130
128
  }
 
129
  /**
 
130
    Construct a deep copy of the argument in memory root mem_root.
 
131
    The elements themselves are copied by pointer. If you also
 
132
    need to copy elements by value, you should employ
 
133
    list_copy_and_replace_each_value after creating a copy.
 
134
  */
 
135
  base_list(const base_list &rhs, MEM_ROOT *mem_root);
131
136
  inline base_list(bool) { }
132
137
  inline bool push_back(void *info)
133
138
  {
139
144
    }
140
145
    return 1;
141
146
  }
142
 
  inline bool push_back(void *info, memory::Root *mem_root)
 
147
  inline bool push_back(void *info, MEM_ROOT *mem_root)
143
148
  {
144
149
    if (((*last)=new (mem_root) list_node(info, &end_of_list)))
145
150
    {
230
235
  inline bool is_empty() { return first == &end_of_list ; }
231
236
  inline list_node *last_ref() { return &end_of_list; }
232
237
  friend class base_list_iterator;
 
238
  friend class error_list;
 
239
  friend class error_list_iterator;
233
240
 
234
241
#ifdef LIST_EXTRA_DEBUG
235
242
  /*
291
298
protected:
292
299
  base_list *list;
293
300
  list_node **el,**prev,*current;
294
 
public:
295
301
  void sublist(base_list &ls, uint32_t elm)
296
302
  {
297
303
    ls.first= *el;
298
304
    ls.last= list->last;
299
305
    ls.elements= elm;
300
306
  }
 
307
public:
301
308
  base_list_iterator()
302
309
    :list(0), el(0), prev(0), current(0)
303
310
  {}
304
311
 
305
 
  base_list_iterator(base_list &list_par, list_node** el0)
306
 
    :list(&list_par), el(el0), prev(0), current(0)
 
312
  base_list_iterator(base_list &list_par)
 
313
  { init(list_par); }
 
314
 
 
315
  inline void init(base_list &list_par)
307
316
  {
 
317
    list= &list_par;
 
318
    el= &list_par.first;
 
319
    prev= 0;
 
320
    current= 0;
308
321
  }
309
322
 
310
323
  inline void *next(void)
314
327
    el= &current->next;
315
328
    return current->info;
316
329
  }
 
330
  inline void *next_fast(void)
 
331
  {
 
332
    list_node *tmp;
 
333
    tmp= *el;
 
334
    el= &tmp->next;
 
335
    return tmp->info;
 
336
  }
 
337
  inline void rewind(void)
 
338
  {
 
339
    el= &list->first;
 
340
  }
317
341
  inline void *replace(void *element)
318
342
  {                                             // Return old element
319
343
    void *tmp=current->info;
355
379
  {
356
380
    return el == &list->last_ref()->next;
357
381
  }
 
382
  friend class error_list_iterator;
358
383
};
359
384
 
360
 
template <class T> class List_iterator;
361
 
 
362
385
template <class T> class List :public base_list
363
386
{
364
387
public:
365
 
  typedef List_iterator<T> iterator;
366
 
 
367
 
  friend class List_iterator<T>;
368
 
 
369
388
  inline List() :base_list() {}
370
389
  inline List(const List<T> &tmp) :base_list(tmp) {}
371
 
  inline List(const List<T> &tmp, memory::Root *mem_root) :
 
390
  inline List(const List<T> &tmp, MEM_ROOT *mem_root) :
372
391
    base_list(tmp, mem_root) {}
373
392
  inline bool push_back(T *a) { return base_list::push_back(a); }
374
 
  inline bool push_back(T *a, memory::Root *mem_root)
 
393
  inline bool push_back(T *a, MEM_ROOT *mem_root)
375
394
  { return base_list::push_back(a, mem_root); }
376
395
  inline bool push_front(T *a) { return base_list::push_front(a); }
377
 
  inline T* head() {return static_cast<T*>(base_list::head()); }
378
 
  inline T* pop()  {return static_cast<T*>(base_list::pop()); }
 
396
  inline T* head() {return (T*) base_list::head(); }
 
397
  inline T** head_ref() {return (T**) base_list::head_ref(); }
 
398
  inline T* pop()  {return (T*) base_list::pop(); }
379
399
  inline void concat(List<T> *list) { base_list::concat(list); }
380
400
  inline void disjoin(List<T> *list) { base_list::disjoin(list); }
381
401
  inline void prepand(List<T> *list) { base_list::prepand(list); }
387
407
      next=element->next;
388
408
      delete (T*) element->info;
389
409
    }
390
 
    clear();
391
 
  }
392
 
 
393
 
  iterator begin()
394
 
  {
395
 
    return iterator(*this, &first);
 
410
    empty();
396
411
  }
397
412
};
398
413
 
400
415
template <class T> class List_iterator :public base_list_iterator
401
416
{
402
417
public:
403
 
  List_iterator(List<T>& a, list_node** b) : base_list_iterator(a, b) {};
404
 
  List_iterator() {};
 
418
  List_iterator(List<T> &a) : base_list_iterator(a) {}
 
419
  List_iterator() : base_list_iterator() {}
 
420
  inline void init(List<T> &a) { base_list_iterator::init(a); }
405
421
  inline T* operator++(int) { return (T*) base_list_iterator::next(); }
406
422
  inline T *replace(T *a)   { return (T*) base_list_iterator::replace(a); }
407
423
  inline T *replace(List<T> &a) { return (T*) base_list_iterator::replace(a); }
 
424
  inline void rewind(void)  { base_list_iterator::rewind(); }
 
425
  inline void remove()      { base_list_iterator::remove(); }
 
426
  inline void after(T *a)   { base_list_iterator::after(a); }
408
427
  inline T** ref(void)      { return (T**) base_list_iterator::ref(); }
409
428
};
410
429
 
 
430
 
 
431
template <class T> class List_iterator_fast :public base_list_iterator
 
432
{
 
433
protected:
 
434
  inline T *replace(T *)   { return (T*) 0; }
 
435
  inline T *replace(List<T> &) { return (T*) 0; }
 
436
  inline void remove(void)  { }
 
437
  inline void after(T *a)   { }
 
438
  inline T** ref(void)      { return (T**) 0; }
 
439
 
 
440
public:
 
441
  inline List_iterator_fast(List<T> &a) : base_list_iterator(a) {}
 
442
  inline List_iterator_fast() : base_list_iterator() {}
 
443
  inline void init(List<T> &a) { base_list_iterator::init(a); }
 
444
  inline T* operator++(int) { return (T*) base_list_iterator::next_fast(); }
 
445
  inline void rewind(void)  { base_list_iterator::rewind(); }
 
446
  void sublist(List<T> &list_arg, uint32_t el_arg)
 
447
  {
 
448
    base_list_iterator::sublist(list_arg, el_arg);
 
449
  }
 
450
};
 
451
 
 
452
 
 
453
/*
 
454
  A simple intrusive list which automaticly removes element from list
 
455
  on delete (for Session element)
 
456
*/
 
457
 
 
458
struct ilink
 
459
{
 
460
  struct ilink **prev,*next;
 
461
  static void *operator new(size_t size)
 
462
  {
 
463
    return (void*)malloc((uint32_t)size);
 
464
  }
 
465
  static void operator delete(void* ptr_arg, size_t)
 
466
  {
 
467
     free((unsigned char*)ptr_arg);
 
468
  }
 
469
 
 
470
  inline ilink()
 
471
  {
 
472
    prev=0; next=0;
 
473
  }
 
474
  inline void unlink()
 
475
  {
 
476
    /* Extra tests because element doesn't have to be linked */
 
477
    if (prev) *prev= next;
 
478
    if (next) next->prev=prev;
 
479
    prev=0 ; next=0;
 
480
  }
 
481
  virtual ~ilink() { unlink(); }                /*lint -e1740 */
 
482
};
 
483
 
 
484
 
 
485
/* Needed to be able to have an I_List of char* strings in mysqld.cc. */
 
486
 
 
487
class i_string: public ilink
 
488
{
 
489
public:
 
490
  const char* ptr;
 
491
  i_string():ptr(0) { }
 
492
  i_string(const char* s) : ptr(s) {}
 
493
};
 
494
 
 
495
/* needed for linked list of two strings for replicate-rewrite-db */
 
496
class i_string_pair: public ilink
 
497
{
 
498
public:
 
499
  const char* key;
 
500
  const char* val;
 
501
  i_string_pair():key(0),val(0) { }
 
502
  i_string_pair(const char* key_arg, const char* val_arg) :
 
503
    key(key_arg),val(val_arg) {}
 
504
};
 
505
 
 
506
 
 
507
template <class T> class I_List_iterator;
 
508
 
 
509
/*
 
510
  WARNING: copy constructor of this class does not create a usable
 
511
  copy, as its members may point at each other.
 
512
*/
 
513
 
 
514
class base_ilist
 
515
{
 
516
public:
 
517
  struct ilink *first,last;
 
518
  inline void empty() { first= &last; last.prev= &first; }
 
519
  base_ilist() { empty(); }
 
520
  inline bool is_empty() {  return first == &last; }
 
521
  inline void append(ilink *a)
 
522
  {
 
523
    first->prev= &a->next;
 
524
    a->next=first; a->prev= &first; first=a;
 
525
  }
 
526
  inline void push_back(ilink *a)
 
527
  {
 
528
    *last.prev= a;
 
529
    a->next= &last;
 
530
    a->prev= last.prev;
 
531
    last.prev= &a->next;
 
532
  }
 
533
  inline struct ilink *get()
 
534
  {
 
535
    struct ilink *first_link=first;
 
536
    if (first_link == &last)
 
537
      return 0;
 
538
    first_link->unlink();                       // Unlink from list
 
539
    return first_link;
 
540
  }
 
541
  inline struct ilink *head()
 
542
  {
 
543
    return (first != &last) ? first : 0;
 
544
  }
 
545
  friend class base_list_iterator;
 
546
};
 
547
 
 
548
 
 
549
class base_ilist_iterator
 
550
{
 
551
  base_ilist *list;
 
552
  struct ilink **el,*current;
 
553
public:
 
554
  base_ilist_iterator(base_ilist &list_par) :list(&list_par),
 
555
    el(&list_par.first),current(0) {}
 
556
  void *next(void)
 
557
  {
 
558
    /* This is coded to allow push_back() while iterating */
 
559
    current= *el;
 
560
    if (current == &list->last) return 0;
 
561
    el= &current->next;
 
562
    return current;
 
563
  }
 
564
};
 
565
 
 
566
 
 
567
template <class T>
 
568
class I_List :private base_ilist
 
569
{
 
570
public:
 
571
  I_List() :base_ilist()        {}
 
572
  inline void empty()           { base_ilist::empty(); }
 
573
  inline bool is_empty()        { return base_ilist::is_empty(); }
 
574
  inline void append(T* a)      { base_ilist::append(a); }
 
575
  inline void push_back(T* a)   { base_ilist::push_back(a); }
 
576
  inline T* get()               { return (T*) base_ilist::get(); }
 
577
  inline T* head()              { return (T*) base_ilist::head(); }
 
578
#ifndef _lint
 
579
  friend class I_List_iterator<T>;
 
580
#endif
 
581
};
 
582
 
 
583
 
 
584
template <class T> class I_List_iterator :public base_ilist_iterator
 
585
{
 
586
public:
 
587
  I_List_iterator(I_List<T> &a) : base_ilist_iterator(a) {}
 
588
  inline T* operator++(int) { return (T*) base_ilist_iterator::next(); }
 
589
};
 
590
 
411
591
/**
412
592
  Make a deep copy of each list element.
413
593
 
424
604
*/
425
605
 
426
606
template <typename T>
427
 
void list_copy_and_replace_each_value(List<T> &list, memory::Root *mem_root)
 
607
inline
 
608
void
 
609
list_copy_and_replace_each_value(List<T> &list, MEM_ROOT *mem_root)
428
610
{
429
611
  /* Make a deep copy of each element */
430
 
  typename List<T>::iterator it(list.begin());
 
612
  List_iterator<T> it(list);
431
613
  T *el;
432
614
  while ((el= it++))
433
615
    it.replace(el->clone(mem_root));
434
616
}
435
617
 
436
 
} /* namespace drizzled */
437
 
 
438
 
#endif /* DRIZZLED_SQL_LIST_H */
 
618
/* sql_list.cc */
 
619
void free_list(I_List <i_string_pair> *list);
 
620
void free_list(I_List <i_string> *list);
 
621
 
 
622
 
 
623
#endif // DRIZZLED_SQL_LIST_H