2017-09-20 01:10:57 +02:00
/** @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>
2018-09-13 23:09:52 +02:00
# include <etk/algorithm.hpp>
2017-09-20 01:10:57 +02:00
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
*/
2017-10-02 23:30:54 +02:00
template < class ETK_SET_TYPE , int STATIC_ALLOCATION_SIZE = - 1 >
2017-09-20 01:10:57 +02:00
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 ) ,
2018-06-19 22:15:52 +02:00
m_set ( null ) {
2017-09-20 01:10:57 +02:00
// 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 ;
2018-06-19 22:15:52 +02:00
m_set = null ;
2017-09-20 01:10:57 +02:00
}
/**
* @ 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 + + ( ) {
2018-06-19 22:15:52 +02:00
if ( m_set ! = null
2017-09-20 01:10:57 +02:00
& & m_current < m_set - > size ( ) )
{
m_current + + ;
}
return * this ;
}
/**
* @ brief Decremental operator
* @ return Reference on the current iterator decrement
*/
Iterator & operator - - ( ) {
2018-06-19 22:15:52 +02:00
if ( m_set ! = null
2017-09-20 01:10:57 +02:00
& & 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 ;
2017-10-21 19:05:21 +02:00
sort ( ) ;
}
private :
/**
* @ brief Order the Set with the corect functor
*/
void sort ( ) {
2018-06-19 22:15:52 +02:00
if ( m_comparator ! = null ) {
2018-09-13 23:09:52 +02:00
etk : : algorithm : : quickSort ( m_data , m_comparator ) ;
2017-10-21 19:05:21 +02:00
} else {
2018-09-13 23:09:52 +02:00
sortFunction comparator = [ ] ( const ETK_SET_TYPE & _key1 , const ETK_SET_TYPE & _key2 ) { return _key1 < _key2 ; } ;
etk : : algorithm : : quickSort ( m_data , comparator ) ;
2017-09-20 01:10:57 +02:00
}
}
2017-10-21 19:05:21 +02:00
public :
2017-09-20 01:10:57 +02:00
/**
* @ brief Constructor of the Set table .
* @ param [ in ] _count Number of basic element ( pre - allocated ) in the table .
*/
Set ( int32_t _count = 0 ) :
2017-10-13 00:07:49 +02:00
m_data ( ) ,
2018-06-19 22:15:52 +02:00
m_comparator ( null ) {
2017-10-13 00:07:49 +02:00
m_data . reserve ( _count ) ;
2017-09-20 01:10:57 +02:00
// 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 ) :
2017-10-13 00:07:49 +02:00
m_data ( ) ,
2018-06-19 22:15:52 +02:00
m_comparator ( null ) {
2017-09-20 01:10:57 +02:00
add ( _args . . . ) ;
}
/**
* @ brief Destructor of the Set table ( clear all element in the table )
*/
~ Set ( ) {
clear ( ) ;
}
2017-10-02 23:30:54 +02:00
/**
* @ brief Remove the first element of the vector
*/
void popFront ( ) {
m_data . popFront ( ) ;
}
/**
* @ brief Remove the last element of the vector
*/
void popBack ( ) {
m_data . popBack ( ) ;
}
2017-09-20 01:10:57 +02:00
/**
* @ 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 ) {
2018-06-19 22:15:52 +02:00
if ( m_comparator ! = null ) {
2017-09-20 01:10:57 +02:00
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 ;
}
}
2017-10-21 19:05:21 +02:00
} else {
for ( size_t iii = 0 ; iii < m_data . size ( ) ; + + iii ) {
if ( _key = = m_data [ iii ] ) {
return ;
}
if ( _key < m_data [ iii ] ) {
// Find a position
m_data . insert ( iii , etk : : move ( _key ) ) ;
return ;
}
}
2017-09-20 01:10:57 +02:00
}
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 ) {
2017-10-02 23:30:54 +02:00
if ( _it ! = end ( ) ) {
m_data . erase ( m_data . begin ( ) + _it . getCurrent ( ) ) ;
return position ( _it . getCurrent ( ) ) ;
}
return _it ;
2017-09-20 01:10:57 +02:00
}
/**
* @ brief Get the number of element in the Set table
* @ return number of elements
*/
size_t size ( ) const {
return m_data . size ( ) ;
}
2017-10-02 23:30:54 +02:00
/**
* @ 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_data . size ( ) = = 0 ;
}
2017-09-20 01:10:57 +02:00
/**
* @ 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 ( ) ;
}
2017-10-02 23:30:54 +02:00
/**
* @ brief Count the number of occurence of a specific element .
* @ param [ in ] _key Name of the element to count iterence
* @ return 0 No element was found
* @ return 1 One element was found
*/
size_t count ( 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 1 ;
}
}
return 0 ;
}
2017-09-20 01:10:57 +02:00
} ;
}