[DEV] some correction and add etk::Set
This commit is contained in:
parent
027ebd8ae9
commit
4fe37acdf0
432
etk/Set.hpp
Normal file
432
etk/Set.hpp
Normal file
@ -0,0 +1,432 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2011, Edouard DUPIN, all right reserved
|
||||
* @license MPL v2.0 (see license file)
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <etk/types.hpp>
|
||||
#include <etk/Pair.hpp>
|
||||
#include <etk/Vector.hpp>
|
||||
|
||||
namespace etk {
|
||||
/**
|
||||
* @brief Set table template is a simple classical "Set" interface.
|
||||
* A Set contain a list of sorted single element
|
||||
* - 1 2 3 4 19 55 4356345
|
||||
* - "aaa" "AABB" "ZZ"
|
||||
*
|
||||
* A simple example of use:
|
||||
* @code{.cpp}
|
||||
* // Create a integer Set table
|
||||
* etk::Set<int> myValue;
|
||||
* // add some element (note add and set is the same function)
|
||||
* myValue.add(98837);
|
||||
* myValue.set(88);
|
||||
* // Display an element:
|
||||
* printf("my value is : %d", myValue[2]);
|
||||
* // Change value of an element:
|
||||
* size_t position = myValue.set(99);
|
||||
* // Remove an element:
|
||||
* myValue.remove(99);
|
||||
* //Clean all the table:
|
||||
* myValue.clear();
|
||||
* // number of elements:
|
||||
* size_t size = myValue.size();
|
||||
* @endcode
|
||||
*/
|
||||
template<class ETK_SET_TYPE>
|
||||
class Set {
|
||||
public:
|
||||
class Iterator {
|
||||
private:
|
||||
size_t m_current; //!< current Id on the vector
|
||||
Set<ETK_SET_TYPE>* m_set; //!< Pointer on the current element of the vectorBin
|
||||
public:
|
||||
/**
|
||||
* @brief Basic iterator constructor with no link with an etk::Vector
|
||||
*/
|
||||
Iterator():
|
||||
m_current(0),
|
||||
m_set(nullptr) {
|
||||
// nothing to do ...
|
||||
}
|
||||
/**
|
||||
* @brief Recopy constructor on a specific etkVector.
|
||||
* @param[in] _obj The Iterator that might be copy
|
||||
*/
|
||||
Iterator(const Iterator & _obj):
|
||||
m_current(_obj.m_current),
|
||||
m_set(_obj.m_set) {
|
||||
// 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 & _obj) {
|
||||
m_current = _obj.m_current;
|
||||
m_set = _obj.m_set;
|
||||
return *this;
|
||||
}
|
||||
/**
|
||||
* @brief Basic destructor
|
||||
*/
|
||||
~Iterator() {
|
||||
m_current = 0;
|
||||
m_set = nullptr;
|
||||
}
|
||||
/**
|
||||
* @brief basic boolean cast
|
||||
* @return true if the element is present in the etkVector size
|
||||
*/
|
||||
operator bool () {
|
||||
return (m_current < m_set->size());
|
||||
}
|
||||
/**
|
||||
* @brief Incremental operator
|
||||
* @return Reference on the current iterator increment
|
||||
*/
|
||||
Iterator& operator++ () {
|
||||
if ( m_set != nullptr
|
||||
&& m_current < m_set->size() )
|
||||
{
|
||||
m_current++;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
/**
|
||||
* @brief Decremental operator
|
||||
* @return Reference on the current iterator decrement
|
||||
*/
|
||||
Iterator& operator-- () {
|
||||
if ( m_set != 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
|
||||
*/
|
||||
const ETK_SET_TYPE* operator-> () const {
|
||||
//TK_CHECK_INOUT(m_current < m_set->size());
|
||||
return &(*m_set)[m_current];
|
||||
}
|
||||
ETK_SET_TYPE* operator-> () {
|
||||
//TK_CHECK_INOUT(m_current < m_set->size());
|
||||
return &(*m_set)[m_current];
|
||||
}
|
||||
/**
|
||||
* @brief Get reference on the current Element
|
||||
* @return the reference on the current Element
|
||||
*/
|
||||
const ETK_SET_TYPE& operator* () const {
|
||||
//TK_CHECK_INOUT(m_current < m_set->size());
|
||||
return (*m_set)[m_current];
|
||||
}
|
||||
ETK_SET_TYPE& operator* () {
|
||||
//TK_CHECK_INOUT(m_current < m_set->size());
|
||||
return (*m_set)[m_current];
|
||||
}
|
||||
bool operator== (const Iterator& _obj) const{
|
||||
return m_set == _obj.m_set
|
||||
&& m_current == _obj.m_current;
|
||||
}
|
||||
bool operator!= (const Iterator& _obj) const {
|
||||
return m_set != _obj.m_set
|
||||
|| m_current != _obj.m_current;
|
||||
}
|
||||
private:
|
||||
Iterator(const etk::Set<ETK_SET_TYPE> * _obj, int32_t _pos):
|
||||
m_current(_pos),
|
||||
m_set(const_cast<etk::Set<ETK_SET_TYPE>*>(_obj)) {
|
||||
// nothing to do ...
|
||||
}
|
||||
size_t getCurrent() const {
|
||||
return m_current;
|
||||
}
|
||||
friend class Set;
|
||||
};
|
||||
typedef bool (*sortFunction)(const ETK_SET_TYPE& _key1, const ETK_SET_TYPE& _key2);
|
||||
private:
|
||||
etk::Vector<ETK_SET_TYPE> m_data; //!< Data of the Set ==> the Set table is composed of pointer, this permit to have high speed when resize the vector ...
|
||||
sortFunction m_comparator;
|
||||
public:
|
||||
/**
|
||||
* @brief Set the comparator of the set.
|
||||
* @param[in] _comparator comparing function.
|
||||
*/
|
||||
void setComparator(sortFunction _comparator) {
|
||||
m_comparator = _comparator;
|
||||
if (m_comparator != nullptr) {
|
||||
m_data.sort(0, m_data.size(), m_comparator);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @brief Constructor of the Set table.
|
||||
* @param[in] _count Number of basic element (pre-allocated) in the table.
|
||||
*/
|
||||
Set(int32_t _count = 0) :
|
||||
m_data(_count),
|
||||
m_comparator([](const ETK_SET_TYPE& _key1, const ETK_SET_TYPE& _key2) { return _key1 < _key2; }) {
|
||||
// nothing to do
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief List initializer (ex: etk::Vector<etk::String> plop = {"hello", world"}
|
||||
* @param[in] _element element to add in the vector
|
||||
*/
|
||||
template<typename... ETK_SET_TYPE_2>
|
||||
Set(const ETK_SET_TYPE_2& ... _args):
|
||||
m_data(0),
|
||||
m_comparator([](const ETK_SET_TYPE& _key1, const ETK_SET_TYPE& _key2) { return _key1 < _key2; }) {
|
||||
add(_args...);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Destructor of the Set table (clear all element in the table)
|
||||
*/
|
||||
~Set() {
|
||||
clear();
|
||||
}
|
||||
/**
|
||||
* @brief Remove all entry in the Set table.
|
||||
* @note It does not delete pointer if your value is a pointer type...
|
||||
*/
|
||||
void clear() {
|
||||
m_data.clear();
|
||||
}
|
||||
/**
|
||||
* @brief Check if an element exist or not
|
||||
* @param[in] _key Name of the Set requested
|
||||
* @return true if the element exist
|
||||
*/
|
||||
bool exist(const ETK_SET_TYPE& _key) const {
|
||||
Iterator it = find(_key);
|
||||
if (it == end()) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
/**
|
||||
* @brief Get Element an a special position
|
||||
* @param[in] _position Position in the Set
|
||||
* @return An reference on the selected element
|
||||
*/
|
||||
ETK_SET_TYPE& operator[] (size_t _position) {
|
||||
return m_data[_position];
|
||||
}
|
||||
/**
|
||||
* @brief Get Element an a special position
|
||||
* @param[in] _position Position in the Set
|
||||
* @return An reference on the selected element
|
||||
*/
|
||||
const ETK_SET_TYPE& operator[] (size_t _position) const {
|
||||
return m_data[_position];
|
||||
}
|
||||
private:
|
||||
template<typename... ETK_SET_TYPE_2>
|
||||
void add(const ETK_SET_TYPE& _value, const ETK_SET_TYPE_2& ... _args) {
|
||||
add(_value);
|
||||
add(_args...);
|
||||
}
|
||||
public:
|
||||
/**
|
||||
* @brief Add an element OR set an element value
|
||||
* @note add and set is the same function.
|
||||
* @param[in] _key Name of the value to set in the Set table.
|
||||
* @param[in] _value Value to set in the Set table.
|
||||
*/
|
||||
void add(const ETK_SET_TYPE& _key) {
|
||||
if (m_comparator != nullptr) {
|
||||
for (size_t iii=0; iii<m_data.size(); ++iii) {
|
||||
if (_key == m_data[iii]) {
|
||||
return;
|
||||
}
|
||||
if (m_comparator(_key, m_data[iii]) == true) {
|
||||
// Find a position
|
||||
m_data.insert(iii, etk::move(_key));
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
m_data.pushBack(etk::move(_key));
|
||||
}
|
||||
/**
|
||||
* @brief Set an element value
|
||||
* @note add and set is the same function.
|
||||
* @param[in] _key Name of the value to set in the Set table.
|
||||
* @param[in] _value Value to set in the Set table.
|
||||
*/
|
||||
void set(const ETK_SET_TYPE& _key) {
|
||||
add(etk::move(_key));
|
||||
}
|
||||
/**
|
||||
* @brief Remove an element in the Set table.
|
||||
* @param[in] _key Name of the element to remove.
|
||||
*/
|
||||
/*
|
||||
// TODO: this is dangerous ...
|
||||
void erase(const ETK_SET_TYPE& _key) {
|
||||
Iterator it = find(_key);
|
||||
if (it == end()) {
|
||||
return;
|
||||
}
|
||||
m_data.erase(m_data.begin() + it.getCurrent());
|
||||
}
|
||||
*/
|
||||
/**
|
||||
* @brief Remove an element in the Set table.
|
||||
* @param[in] _it Iterator on the element.
|
||||
*/
|
||||
Iterator erase(const Iterator& _it) {
|
||||
return position(*m_data.erase(m_data.begin() + _it.getCurrent()));
|
||||
}
|
||||
/**
|
||||
* @brief Get the number of element in the Set table
|
||||
* @return number of elements
|
||||
*/
|
||||
size_t size() const {
|
||||
return m_data.size();
|
||||
}
|
||||
/**
|
||||
* @brief Swap generic function
|
||||
* @param[in,out] _obj Object to swap data & control...
|
||||
*/
|
||||
void swap(Set& _obj) {
|
||||
etk::swap(m_data, _obj.m_data);
|
||||
etk::swap(m_comparator, _obj.m_comparator);
|
||||
}
|
||||
/**
|
||||
* @brief Get an iterator an an specific position
|
||||
* @param[in] _pos Requested position of the iterator in the vector
|
||||
* @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 Vector
|
||||
* @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 Vector
|
||||
* @return The Iterator
|
||||
*/
|
||||
Iterator end() {
|
||||
return position(size());
|
||||
}
|
||||
const Iterator end() const {
|
||||
return position(size());
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Find an element position the the Set table
|
||||
* @param[in] _key Name of the element to find
|
||||
* @return Iterator on the element find or end()
|
||||
*/
|
||||
const Iterator find(const ETK_SET_TYPE& _key) const {
|
||||
// TODO: search in a dichotomic way.
|
||||
for (size_t iii=0; iii<m_data.size(); iii++) {
|
||||
if (m_data[iii] == _key) {
|
||||
return position(iii);
|
||||
}
|
||||
}
|
||||
return end();
|
||||
}
|
||||
Iterator find(const ETK_SET_TYPE& _key) {
|
||||
// TODO: search in a dichotomic way.
|
||||
for (size_t iii=0; iii<m_data.size(); iii++) {
|
||||
if (m_data[iii] == _key) {
|
||||
return position(iii);
|
||||
}
|
||||
}
|
||||
return end();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -1038,11 +1038,10 @@ namespace etk {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
bool etk::operator> (const etk::String& _left, const etk::String& _right) {
|
||||
for (size_t iii=0; iii<_left.size() && iii<_right.size(); ++iii) {
|
||||
for (size_t iii=0;
|
||||
iii<_left.size() && iii<_right.size();
|
||||
++iii) {
|
||||
if (_left[iii] > _right[iii]) {
|
||||
return true;
|
||||
}
|
||||
@ -1056,7 +1055,9 @@ bool etk::operator> (const etk::String& _left, const etk::String& _right) {
|
||||
return false;
|
||||
}
|
||||
bool etk::operator>= (const etk::String& _left, const etk::String& _right) {
|
||||
for (size_t iii=0; iii<_left.size() && iii<_right.size(); ++iii) {
|
||||
for (size_t iii=0;
|
||||
iii<_left.size() && iii<_right.size();
|
||||
++iii) {
|
||||
if (_left[iii] > _right[iii]) {
|
||||
return true;
|
||||
}
|
||||
@ -1070,7 +1071,9 @@ bool etk::operator>= (const etk::String& _left, const etk::String& _right) {
|
||||
return false;
|
||||
}
|
||||
bool etk::operator< (const etk::String& _left, const etk::String& _right) {
|
||||
for (size_t iii=0; iii<_left.size() && iii<_right.size(); ++iii) {
|
||||
for (size_t iii=0;
|
||||
iii<_left.size() && iii<_right.size();
|
||||
++iii) {
|
||||
if (_left[iii] < _right[iii]) {
|
||||
return true;
|
||||
}
|
||||
@ -1084,7 +1087,9 @@ bool etk::operator< (const etk::String& _left, const etk::String& _right) {
|
||||
return false;
|
||||
}
|
||||
bool etk::operator<= (const etk::String& _left, const etk::String& _right) {
|
||||
for (size_t iii=0; iii<_left.size() && iii<_right.size(); ++iii) {
|
||||
for (size_t iii=0;
|
||||
iii<_left.size() && iii<_right.size();
|
||||
++iii) {
|
||||
if (_left[iii] < _right[iii]) {
|
||||
return true;
|
||||
}
|
||||
|
@ -205,6 +205,9 @@ namespace etk {
|
||||
m_vector(const_cast<Vector<ETK_VECTOR_TYPE> *>(_obj)) {
|
||||
// nothing to do ...
|
||||
}
|
||||
size_t getCurrent() const {
|
||||
return m_current;
|
||||
}
|
||||
friend class Vector;
|
||||
};
|
||||
private:
|
||||
@ -470,6 +473,7 @@ namespace etk {
|
||||
m_data[idElement+iii] = _item[iii];
|
||||
}
|
||||
}
|
||||
private:
|
||||
void pushBackN(const ETK_VECTOR_TYPE& _value) {
|
||||
pushBack(_value);
|
||||
}
|
||||
@ -478,6 +482,7 @@ namespace etk {
|
||||
pushBack(_value);
|
||||
pushBackN(_args...);
|
||||
}
|
||||
public:
|
||||
/**
|
||||
* @brief Remove the first element of the vector
|
||||
*/
|
||||
@ -509,7 +514,7 @@ namespace etk {
|
||||
* @param[in] _nbElement Number of element to add in the Vector
|
||||
*/
|
||||
void insert(size_t _pos, const ETK_VECTOR_TYPE * _item, size_t _nbElement) {
|
||||
if (_pos>m_size) {
|
||||
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;
|
||||
@ -517,14 +522,15 @@ namespace etk {
|
||||
size_t idElement = m_size;
|
||||
// Request resize of the current buffer
|
||||
resize(m_size+_nbElement);
|
||||
if (idElement>=m_size) {
|
||||
if (idElement >= m_size) {
|
||||
//TK_ERROR("Resize does not work correctly ... not added item");
|
||||
return;
|
||||
}
|
||||
// move current data (after the position)
|
||||
size_t sizeToMove = (idElement - _pos);
|
||||
if ( 0 < sizeToMove) {
|
||||
if (sizeToMove > 0) {
|
||||
for (size_t iii=1; iii<=sizeToMove; iii++) {
|
||||
// tODO: better explicite the swap...
|
||||
m_data[m_size-iii] = etk::move(m_data[idElement-iii]);
|
||||
}
|
||||
}
|
||||
@ -541,6 +547,14 @@ namespace etk {
|
||||
void insert(size_t _pos, const ETK_VECTOR_TYPE& _item) {
|
||||
insert(_pos, &_item, 1);
|
||||
}
|
||||
/**
|
||||
* @brief Insert one element in the Vector 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_VECTOR_TYPE& _item) {
|
||||
insert(_pos.getCurrent(), _item);
|
||||
}
|
||||
/**
|
||||
* @brief Remove N element
|
||||
* @param[in] _pos Position to remove the data
|
||||
@ -578,8 +592,8 @@ namespace etk {
|
||||
* @return An iterator on the new element at this position.
|
||||
*/
|
||||
Iterator erase(const Iterator& _it) {
|
||||
eraseLen(_it.m_current, 1);
|
||||
return position(_it.m_current);
|
||||
eraseLen(_it.getCurrent(), 1);
|
||||
return position(_it.getCurrent());
|
||||
}
|
||||
/**
|
||||
* @brief Remove one element
|
||||
@ -613,6 +627,9 @@ namespace etk {
|
||||
// Request resize of the current buffer
|
||||
resize(m_size-nbElement);
|
||||
}
|
||||
void erase(const Iterator& _pos, const Iterator& _posEnd) {
|
||||
erase(_pos.getCurrent(), _posEnd.getCurrent());
|
||||
}
|
||||
/**
|
||||
* @brief extract data between two point :
|
||||
* @param[in] _posStart start position to extract data
|
||||
|
@ -28,13 +28,18 @@ namespace etk {
|
||||
return (typename etk::RemoveReference<ETK_MOVE_TYPE>::m_type&&)_obj;
|
||||
}
|
||||
|
||||
template<typename ETK_SWAP_TYPE>
|
||||
template<typename ETK_SWAP_TYPE,
|
||||
typename etk::EnableIf<etk::Is_swap_MemberFunctionExists<ETK_SWAP_TYPE>::value,int>::type = 0>
|
||||
inline void swap(ETK_SWAP_TYPE& _obj1, ETK_SWAP_TYPE& _obj2) {
|
||||
_obj1.swap(_obj2);
|
||||
}
|
||||
template<typename ETK_SWAP_TYPE,
|
||||
typename etk::EnableIf<!etk::Is_swap_MemberFunctionExists<ETK_SWAP_TYPE>::value,int>::type = 0>
|
||||
inline void swap(ETK_SWAP_TYPE& _obj1, ETK_SWAP_TYPE& _obj2) {
|
||||
ETK_SWAP_TYPE tmp = etk::move(_obj1);
|
||||
_obj1 = etk::move(_obj2);
|
||||
_obj2 = etk::move(tmp);
|
||||
}
|
||||
|
||||
template <class ETK_FORWARD_TYPE>
|
||||
inline ETK_FORWARD_TYPE&& forward(typename etk::RemoveReference<ETK_FORWARD_TYPE>::m_type& _obj) noexcept {
|
||||
return static_cast<ETK_FORWARD_TYPE&&>(_obj);
|
||||
|
@ -28,6 +28,19 @@ namespace etk {
|
||||
inline float sqrt(float _value) {
|
||||
return ::sqrtf(_value);
|
||||
}
|
||||
inline float pow(float _xxx, float _yyy) {
|
||||
return ::powf(_xxx, _yyy);
|
||||
}
|
||||
inline float log(float _value) {
|
||||
return ::logf(_value);
|
||||
}
|
||||
inline float log10(float _value) {
|
||||
return ::log10f(_value);
|
||||
}
|
||||
inline float exp(float _value) {
|
||||
return ::expf(_value);
|
||||
}
|
||||
|
||||
inline double cos(double _value) {
|
||||
return ::cos(_value);
|
||||
}
|
||||
@ -49,6 +62,18 @@ namespace etk {
|
||||
inline double sqrt(double _value) {
|
||||
return ::sqrt(_value);
|
||||
}
|
||||
inline double pow(double _xxx, double _yyy) {
|
||||
return ::pow(_xxx, _yyy);
|
||||
}
|
||||
inline double log(double _value) {
|
||||
return ::log(_value);
|
||||
}
|
||||
inline double log10(double _value) {
|
||||
return ::log10(_value);
|
||||
}
|
||||
inline double exp(double _value) {
|
||||
return ::exp(_value);
|
||||
}
|
||||
template <class TYPE> const TYPE& min(const TYPE& _val1, const TYPE& _val2) {
|
||||
return (_val1 > _val2) ? _val2 : _val1;
|
||||
}
|
||||
@ -72,7 +97,8 @@ namespace etk {
|
||||
size_t distance(const ETK_ITERATOR_TYPE& _start, const ETK_ITERATOR_TYPE& _stop) {
|
||||
size_t out = 0;
|
||||
ETK_ITERATOR_TYPE tmp = _start;
|
||||
while (tmp != _stop) {
|
||||
ETK_ITERATOR_TYPE tmp2 = _stop;
|
||||
while (tmp != tmp2) {
|
||||
out++;
|
||||
++tmp;
|
||||
}
|
||||
|
12
etk/tool.cpp
12
etk/tool.cpp
@ -12,21 +12,21 @@ extern "C" {
|
||||
#include <stdlib.h>
|
||||
}
|
||||
|
||||
double etk::tool::frand(double _a, double _b) {
|
||||
double etk::random::frand(double _a, double _b) {
|
||||
return (float)(( (double)rand()/(double)RAND_MAX ) * ((double)_b-(double)_a) + (double)_a);
|
||||
}
|
||||
|
||||
int32_t etk::tool::irand(int32_t _a, int32_t _b) {
|
||||
int32_t etk::random::irand(int32_t _a, int32_t _b) {
|
||||
return (int32_t)(( rand()/(double)RAND_MAX ) * ((double)_b-(double)_a) + (double)_a);
|
||||
}
|
||||
uint32_t etk::tool::urand(uint32_t _a, uint32_t _b) {
|
||||
uint32_t etk::random::urand(uint32_t _a, uint32_t _b) {
|
||||
return (uint32_t)(( rand()/(double)RAND_MAX ) * ((double)_b-(double)_a) + (double)_a);
|
||||
}
|
||||
|
||||
void etk::tool::resetRandom() {
|
||||
srand(time(NULL));
|
||||
void etk::random::reset() {
|
||||
srand(time(0));
|
||||
}
|
||||
|
||||
void etk::tool::randSeek(int32_t _val) {
|
||||
void etk::random::resetSeed(int32_t _val) {
|
||||
srand(_val);
|
||||
}
|
||||
|
64
etk/tool.hpp
64
etk/tool.hpp
@ -10,10 +10,18 @@
|
||||
|
||||
namespace etk {
|
||||
/**
|
||||
* @brief Some useful tools
|
||||
* @todo Remove all of this use std11 random
|
||||
* @brief Some useful random elements
|
||||
*/
|
||||
namespace tool {
|
||||
namespace random {
|
||||
/**
|
||||
* @brief Reset the random system with a random value (time).
|
||||
*/
|
||||
void reset();
|
||||
/**
|
||||
* @brief Reset the random system with The specify value.
|
||||
* @param[in] _val Seek value for the pseudo random system.
|
||||
*/
|
||||
void resetSeed(int32_t _val);
|
||||
/**
|
||||
* @brief Get a random value in a specific range in float.
|
||||
* @param[in] _a Lower value of the random.
|
||||
@ -29,15 +37,61 @@ namespace etk {
|
||||
*/
|
||||
int32_t irand(int32_t _a=0x80000000, int32_t _b=0x7FFFFFFF);
|
||||
uint32_t urand(uint32_t _a=0, uint32_t _b=0xFFFFFFFF);
|
||||
|
||||
template<typename ETK_RANDOM_TYPE_1, typename ETK_RANDOM_TYPE_2>
|
||||
void shuffle(ETK_RANDOM_TYPE_1 _left, ETK_RANDOM_TYPE_2 _right) {
|
||||
int32_t distance = etk::distance(_left, _right);
|
||||
while (_left != _right) {
|
||||
int64_t randValue = etk::random::urand(0, distance);
|
||||
auto it = _left + randValue;
|
||||
etk::swap(*_left, *it);
|
||||
++_left;
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @brief Some useful tools
|
||||
* @todo Remove all of this use std11 random
|
||||
*/
|
||||
namespace tool {
|
||||
/**
|
||||
* @brief Get a random value in a specific range in float.
|
||||
* @param[in] _a Lower value of the random.
|
||||
* @param[in] _b Bigger value of the random.
|
||||
* @return Random Value between [_a and _b]
|
||||
* @note DEPRECATED
|
||||
*/
|
||||
inline double frand(double _a, double _b) {
|
||||
return etk::random::frand(_a, _b);
|
||||
}
|
||||
/**
|
||||
* @brief Get a random value in a specific range in integer.
|
||||
* @param[in] _a Lower value of the random.
|
||||
* @param[in] _b Bigger value of the random.
|
||||
* @return Random Value between [_a and _b]
|
||||
* @note DEPRECATED
|
||||
*/
|
||||
inline int32_t irand(int32_t _a=0x80000000, int32_t _b=0x7FFFFFFF) {
|
||||
return etk::random::irand(_a, _b);
|
||||
}
|
||||
inline uint32_t urand(uint32_t _a=0, uint32_t _b=0xFFFFFFFF) {
|
||||
return etk::random::urand(_a, _b);
|
||||
}
|
||||
/**
|
||||
* @brief Reset the random system with a random value (time).
|
||||
* @note DEPRECATED
|
||||
*/
|
||||
void resetRandom();
|
||||
inline void resetRandom() {
|
||||
etk::random::reset();
|
||||
}
|
||||
/**
|
||||
* @brief Reset the random system with The specify value.
|
||||
* @param[in] _val Seek value for the pseudo random system.
|
||||
* @note DEPRECATED
|
||||
*/
|
||||
void randSeek(int32_t _val);
|
||||
inline void randSeek(int32_t _val) {
|
||||
etk::random::resetSeed(_val);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -8,15 +8,6 @@
|
||||
#include <etk/Vector.hpp>
|
||||
|
||||
#pragma once
|
||||
// in header
|
||||
template<typename T>
|
||||
struct TypeParseTraits
|
||||
{ static const char* name; };
|
||||
|
||||
// in c-file
|
||||
#define REGISTER_PARSE_TYPE(X) \
|
||||
template <> const char* TypeParseTraits<X>::name = #X
|
||||
|
||||
|
||||
namespace etk {
|
||||
template<typename ETK_TYPE>
|
||||
|
@ -154,4 +154,97 @@ namespace etk {
|
||||
public etk::typeTrue {
|
||||
|
||||
};
|
||||
|
||||
#define DEFINE_METHOD_CHECKER(RETURN_TYPE, METHOD_NAME, PARAMETERS) \
|
||||
template<typename ETK_TYPE> \
|
||||
struct Is_ ## METHOD_NAME ## _MemberFunctionExists { \
|
||||
private: \
|
||||
typedef char True; \
|
||||
typedef char (&False)[2]; \
|
||||
template<typename U, RETURN_TYPE (U::*)PARAMETERS = &U::METHOD_NAME> \
|
||||
struct Checker { \
|
||||
typedef True Type; \
|
||||
}; \
|
||||
template<typename U> \
|
||||
static typename Checker<U>::Type Tester(const U*); \
|
||||
static False Tester(...); \
|
||||
public: \
|
||||
enum { value = (sizeof(Tester(static_cast<const ETK_TYPE*>(0))) == sizeof(True)) }; \
|
||||
}
|
||||
// Use example:
|
||||
// Is_swap_MemberFunctionExists<T>::value
|
||||
DEFINE_METHOD_CHECKER(void, swap, (ETK_TYPE&));
|
||||
|
||||
|
||||
/*
|
||||
#if 0
|
||||
template<typename T>
|
||||
struct hasEtkStreamExporter {
|
||||
typedef char yes[1];
|
||||
typedef char no[2];
|
||||
template<typename U> static yes& test( U& );
|
||||
template<typename U> static no& test(...);
|
||||
|
||||
static etk::Stream &s;
|
||||
static T const &t;
|
||||
|
||||
static bool const value = sizeof( test( s << t ) ) == sizeof( yes ); // line 48
|
||||
};
|
||||
#else
|
||||
namespace hasEtkStreamExporterImpl {
|
||||
typedef char no;
|
||||
typedef char yes[2];
|
||||
struct AnyType {
|
||||
template<typename ETK_TYPE> AnyType(const ETK_TYPE&);
|
||||
};
|
||||
no operator<<( etk::Stream&, const AnyType& );
|
||||
yes& test( etk::Stream& );
|
||||
no test( no );
|
||||
template<typename ETK_TYPE>
|
||||
struct hasEtkStreamExporter {
|
||||
static etk::Stream& sss;
|
||||
static const ETK_TYPE& ttt;
|
||||
static bool const value = sizeof( test(sss << ttt) ) == sizeof( yes );
|
||||
};
|
||||
}
|
||||
|
||||
template<typename ETK_TYPE>
|
||||
struct hasEtkStreamExporter:
|
||||
etk::hasEtkStreamExporterImpl::hasEtkStreamExporter<ETK_TYPE> {
|
||||
};
|
||||
#endif
|
||||
#if 1
|
||||
template <typename T>
|
||||
class hasMemberToString {
|
||||
typedef char one;
|
||||
typedef long two;
|
||||
template <typename C> static one test( decltype(T::toString()) );
|
||||
template <typename C> static two test(...);
|
||||
public:
|
||||
enum { value = sizeof(test<T>(0)) == sizeof(char) };
|
||||
};
|
||||
#else
|
||||
namespace hasMemberToStringImpl {
|
||||
typedef char no;
|
||||
typedef char yes[2];
|
||||
struct AnyType {
|
||||
template<typename ETK_TYPE> AnyType(const ETK_TYPE&);
|
||||
};
|
||||
no operator<<( etk::Stream&, const AnyType& );
|
||||
yes& test( etk::Stream& );
|
||||
no test( no );
|
||||
template<typename ETK_TYPE>
|
||||
struct hasMemberToString {
|
||||
static etk::Stream& sss;
|
||||
static const ETK_TYPE& ttt;
|
||||
static bool const value = sizeof( test(sss << ttt) ) == sizeof( yes );
|
||||
};
|
||||
}
|
||||
|
||||
template<typename ETK_TYPE>
|
||||
struct hasMemberToString:
|
||||
etk::hasMemberToStringImpl::hasMemberToString<ETK_TYPE> {
|
||||
};
|
||||
#endif
|
||||
*/
|
||||
}
|
||||
|
@ -49,6 +49,7 @@ def configure(target, my_module):
|
||||
'etk/Stream.hpp',
|
||||
'etk/Pair.hpp',
|
||||
'etk/Map.hpp',
|
||||
'etk/Set.hpp',
|
||||
'etk/move.hpp',
|
||||
'etk/typeTrait.hpp',
|
||||
'etk/Function.hpp',
|
||||
|
@ -31,6 +31,7 @@ def configure(target, my_module):
|
||||
'test/testFunction.cpp',
|
||||
'test/testMapUnordered.cpp',
|
||||
'test/testMap.cpp',
|
||||
'test/testSet.cpp',
|
||||
'test/testMatrix3x3.cpp',
|
||||
'test/testRegExp.cpp',
|
||||
'test/testTransform.cpp',
|
||||
|
105
test/testSet.cpp
Normal file
105
test/testSet.cpp
Normal file
@ -0,0 +1,105 @@
|
||||
/**
|
||||
* @author Edouard DUPIN
|
||||
*
|
||||
* @copyright 2011, Edouard DUPIN, all right reserved
|
||||
*
|
||||
* @license MPL v2.0 (see license file)
|
||||
*/
|
||||
|
||||
#include <etest/etest.hpp>
|
||||
|
||||
#include <etk/Set.hpp>
|
||||
#include <test-debug/debug.hpp>
|
||||
|
||||
TEST(TestEtkSet, Creation) {
|
||||
etk::Set<uint32_t> testData;
|
||||
EXPECT_EQ(testData.size(), 0);
|
||||
}
|
||||
|
||||
TEST(TestEtkSet, addGoodOrder) {
|
||||
etk::Set<uint32_t> testData;
|
||||
EXPECT_EQ(testData.size(), 0);
|
||||
testData.add(2);
|
||||
testData.add(9);
|
||||
testData.add(1);
|
||||
testData.add(6);
|
||||
EXPECT_EQ(testData.size(), 4);
|
||||
EXPECT_EQ(testData[0], 1);
|
||||
EXPECT_EQ(testData[1], 2);
|
||||
EXPECT_EQ(testData[2], 6);
|
||||
EXPECT_EQ(testData[3], 9);
|
||||
}
|
||||
|
||||
TEST(TestEtkSet, addMultiple) {
|
||||
etk::Set<uint32_t> testData;
|
||||
EXPECT_EQ(testData.size(), 0);
|
||||
testData.add(2);
|
||||
testData.add(9);
|
||||
testData.add(9);
|
||||
testData.add(2);
|
||||
EXPECT_EQ(testData.size(), 2);
|
||||
EXPECT_EQ(testData[0], 2);
|
||||
EXPECT_EQ(testData[1], 9);
|
||||
}
|
||||
|
||||
TEST(TestEtkSet, initializationList) {
|
||||
etk::Set<int> testData = {7,2,3,3,1,99};
|
||||
EXPECT_EQ(testData.size(), 5);
|
||||
EXPECT_EQ(testData[0], 1);
|
||||
EXPECT_EQ(testData[1], 2);
|
||||
EXPECT_EQ(testData[2], 3);
|
||||
EXPECT_EQ(testData[3], 7);
|
||||
EXPECT_EQ(testData[4], 99);
|
||||
}
|
||||
|
||||
TEST(TestEtkSet, find) {
|
||||
etk::Set<int> testData = {1,2,3,66,74623};
|
||||
EXPECT_EQ(testData.size(), 5);
|
||||
auto it = testData.find(66);
|
||||
EXPECT_EQ(it, testData.begin() + 3);
|
||||
it = testData.find(99);
|
||||
EXPECT_EQ(it, testData.end());
|
||||
}
|
||||
|
||||
TEST(TestEtkSet, erase) {
|
||||
etk::Set<int> testData = {1,3,4,2,0,7};
|
||||
EXPECT_EQ(testData.size(), 6);
|
||||
auto it = testData.erase(testData.begin() + 4);
|
||||
EXPECT_EQ(testData.size(), 5);
|
||||
EXPECT_EQ(testData[0], 0);
|
||||
EXPECT_EQ(testData[1], 1);
|
||||
EXPECT_EQ(testData[2], 2);
|
||||
EXPECT_EQ(testData[3], 3);
|
||||
EXPECT_EQ(testData[4], 7);
|
||||
}
|
||||
|
||||
TEST(TestEtkSet, withStringClass) {
|
||||
etk::Set<etk::String> testData;
|
||||
EXPECT_EQ(testData.size(), 0);
|
||||
testData.add("2");
|
||||
testData.add("9");
|
||||
testData.add("9");
|
||||
testData.add("4");
|
||||
EXPECT_EQ(testData.size(), 3);
|
||||
EXPECT_EQ(testData[0], "2");
|
||||
EXPECT_EQ(testData[1], "4");
|
||||
EXPECT_EQ(testData[2], "9");
|
||||
}
|
||||
|
||||
bool comp(const uint32_t& _left, const uint32_t& _right ) { return _left>_right; };
|
||||
|
||||
TEST(TestEtkSet, creationComparatorReverse) {
|
||||
etk::Set<uint32_t> testData;
|
||||
//auto comp = [](const uint32_t& _left, const uint32_t& _right ) { return _left>_right; };
|
||||
testData.setComparator(&comp);
|
||||
EXPECT_EQ(testData.size(), 0);
|
||||
testData.add(2);
|
||||
testData.add(9);
|
||||
testData.add(1);
|
||||
testData.add(6);
|
||||
EXPECT_EQ(testData.size(), 4);
|
||||
EXPECT_EQ(testData[0], 9);
|
||||
EXPECT_EQ(testData[1], 6);
|
||||
EXPECT_EQ(testData[2], 2);
|
||||
EXPECT_EQ(testData[3], 1);
|
||||
}
|
@ -214,4 +214,48 @@ TEST(typeMove, move_1) {
|
||||
EXPECT_EQ(contructCount, 1001);
|
||||
}
|
||||
|
||||
static uint32_t swapMode = 0;
|
||||
|
||||
class TestSwap1 {
|
||||
private:
|
||||
uint32_t m_value;
|
||||
public:
|
||||
TestSwap1(uint32_t _value) {
|
||||
m_value = _value;
|
||||
swapMode += m_value;
|
||||
}
|
||||
~TestSwap1() {
|
||||
swapMode += m_value;
|
||||
}
|
||||
};
|
||||
class TestSwap2 {
|
||||
private:
|
||||
uint32_t m_value;
|
||||
public:
|
||||
TestSwap2(uint32_t _value) {
|
||||
m_value = _value;
|
||||
swapMode += m_value;
|
||||
}
|
||||
~TestSwap2() {
|
||||
swapMode += m_value;
|
||||
}
|
||||
|
||||
void swap(TestSwap2& _obj) {
|
||||
swapMode += 1000000;
|
||||
uint32_t tmp = m_value;
|
||||
m_value = _obj.m_value;
|
||||
_obj.m_value = tmp;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
TEST(typeTrait, swap_1) {
|
||||
bool ret = etk::Is_swap_MemberFunctionExists<TestSwap1>::value;
|
||||
EXPECT_EQ(ret, false);
|
||||
}
|
||||
|
||||
TEST(typeTrait, swap_2) {
|
||||
bool ret = etk::Is_swap_MemberFunctionExists<TestSwap2>::value;
|
||||
EXPECT_EQ(ret, true);
|
||||
}
|
||||
|
||||
|
@ -51,6 +51,53 @@ TEST(TestVector, pushBack) {
|
||||
EXPECT_EQ(test[1], 4);
|
||||
}
|
||||
|
||||
TEST(TestVector, pushFront) {
|
||||
// Test contructor value
|
||||
etk::Vector<float> 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(TestVector, insert) {
|
||||
// Test contructor value
|
||||
etk::Vector<float> 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(TestVector, back) {
|
||||
// Test contructor value
|
||||
|
Loading…
x
Reference in New Issue
Block a user