mirror of
https://github.com/tesseract-ocr/tesseract.git
synced 2024-12-18 11:28:51 +08:00
399 lines
11 KiB
C
399 lines
11 KiB
C
|
///////////////////////////////////////////////////////////////////////
|
||
|
// 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_
|