~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to server/sql_list.h

  • Committer: Brian Aker
  • Date: 2008-07-14 22:07:42 UTC
  • Revision ID: brian@tangent.org-20080714220742-y7fjh1mitrfcgfij
Second pass cleanup on removal of my_uint types

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
2
 
 *  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
3
 
 *
4
 
 *  Copyright (C) 2008 Sun Microsystems
5
 
 *
6
 
 *  This program is free software; you can redistribute it and/or modify
7
 
 *  it under the terms of the GNU General Public License as published by
8
 
 *  the Free Software Foundation; version 2 of the License.
9
 
 *
10
 
 *  This program is distributed in the hope that it will be useful,
11
 
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 
 *  GNU General Public License for more details.
14
 
 *
15
 
 *  You should have received a copy of the GNU General Public License
16
 
 *  along with this program; if not, write to the Free Software
17
 
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
18
 
 */
19
 
 
20
 
#ifndef DRIZZLED_SQL_LIST_H
21
 
#define DRIZZLED_SQL_LIST_H
22
 
 
23
 
 
24
 
#include <cstdlib>
25
 
#include <cassert>
26
 
#include <utility>
27
 
#include <algorithm>
28
 
#include "drizzled/memory/sql_alloc.h"
29
 
 
30
 
namespace drizzled
 
1
#ifndef INCLUDES_MYSQL_SQL_LIST_H
 
2
#define INCLUDES_MYSQL_SQL_LIST_H
 
3
/* Copyright (C) 2000-2003 MySQL AB
 
4
 
 
5
   This program is free software; you can redistribute it and/or modify
 
6
   it under the terms of the GNU General Public License as published by
 
7
   the Free Software Foundation; version 2 of the License.
 
8
 
 
9
   This program is distributed in the hope that it will be useful,
 
10
   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
11
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
12
   GNU General Public License for more details.
 
13
 
 
14
   You should have received a copy of the GNU General Public License
 
15
   along with this program; if not, write to the Free Software
 
16
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
 
17
 
 
18
 
 
19
#ifdef USE_PRAGMA_INTERFACE
 
20
#pragma interface                       /* gcc class implementation */
 
21
#endif
 
22
 
 
23
/* mysql standard class memory allocator */
 
24
 
 
25
class Sql_alloc
31
26
{
32
 
 
33
 
/** Struct to handle simple linked lists. */
34
 
typedef struct st_sql_list {
35
 
  uint32_t elements;
36
 
  unsigned char *first;
37
 
  unsigned char **next;
38
 
 
39
 
  st_sql_list() {}                              /* Remove gcc warning */
40
 
  inline void empty()
41
 
  {
42
 
    elements=0;
43
 
    first=0;
44
 
    next= &first;
45
 
  }
46
 
  inline void link_in_list(unsigned char *element,unsigned char **next_ptr)
47
 
  {
48
 
    elements++;
49
 
    (*next)=element;
50
 
    next= next_ptr;
51
 
    *next=0;
52
 
  }
53
 
  inline void save_and_clear(struct st_sql_list *save)
54
 
  {
55
 
    *save= *this;
56
 
    empty();
57
 
  }
58
 
  inline void push_front(struct st_sql_list *save)
59
 
  {
60
 
    *save->next= first;                         /* link current list last */
61
 
    first= save->first;
62
 
    elements+= save->elements;
63
 
  }
64
 
  inline void push_back(struct st_sql_list *save)
65
 
  {
66
 
    if (save->first)
67
 
    {
68
 
      *next= save->first;
69
 
      next= save->next;
70
 
      elements+= save->elements;
71
 
    }
72
 
  }
73
 
} SQL_LIST;
 
27
public:
 
28
  static void *operator new(size_t size) throw ()
 
29
  {
 
30
    return sql_alloc(size);
 
31
  }
 
32
  static void *operator new[](size_t size)
 
33
  {
 
34
    return sql_alloc(size);
 
35
  }
 
36
  static void *operator new[](size_t size, MEM_ROOT *mem_root) throw ()
 
37
  { return alloc_root(mem_root, size); }
 
38
  static void *operator new(size_t size, MEM_ROOT *mem_root) throw ()
 
39
  { return alloc_root(mem_root, size); }
 
40
  static void operator delete(void *ptr __attribute__((__unused__)),
 
41
                              size_t size __attribute__((__unused__)))
 
42
  { TRASH(ptr, size); }
 
43
  static void operator delete(void *ptr __attribute__((__unused__)),
 
44
                              MEM_ROOT *mem_root __attribute__((__unused__)))
 
45
  { /* never called */ }
 
46
  static void operator delete[](void *ptr __attribute__((__unused__)),
 
47
                                MEM_ROOT *mem_root __attribute__((__unused__)))
 
48
  { /* never called */ }
 
49
  static void operator delete[](void *ptr __attribute__((__unused__)),
 
50
                                size_t size __attribute__((__unused__)))
 
51
  { TRASH(ptr, size); }
 
52
#ifdef HAVE_purify
 
53
  bool dummy;
 
54
  inline Sql_alloc() :dummy(0) {}
 
55
  inline ~Sql_alloc() {}
 
56
#else
 
57
  inline Sql_alloc() {}
 
58
  inline ~Sql_alloc() {}
 
59
#endif
 
60
 
 
61
};
 
62
 
74
63
 
75
64
/*
76
65
  Basic single linked list
88
77
  @note We never call a destructor for instances of this class.
89
78
*/
90
79
 
91
 
struct list_node : public memory::SqlAlloc
 
80
struct list_node :public Sql_alloc
92
81
{
93
82
  list_node *next;
94
83
  void *info;
105
94
 
106
95
extern list_node end_of_list;
107
96
 
108
 
class base_list :public memory::SqlAlloc
 
97
class base_list :public Sql_alloc
109
98
{
110
99
protected:
111
100
  list_node *first,**last;
112
101
 
113
102
public:
114
 
  uint32_t elements;
 
103
  uint elements;
115
104
 
116
105
  inline void empty() { elements=0; first= &end_of_list; last=&first;}
117
106
  inline base_list() { empty(); }
124
113
    relies on this behaviour. This logic is quite tricky: please do not use
125
114
    it in any new code.
126
115
  */
127
 
  inline base_list(const base_list &tmp) :memory::SqlAlloc()
 
116
  inline base_list(const base_list &tmp) :Sql_alloc()
128
117
  {
129
118
    elements= tmp.elements;
130
119
    first= tmp.first;
131
120
    last= elements ? tmp.last : &first;
132
121
  }
133
 
  inline base_list(bool) { }
 
122
  /**
 
123
    Construct a deep copy of the argument in memory root mem_root.
 
124
    The elements themselves are copied by pointer. If you also
 
125
    need to copy elements by value, you should employ
 
126
    list_copy_and_replace_each_value after creating a copy.
 
127
  */
 
128
  base_list(const base_list &rhs, MEM_ROOT *mem_root);
 
129
  inline base_list(bool error __attribute__((__unused__))) { }
134
130
  inline bool push_back(void *info)
135
131
  {
136
132
    if (((*last)=new list_node(info, &end_of_list)))
141
137
    }
142
138
    return 1;
143
139
  }
144
 
  inline bool push_back(void *info, memory::Root *mem_root)
 
140
  inline bool push_back(void *info, MEM_ROOT *mem_root)
145
141
  {
146
142
    if (((*last)=new (mem_root) list_node(info, &end_of_list)))
147
143
    {
221
217
  */
222
218
  inline void swap(base_list &rhs)
223
219
  {
224
 
    std::swap(first, rhs.first);
225
 
    std::swap(last, rhs.last);
226
 
    std::swap(elements, rhs.elements);
 
220
    swap_variables(list_node *, first, rhs.first);
 
221
    swap_variables(list_node **, last, rhs.last);
 
222
    swap_variables(uint, elements, rhs.elements);
227
223
  }
228
224
  inline list_node* last_node() { return *last; }
229
225
  inline list_node* first_node() { return first;}
246
242
      check_list()
247
243
        name  Name to print to trace file
248
244
 
249
 
    RETURN
 
245
    RETURN 
250
246
      1  The list is Ok.
251
247
      0  List invariants are not met.
252
248
  */
255
251
  {
256
252
    base_list *list= this;
257
253
    list_node *node= first;
258
 
    uint32_t cnt= 0;
 
254
    uint cnt= 0;
259
255
 
260
256
    while (node->next != &end_of_list)
261
257
    {
295
291
protected:
296
292
  base_list *list;
297
293
  list_node **el,**prev,*current;
298
 
  void sublist(base_list &ls, uint32_t elm)
 
294
  void sublist(base_list &ls, uint elm)
299
295
  {
300
296
    ls.first= *el;
301
297
    ls.last= list->last;
302
298
    ls.elements= elm;
303
299
  }
304
300
public:
305
 
  base_list_iterator()
 
301
  base_list_iterator() 
306
302
    :list(0), el(0), prev(0), current(0)
307
303
  {}
308
304
 
309
 
  base_list_iterator(base_list &list_par)
 
305
  base_list_iterator(base_list &list_par) 
310
306
  { init(list_par); }
311
307
 
312
308
  inline void init(base_list &list_par)
384
380
public:
385
381
  inline List() :base_list() {}
386
382
  inline List(const List<T> &tmp) :base_list(tmp) {}
387
 
  inline List(const List<T> &tmp, memory::Root *mem_root) :
 
383
  inline List(const List<T> &tmp, MEM_ROOT *mem_root) :
388
384
    base_list(tmp, mem_root) {}
389
385
  inline bool push_back(T *a) { return base_list::push_back(a); }
390
 
  inline bool push_back(T *a, memory::Root *mem_root)
 
386
  inline bool push_back(T *a, MEM_ROOT *mem_root)
391
387
  { return base_list::push_back(a, mem_root); }
392
388
  inline bool push_front(T *a) { return base_list::push_front(a); }
393
389
  inline T* head() {return (T*) base_list::head(); }
428
424
template <class T> class List_iterator_fast :public base_list_iterator
429
425
{
430
426
protected:
431
 
  inline T *replace(T *)   { return (T*) 0; }
432
 
  inline T *replace(List<T> &) { return (T*) 0; }
 
427
  inline T *replace(T *a __attribute__((__unused__)))   { return (T*) 0; }
 
428
  inline T *replace(List<T> &a __attribute__((__unused__))) { return (T*) 0; }
433
429
  inline void remove(void)  { }
434
 
  inline void after(T *)   { }
 
430
  inline void after(T *a __attribute__((__unused__)))   { }
435
431
  inline T** ref(void)      { return (T**) 0; }
436
432
 
437
433
public:
440
436
  inline void init(List<T> &a) { base_list_iterator::init(a); }
441
437
  inline T* operator++(int) { return (T*) base_list_iterator::next_fast(); }
442
438
  inline void rewind(void)  { base_list_iterator::rewind(); }
443
 
  void sublist(List<T> &list_arg, uint32_t el_arg)
 
439
  void sublist(List<T> &list_arg, uint el_arg)
444
440
  {
445
441
    base_list_iterator::sublist(list_arg, el_arg);
446
442
  }
447
443
};
448
444
 
449
445
 
 
446
/*
 
447
  A simple intrusive list which automaticly removes element from list
 
448
  on delete (for THD element)
 
449
*/
 
450
 
 
451
struct ilink
 
452
{
 
453
  struct ilink **prev,*next;
 
454
  static void *operator new(size_t size)
 
455
  {
 
456
    return (void*)my_malloc((uint)size, MYF(MY_WME | MY_FAE | ME_FATALERROR));
 
457
  }
 
458
  static void operator delete(void* ptr_arg,
 
459
                              size_t size __attribute__((__unused__)))
 
460
  {
 
461
     my_free((uchar*)ptr_arg, MYF(MY_WME|MY_ALLOW_ZERO_PTR));
 
462
  }
 
463
 
 
464
  inline ilink()
 
465
  {
 
466
    prev=0; next=0;
 
467
  }
 
468
  inline void unlink()
 
469
  {
 
470
    /* Extra tests because element doesn't have to be linked */
 
471
    if (prev) *prev= next;
 
472
    if (next) next->prev=prev;
 
473
    prev=0 ; next=0;
 
474
  }
 
475
  virtual ~ilink() { unlink(); }                /*lint -e1740 */
 
476
};
 
477
 
 
478
 
 
479
/* Needed to be able to have an I_List of char* strings in mysqld.cc. */
 
480
 
 
481
class i_string: public ilink
 
482
{
 
483
public:
 
484
  const char* ptr;
 
485
  i_string():ptr(0) { }
 
486
  i_string(const char* s) : ptr(s) {}
 
487
};
 
488
 
 
489
/* needed for linked list of two strings for replicate-rewrite-db */
 
490
class i_string_pair: public ilink
 
491
{
 
492
public:
 
493
  const char* key;
 
494
  const char* val;
 
495
  i_string_pair():key(0),val(0) { }
 
496
  i_string_pair(const char* key_arg, const char* val_arg) : 
 
497
    key(key_arg),val(val_arg) {}
 
498
};
 
499
 
 
500
 
 
501
template <class T> class I_List_iterator;
 
502
 
 
503
/*
 
504
  WARNING: copy constructor of this class does not create a usable
 
505
  copy, as its members may point at each other.
 
506
*/
 
507
 
 
508
class base_ilist
 
509
{
 
510
public:
 
511
  struct ilink *first,last;
 
512
  inline void empty() { first= &last; last.prev= &first; }
 
513
  base_ilist() { empty(); }
 
514
  inline bool is_empty() {  return first == &last; }
 
515
  inline void append(ilink *a)
 
516
  {
 
517
    first->prev= &a->next;
 
518
    a->next=first; a->prev= &first; first=a;
 
519
  }
 
520
  inline void push_back(ilink *a)
 
521
  {
 
522
    *last.prev= a;
 
523
    a->next= &last;
 
524
    a->prev= last.prev;
 
525
    last.prev= &a->next;
 
526
  }
 
527
  inline struct ilink *get()
 
528
  {
 
529
    struct ilink *first_link=first;
 
530
    if (first_link == &last)
 
531
      return 0;
 
532
    first_link->unlink();                       // Unlink from list
 
533
    return first_link;
 
534
  }
 
535
  inline struct ilink *head()
 
536
  {
 
537
    return (first != &last) ? first : 0;
 
538
  }
 
539
  friend class base_list_iterator;
 
540
};
 
541
 
 
542
 
 
543
class base_ilist_iterator
 
544
{
 
545
  base_ilist *list;
 
546
  struct ilink **el,*current;
 
547
public:
 
548
  base_ilist_iterator(base_ilist &list_par) :list(&list_par),
 
549
    el(&list_par.first),current(0) {}
 
550
  void *next(void)
 
551
  {
 
552
    /* This is coded to allow push_back() while iterating */
 
553
    current= *el;
 
554
    if (current == &list->last) return 0;
 
555
    el= &current->next;
 
556
    return current;
 
557
  }
 
558
};
 
559
 
 
560
 
 
561
template <class T>
 
562
class I_List :private base_ilist
 
563
{
 
564
public:
 
565
  I_List() :base_ilist()        {}
 
566
  inline void empty()           { base_ilist::empty(); }
 
567
  inline bool is_empty()        { return base_ilist::is_empty(); } 
 
568
  inline void append(T* a)      { base_ilist::append(a); }
 
569
  inline void push_back(T* a)   { base_ilist::push_back(a); }
 
570
  inline T* get()               { return (T*) base_ilist::get(); }
 
571
  inline T* head()              { return (T*) base_ilist::head(); }
 
572
#ifndef _lint
 
573
  friend class I_List_iterator<T>;
 
574
#endif
 
575
};
 
576
 
 
577
 
 
578
template <class T> class I_List_iterator :public base_ilist_iterator
 
579
{
 
580
public:
 
581
  I_List_iterator(I_List<T> &a) : base_ilist_iterator(a) {}
 
582
  inline T* operator++(int) { return (T*) base_ilist_iterator::next(); }
 
583
};
 
584
 
450
585
/**
451
586
  Make a deep copy of each list element.
452
587
 
458
593
  Evidently not all template arguments have clone() method with
459
594
  the right signature.
460
595
 
461
 
  @return You must query the error state in Session for out-of-memory
 
596
  @return You must query the error state in THD for out-of-memory
462
597
  situation after calling this function.
463
598
*/
464
599
 
465
600
template <typename T>
466
601
inline
467
602
void
468
 
list_copy_and_replace_each_value(List<T> &list, memory::Root *mem_root)
 
603
list_copy_and_replace_each_value(List<T> &list, MEM_ROOT *mem_root)
469
604
{
470
605
  /* Make a deep copy of each element */
471
606
  List_iterator<T> it(list);
474
609
    it.replace(el->clone(mem_root));
475
610
}
476
611
 
477
 
} /* namespace drizzled */
478
 
 
479
 
#endif /* DRIZZLED_SQL_LIST_H */
 
612
#endif // INCLUDES_MYSQL_SQL_LIST_H