[DEV] start add Array
This commit is contained in:
parent
966f431549
commit
f92f9fb54e
999
etk/Array.hpp
Normal file
999
etk/Array.hpp
Normal file
@ -0,0 +1,999 @@
|
||||
/**
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2011, Edouard DUPIN, all right reserved
|
||||
* @license MPL-2 (see license file)
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <etk/types.hpp>
|
||||
#include <etk/Stream.hpp>
|
||||
#include <etk/Allocator.hpp>
|
||||
|
||||
//#define ETK_ARRAY_DEBUG(...) printf(__VA_ARGS__)
|
||||
#define ETK_ARRAY_DEBUG(...) do {} while (false)
|
||||
|
||||
namespace etk {
|
||||
class Stream;
|
||||
/**
|
||||
* @brief Array class ...
|
||||
*
|
||||
* @param[in] ETK_ARRAY_TYPE class type of the current element.
|
||||
*
|
||||
* m_data
|
||||
* <------------ m_dataSize ------------>
|
||||
* ----------------------------------------
|
||||
* | 0 |
|
||||
* |--------------------------------------|
|
||||
* | 1 |
|
||||
* |--------------------------------------|
|
||||
* | 2 |
|
||||
* |--------------------------------------|
|
||||
* m_size | 3 |
|
||||
* |--------------------------------------|
|
||||
* | x |
|
||||
* |--------------------------------------|
|
||||
* | x |
|
||||
* |--------------------------------------|
|
||||
* | x |
|
||||
* |--------------------------------------|
|
||||
* | x |
|
||||
* |--------------------------------------|
|
||||
* | x |
|
||||
* |--------------------------------------|
|
||||
* | x |
|
||||
* |--------------------------------------|
|
||||
* | x |
|
||||
* |--------------------------------------|
|
||||
* ETK_ARRAY_SIZE | x |
|
||||
* ----------------------------------------
|
||||
*/
|
||||
template<class ETK_ARRAY_TYPE, size_t ETK_ARRAY_SIZE=1> class Array {
|
||||
public:
|
||||
class Iterator {
|
||||
private:
|
||||
size_t m_current; //!< current Id on the Array
|
||||
Array<ETK_ARRAY_TYPE, ETK_ARRAY_SIZE>* m_array; //!< Pointer on the current element of the ArrayBin
|
||||
public:
|
||||
/**
|
||||
* @brief Basic iterator constructor with no link with an etk::Array
|
||||
*/
|
||||
Iterator():
|
||||
m_current(0),
|
||||
m_array(nullptr) {
|
||||
// nothing to do ...
|
||||
}
|
||||
/**
|
||||
* @brief Recopy constructor on a specific etkArray.
|
||||
* @param[in] _obj The Iterator that might be copy
|
||||
*/
|
||||
Iterator(const Iterator & _obj):
|
||||
m_current(_obj.m_current),
|
||||
m_array(_obj.m_array) {
|
||||
// nothing to do ...
|
||||
}
|
||||
/**
|
||||
* @brief Assignation operator.
|
||||
* @param[in] _otherIterator The Iterator that might be copy
|
||||
* @return reference on the current Iterator
|
||||
*/
|
||||
Iterator& operator=(const Iterator & _otherIterator) {
|
||||
m_current = _otherIterator.m_current;
|
||||
m_array = _otherIterator.m_array;
|
||||
return *this;
|
||||
}
|
||||
/**
|
||||
* @brief Basic destructor
|
||||
*/
|
||||
~Iterator() {
|
||||
m_current = 0;
|
||||
m_array = nullptr;
|
||||
}
|
||||
/**
|
||||
* @brief basic boolean cast
|
||||
* @return true if the element is present in the etkArray size
|
||||
*/
|
||||
operator bool () {
|
||||
return (m_current < m_array->size());
|
||||
}
|
||||
/**
|
||||
* @brief != Comparaison operator
|
||||
* @param[in] _obj Object to compare
|
||||
* @return true if the element are different
|
||||
*/
|
||||
bool operator!= (const Iterator& _obj) {
|
||||
if ( m_array != _obj.m_array
|
||||
|| m_current != _obj.m_current) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
/**
|
||||
* @brief == Comparaison operator.
|
||||
* @param[in] _obj Object to compare.
|
||||
* @return true if the element are identical.
|
||||
*/
|
||||
bool operator== (const Iterator& _obj) {
|
||||
if ( m_array == _obj.m_array
|
||||
&& m_current == _obj.m_current) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
/**
|
||||
* @brief Incremental operator
|
||||
* @return Reference on the current iterator increment
|
||||
*/
|
||||
Iterator& operator++ () {
|
||||
if ( m_array != nullptr
|
||||
&& m_current < m_array->size() )
|
||||
{
|
||||
m_current++;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
/**
|
||||
* @brief Decremental operator
|
||||
* @return Reference on the current iterator decrement
|
||||
*/
|
||||
Iterator& operator-- () {
|
||||
if ( m_array != nullptr
|
||||
&& m_current > 0) {
|
||||
m_current--;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
/**
|
||||
* @brief Incremental operator
|
||||
* @return Reference on a new iterator and increment the other one
|
||||
*/
|
||||
Iterator operator++ (int32_t) {
|
||||
Iterator it(*this);
|
||||
++(*this);
|
||||
return it;
|
||||
}
|
||||
/**
|
||||
* @brief Decremental operator
|
||||
* @return Reference on a new iterator and decrement the other one
|
||||
*/
|
||||
Iterator operator-- (int32_t) {
|
||||
Iterator it(*this);
|
||||
--(*this);
|
||||
return it;
|
||||
}
|
||||
Iterator& operator-= (size_t _offset) {
|
||||
m_current -= _offset;
|
||||
return *this;
|
||||
}
|
||||
Iterator operator- (size_t _offset) const {
|
||||
Iterator tmp(*this);
|
||||
tmp -= _offset;
|
||||
return tmp;
|
||||
}
|
||||
Iterator& operator-= (int _offset) {
|
||||
m_current -= _offset;
|
||||
return *this;
|
||||
}
|
||||
Iterator operator- (int _offset) const {
|
||||
Iterator tmp(*this);
|
||||
tmp -= _offset;
|
||||
return tmp;
|
||||
}
|
||||
Iterator& operator-= (int64_t _offset) {
|
||||
m_current -= _offset;
|
||||
return *this;
|
||||
}
|
||||
Iterator operator- (int64_t _offset) const {
|
||||
Iterator tmp(*this);
|
||||
tmp -= _offset;
|
||||
return tmp;
|
||||
}
|
||||
Iterator& operator+= (size_t _offset) {
|
||||
m_current += _offset;
|
||||
return *this;
|
||||
}
|
||||
Iterator operator+ (size_t _offset) const {
|
||||
Iterator tmp(*this);
|
||||
tmp += _offset;
|
||||
return tmp;
|
||||
}
|
||||
Iterator& operator+= (int _offset) {
|
||||
m_current += _offset;
|
||||
return *this;
|
||||
}
|
||||
Iterator operator+ (int _offset) const {
|
||||
Iterator tmp(*this);
|
||||
tmp += _offset;
|
||||
return tmp;
|
||||
}
|
||||
Iterator& operator+= (int64_t _offset) {
|
||||
m_current += _offset;
|
||||
return *this;
|
||||
}
|
||||
Iterator operator+ (int64_t _offset) const {
|
||||
Iterator tmp(*this);
|
||||
tmp += _offset;
|
||||
return tmp;
|
||||
}
|
||||
/**
|
||||
* @brief Get reference on the current Element
|
||||
* @return the reference on the current Element
|
||||
*/
|
||||
ETK_ARRAY_TYPE* operator-> () const {
|
||||
return &m_array->get(m_current);
|
||||
}
|
||||
/**
|
||||
* @brief Get reference on the current Element
|
||||
* @return the reference on the current Element
|
||||
*/
|
||||
ETK_ARRAY_TYPE& operator* () const {
|
||||
return m_array->get(m_current);
|
||||
}
|
||||
private:
|
||||
Iterator(const Array<ETK_ARRAY_TYPE> * _obj, int32_t _pos):
|
||||
m_current(_pos),
|
||||
m_array(const_cast<Array<ETK_ARRAY_TYPE> *>(_obj)) {
|
||||
// nothing to do ...
|
||||
}
|
||||
size_t getCurrent() const {
|
||||
return m_current;
|
||||
}
|
||||
friend class Array;
|
||||
};
|
||||
private:
|
||||
ETK_ARRAY_TYPE m_data[ETK_ARRAY_SIZE]; //!< pointer on the current table of Data (static allocated ==> can not change)
|
||||
size_t m_size = 0; //!< Number of element in the buffer
|
||||
const size_t m_allocated = ETK_ARRAY_SIZE; //!< Current allocated size
|
||||
public:
|
||||
/**
|
||||
* @brief Create an empty Array
|
||||
*/
|
||||
Array() {
|
||||
|
||||
}
|
||||
/**
|
||||
* @brief List initializer (ex: etk::Array<etk::String> plop = {"hello", world"}
|
||||
* @param[in] _element element to add in the Array
|
||||
*/
|
||||
template<typename... ETK_ARRAY_TYPE_2>
|
||||
Array(const ETK_ARRAY_TYPE_2& ... _args) {
|
||||
int32_t nbElement = int32_t(sizeof...(ETK_ARRAY_TYPE_2));
|
||||
if (nbElement >= m_allocated) {
|
||||
throw etk::exception::InvalidArgument("Size too big ...");
|
||||
return;
|
||||
}
|
||||
changeAllocation(int32_t(sizeof...(ETK_ARRAY_TYPE_2)));
|
||||
pushBackN(_args...);
|
||||
}
|
||||
/**
|
||||
* @brief Re-copy constructor (copy all needed data)
|
||||
* @param[in] _obj Array that might be copy
|
||||
*/
|
||||
Array(const etk::Array<ETK_ARRAY_TYPE, ETK_ARRAY_SIZE>& _obj) {
|
||||
reserve(_obj.m_size);
|
||||
for(size_t iii=0; iii<_obj.m_size; iii++) {
|
||||
new ((char*)&m_data[iii]) ETK_ARRAY_TYPE(etk::move(_obj.m_data[iii]));
|
||||
}
|
||||
m_size = _obj.m_size;
|
||||
}
|
||||
/**
|
||||
* @brief Move operator of elements
|
||||
* @param[in] _obj Object to move
|
||||
*/
|
||||
// TODO: This is a little complicated ...
|
||||
Array(etk::Array<ETK_ARRAY_TYPE, ETK_ARRAY_SIZE>&& _obj):
|
||||
m_size(_obj.m_size) {
|
||||
/*
|
||||
_obj.m_data = nullptr;
|
||||
_obj.m_size = 0;
|
||||
_obj.m_allocated = 0;
|
||||
*/
|
||||
throw etk::exception::InvalidArgument("TODO ...");
|
||||
}
|
||||
/**
|
||||
* @brief Destructor of the current class
|
||||
*/
|
||||
~Array() {
|
||||
for(size_t iii=0; iii<m_size; iii++) {
|
||||
m_data[iii].~ETK_ARRAY_TYPE();
|
||||
#ifdef DEBUG
|
||||
// we place bad data to permit to detect stipid thing that is done in C++ code when developement is in progress.
|
||||
// Only in debug this is really slow ... and for the real allocation of memory
|
||||
for (size_t kkk=iii*sizeof(ETK_ARRAY_TYPE); kkk<sizeof(ETK_ARRAY_TYPE)*(iii+1); ++kkk) {
|
||||
((char*)m_data)[kkk] = 0xA5;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
m_size = 0;
|
||||
}
|
||||
/**
|
||||
* @brief Swap the data of 2 Arrays
|
||||
* @param[in] _obj second Array to swap data.
|
||||
*/
|
||||
void swap(etk::Array<ETK_ARRAY_TYPE, ETK_ARRAY_SIZE>& _obj) {
|
||||
// avoid Swap of itself
|
||||
if(this != &_obj) {
|
||||
if (_obj.size() < size()) {
|
||||
_obj.swap(*this);
|
||||
return;
|
||||
}
|
||||
for (size_t iii=0; iii<size(); ++iii) {
|
||||
etk::swap(m_data[iii], _obj.m_data[iii]);
|
||||
}
|
||||
for (size_t iii=size(); iii<_obj.size(); ++iii) {
|
||||
// Construc new local object
|
||||
new ((char*)&m_data[iii]) ETK_ARRAY_TYPE(etk::move(_obj.m_data[iii]));
|
||||
// destruct remote object
|
||||
_obj.m_data[iii].~ETK_ARRAY_TYPE();
|
||||
}
|
||||
etk::swap(m_size, _obj.m_size);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @brief Move operator
|
||||
* @param[in] _obj Array that might be copy
|
||||
* @return reference on the current re-copy Array
|
||||
*/
|
||||
Array& operator=(etk::Array<ETK_ARRAY_TYPE, ETK_ARRAY_SIZE>&& _obj) {
|
||||
if(this != &_obj) {
|
||||
etk::swap(this, _obj);
|
||||
}
|
||||
// Return the current pointer
|
||||
return *this;
|
||||
}
|
||||
/**
|
||||
* @brief Re-copy operator
|
||||
* @param[in] _obj Array that might be copy
|
||||
* @return reference on the current re-copy Array
|
||||
*/
|
||||
Array& operator=(const etk::Array<ETK_ARRAY_TYPE, ETK_ARRAY_SIZE>& _obj) {
|
||||
// remove all previous elements
|
||||
clear();
|
||||
// Force a specicfic size
|
||||
reserve(_obj.m_size);
|
||||
for(size_t iii=0; iii<_obj.m_size; iii++) {
|
||||
new ((char*)&m_data[iii]) ETK_ARRAY_TYPE(etk::move(_obj.m_data[iii]));
|
||||
}
|
||||
m_size = _obj.m_size;
|
||||
// Return the current pointer
|
||||
return *this;
|
||||
}
|
||||
/**
|
||||
* @brief Add at the Last position of the Array
|
||||
* @param[in] _obj Element to add at the end of Array
|
||||
*/
|
||||
Array& operator+= (const etk::Array<ETK_ARRAY_TYPE>& _obj) {
|
||||
reserve(m_size + _obj.size());
|
||||
for(size_t iii=0; iii<_obj.size(); iii++) {
|
||||
// copy operator ...
|
||||
new ((char*)&m_data[m_size+iii]) ETK_ARRAY_TYPE(etk::move(_obj.m_data[iii]));
|
||||
}
|
||||
m_size += _obj.size();
|
||||
// Return the current pointer
|
||||
return *this;
|
||||
}
|
||||
/**
|
||||
* @brief Get the number of element in the Array
|
||||
* @return The number requested
|
||||
*/
|
||||
size_t size() const {
|
||||
return m_size;
|
||||
}
|
||||
/**
|
||||
* @brief Check if the container have some element
|
||||
* @return true The container is empty
|
||||
* @return famse The container have some element
|
||||
*/
|
||||
bool empty() const {
|
||||
return m_size == 0;
|
||||
}
|
||||
/**
|
||||
* @brief Get the Allocated size in the Array
|
||||
* @return The size of allocation
|
||||
*/
|
||||
size_t allocatedSize() const {
|
||||
return m_allocated;
|
||||
}
|
||||
/**
|
||||
* @brief Get a current element in the Array
|
||||
* @param[in] _pos Desired position read
|
||||
* @return Reference on the Element
|
||||
*/
|
||||
ETK_ARRAY_TYPE& get(const size_t _pos) {
|
||||
return m_data[_pos];
|
||||
}
|
||||
/**
|
||||
* @brief Get an copy Element an a special position
|
||||
* @param[in] _pos Position in the Array that might be get [0..Size()]
|
||||
* @return An reference on the copy of selected element
|
||||
*/
|
||||
ETK_ARRAY_TYPE& operator[] (const size_t _pos) {
|
||||
return m_data[_pos];
|
||||
}
|
||||
/**
|
||||
* @brief Get an Element an a special position
|
||||
* @param[in] _pos Position in the Array that might be get [0..Size()]
|
||||
* @return An reference on the selected element
|
||||
*/
|
||||
const ETK_ARRAY_TYPE& operator[] (const size_t _pos) const {
|
||||
return m_data[_pos];
|
||||
}
|
||||
/**
|
||||
* @brief Get the last element of the Array
|
||||
* @return An reference on the element
|
||||
*/
|
||||
ETK_ARRAY_TYPE& back() {
|
||||
return m_data[m_size-1];
|
||||
}
|
||||
const ETK_ARRAY_TYPE& back() const {
|
||||
return m_data[m_size-1];
|
||||
}
|
||||
/**
|
||||
* @brief Get the first element of the Array
|
||||
* @return An reference on the element
|
||||
*/
|
||||
ETK_ARRAY_TYPE& front() {
|
||||
return m_data[0];
|
||||
}
|
||||
const ETK_ARRAY_TYPE& front() const {
|
||||
return m_data[0];
|
||||
}
|
||||
/**
|
||||
* @brief Add at the First position of the Array
|
||||
* @param[in] _item Element to add at the end of Array
|
||||
*/
|
||||
void pushFront(const ETK_ARRAY_TYPE& _item) {
|
||||
insert(0, &_item, 1);
|
||||
}
|
||||
/**
|
||||
* @brief Add at the Last position of the Array
|
||||
* @param[in] _item Pointer on a list of Element to add at the start of Array
|
||||
* @param[in] _nbElement Number of element to add.
|
||||
*/
|
||||
void pushFront(const ETK_ARRAY_TYPE * _item, size_t _nbElement) {
|
||||
insert(0, _item, _nbElement);
|
||||
}
|
||||
/**
|
||||
* @brief Add at the Last position of the Array (move push)
|
||||
* @param[in] _item Element to add at the end of Array
|
||||
*/
|
||||
void pushBack(ETK_ARRAY_TYPE&& _item) {
|
||||
reserve(m_size+1);
|
||||
new ((char*)&m_data[m_size]) ETK_ARRAY_TYPE(etk::move(_item));
|
||||
m_size += 1;
|
||||
}
|
||||
/**
|
||||
* @brief Add at the Last position of the Array
|
||||
* @param[in] _item Element to add at the end of Array
|
||||
*/
|
||||
void pushBack(const ETK_ARRAY_TYPE& _item) {
|
||||
reserve(m_size+1);
|
||||
new ((char*)&m_data[m_size]) ETK_ARRAY_TYPE(etk::move(_item));
|
||||
m_size += 1;
|
||||
}
|
||||
/**
|
||||
* @brief Add at the Last position of the Array
|
||||
* @param[in] _item Pointer on a list of Element to add at the end of Array
|
||||
* @param[in] _nbElement Number of element to add.
|
||||
*/
|
||||
void pushBack(const ETK_ARRAY_TYPE * _item, size_t _nbElement) {
|
||||
if (_item == nullptr) {
|
||||
return;
|
||||
}
|
||||
reserve(m_size+_nbElement);
|
||||
if (m_size > m_allocated) {
|
||||
//TK_ERROR("Resize does not work correctly ... not added item");
|
||||
return;
|
||||
}
|
||||
for (size_t iii=0; iii<_nbElement; iii++) {
|
||||
new ((char*)&m_data[m_size+iii]) ETK_ARRAY_TYPE(_item[iii]);
|
||||
m_size += 1;
|
||||
}
|
||||
}
|
||||
private:
|
||||
void pushBackN(const ETK_ARRAY_TYPE& _value) {
|
||||
pushBack(_value);
|
||||
}
|
||||
template<typename... ETK_ARRAY_TYPE_2>
|
||||
void pushBackN(const ETK_ARRAY_TYPE& _value, const ETK_ARRAY_TYPE_2& ... _args) {
|
||||
pushBack(_value);
|
||||
pushBackN(_args...);
|
||||
}
|
||||
public:
|
||||
/**
|
||||
* @brief Remove the first element of the Array
|
||||
*/
|
||||
void popFront() {
|
||||
if(m_size>0) {
|
||||
eraseLen(0, 1);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @brief Remove the last element of the Array
|
||||
*/
|
||||
void popBack() {
|
||||
if(m_size>0) {
|
||||
resizeDown(m_size-1);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @brief Remove all element in the current Array
|
||||
*/
|
||||
void clear() {
|
||||
if(m_size>0) {
|
||||
resizeDown(0);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @brief Insert N element in the Array.
|
||||
* @param[in] _pos Position to add the elements.
|
||||
* @param[in] _item Pointer on a table of the elements to add.
|
||||
* @param[in] _nbElement Number of element to add in the Array
|
||||
*/
|
||||
void insert(size_t _pos, const ETK_ARRAY_TYPE * _item, size_t _nbElement) {
|
||||
if (_pos > m_size) {
|
||||
//TK_WARNING(" can not insert Element at this position : " << _pos << " > " << m_size << " add it at the end ... ");
|
||||
pushBack(_item, _nbElement);
|
||||
return;
|
||||
}
|
||||
// move current data (after the position)
|
||||
size_t sizeToMove = (m_size - _pos);
|
||||
// Request resize of the current buffer
|
||||
reserve(m_size+_nbElement);
|
||||
if (sizeToMove > 0) {
|
||||
for (size_t iii=1; iii<=sizeToMove; iii++) {
|
||||
// placement allocate of the element
|
||||
new ((char*)&m_data[m_size+_nbElement-iii]) ETK_ARRAY_TYPE(etk::move(m_data[m_size-iii]));
|
||||
// Remove previous element ==> simplify code.
|
||||
m_data[m_size-iii].~ETK_ARRAY_TYPE();
|
||||
#ifdef DEBUG
|
||||
// we place bad data to permit to detect stipid thing that is done in C++ code when developement is in progress.
|
||||
// Only in debug this is really slow ... and for the real allocation of memory
|
||||
for (size_t kkk=(m_size-iii)*sizeof(ETK_ARRAY_TYPE); kkk<sizeof(ETK_ARRAY_TYPE)*((m_size-iii)+1); ++kkk) {
|
||||
((char*)m_data)[kkk] = 0xA5;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
}
|
||||
// affectation of all input element
|
||||
for (size_t iii=0; iii<_nbElement; iii++) {
|
||||
new ((char*)&m_data[_pos-iii]) ETK_ARRAY_TYPE(etk::move(_item[iii]));
|
||||
}
|
||||
m_size += _nbElement;
|
||||
}
|
||||
/**
|
||||
* @brief Insert one element in the Array at a specific position
|
||||
* @param[in] _pos Position to add the elements.
|
||||
* @param[in] _item Element to add.
|
||||
*/
|
||||
void insert(size_t _pos, const ETK_ARRAY_TYPE& _item) {
|
||||
insert(_pos, &_item, 1);
|
||||
}
|
||||
/**
|
||||
* @brief Insert one element in the Array at a specific position
|
||||
* @param[in] _pos Position to add the elements.
|
||||
* @param[in] _item Element to add.
|
||||
*/
|
||||
void insert(const Iterator& _pos, const ETK_ARRAY_TYPE& _item) {
|
||||
insert(_pos.getCurrent(), _item);
|
||||
}
|
||||
/**
|
||||
* @brief Remove N element
|
||||
* @param[in] _pos Position to remove the data
|
||||
* @param[in] _nbElement number of element to remove
|
||||
*/
|
||||
void eraseLen(size_t _pos, size_t _nbElement) {
|
||||
ETK_ARRAY_DEBUG("Erase len %zu %zu\n", _pos, _nbElement);
|
||||
if (_pos > m_size) {
|
||||
//TK_ERROR(" can not Erase Len Element at this position : " << _pos << " > " << m_size);
|
||||
return;
|
||||
}
|
||||
if (_pos + _nbElement > m_size) {
|
||||
_nbElement = m_size - _pos;
|
||||
}
|
||||
ETK_ARRAY_DEBUG("Erase len %zu %zu\n", _pos, _nbElement);
|
||||
size_t idElement = m_size;
|
||||
// move current data
|
||||
size_t sizeToMove = (idElement - (_pos+_nbElement));
|
||||
if ( 0 < sizeToMove) {
|
||||
for (size_t iii=0; iii<sizeToMove; iii++) {
|
||||
etk::swap(m_data[_pos+iii], m_data[_pos+_nbElement+iii]);
|
||||
}
|
||||
}
|
||||
// Request resize of the current buffer
|
||||
resizeDown(m_size-_nbElement);
|
||||
}
|
||||
/**
|
||||
* @brief Remove one element
|
||||
* @param[in] _pos Position to remove the data
|
||||
*/
|
||||
inline void erase(size_t _pos) {
|
||||
eraseLen(_pos, 1);
|
||||
}
|
||||
/**
|
||||
* @brief Remove one element
|
||||
* @param[in] _it Iterator on the element to remove
|
||||
* @return An iterator on the new element at this position.
|
||||
*/
|
||||
Iterator erase(const Iterator& _it) {
|
||||
ETK_ARRAY_DEBUG("Erase IT \n");
|
||||
eraseLen(_it.getCurrent(), 1);
|
||||
return position(_it.getCurrent());
|
||||
}
|
||||
/**
|
||||
* @brief Remove one element
|
||||
* @param[in] _pos Position to remove the data
|
||||
*/
|
||||
inline void remove(size_t _pos) {
|
||||
eraseLen(_pos, 1);
|
||||
}
|
||||
/**
|
||||
* @brief Remove N elements
|
||||
* @param[in] _pos Position to remove the data
|
||||
* @param[in] _posEnd Last position number
|
||||
*/
|
||||
void erase(size_t _pos, size_t _posEnd) {
|
||||
if (_pos > m_size) {
|
||||
//TK_ERROR(" can not Erase Element at this position : " << _pos << " > " << m_size);
|
||||
return;
|
||||
}
|
||||
if (_posEnd > m_size) {
|
||||
_posEnd = m_size;
|
||||
}
|
||||
size_t nbElement = m_size - _pos;
|
||||
size_t tmpSize = m_size;
|
||||
// move current data (to the end) ==> auto removed by the resize()
|
||||
size_t sizeToMove = (tmpSize - (_pos+nbElement));
|
||||
if ( 0 < sizeToMove) {
|
||||
for (size_t iii=0; iii<sizeToMove; iii++) {
|
||||
etk::swap(m_data[_pos+iii], m_data[_pos+nbElement+iii]);
|
||||
}
|
||||
}
|
||||
// Request resize of the current buffer
|
||||
resizeDown(m_size-nbElement);
|
||||
}
|
||||
void erase(const Iterator& _pos, const Iterator& _posEnd) {
|
||||
erase(_pos.getCurrent(), _posEnd.getCurrent());
|
||||
}
|
||||
/**
|
||||
* @brief Get the pointer on the data
|
||||
* @return the type pointer on data
|
||||
*/
|
||||
ETK_ARRAY_TYPE* dataPointer() {
|
||||
return &m_data[0];
|
||||
}
|
||||
/**
|
||||
* @brief Get an iterator an an specific position
|
||||
* @param[in] _pos Requested position of the iterator in the Array
|
||||
* @return The Iterator
|
||||
*/
|
||||
Iterator position(size_t _pos) {
|
||||
return Iterator(this, _pos);
|
||||
}
|
||||
const Iterator position(size_t _pos) const {
|
||||
return Iterator(this, _pos);
|
||||
}
|
||||
/**
|
||||
* @brief Get an Iterator on the start position of the Array
|
||||
* @return The Iterator
|
||||
*/
|
||||
Iterator begin() {
|
||||
return position(0);
|
||||
}
|
||||
const Iterator begin() const {
|
||||
return position(0);
|
||||
}
|
||||
/**
|
||||
* @brief Get an Iterator on the end position of the Array
|
||||
* @return The Iterator
|
||||
*/
|
||||
Iterator end() {
|
||||
return position(size());
|
||||
}
|
||||
const Iterator end() const {
|
||||
return position(size());
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Resize the Array with a basic element
|
||||
* @param[in] _newSize New size of the Array
|
||||
*/
|
||||
void resize(size_t _newSize, const ETK_ARRAY_TYPE& _basicElement) {
|
||||
// Reallocate memory
|
||||
if (_newSize > m_size) {
|
||||
if (_newSize > m_allocated) {
|
||||
changeAllocation(_newSize);
|
||||
}
|
||||
for (size_t iii=m_size; iii<_newSize; ++iii) {
|
||||
new ((char*)&m_data[iii]) ETK_ARRAY_TYPE(_basicElement);
|
||||
}
|
||||
m_size = _newSize;
|
||||
return;
|
||||
} else if (_newSize == m_size) {
|
||||
return;
|
||||
}
|
||||
for (size_t iii=m_size; iii<_newSize; ++iii) {
|
||||
m_data[iii].~ETK_ARRAY_TYPE();
|
||||
#ifdef DEBUG
|
||||
// we place bad data to permit to detect stipid thing that is done in C++ code when developement is in progress.
|
||||
// Only in debug this is really slow ... and for the real allocation of memory
|
||||
for (size_t kkk=iii*sizeof(ETK_ARRAY_TYPE); kkk<sizeof(ETK_ARRAY_TYPE)*(iii+1); ++kkk) {
|
||||
((char*)m_data)[kkk] = 0xA5;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
m_size = _newSize;
|
||||
}
|
||||
/**
|
||||
* @brief Change the current size of the Array
|
||||
* @param[in] _newSize New requested size of element in the Array
|
||||
*/
|
||||
void resize(size_t _newSize) {
|
||||
ETK_ARRAY_DEBUG("Resize %zu => %zu\n", m_size, _newSize);
|
||||
// Reallocate memory
|
||||
if (_newSize > m_size) {
|
||||
if (_newSize > m_allocated) {
|
||||
changeAllocation(_newSize);
|
||||
}
|
||||
for (size_t iii=m_size; iii<_newSize; ++iii) {
|
||||
new ((char*)&m_data[iii]) ETK_ARRAY_TYPE();
|
||||
}
|
||||
} else if (_newSize == m_size) {
|
||||
return;
|
||||
}
|
||||
ETK_ARRAY_DEBUG("Reduce %zu => %zu\n", m_size, _newSize);
|
||||
for (size_t iii=_newSize; iii<m_size; ++iii) {
|
||||
m_data[iii].~ETK_ARRAY_TYPE();
|
||||
#ifdef DEBUG
|
||||
// we place bad data to permit to detect stipid thing that is done in C++ code when developement is in progress.
|
||||
// Only in debug this is really slow ... and for the real allocation of memory
|
||||
for (size_t kkk=iii*sizeof(ETK_ARRAY_TYPE); kkk<sizeof(ETK_ARRAY_TYPE)*(iii+1); ++kkk) {
|
||||
((char*)m_data)[kkk] = 0xA5;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
m_size = _newSize;
|
||||
}
|
||||
private:
|
||||
void resizeDown(size_t _newSize) {
|
||||
ETK_ARRAY_DEBUG("Resize %zu => %zu\n", m_size, _newSize);
|
||||
// Reallocate memory
|
||||
if (_newSize > m_allocated) {
|
||||
ETK_ARRAY_DEBUG("Resize Down %zu => %zu\n", m_size, _newSize);
|
||||
return;
|
||||
} else if (_newSize == m_allocated) {
|
||||
return;
|
||||
}
|
||||
ETK_ARRAY_DEBUG("Reduce %zu => %zu\n", m_size, _newSize);
|
||||
for (size_t iii=_newSize; iii<m_size; ++iii) {
|
||||
m_data[iii].~ETK_ARRAY_TYPE();
|
||||
#ifdef DEBUG
|
||||
// we place bad data to permit to detect stipid thing that is done in C++ code when developement is in progress.
|
||||
// Only in debug this is really slow ... and for the real allocation of memory
|
||||
for (size_t kkk=iii*sizeof(ETK_ARRAY_TYPE); kkk<sizeof(ETK_ARRAY_TYPE)*(iii+1); ++kkk) {
|
||||
((char*)m_data)[kkk] = 0xA5;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
m_size = _newSize;
|
||||
}
|
||||
public:
|
||||
/**
|
||||
* @brief Force the container to have a minimum size in memory allocation
|
||||
* @param[in] _size Size in byte that is requested.
|
||||
*/
|
||||
void reserve(size_t _size) {
|
||||
if (_size <= m_allocated) {
|
||||
return;
|
||||
}
|
||||
changeAllocation(_size);
|
||||
}
|
||||
private:
|
||||
/**
|
||||
* @brief Change the current allocation to the correct one (depend on the current size)
|
||||
* @param[in] _newSize Minimum number of element needed
|
||||
*/
|
||||
void changeAllocation(size_t _newSize) {
|
||||
size_t requestSize = m_allocated;
|
||||
// set the size with the correct chose type:
|
||||
if (_newSize == requestSize) {
|
||||
return;
|
||||
} else if (_newSize < requestSize) {
|
||||
// we did not remove data ???
|
||||
} else {
|
||||
while(_newSize > requestSize) {
|
||||
if (0 == requestSize) {
|
||||
requestSize = 1;
|
||||
} else {
|
||||
requestSize = requestSize * 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
// No reallocation needed :
|
||||
if (requestSize <= m_allocated) {
|
||||
return;
|
||||
}
|
||||
//TK_INFO("Change Array allocation : " << m_allocated << "==>" << requestSize);
|
||||
// check if something is allocated :
|
||||
if (m_data == nullptr) {
|
||||
// no data allocated ==> request an allocation (might be the first)
|
||||
m_data = (ETK_ARRAY_TYPE*)ETK_MALLOC(char, sizeof(ETK_ARRAY_TYPE)*requestSize);
|
||||
if (m_data == nullptr) {
|
||||
//TK_CRITICAL("Array : Error in data allocation request allocation:" << requestSize << "*" << (int32_t)(sizeof(ETK_ARRAY_TYPE)) << "bytes" );
|
||||
m_allocated = 0;
|
||||
return;
|
||||
}
|
||||
#ifdef DEBUG
|
||||
// we place bad data to permit to detect stipid thing that is done in C++ code when developement is in progress.
|
||||
// Only in debug this is really slow ... and for the real allocation of memory
|
||||
for (size_t kkk=0; kkk<sizeof(ETK_ARRAY_TYPE)*requestSize; ++kkk) {
|
||||
((char*)m_data)[kkk] = 0x5A;
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
// allocate a new pool of data:
|
||||
ETK_ARRAY_TYPE* dataTmp = (ETK_ARRAY_TYPE*)ETK_MALLOC(char, sizeof(ETK_ARRAY_TYPE)*requestSize);;
|
||||
if (dataTmp == nullptr) {
|
||||
//TK_CRITICAL("Array : Error in data allocation request allocation:" << requestSize << "*" << (int32_t)(sizeof(ETK_ARRAY_TYPE)) << "bytes" );
|
||||
return;
|
||||
}
|
||||
ETK_MEM_FLIP_ID(dataTmp, m_data);
|
||||
#ifdef DEBUG
|
||||
// we place bad data to permit to detect stipid thing that is done in C++ code when developement is in progress.
|
||||
// Only in debug this is really slow ... and for the real allocation of memory
|
||||
for (size_t kkk=0; kkk<sizeof(ETK_ARRAY_TYPE)*requestSize; ++kkk) {
|
||||
((char*)dataTmp)[kkk] = 0x5A;
|
||||
}
|
||||
#endif
|
||||
// copy data in the new pool
|
||||
size_t nbElements = etk::min(requestSize, m_allocated);
|
||||
for(size_t iii=0; iii<nbElements; iii++) {
|
||||
// Move in the new element
|
||||
new ((char*)&dataTmp[iii]) ETK_ARRAY_TYPE(etk::move(m_data[iii]));
|
||||
// Remove the old one.
|
||||
m_data[iii].~ETK_ARRAY_TYPE();
|
||||
#ifdef DEBUG
|
||||
// we place bad data to permit to detect stipid thing that is done in C++ code when developement is in progress.
|
||||
// Only in debug this is really slow ... and for the real allocation of memory
|
||||
for (size_t kkk=iii*sizeof(ETK_ARRAY_TYPE); kkk<sizeof(ETK_ARRAY_TYPE)*(iii+1); ++kkk) {
|
||||
((char*)m_data)[kkk] = 0xA5;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
// switch pointer:
|
||||
ETK_ARRAY_TYPE* dataTmp2 = m_data;
|
||||
m_data = dataTmp;
|
||||
// remove old pool
|
||||
if (dataTmp2 != nullptr) {
|
||||
ETK_FREE(char, dataTmp2);
|
||||
}
|
||||
}
|
||||
// set the new allocation size
|
||||
m_allocated = requestSize;
|
||||
}
|
||||
public :
|
||||
/*****************************************************
|
||||
* == operator
|
||||
*****************************************************/
|
||||
bool operator== (const Array<ETK_ARRAY_TYPE, ETK_ARRAY_SIZE>& _obj) const {
|
||||
// check if it was the same pointer
|
||||
if( this == &_obj ) {
|
||||
return true;
|
||||
}
|
||||
// first step : check the size ...
|
||||
if (m_size != _obj.m_size) {
|
||||
return false;
|
||||
}
|
||||
if( m_data == nullptr
|
||||
|| _obj.m_data == nullptr) {
|
||||
return false;
|
||||
}
|
||||
for (size_t iii=0; iii<m_size; iii++) {
|
||||
if (m_data[iii]!=_obj.m_data[iii]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
/*****************************************************
|
||||
* != operator
|
||||
*****************************************************/
|
||||
bool operator!= (const Array<ETK_ARRAY_TYPE, ETK_ARRAY_SIZE>& _obj) const {
|
||||
// check if it was the same pointer
|
||||
if( this == &_obj ) {
|
||||
return false;
|
||||
}
|
||||
// first step : check the size ...
|
||||
if (m_size != _obj.m_size) {
|
||||
return true;
|
||||
}
|
||||
if( m_data == nullptr
|
||||
|| _obj.m_data == nullptr) {
|
||||
return false;
|
||||
}
|
||||
for (size_t iii=0; iii<m_size; iii++) {
|
||||
if (m_data[iii]!=_obj.m_data[iii]) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
/*****************************************************
|
||||
* >= operator
|
||||
*****************************************************/
|
||||
bool operator>= (const Array<ETK_ARRAY_TYPE, ETK_ARRAY_SIZE>& _obj) const {
|
||||
// TODO : Later
|
||||
return false;
|
||||
}
|
||||
/*****************************************************
|
||||
* > operator
|
||||
*****************************************************/
|
||||
bool operator> (const Array<ETK_ARRAY_TYPE, ETK_ARRAY_SIZE>& _obj) const {
|
||||
// TODO : Later
|
||||
return false;
|
||||
}
|
||||
/*****************************************************
|
||||
* <= operator
|
||||
*****************************************************/
|
||||
bool operator<= (const Array<ETK_ARRAY_TYPE, ETK_ARRAY_SIZE>& _obj) const {
|
||||
// TODO : Later
|
||||
return false;
|
||||
}
|
||||
/*****************************************************
|
||||
* > operator
|
||||
*****************************************************/
|
||||
bool operator< (const Array<ETK_ARRAY_TYPE, ETK_ARRAY_SIZE>& _obj) const {
|
||||
// TODO : Later
|
||||
return false;
|
||||
}
|
||||
void sort(size_t _start, size_t _stop, bool (*_comparator)(const ETK_ARRAY_TYPE&, const ETK_ARRAY_TYPE&)) {
|
||||
if (_stop > m_size) {
|
||||
_stop = m_size;
|
||||
}
|
||||
if (_start > m_size) {
|
||||
_start = m_size;
|
||||
}
|
||||
if (_start > _stop) {
|
||||
size_t start = _start;
|
||||
_start = _stop;
|
||||
_stop = start;
|
||||
}
|
||||
for (size_t iii=_start; iii<_stop; ++iii) {
|
||||
bool swapped = false;
|
||||
for (size_t jjj=_start; jjj<_stop - (iii+1); ++jjj) {
|
||||
if (_comparator(m_data[jjj], m_data[jjj+1]) == false) {
|
||||
etk::swap(m_data[jjj], m_data[jjj+1]);
|
||||
swapped = true;
|
||||
}
|
||||
}
|
||||
if (swapped == false) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
//! @not_in_doc
|
||||
template<typename ETK_ARRAY_TYPE_1, typename ETK_ARRAY_TYPE_2, size_t ETK_ARRAY_SIZE>
|
||||
bool isIn(const ETK_ARRAY_TYPE_1& _val, const etk::Array<ETK_ARRAY_TYPE_2, ETK_ARRAY_SIZE>& _list) {
|
||||
for (size_t iii=0; iii<_list.size(); ++iii) {
|
||||
if (_list[iii] == _val) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
class Stream;
|
||||
//! @not_in_doc
|
||||
template<class ETK_ARRAY_TYPE, size_t ETK_ARRAY_SIZE>
|
||||
etk::Stream& operator <<(etk::Stream& _os, const etk::Array<ETK_ARRAY_TYPE, ETK_ARRAY_SIZE>& _obj) {
|
||||
_os << "{";
|
||||
for (size_t iii=0; iii< _obj.size(); iii++) {
|
||||
if (iii>0) {
|
||||
_os << ";";
|
||||
}
|
||||
_os << _obj[iii];
|
||||
}
|
||||
_os << "}";
|
||||
return _os;
|
||||
}
|
||||
}
|
@ -9,7 +9,6 @@
|
||||
|
||||
|
||||
namespace etk {
|
||||
//class String;
|
||||
/**
|
||||
* @brief Global exception handle
|
||||
*/
|
||||
|
@ -47,6 +47,7 @@ def configure(target, my_module):
|
||||
'etk/String.hpp',
|
||||
'etk/UString.hpp',
|
||||
'etk/utf8.hpp',
|
||||
'etk/Array.hpp',
|
||||
'etk/Vector.hpp',
|
||||
'etk/Stream.hpp',
|
||||
'etk/Pair.hpp',
|
||||
|
@ -35,6 +35,7 @@ def configure(target, my_module):
|
||||
'test/testMatrix3x3.cpp',
|
||||
'test/testRegExp.cpp',
|
||||
'test/testTransform.cpp',
|
||||
'test/testArray.cpp',
|
||||
'test/testVector.cpp',
|
||||
'test/testVector3_f.cpp',
|
||||
'test/testArchive.cpp',
|
||||
|
288
test/testArray.cpp
Normal file
288
test/testArray.cpp
Normal file
@ -0,0 +1,288 @@
|
||||
/**
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2011, Edouard DUPIN, all right reserved
|
||||
* @license MPL v2.0 (see license file)
|
||||
*/
|
||||
|
||||
|
||||
#include <etk/Pair.hpp>
|
||||
#include <etk/Array.hpp>
|
||||
#include <test-debug/debug.hpp>
|
||||
#include <etest/etest.hpp>
|
||||
|
||||
TEST(TestArray, constructor) {
|
||||
// Test contructor value
|
||||
etk::Array<float, 20> test;
|
||||
EXPECT_EQ(test.size(), 0);
|
||||
}
|
||||
|
||||
TEST(TestArray, constructor_2) {
|
||||
// Test contructor value
|
||||
etk::Array<float, 20> test(3.9f, 33.0f,55.8f);
|
||||
EXPECT_EQ(test.size(), 3);
|
||||
EXPECT_EQ(test[0], 3.9f);
|
||||
EXPECT_EQ(test[1], 33.0f);
|
||||
EXPECT_EQ(test[2], 55.8f);
|
||||
}
|
||||
|
||||
TEST(TestArray, resize) {
|
||||
// Test contructor value
|
||||
etk::Array<float, 20> test;
|
||||
test.resize(3);
|
||||
EXPECT_EQ(test.size(), 3);
|
||||
}
|
||||
TEST(TestArray, empty) {
|
||||
// Test contructor value
|
||||
etk::Array<float, 20> test;
|
||||
EXPECT_EQ(test.empty(), true);
|
||||
test.pushBack(2);
|
||||
EXPECT_EQ(test.empty(), false);
|
||||
}
|
||||
|
||||
TEST(TestArray, pushBack) {
|
||||
// Test contructor value
|
||||
etk::Array<float, 20> test;
|
||||
EXPECT_EQ(test.size(), 0);
|
||||
test.pushBack(2);
|
||||
EXPECT_EQ(test.size(), 1);
|
||||
EXPECT_EQ(test[0], 2);
|
||||
test.pushBack(4);
|
||||
EXPECT_EQ(test.size(), 2);
|
||||
EXPECT_EQ(test[0], 2);
|
||||
EXPECT_EQ(test[1], 4);
|
||||
test.pushBack(8);
|
||||
EXPECT_EQ(test.size(), 3);
|
||||
EXPECT_EQ(test[0], 2);
|
||||
EXPECT_EQ(test[1], 4);
|
||||
EXPECT_EQ(test[2], 8);
|
||||
test.popBack();
|
||||
EXPECT_EQ(test.size(), 2);
|
||||
EXPECT_EQ(test[0], 2);
|
||||
EXPECT_EQ(test[1], 4);
|
||||
}
|
||||
|
||||
TEST(TestArray, pushFront) {
|
||||
// Test contructor value
|
||||
etk::Array<float, 20> test;
|
||||
EXPECT_EQ(test.size(), 0);
|
||||
test.pushBack(2);
|
||||
EXPECT_EQ(test.size(), 1);
|
||||
EXPECT_EQ(test[0], 2);
|
||||
test.pushBack(4);
|
||||
EXPECT_EQ(test.size(), 2);
|
||||
EXPECT_EQ(test[0], 2);
|
||||
EXPECT_EQ(test[1], 4);
|
||||
test.pushFront(8);
|
||||
EXPECT_EQ(test.size(), 3);
|
||||
EXPECT_EQ(test[0], 8);
|
||||
EXPECT_EQ(test[1], 2);
|
||||
EXPECT_EQ(test[2], 4);
|
||||
test.pushFront(55);
|
||||
EXPECT_EQ(test.size(), 4);
|
||||
EXPECT_EQ(test[0], 55);
|
||||
EXPECT_EQ(test[1], 8);
|
||||
EXPECT_EQ(test[2], 2);
|
||||
EXPECT_EQ(test[3], 4);
|
||||
}
|
||||
|
||||
TEST(TestArray, insert) {
|
||||
// Test contructor value
|
||||
etk::Array<float, 20> test;
|
||||
EXPECT_EQ(test.size(), 0);
|
||||
test.pushBack(2);
|
||||
EXPECT_EQ(test.size(), 1);
|
||||
EXPECT_EQ(test[0], 2);
|
||||
test.pushBack(4);
|
||||
EXPECT_EQ(test.size(), 2);
|
||||
EXPECT_EQ(test[0], 2);
|
||||
EXPECT_EQ(test[1], 4);
|
||||
test.pushFront(8);
|
||||
EXPECT_EQ(test.size(), 3);
|
||||
EXPECT_EQ(test[0], 8);
|
||||
EXPECT_EQ(test[1], 2);
|
||||
EXPECT_EQ(test[2], 4);
|
||||
test.pushFront(55);
|
||||
EXPECT_EQ(test.size(), 4);
|
||||
EXPECT_EQ(test[0], 55);
|
||||
EXPECT_EQ(test[1], 8);
|
||||
EXPECT_EQ(test[2], 2);
|
||||
EXPECT_EQ(test[3], 4);
|
||||
}
|
||||
|
||||
TEST(TestArray, back) {
|
||||
// Test contructor value
|
||||
etk::Array<float, 20> test;
|
||||
EXPECT_EQ(test.size(), 0);
|
||||
test.pushBack(2);
|
||||
test.pushBack(4);
|
||||
test.pushBack(8);
|
||||
EXPECT_EQ(test.size(), 3);
|
||||
EXPECT_EQ(test[0], 2);
|
||||
EXPECT_EQ(test[1], 4);
|
||||
EXPECT_EQ(test[2], 8);
|
||||
EXPECT_EQ(test.back(), 8);
|
||||
}
|
||||
|
||||
TEST(TestArray, popBack) {
|
||||
// Test contructor value
|
||||
etk::Array<float, 20> test;
|
||||
EXPECT_EQ(test.size(), 0);
|
||||
test.pushBack(2);
|
||||
test.pushBack(4);
|
||||
test.pushBack(8);
|
||||
EXPECT_EQ(test.size(), 3);
|
||||
EXPECT_EQ(test[0], 2);
|
||||
EXPECT_EQ(test[1], 4);
|
||||
EXPECT_EQ(test[2], 8);
|
||||
test.popBack();
|
||||
EXPECT_EQ(test.size(), 2);
|
||||
EXPECT_EQ(test[0], 2);
|
||||
EXPECT_EQ(test[1], 4);
|
||||
}
|
||||
|
||||
TEST(TestArray, front) {
|
||||
// Test contructor value
|
||||
etk::Array<float, 20> test;
|
||||
EXPECT_EQ(test.size(), 0);
|
||||
test.pushBack(2);
|
||||
test.pushBack(4);
|
||||
test.pushBack(8);
|
||||
EXPECT_EQ(test.size(), 3);
|
||||
EXPECT_EQ(test[0], 2);
|
||||
EXPECT_EQ(test[1], 4);
|
||||
EXPECT_EQ(test[2], 8);
|
||||
EXPECT_EQ(test.front(), 2);
|
||||
}
|
||||
|
||||
TEST(TestArray, popFront) {
|
||||
// Test contructor value
|
||||
etk::Array<float, 20> test;
|
||||
EXPECT_EQ(test.size(), 0);
|
||||
test.pushBack(2);
|
||||
test.pushBack(4);
|
||||
test.pushBack(8);
|
||||
EXPECT_EQ(test.size(), 3);
|
||||
EXPECT_EQ(test[0], 2);
|
||||
EXPECT_EQ(test[1], 4);
|
||||
EXPECT_EQ(test[2], 8);
|
||||
test.popFront();
|
||||
EXPECT_EQ(test.size(), 2);
|
||||
EXPECT_EQ(test[0], 4);
|
||||
EXPECT_EQ(test[1], 8);
|
||||
}
|
||||
|
||||
|
||||
TEST(TestArray, initializationList_1) {
|
||||
// Test contructor value
|
||||
etk::Array<int, 20> test = {1, 5, 6, 8};
|
||||
EXPECT_EQ(test.size(), 4);
|
||||
EXPECT_EQ(test[0], 1);
|
||||
EXPECT_EQ(test[1], 5);
|
||||
EXPECT_EQ(test[2], 6);
|
||||
EXPECT_EQ(test[3], 8);
|
||||
}
|
||||
|
||||
TEST(TestArray, initializationList_2) {
|
||||
// Test contructor value
|
||||
etk::Array<int, 20> test(1, 5, 6, 8);
|
||||
EXPECT_EQ(test.size(), 4);
|
||||
EXPECT_EQ(test[0], 1);
|
||||
EXPECT_EQ(test[1], 5);
|
||||
EXPECT_EQ(test[2], 6);
|
||||
EXPECT_EQ(test[3], 8);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static uint32_t isDestroy = 0;
|
||||
|
||||
class testContructDestruct {
|
||||
private:
|
||||
uint32_t m_addValue;
|
||||
public:
|
||||
testContructDestruct(uint32_t _addValue):
|
||||
m_addValue(_addValue) {
|
||||
isDestroy += m_addValue;
|
||||
TEST_DEBUG("Create class " << m_addValue);
|
||||
}
|
||||
testContructDestruct(testContructDestruct&& _obj):
|
||||
m_addValue(_obj.m_addValue) {
|
||||
_obj.m_addValue = 0;
|
||||
TEST_DEBUG("move contruction " << m_addValue);
|
||||
}
|
||||
virtual ~testContructDestruct() {
|
||||
if (m_addValue == 0) {
|
||||
TEST_DEBUG("Remove class (after move)");
|
||||
return;
|
||||
}
|
||||
TEST_DEBUG("Remove Class " << m_addValue);
|
||||
isDestroy -= m_addValue;
|
||||
}
|
||||
testContructDestruct& operator= (testContructDestruct&& _obj) {
|
||||
TEST_DEBUG("move operator " << m_addValue);
|
||||
if (this != &_obj) {
|
||||
etk::swap(m_addValue, _obj.m_addValue);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
TEST(TestArray, destroyElementAtTheCorectMoment) {
|
||||
isDestroy = 0;
|
||||
{
|
||||
etk::Array<testContructDestruct, 20> list;
|
||||
list.pushBack(testContructDestruct(55));
|
||||
EXPECT_EQ(list.size(), 1);
|
||||
EXPECT_EQ(isDestroy, 55);
|
||||
auto it = list.erase(list.begin());
|
||||
EXPECT_EQ(isDestroy, 0);
|
||||
EXPECT_EQ(list.size(), 0);
|
||||
EXPECT_EQ(it, list.end());
|
||||
}
|
||||
EXPECT_EQ(isDestroy, 0);
|
||||
}
|
||||
|
||||
TEST(TestArray, destroyElementAtTheCorectMoment_2) {
|
||||
isDestroy = 0;
|
||||
{
|
||||
etk::Array<testContructDestruct, 20> list;
|
||||
list.pushBack(testContructDestruct(4));
|
||||
list.pushBack(testContructDestruct(30));
|
||||
list.pushBack(testContructDestruct(1000));
|
||||
list.pushBack(testContructDestruct(200));
|
||||
EXPECT_EQ(list.size(), 4);
|
||||
EXPECT_EQ(isDestroy, 1234);
|
||||
auto it = list.erase(list.begin());
|
||||
EXPECT_EQ(list.size(), 3);
|
||||
EXPECT_EQ(isDestroy, 1230);
|
||||
it = list.erase(list.begin()+1);
|
||||
EXPECT_EQ(isDestroy, 230);
|
||||
EXPECT_EQ(list.size(), 2);
|
||||
}
|
||||
EXPECT_EQ(isDestroy, 0);
|
||||
}
|
||||
|
||||
TEST(TestArray, allocateElementAtTheCorectMoment) {
|
||||
isDestroy = 0;
|
||||
{
|
||||
etk::Array<testContructDestruct, 20> list;
|
||||
list.reserve(10);
|
||||
EXPECT_EQ(list.size(), 0);
|
||||
EXPECT_EQ(isDestroy, 0);
|
||||
}
|
||||
EXPECT_EQ(isDestroy, 0);
|
||||
}
|
||||
/*
|
||||
TEST(TestArray, allocateBench) {
|
||||
while (1) {
|
||||
etk::Array<uint8_t, 20> list;
|
||||
//list.reserve(1024*1024);
|
||||
for (size_t iii=0; iii < 1024*1024; ++iii) {
|
||||
list.pushBack(66);
|
||||
}
|
||||
EXPECT_EQ(list.size(), 1024*1024);
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user