Tesseract 3.02

- Main Page
- Related Pages
- Modules
- Namespaces
- Classes
- Files

- File List
- File Members

All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
genericvector.h
Go to the documentation of this file.
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 //
19 //
20 #ifndef TESSERACT_CCUTIL_GENERICVECTOR_H_
21 #define TESSERACT_CCUTIL_GENERICVECTOR_H_
22
23 #include <stdio.h>
24 #include <stdlib.h>
25
26 #include "tesscallback.h"
27 #include "errcode.h"
28 #include "helpers.h"
29 #include "ndminx.h"
30
31 // Use PointerVector<T> below in preference to GenericVector<T*>, as that
32 // provides automatic deletion of pointers, [De]Serialize that works, and
33 // sort that works.
34 template <typename T>
35 class GenericVector {
36 public:
37 GenericVector() { this->init(kDefaultVectorSize); }
38 explicit GenericVector(int size) { this->init(size); }
39
40 // Copy
41 GenericVector(const GenericVector& other) {
42 this->init(other.size());
43 this->operator+=(other);
44 }
45 GenericVector<T> &operator+=(const GenericVector& other);
46 GenericVector<T> &operator=(const GenericVector& other);
47
48 virtual ~GenericVector();
49
50 // Reserve some memory.
51 void reserve(int size);
52 // Double the size of the internal array.
53 void double_the_size();
54
55 // Resizes to size and sets all values to t.
56 void init_to_size(int size, T t);
57
58 // Return the size used.
59 int size() const {
60 return size_used_;
61 }
62
63 int length() const {
64 return size_used_;
65 }
66
67 // Return true if empty.
68 bool empty() const {
69 return size_used_ == 0;
70 }
71
72 // Return the object from an index.
73 T &get(int index) const;
74 T &back() const;
75 T &operator[](int index) const;
76
77 // Return the index of the T object.
78 // This method NEEDS a compare_callback to be passed to
79 // set_compare_callback.
80 int get_index(T object) const;
81
82 // Return true if T is in the array
83 bool contains(T object) const;
84
85 // Return true if the index is valid
86 T contains_index(int index) const;
87
88 // Push an element in the end of the array
89 int push_back(T object);
90 void operator+=(T t);
91
92 // Push an element in the end of the array if the same
93 // element is not already contained in the array.
94 int push_back_new(T object);
95
96 // Push an element in the front of the array
97 // Note: This function is O(n)
98 int push_front(T object);
99
100 // Set the value at the given index
101 void set(T t, int index);
102
103 // Insert t at the given index, push other elements to the right.
104 void insert(T t, int index);
105
106 // Removes an element at the given index and
107 // shifts the remaining elements to the left.
108 virtual void remove(int index);
109
110 // Truncates the array to the given size by removing the end.
111 // If the current size is less, the array is not expanded.
112 virtual void truncate(int size) {
113 if (size < size_used_)
114 size_used_ = size;
115 }
116
117 // Add a callback to be called to delete the elements when the array took
118 // their ownership.
119 void set_clear_callback(TessCallback1<T>* cb);
120
121 // Add a callback to be called to compare the elements when needed (contains,
122 // get_id, ...)
123 void set_compare_callback(TessResultCallback2<bool, T const &, T const &>* cb);
124
125 // Clear the array, calling the clear callback function if any.
126 // All the owned callbacks are also deleted.
127 // If you don't want the callbacks to be deleted, before calling clear, set
128 // the callback to NULL.
129 virtual void clear();
130
131 // Delete objects pointed to by data_[i]
132 void delete_data_pointers();
133
134 // This method clears the current object, then, does a shallow copy of
135 // its argument, and finally invalidates its argument.
136 // Callbacks are moved to the current object;
137 void move(GenericVector<T>* from);
138
139 // Read/Write the array to a file. This does _NOT_ read/write the callbacks.
140 // The callback given must be permanent since they will be called more than
141 // once. The given callback will be deleted at the end.
142 // If the callbacks are NULL, then the data is simply read/written using
143 // fread (and swapping)/fwrite.
144 // Returns false on error or if the callback returns false.
145 // DEPRECATED. Use [De]Serialize[Classes] instead.
146 bool write(FILE* f, TessResultCallback2<bool, FILE*, T const &>* cb) const;
147 bool read(FILE* f, TessResultCallback3<bool, FILE*, T*, bool>* cb, bool swap);
148 // Writes a vector of simple types to the given file. Assumes that bitwise
149 // read/write of T will work. Returns false in case of error.
150 virtual bool Serialize(FILE* fp) const;
151 // Reads a vector of simple types from the given file. Assumes that bitwise
152 // read/write will work with ReverseN according to sizeof(T).
153 // Returns false in case of error.
154 // If swap is true, assumes a big/little-endian swap is needed.
155 virtual bool DeSerialize(bool swap, FILE* fp);
156 // Writes a vector of classes to the given file. Assumes the existence of
157 // bool T::Serialize(FILE* fp) const that returns false in case of error.
158 // Returns false in case of error.
159 bool SerializeClasses(FILE* fp) const;
160 // Reads a vector of classes from the given file. Assumes the existence of
161 // bool T::Deserialize(bool swap, FILE* fp) that returns false in case of
162 // error. Also needs T::T() and T::T(constT&), as init_to_size is used in
163 // this function. Returns false in case of error.
164 // If swap is true, assumes a big/little-endian swap is needed.
165 bool DeSerializeClasses(bool swap, FILE* fp);
166
167 // Allocates a new array of double the current_size, copies over the
168 // information from data to the new location, deletes data and returns
169 // the pointed to the new larger array.
170 // This function uses memcpy to copy the data, instead of invoking
171 // operator=() for each element like double_the_size() does.
172 static T *double_the_size_memcpy(int current_size, T *data) {
173 T *data_new = new T[current_size * 2];
174 memcpy(data_new, data, sizeof(T) * current_size);
175 delete[] data;
176 return data_new;
177 }
178
179 // Sorts the members of this vector using the less than comparator (cmp_lt),
180 // which compares the values. Useful for GenericVectors to primitive types.
181 // Will not work so great for pointers (unless you just want to sort some
182 // pointers). You need to provide a specialization to sort_cmp to use
183 // your type.
184 void sort();
185
186 // Sort the array into the order defined by the qsort function comparator.
187 // The comparator function is as defined by qsort, ie. it receives pointers
188 // to two Ts and returns negative if the first element is to appear earlier
189 // in the result and positive if it is to appear later, with 0 for equal.
190 void sort(int (*comparator)(const void*, const void*)) {
191 qsort(data_, size_used_, sizeof(*data_), comparator);
192 }
193
194 // Searches the array (assuming sorted in ascending order, using sort()) for
195 // an element equal to target and returns true if it is present.
196 // Use binary_search to get the index of target, or its nearest candidate.
197 bool bool_binary_search(const T& target) const {
198 int index = binary_search(target);
199 if (index >= size_used_)
200 return false;
201 return data_[index] == target;
202 }
203 // Searches the array (assuming sorted in ascending order, using sort()) for
204 // an element equal to target and returns the index of the best candidate.
205 // The return value is conceptually the largest index i such that
206 // data_[i] <= target or 0 if target < the whole vector.
207 // NOTE that this function uses operator> so really the return value is
208 // the largest index i such that data_[i] > target is false.
209 int binary_search(const T& target) const {
210 int bottom = 0;
211 int top = size_used_;
212 do {
213 int middle = (bottom + top) / 2;
214 if (data_[middle] > target)
215 top = middle;
216 else
217 bottom = middle;
218 }
219 while (top - bottom > 1);
220 return bottom;
221 }
222
223 // Compact the vector by deleting elements using operator!= on basic types.
224 // The vector must be sorted.
225 void compact_sorted() {
226 if (size_used_ == 0)
227 return;
228
229 // First element is in no matter what, hence the i = 1.
230 int last_write = 0;
231 for (int i = 1; i < size_used_; ++i) {
232 // Finds next unique item and writes it.
233 if (data_[last_write] != data_[i])
234 data_[++last_write] = data_[i];
235 }
236 // last_write is the index of a valid data cell, so add 1.
237 size_used_ = last_write + 1;
238 }
239
240 // Compact the vector by deleting elements for which delete_cb returns
241 // true. delete_cb is a permanent callback and will be deleted.
242 void compact(TessResultCallback1<bool, int>* delete_cb) {
243 int new_size = 0;
244 int old_index = 0;
245 // Until the callback returns true, the elements stay the same.
246 while (old_index < size_used_ && !delete_cb->Run(old_index++))
247 ++new_size;
248 // Now just copy anything else that gets false from delete_cb.
249 for (; old_index < size_used_; ++old_index) {
250 if (!delete_cb->Run(old_index)) {
251 data_[new_size++] = data_[old_index];
252 }
253 }
254 size_used_ = new_size;
255 delete delete_cb;
256 }
257
258 T dot_product(const GenericVector<T>& other) const {
259 T result = static_cast<T>(0);
260 for (int i = MIN(size_used_, other.size_used_) - 1; i >= 0; --i)
261 result += data_[i] * other.data_[i];
262 return result;
263 }
264
265 protected:
266
267 // Init the object, allocating size memory.
268 void init(int size);
269
270 // We are assuming that the object generally placed in thie
271 // vector are small enough that for efficiency it makes sence
272 // to start with a larger initial size.
273 static const int kDefaultVectorSize = 4;
274 inT32 size_used_;
275 inT32 size_reserved_;
276 T* data_;
277 TessCallback1<T>* clear_cb_;
278 // Mutable because Run method is not const
279 mutable TessResultCallback2<bool, T const &, T const &>* compare_cb_;
280 };
281
282 namespace tesseract {
283
284 template <typename T>
285 bool cmp_eq(T const & t1, T const & t2) {
286 return t1 == t2;
287 }
288
289 // Used by sort()
290 // return < 0 if t1 < t2
291 // return 0 if t1 == t2
292 // return > 0 if t1 > t2
293 template <typename T>
294 int sort_cmp(const void* t1, const void* t2) {
295 const T* a = static_cast<const T *> (t1);
296 const T* b = static_cast<const T *> (t2);
297 if (*a < *b) {
298 return -1;
299 } else if (*b < *a) {
300 return 1;
301 } else {
302 return 0;
303 }
304 }
305
306 // Used by PointerVector::sort()
307 // return < 0 if t1 < t2
308 // return 0 if t1 == t2
309 // return > 0 if t1 > t2
310 template <typename T>
311 int sort_ptr_cmp(const void* t1, const void* t2) {
312 const T* a = *reinterpret_cast<T * const *>(t1);
313 const T* b = *reinterpret_cast<T * const *>(t2);
314 if (*a < *b) {
315 return -1;
316 } else if (*b < *a) {
317 return 1;
318 } else {
319 return 0;
320 }
321 }
322
323 // Subclass for a vector of pointers. Use in preference to GenericVector<T*>
324 // as it provides automatic deletion and correct serialization, with the
325 // corollary that all copy operations are deep copies of the pointed-to objects.
326 template<typename T>
327 class PointerVector : public GenericVector<T*> {
328 public:
329 PointerVector() : GenericVector<T*>() { }
330 explicit PointerVector(int size) : GenericVector<T*>(size) { }
331 virtual ~PointerVector() {
332 // Clear must be called here, even though it is called again by the base,
333 // as the base will call the wrong clear.
334 clear();
335 }
336 // Copy must be deep, as the pointers will be automatically deleted on
337 // destruction.
338 PointerVector(const PointerVector& other) {
339 this->init(other.size());
340 this->operator+=(other);
341 }
342 PointerVector<T>& operator+=(const PointerVector& other) {
343 this->reserve(this->size_used_ + other.size_used_);
344 for (int i = 0; i < other.size(); ++i) {
345 this->push_back(new T(*other.data_[i]));
346 }
347 return *this;
348 }
349
350 PointerVector<T>& operator=(const PointerVector& other) {
351 this->truncate(0);
352 this->operator+=(other);
353 return *this;
354 }
355
356 // Removes an element at the given index and
357 // shifts the remaining elements to the left.
358 virtual void remove(int index) {
359 delete GenericVector<T*>::data_[index];
360 GenericVector<T*>::remove(index);
361 }
362
363 // Truncates the array to the given size by removing the end.
364 // If the current size is less, the array is not expanded.
365 virtual void truncate(int size) {
366 for (int i = size; i < GenericVector<T*>::size_used_; ++i)
367 delete GenericVector<T*>::data_[i];
368 GenericVector<T*>::truncate(size);
369 }
370
371 // Compact the vector by deleting elements for which delete_cb returns
372 // true. delete_cb is a permanent callback and will be deleted.
373 void compact(TessResultCallback1<bool, const T*>* delete_cb) {
374 int new_size = 0;
375 int old_index = 0;
376 // Until the callback returns true, the elements stay the same.
377 while (old_index < GenericVector<T*>::size_used_ &&
378 !delete_cb->Run(GenericVector<T*>::data_[old_index++]))
379 ++new_size;
380 // Now just copy anything else that gets false from delete_cb.
381 for (; old_index < GenericVector<T*>::size_used_; ++old_index) {
382 if (!delete_cb->Run(GenericVector<T*>::data_[old_index])) {
383 GenericVector<T*>::data_[new_size++] =
384 GenericVector<T*>::data_[old_index];
385 } else {
386 delete GenericVector<T*>::data_[old_index];
387 }
388 }
389 GenericVector<T*>::size_used_ = new_size;
390 delete delete_cb;
391 }
392
393 // Clear the array, calling the clear callback function if any.
394 // All the owned callbacks are also deleted.
395 // If you don't want the callbacks to be deleted, before calling clear, set
396 // the callback to NULL.
397 virtual void clear() {
398 GenericVector<T*>::delete_data_pointers();
399 GenericVector<T*>::clear();
400 }
401
402 // Writes a vector of simple types to the given file. Assumes that bitwise
403 // read/write of T will work. Returns false in case of error.
404 virtual bool Serialize(FILE* fp) const {
405 inT32 used = GenericVector<T*>::size_used_;
406 if (fwrite(&used, sizeof(used), 1, fp) != 1) return false;
407 for (int i = 0; i < used; ++i) {
408 inT8 non_null = GenericVector<T*>::data_[i] != NULL;
409 if (fwrite(&non_null, sizeof(non_null), 1, fp) != 1) return false;
410 if (non_null && !GenericVector<T*>::data_[i]->Serialize(fp)) return false;
411 }
412 return true;
413 }
414 // Reads a vector of simple types from the given file. Assumes that bitwise
415 // read/write will work with ReverseN according to sizeof(T).
416 // Also needs T::T(), as new T is used in this function.
417 // Returns false in case of error.
418 // If swap is true, assumes a big/little-endian swap is needed.
419 virtual bool DeSerialize(bool swap, FILE* fp) {
420 inT32 reserved;
421 if (fread(&reserved, sizeof(reserved), 1, fp) != 1) return false;
422 if (swap) Reverse32(&reserved);
423 GenericVector<T*>::reserve(reserved);
424 for (int i = 0; i < reserved; ++i) {
425 inT8 non_null;
426 if (fread(&non_null, sizeof(non_null), 1, fp) != 1) return false;
427 T* item = NULL;
428 if (non_null) {
429 item = new T;
430 if (!item->DeSerialize(swap, fp)) return false;
431 }
432 this->push_back(item);
433 }
434 return true;
435 }
436
437 // Sorts the items pointed to by the members of this vector using
438 // t::operator<().
439 void sort() {
440 sort(&sort_ptr_cmp<T>);
441 }
442 };
443
444 } // namespace tesseract
445
446 // A useful vector that uses operator== to do comparisons.
447 template <typename T>
448 class GenericVectorEqEq : public GenericVector<T> {
449 public:
450 GenericVectorEqEq() {
451 GenericVector<T>::set_compare_callback(
452 NewPermanentTessCallback(tesseract::cmp_eq<T>));
453 }
454 GenericVectorEqEq(int size) : GenericVector<T>(size) {
455 GenericVector<T>::set_compare_callback(
456 NewPermanentTessCallback(tesseract::cmp_eq<T>));
457 }
458 };
459
460 template <typename T>
461 void GenericVector<T>::init(int size) {
462 size_used_ = 0;
463 size_reserved_ = 0;
464 data_ = 0;
465 clear_cb_ = 0;
466 compare_cb_ = 0;
467 reserve(size);
468 }
469
470 template <typename T>
471 GenericVector<T>::~GenericVector() {
472 clear();
473 }
474
475 // Reserve some memory. If the internal array contains elements, they are
476 // copied.
477 template <typename T>
478 void GenericVector<T>::reserve(int size) {
479 if (size_reserved_ >= size || size <= 0)
480 return;
481 T* new_array = new T[size];
482 for (int i = 0; i < size_used_; ++i)
483 new_array[i] = data_[i];
484 if (data_ != NULL) delete[] data_;
485 data_ = new_array;
486 size_reserved_ = size;
487 }
488
489 template <typename T>
490 void GenericVector<T>::double_the_size() {
491 if (size_reserved_ == 0) {
492 reserve(kDefaultVectorSize);
493 }
494 else {
495 reserve(2 * size_reserved_);
496 }
497 }
498
499 // Resizes to size and sets all values to t.
500 template <typename T>
501 void GenericVector<T>::init_to_size(int size, T t) {
502 reserve(size);
503 size_used_ = size;
504 for (int i = 0; i < size; ++i)
505 data_[i] = t;
506 }
507
508
509 // Return the object from an index.
510 template <typename T>
511 T &GenericVector<T>::get(int index) const {
512 ASSERT_HOST(index >= 0 && index < size_used_);
513 return data_[index];
514 }
515
516 template <typename T>
517 T &GenericVector<T>::operator[](int index) const {
518 return data_[index];
519 }
520
521 template <typename T>
522 T &GenericVector<T>::back() const {
523 ASSERT_HOST(size_used_ > 0);
524 return data_[size_used_ - 1];
525 }
526
527 // Return the object from an index.
528 template <typename T>
529 void GenericVector<T>::set(T t, int index) {
530 ASSERT_HOST(index >= 0 && index < size_used_);
531 data_[index] = t;
532 }
533
534 // Shifts the rest of the elements to the right to make
535 // space for the new elements and inserts the given element
536 // at the specified index.
537 template <typename T>
538 void GenericVector<T>::insert(T t, int index) {
539 ASSERT_HOST(index >= 0 && index < size_used_);
540 if (size_reserved_ == size_used_)
541 double_the_size();
542 for (int i = size_used_; i > index; --i) {
543 data_[i] = data_[i-1];
544 }
545 data_[index] = t;
546 size_used_++;
547 }
548
549 // Removes an element at the given index and
550 // shifts the remaining elements to the left.
551 template <typename T>
552 void GenericVector<T>::remove(int index) {
553 ASSERT_HOST(index >= 0 && index < size_used_);
554 for (int i = index; i < size_used_ - 1; ++i) {
555 data_[i] = data_[i+1];
556 }
557 size_used_--;
558 }
559
560 // Return true if the index is valindex
561 template <typename T>
562 T GenericVector<T>::contains_index(int index) const {
563 return index >= 0 && index < size_used_;
564 }
565
566 // Return the index of the T object.
567 template <typename T>
568 int GenericVector<T>::get_index(T object) const {
569 for (int i = 0; i < size_used_; ++i) {
570 ASSERT_HOST(compare_cb_ != NULL);
571 if (compare_cb_->Run(object, data_[i]))
572 return i;
573 }
574 return -1;
575 }
576
577 // Return true if T is in the array
578 template <typename T>
579 bool GenericVector<T>::contains(T object) const {
580 return get_index(object) != -1;
581 }
582
583 // Add an element in the array
584 template <typename T>
585 int GenericVector<T>::push_back(T object) {
586 int index = 0;
587 if (size_used_ == size_reserved_)
588 double_the_size();
589 index = size_used_++;
590 data_[index] = object;
591 return index;
592 }
593
594 template <typename T>
595 int GenericVector<T>::push_back_new(T object) {
596 int index = get_index(object);
597 if (index >= 0)
598 return index;
599 return push_back(object);
600 }
601
602 // Add an element in the array (front)
603 template <typename T>
604 int GenericVector<T>::push_front(T object) {
605 if (size_used_ == size_reserved_)
606 double_the_size();
607 for (int i = size_used_; i > 0; --i)
608 data_[i] = data_[i-1];
609 data_[0] = object;
610 ++size_used_;
611 return 0;
612 }
613
614 template <typename T>
615 void GenericVector<T>::operator+=(T t) {
616 push_back(t);
617 }
618
619 template <typename T>
620 GenericVector<T> &GenericVector<T>::operator+=(const GenericVector& other) {
621 this->reserve(size_used_ + other.size_used_);
622 for (int i = 0; i < other.size(); ++i) {
623 this->operator+=(other.data_[i]);
624 }
625 return *this;
626 }
627
628 template <typename T>
629 GenericVector<T> &GenericVector<T>::operator=(const GenericVector& other) {
630 this->truncate(0);
631 this->operator+=(other);
632 return *this;
633 }
634
635 // Add a callback to be called to delete the elements when the array took
636 // their ownership.
637 template <typename T>
638 void GenericVector<T>::set_clear_callback(TessCallback1<T>* cb) {
639 clear_cb_ = cb;
640 }
641
642 // Add a callback to be called to delete the elements when the array took
643 // their ownership.
644 template <typename T>
645 void GenericVector<T>::set_compare_callback(TessResultCallback2<bool, T const &, T const &>* cb) {
646 compare_cb_ = cb;
647 }
648
649 // Clear the array, calling the callback function if any.
650 template <typename T>
651 void GenericVector<T>::clear() {
652 if (size_reserved_ > 0) {
653 if (clear_cb_ != NULL)
654 for (int i = 0; i < size_used_; ++i)
655 clear_cb_->Run(data_[i]);
656 delete[] data_;
657 data_ = NULL;
658 size_used_ = 0;
659 size_reserved_ = 0;
660 }
661 if (clear_cb_ != NULL) {
662 delete clear_cb_;
663 clear_cb_ = NULL;
664 }
665 if (compare_cb_ != NULL) {
666 delete compare_cb_;
667 compare_cb_ = NULL;
668 }
669 }
670
671 template <typename T>
672 void GenericVector<T>::delete_data_pointers() {
673 for (int i = 0; i < size_used_; ++i)
674 if (data_[i]) {
675 delete data_[i];
676 }
677 }
678
679
680 template <typename T>
681 bool GenericVector<T>::write(
682 FILE* f, TessResultCallback2<bool, FILE*, T const &>* cb) const {
683 if (fwrite(&size_reserved_, sizeof(size_reserved_), 1, f) != 1) return false;
684 if (fwrite(&size_used_, sizeof(size_used_), 1, f) != 1) return false;
685 if (cb != NULL) {
686 for (int i = 0; i < size_used_; ++i) {
687 if (!cb->Run(f, data_[i])) {
688 delete cb;
689 return false;
690 }
691 }
692 delete cb;
693 } else {
694 if (fwrite(data_, sizeof(T), size_used_, f) != size_used_) return false;
695 }
696 return true;
697 }
698
699 template <typename T>
700 bool GenericVector<T>::read(FILE* f,
701 TessResultCallback3<bool, FILE*, T*, bool>* cb,
702 bool swap) {
703 inT32 reserved;
704 if (fread(&reserved, sizeof(reserved), 1, f) != 1) return false;
705 if (swap) Reverse32(&reserved);
706 reserve(reserved);
707 if (fread(&size_used_, sizeof(size_used_), 1, f) != 1) return false;
708 if (swap) Reverse32(&size_used_);
709 if (cb != NULL) {
710 for (int i = 0; i < size_used_; ++i) {
711 if (!cb->Run(f, data_ + i, swap)) {
712 delete cb;
713 return false;
714 }
715 }
716 delete cb;
717 } else {
718 if (fread(data_, sizeof(T), size_used_, f) != size_used_) return false;
719 if (swap) {
720 for (int i = 0; i < size_used_; ++i)
721 ReverseN(&data_[i], sizeof(T));
722 }
723 }
724 return true;
725 }
726
727 // Writes a vector of simple types to the given file. Assumes that bitwise
728 // read/write of T will work. Returns false in case of error.
729 template <typename T>
730 bool GenericVector<T>::Serialize(FILE* fp) const {
731 if (fwrite(&size_used_, sizeof(size_used_), 1, fp) != 1) return false;
732 if (fwrite(data_, sizeof(*data_), size_used_, fp) != size_used_) return false;
733 return true;
734 }
735
736 // Reads a vector of simple types from the given file. Assumes that bitwise
737 // read/write will work with ReverseN according to sizeof(T).
738 // Returns false in case of error.
739 // If swap is true, assumes a big/little-endian swap is needed.
740 template <typename T>
741 bool GenericVector<T>::DeSerialize(bool swap, FILE* fp) {
742 inT32 reserved;
743 if (fread(&reserved, sizeof(reserved), 1, fp) != 1) return false;
744 if (swap) Reverse32(&reserved);
745 reserve(reserved);
746 size_used_ = reserved;
747 if (fread(data_, sizeof(T), size_used_, fp) != size_used_) return false;
748 if (swap) {
749 for (int i = 0; i < size_used_; ++i)
750 ReverseN(&data_[i], sizeof(data_[i]));
751 }
752 return true;
753 }
754
755 // Writes a vector of classes to the given file. Assumes the existence of
756 // bool T::Serialize(FILE* fp) const that returns false in case of error.
757 // Returns false in case of error.
758 template <typename T>
759 bool GenericVector<T>::SerializeClasses(FILE* fp) const {
760 if (fwrite(&size_used_, sizeof(size_used_), 1, fp) != 1) return false;
761 for (int i = 0; i < size_used_; ++i) {
762 if (!data_[i].Serialize(fp)) return false;
763 }
764 return true;
765 }
766
767 // Reads a vector of classes from the given file. Assumes the existence of
768 // bool T::Deserialize(bool swap, FILE* fp) that returns false in case of
769 // error. Alse needs T::T() and T::T(constT&), as init_to_size is used in
770 // this function. Returns false in case of error.
771 // If swap is true, assumes a big/little-endian swap is needed.
772 template <typename T>
773 bool GenericVector<T>::DeSerializeClasses(bool swap, FILE* fp) {
774 uinT32 reserved;
775 if (fread(&reserved, sizeof(reserved), 1, fp) != 1) return false;
776 if (swap) Reverse32(&reserved);
777 T empty;
778 init_to_size(reserved, empty);
779 for (int i = 0; i < reserved; ++i) {
780 if (!data_[i].DeSerialize(swap, fp)) return false;
781 }
782 return true;
783 }
784
785 // This method clear the current object, then, does a shallow copy of
786 // its argument, and finally invalidates its argument.
787 template <typename T>
788 void GenericVector<T>::move(GenericVector<T>* from) {
789 this->clear();
790 this->data_ = from->data_;
791 this->size_reserved_ = from->size_reserved_;
792 this->size_used_ = from->size_used_;
793 this->compare_cb_ = from->compare_cb_;
794 this->clear_cb_ = from->clear_cb_;
795 from->data_ = NULL;
796 from->clear_cb_ = NULL;
797 from->compare_cb_ = NULL;
798 from->size_used_ = 0;
799 from->size_reserved_ = 0;
800 }
801
802 template <typename T>
803 void GenericVector<T>::sort() {
804 sort(&tesseract::sort_cmp<T>);
805 }
806
807 #endif // TESSERACT_CCUTIL_GENERICVECTOR_H_