/src/tesseract/src/ccutil/genericvector.h
Line | Count | Source |
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 | 887k | GenericVector() { |
42 | 887k | init(kDefaultVectorSize); |
43 | 887k | } tesseract::GenericVector<tesseract::WERD_RES*>::GenericVector() Line | Count | Source | 41 | 887k | GenericVector() { | 42 | 887k | init(kDefaultVectorSize); | 43 | 887k | } |
tesseract::GenericVector<tesseract::FontInfo>::GenericVector() Line | Count | Source | 41 | 8 | GenericVector() { | 42 | 8 | init(kDefaultVectorSize); | 43 | 8 | } |
tesseract::GenericVector<std::__1::vector<int, std::__1::allocator<int> > >::GenericVector() Line | Count | Source | 41 | 4 | GenericVector() { | 42 | 4 | init(kDefaultVectorSize); | 43 | 4 | } |
Unexecuted instantiation: tesseract::GenericVector<int>::GenericVector() |
44 | | |
45 | | // Copy |
46 | 766k | GenericVector(const GenericVector &other) { |
47 | 766k | this->init(other.size()); |
48 | 766k | this->operator+=(other); |
49 | 766k | } |
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 | 0 | void resize_no_init(int size) { |
65 | 0 | reserve(size); |
66 | 0 | size_used_ = size; |
67 | 0 | } |
68 | | |
69 | | // Return the size used. |
70 | 95.6M | unsigned size() const { |
71 | 95.6M | return size_used_; |
72 | 95.6M | } tesseract::GenericVector<tesseract::FontInfo>::size() const Line | Count | Source | 70 | 88.5M | unsigned size() const { | 71 | 88.5M | return size_used_; | 72 | 88.5M | } |
Unexecuted instantiation: tesseract::GenericVector<char>::size() const tesseract::GenericVector<tesseract::WERD_RES*>::size() const Line | Count | Source | 70 | 7.11M | unsigned size() const { | 71 | 7.11M | return size_used_; | 72 | 7.11M | } |
Unexecuted instantiation: tesseract::GenericVector<int>::size() const |
73 | | // Workaround to avoid g++ -Wsign-compare warnings. |
74 | 0 | size_t unsigned_size() const { |
75 | 0 | static_assert(sizeof(size_used_) <= sizeof(size_t), "Wow! sizeof(size_t) < sizeof(int32_t)!!"); |
76 | 0 | assert(0 <= size_used_); |
77 | 0 | return static_cast<size_t>(size_used_); |
78 | 0 | } Unexecuted instantiation: tesseract::GenericVector<tesseract::FontInfo>::unsigned_size() const Unexecuted instantiation: tesseract::GenericVector<std::__1::vector<int, std::__1::allocator<int> > >::unsigned_size() const |
79 | | int size_reserved() const { |
80 | | return size_reserved_; |
81 | | } |
82 | | |
83 | | // Return true if empty. |
84 | 674k | bool empty() const { |
85 | 674k | return size_used_ == 0; |
86 | 674k | } |
87 | | |
88 | | // Return the object from an index. |
89 | 669M | T &at(int index) const { |
90 | 669M | assert(index >= 0 && index < size_used_); |
91 | 669M | return data_[index]; |
92 | 669M | } tesseract::GenericVector<tesseract::FontInfo>::at(int) const Line | Count | Source | 89 | 67.1M | T &at(int index) const { | 90 | | assert(index >= 0 && index < size_used_); | 91 | 67.1M | return data_[index]; | 92 | 67.1M | } |
tesseract::GenericVector<std::__1::vector<int, std::__1::allocator<int> > >::at(int) const Line | Count | Source | 89 | 602M | T &at(int index) const { | 90 | | assert(index >= 0 && index < size_used_); | 91 | 602M | return data_[index]; | 92 | 602M | } |
Unexecuted instantiation: tesseract::GenericVector<tesseract::WERD_RES*>::at(int) const |
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 | 347k | void truncate(int size) { |
119 | 347k | if (size < size_used_) { |
120 | 0 | size_used_ = size; |
121 | 0 | } |
122 | 347k | } tesseract::GenericVector<tesseract::WERD_RES*>::truncate(int) Line | Count | Source | 118 | 347k | void truncate(int size) { | 119 | 347k | if (size < size_used_) { | 120 | 0 | size_used_ = size; | 121 | 0 | } | 122 | 347k | } |
Unexecuted instantiation: tesseract::GenericVector<tesseract::FontInfo>::truncate(int) |
123 | | |
124 | | // Add a callback to be called to delete the elements when the array took |
125 | | // their ownership. |
126 | 4 | void set_clear_callback(const std::function<void(T)> &cb) { |
127 | 4 | clear_cb_ = cb; |
128 | 4 | } |
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 | 0 | inline bool LoadDataFromFile(const char *filename, GenericVector<char> *data) { |
234 | 0 | bool result = false; |
235 | 0 | FILE *fp = fopen(filename, "rb"); |
236 | 0 | if (fp != nullptr) { |
237 | 0 | fseek(fp, 0, SEEK_END); |
238 | 0 | auto size = std::ftell(fp); |
239 | 0 | fseek(fp, 0, SEEK_SET); |
240 | 0 | // Trying to open a directory on Linux sets size to LONG_MAX. Catch it here. |
241 | 0 | if (size > 0 && size < LONG_MAX) { |
242 | 0 | // reserve an extra byte in case caller wants to append a '\0' character |
243 | 0 | data->reserve(size + 1); |
244 | 0 | data->resize_no_init(size); |
245 | 0 | result = static_cast<long>(fread(&(*data)[0], 1, size, fp)) == size; |
246 | 0 | } |
247 | 0 | fclose(fp); |
248 | 0 | } |
249 | 0 | return result; |
250 | 0 | } |
251 | | |
252 | | // The default FileWriter writes the vector of char to the filename file, |
253 | | // returning false on error. |
254 | 0 | inline bool SaveDataToFile(const GenericVector<char> &data, const char *filename) { |
255 | 0 | FILE *fp = fopen(filename, "wb"); |
256 | 0 | if (fp == nullptr) { |
257 | 0 | return false; |
258 | 0 | } |
259 | 0 | bool result = fwrite(&data[0], 1, data.size(), fp) == data.size(); |
260 | 0 | fclose(fp); |
261 | 0 | return result; |
262 | 0 | } |
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 | 887k | PointerVector() : GenericVector<T *>() {} |
305 | | explicit PointerVector(int size) : GenericVector<T *>(size) {} |
306 | 1.65M | ~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 | 1.65M | clear(); |
310 | 1.65M | } |
311 | | // Copy must be deep, as the pointers will be automatically deleted on |
312 | | // destruction. |
313 | 766k | PointerVector(const PointerVector &other) : GenericVector<T *>(other) { |
314 | 766k | this->init(other.size()); |
315 | 766k | this->operator+=(other); |
316 | 766k | } |
317 | 766k | PointerVector<T> &operator+=(const PointerVector &other) { |
318 | 766k | this->reserve(this->size_used_ + other.size_used_); |
319 | 766k | for (unsigned i = 0; i < other.size(); ++i) { |
320 | 0 | this->push_back(new T(*other.data_[i])); |
321 | 0 | } |
322 | 766k | return *this; |
323 | 766k | } |
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 | 347k | void truncate(int size) { |
343 | 347k | for (int i = size; i < GenericVector<T *>::size_used_; ++i) { |
344 | 0 | delete GenericVector<T *>::data_[i]; |
345 | 0 | } |
346 | 347k | GenericVector<T *>::truncate(size); |
347 | 347k | } |
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 | 1.97M | void clear() { |
354 | 1.97M | GenericVector<T *>::delete_data_pointers(); |
355 | 1.97M | GenericVector<T *>::clear(); |
356 | 1.97M | } |
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 | 2.42M | void GenericVector<T>::init(int size) { |
447 | 2.42M | size_used_ = 0; |
448 | 2.42M | if (size <= 0) { |
449 | 1.53M | data_ = nullptr; |
450 | 1.53M | size_reserved_ = 0; |
451 | 1.53M | } else { |
452 | 887k | if (size < kDefaultVectorSize) { |
453 | 0 | size = kDefaultVectorSize; |
454 | 0 | } |
455 | 887k | data_ = new T[size]; |
456 | 887k | size_reserved_ = size; |
457 | 887k | } |
458 | 2.42M | clear_cb_ = nullptr; |
459 | 2.42M | } tesseract::GenericVector<tesseract::WERD_RES*>::init(int) Line | Count | Source | 446 | 2.42M | void GenericVector<T>::init(int size) { | 447 | 2.42M | size_used_ = 0; | 448 | 2.42M | if (size <= 0) { | 449 | 1.53M | data_ = nullptr; | 450 | 1.53M | size_reserved_ = 0; | 451 | 1.53M | } else { | 452 | 887k | if (size < kDefaultVectorSize) { | 453 | 0 | size = kDefaultVectorSize; | 454 | 0 | } | 455 | 887k | data_ = new T[size]; | 456 | 887k | size_reserved_ = size; | 457 | 887k | } | 458 | 2.42M | clear_cb_ = nullptr; | 459 | 2.42M | } |
tesseract::GenericVector<tesseract::FontInfo>::init(int) Line | Count | Source | 446 | 8 | void GenericVector<T>::init(int size) { | 447 | 8 | size_used_ = 0; | 448 | 8 | if (size <= 0) { | 449 | 0 | data_ = nullptr; | 450 | 0 | size_reserved_ = 0; | 451 | 8 | } else { | 452 | 8 | if (size < kDefaultVectorSize) { | 453 | 0 | size = kDefaultVectorSize; | 454 | 0 | } | 455 | 8 | data_ = new T[size]; | 456 | 8 | size_reserved_ = size; | 457 | 8 | } | 458 | 8 | clear_cb_ = nullptr; | 459 | 8 | } |
tesseract::GenericVector<std::__1::vector<int, std::__1::allocator<int> > >::init(int) Line | Count | Source | 446 | 4 | void GenericVector<T>::init(int size) { | 447 | 4 | size_used_ = 0; | 448 | 4 | if (size <= 0) { | 449 | 0 | data_ = nullptr; | 450 | 0 | size_reserved_ = 0; | 451 | 4 | } else { | 452 | 4 | if (size < kDefaultVectorSize) { | 453 | 0 | size = kDefaultVectorSize; | 454 | 0 | } | 455 | 4 | data_ = new T[size]; | 456 | 4 | size_reserved_ = size; | 457 | 4 | } | 458 | 4 | clear_cb_ = nullptr; | 459 | 4 | } |
Unexecuted instantiation: tesseract::GenericVector<int>::init(int) |
460 | | |
461 | | template <typename T> |
462 | 1.65M | GenericVector<T>::~GenericVector() { |
463 | 1.65M | clear(); |
464 | 1.65M | } tesseract::GenericVector<tesseract::WERD_RES*>::~GenericVector() Line | Count | Source | 462 | 1.65M | GenericVector<T>::~GenericVector() { | 463 | 1.65M | clear(); | 464 | 1.65M | } |
tesseract::GenericVector<tesseract::FontInfo>::~GenericVector() Line | Count | Source | 462 | 4 | GenericVector<T>::~GenericVector() { | 463 | 4 | clear(); | 464 | 4 | } |
Unexecuted instantiation: tesseract::GenericVector<std::__1::vector<int, std::__1::allocator<int> > >::~GenericVector() Unexecuted instantiation: tesseract::GenericVector<int>::~GenericVector() |
465 | | |
466 | | // Reserve some memory. If the internal array contains elements, they are |
467 | | // copied. |
468 | | template <typename T> |
469 | 1.95M | void GenericVector<T>::reserve(int size) { |
470 | 1.95M | if (size_reserved_ >= size || size <= 0) { |
471 | 1.53M | return; |
472 | 1.53M | } |
473 | 419k | if (size < kDefaultVectorSize) { |
474 | 0 | size = kDefaultVectorSize; |
475 | 0 | } |
476 | 419k | T *new_array = new T[size]; |
477 | 432k | for (int i = 0; i < size_used_; ++i) { |
478 | 12.8k | new_array[i] = data_[i]; |
479 | 12.8k | } |
480 | 419k | delete[] data_; |
481 | 419k | data_ = new_array; |
482 | 419k | size_reserved_ = size; |
483 | 419k | } Unexecuted instantiation: tesseract::GenericVector<char>::reserve(int) tesseract::GenericVector<tesseract::WERD_RES*>::reserve(int) Line | Count | Source | 469 | 1.95M | void GenericVector<T>::reserve(int size) { | 470 | 1.95M | if (size_reserved_ >= size || size <= 0) { | 471 | 1.53M | return; | 472 | 1.53M | } | 473 | 419k | if (size < kDefaultVectorSize) { | 474 | 0 | size = kDefaultVectorSize; | 475 | 0 | } | 476 | 419k | T *new_array = new T[size]; | 477 | 430k | for (int i = 0; i < size_used_; ++i) { | 478 | 10.7k | new_array[i] = data_[i]; | 479 | 10.7k | } | 480 | 419k | delete[] data_; | 481 | 419k | data_ = new_array; | 482 | 419k | size_reserved_ = size; | 483 | 419k | } |
tesseract::GenericVector<tesseract::FontInfo>::reserve(int) Line | Count | Source | 469 | 36 | void GenericVector<T>::reserve(int size) { | 470 | 36 | if (size_reserved_ >= size || size <= 0) { | 471 | 4 | return; | 472 | 4 | } | 473 | 32 | if (size < kDefaultVectorSize) { | 474 | 0 | size = kDefaultVectorSize; | 475 | 0 | } | 476 | 32 | T *new_array = new T[size]; | 477 | 2.06k | for (int i = 0; i < size_used_; ++i) { | 478 | 2.03k | new_array[i] = data_[i]; | 479 | 2.03k | } | 480 | 32 | delete[] data_; | 481 | 32 | data_ = new_array; | 482 | 32 | size_reserved_ = size; | 483 | 32 | } |
tesseract::GenericVector<std::__1::vector<int, std::__1::allocator<int> > >::reserve(int) Line | Count | Source | 469 | 4 | void GenericVector<T>::reserve(int size) { | 470 | 4 | if (size_reserved_ >= size || size <= 0) { | 471 | 0 | return; | 472 | 0 | } | 473 | 4 | if (size < kDefaultVectorSize) { | 474 | 0 | size = kDefaultVectorSize; | 475 | 0 | } | 476 | 4 | T *new_array = new T[size]; | 477 | 4 | for (int i = 0; i < size_used_; ++i) { | 478 | 0 | new_array[i] = data_[i]; | 479 | 0 | } | 480 | 4 | delete[] data_; | 481 | 4 | data_ = new_array; | 482 | 4 | size_reserved_ = size; | 483 | 4 | } |
|
484 | | |
485 | | template <typename T> |
486 | 419k | void GenericVector<T>::double_the_size() { |
487 | 419k | if (size_reserved_ == 0) { |
488 | 417k | reserve(kDefaultVectorSize); |
489 | 417k | } else { |
490 | 2.22k | reserve(2 * size_reserved_); |
491 | 2.22k | } |
492 | 419k | } tesseract::GenericVector<tesseract::WERD_RES*>::double_the_size() Line | Count | Source | 486 | 419k | void GenericVector<T>::double_the_size() { | 487 | 419k | if (size_reserved_ == 0) { | 488 | 417k | reserve(kDefaultVectorSize); | 489 | 417k | } else { | 490 | 2.19k | reserve(2 * size_reserved_); | 491 | 2.19k | } | 492 | 419k | } |
tesseract::GenericVector<tesseract::FontInfo>::double_the_size() Line | Count | Source | 486 | 28 | void GenericVector<T>::double_the_size() { | 487 | 28 | if (size_reserved_ == 0) { | 488 | 0 | reserve(kDefaultVectorSize); | 489 | 28 | } else { | 490 | 28 | reserve(2 * size_reserved_); | 491 | 28 | } | 492 | 28 | } |
Unexecuted instantiation: tesseract::GenericVector<std::__1::vector<int, std::__1::allocator<int> > >::double_the_size() |
493 | | |
494 | | // Resizes to size and sets all values to t. |
495 | | template <typename T> |
496 | 0 | void GenericVector<T>::init_to_size(int size, const T &t) { |
497 | 0 | reserve(size); |
498 | 0 | size_used_ = size; |
499 | 0 | for (int i = 0; i < size; ++i) { |
500 | 0 | data_[i] = t; |
501 | 0 | } |
502 | 0 | } |
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 | 2.90M | T &GenericVector<T>::operator[](int index) const { |
511 | 2.90M | assert(index >= 0 && index < size_used_); |
512 | 2.90M | return data_[index]; |
513 | 2.90M | } Unexecuted instantiation: tesseract::GenericVector<char>::operator[](int) const tesseract::GenericVector<tesseract::WERD_RES*>::operator[](int) const Line | Count | Source | 510 | 2.90M | T &GenericVector<T>::operator[](int index) const { | 511 | | assert(index >= 0 && index < size_used_); | 512 | 2.90M | return data_[index]; | 513 | 2.90M | } |
Unexecuted instantiation: tesseract::GenericVector<int>::operator[](int) const |
514 | | |
515 | | template <typename T> |
516 | 231k | T &GenericVector<T>::back() const { |
517 | 231k | assert(size_used_ > 0); |
518 | 231k | return data_[size_used_ - 1]; |
519 | 231k | } |
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 | 4.66k | int GenericVector<T>::get_index(const T &object) const { |
564 | 797k | for (int i = 0; i < size_used_; ++i) { |
565 | 795k | if (object == data_[i]) { |
566 | 2.95k | return i; |
567 | 2.95k | } |
568 | 795k | } |
569 | 1.70k | return -1; |
570 | 4.66k | } tesseract::GenericVector<tesseract::FontInfo>::get_index(tesseract::FontInfo const&) const Line | Count | Source | 563 | 4.66k | int GenericVector<T>::get_index(const T &object) const { | 564 | 797k | for (int i = 0; i < size_used_; ++i) { | 565 | 795k | if (object == data_[i]) { | 566 | 2.95k | return i; | 567 | 2.95k | } | 568 | 795k | } | 569 | 1.70k | return -1; | 570 | 4.66k | } |
Unexecuted instantiation: tesseract::GenericVector<std::__1::vector<int, std::__1::allocator<int> > >::get_index(std::__1::vector<int, std::__1::allocator<int> > const&) const |
571 | | |
572 | | // Add an element in the array |
573 | | template <typename T> |
574 | 655k | int GenericVector<T>::push_back(T object) { |
575 | 655k | int index = 0; |
576 | 655k | if (size_used_ == size_reserved_) { |
577 | 419k | double_the_size(); |
578 | 419k | } |
579 | 655k | index = size_used_++; |
580 | 655k | data_[index] = std::move(object); |
581 | 655k | return index; |
582 | 655k | } tesseract::GenericVector<tesseract::WERD_RES*>::push_back(tesseract::WERD_RES*) Line | Count | Source | 574 | 653k | int GenericVector<T>::push_back(T object) { | 575 | 653k | int index = 0; | 576 | 653k | if (size_used_ == size_reserved_) { | 577 | 419k | double_the_size(); | 578 | 419k | } | 579 | 653k | index = size_used_++; | 580 | 653k | data_[index] = std::move(object); | 581 | 653k | return index; | 582 | 653k | } |
tesseract::GenericVector<tesseract::FontInfo>::push_back(tesseract::FontInfo) Line | Count | Source | 574 | 1.70k | int GenericVector<T>::push_back(T object) { | 575 | 1.70k | int index = 0; | 576 | 1.70k | if (size_used_ == size_reserved_) { | 577 | 28 | double_the_size(); | 578 | 28 | } | 579 | 1.70k | index = size_used_++; | 580 | 1.70k | data_[index] = std::move(object); | 581 | 1.70k | return index; | 582 | 1.70k | } |
Unexecuted instantiation: tesseract::GenericVector<std::__1::vector<int, std::__1::allocator<int> > >::push_back(std::__1::vector<int, std::__1::allocator<int> >) |
583 | | |
584 | | template <typename T> |
585 | 0 | void GenericVector<T>::operator+=(const T &t) { |
586 | 0 | push_back(t); |
587 | 0 | } |
588 | | |
589 | | template <typename T> |
590 | 766k | GenericVector<T> &GenericVector<T>::operator+=(const GenericVector &other) { |
591 | 766k | this->reserve(size_used_ + other.size_used_); |
592 | 766k | for (unsigned i = 0; i < other.size(); ++i) { |
593 | 0 | this->operator+=(other.data_[i]); |
594 | 0 | } |
595 | 766k | return *this; |
596 | 766k | } |
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 | 3.63M | void GenericVector<T>::clear() { |
610 | 3.63M | if (size_reserved_ > 0 && clear_cb_ != nullptr) { |
611 | 0 | for (int i = 0; i < size_used_; ++i) { |
612 | 0 | clear_cb_(data_[i]); |
613 | 0 | } |
614 | 0 | } |
615 | 3.63M | delete[] data_; |
616 | 3.63M | data_ = nullptr; |
617 | 3.63M | size_used_ = 0; |
618 | 3.63M | size_reserved_ = 0; |
619 | 3.63M | clear_cb_ = nullptr; |
620 | 3.63M | } tesseract::GenericVector<tesseract::WERD_RES*>::clear() Line | Count | Source | 609 | 3.63M | void GenericVector<T>::clear() { | 610 | 3.63M | if (size_reserved_ > 0 && clear_cb_ != nullptr) { | 611 | 0 | for (int i = 0; i < size_used_; ++i) { | 612 | 0 | clear_cb_(data_[i]); | 613 | 0 | } | 614 | 0 | } | 615 | 3.63M | delete[] data_; | 616 | 3.63M | data_ = nullptr; | 617 | 3.63M | size_used_ = 0; | 618 | 3.63M | size_reserved_ = 0; | 619 | 3.63M | clear_cb_ = nullptr; | 620 | 3.63M | } |
tesseract::GenericVector<tesseract::FontInfo>::clear() Line | Count | Source | 609 | 8 | void GenericVector<T>::clear() { | 610 | 8 | if (size_reserved_ > 0 && clear_cb_ != nullptr) { | 611 | 0 | for (int i = 0; i < size_used_; ++i) { | 612 | 0 | clear_cb_(data_[i]); | 613 | 0 | } | 614 | 0 | } | 615 | 8 | delete[] data_; | 616 | 8 | data_ = nullptr; | 617 | 8 | size_used_ = 0; | 618 | 8 | size_reserved_ = 0; | 619 | 8 | clear_cb_ = nullptr; | 620 | 8 | } |
Unexecuted instantiation: tesseract::GenericVector<std::__1::vector<int, std::__1::allocator<int> > >::clear() Unexecuted instantiation: tesseract::GenericVector<int>::clear() |
621 | | |
622 | | template <typename T> |
623 | 1.97M | void GenericVector<T>::delete_data_pointers() { |
624 | 2.63M | for (int i = 0; i < size_used_; ++i) { |
625 | 653k | delete data_[i]; |
626 | 653k | } |
627 | 1.97M | } |
628 | | |
629 | | template <typename T> |
630 | 0 | bool GenericVector<T>::write(FILE *f, const std::function<bool(FILE *, const T &)> &cb) const { |
631 | 0 | if (fwrite(&size_reserved_, sizeof(size_reserved_), 1, f) != 1) { |
632 | 0 | return false; |
633 | 0 | } |
634 | 0 | if (fwrite(&size_used_, sizeof(size_used_), 1, f) != 1) { |
635 | 0 | return false; |
636 | 0 | } |
637 | 0 | if (cb != nullptr) { |
638 | 0 | for (int i = 0; i < size_used_; ++i) { |
639 | 0 | if (!cb(f, data_[i])) { |
640 | 0 | return false; |
641 | 0 | } |
642 | 0 | } |
643 | 0 | } else { |
644 | 0 | if (fwrite(data_, sizeof(T), size_used_, f) != unsigned_size()) { |
645 | 0 | return false; |
646 | 0 | } |
647 | 0 | } |
648 | 0 | return true; |
649 | 0 | } Unexecuted instantiation: tesseract::GenericVector<tesseract::FontInfo>::write(_IO_FILE*, std::__1::function<bool (_IO_FILE*, tesseract::FontInfo const&)> const&) const Unexecuted instantiation: tesseract::GenericVector<std::__1::vector<int, std::__1::allocator<int> > >::write(_IO_FILE*, std::__1::function<bool (_IO_FILE*, std::__1::vector<int, std::__1::allocator<int> > const&)> const&) const |
650 | | |
651 | | template <typename T> |
652 | 12 | bool GenericVector<T>::read(TFile *f, const std::function<bool(TFile *, T *)> &cb) { |
653 | 12 | int32_t reserved; |
654 | 12 | if (f->FReadEndian(&reserved, sizeof(reserved), 1) != 1) { |
655 | 0 | return false; |
656 | 0 | } |
657 | 12 | reserve(reserved); |
658 | 12 | if (f->FReadEndian(&size_used_, sizeof(size_used_), 1) != 1) { |
659 | 0 | return false; |
660 | 0 | } |
661 | 12 | if (cb != nullptr) { |
662 | 3.87k | for (int i = 0; i < size_used_; ++i) { |
663 | 3.86k | if (!cb(f, data_ + i)) { |
664 | 0 | return false; |
665 | 0 | } |
666 | 3.86k | } |
667 | 12 | } else { |
668 | 0 | if (f->FReadEndian(data_, sizeof(T), size_used_) != static_cast<unsigned>(size_used_)) { |
669 | 0 | return false; |
670 | 0 | } |
671 | 0 | } |
672 | 12 | return true; |
673 | 12 | } tesseract::GenericVector<tesseract::FontInfo>::read(tesseract::TFile*, std::__1::function<bool (tesseract::TFile*, tesseract::FontInfo*)> const&) Line | Count | Source | 652 | 8 | bool GenericVector<T>::read(TFile *f, const std::function<bool(TFile *, T *)> &cb) { | 653 | 8 | int32_t reserved; | 654 | 8 | if (f->FReadEndian(&reserved, sizeof(reserved), 1) != 1) { | 655 | 0 | return false; | 656 | 0 | } | 657 | 8 | reserve(reserved); | 658 | 8 | if (f->FReadEndian(&size_used_, sizeof(size_used_), 1) != 1) { | 659 | 0 | return false; | 660 | 0 | } | 661 | 8 | if (cb != nullptr) { | 662 | 3.42k | for (int i = 0; i < size_used_; ++i) { | 663 | 3.41k | if (!cb(f, data_ + i)) { | 664 | 0 | return false; | 665 | 0 | } | 666 | 3.41k | } | 667 | 8 | } else { | 668 | 0 | if (f->FReadEndian(data_, sizeof(T), size_used_) != static_cast<unsigned>(size_used_)) { | 669 | 0 | return false; | 670 | 0 | } | 671 | 0 | } | 672 | 8 | return true; | 673 | 8 | } |
tesseract::GenericVector<std::__1::vector<int, std::__1::allocator<int> > >::read(tesseract::TFile*, std::__1::function<bool (tesseract::TFile*, std::__1::vector<int, std::__1::allocator<int> >*)> const&) Line | Count | Source | 652 | 4 | bool GenericVector<T>::read(TFile *f, const std::function<bool(TFile *, T *)> &cb) { | 653 | 4 | int32_t reserved; | 654 | 4 | if (f->FReadEndian(&reserved, sizeof(reserved), 1) != 1) { | 655 | 0 | return false; | 656 | 0 | } | 657 | 4 | reserve(reserved); | 658 | 4 | if (f->FReadEndian(&size_used_, sizeof(size_used_), 1) != 1) { | 659 | 0 | return false; | 660 | 0 | } | 661 | 4 | if (cb != nullptr) { | 662 | 448 | for (int i = 0; i < size_used_; ++i) { | 663 | 444 | if (!cb(f, data_ + i)) { | 664 | 0 | return false; | 665 | 0 | } | 666 | 444 | } | 667 | 4 | } else { | 668 | 0 | if (f->FReadEndian(data_, sizeof(T), size_used_) != static_cast<unsigned>(size_used_)) { | 669 | 0 | return false; | 670 | 0 | } | 671 | 0 | } | 672 | 4 | return true; | 673 | 4 | } |
|
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 | 0 | bool GenericVector<T>::SerializeClasses(FILE *fp) const { |
750 | 0 | if (fwrite(&size_used_, sizeof(size_used_), 1, fp) != 1) { |
751 | 0 | return false; |
752 | 0 | } |
753 | 0 | for (int i = 0; i < size_used_; ++i) { |
754 | 0 | if (!data_[i].Serialize(fp)) { |
755 | 0 | return false; |
756 | 0 | } |
757 | 0 | } |
758 | 0 | return true; |
759 | 0 | } |
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 | 0 | bool GenericVector<T>::DeSerializeClasses(TFile *fp) { |
768 | 0 | int32_t reserved; |
769 | 0 | if (fp->FReadEndian(&reserved, sizeof(reserved), 1) != 1) { |
770 | 0 | return false; |
771 | 0 | } |
772 | 0 | T empty; |
773 | 0 | init_to_size(reserved, empty); |
774 | 0 | for (int i = 0; i < reserved; ++i) { |
775 | 0 | if (!data_[i].DeSerialize(fp)) { |
776 | 0 | return false; |
777 | 0 | } |
778 | 0 | } |
779 | 0 | return true; |
780 | 0 | } |
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_ |