| /////////////////////////////////////////////////////////////////////// |
| // File: genericvector.h |
| // Description: Generic vector class |
| // Author: Daria Antonova |
| // Created: Mon Jun 23 11:26:43 PDT 2008 |
| // |
| // (C) Copyright 2007, Google Inc. |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| // |
| /////////////////////////////////////////////////////////////////////// |
| // |
| #ifndef TESSERACT_CCUTIL_GENERICVECTOR_H_ |
| #define TESSERACT_CCUTIL_GENERICVECTOR_H_ |
| |
| #include <stdio.h> |
| |
| #include "callback.h" |
| #include "errcode.h" |
| |
| template <typename T> |
| class GenericVector { |
| public: |
| GenericVector() { this->init(kDefaultVectorSize); } |
| GenericVector(int size) { this->init(size); } |
| |
| // Copy |
| GenericVector(const GenericVector& other) { |
| this->init(other.size()); |
| this->operator+=(other); |
| } |
| GenericVector<T> &operator+=(const GenericVector& other); |
| GenericVector<T> &operator=(const GenericVector& other); |
| |
| virtual ~GenericVector(); |
| |
| // Reserve some memory. |
| void reserve(int size); |
| // Double the size of the internal array. |
| void double_the_size(); |
| |
| // Init the object, allocating size memory. |
| void init(int size); |
| |
| // Return the size used. |
| int size() const { |
| return size_used_; |
| } |
| |
| int length() const { |
| return size_used_; |
| } |
| |
| // Return true if empty. |
| bool empty() const { |
| return size_used_ == 0; |
| } |
| |
| // Return the object from an index. |
| T &get(int index) const; |
| T &operator[](int index) const; |
| |
| // Return the index of the T object. |
| // This method NEEDS a compare_callback to be passed to |
| // set_compare_callback. |
| int get_index(T object) const; |
| |
| // Return true if T is in the array |
| bool contains(T object) const; |
| |
| // Return true if the index is valid |
| T contains_index(int index) const; |
| |
| // Push an element in the end of the array |
| int push_back(T object); |
| void operator+=(T t); |
| |
| // Set the value at the given index |
| void set(T t, int index); |
| |
| // Insert t at the given index, push other elements to the right. |
| void insert(T t, int index); |
| |
| // Removes an element at the given index and |
| // shifts the remaining elements to the left. |
| void remove(int index); |
| |
| // Add a callback to be called to delete the elements when the array took |
| // their ownership. |
| void set_clear_callback(Callback1<T>* cb); |
| |
| // Add a callback to be called to compare the elements when needed (contains, |
| // get_id, ...) |
| void set_compare_callback(ResultCallback2<bool, T const &, T const &>* cb); |
| |
| // Clear the array, calling the clear callback function if any. |
| // All the owned Callbacks are also deleted. |
| // If you don't want the Callbacks to be deleted, before calling clear, set |
| // the callback to NULL. |
| virtual void clear(); |
| |
| // Delete objects pointed to by data_[i] |
| void delete_data_pointers(); |
| |
| // This method clears the current object, then, does a shallow copy of |
| // its argument, and finally invalidate its argument. |
| // Callbacks are moved to the current object; |
| void move(GenericVector<T>* from); |
| |
| // Read/Write the array to a file. This does _NOT_ read/write the callbacks. |
| // The Callback given must be permanent since they will be called more than |
| // once. The given callback will be deleted at the end. |
| void write(FILE* f, Callback2<FILE*, T const &>* cb); |
| void read(FILE* f, Callback3<FILE*, T*, bool>* cb, bool swap); |
| |
| // Allocates a new array of double the current_size, copies over the |
| // information from data to the new location, deletes data and returns |
| // the pointed to the new larger array. |
| // This function uses memcpy to copy the data, instead of invoking |
| // operator=() for each element like double_the_size() does. |
| static T *double_the_size_memcpy(int current_size, T *data) { |
| T *data_new = new T[current_size * 2]; |
| memcpy(data_new, data, sizeof(T) * current_size); |
| delete[] data; |
| return data_new; |
| } |
| |
| protected: |
| // We are assuming that the object generally placed in thie |
| // vector are small enough that for efficiency it makes sence |
| // to start with a larger initial size. |
| static const int kDefaultVectorSize = 4; |
| int size_used_; |
| int size_reserved_; |
| T* data_; |
| Callback1<T>* clear_cb_; |
| // Mutable because Run method is not const |
| mutable ResultCallback2<bool, T const &, T const &>* compare_cb_; |
| }; |
| |
| namespace tesseract { |
| |
| template <typename T> |
| bool cmp_eq(T const & t1, T const & t2) { |
| return t1 == t2; |
| } |
| |
| } // namespace tesseract |
| |
| // A useful vector that uses operator== to do comparisons. |
| template <typename T> |
| class GenericVectorEqEq : public GenericVector<T> { |
| public: |
| GenericVectorEqEq() { |
| GenericVector<T>::set_compare_callback( |
| NewPermanentCallback(tesseract::cmp_eq<T>)); |
| } |
| GenericVectorEqEq(int size) : GenericVector<T>(size) { |
| GenericVector<T>::set_compare_callback( |
| NewPermanentCallback(tesseract::cmp_eq<T>)); |
| } |
| }; |
| |
| template <typename T> |
| void GenericVector<T>::init(int size) { |
| size_used_ = 0; |
| size_reserved_ = 0; |
| data_ = 0; |
| clear_cb_ = 0; |
| compare_cb_ = 0; |
| reserve(size); |
| } |
| |
| template <typename T> |
| GenericVector<T>::~GenericVector() { |
| clear(); |
| } |
| |
| // Reserve some memory. If the internal array contains elements, they are |
| // copied. |
| template <typename T> |
| void GenericVector<T>::reserve(int size) { |
| if (size_reserved_ > size || size <= 0) |
| return; |
| T* new_array = new T[size]; |
| for (int i = 0; i < size_used_; ++i) |
| new_array[i] = data_[i]; |
| if (data_ != NULL) delete[] data_; |
| data_ = new_array; |
| size_reserved_ = size; |
| } |
| |
| template <typename T> |
| void GenericVector<T>::double_the_size() { |
| if (size_reserved_ == 0) { |
| reserve(kDefaultVectorSize); |
| } |
| else { |
| reserve(2 * size_reserved_); |
| } |
| } |
| |
| |
| |
| // Return the object from an index. |
| template <typename T> |
| T &GenericVector<T>::get(int index) const { |
| ASSERT_HOST(index >= 0 && index < size_used_); |
| return data_[index]; |
| } |
| |
| template <typename T> |
| T &GenericVector<T>::operator[](int index) const { |
| return data_[index]; |
| } |
| |
| // Return the object from an index. |
| template <typename T> |
| void GenericVector<T>::set(T t, int index) { |
| ASSERT_HOST(index >= 0 && index < size_used_); |
| data_[index] = t; |
| } |
| |
| // Shifts the rest of the elements to the right to make |
| // space for the new elements and inserts the given element |
| // at the specified index. |
| template <typename T> |
| void GenericVector<T>::insert(T t, int index) { |
| ASSERT_HOST(index >= 0 && index < size_used_); |
| if (size_reserved_ == size_used_) |
| double_the_size(); |
| for (int i = size_used_; i > index; --i) { |
| data_[i] = data_[i-1]; |
| } |
| data_[index] = t; |
| size_used_++; |
| } |
| |
| // Removes an element at the given index and |
| // shifts the remaining elements to the left. |
| template <typename T> |
| void GenericVector<T>::remove(int index) { |
| ASSERT_HOST(index >= 0 && index < size_used_); |
| for (int i = index; i < size_used_ - 1; ++i) { |
| data_[i] = data_[i+1]; |
| } |
| size_used_--; |
| } |
| |
| // Return true if the index is valindex |
| template <typename T> |
| T GenericVector<T>::contains_index(int index) const { |
| return index >= 0 && index < size_used_; |
| } |
| |
| // Return the index of the T object. |
| template <typename T> |
| int GenericVector<T>::get_index(T object) const { |
| for (int i = 0; i < size_used_; ++i) { |
| ASSERT_HOST(compare_cb_ != NULL); |
| if (compare_cb_->Run(object, data_[i])) |
| return i; |
| } |
| return -1; |
| } |
| |
| // Return true if T is in the array |
| template <typename T> |
| bool GenericVector<T>::contains(T object) const { |
| return get_index(object) != -1; |
| } |
| |
| // Add an element in the array |
| template <typename T> |
| int GenericVector<T>::push_back(T object) { |
| int index = 0; |
| if (size_used_ == size_reserved_) |
| double_the_size(); |
| index = size_used_++; |
| data_[index] = object; |
| return index; |
| } |
| |
| template <typename T> |
| void GenericVector<T>::operator+=(T t) { |
| push_back(t); |
| } |
| |
| template <typename T> |
| GenericVector<T> &GenericVector<T>::operator+=(const GenericVector& other) { |
| for (int i = 0;i < other.size(); ++i) { |
| this->operator+=(other.data_[i]); |
| } |
| return *this; |
| } |
| |
| template <typename T> |
| GenericVector<T> &GenericVector<T>::operator=(const GenericVector& other) { |
| this->clear(); |
| this->operator+=(other); |
| return *this; |
| } |
| |
| // Add a callback to be called to delete the elements when the array took |
| // their ownership. |
| template <typename T> |
| void GenericVector<T>::set_clear_callback(Callback1<T>* cb) { |
| clear_cb_ = cb; |
| } |
| |
| // Add a callback to be called to delete the elements when the array took |
| // their ownership. |
| template <typename T> |
| void GenericVector<T>::set_compare_callback(ResultCallback2<bool, T const &, T const &>* cb) { |
| compare_cb_ = cb; |
| } |
| |
| // Clear the array, calling the callback function if any. |
| template <typename T> |
| void GenericVector<T>::clear() { |
| if (size_reserved_ > 0) { |
| if (clear_cb_ != NULL) |
| for (int i = 0; i < size_used_; ++i) |
| clear_cb_->Run(data_[i]); |
| delete[] data_; |
| size_used_ = 0; |
| size_reserved_ = 0; |
| } |
| if (clear_cb_ != NULL) { |
| delete clear_cb_; |
| clear_cb_ = NULL; |
| } |
| if (compare_cb_ != NULL) { |
| delete compare_cb_; |
| compare_cb_ = NULL; |
| } |
| } |
| |
| template <typename T> |
| void GenericVector<T>::delete_data_pointers() { |
| for (int i = 0; i < size_used_; ++i) |
| if (data_[i]) { |
| delete data_[i]; |
| } |
| } |
| |
| |
| template <typename T> |
| void GenericVector<T>::write(FILE* f, Callback2<FILE*, T const &>* cb) { |
| fwrite(&size_reserved_, sizeof(int), 1, f); |
| fwrite(&size_used_, sizeof(int), 1, f); |
| for (int i = 0; i < size_used_; ++i) { |
| cb->Run(f, data_[i]); |
| } |
| delete cb; |
| } |
| |
| template <typename T> |
| void GenericVector<T>::read(FILE* f, Callback3<FILE*, T*, bool>* cb, bool swap) { |
| uinT32 reserved; |
| fread(&reserved, sizeof(int), 1, f); |
| if (swap) |
| reserved = reverse32(reserved); |
| reserve(reserved); |
| fread(&size_used_, sizeof(int), 1, f); |
| if (swap) |
| size_used_ = reverse32(size_used_); |
| for (int i = 0; i < size_used_; ++i) { |
| cb->Run(f, data_ + i, swap); |
| } |
| delete cb; |
| } |
| |
| // This method clear the current object, then, does a shallow copy of |
| // its argument, and finally invalindate its argument. |
| template <typename T> |
| void GenericVector<T>::move(GenericVector<T>* from) { |
| this->clear(); |
| this->data_ = from->data_; |
| this->size_reserved_ = from->size_reserved_; |
| this->size_used_ = from->size_used_; |
| this->compare_cb_ = from->compare_cb_; |
| this->clear_cb_ = from->clear_cb_; |
| from->data_ = NULL; |
| from->clear_cb_ = NULL; |
| from->compare_cb_ = NULL; |
| from->size_used_ = 0; |
| from->size_reserved_ = 0; |
| } |
| |
| #endif // TESSERACT_CCUTIL_GENERICVECTOR_H_ |