comparison mupdf-source/thirdparty/tesseract/src/ccutil/genericvector.h @ 2:b50eed0cc0ef upstream

ADD: MuPDF v1.26.7: the MuPDF source as downloaded by a default build of PyMuPDF 1.26.4. The directory name has changed: no version number in the expanded directory now.
author Franz Glasner <fzglas.hg@dom66.de>
date Mon, 15 Sep 2025 11:43:07 +0200
parents
children
comparison
equal deleted inserted replaced
1:1d09e1dec1d9 2:b50eed0cc0ef
1 ///////////////////////////////////////////////////////////////////////
2 // 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 //
17 ///////////////////////////////////////////////////////////////////////
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>
39 class GenericVector {
40 public:
41 GenericVector() {
42 init(kDefaultVectorSize);
43 }
44
45 // Copy
46 GenericVector(const GenericVector &other) {
47 this->init(other.size());
48 this->operator+=(other);
49 }
50 GenericVector<T> &operator+=(const GenericVector &other);
51 GenericVector<T> &operator=(const GenericVector &other);
52
53 ~GenericVector();
54
55 // Reserve some memory.
56 void reserve(int size);
57 // Double the size of the internal array.
58 void double_the_size();
59
60 // Resizes to size and sets all values to t.
61 void init_to_size(int size, const T &t);
62 void resize(int size, const T &t);
63 // Resizes to size without any initialization.
64 void resize_no_init(int size) {
65 reserve(size);
66 size_used_ = size;
67 }
68
69 // Return the size used.
70 unsigned size() const {
71 return size_used_;
72 }
73 // Workaround to avoid g++ -Wsign-compare warnings.
74 size_t unsigned_size() const {
75 static_assert(sizeof(size_used_) <= sizeof(size_t), "Wow! sizeof(size_t) < sizeof(int32_t)!!");
76 assert(0 <= size_used_);
77 return static_cast<size_t>(size_used_);
78 }
79 int size_reserved() const {
80 return size_reserved_;
81 }
82
83 // Return true if empty.
84 bool empty() const {
85 return size_used_ == 0;
86 }
87
88 // Return the object from an index.
89 T &at(int index) const {
90 assert(index >= 0 && index < size_used_);
91 return data_[index];
92 }
93
94 T &back() const;
95 T &operator[](int index) const;
96 // Returns the last object and removes it.
97 T pop_back();
98
99 // Return the index of the T object.
100 int get_index(const T &object) const;
101
102 // Push an element in the end of the array
103 int push_back(T object);
104 void operator+=(const T &t);
105
106 // Set the value at the given index
107 void set(const T &t, int index);
108
109 // Insert t at the given index, push other elements to the right.
110 void insert(const T &t, int index);
111
112 // Removes an element at the given index and
113 // shifts the remaining elements to the left.
114 void remove(int index);
115
116 // Truncates the array to the given size by removing the end.
117 // If the current size is less, the array is not expanded.
118 void truncate(int size) {
119 if (size < size_used_) {
120 size_used_ = size;
121 }
122 }
123
124 // Add a callback to be called to delete the elements when the array took
125 // their ownership.
126 void set_clear_callback(const std::function<void(T)> &cb) {
127 clear_cb_ = cb;
128 }
129
130 // Clear the array, calling the clear callback function if any.
131 // All the owned callbacks are also deleted.
132 // If you don't want the callbacks to be deleted, before calling clear, set
133 // the callback to nullptr.
134 void clear();
135
136 // Delete objects pointed to by data_[i]
137 void delete_data_pointers();
138
139 // This method clears the current object, then, does a shallow copy of
140 // its argument, and finally invalidates its argument.
141 // Callbacks are moved to the current object;
142 void move(GenericVector<T> *from);
143
144 // Read/Write the array to a file. This does _NOT_ read/write the callbacks.
145 // The callback given must be permanent since they will be called more than
146 // once. The given callback will be deleted at the end.
147 // If the callbacks are nullptr, then the data is simply read/written using
148 // fread (and swapping)/fwrite.
149 // Returns false on error or if the callback returns false.
150 // DEPRECATED. Use [De]Serialize[Classes] instead.
151 bool write(FILE *f, const std::function<bool(FILE *, const T &)> &cb) const;
152 bool read(TFile *f, const std::function<bool(TFile *, T *)> &cb);
153 // Writes a vector of simple types to the given file. Assumes that bitwise
154 // read/write of T will work. Returns false in case of error.
155 // TODO(rays) Change all callers to use TFile and remove deprecated methods.
156 bool Serialize(FILE *fp) const;
157 bool Serialize(TFile *fp) const;
158 // Reads a vector of simple types from the given file. Assumes that bitwise
159 // read/write will work with ReverseN according to sizeof(T).
160 // Returns false in case of error.
161 // If swap is true, assumes a big/little-endian swap is needed.
162 // TFile is assumed to know about swapping.
163 bool DeSerialize(bool swap, FILE *fp);
164 bool DeSerialize(TFile *fp);
165 // Writes a vector of classes to the given file. Assumes the existence of
166 // bool T::Serialize(FILE* fp) const that returns false in case of error.
167 // Returns false in case of error.
168 bool SerializeClasses(FILE *fp) const;
169 // Reads a vector of classes from the given file. Assumes the existence of
170 // bool T::Deserialize(bool swap, FILE* fp) that returns false in case of
171 // error. Also needs T::T() and T::T(constT&), as init_to_size is used in
172 // this function. Returns false in case of error.
173 // If swap is true, assumes a big/little-endian swap is needed.
174 bool DeSerializeClasses(TFile *fp);
175
176 // Reverses the elements of the vector.
177 void reverse() {
178 for (int i = 0; i < size_used_ / 2; ++i) {
179 std::swap(data_[i], data_[size_used_ - 1 - i]);
180 }
181 }
182
183 // Sorts the members of this vector using the less than comparator (cmp_lt),
184 // which compares the values. Useful for GenericVectors to primitive types.
185 // Will not work so great for pointers (unless you just want to sort some
186 // pointers). You need to provide a specialization to sort_cmp to use
187 // your type.
188 void sort();
189
190 // Sort the array into the order defined by the qsort function comparator.
191 // The comparator function is as defined by qsort, ie. it receives pointers
192 // to two Ts and returns negative if the first element is to appear earlier
193 // in the result and positive if it is to appear later, with 0 for equal.
194 void sort(int (*comparator)(const void *, const void *)) {
195 qsort(data_, size_used_, sizeof(*data_), comparator);
196 }
197
198 // Swaps the elements with the given indices.
199 void swap(int index1, int index2) {
200 if (index1 != index2) {
201 T tmp = data_[index1];
202 data_[index1] = data_[index2];
203 data_[index2] = tmp;
204 }
205 }
206 // Returns true if all elements of *this are within the given range.
207 // Only uses operator<
208 /*bool WithinBounds(const T& rangemin, const T& rangemax) const {
209 for (int i = 0; i < size_used_; ++i) {
210 if (data_[i] < rangemin || rangemax < data_[i]) {
211 return false;
212 }
213 }
214 return true;
215 }*/
216
217 protected:
218 // Init the object, allocating size memory.
219 void init(int size);
220
221 // We are assuming that the object generally placed in the
222 // vector are small enough that for efficiency it makes sense
223 // to start with a larger initial size.
224 static const int kDefaultVectorSize = 4;
225 int32_t size_used_{};
226 int32_t size_reserved_{};
227 T *data_;
228 std::function<void(T)> clear_cb_;
229 };
230
231 // The default FileReader loads the whole file into the vector of char,
232 // returning false on error.
233 inline bool LoadDataFromFile(const char *filename, GenericVector<char> *data) {
234 bool result = false;
235 FILE *fp = fopen(filename, "rb");
236 if (fp != nullptr) {
237 fseek(fp, 0, SEEK_END);
238 auto size = std::ftell(fp);
239 fseek(fp, 0, SEEK_SET);
240 // Trying to open a directory on Linux sets size to LONG_MAX. Catch it here.
241 if (size > 0 && size < LONG_MAX) {
242 // reserve an extra byte in case caller wants to append a '\0' character
243 data->reserve(size + 1);
244 data->resize_no_init(size);
245 result = static_cast<long>(fread(&(*data)[0], 1, size, fp)) == size;
246 }
247 fclose(fp);
248 }
249 return result;
250 }
251
252 // The default FileWriter writes the vector of char to the filename file,
253 // returning false on error.
254 inline bool SaveDataToFile(const GenericVector<char> &data, const char *filename) {
255 FILE *fp = fopen(filename, "wb");
256 if (fp == nullptr) {
257 return false;
258 }
259 bool result = fwrite(&data[0], 1, data.size(), fp) == data.size();
260 fclose(fp);
261 return result;
262 }
263
264 // Used by sort()
265 // return < 0 if t1 < t2
266 // return 0 if t1 == t2
267 // return > 0 if t1 > t2
268 template <typename T>
269 int sort_cmp(const void *t1, const void *t2) {
270 const T *a = static_cast<const T *>(t1);
271 const T *b = static_cast<const T *>(t2);
272 if (*a < *b) {
273 return -1;
274 }
275 if (*b < *a) {
276 return 1;
277 }
278 return 0;
279 }
280
281 // Used by PointerVector::sort()
282 // return < 0 if t1 < t2
283 // return 0 if t1 == t2
284 // return > 0 if t1 > t2
285 template <typename T>
286 int sort_ptr_cmp(const void *t1, const void *t2) {
287 const T *a = *static_cast<T *const *>(t1);
288 const T *b = *static_cast<T *const *>(t2);
289 if (*a < *b) {
290 return -1;
291 }
292 if (*b < *a) {
293 return 1;
294 }
295 return 0;
296 }
297
298 // Subclass for a vector of pointers. Use in preference to GenericVector<T*>
299 // as it provides automatic deletion and correct serialization, with the
300 // corollary that all copy operations are deep copies of the pointed-to objects.
301 template <typename T>
302 class PointerVector : public GenericVector<T *> {
303 public:
304 PointerVector() : GenericVector<T *>() {}
305 explicit PointerVector(int size) : GenericVector<T *>(size) {}
306 ~PointerVector() {
307 // Clear must be called here, even though it is called again by the base,
308 // as the base will call the wrong clear.
309 clear();
310 }
311 // Copy must be deep, as the pointers will be automatically deleted on
312 // destruction.
313 PointerVector(const PointerVector &other) : GenericVector<T *>(other) {
314 this->init(other.size());
315 this->operator+=(other);
316 }
317 PointerVector<T> &operator+=(const PointerVector &other) {
318 this->reserve(this->size_used_ + other.size_used_);
319 for (unsigned i = 0; i < other.size(); ++i) {
320 this->push_back(new T(*other.data_[i]));
321 }
322 return *this;
323 }
324
325 PointerVector<T> &operator=(const PointerVector &other) {
326 if (&other != this) {
327 this->truncate(0);
328 this->operator+=(other);
329 }
330 return *this;
331 }
332
333 // Removes an element at the given index and
334 // shifts the remaining elements to the left.
335 void remove(int index) {
336 delete GenericVector<T *>::data_[index];
337 GenericVector<T *>::remove(index);
338 }
339
340 // Truncates the array to the given size by removing the end.
341 // If the current size is less, the array is not expanded.
342 void truncate(int size) {
343 for (int i = size; i < GenericVector<T *>::size_used_; ++i) {
344 delete GenericVector<T *>::data_[i];
345 }
346 GenericVector<T *>::truncate(size);
347 }
348
349 // Clear the array, calling the clear callback function if any.
350 // All the owned callbacks are also deleted.
351 // If you don't want the callbacks to be deleted, before calling clear, set
352 // the callback to nullptr.
353 void clear() {
354 GenericVector<T *>::delete_data_pointers();
355 GenericVector<T *>::clear();
356 }
357
358 // Writes a vector of (pointers to) classes to the given file. Assumes the
359 // existence of bool T::Serialize(FILE*) const that returns false in case of
360 // error. There is no Serialize for simple types, as you would have a
361 // normal GenericVector of those.
362 // Returns false in case of error.
363 bool Serialize(FILE *fp) const {
364 int32_t used = GenericVector<T *>::size_used_;
365 if (fwrite(&used, sizeof(used), 1, fp) != 1) {
366 return false;
367 }
368 for (int i = 0; i < used; ++i) {
369 int8_t non_null = GenericVector<T *>::data_[i] != nullptr;
370 if (fwrite(&non_null, sizeof(non_null), 1, fp) != 1) {
371 return false;
372 }
373 if (non_null && !GenericVector<T *>::data_[i]->Serialize(fp)) {
374 return false;
375 }
376 }
377 return true;
378 }
379 bool Serialize(TFile *fp) const {
380 int32_t used = GenericVector<T *>::size_used_;
381 if (fp->FWrite(&used, sizeof(used), 1) != 1) {
382 return false;
383 }
384 for (int i = 0; i < used; ++i) {
385 int8_t non_null = GenericVector<T *>::data_[i] != nullptr;
386 if (fp->FWrite(&non_null, sizeof(non_null), 1) != 1) {
387 return false;
388 }
389 if (non_null && !GenericVector<T *>::data_[i]->Serialize(fp)) {
390 return false;
391 }
392 }
393 return true;
394 }
395 // Reads a vector of (pointers to) classes to the given file. Assumes the
396 // existence of bool T::DeSerialize(bool, Tfile*) const that returns false in
397 // case of error. There is no Serialize for simple types, as you would have a
398 // normal GenericVector of those.
399 // If swap is true, assumes a big/little-endian swap is needed.
400 // Also needs T::T(), as new T is used in this function.
401 // Returns false in case of error.
402 bool DeSerialize(bool swap, FILE *fp) {
403 uint32_t reserved;
404 if (fread(&reserved, sizeof(reserved), 1, fp) != 1) {
405 return false;
406 }
407 if (swap) {
408 Reverse32(&reserved);
409 }
410 // Arbitrarily limit the number of elements to protect against bad data.
411 assert(reserved <= UINT16_MAX);
412 if (reserved > UINT16_MAX) {
413 return false;
414 }
415 GenericVector<T *>::reserve(reserved);
416 truncate(0);
417 for (uint32_t i = 0; i < reserved; ++i) {
418 int8_t non_null;
419 if (fread(&non_null, sizeof(non_null), 1, fp) != 1) {
420 return false;
421 }
422 T *item = nullptr;
423 if (non_null != 0) {
424 item = new T;
425 if (!item->DeSerialize(swap, fp)) {
426 delete item;
427 return false;
428 }
429 this->push_back(item);
430 } else {
431 // Null elements should keep their place in the vector.
432 this->push_back(nullptr);
433 }
434 }
435 return true;
436 }
437
438 // Sorts the items pointed to by the members of this vector using
439 // t::operator<().
440 void sort() {
441 this->GenericVector<T *>::sort(&sort_ptr_cmp<T>);
442 }
443 };
444
445 template <typename T>
446 void GenericVector<T>::init(int size) {
447 size_used_ = 0;
448 if (size <= 0) {
449 data_ = nullptr;
450 size_reserved_ = 0;
451 } else {
452 if (size < kDefaultVectorSize) {
453 size = kDefaultVectorSize;
454 }
455 data_ = new T[size];
456 size_reserved_ = size;
457 }
458 clear_cb_ = nullptr;
459 }
460
461 template <typename T>
462 GenericVector<T>::~GenericVector() {
463 clear();
464 }
465
466 // Reserve some memory. If the internal array contains elements, they are
467 // copied.
468 template <typename T>
469 void GenericVector<T>::reserve(int size) {
470 if (size_reserved_ >= size || size <= 0) {
471 return;
472 }
473 if (size < kDefaultVectorSize) {
474 size = kDefaultVectorSize;
475 }
476 T *new_array = new T[size];
477 for (int i = 0; i < size_used_; ++i) {
478 new_array[i] = data_[i];
479 }
480 delete[] data_;
481 data_ = new_array;
482 size_reserved_ = size;
483 }
484
485 template <typename T>
486 void GenericVector<T>::double_the_size() {
487 if (size_reserved_ == 0) {
488 reserve(kDefaultVectorSize);
489 } else {
490 reserve(2 * size_reserved_);
491 }
492 }
493
494 // Resizes to size and sets all values to t.
495 template <typename T>
496 void GenericVector<T>::init_to_size(int size, const T &t) {
497 reserve(size);
498 size_used_ = size;
499 for (int i = 0; i < size; ++i) {
500 data_[i] = t;
501 }
502 }
503
504 template <typename T>
505 void GenericVector<T>::resize(int size, const T &t) {
506 init_to_size(size, t);
507 }
508
509 template <typename T>
510 T &GenericVector<T>::operator[](int index) const {
511 assert(index >= 0 && index < size_used_);
512 return data_[index];
513 }
514
515 template <typename T>
516 T &GenericVector<T>::back() const {
517 assert(size_used_ > 0);
518 return data_[size_used_ - 1];
519 }
520 // Returns the last object and removes it.
521 template <typename T>
522 T GenericVector<T>::pop_back() {
523 assert(size_used_ > 0);
524 return data_[--size_used_];
525 }
526
527 // Return the object from an index.
528 template <typename T>
529 void GenericVector<T>::set(const T &t, int index) {
530 assert(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(const T &t, int index) {
539 assert(index >= 0 && index <= size_used_);
540 if (size_reserved_ == size_used_) {
541 double_the_size();
542 }
543 for (int i = size_used_; i > index; --i) {
544 data_[i] = data_[i - 1];
545 }
546 data_[index] = t;
547 size_used_++;
548 }
549
550 // Removes an element at the given index and
551 // shifts the remaining elements to the left.
552 template <typename T>
553 void GenericVector<T>::remove(int index) {
554 assert(index >= 0 && index < size_used_);
555 for (int i = index; i < size_used_ - 1; ++i) {
556 data_[i] = data_[i + 1];
557 }
558 size_used_--;
559 }
560
561 // Return the index of the T object.
562 template <typename T>
563 int GenericVector<T>::get_index(const T &object) const {
564 for (int i = 0; i < size_used_; ++i) {
565 if (object == data_[i]) {
566 return i;
567 }
568 }
569 return -1;
570 }
571
572 // Add an element in the array
573 template <typename T>
574 int GenericVector<T>::push_back(T object) {
575 int index = 0;
576 if (size_used_ == size_reserved_) {
577 double_the_size();
578 }
579 index = size_used_++;
580 data_[index] = std::move(object);
581 return index;
582 }
583
584 template <typename T>
585 void GenericVector<T>::operator+=(const T &t) {
586 push_back(t);
587 }
588
589 template <typename T>
590 GenericVector<T> &GenericVector<T>::operator+=(const GenericVector &other) {
591 this->reserve(size_used_ + other.size_used_);
592 for (unsigned i = 0; i < other.size(); ++i) {
593 this->operator+=(other.data_[i]);
594 }
595 return *this;
596 }
597
598 template <typename T>
599 GenericVector<T> &GenericVector<T>::operator=(const GenericVector &other) {
600 if (&other != this) {
601 this->truncate(0);
602 this->operator+=(other);
603 }
604 return *this;
605 }
606
607 // Clear the array, calling the callback function if any.
608 template <typename T>
609 void GenericVector<T>::clear() {
610 if (size_reserved_ > 0 && clear_cb_ != nullptr) {
611 for (int i = 0; i < size_used_; ++i) {
612 clear_cb_(data_[i]);
613 }
614 }
615 delete[] data_;
616 data_ = nullptr;
617 size_used_ = 0;
618 size_reserved_ = 0;
619 clear_cb_ = nullptr;
620 }
621
622 template <typename T>
623 void GenericVector<T>::delete_data_pointers() {
624 for (int i = 0; i < size_used_; ++i) {
625 delete data_[i];
626 }
627 }
628
629 template <typename T>
630 bool GenericVector<T>::write(FILE *f, const std::function<bool(FILE *, const T &)> &cb) const {
631 if (fwrite(&size_reserved_, sizeof(size_reserved_), 1, f) != 1) {
632 return false;
633 }
634 if (fwrite(&size_used_, sizeof(size_used_), 1, f) != 1) {
635 return false;
636 }
637 if (cb != nullptr) {
638 for (int i = 0; i < size_used_; ++i) {
639 if (!cb(f, data_[i])) {
640 return false;
641 }
642 }
643 } else {
644 if (fwrite(data_, sizeof(T), size_used_, f) != unsigned_size()) {
645 return false;
646 }
647 }
648 return true;
649 }
650
651 template <typename T>
652 bool GenericVector<T>::read(TFile *f, const std::function<bool(TFile *, T *)> &cb) {
653 int32_t reserved;
654 if (f->FReadEndian(&reserved, sizeof(reserved), 1) != 1) {
655 return false;
656 }
657 reserve(reserved);
658 if (f->FReadEndian(&size_used_, sizeof(size_used_), 1) != 1) {
659 return false;
660 }
661 if (cb != nullptr) {
662 for (int i = 0; i < size_used_; ++i) {
663 if (!cb(f, data_ + i)) {
664 return false;
665 }
666 }
667 } else {
668 if (f->FReadEndian(data_, sizeof(T), size_used_) != static_cast<unsigned>(size_used_)) {
669 return false;
670 }
671 }
672 return true;
673 }
674
675 // Writes a vector of simple types to the given file. Assumes that bitwise
676 // read/write of T will work. Returns false in case of error.
677 template <typename T>
678 bool GenericVector<T>::Serialize(FILE *fp) const {
679 if (fwrite(&size_used_, sizeof(size_used_), 1, fp) != 1) {
680 return false;
681 }
682 if (fwrite(data_, sizeof(*data_), size_used_, fp) != unsigned_size()) {
683 return false;
684 }
685 return true;
686 }
687 template <typename T>
688 bool GenericVector<T>::Serialize(TFile *fp) const {
689 if (fp->FWrite(&size_used_, sizeof(size_used_), 1) != 1) {
690 return false;
691 }
692 if (fp->FWrite(data_, sizeof(*data_), size_used_) != size_used_) {
693 return false;
694 }
695 return true;
696 }
697
698 // Reads a vector of simple types from the given file. Assumes that bitwise
699 // read/write will work with ReverseN according to sizeof(T).
700 // Returns false in case of error.
701 // If swap is true, assumes a big/little-endian swap is needed.
702 template <typename T>
703 bool GenericVector<T>::DeSerialize(bool swap, FILE *fp) {
704 uint32_t reserved;
705 if (fread(&reserved, sizeof(reserved), 1, fp) != 1) {
706 return false;
707 }
708 if (swap) {
709 Reverse32(&reserved);
710 }
711 // Arbitrarily limit the number of elements to protect against bad data.
712 assert(reserved <= UINT16_MAX);
713 if (reserved > UINT16_MAX) {
714 return false;
715 }
716 reserve(reserved);
717 size_used_ = reserved;
718 if (fread(data_, sizeof(T), size_used_, fp) != unsigned_size()) {
719 return false;
720 }
721 if (swap) {
722 for (int i = 0; i < size_used_; ++i) {
723 ReverseN(&data_[i], sizeof(data_[i]));
724 }
725 }
726 return true;
727 }
728 template <typename T>
729 bool GenericVector<T>::DeSerialize(TFile *fp) {
730 uint32_t reserved;
731 if (fp->FReadEndian(&reserved, sizeof(reserved), 1) != 1) {
732 return false;
733 }
734 // Arbitrarily limit the number of elements to protect against bad data.
735 const uint32_t limit = 50000000;
736 assert(reserved <= limit);
737 if (reserved > limit) {
738 return false;
739 }
740 reserve(reserved);
741 size_used_ = reserved;
742 return fp->FReadEndian(data_, sizeof(T), size_used_) == size_used_;
743 }
744
745 // Writes a vector of classes to the given file. Assumes the existence of
746 // bool T::Serialize(FILE* fp) const that returns false in case of error.
747 // Returns false in case of error.
748 template <typename T>
749 bool GenericVector<T>::SerializeClasses(FILE *fp) const {
750 if (fwrite(&size_used_, sizeof(size_used_), 1, fp) != 1) {
751 return false;
752 }
753 for (int i = 0; i < size_used_; ++i) {
754 if (!data_[i].Serialize(fp)) {
755 return false;
756 }
757 }
758 return true;
759 }
760
761 // Reads a vector of classes from the given file. Assumes the existence of
762 // bool T::Deserialize(bool swap, FILE* fp) that returns false in case of
763 // error. Also needs T::T() and T::T(constT&), as init_to_size is used in
764 // this function. Returns false in case of error.
765 // If swap is true, assumes a big/little-endian swap is needed.
766 template <typename T>
767 bool GenericVector<T>::DeSerializeClasses(TFile *fp) {
768 int32_t reserved;
769 if (fp->FReadEndian(&reserved, sizeof(reserved), 1) != 1) {
770 return false;
771 }
772 T empty;
773 init_to_size(reserved, empty);
774 for (int i = 0; i < reserved; ++i) {
775 if (!data_[i].DeSerialize(fp)) {
776 return false;
777 }
778 }
779 return true;
780 }
781
782 // This method clear the current object, then, does a shallow copy of
783 // its argument, and finally invalidates its argument.
784 template <typename T>
785 void GenericVector<T>::move(GenericVector<T> *from) {
786 this->clear();
787 this->data_ = from->data_;
788 this->size_reserved_ = from->size_reserved_;
789 this->size_used_ = from->size_used_;
790 this->clear_cb_ = from->clear_cb_;
791 from->data_ = nullptr;
792 from->clear_cb_ = nullptr;
793 from->size_used_ = 0;
794 from->size_reserved_ = 0;
795 }
796
797 template <typename T>
798 void GenericVector<T>::sort() {
799 sort(&sort_cmp<T>);
800 }
801
802 } // namespace tesseract
803
804 #endif // TESSERACT_CCUTIL_GENERICVECTOR_H_