• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 ///////////////////////////////////////////////////////////////////////
2 // File:        genericvector.h
3 // Description: Generic vector class
4 // Author:      Daria Antonova
5 // Created:     Mon Jun 23 11:26:43 PDT 2008
6 //
7 // (C) Copyright 2007, Google Inc.
8 // Licensed under the Apache License, Version 2.0 (the "License");
9 // you may not use this file except in compliance with the License.
10 // You may obtain a copy of the License at
11 // http://www.apache.org/licenses/LICENSE-2.0
12 // Unless required by applicable law or agreed to in writing, software
13 // distributed under the License is distributed on an "AS IS" BASIS,
14 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 // See the License for the specific language governing permissions and
16 // limitations under the License.
17 //
18 ///////////////////////////////////////////////////////////////////////
19 //
20 #ifndef TESSERACT_CCUTIL_GENERICVECTOR_H_
21 #define TESSERACT_CCUTIL_GENERICVECTOR_H_
22 
23 #include <stdio.h>
24 
25 #include "callback.h"
26 #include "errcode.h"
27 
28 template <typename T>
29 class GenericVector {
30  public:
GenericVector()31   GenericVector() { this->init(kDefaultVectorSize); }
GenericVector(int size)32   GenericVector(int size) { this->init(size); }
33 
34   // Copy
GenericVector(const GenericVector & other)35   GenericVector(const GenericVector& other) {
36     this->init(other.size());
37     this->operator+=(other);
38   }
39   GenericVector<T> &operator+=(const GenericVector& other);
40   GenericVector<T> &operator=(const GenericVector& other);
41 
42   virtual ~GenericVector();
43 
44   // Reserve some memory.
45   void reserve(int size);
46   // Double the size of the internal array.
47   void double_the_size();
48 
49   // Init the object, allocating size memory.
50   void init(int size);
51 
52   // Return the size used.
size()53   int size() const {
54     return size_used_;
55   }
56 
length()57   int length() const {
58     return size_used_;
59   }
60 
61   // Return true if empty.
empty()62   bool empty() const {
63     return size_used_ == 0;
64   }
65 
66   // Return the object from an index.
67   T &get(int index) const;
68   T &operator[](int index) const;
69 
70   // Return the index of the T object.
71   // This method NEEDS a compare_callback to be passed to
72   // set_compare_callback.
73   int get_index(T object) const;
74 
75   // Return true if T is in the array
76   bool contains(T object) const;
77 
78   // Return true if the index is valid
79   T contains_index(int index) const;
80 
81   // Push an element in the end of the array
82   int push_back(T object);
83   void operator+=(T t);
84 
85   // Set the value at the given index
86   void set(T t, int index);
87 
88   // Insert t at the given index, push other elements to the right.
89   void insert(T t, int index);
90 
91   // Removes an element at the given index and
92   // shifts the remaining elements to the left.
93   void remove(int index);
94 
95   // Add a callback to be called to delete the elements when the array took
96   // their ownership.
97   void set_clear_callback(Callback1<T>* cb);
98 
99   // Add a callback to be called to compare the elements when needed (contains,
100   // get_id, ...)
101   void set_compare_callback(ResultCallback2<bool, T const &, T const &>* cb);
102 
103   // Clear the array, calling the clear callback function if any.
104   // All the owned Callbacks are also deleted.
105   // If you don't want the Callbacks to be deleted, before calling clear, set
106   // the callback to NULL.
107   virtual void clear();
108 
109   // Delete objects pointed to by data_[i]
110   void delete_data_pointers();
111 
112   // This method clears the current object, then, does a shallow copy of
113   // its argument, and finally invalidate its argument.
114   // Callbacks are moved to the current object;
115   void move(GenericVector<T>* from);
116 
117   // Read/Write the array to a file. This does _NOT_ read/write the callbacks.
118   // The Callback given must be permanent since they will be called more than
119   // once. The given callback will be deleted at the end.
120   void write(FILE* f, Callback2<FILE*, T const &>* cb);
121   void read(FILE* f, Callback3<FILE*, T*, bool>* cb, bool swap);
122 
123   // Allocates a new array of double the current_size, copies over the
124   // information from data to the new location, deletes data and returns
125   // the pointed to the new larger array.
126   // This function uses memcpy to copy the data, instead of invoking
127   // operator=() for each element like double_the_size() does.
double_the_size_memcpy(int current_size,T * data)128   static T *double_the_size_memcpy(int current_size, T *data) {
129     T *data_new = new T[current_size * 2];
130     memcpy(data_new, data, sizeof(T) * current_size);
131     delete[] data;
132     return data_new;
133   }
134 
135  protected:
136   // We are assuming that the object generally placed in thie
137   // vector are small enough that for efficiency it makes sence
138   // to start with a larger initial size.
139   static const int kDefaultVectorSize = 4;
140   int   size_used_;
141   int   size_reserved_;
142   T*    data_;
143   Callback1<T>* clear_cb_;
144   // Mutable because Run method is not const
145   mutable ResultCallback2<bool, T const &, T const &>* compare_cb_;
146 };
147 
148 namespace tesseract {
149 
150 template <typename T>
cmp_eq(T const & t1,T const & t2)151 bool cmp_eq(T const & t1, T const & t2) {
152   return t1 == t2;
153 }
154 
155 }  // namespace tesseract
156 
157 // A useful vector that uses operator== to do comparisons.
158 template <typename T>
159 class GenericVectorEqEq : public GenericVector<T> {
160  public:
GenericVectorEqEq()161   GenericVectorEqEq() {
162     GenericVector<T>::set_compare_callback(
163         NewPermanentCallback(tesseract::cmp_eq<T>));
164   }
GenericVectorEqEq(int size)165   GenericVectorEqEq(int size) : GenericVector<T>(size) {
166     GenericVector<T>::set_compare_callback(
167         NewPermanentCallback(tesseract::cmp_eq<T>));
168   }
169 };
170 
171 template <typename T>
init(int size)172 void GenericVector<T>::init(int size) {
173   size_used_ = 0;
174   size_reserved_ = 0;
175   data_ = 0;
176   clear_cb_ = 0;
177   compare_cb_ = 0;
178   reserve(size);
179 }
180 
181 template <typename T>
~GenericVector()182 GenericVector<T>::~GenericVector() {
183   clear();
184 }
185 
186 // Reserve some memory. If the internal array contains elements, they are
187 // copied.
188 template <typename T>
reserve(int size)189 void GenericVector<T>::reserve(int size) {
190   if (size_reserved_ > size || size <= 0)
191     return;
192   T* new_array = new T[size];
193   for (int i = 0; i < size_used_; ++i)
194     new_array[i] = data_[i];
195   if (data_ != NULL) delete[] data_;
196   data_ = new_array;
197   size_reserved_ = size;
198 }
199 
200 template <typename T>
double_the_size()201 void GenericVector<T>::double_the_size() {
202   if (size_reserved_ == 0) {
203     reserve(kDefaultVectorSize);
204   }
205   else {
206     reserve(2 * size_reserved_);
207   }
208 }
209 
210 
211 
212 // Return the object from an index.
213 template <typename T>
get(int index)214 T &GenericVector<T>::get(int index) const {
215   ASSERT_HOST(index >= 0 && index < size_used_);
216   return data_[index];
217 }
218 
219 template <typename T>
220 T &GenericVector<T>::operator[](int index) const {
221  return data_[index];
222 }
223 
224 // Return the object from an index.
225 template <typename T>
set(T t,int index)226 void GenericVector<T>::set(T t, int index) {
227   ASSERT_HOST(index >= 0 && index < size_used_);
228   data_[index] = t;
229 }
230 
231 // Shifts the rest of the elements to the right to make
232 // space for the new elements and inserts the given element
233 // at the specified index.
234 template <typename T>
insert(T t,int index)235 void GenericVector<T>::insert(T t, int index) {
236   ASSERT_HOST(index >= 0 && index < size_used_);
237   if (size_reserved_ == size_used_)
238     double_the_size();
239   for (int i = size_used_; i > index; --i) {
240     data_[i] = data_[i-1];
241   }
242   data_[index] = t;
243   size_used_++;
244 }
245 
246 // Removes an element at the given index and
247 // shifts the remaining elements to the left.
248 template <typename T>
remove(int index)249 void GenericVector<T>::remove(int index) {
250   ASSERT_HOST(index >= 0 && index < size_used_);
251   for (int i = index; i < size_used_ - 1; ++i) {
252     data_[i] = data_[i+1];
253   }
254   size_used_--;
255 }
256 
257 // Return true if the index is valindex
258 template <typename T>
contains_index(int index)259 T GenericVector<T>::contains_index(int index) const {
260   return index >= 0 && index < size_used_;
261 }
262 
263 // Return the index of the T object.
264 template <typename T>
get_index(T object)265 int GenericVector<T>::get_index(T object) const {
266   for (int i = 0; i < size_used_; ++i) {
267     ASSERT_HOST(compare_cb_ != NULL);
268     if (compare_cb_->Run(object, data_[i]))
269       return i;
270   }
271   return -1;
272 }
273 
274 // Return true if T is in the array
275 template <typename T>
contains(T object)276 bool GenericVector<T>::contains(T object) const {
277   return get_index(object) != -1;
278 }
279 
280 // Add an element in the array
281 template <typename T>
push_back(T object)282 int GenericVector<T>::push_back(T object) {
283   int index = 0;
284   if (size_used_ == size_reserved_)
285     double_the_size();
286   index = size_used_++;
287   data_[index] = object;
288   return index;
289 }
290 
291 template <typename T>
292 void GenericVector<T>::operator+=(T t) {
293   push_back(t);
294 }
295 
296 template <typename T>
297 GenericVector<T> &GenericVector<T>::operator+=(const GenericVector& other) {
298   for (int i = 0;i < other.size(); ++i) {
299     this->operator+=(other.data_[i]);
300   }
301   return *this;
302 }
303 
304 template <typename T>
305 GenericVector<T> &GenericVector<T>::operator=(const GenericVector& other) {
306   this->clear();
307   this->operator+=(other);
308   return *this;
309 }
310 
311 // Add a callback to be called to delete the elements when the array took
312 // their ownership.
313 template <typename T>
set_clear_callback(Callback1<T> * cb)314 void GenericVector<T>::set_clear_callback(Callback1<T>* cb) {
315   clear_cb_ = cb;
316 }
317 
318 // Add a callback to be called to delete the elements when the array took
319 // their ownership.
320 template <typename T>
set_compare_callback(ResultCallback2<bool,T const &,T const &> * cb)321 void GenericVector<T>::set_compare_callback(ResultCallback2<bool, T const &, T const &>* cb) {
322   compare_cb_ = cb;
323 }
324 
325 // Clear the array, calling the callback function if any.
326 template <typename T>
clear()327 void GenericVector<T>::clear() {
328   if (size_reserved_ > 0) {
329     if (clear_cb_ != NULL)
330       for (int i = 0; i < size_used_; ++i)
331         clear_cb_->Run(data_[i]);
332     delete[] data_;
333     size_used_ = 0;
334     size_reserved_ = 0;
335   }
336   if (clear_cb_ != NULL) {
337     delete clear_cb_;
338     clear_cb_ = NULL;
339   }
340   if (compare_cb_ != NULL) {
341     delete compare_cb_;
342     compare_cb_ = NULL;
343   }
344 }
345 
346 template <typename T>
delete_data_pointers()347 void GenericVector<T>::delete_data_pointers() {
348   for (int i = 0; i < size_used_; ++i)
349     if (data_[i]) {
350       delete data_[i];
351     }
352 }
353 
354 
355 template <typename T>
write(FILE * f,Callback2<FILE *,T const &> * cb)356 void GenericVector<T>::write(FILE* f, Callback2<FILE*, T const &>* cb) {
357   fwrite(&size_reserved_, sizeof(int), 1, f);
358   fwrite(&size_used_, sizeof(int), 1, f);
359   for (int i = 0; i < size_used_; ++i) {
360     cb->Run(f, data_[i]);
361   }
362   delete cb;
363 }
364 
365 template <typename T>
read(FILE * f,Callback3<FILE *,T *,bool> * cb,bool swap)366 void GenericVector<T>::read(FILE* f, Callback3<FILE*, T*, bool>* cb, bool swap) {
367   uinT32 reserved;
368   fread(&reserved, sizeof(int), 1, f);
369   if (swap)
370     reserved = reverse32(reserved);
371   reserve(reserved);
372   fread(&size_used_, sizeof(int), 1, f);
373   if (swap)
374     size_used_ = reverse32(size_used_);
375   for (int i = 0; i < size_used_; ++i) {
376     cb->Run(f, data_ + i, swap);
377   }
378   delete cb;
379 }
380 
381 // This method clear the current object, then, does a shallow copy of
382 // its argument, and finally invalindate its argument.
383 template <typename T>
move(GenericVector<T> * from)384 void GenericVector<T>::move(GenericVector<T>* from) {
385   this->clear();
386   this->data_ = from->data_;
387   this->size_reserved_ = from->size_reserved_;
388   this->size_used_ = from->size_used_;
389   this->compare_cb_ = from->compare_cb_;
390   this->clear_cb_ = from->clear_cb_;
391   from->data_ = NULL;
392   from->clear_cb_ = NULL;
393   from->compare_cb_ = NULL;
394   from->size_used_ = 0;
395   from->size_reserved_ = 0;
396 }
397 
398 #endif  // TESSERACT_CCUTIL_GENERICVECTOR_H_
399