~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>
1253.1.4 by Monty Taylor
Moved sql_alloc into memory.
28
#include "drizzled/memory/sql_alloc.h"
322.2.2 by Mats Kindahl
Hiding THD::proc_info field and providing a setter and getter.
29
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
30
namespace drizzled
31
{
32
243.1.1 by Jay Pipes
* Pulled Object_creation_ctx and Default_creation_ctx out of mysql_priv.h
33
/** Struct to handle simple linked lists. */
34
typedef struct st_sql_list {
482 by Brian Aker
Remove uint.
35
  uint32_t elements;
481 by Brian Aker
Remove all of uchar.
36
  unsigned char *first;
37
  unsigned char **next;
243.1.1 by Jay Pipes
* Pulled Object_creation_ctx and Default_creation_ctx out of mysql_priv.h
38
39
  st_sql_list() {}                              /* Remove gcc warning */
40
  inline void empty()
41
  {
42
    elements=0;
43
    first=0;
44
    next= &first;
45
  }
481 by Brian Aker
Remove all of uchar.
46
  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
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;
1 by brian
clean slate
74
75
/*
76
  Basic single linked list
77
  Used for item and item_buffs.
78
  All list ends with a pointer to the 'end_of_list' element, which
79
  data pointer is a null pointer and the next pointer points to itself.
80
  This makes it very fast to traverse lists as we don't have to
81
  test for a specialend condition for list that can't contain a null
82
  pointer.
83
*/
84
85
86
/**
87
  list_node - a node of a single-linked list.
88
  @note We never call a destructor for instances of this class.
89
*/
90
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
91
struct list_node : public memory::SqlAlloc
1 by brian
clean slate
92
{
93
  list_node *next;
94
  void *info;
95
  list_node(void *info_par,list_node *next_par)
96
    :next(next_par),info(info_par)
97
  {}
98
  list_node()					/* For end_of_list */
99
  {
100
    info= 0;
101
    next= this;
102
  }
103
};
104
105
106
extern list_node end_of_list;
107
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
108
class base_list :public memory::SqlAlloc
1 by brian
clean slate
109
{
110
protected:
111
  list_node *first,**last;
112
113
public:
482 by Brian Aker
Remove uint.
114
  uint32_t elements;
1 by brian
clean slate
115
116
  inline void empty() { elements=0; first= &end_of_list; last=&first;}
117
  inline base_list() { empty(); }
118
  /**
119
    This is a shallow copy constructor that implicitly passes the ownership
120
    from the source list to the new instance. The old instance is not
121
    updated, so both objects end up sharing the same nodes. If one of
122
    the instances then adds or removes a node, the other becomes out of
123
    sync ('last' pointer), while still operational. Some old code uses and
124
    relies on this behaviour. This logic is quite tricky: please do not use
125
    it in any new code.
126
  */
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
127
  inline base_list(const base_list &tmp) :memory::SqlAlloc()
1 by brian
clean slate
128
  {
129
    elements= tmp.elements;
130
    first= tmp.first;
131
    last= elements ? tmp.last : &first;
132
  }
644 by Brian Aker
Clean up warnings for Solaris.
133
  inline base_list(bool) { }
1 by brian
clean slate
134
  inline bool push_back(void *info)
135
  {
136
    if (((*last)=new list_node(info, &end_of_list)))
137
    {
138
      last= &(*last)->next;
139
      elements++;
140
      return 0;
141
    }
142
    return 1;
143
  }
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
144
  inline bool push_back(void *info, memory::Root *mem_root)
1 by brian
clean slate
145
  {
146
    if (((*last)=new (mem_root) list_node(info, &end_of_list)))
147
    {
148
      last= &(*last)->next;
149
      elements++;
150
      return 0;
151
    }
152
    return 1;
153
  }
154
  inline bool push_front(void *info)
155
  {
156
    list_node *node=new list_node(info,first);
157
    if (node)
158
    {
159
      if (last == &first)
160
	last= &node->next;
161
      first=node;
162
      elements++;
163
      return 0;
164
    }
165
    return 1;
166
  }
167
  void remove(list_node **prev)
168
  {
169
    list_node *node=(*prev)->next;
170
    if (!--elements)
171
      last= &first;
172
    else if (last == &(*prev)->next)
173
      last= prev;
174
    delete *prev;
175
    *prev=node;
176
  }
177
  inline void concat(base_list *list)
178
  {
179
    if (!list->is_empty())
180
    {
181
      *last= list->first;
182
      last= list->last;
183
      elements+= list->elements;
184
    }
185
  }
186
  inline void *pop(void)
187
  {
188
    if (first == &end_of_list) return 0;
189
    list_node *tmp=first;
190
    first=first->next;
191
    if (!--elements)
192
      last= &first;
193
    return tmp->info;
194
  }
195
  inline void disjoin(base_list *list)
196
  {
197
    list_node **prev= &first;
198
    list_node *node= first;
199
    list_node *list_first= list->first;
200
    elements=0;
201
    while (node && node != list_first)
202
    {
203
      prev= &node->next;
204
      node= node->next;
205
      elements++;
206
    }
207
    *prev= *last;
208
    last= prev;
209
  }
210
  inline void prepand(base_list *list)
211
  {
212
    if (!list->is_empty())
213
    {
214
      *list->last= first;
215
      first= list->first;
216
      elements+= list->elements;
217
    }
218
  }
219
  /**
220
    Swap two lists.
221
  */
222
  inline void swap(base_list &rhs)
223
  {
322.2.2 by Mats Kindahl
Hiding THD::proc_info field and providing a setter and getter.
224
    std::swap(first, rhs.first);
225
    std::swap(last, rhs.last);
226
    std::swap(elements, rhs.elements);
1 by brian
clean slate
227
  }
228
  inline list_node* last_node() { return *last; }
229
  inline list_node* first_node() { return first;}
230
  inline void *head() { return first->info; }
231
  inline void **head_ref() { return first != &end_of_list ? &first->info : 0; }
232
  inline bool is_empty() { return first == &end_of_list ; }
233
  inline list_node *last_ref() { return &end_of_list; }
234
  friend class base_list_iterator;
235
  friend class error_list;
236
  friend class error_list_iterator;
237
238
#ifdef LIST_EXTRA_DEBUG
239
  /*
240
    Check list invariants and print results into trace. Invariants are:
241
      - (*last) points to end_of_list
242
      - There are no NULLs in the list.
243
      - base_list::elements is the number of elements in the list.
244
245
    SYNOPSIS
246
      check_list()
247
        name  Name to print to trace file
248
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
249
    RETURN
1 by brian
clean slate
250
      1  The list is Ok.
251
      0  List invariants are not met.
252
  */
253
254
  bool check_list(const char *name)
255
  {
256
    base_list *list= this;
257
    list_node *node= first;
482 by Brian Aker
Remove uint.
258
    uint32_t cnt= 0;
1 by brian
clean slate
259
260
    while (node->next != &end_of_list)
261
    {
262
      if (!node->info)
263
      {
51.1.53 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
264
        return false;
1 by brian
clean slate
265
      }
266
      node= node->next;
267
      cnt++;
268
    }
269
    if (last != &(node->next))
270
    {
51.1.53 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
271
      return false;
1 by brian
clean slate
272
    }
273
    if (cnt+1 != elements)
274
    {
51.1.53 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
275
      return false;
1 by brian
clean slate
276
    }
51.1.53 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
277
    return true;
1 by brian
clean slate
278
  }
279
#endif // LIST_EXTRA_DEBUG
280
281
protected:
282
  void after(void *info,list_node *node)
283
  {
284
    list_node *new_node=new list_node(info,node->next);
285
    node->next=new_node;
286
    elements++;
287
    if (last == &(node->next))
288
      last= &new_node->next;
289
  }
290
};
291
292
293
class base_list_iterator
294
{
295
protected:
296
  base_list *list;
297
  list_node **el,**prev,*current;
482 by Brian Aker
Remove uint.
298
  void sublist(base_list &ls, uint32_t elm)
1 by brian
clean slate
299
  {
300
    ls.first= *el;
301
    ls.last= list->last;
302
    ls.elements= elm;
303
  }
304
public:
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
305
  base_list_iterator()
1 by brian
clean slate
306
    :list(0), el(0), prev(0), current(0)
307
  {}
308
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
309
  base_list_iterator(base_list &list_par)
1 by brian
clean slate
310
  { init(list_par); }
311
312
  inline void init(base_list &list_par)
313
  {
314
    list= &list_par;
315
    el= &list_par.first;
316
    prev= 0;
317
    current= 0;
318
  }
319
320
  inline void *next(void)
321
  {
322
    prev=el;
323
    current= *el;
324
    el= &current->next;
325
    return current->info;
326
  }
327
  inline void *next_fast(void)
328
  {
329
    list_node *tmp;
330
    tmp= *el;
331
    el= &tmp->next;
332
    return tmp->info;
333
  }
334
  inline void rewind(void)
335
  {
336
    el= &list->first;
337
  }
338
  inline void *replace(void *element)
339
  {						// Return old element
340
    void *tmp=current->info;
51.1.53 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
341
    assert(current->info != 0);
1 by brian
clean slate
342
    current->info=element;
343
    return tmp;
344
  }
345
  void *replace(base_list &new_list)
346
  {
347
    void *ret_value=current->info;
348
    if (!new_list.is_empty())
349
    {
350
      *new_list.last=current->next;
351
      current->info=new_list.first->info;
352
      current->next=new_list.first->next;
353
      if ((list->last == &current->next) && (new_list.elements > 1))
354
	list->last= new_list.last;
355
      list->elements+=new_list.elements-1;
356
    }
357
    return ret_value;				// return old element
358
  }
359
  inline void remove(void)			// Remove current
360
  {
361
    list->remove(prev);
362
    el=prev;
363
    current=0;					// Safeguard
364
  }
365
  void after(void *element)			// Insert element after current
366
  {
367
    list->after(element,current);
368
    current=current->next;
369
    el= &current->next;
370
  }
371
  inline void **ref(void)			// Get reference pointer
372
  {
373
    return &current->info;
374
  }
375
  inline bool is_last(void)
376
  {
377
    return el == &list->last_ref()->next;
378
  }
379
  friend class error_list_iterator;
380
};
381
382
template <class T> class List :public base_list
383
{
384
public:
385
  inline List() :base_list() {}
386
  inline List(const List<T> &tmp) :base_list(tmp) {}
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
387
  inline List(const List<T> &tmp, memory::Root *mem_root) :
1 by brian
clean slate
388
    base_list(tmp, mem_root) {}
389
  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.
390
  inline bool push_back(T *a, memory::Root *mem_root)
1 by brian
clean slate
391
  { return base_list::push_back(a, mem_root); }
392
  inline bool push_front(T *a) { return base_list::push_front(a); }
393
  inline T* head() {return (T*) base_list::head(); }
394
  inline T** head_ref() {return (T**) base_list::head_ref(); }
395
  inline T* pop()  {return (T*) base_list::pop(); }
396
  inline void concat(List<T> *list) { base_list::concat(list); }
397
  inline void disjoin(List<T> *list) { base_list::disjoin(list); }
398
  inline void prepand(List<T> *list) { base_list::prepand(list); }
399
  void delete_elements(void)
400
  {
401
    list_node *element,*next;
402
    for (element=first; element != &end_of_list; element=next)
403
    {
404
      next=element->next;
405
      delete (T*) element->info;
406
    }
407
    empty();
408
  }
409
};
410
411
412
template <class T> class List_iterator :public base_list_iterator
413
{
414
public:
415
  List_iterator(List<T> &a) : base_list_iterator(a) {}
416
  List_iterator() : base_list_iterator() {}
417
  inline void init(List<T> &a) { base_list_iterator::init(a); }
418
  inline T* operator++(int) { return (T*) base_list_iterator::next(); }
419
  inline T *replace(T *a)   { return (T*) base_list_iterator::replace(a); }
420
  inline T *replace(List<T> &a) { return (T*) base_list_iterator::replace(a); }
421
  inline void rewind(void)  { base_list_iterator::rewind(); }
422
  inline void remove()      { base_list_iterator::remove(); }
423
  inline void after(T *a)   { base_list_iterator::after(a); }
424
  inline T** ref(void)	    { return (T**) base_list_iterator::ref(); }
425
};
426
427
428
template <class T> class List_iterator_fast :public base_list_iterator
429
{
430
protected:
644 by Brian Aker
Clean up warnings for Solaris.
431
  inline T *replace(T *)   { return (T*) 0; }
432
  inline T *replace(List<T> &) { return (T*) 0; }
1 by brian
clean slate
433
  inline void remove(void)  { }
1891.2.1 by Monty Taylor
Fixed things to make things compile with clang
434
  inline void after(T *)   { }
1 by brian
clean slate
435
  inline T** ref(void)	    { return (T**) 0; }
436
437
public:
438
  inline List_iterator_fast(List<T> &a) : base_list_iterator(a) {}
439
  inline List_iterator_fast() : base_list_iterator() {}
440
  inline void init(List<T> &a) { base_list_iterator::init(a); }
441
  inline T* operator++(int) { return (T*) base_list_iterator::next_fast(); }
442
  inline void rewind(void)  { base_list_iterator::rewind(); }
482 by Brian Aker
Remove uint.
443
  void sublist(List<T> &list_arg, uint32_t el_arg)
1 by brian
clean slate
444
  {
445
    base_list_iterator::sublist(list_arg, el_arg);
446
  }
447
};
448
449
450
/**
451
  Make a deep copy of each list element.
452
453
  @note A template function and not a template method of class List
454
  is employed because of explicit template instantiation:
455
  in server code there are explicit instantiations of List<T> and
456
  an explicit instantiation of a template requires that any method
457
  of the instantiated class used in the template can be resolved.
458
  Evidently not all template arguments have clone() method with
459
  the right signature.
460
520.1.21 by Brian Aker
THD -> Session rename
461
  @return You must query the error state in Session for out-of-memory
1 by brian
clean slate
462
  situation after calling this function.
463
*/
464
465
template <typename T>
466
inline
467
void
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
468
list_copy_and_replace_each_value(List<T> &list, memory::Root *mem_root)
1 by brian
clean slate
469
{
470
  /* Make a deep copy of each element */
471
  List_iterator<T> it(list);
472
  T *el;
473
  while ((el= it++))
474
    it.replace(el->clone(mem_root));
475
}
476
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
477
} /* 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.
478
1122.2.10 by Monty Taylor
Fixed all of the include guards.
479
#endif /* DRIZZLED_SQL_LIST_H */