~drizzle-trunk/drizzle/development

390.1.2 by Monty Taylor
Fixed copyright headers in drizzled/
1
/* -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
2
 *  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
3
 *
1999.6.1 by kalebral at gmail
update Copyright strings to a more common format to help with creating the master debian copyright file
4
 *  Copyright (C) 2008 Sun Microsystems, Inc.
390.1.2 by Monty Taylor
Fixed copyright headers in drizzled/
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
520.6.6 by Monty Taylor
Removed sql_alloc.h from common_includes.
20
#ifndef DRIZZLED_SQL_LIST_H
21
#define DRIZZLED_SQL_LIST_H
1 by brian
clean slate
22
23
1241.9.1 by Monty Taylor
Removed global.h. Fixed all the headers.
24
#include <cstdlib>
25
#include <cassert>
322.2.2 by Mats Kindahl
Hiding THD::proc_info field and providing a setter and getter.
26
#include <utility>
398.1.5 by Monty Taylor
Removed C++ includes and std namespace from global.h.
27
#include <algorithm>
2173.2.1 by Monty Taylor
Fixes incorrect usage of include
28
#include <drizzled/memory/sql_alloc.h>
29
#include <drizzled/visibility.h>
2119.4.2 by Monty Taylor
Fixed a sun studio compile issue.
30
322.2.2 by Mats Kindahl
Hiding THD::proc_info field and providing a setter and getter.
31
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
32
namespace drizzled
33
{
34
243.1.1 by Jay Pipes
* Pulled Object_creation_ctx and Default_creation_ctx out of mysql_priv.h
35
/** Struct to handle simple linked lists. */
36
typedef struct st_sql_list {
482 by Brian Aker
Remove uint.
37
  uint32_t elements;
481 by Brian Aker
Remove all of uchar.
38
  unsigned char *first;
39
  unsigned char **next;
243.1.1 by Jay Pipes
* Pulled Object_creation_ctx and Default_creation_ctx out of mysql_priv.h
40
41
  st_sql_list() {}                              /* Remove gcc warning */
42
  inline void empty()
43
  {
44
    elements=0;
45
    first=0;
46
    next= &first;
47
  }
481 by Brian Aker
Remove all of uchar.
48
  inline void link_in_list(unsigned char *element,unsigned char **next_ptr)
243.1.1 by Jay Pipes
* Pulled Object_creation_ctx and Default_creation_ctx out of mysql_priv.h
49
  {
50
    elements++;
51
    (*next)=element;
52
    next= next_ptr;
53
    *next=0;
54
  }
55
  inline void save_and_clear(struct st_sql_list *save)
56
  {
57
    *save= *this;
58
    empty();
59
  }
60
  inline void push_front(struct st_sql_list *save)
61
  {
62
    *save->next= first;				/* link current list last */
63
    first= save->first;
64
    elements+= save->elements;
65
  }
66
  inline void push_back(struct st_sql_list *save)
67
  {
68
    if (save->first)
69
    {
70
      *next= save->first;
71
      next= save->next;
72
      elements+= save->elements;
73
    }
74
  }
75
} SQL_LIST;
1 by brian
clean slate
76
77
/*
78
  Basic single linked list
79
  Used for item and item_buffs.
80
  All list ends with a pointer to the 'end_of_list' element, which
81
  data pointer is a null pointer and the next pointer points to itself.
82
  This makes it very fast to traverse lists as we don't have to
83
  test for a specialend condition for list that can't contain a null
84
  pointer.
85
*/
86
87
88
/**
89
  list_node - a node of a single-linked list.
90
  @note We never call a destructor for instances of this class.
91
*/
92
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
93
struct list_node : public memory::SqlAlloc
1 by brian
clean slate
94
{
95
  list_node *next;
96
  void *info;
97
  list_node(void *info_par,list_node *next_par)
98
    :next(next_par),info(info_par)
99
  {}
100
  list_node()					/* For end_of_list */
101
  {
102
    info= 0;
103
    next= this;
104
  }
105
};
106
107
2119.4.2 by Monty Taylor
Fixed a sun studio compile issue.
108
extern DRIZZLED_API list_node end_of_list;
1 by brian
clean slate
109
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
110
class base_list :public memory::SqlAlloc
1 by brian
clean slate
111
{
112
protected:
113
  list_node *first,**last;
114
115
public:
482 by Brian Aker
Remove uint.
116
  uint32_t elements;
1 by brian
clean slate
117
118
  inline void empty() { elements=0; first= &end_of_list; last=&first;}
119
  inline base_list() { empty(); }
120
  /**
121
    This is a shallow copy constructor that implicitly passes the ownership
122
    from the source list to the new instance. The old instance is not
123
    updated, so both objects end up sharing the same nodes. If one of
124
    the instances then adds or removes a node, the other becomes out of
125
    sync ('last' pointer), while still operational. Some old code uses and
126
    relies on this behaviour. This logic is quite tricky: please do not use
127
    it in any new code.
128
  */
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
129
  inline base_list(const base_list &tmp) :memory::SqlAlloc()
1 by brian
clean slate
130
  {
131
    elements= tmp.elements;
132
    first= tmp.first;
133
    last= elements ? tmp.last : &first;
134
  }
644 by Brian Aker
Clean up warnings for Solaris.
135
  inline base_list(bool) { }
1 by brian
clean slate
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
  }
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
146
  inline bool push_back(void *info, memory::Root *mem_root)
1 by brian
clean slate
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)
157
  {
158
    list_node *node=new list_node(info,first);
159
    if (node)
160
    {
161
      if (last == &first)
162
	last= &node->next;
163
      first=node;
164
      elements++;
165
      return 0;
166
    }
167
    return 1;
168
  }
169
  void remove(list_node **prev)
170
  {
171
    list_node *node=(*prev)->next;
172
    if (!--elements)
173
      last= &first;
174
    else if (last == &(*prev)->next)
175
      last= prev;
176
    delete *prev;
177
    *prev=node;
178
  }
179
  inline void concat(base_list *list)
180
  {
181
    if (!list->is_empty())
182
    {
183
      *last= list->first;
184
      last= list->last;
185
      elements+= list->elements;
186
    }
187
  }
188
  inline void *pop(void)
189
  {
190
    if (first == &end_of_list) return 0;
191
    list_node *tmp=first;
192
    first=first->next;
193
    if (!--elements)
194
      last= &first;
195
    return tmp->info;
196
  }
197
  inline void disjoin(base_list *list)
198
  {
199
    list_node **prev= &first;
200
    list_node *node= first;
201
    list_node *list_first= list->first;
202
    elements=0;
203
    while (node && node != list_first)
204
    {
205
      prev= &node->next;
206
      node= node->next;
207
      elements++;
208
    }
209
    *prev= *last;
210
    last= prev;
211
  }
212
  inline void prepand(base_list *list)
213
  {
214
    if (!list->is_empty())
215
    {
216
      *list->last= first;
217
      first= list->first;
218
      elements+= list->elements;
219
    }
220
  }
221
  /**
222
    Swap two lists.
223
  */
224
  inline void swap(base_list &rhs)
225
  {
322.2.2 by Mats Kindahl
Hiding THD::proc_info field and providing a setter and getter.
226
    std::swap(first, rhs.first);
227
    std::swap(last, rhs.last);
228
    std::swap(elements, rhs.elements);
1 by brian
clean slate
229
  }
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; }
236
  friend class base_list_iterator;
237
  friend class error_list;
238
  friend class error_list_iterator;
239
240
#ifdef LIST_EXTRA_DEBUG
241
  /*
242
    Check list invariants and print results into trace. Invariants are:
243
      - (*last) points to end_of_list
244
      - There are no NULLs in the list.
245
      - base_list::elements is the number of elements in the list.
246
247
    SYNOPSIS
248
      check_list()
249
        name  Name to print to trace file
250
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
251
    RETURN
1 by brian
clean slate
252
      1  The list is Ok.
253
      0  List invariants are not met.
254
  */
255
256
  bool check_list(const char *name)
257
  {
258
    base_list *list= this;
259
    list_node *node= first;
482 by Brian Aker
Remove uint.
260
    uint32_t cnt= 0;
1 by brian
clean slate
261
262
    while (node->next != &end_of_list)
263
    {
264
      if (!node->info)
265
      {
51.1.53 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
266
        return false;
1 by brian
clean slate
267
      }
268
      node= node->next;
269
      cnt++;
270
    }
271
    if (last != &(node->next))
272
    {
51.1.53 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
273
      return false;
1 by brian
clean slate
274
    }
275
    if (cnt+1 != elements)
276
    {
51.1.53 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
277
      return false;
1 by brian
clean slate
278
    }
51.1.53 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
279
    return true;
1 by brian
clean slate
280
  }
281
#endif // LIST_EXTRA_DEBUG
282
283
protected:
284
  void after(void *info,list_node *node)
285
  {
286
    list_node *new_node=new list_node(info,node->next);
287
    node->next=new_node;
288
    elements++;
289
    if (last == &(node->next))
290
      last= &new_node->next;
291
  }
292
};
293
294
295
class base_list_iterator
296
{
297
protected:
298
  base_list *list;
299
  list_node **el,**prev,*current;
482 by Brian Aker
Remove uint.
300
  void sublist(base_list &ls, uint32_t elm)
1 by brian
clean slate
301
  {
302
    ls.first= *el;
303
    ls.last= list->last;
304
    ls.elements= elm;
305
  }
306
public:
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
307
  base_list_iterator()
1 by brian
clean slate
308
    :list(0), el(0), prev(0), current(0)
309
  {}
310
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
311
  base_list_iterator(base_list &list_par)
1 by brian
clean slate
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;
51.1.53 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
343
    assert(current->info != 0);
1 by brian
clean slate
344
    current->info=element;
345
    return tmp;
346
  }
347
  void *replace(base_list &new_list)
348
  {
349
    void *ret_value=current->info;
350
    if (!new_list.is_empty())
351
    {
352
      *new_list.last=current->next;
353
      current->info=new_list.first->info;
354
      current->next=new_list.first->next;
355
      if ((list->last == &current->next) && (new_list.elements > 1))
356
	list->last= new_list.last;
357
      list->elements+=new_list.elements-1;
358
    }
359
    return ret_value;				// return old element
360
  }
361
  inline void remove(void)			// Remove current
362
  {
363
    list->remove(prev);
364
    el=prev;
365
    current=0;					// Safeguard
366
  }
367
  void after(void *element)			// Insert element after current
368
  {
369
    list->after(element,current);
370
    current=current->next;
371
    el= &current->next;
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;
382
};
383
384
template <class T> class List :public base_list
385
{
386
public:
387
  inline List() :base_list() {}
388
  inline List(const List<T> &tmp) :base_list(tmp) {}
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
389
  inline List(const List<T> &tmp, memory::Root *mem_root) :
1 by brian
clean slate
390
    base_list(tmp, mem_root) {}
391
  inline bool push_back(T *a) { return base_list::push_back(a); }
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
392
  inline bool push_back(T *a, memory::Root *mem_root)
1 by brian
clean slate
393
  { return base_list::push_back(a, mem_root); }
394
  inline bool push_front(T *a) { return base_list::push_front(a); }
2160.1.4 by Olaf van der Spek
casts
395
  inline T* head() {return static_cast<T*>(base_list::head()); }
396
  inline T** head_ref() {return static_cast<T**>(base_list::head_ref()); }
397
  inline T* pop()  {return static_cast<T*>(base_list::pop()); }
1 by brian
clean slate
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)
402
  {
403
    list_node *element,*next;
404
    for (element=first; element != &end_of_list; element=next)
405
    {
406
      next=element->next;
407
      delete (T*) element->info;
408
    }
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:
644 by Brian Aker
Clean up warnings for Solaris.
433
  inline T *replace(T *)   { return (T*) 0; }
434
  inline T *replace(List<T> &) { return (T*) 0; }
1 by brian
clean slate
435
  inline void remove(void)  { }
1891.2.1 by Monty Taylor
Fixed things to make things compile with clang
436
  inline void after(T *)   { }
1 by brian
clean slate
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(); }
482 by Brian Aker
Remove uint.
445
  void sublist(List<T> &list_arg, uint32_t el_arg)
1 by brian
clean slate
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
520.1.21 by Brian Aker
THD -> Session rename
463
  @return You must query the error state in Session for out-of-memory
1 by brian
clean slate
464
  situation after calling this function.
465
*/
466
467
template <typename T>
468
inline
469
void
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
470
list_copy_and_replace_each_value(List<T> &list, memory::Root *mem_root)
1 by brian
clean slate
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
}
478
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
479
} /* namespace drizzled */
584.1.15 by Monty Taylor
The mega-patch from hell. Renamed sql_class to session (since that's what it is) and removed it and field and table from common_includes.
480
1122.2.10 by Monty Taylor
Fixed all of the include guards.
481
#endif /* DRIZZLED_SQL_LIST_H */