tesseract  5.0.0
genericvector.h
Go to the documentation of this file.
1 // File: genericvector.h
3 // Description: Generic vector class
4 // Author: Daria Antonova
5 //
6 // (C) Copyright 2007, Google Inc.
7 // Licensed under the Apache License, Version 2.0 (the "License");
8 // you may not use this file except in compliance with the License.
9 // You may obtain a copy of the License at
10 // http://www.apache.org/licenses/LICENSE-2.0
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
16 //
18 //
19 #ifndef TESSERACT_CCUTIL_GENERICVECTOR_H_
20 #define TESSERACT_CCUTIL_GENERICVECTOR_H_
21 
22 #include "helpers.h"
23 #include "serialis.h"
24 
25 #include <algorithm>
26 #include <cassert>
27 #include <climits> // for LONG_MAX
28 #include <cstdint> // for uint32_t
29 #include <cstdio>
30 #include <cstdlib>
31 #include <functional> // for std::function
32 
33 namespace tesseract {
34 
35 // Use PointerVector<T> below in preference to GenericVector<T*>, as that
36 // provides automatic deletion of pointers, [De]Serialize that works, and
37 // sort that works.
38 template <typename T>
40 public:
43  }
44  GenericVector(int size, const T &init_val) {
45  init(size);
46  init_to_size(size, init_val);
47  }
48 
49  // Copy
50  GenericVector(const GenericVector &other) {
51  this->init(other.size());
52  this->operator+=(other);
53  }
56 
58 
59  // Reserve some memory.
60  void reserve(int size);
61  // Double the size of the internal array.
63 
64  // Resizes to size and sets all values to t.
65  void init_to_size(int size, const T &t);
66  void resize(int size, const T &t);
67  // Resizes to size without any initialization.
68  void resize_no_init(int size) {
69  reserve(size);
70  size_used_ = size;
71  }
72 
73  // Return the size used.
74  unsigned size() const {
75  return size_used_;
76  }
77  // Workaround to avoid g++ -Wsign-compare warnings.
78  size_t unsigned_size() const {
79  static_assert(sizeof(size_used_) <= sizeof(size_t), "Wow! sizeof(size_t) < sizeof(int32_t)!!");
80  assert(0 <= size_used_);
81  return static_cast<size_t>(size_used_);
82  }
83  int size_reserved() const {
84  return size_reserved_;
85  }
86 
87  // Return true if empty.
88  bool empty() const {
89  return size_used_ == 0;
90  }
91 
92  // Return the object from an index.
93  T &at(int index) const {
94  assert(index >= 0 && index < size_used_);
95  return data_[index];
96  }
97 
98  T &back() const;
99  T &operator[](int index) const;
100  // Returns the last object and removes it.
101  T pop_back();
102 
103  // Return the index of the T object.
104  int get_index(const T &object) const;
105 
106  // Push an element in the end of the array
107  int push_back(T object);
108  void operator+=(const T &t);
109 
110  // Push an element in the end of the array if the same
111  // element is not already contained in the array.
112  int push_back_new(const T &object);
113 
114  // Push an element in the front of the array
115  // Note: This function is O(n)
116  int push_front(const T &object);
117 
118  // Set the value at the given index
119  void set(const T &t, int index);
120 
121  // Insert t at the given index, push other elements to the right.
122  void insert(const T &t, int index);
123 
124  // Removes an element at the given index and
125  // shifts the remaining elements to the left.
126  void remove(int index);
127 
128  // Truncates the array to the given size by removing the end.
129  // If the current size is less, the array is not expanded.
130  void truncate(int size) {
131  if (size < size_used_) {
132  size_used_ = size;
133  }
134  }
135 
136  // Add a callback to be called to delete the elements when the array took
137  // their ownership.
138  void set_clear_callback(std::function<void(T)> cb) {
139  clear_cb_ = cb;
140  }
141 
142  // Clear the array, calling the clear callback function if any.
143  // All the owned callbacks are also deleted.
144  // If you don't want the callbacks to be deleted, before calling clear, set
145  // the callback to nullptr.
146  void clear();
147 
148  // Delete objects pointed to by data_[i]
150 
151  // This method clears the current object, then, does a shallow copy of
152  // its argument, and finally invalidates its argument.
153  // Callbacks are moved to the current object;
154  void move(GenericVector<T> *from);
155 
156  // Read/Write the array to a file. This does _NOT_ read/write the callbacks.
157  // The callback given must be permanent since they will be called more than
158  // once. The given callback will be deleted at the end.
159  // If the callbacks are nullptr, then the data is simply read/written using
160  // fread (and swapping)/fwrite.
161  // Returns false on error or if the callback returns false.
162  // DEPRECATED. Use [De]Serialize[Classes] instead.
163  bool write(FILE *f, std::function<bool(FILE *, const T &)> cb) const;
164  bool read(TFile *f, std::function<bool(TFile *, T *)> cb);
165  // Writes a vector of simple types to the given file. Assumes that bitwise
166  // read/write of T will work. Returns false in case of error.
167  // TODO(rays) Change all callers to use TFile and remove deprecated methods.
168  bool Serialize(FILE *fp) const;
169  bool Serialize(TFile *fp) const;
170  // Reads a vector of simple types from the given file. Assumes that bitwise
171  // read/write will work with ReverseN according to sizeof(T).
172  // Returns false in case of error.
173  // If swap is true, assumes a big/little-endian swap is needed.
174  // TFile is assumed to know about swapping.
175  bool DeSerialize(bool swap, FILE *fp);
176  bool DeSerialize(TFile *fp);
177  // Writes a vector of classes to the given file. Assumes the existence of
178  // bool T::Serialize(FILE* fp) const that returns false in case of error.
179  // Returns false in case of error.
180  bool SerializeClasses(FILE *fp) const;
181  bool SerializeClasses(TFile *fp) const;
182  // Reads a vector of classes from the given file. Assumes the existence of
183  // bool T::Deserialize(bool swap, FILE* fp) that returns false in case of
184  // error. Also needs T::T() and T::T(constT&), as init_to_size is used in
185  // this function. Returns false in case of error.
186  // If swap is true, assumes a big/little-endian swap is needed.
187  bool DeSerializeClasses(bool swap, FILE *fp);
189 
190  // Allocates a new array of double the current_size, copies over the
191  // information from data to the new location, deletes data and returns
192  // the pointed to the new larger array.
193  // This function uses memcpy to copy the data, instead of invoking
194  // operator=() for each element like double_the_size() does.
195  static T *double_the_size_memcpy(int current_size, T *data) {
196  T *data_new = new T[current_size * 2];
197  memcpy(data_new, data, sizeof(T) * current_size);
198  delete[] data;
199  return data_new;
200  }
201 
202  // Reverses the elements of the vector.
203  void reverse() {
204  for (int i = 0; i < size_used_ / 2; ++i) {
205  std::swap(data_[i], data_[size_used_ - 1 - i]);
206  }
207  }
208 
209  // Sorts the members of this vector using the less than comparator (cmp_lt),
210  // which compares the values. Useful for GenericVectors to primitive types.
211  // Will not work so great for pointers (unless you just want to sort some
212  // pointers). You need to provide a specialization to sort_cmp to use
213  // your type.
214  void sort();
215 
216  // Sort the array into the order defined by the qsort function comparator.
217  // The comparator function is as defined by qsort, ie. it receives pointers
218  // to two Ts and returns negative if the first element is to appear earlier
219  // in the result and positive if it is to appear later, with 0 for equal.
220  void sort(int (*comparator)(const void *, const void *)) {
221  qsort(data_, size_used_, sizeof(*data_), comparator);
222  }
223 
224  // Searches the array (assuming sorted in ascending order, using sort()) for
225  // an element equal to target and returns the index of the best candidate.
226  // The return value is conceptually the largest index i such that
227  // data_[i] <= target or 0 if target < the whole vector.
228  // NOTE that this function uses operator> so really the return value is
229  // the largest index i such that data_[i] > target is false.
230  int binary_search(const T &target) const {
231  int bottom = 0;
232  int top = size_used_;
233  while (top - bottom > 1) {
234  int middle = (bottom + top) / 2;
235  if (data_[middle] > target) {
236  top = middle;
237  } else {
238  bottom = middle;
239  }
240  }
241  return bottom;
242  }
243 
244  // Swaps the elements with the given indices.
245  void swap(int index1, int index2) {
246  if (index1 != index2) {
247  T tmp = data_[index1];
248  data_[index1] = data_[index2];
249  data_[index2] = tmp;
250  }
251  }
252  // Returns true if all elements of *this are within the given range.
253  // Only uses operator<
254  /*bool WithinBounds(const T& rangemin, const T& rangemax) const {
255  for (int i = 0; i < size_used_; ++i) {
256  if (data_[i] < rangemin || rangemax < data_[i]) {
257  return false;
258  }
259  }
260  return true;
261 }*/
262 
263 protected:
264  // Init the object, allocating size memory.
265  void init(int size);
266 
267  // We are assuming that the object generally placed in the
268  // vector are small enough that for efficiency it makes sense
269  // to start with a larger initial size.
270  static const int kDefaultVectorSize = 4;
271  int32_t size_used_{};
272  int32_t size_reserved_{};
273  T *data_;
274  std::function<void(T)> clear_cb_;
275 };
276 
277 // The default FileReader loads the whole file into the vector of char,
278 // returning false on error.
279 inline bool LoadDataFromFile(const char *filename, GenericVector<char> *data) {
280  bool result = false;
281  FILE *fp = fopen(filename, "rb");
282  if (fp != nullptr) {
283  fseek(fp, 0, SEEK_END);
284  auto size = std::ftell(fp);
285  fseek(fp, 0, SEEK_SET);
286  // Trying to open a directory on Linux sets size to LONG_MAX. Catch it here.
287  if (size > 0 && size < LONG_MAX) {
288  // reserve an extra byte in case caller wants to append a '\0' character
289  data->reserve(size + 1);
290  data->resize_no_init(size);
291  result = static_cast<long>(fread(&(*data)[0], 1, size, fp)) == size;
292  }
293  fclose(fp);
294  }
295  return result;
296 }
297 
298 // The default FileWriter writes the vector of char to the filename file,
299 // returning false on error.
300 inline bool SaveDataToFile(const GenericVector<char> &data, const char *filename) {
301  FILE *fp = fopen(filename, "wb");
302  if (fp == nullptr) {
303  return false;
304  }
305  bool result = fwrite(&data[0], 1, data.size(), fp) == data.size();
306  fclose(fp);
307  return result;
308 }
309 
310 template <typename T>
311 bool cmp_eq(T const &t1, T const &t2) {
312  return t1 == t2;
313 }
314 
315 // Used by sort()
316 // return < 0 if t1 < t2
317 // return 0 if t1 == t2
318 // return > 0 if t1 > t2
319 template <typename T>
320 int sort_cmp(const void *t1, const void *t2) {
321  const T *a = static_cast<const T *>(t1);
322  const T *b = static_cast<const T *>(t2);
323  if (*a < *b) {
324  return -1;
325  }
326  if (*b < *a) {
327  return 1;
328  }
329  return 0;
330 }
331 
332 // Used by PointerVector::sort()
333 // return < 0 if t1 < t2
334 // return 0 if t1 == t2
335 // return > 0 if t1 > t2
336 template <typename T>
337 int sort_ptr_cmp(const void *t1, const void *t2) {
338  const T *a = *static_cast<T *const *>(t1);
339  const T *b = *static_cast<T *const *>(t2);
340  if (*a < *b) {
341  return -1;
342  }
343  if (*b < *a) {
344  return 1;
345  }
346  return 0;
347 }
348 
349 // Subclass for a vector of pointers. Use in preference to GenericVector<T*>
350 // as it provides automatic deletion and correct serialization, with the
351 // corollary that all copy operations are deep copies of the pointed-to objects.
352 template <typename T>
353 class PointerVector : public GenericVector<T *> {
354 public:
356  explicit PointerVector(int size) : GenericVector<T *>(size) {}
358  // Clear must be called here, even though it is called again by the base,
359  // as the base will call the wrong clear.
360  clear();
361  }
362  // Copy must be deep, as the pointers will be automatically deleted on
363  // destruction.
364  PointerVector(const PointerVector &other) : GenericVector<T *>(other) {
365  this->init(other.size());
366  this->operator+=(other);
367  }
369  this->reserve(this->size_used_ + other.size_used_);
370  for (unsigned i = 0; i < other.size(); ++i) {
371  this->push_back(new T(*other.data_[i]));
372  }
373  return *this;
374  }
375 
377  if (&other != this) {
378  this->truncate(0);
379  this->operator+=(other);
380  }
381  return *this;
382  }
383 
384  // Removes an element at the given index and
385  // shifts the remaining elements to the left.
386  void remove(int index) {
387  delete GenericVector<T *>::data_[index];
389  }
390 
391  // Truncates the array to the given size by removing the end.
392  // If the current size is less, the array is not expanded.
393  void truncate(int size) {
394  for (int i = size; i < GenericVector<T *>::size_used_; ++i) {
395  delete GenericVector<T *>::data_[i];
396  }
398  }
399 
400  // Clear the array, calling the clear callback function if any.
401  // All the owned callbacks are also deleted.
402  // If you don't want the callbacks to be deleted, before calling clear, set
403  // the callback to nullptr.
404  void clear() {
407  }
408 
409  // Writes a vector of (pointers to) classes to the given file. Assumes the
410  // existence of bool T::Serialize(FILE*) const that returns false in case of
411  // error. There is no Serialize for simple types, as you would have a
412  // normal GenericVector of those.
413  // Returns false in case of error.
414  bool Serialize(FILE *fp) const {
415  int32_t used = GenericVector<T *>::size_used_;
416  if (fwrite(&used, sizeof(used), 1, fp) != 1) {
417  return false;
418  }
419  for (int i = 0; i < used; ++i) {
420  int8_t non_null = GenericVector<T *>::data_[i] != nullptr;
421  if (fwrite(&non_null, sizeof(non_null), 1, fp) != 1) {
422  return false;
423  }
424  if (non_null && !GenericVector<T *>::data_[i]->Serialize(fp)) {
425  return false;
426  }
427  }
428  return true;
429  }
430  bool Serialize(TFile *fp) const {
431  int32_t used = GenericVector<T *>::size_used_;
432  if (fp->FWrite(&used, sizeof(used), 1) != 1) {
433  return false;
434  }
435  for (int i = 0; i < used; ++i) {
436  int8_t non_null = GenericVector<T *>::data_[i] != nullptr;
437  if (fp->FWrite(&non_null, sizeof(non_null), 1) != 1) {
438  return false;
439  }
440  if (non_null && !GenericVector<T *>::data_[i]->Serialize(fp)) {
441  return false;
442  }
443  }
444  return true;
445  }
446  // Reads a vector of (pointers to) classes to the given file. Assumes the
447  // existence of bool T::DeSerialize(bool, Tfile*) const that returns false in
448  // case of error. There is no Serialize for simple types, as you would have a
449  // normal GenericVector of those.
450  // If swap is true, assumes a big/little-endian swap is needed.
451  // Also needs T::T(), as new T is used in this function.
452  // Returns false in case of error.
453  bool DeSerialize(bool swap, FILE *fp) {
454  uint32_t reserved;
455  if (fread(&reserved, sizeof(reserved), 1, fp) != 1) {
456  return false;
457  }
458  if (swap) {
459  Reverse32(&reserved);
460  }
461  // Arbitrarily limit the number of elements to protect against bad data.
462  assert(reserved <= UINT16_MAX);
463  if (reserved > UINT16_MAX) {
464  return false;
465  }
466  GenericVector<T *>::reserve(reserved);
467  truncate(0);
468  for (uint32_t i = 0; i < reserved; ++i) {
469  int8_t non_null;
470  if (fread(&non_null, sizeof(non_null), 1, fp) != 1) {
471  return false;
472  }
473  T *item = nullptr;
474  if (non_null != 0) {
475  item = new T;
476  if (!item->DeSerialize(swap, fp)) {
477  delete item;
478  return false;
479  }
480  this->push_back(item);
481  } else {
482  // Null elements should keep their place in the vector.
483  this->push_back(nullptr);
484  }
485  }
486  return true;
487  }
488 
489  // Sorts the items pointed to by the members of this vector using
490  // t::operator<().
491  void sort() {
492  this->GenericVector<T *>::sort(&sort_ptr_cmp<T>);
493  }
494 };
495 
496 template <typename T>
497 void GenericVector<T>::init(int size) {
498  size_used_ = 0;
499  if (size <= 0) {
500  data_ = nullptr;
501  size_reserved_ = 0;
502  } else {
503  if (size < kDefaultVectorSize) {
504  size = kDefaultVectorSize;
505  }
506  data_ = new T[size];
507  size_reserved_ = size;
508  }
509  clear_cb_ = nullptr;
510 }
511 
512 template <typename T>
514  clear();
515 }
516 
517 // Reserve some memory. If the internal array contains elements, they are
518 // copied.
519 template <typename T>
521  if (size_reserved_ >= size || size <= 0) {
522  return;
523  }
524  if (size < kDefaultVectorSize) {
525  size = kDefaultVectorSize;
526  }
527  T *new_array = new T[size];
528  for (int i = 0; i < size_used_; ++i) {
529  new_array[i] = data_[i];
530  }
531  delete[] data_;
532  data_ = new_array;
533  size_reserved_ = size;
534 }
535 
536 template <typename T>
538  if (size_reserved_ == 0) {
539  reserve(kDefaultVectorSize);
540  } else {
541  reserve(2 * size_reserved_);
542  }
543 }
544 
545 // Resizes to size and sets all values to t.
546 template <typename T>
547 void GenericVector<T>::init_to_size(int size, const T &t) {
548  reserve(size);
549  size_used_ = size;
550  for (int i = 0; i < size; ++i) {
551  data_[i] = t;
552  }
553 }
554 
555 template <typename T>
556 void GenericVector<T>::resize(int size, const T &t) {
557  init_to_size(size, t);
558 }
559 
560 template <typename T>
561 T &GenericVector<T>::operator[](int index) const {
562  assert(index >= 0 && index < size_used_);
563  return data_[index];
564 }
565 
566 template <typename T>
568  assert(size_used_ > 0);
569  return data_[size_used_ - 1];
570 }
571 // Returns the last object and removes it.
572 template <typename T>
574  assert(size_used_ > 0);
575  return data_[--size_used_];
576 }
577 
578 // Return the object from an index.
579 template <typename T>
580 void GenericVector<T>::set(const T &t, int index) {
581  assert(index >= 0 && index < size_used_);
582  data_[index] = t;
583 }
584 
585 // Shifts the rest of the elements to the right to make
586 // space for the new elements and inserts the given element
587 // at the specified index.
588 template <typename T>
589 void GenericVector<T>::insert(const T &t, int index) {
590  assert(index >= 0 && index <= size_used_);
591  if (size_reserved_ == size_used_) {
592  double_the_size();
593  }
594  for (int i = size_used_; i > index; --i) {
595  data_[i] = data_[i - 1];
596  }
597  data_[index] = t;
598  size_used_++;
599 }
600 
601 // Removes an element at the given index and
602 // shifts the remaining elements to the left.
603 template <typename T>
604 void GenericVector<T>::remove(int index) {
605  assert(index >= 0 && index < size_used_);
606  for (int i = index; i < size_used_ - 1; ++i) {
607  data_[i] = data_[i + 1];
608  }
609  size_used_--;
610 }
611 
612 // Return the index of the T object.
613 template <typename T>
614 int GenericVector<T>::get_index(const T &object) const {
615  for (int i = 0; i < size_used_; ++i) {
616  if (object == data_[i]) {
617  return i;
618  }
619  }
620  return -1;
621 }
622 
623 // Add an element in the array
624 template <typename T>
626  int index = 0;
627  if (size_used_ == size_reserved_) {
628  double_the_size();
629  }
630  index = size_used_++;
631  data_[index] = object;
632  return index;
633 }
634 
635 template <typename T>
636 int GenericVector<T>::push_back_new(const T &object) {
637  int index = get_index(object);
638  if (index >= 0) {
639  return index;
640  }
641  return push_back(object);
642 }
643 
644 // Add an element in the array (front)
645 template <typename T>
646 int GenericVector<T>::push_front(const T &object) {
647  if (size_used_ == size_reserved_) {
648  double_the_size();
649  }
650  for (int i = size_used_; i > 0; --i) {
651  data_[i] = data_[i - 1];
652  }
653  data_[0] = object;
654  ++size_used_;
655  return 0;
656 }
657 
658 template <typename T>
660  push_back(t);
661 }
662 
663 template <typename T>
665  this->reserve(size_used_ + other.size_used_);
666  for (unsigned i = 0; i < other.size(); ++i) {
667  this->operator+=(other.data_[i]);
668  }
669  return *this;
670 }
671 
672 template <typename T>
674  if (&other != this) {
675  this->truncate(0);
676  this->operator+=(other);
677  }
678  return *this;
679 }
680 
681 // Clear the array, calling the callback function if any.
682 template <typename T>
684  if (size_reserved_ > 0 && clear_cb_ != nullptr) {
685  for (int i = 0; i < size_used_; ++i) {
686  clear_cb_(data_[i]);
687  }
688  }
689  delete[] data_;
690  data_ = nullptr;
691  size_used_ = 0;
692  size_reserved_ = 0;
693  clear_cb_ = nullptr;
694 }
695 
696 template <typename T>
698  for (int i = 0; i < size_used_; ++i) {
699  delete data_[i];
700  }
701 }
702 
703 template <typename T>
704 bool GenericVector<T>::write(FILE *f, std::function<bool(FILE *, const T &)> cb) const {
705  if (fwrite(&size_reserved_, sizeof(size_reserved_), 1, f) != 1) {
706  return false;
707  }
708  if (fwrite(&size_used_, sizeof(size_used_), 1, f) != 1) {
709  return false;
710  }
711  if (cb != nullptr) {
712  for (int i = 0; i < size_used_; ++i) {
713  if (!cb(f, data_[i])) {
714  return false;
715  }
716  }
717  } else {
718  if (fwrite(data_, sizeof(T), size_used_, f) != unsigned_size()) {
719  return false;
720  }
721  }
722  return true;
723 }
724 
725 template <typename T>
726 bool GenericVector<T>::read(TFile *f, std::function<bool(TFile *, T *)> cb) {
727  int32_t reserved;
728  if (f->FReadEndian(&reserved, sizeof(reserved), 1) != 1) {
729  return false;
730  }
731  reserve(reserved);
732  if (f->FReadEndian(&size_used_, sizeof(size_used_), 1) != 1) {
733  return false;
734  }
735  if (cb != nullptr) {
736  for (int i = 0; i < size_used_; ++i) {
737  if (!cb(f, data_ + i)) {
738  return false;
739  }
740  }
741  } else {
742  if (f->FReadEndian(data_, sizeof(T), size_used_) != static_cast<unsigned>(size_used_)) {
743  return false;
744  }
745  }
746  return true;
747 }
748 
749 // Writes a vector of simple types to the given file. Assumes that bitwise
750 // read/write of T will work. Returns false in case of error.
751 template <typename T>
752 bool GenericVector<T>::Serialize(FILE *fp) const {
753  if (fwrite(&size_used_, sizeof(size_used_), 1, fp) != 1) {
754  return false;
755  }
756  if (fwrite(data_, sizeof(*data_), size_used_, fp) != unsigned_size()) {
757  return false;
758  }
759  return true;
760 }
761 template <typename T>
763  if (fp->FWrite(&size_used_, sizeof(size_used_), 1) != 1) {
764  return false;
765  }
766  if (fp->FWrite(data_, sizeof(*data_), size_used_) != size_used_) {
767  return false;
768  }
769  return true;
770 }
771 
772 // Reads a vector of simple types from the given file. Assumes that bitwise
773 // read/write will work with ReverseN according to sizeof(T).
774 // Returns false in case of error.
775 // If swap is true, assumes a big/little-endian swap is needed.
776 template <typename T>
777 bool GenericVector<T>::DeSerialize(bool swap, FILE *fp) {
778  uint32_t reserved;
779  if (fread(&reserved, sizeof(reserved), 1, fp) != 1) {
780  return false;
781  }
782  if (swap) {
783  Reverse32(&reserved);
784  }
785  // Arbitrarily limit the number of elements to protect against bad data.
786  assert(reserved <= UINT16_MAX);
787  if (reserved > UINT16_MAX) {
788  return false;
789  }
790  reserve(reserved);
791  size_used_ = reserved;
792  if (fread(data_, sizeof(T), size_used_, fp) != unsigned_size()) {
793  return false;
794  }
795  if (swap) {
796  for (int i = 0; i < size_used_; ++i) {
797  ReverseN(&data_[i], sizeof(data_[i]));
798  }
799  }
800  return true;
801 }
802 template <typename T>
804  uint32_t reserved;
805  if (fp->FReadEndian(&reserved, sizeof(reserved), 1) != 1) {
806  return false;
807  }
808  // Arbitrarily limit the number of elements to protect against bad data.
809  const uint32_t limit = 50000000;
810  assert(reserved <= limit);
811  if (reserved > limit) {
812  return false;
813  }
814  reserve(reserved);
815  size_used_ = reserved;
816  return fp->FReadEndian(data_, sizeof(T), size_used_) == size_used_;
817 }
818 
819 // Writes a vector of classes to the given file. Assumes the existence of
820 // bool T::Serialize(FILE* fp) const that returns false in case of error.
821 // Returns false in case of error.
822 template <typename T>
824  if (fwrite(&size_used_, sizeof(size_used_), 1, fp) != 1) {
825  return false;
826  }
827  for (int i = 0; i < size_used_; ++i) {
828  if (!data_[i].Serialize(fp)) {
829  return false;
830  }
831  }
832  return true;
833 }
834 template <typename T>
836  if (fp->FWrite(&size_used_, sizeof(size_used_), 1) != 1) {
837  return false;
838  }
839  for (int i = 0; i < size_used_; ++i) {
840  if (!data_[i].Serialize(fp)) {
841  return false;
842  }
843  }
844  return true;
845 }
846 
847 // Reads a vector of classes from the given file. Assumes the existence of
848 // bool T::Deserialize(bool swap, FILE* fp) that returns false in case of
849 // error. Also needs T::T() and T::T(constT&), as init_to_size is used in
850 // this function. Returns false in case of error.
851 // If swap is true, assumes a big/little-endian swap is needed.
852 template <typename T>
853 bool GenericVector<T>::DeSerializeClasses(bool swap, FILE *fp) {
854  int32_t reserved;
855  if (fread(&reserved, sizeof(reserved), 1, fp) != 1) {
856  return false;
857  }
858  if (swap) {
859  Reverse32(&reserved);
860  }
861  T empty;
862  init_to_size(reserved, empty);
863  for (int i = 0; i < reserved; ++i) {
864  if (!data_[i].DeSerialize(swap, fp)) {
865  return false;
866  }
867  }
868  return true;
869 }
870 template <typename T>
872  int32_t reserved;
873  if (fp->FReadEndian(&reserved, sizeof(reserved), 1) != 1) {
874  return false;
875  }
876  T empty;
877  init_to_size(reserved, empty);
878  for (int i = 0; i < reserved; ++i) {
879  if (!data_[i].DeSerialize(fp)) {
880  return false;
881  }
882  }
883  return true;
884 }
885 
886 // This method clear the current object, then, does a shallow copy of
887 // its argument, and finally invalidates its argument.
888 template <typename T>
890  this->clear();
891  this->data_ = from->data_;
892  this->size_reserved_ = from->size_reserved_;
893  this->size_used_ = from->size_used_;
894  this->clear_cb_ = from->clear_cb_;
895  from->data_ = nullptr;
896  from->clear_cb_ = nullptr;
897  from->size_used_ = 0;
898  from->size_reserved_ = 0;
899 }
900 
901 template <typename T>
903  sort(&sort_cmp<T>);
904 }
905 
906 } // namespace tesseract
907 
908 #endif // TESSERACT_CCUTIL_GENERICVECTOR_H_
void ReverseN(void *ptr, int num_bytes)
Definition: helpers.h:189
bool cmp_eq(T const &t1, T const &t2)
bool DeSerialize(bool swap, FILE *fp, std::vector< T > &data)
Definition: helpers.h:220
bool Serialize(FILE *fp, const std::vector< T > &data)
Definition: helpers.h:251
ICOORD & operator+=(ICOORD &op1, const ICOORD &op2)
Definition: points.h:372
int sort_cmp(const void *t1, const void *t2)
bool SaveDataToFile(const GenericVector< char > &data, const char *filename)
void Reverse32(void *ptr)
Definition: helpers.h:206
int sort_ptr_cmp(const void *t1, const void *t2)
bool LoadDataFromFile(const char *filename, GenericVector< char > *data)
size_t unsigned_size() const
Definition: genericvector.h:78
void resize(int size, const T &t)
void resize_no_init(int size)
Definition: genericvector.h:68
int push_back_new(const T &object)
void operator+=(const T &t)
GenericVector(int size, const T &init_val)
Definition: genericvector.h:44
bool read(TFile *f, std::function< bool(TFile *, T *)> cb)
GenericVector(const GenericVector &other)
Definition: genericvector.h:50
bool SerializeClasses(TFile *fp) const
void insert(const T &t, int index)
static const int kDefaultVectorSize
int get_index(const T &object) const
int binary_search(const T &target) const
bool DeSerializeClasses(TFile *fp)
bool Serialize(TFile *fp) const
std::function< void(T)> clear_cb_
void set_clear_callback(std::function< void(T)> cb)
void swap(int index1, int index2)
int push_front(const T &object)
void sort(int(*comparator)(const void *, const void *))
bool Serialize(FILE *fp) const
static T * double_the_size_memcpy(int current_size, T *data)
void set(const T &t, int index)
unsigned size() const
Definition: genericvector.h:74
bool SerializeClasses(FILE *fp) const
GenericVector< T > & operator=(const GenericVector &other)
T & at(int index) const
Definition: genericvector.h:93
bool DeSerialize(TFile *fp)
void remove(int index)
void move(GenericVector< T > *from)
void init_to_size(int size, const T &t)
GenericVector< T > & operator+=(const GenericVector &other)
bool write(FILE *f, std::function< bool(FILE *, const T &)> cb) const
bool DeSerializeClasses(bool swap, FILE *fp)
T & operator[](int index) const
bool DeSerialize(bool swap, FILE *fp)
bool Serialize(FILE *fp) const
bool DeSerialize(bool swap, FILE *fp)
PointerVector(const PointerVector &other)
bool Serialize(TFile *fp) const
PointerVector< T > & operator=(const PointerVector &other)
void remove(int index)
PointerVector< T > & operator+=(const PointerVector &other)
size_t FWrite(const void *buffer, size_t size, size_t count)
Definition: serialis.cpp:272
size_t FReadEndian(void *buffer, size_t size, size_t count)
Definition: serialis.cpp:210