1 #ifndef SQL_ARRAY_INCLUDED
2 #define SQL_ARRAY_INCLUDED
3 
4 /* Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved.
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, version 2.0,
8    as published by the Free Software Foundation.
9 
10    This program is also distributed with certain software (including
11    but not limited to OpenSSL) that is licensed under separate terms,
12    as designated in a particular file or component or in included license
13    documentation.  The authors of MySQL hereby grant you an additional
14    permission to link the program and your derivative works with the
15    separately licensed software that they have included with MySQL.
16 
17    This program is distributed in the hope that it will be useful,
18    but WITHOUT ANY WARRANTY; without even the implied warranty of
19    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20    GNU General Public License, version 2.0, for more details.
21 
22    You should have received a copy of the GNU General Public License
23    along with this program; if not, write to the Free Software Foundation,
24    51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */
25 
26 #include <my_sys.h>
27 
28 /**
29    A wrapper class which provides array bounds checking.
30    We do *not* own the array, we simply have a pointer to the first element,
31    and a length.
32 
33    @remark
34    We want the compiler-generated versions of:
35    - the copy CTOR (memberwise initialization)
36    - the assignment operator (memberwise assignment)
37 
38    @param Element_type The type of the elements of the container.
39  */
40 template <typename Element_type> class Bounds_checked_array
41 {
42 public:
Bounds_checked_array()43   Bounds_checked_array() : m_array(NULL), m_size(0) {}
44 
Bounds_checked_array(Element_type * el,size_t size)45   Bounds_checked_array(Element_type *el, size_t size)
46     : m_array(el), m_size(size)
47   {}
48 
reset()49   void reset() { m_array= NULL; m_size= 0; }
50 
reset(Element_type * array,size_t size)51   void reset(Element_type *array, size_t size)
52   {
53     m_array= array;
54     m_size= size;
55   }
56 
57   /**
58     Set a new bound on the array. Does not resize the underlying
59     array, so the new size must be smaller than or equal to the
60     current size.
61    */
resize(size_t new_size)62   void resize(size_t new_size)
63   {
64     DBUG_ASSERT(new_size <= m_size);
65     m_size= new_size;
66   }
67 
68   Element_type &operator[](size_t n)
69   {
70     DBUG_ASSERT(n < m_size);
71     return m_array[n];
72   }
73 
74   const Element_type &operator[](size_t n) const
75   {
76     DBUG_ASSERT(n < m_size);
77     return m_array[n];
78   }
79 
element_size()80   size_t element_size() const { return sizeof(Element_type); }
size()81   size_t size() const         { return m_size; }
82 
is_null()83   bool is_null() const { return m_array == NULL; }
84 
pop_front()85   void pop_front()
86   {
87     DBUG_ASSERT(m_size > 0);
88     m_array+= 1;
89     m_size-= 1;
90   }
91 
array()92   Element_type *array() const { return m_array; }
93 
94   bool operator==(const Bounds_checked_array<Element_type>&rhs) const
95   {
96     return m_array == rhs.m_array && m_size == rhs.m_size;
97   }
98   bool operator!=(const Bounds_checked_array<Element_type>&rhs) const
99   {
100     return m_array != rhs.m_array || m_size != rhs.m_size;
101   }
102 
103 private:
104   Element_type *m_array;
105   size_t        m_size;
106 };
107 
108 /*
109   A typesafe wrapper around DYNAMIC_ARRAY
110 */
111 
112 template <class Elem> class Dynamic_array
113 {
114   DYNAMIC_ARRAY  array;
115 public:
116   Dynamic_array(uint prealloc=16, uint increment=16)
117   {
118     init(prealloc, increment);
119   }
120 
121   void init(uint prealloc=16, uint increment=16)
122   {
123     my_init_dynamic_array(&array, sizeof(Elem), prealloc, increment);
124   }
125 
126   /**
127      @note Though formally this could be declared "const" it would be
128      misleading at it returns a non-const pointer to array's data.
129   */
at(int idx)130   Elem& at(int idx)
131   {
132     return *(((Elem*)array.buffer) + idx);
133   }
134   /// Const variant of at(), which cannot change data
at(int idx)135   const Elem& at(int idx) const
136   {
137     return *(((Elem*)array.buffer) + idx);
138   }
139 
140   /// @returns pointer to first element; undefined behaviour if array is empty
front()141   Elem *front()
142   {
143     DBUG_ASSERT(array.elements >= 1);
144     return (Elem*)array.buffer;
145   }
146 
147   /// @returns pointer to first element; undefined behaviour if array is empty
front()148   const Elem *front() const
149   {
150     DBUG_ASSERT(array.elements >= 1);
151     return (const Elem*)array.buffer;
152   }
153 
154   /// @returns pointer to last element; undefined behaviour if array is empty.
back()155   Elem *back()
156   {
157     DBUG_ASSERT(array.elements >= 1);
158     return ((Elem*)array.buffer) + (array.elements - 1);
159   }
160 
161   /// @returns pointer to last element; undefined behaviour if array is empty.
back()162   const Elem *back() const
163   {
164     DBUG_ASSERT(array.elements >= 1);
165     return ((const Elem*)array.buffer) + (array.elements - 1);
166   }
167 
168   /**
169      @retval false ok
170      @retval true  OOM, @c my_error() has been called.
171   */
append(const Elem & el)172   bool append(const Elem &el)
173   {
174     return insert_dynamic(&array, &el);
175   }
176 
177   /// Pops the last element. Does nothing if array is empty.
pop()178   Elem& pop()
179   {
180     return *((Elem*)pop_dynamic(&array));
181   }
182 
del(uint idx)183   void del(uint idx)
184   {
185     delete_dynamic_element(&array, idx);
186   }
187 
elements()188   int elements() const
189   {
190     return array.elements;
191   }
192 
elements(uint num_elements)193   void elements(uint num_elements)
194   {
195     DBUG_ASSERT(num_elements <= array.max_element);
196     array.elements= num_elements;
197   }
198 
clear()199   void clear()
200   {
201     elements(0);
202   }
203 
set(uint idx,const Elem & el)204   void set(uint idx, const Elem &el)
205   {
206     set_dynamic(&array, &el, idx);
207   }
208 
~Dynamic_array()209   ~Dynamic_array()
210   {
211     delete_dynamic(&array);
212   }
213 
214   typedef int (*CMP_FUNC)(const Elem *el1, const Elem *el2);
215 
sort(CMP_FUNC cmp_func)216   void sort(CMP_FUNC cmp_func)
217   {
218     my_qsort(array.buffer, array.elements, sizeof(Elem), (qsort_cmp)cmp_func);
219   }
220 };
221 
222 #endif /* SQL_ARRAY_INCLUDED */
223