1#ifndef SQL_ARRAY_INCLUDED
2#define SQL_ARRAY_INCLUDED
3
4/* Copyright (c) 2003, 2005-2007 MySQL AB, 2009 Sun Microsystems, Inc.
5 Use is subject to license terms.
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; version 2 of the License.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
19
20#include <my_sys.h>
21
22/**
23 A wrapper class which provides array bounds checking.
24 We do *not* own the array, we simply have a pointer to the first element,
25 and a length.
26
27 @remark
28 We want the compiler-generated versions of:
29 - the copy CTOR (memberwise initialization)
30 - the assignment operator (memberwise assignment)
31
32 @param Element_type The type of the elements of the container.
33 */
34template <typename Element_type> class Bounds_checked_array
35{
36public:
37 Bounds_checked_array() : m_array(NULL), m_size(0) {}
38
39 Bounds_checked_array(Element_type *el, size_t size_arg)
40 : m_array(el), m_size(size_arg)
41 {}
42
43 void reset() { m_array= NULL; m_size= 0; }
44
45 void reset(Element_type *array_arg, size_t size_arg)
46 {
47 m_array= array_arg;
48 m_size= size_arg;
49 }
50
51 /**
52 Set a new bound on the array. Does not resize the underlying
53 array, so the new size must be smaller than or equal to the
54 current size.
55 */
56 void resize(size_t new_size)
57 {
58 DBUG_ASSERT(new_size <= m_size);
59 m_size= new_size;
60 }
61
62 Element_type &operator[](size_t n)
63 {
64 DBUG_ASSERT(n < m_size);
65 return m_array[n];
66 }
67
68 const Element_type &operator[](size_t n) const
69 {
70 DBUG_ASSERT(n < m_size);
71 return m_array[n];
72 }
73
74 size_t element_size() const { return sizeof(Element_type); }
75 size_t size() const { return m_size; }
76
77 bool is_null() const { return m_array == NULL; }
78
79 void pop_front()
80 {
81 DBUG_ASSERT(m_size > 0);
82 m_array+= 1;
83 m_size-= 1;
84 }
85
86 Element_type *array() const { return m_array; }
87
88 bool operator==(const Bounds_checked_array<Element_type>&rhs) const
89 {
90 return m_array == rhs.m_array && m_size == rhs.m_size;
91 }
92 bool operator!=(const Bounds_checked_array<Element_type>&rhs) const
93 {
94 return m_array != rhs.m_array || m_size != rhs.m_size;
95 }
96
97private:
98 Element_type *m_array;
99 size_t m_size;
100};
101
102/*
103 A typesafe wrapper around DYNAMIC_ARRAY
104
105 TODO: Change creator to take a THREAD_SPECIFIC option.
106*/
107
108template <class Elem> class Dynamic_array
109{
110 DYNAMIC_ARRAY array;
111public:
112 Dynamic_array(uint prealloc=16, uint increment=16)
113 {
114 init(prealloc, increment);
115 }
116
117 Dynamic_array(MEM_ROOT *root, uint prealloc=16, uint increment=16)
118 {
119 void *init_buffer= alloc_root(root, sizeof(Elem) * prealloc);
120 my_init_dynamic_array2(&array, sizeof(Elem), init_buffer,
121 prealloc, increment, MYF(0));
122 }
123
124 void init(uint prealloc=16, uint increment=16)
125 {
126 my_init_dynamic_array(&array, sizeof(Elem), prealloc, increment,
127 MYF(0));
128 }
129
130 /**
131 @note Though formally this could be declared "const" it would be
132 misleading at it returns a non-const pointer to array's data.
133 */
134 Elem& at(size_t idx)
135 {
136 DBUG_ASSERT(idx < array.elements);
137 return *(((Elem*)array.buffer) + idx);
138 }
139 /// Const variant of at(), which cannot change data
140 const Elem& at(size_t idx) const
141 {
142 return *(((Elem*)array.buffer) + idx);
143 }
144
145 /// @returns pointer to first element
146 Elem *front()
147 {
148 return (Elem*)array.buffer;
149 }
150
151 /// @returns pointer to first element
152 const Elem *front() const
153 {
154 return (const Elem*)array.buffer;
155 }
156
157 /// @returns pointer to last element
158 Elem *back()
159 {
160 return ((Elem*)array.buffer) + array.elements - 1;
161 }
162
163 /// @returns pointer to last element
164 const Elem *back() const
165 {
166 return ((const Elem*)array.buffer) + array.elements - 1;
167 }
168
169 /**
170 @retval false ok
171 @retval true OOM, @c my_error() has been called.
172 */
173 bool append(const Elem &el)
174 {
175 return insert_dynamic(&array, &el);
176 }
177
178 bool append_val(Elem el)
179 {
180 return (insert_dynamic(&array, (uchar*)&el));
181 }
182
183 bool push(Elem &el)
184 {
185 return append(el);
186 }
187
188 /// Pops the last element. Does nothing if array is empty.
189 Elem& pop()
190 {
191 return *((Elem*)pop_dynamic(&array));
192 }
193
194 void del(size_t idx)
195 {
196 DBUG_ASSERT(idx <= array.max_element);
197 delete_dynamic_element(&array, (uint)idx);
198 }
199
200 size_t elements() const
201 {
202 return array.elements;
203 }
204
205 void elements(size_t num_elements)
206 {
207 DBUG_ASSERT(num_elements <= array.max_element);
208 array.elements= (uint)num_elements;
209 }
210
211 void clear()
212 {
213 elements(0);
214 }
215
216 void set(uint idx, const Elem &el)
217 {
218 set_dynamic(&array, &el, idx);
219 }
220
221 bool resize(size_t new_size, Elem default_val)
222 {
223 size_t old_size= elements();
224 if (unlikely(allocate_dynamic(&array, (uint)new_size)))
225 return true;
226
227 if (new_size > old_size)
228 {
229 set_dynamic(&array, (uchar*)&default_val, (uint)(new_size - 1));
230 /*for (size_t i= old_size; i != new_size; i++)
231 {
232 at(i)= default_val;
233 }*/
234 }
235 return false;
236 }
237
238 ~Dynamic_array()
239 {
240 delete_dynamic(&array);
241 }
242
243 void free_memory()
244 {
245 delete_dynamic(&array);
246 }
247
248 typedef int (*CMP_FUNC)(const Elem *el1, const Elem *el2);
249
250 void sort(CMP_FUNC cmp_func)
251 {
252 my_qsort(array.buffer, array.elements, sizeof(Elem), (qsort_cmp)cmp_func);
253 }
254
255 typedef int (*CMP_FUNC2)(const Elem *el1, const Elem *el2, void *);
256 void sort(CMP_FUNC2 cmp_func, void *data)
257 {
258 my_qsort2(array.buffer, array.elements, sizeof(Elem), (qsort2_cmp)cmp_func, data);
259 }
260};
261
262typedef Bounds_checked_array<Item*> Ref_ptr_array;
263
264#endif /* SQL_ARRAY_INCLUDED */
265