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