1 /*
2    Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
3 
4    This program is free software; you can redistribute it and/or modify
5    it under the terms of the GNU General Public License, version 2.0,
6    as published by the Free Software Foundation.
7 
8    This program is also distributed with certain software (including
9    but not limited to OpenSSL) that is licensed under separate terms,
10    as designated in a particular file or component or in included license
11    documentation.  The authors of MySQL hereby grant you an additional
12    permission to link the program and your derivative works with the
13    separately licensed software that they have included with MySQL.
14 
15    This program is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18    GNU General Public License, version 2.0, for more details.
19 
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software
22    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA
23 */
24 
25 #ifndef NDB_VECTOR_HPP
26 #define NDB_VECTOR_HPP
27 
28 #include <ndb_global.h>
29 #include <portlib/NdbMutex.h>
30 
31 template<class T>
32 class Vector {
33 public:
34   Vector(int sz = 10);
35   ~Vector();
36 
37   T& operator[](unsigned i);
38   const T& operator[](unsigned i) const;
size() const39   unsigned size() const { return m_size; };
40 
41   int push_back(const T &);
42   void push(const T&, unsigned pos);
43   T& set(T&, unsigned pos, T& fill_obj);
44   T& back();
45 
46   void erase(unsigned index);
47 
48   void clear();
49 
50   int fill(unsigned new_size, T & obj);
51 
52   Vector<T>& operator=(const Vector<T>&);
53 
54   /** Does deep copy.*/
55   Vector(const Vector&);
56   /**
57    * Shallow equal (i.e does memcmp)
58    */
59   bool equal(const Vector<T>& obj) const;
60 
61   int assign(const T*, unsigned cnt);
assign(const Vector<T> & obj)62   int assign(const Vector<T>& obj) { return assign(obj.getBase(), obj.size());}
63 
getBase()64   T* getBase() { return m_items;}
getBase() const65   const T* getBase() const { return m_items;}
66 private:
67   T * m_items;
68   unsigned m_size;
69   unsigned m_incSize;
70   unsigned m_arraySize;
71 };
72 
73 template<class T>
Vector(int i)74 Vector<T>::Vector(int i){
75   m_items = new T[i];
76   if (m_items == NULL)
77   {
78     errno = ENOMEM;
79     m_size = 0;
80     m_arraySize = 0;
81     m_incSize = 0;
82     return;
83   }
84   m_size = 0;
85   m_arraySize = i;
86   m_incSize = 50;
87 }
88 
89 template<class T>
Vector(const Vector & src)90 Vector<T>::Vector(const Vector& src):
91   m_items(new T[src.m_size]),
92   m_size(src.m_size),
93   m_incSize(src.m_incSize),
94   m_arraySize(src.m_size)
95 
96 {
97   if (unlikely(m_items == NULL)){
98     errno = ENOMEM;
99     m_size = 0;
100     m_arraySize = 0;
101     m_incSize = 0;
102     return;
103   }
104   for(unsigned i = 0; i < m_size; i++){
105     m_items[i] = src.m_items[i];
106   }
107 }
108 
109 template<class T>
~Vector()110 Vector<T>::~Vector(){
111   delete[] m_items;
112   // safety for placement new usage
113   m_items = 0;
114   m_size = 0;
115   m_arraySize = 0;
116 }
117 
118 template<class T>
119 T &
operator [](unsigned i)120 Vector<T>::operator[](unsigned i){
121   if(i >= m_size)
122     abort();
123   return m_items[i];
124 }
125 
126 template<class T>
127 const T &
operator [](unsigned i) const128 Vector<T>::operator[](unsigned i) const {
129   if(i >= m_size)
130     abort();
131   return m_items[i];
132 }
133 
134 template<class T>
135 T &
back()136 Vector<T>::back(){
137   return (* this)[m_size - 1];
138 }
139 
140 template<class T>
141 int
push_back(const T & t)142 Vector<T>::push_back(const T & t){
143   if(m_size == m_arraySize){
144     T * tmp = new T [m_arraySize + m_incSize];
145     if(tmp == NULL)
146     {
147       errno = ENOMEM;
148       return -1;
149     }
150     for (unsigned k = 0; k < m_size; k++)
151       tmp[k] = m_items[k];
152     delete[] m_items;
153     m_items = tmp;
154     m_arraySize = m_arraySize + m_incSize;
155   }
156   m_items[m_size] = t;
157   m_size++;
158   return 0;
159 }
160 
161 template<class T>
162 void
push(const T & t,unsigned pos)163 Vector<T>::push(const T & t, unsigned pos)
164 {
165   push_back(t);
166   if (pos < m_size - 1)
167   {
168     for(unsigned i = m_size - 1; i > pos; i--)
169     {
170       m_items[i] = m_items[i-1];
171     }
172     m_items[pos] = t;
173   }
174 }
175 
176 template<class T>
177 T&
set(T & t,unsigned pos,T & fill_obj)178 Vector<T>::set(T & t, unsigned pos, T& fill_obj)
179 {
180   fill(pos, fill_obj);
181   T& ret = m_items[pos];
182   m_items[pos] = t;
183   return ret;
184 }
185 
186 template<class T>
187 void
erase(unsigned i)188 Vector<T>::erase(unsigned i){
189   if(i >= m_size)
190     abort();
191 
192   for (unsigned k = i; k + 1 < m_size; k++)
193     m_items[k] = m_items[k + 1];
194   m_size--;
195 }
196 
197 template<class T>
198 void
clear()199 Vector<T>::clear(){
200   m_size = 0;
201 }
202 
203 template<class T>
204 int
fill(unsigned new_size,T & obj)205 Vector<T>::fill(unsigned new_size, T & obj){
206   while(m_size <= new_size)
207     if (push_back(obj))
208       return -1;
209   return 0;
210 }
211 
212 template<class T>
213 Vector<T>&
operator =(const Vector<T> & obj)214 Vector<T>::operator=(const Vector<T>& obj){
215   if(this != &obj){
216     clear();
217     for(unsigned i = 0; i<obj.size(); i++){
218       push_back(obj[i]);
219     }
220   }
221   return * this;
222 }
223 
224 template<class T>
225 int
assign(const T * src,unsigned cnt)226 Vector<T>::assign(const T* src, unsigned cnt)
227 {
228   clear();
229   for (unsigned i = 0; i<cnt; i++)
230   {
231     int ret;
232     if ((ret = push_back(src[i])))
233       return ret;
234   }
235   return 0;
236 }
237 
238 template<class T>
239 bool
equal(const Vector<T> & obj) const240 Vector<T>::equal(const Vector<T>& obj) const
241 {
242   if (size() != obj.size())
243     return false;
244 
245   return memcmp(getBase(), obj.getBase(), size() * sizeof(T)) == 0;
246 }
247 
248 template<class T>
249 class MutexVector : public NdbLockable {
250 public:
251   MutexVector(int sz = 10);
252   ~MutexVector();
253 
254   T& operator[](unsigned i);
255   const T& operator[](unsigned i) const;
size() const256   unsigned size() const { return m_size; };
257 
258   int push_back(const T &);
259   int push_back(const T &, bool lockMutex);
260   T& back();
261 
262   void erase(unsigned index);
263   void erase(unsigned index, bool lockMutex);
264 
265   void clear();
266   void clear(bool lockMutex);
267 
268   int fill(unsigned new_size, T & obj);
269 private:
270   T * m_items;
271   unsigned m_size;
272   unsigned m_incSize;
273   unsigned m_arraySize;
274 };
275 
276 template<class T>
MutexVector(int i)277 MutexVector<T>::MutexVector(int i){
278   m_items = new T[i];
279   if (m_items == NULL)
280   {
281     errno = ENOMEM;
282     m_size = 0;
283     m_arraySize = 0;
284     m_incSize = 0;
285     return;
286   }
287   m_size = 0;
288   m_arraySize = i;
289   m_incSize = 50;
290 }
291 
292 template<class T>
~MutexVector()293 MutexVector<T>::~MutexVector(){
294   delete[] m_items;
295   // safety for placement new usage
296   m_items = 0;
297   m_size = 0;
298   m_arraySize = 0;
299 }
300 
301 template<class T>
302 T &
operator [](unsigned i)303 MutexVector<T>::operator[](unsigned i){
304   if(i >= m_size)
305     abort();
306   return m_items[i];
307 }
308 
309 template<class T>
310 const T &
operator [](unsigned i) const311 MutexVector<T>::operator[](unsigned i) const {
312   if(i >= m_size)
313     abort();
314   return m_items[i];
315 }
316 
317 template<class T>
318 T &
back()319 MutexVector<T>::back(){
320   return (* this)[m_size - 1];
321 }
322 
323 template<class T>
324 int
push_back(const T & t)325 MutexVector<T>::push_back(const T & t){
326   lock();
327   if(m_size == m_arraySize){
328     T * tmp = new T [m_arraySize + m_incSize];
329     if (tmp == NULL)
330     {
331       errno = ENOMEM;
332       unlock();
333       return -1;
334     }
335     for (unsigned k = 0; k < m_size; k++)
336       tmp[k] = m_items[k];
337     delete[] m_items;
338     m_items = tmp;
339     m_arraySize = m_arraySize + m_incSize;
340   }
341   m_items[m_size] = t;
342   m_size++;
343   unlock();
344   return 0;
345 }
346 
347 template<class T>
348 int
push_back(const T & t,bool lockMutex)349 MutexVector<T>::push_back(const T & t, bool lockMutex){
350   if(lockMutex)
351     lock();
352   if(m_size == m_arraySize){
353     T * tmp = new T [m_arraySize + m_incSize];
354     if (tmp == NULL)
355     {
356       errno = ENOMEM;
357       if(lockMutex)
358         unlock();
359       return -1;
360     }
361     for (unsigned k = 0; k < m_size; k++)
362       tmp[k] = m_items[k];
363     delete[] m_items;
364     m_items = tmp;
365     m_arraySize = m_arraySize + m_incSize;
366   }
367   m_items[m_size] = t;
368   m_size++;
369   if(lockMutex)
370     unlock();
371   return 0;
372 }
373 
374 template<class T>
375 void
erase(unsigned i)376 MutexVector<T>::erase(unsigned i){
377   if(i >= m_size)
378     abort();
379 
380   lock();
381   for (unsigned k = i; k + 1 < m_size; k++)
382     m_items[k] = m_items[k + 1];
383   m_size--;
384   unlock();
385 }
386 
387 template<class T>
388 void
erase(unsigned i,bool _lock)389 MutexVector<T>::erase(unsigned i, bool _lock){
390   if(i >= m_size)
391     abort();
392 
393   if(_lock)
394     lock();
395   for (unsigned k = i; k + 1 < m_size; k++)
396     m_items[k] = m_items[k + 1];
397   m_size--;
398   if(_lock)
399     unlock();
400 }
401 
402 template<class T>
403 void
clear()404 MutexVector<T>::clear(){
405   lock();
406   m_size = 0;
407   unlock();
408 }
409 
410 template<class T>
411 void
clear(bool l)412 MutexVector<T>::clear(bool l){
413   if(l) lock();
414   m_size = 0;
415   if(l) unlock();
416 }
417 
418 template<class T>
419 int
fill(unsigned new_size,T & obj)420 MutexVector<T>::fill(unsigned new_size, T & obj){
421   while(m_size <= new_size)
422     if (push_back(obj))
423       return -1;
424   return 0;
425 }
426 
427 #endif
428