@ -40,291 +40,291 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
namespace stfu {
namespace stfu {
const static std : : string not_found ( " search->No such child/value " ) ;
const static std : : string not_found ( " search->No such child/value " ) ;
/*! \class node
/*! \class node
* \ brief A node in an STF tree .
* \ brief A node in an STF tree .
* \ author Maurice Bos
* \ author Maurice Bos
* \ author Nick Overdijk
* \ author Nick Overdijk
* \ version 1.0
* \ version 1.0
* \ date 2009 - 04 - 25
* \ date 2009 - 04 - 25
*
*
* When you read an STF file through a node ( with read ( ) for example ) , this node will be the root node , without a name . See the examples for more information .
* When you read an STF file through a node ( with read ( ) for example ) , this node will be the root node , without a name . See the examples for more information .
*/
*/
class node {
class node {
/** Overloaded ostream's operator<< */
/** Overloaded ostream's operator<< */
friend std : : ostream & operator < < ( std : : ostream & out , const node & root ) ;
friend std : : ostream & operator < < ( std : : ostream & out , const node & root ) ;
/** Returns whether it was succesful or not*/
/** Returns whether it was succesful or not*/
friend bool operator < < ( std : : ofstream & out , const node & root ) ;
friend bool operator < < ( std : : ofstream & out , const node & root ) ;
/** Acts like write(), but looks like this: "filename" << node */
/** Acts like write(), but looks like this: "filename" << node */
friend bool operator < < ( const char * filename , const node & root ) ;
friend bool operator < < ( const char * filename , const node & root ) ;
/** Overloaded istream's operator>> */
/** Overloaded istream's operator>> */
friend bool operator > > ( std : : istream & in , node & root ) ;
friend bool operator > > ( std : : istream & in , node & root ) ;
/** Acts like read(), but looks like this: "filename" >> node */
/** Acts like read(), but looks like this: "filename" >> node */
friend bool operator > > ( const char * filename , node & root ) ;
friend bool operator > > ( const char * filename , node & root ) ;
public :
public :
//@{
//@{
/** The values and children belonging to this node. To add, remove, do whatever: you CAN use these variables directly. To use indexing, use the member functions below*/
/** The values and children belonging to this node. To add, remove, do whatever: you CAN use these variables directly. To use indexing, use the member functions below*/
std : : multimap < std : : string , std : : string > values ;
std : : multimap < std : : string , std : : string > values ;
std : : multimap < std : : string , node > children ;
std : : multimap < std : : string , node > children ;
//@}
//@}
/**
/**
Clears the whole node recursively .
Clears the whole node recursively .
*/
*/
void clear ( ) {
void clear ( ) {
values . clear ( ) ;
values . clear ( ) ;
children . clear ( ) ;
children . clear ( ) ;
}
}
/**
/**
Gets the std : : string value from a variable
Gets the std : : string value from a variable
\ param name The name of the value you wish to retrieve
\ param name The name of the value you wish to retrieve
\ param index If there are more values with the same name , they are indexed . Here you can supply its indexnumber .
\ param index If there are more values with the same name , they are indexed . Here you can supply its indexnumber .
\ return The retrieved value
\ return The retrieved value
*/
*/
std : : string & value ( const std : : string & name , size_t index = 0 ) ;
std : : string & value ( const std : : string & name , size_t index = 0 ) ;
/**
/**
Same as value ( ) , but for unnamed values
Same as value ( ) , but for unnamed values
\ note same as value ( " " , index )
\ note same as value ( " " , index )
\ param index If there are more unnamed values , they are indexed . Here you can supply its indexnumber .
\ param index If there are more unnamed values , they are indexed . Here you can supply its indexnumber .
\ return Same as value
\ return Same as value
*/
*/
std : : string & value ( size_t index ) {
std : : string & value ( size_t index ) {
return value ( " " , index ) ;
return value ( " " , index ) ;
}
}
/**
/**
Creates and adds a value .
Creates and adds a value .
\ param name The name of the value to be created
\ param name The name of the value to be created
\ return A reference to the value of the created value .
\ return A reference to the value of the created value .
*/
*/
std : : string & addValue ( const std : : string & name = " " ) ;
std : : string & addValue ( const std : : string & name = " " ) ;
/**
/**
Const function for const objects to get a value . It ' s NOT possible to call value ( ) on constant objects for value ( ) isn ' t const .
Const function for const objects to get a value . It ' s NOT possible to call value ( ) on constant objects for value ( ) isn ' t const .
\ param name Name of the value to be retrieved
\ param name Name of the value to be retrieved
\ param index If there are > 1 values with the same name , they are indexed . Here you can supply an indexnumber .
\ param index If there are > 1 values with the same name , they are indexed . Here you can supply an indexnumber .
\ return Returns a const std : : string & to the value of value with the name and index specified
\ return Returns a const std : : string & to the value of value with the name and index specified
*/
*/
const std : : string & getValue ( const std : : string & name , size_t index ) const throw ( std : : out_of_range ) ;
const std : : string & getValue ( const std : : string & name , size_t index ) const throw ( std : : out_of_range ) ;
/**
/**
Same as getValue ( ) const , but for unnamed values
Same as getValue ( ) const , but for unnamed values
\ note same as getValue ( " " , index ) const
\ note same as getValue ( " " , index ) const
\ param index If there are > 1 unnamed values , they are indexed . Here you can supply an indexnumber .
\ param index If there are > 1 unnamed values , they are indexed . Here you can supply an indexnumber .
\ return Returns a const std : : string & to the value of value with the name and index specified
\ return Returns a const std : : string & to the value of value with the name and index specified
*/
*/
const std : : string & getValue ( size_t index ) const throw ( std : : out_of_range ) {
const std : : string & getValue ( size_t index ) const throw ( std : : out_of_range ) {
return getValue ( " " , index ) ;
return getValue ( " " , index ) ;
}
}
/**
/**
Same as getValue ( ) const , but for non - const objects . The returned std : : string & can safely be modified .
Same as getValue ( ) const , but for non - const objects . The returned std : : string & can safely be modified .
\ param name Name of the value to be retrieved
\ param name Name of the value to be retrieved
\ param index If there are > 1 values with the same name , they are indexed . Here you can supply an indexnumber .
\ param index If there are > 1 values with the same name , they are indexed . Here you can supply an indexnumber .
\ return Returns a std : : string & to the value of value with the name and index specified
\ return Returns a std : : string & to the value of value with the name and index specified
*/
*/
std : : string & getValue ( const std : : string & name , size_t index = 0 ) throw ( std : : out_of_range ) ;
std : : string & getValue ( const std : : string & name , size_t index = 0 ) throw ( std : : out_of_range ) ;
/**
/**
Same as getValue ( ) , but for unnamed values
Same as getValue ( ) , but for unnamed values
\ note same as getValue ( " " , index )
\ note same as getValue ( " " , index )
\ param index If there are > 1 unnamed values , they are indexed . Here you can supply an indexnumber .
\ param index If there are > 1 unnamed values , they are indexed . Here you can supply an indexnumber .
\ return Returns a std : : string & to the value of value with the name and index specified
\ return Returns a std : : string & to the value of value with the name and index specified
*/
*/
std : : string & getValue ( size_t index ) throw ( std : : out_of_range ) {
std : : string & getValue ( size_t index ) throw ( std : : out_of_range ) {
return getValue ( " " , index ) ;
return getValue ( " " , index ) ;
}
}
/**
/**
Removes a value . Surprise huh ?
Removes a value . Surprise huh ?
\ param name Name of the value to be removed
\ param name Name of the value to be removed
\ param index If there are > 1 values with the same name , they are indexed . Here you can supply an indexnumber .
\ param index If there are > 1 values with the same name , they are indexed . Here you can supply an indexnumber .
*/
*/
void removeValue ( const std : : string & name , size_t index = 0 ) throw ( std : : out_of_range ) ;
void removeValue ( const std : : string & name , size_t index = 0 ) throw ( std : : out_of_range ) ;
/**
/**
Removes an unnamed value .
Removes an unnamed value .
\ note same as removeValue ( " " , index ) ;
\ note same as removeValue ( " " , index ) ;
\ param index If there are > 1 unnamed values , they are indexed . Here you can supply an indexnumber .
\ param index If there are > 1 unnamed values , they are indexed . Here you can supply an indexnumber .
*/
*/
void removeValue ( size_t index ) throw ( std : : out_of_range ) {
void removeValue ( size_t index ) throw ( std : : out_of_range ) {
removeValue ( " " , index ) ;
removeValue ( " " , index ) ;
}
}
/**
/**
Renames a value .
Renames a value .
\ param oldName Name of the value to be renamed
\ param oldName Name of the value to be renamed
\ param newName The name that the oldName - value should have
\ param newName The name that the oldName - value should have
\ param index If there are > 1 values with the same name , they are indexed . Here you can supply an indexnumber .
\ param index If there are > 1 values with the same name , they are indexed . Here you can supply an indexnumber .
*/
*/
void renameValue ( const std : : string & oldName , const std : : string & newName , size_t index = 0 ) ;
void renameValue ( const std : : string & oldName , const std : : string & newName , size_t index = 0 ) ;
/**
/**
Changes , adds or retrieves node
Changes , adds or retrieves node
\ param name The name of the child you wish to retrieve , change or add .
\ param name The name of the child you wish to retrieve , change or add .
\ param index If there are > 1 children with the same name , they are indexed . Here you can supply an indexnumber .
\ param index If there are > 1 children with the same name , they are indexed . Here you can supply an indexnumber .
\ return The retrieved node
\ return The retrieved node
If this index number is > the number of variables with that name , a new variable with that name is created with index = current number of same name variables + 1.
If this index number is > the number of variables with that name , a new variable with that name is created with index = current number of same name variables + 1.
So say you have 4 variables named " tree " , you call child ( " tree " , 10 ) , another tree gets made with index 5 , NOT 10.
So say you have 4 variables named " tree " , you call child ( " tree " , 10 ) , another tree gets made with index 5 , NOT 10.
*/
*/
node & child ( const std : : string & name , size_t index = 0 ) ;
node & child ( const std : : string & name , size_t index = 0 ) ;
/**
/**
Same as child ( ) , but for unnamed children .
Same as child ( ) , but for unnamed children .
\ note same as child ( " " , index )
\ note same as child ( " " , index )
\ param index If there are > 1 unnamed children , they are indexed . Here you can supply an indexnumber .
\ param index If there are > 1 unnamed children , they are indexed . Here you can supply an indexnumber .
\ return The retrieved node
\ return The retrieved node
*/
*/
node & child ( size_t index = 0 ) {
node & child ( size_t index = 0 ) {
return child ( " " , index ) ;
return child ( " " , index ) ;
}
}
/**
/**
Guarranteed to add a child
Guarranteed to add a child
\ param name Name for the child
\ param name Name for the child
\ return A reference to the created node
\ return A reference to the created node
*/
*/
node & addChild ( const std : : string & name = " " ) ;
node & addChild ( const std : : string & name = " " ) ;
/**
/**
As addChild ( name ) , but copies data from newChild as well .
As addChild ( name ) , but copies data from newChild as well .
\ param name Name for the child
\ param name Name for the child
\ param newChild Data to copy from the child .
\ param newChild Data to copy from the child .
\ return A reference to the created node
\ return A reference to the created node
*/
*/
node & addChild ( const std : : string & name , node & newChild ) ;
node & addChild ( const std : : string & name , node & newChild ) ;
/**
/**
As addChild ( name , newChild ) , but without name , for unnamed children
As addChild ( name , newChild ) , but without name , for unnamed children
\ note same as addChild ( " " , newChild ) ;
\ note same as addChild ( " " , newChild ) ;
\ param newChild Data to copy from the child .
\ param newChild Data to copy from the child .
\ return A reference to the created node
\ return A reference to the created node
*/
*/
node & addChild ( node & newChild ) {
node & addChild ( node & newChild ) {
return addChild ( " " , newChild ) ;
return addChild ( " " , newChild ) ;
}
}
/**
/**
Const function for const objects to get a node . It ' s NOT possible to call child ( ) for this , for child ( ) isn ' t const .
Const function for const objects to get a node . It ' s NOT possible to call child ( ) for this , for child ( ) isn ' t const .
\ param name Name of the child to be retrieved
\ param name Name of the child to be retrieved
\ param index If there are > 1 children with the same name , they are indexed . Here you can supply an indexnumber .
\ param index If there are > 1 children with the same name , they are indexed . Here you can supply an indexnumber .
\ return Returns a const node & to the node with the name and index specified
\ return Returns a const node & to the node with the name and index specified
*/
*/
const node & getChild ( const std : : string & name , size_t index = 0 ) const throw ( std : : out_of_range ) ;
const node & getChild ( const std : : string & name , size_t index = 0 ) const throw ( std : : out_of_range ) ;
/**
/**
Const function for const objects to get an unnamed const node & .
Const function for const objects to get an unnamed const node & .
\ note same as getChild ( " " , index ) const ;
\ note same as getChild ( " " , index ) const ;
\ param index If there are > 1 unnamed children , they are indexed . Here you can supply an indexnumber .
\ param index If there are > 1 unnamed children , they are indexed . Here you can supply an indexnumber .
\ return Returns a const node & to the node with the name and index specified
\ return Returns a const node & to the node with the name and index specified
*/
*/
const node & getChild ( size_t index = 0 ) const throw ( std : : out_of_range ) {
const node & getChild ( size_t index = 0 ) const throw ( std : : out_of_range ) {
return getChild ( " " , index ) ;
return getChild ( " " , index ) ;
}
}
/**
/**
Same as getChild ( ) const , but for non - const objects . The returned child & can be modified
Same as getChild ( ) const , but for non - const objects . The returned child & can be modified
\ param name Name of the child to be retrieved
\ param name Name of the child to be retrieved
\ param index If there are > 1 children with the same name , they are indexed . Here you can supply an indexnumber .
\ param index If there are > 1 children with the same name , they are indexed . Here you can supply an indexnumber .
\ return Returns a node & to the node with the name and index specified
\ return Returns a node & to the node with the name and index specified
*/
*/
node & getChild ( const std : : string & name , size_t index = 0 ) throw ( std : : out_of_range ) ;
node & getChild ( const std : : string & name , size_t index = 0 ) throw ( std : : out_of_range ) ;
/**
/**
Same as getChild ( ) const , but for non - const objects .
Same as getChild ( ) const , but for non - const objects .
\ note same as getChild ( " " , index ) ;
\ note same as getChild ( " " , index ) ;
\ param index If there are > 1 unnamed children , they are indexed . Here you can supply an indexnumber .
\ param index If there are > 1 unnamed children , they are indexed . Here you can supply an indexnumber .
\ return Returns a node & to the node with the name and index specified
\ return Returns a node & to the node with the name and index specified
*/
*/
node & getChild ( size_t index = 0 ) throw ( std : : out_of_range ) {
node & getChild ( size_t index = 0 ) throw ( std : : out_of_range ) {
return getChild ( " " , index ) ;
return getChild ( " " , index ) ;
}
}
/**
/**
Removes a child . Surprise huh ?
Removes a child . Surprise huh ?
\ param name Name of the child to be removed
\ param name Name of the child to be removed
\ param index If there are > 1 children with the same name , they are indexed . Here you can supply an indexnumber .
\ param index If there are > 1 children with the same name , they are indexed . Here you can supply an indexnumber .
*/
*/
void removeChild ( const std : : string & name , size_t index = 0 ) throw ( std : : out_of_range ) ;
void removeChild ( const std : : string & name , size_t index = 0 ) throw ( std : : out_of_range ) ;
/**
/**
As removeChild ( ) for unnamed children .
As removeChild ( ) for unnamed children .
\ param index If there are > 1 unnamed children , they are indexed . Here you can supply an indexnumber .
\ param index If there are > 1 unnamed children , they are indexed . Here you can supply an indexnumber .
*/
*/
void removeChild ( size_t index = 0 ) throw ( std : : out_of_range ) {
void removeChild ( size_t index = 0 ) throw ( std : : out_of_range ) {
removeChild ( " " , index ) ;
removeChild ( " " , index ) ;
}
}
/**
/**
Renames a child .
Renames a child .
\ param oldName Name of the child to be renamed
\ param oldName Name of the child to be renamed
\ param newName The name that the oldName - child should have
\ param newName The name that the oldName - child should have
\ param index If there are > 1 children with the same name , they are indexed . Here you can supply an indexnumber .
\ param index If there are > 1 children with the same name , they are indexed . Here you can supply an indexnumber .
*/
*/
void renameChild ( const std : : string & oldName , const std : : string & newName , size_t index = 0 ) ;
void renameChild ( const std : : string & oldName , const std : : string & newName , size_t index = 0 ) ;
/**
/**
Reads the STF from an istream
Reads the STF from an istream
\ return Returns whether it was succesful
\ return Returns whether it was succesful
*/
*/
bool read ( std : : istream & in ) ;
bool read ( std : : istream & in ) ;
/**
/**
Reads the STF from a file
Reads the STF from a file
\ return Returns whether it was succesful
\ return Returns whether it was succesful
*/
*/
bool read ( const char * filename ) ;
bool read ( const char * filename ) ;
/**
/**
Writes the STF to an ostream with optional indentation
Writes the STF to an ostream with optional indentation
\ param out ostream to write to
\ param out ostream to write to
\ param depth how much indentation to start with
\ param depth how much indentation to start with
\ param indent What std : : string to use as indenation
\ param indent What std : : string to use as indenation
\ return Returns whether it was succesful
\ return Returns whether it was succesful
*/
*/
bool write ( std : : ostream & out , size_t depth = 0 , std : : string indent = " \t " ) const ;
bool write ( std : : ostream & out , size_t depth = 0 , std : : string indent = " \t " ) const ;
/**
/**
Writes to a file . Simply first opens a file and passes that ostream to itself .
Writes to a file . Simply first opens a file and passes that ostream to itself .
\ param filename File to write to
\ param filename File to write to
\ return Returns whether it was succesful
\ return Returns whether it was succesful
*/
*/
bool write ( const char * filename ) const ;
bool write ( const char * filename ) const ;
private :
private :
char streamRead ( std : : istream & in , std : : string & out , const std : : string & delim ) ;
char streamRead ( std : : istream & in , std : : string & out , const std : : string & delim ) ;
char streamRead ( std : : istream & in , std : : string & out , const char delim ) ;
char streamRead ( std : : istream & in , std : : string & out , const char delim ) ;
char streamSkip ( std : : istream & in , const std : : string & delim ) ;
char streamSkip ( std : : istream & in , const std : : string & delim ) ;
/*
/*
returns a T2 & , not a const T2 & . The functions getValue / getChild make sure this will be done correctly for const objects
returns a T2 & , not a const T2 & . The functions getValue / getChild make sure this will be done correctly for const objects
this function can NOT use get_indexed_it , because that function can ' t be const :
this function can NOT use get_indexed_it , because that function can ' t be const :
const_iterators can not be transformed into iterators , and the iterator is needed for erase ( ) , which wants an iterator .
const_iterators can not be transformed into iterators , and the iterator is needed for erase ( ) , which wants an iterator .
*/
*/
template < typename T1 , typename T2 >
template < typename T1 , typename T2 >
T2 & get_indexed ( const std : : multimap < T1 , T2 > & container , const T1 & key , size_t index = 0 ) const throw ( std : : out_of_range ) {
T2 & get_indexed ( const std : : multimap < T1 , T2 > & container , const T1 & key , size_t index = 0 ) const throw ( std : : out_of_range ) {
size_t count = container . count ( key ) ;
size_t count = container . count ( key ) ;
if ( count ! = 0 & & count - 1 > = index ) {
if ( count ! = 0 & & count - 1 > = index ) {
typename std : : multimap < T1 , T2 > : : const_iterator it = container . find ( key ) ;
typename std : : multimap < T1 , T2 > : : const_iterator it = container . find ( key ) ;
while ( index - - ) it + + ;
while ( index - - ) it + + ;
return const_cast < T2 & > ( it - > second ) ;
return const_cast < T2 & > ( it - > second ) ;
} else {
} else {
throw std : : out_of_range ( ( std : : string ) " get_indexed-> " + " Element " + key + " doesn't exist! " ) ;
throw std : : out_of_range ( ( std : : string ) " get_indexed-> " + " Element " + key + " doesn't exist! " ) ;
}
}
}
}
// template <typename T1, typename T2>
// template <typename T1, typename T2>
// typename multimap<T1, T2>::iterator get_indexed_it(multimap<T1, T2> &container, const T1 &key, size_t index = 0) throw (out_of_range) {
// typename multimap<T1, T2>::iterator get_indexed_it(multimap<T1, T2> &container, const T1 &key, size_t index = 0) throw (out_of_range) {
@ -339,21 +339,21 @@ namespace stfu {
// }
// }
// }
// }
template < typename Container , typename T >
template < typename Container , typename T >
typename Container : : iterator get_indexed_it ( Container & container , const T & key , size_t index = 0 )
typename Container : : iterator get_indexed_it ( Container & container , const T & key , size_t index = 0 )
throw ( std : : out_of_range ) {
throw ( std : : out_of_range ) {
typename Container : : iterator it = container . find ( key ) ;
typename Container : : iterator it = container . find ( key ) ;
while ( index - - & & it ! = container . end ( ) & & it - > first = = key ) it + + ;
while ( index - - & & it ! = container . end ( ) & & it - > first = = key ) it + + ;
if ( it = = container . end ( ) ) throw std : : out_of_range ( " get_indexed_it(Container&, const T&, size_t) " ) ;
if ( it = = container . end ( ) ) throw std : : out_of_range ( " get_indexed_it(Container&, const T&, size_t) " ) ;
return it ;
return it ;
}
}
} ;
} ;
typedef std : : pair < std : : string , std : : string > value ;
typedef std : : pair < std : : string , std : : string > value ;
typedef std : : pair < std : : string , node > child ;
typedef std : : pair < std : : string , node > child ;
typedef std : : multimap < std : : string , std : : string > : : iterator valueiterator ;
typedef std : : multimap < std : : string , std : : string > : : iterator valueiterator ;
typedef std : : multimap < std : : string , node > : : iterator childiterator ;
typedef std : : multimap < std : : string , node > : : iterator childiterator ;
}
}
# endif // STFU_HPP
# endif // STFU_HPP