2015-01-07 20:23:15 -05:00
/*
* DataElement / DataNode / DataTree - - structured serialization / unserialization system
* designed for the CoolMule project : )
*
Copyright ( C ) 2003 by Charles J . Cliffe
Permission is hereby granted , free of charge , to any person obtaining a copy
of this software and associated documentation files ( the " Software " ) , to deal
in the Software without restriction , including without limitation the rights
to use , copy , modify , merge , publish , distribute , sublicense , and / or sell
copies of the Software , and to permit persons to whom the Software is
furnished to do so , subject to the following conditions :
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software .
THE SOFTWARE IS PROVIDED " AS IS " , WITHOUT WARRANTY OF ANY KIND , EXPRESS OR
IMPLIED , INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY ,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT . IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM , DAMAGES OR OTHER
LIABILITY , WHETHER IN AN ACTION OF CONTRACT , TORT OR OTHERWISE , ARISING FROM ,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE .
*/
# include "DataTree.h"
# include <fstream>
# include <math.h>
/* DataElement class */
using namespace std ;
2015-01-08 18:33:37 -05:00
# define STRINGIFY(A) #A
2015-01-10 11:00:03 -05:00
DataElement : : DataElement ( ) : data_type ( DATA_NULL ) , data_val ( NULL ) , data_size ( 0 ) , unit_size ( 0 ) {
2015-01-07 20:23:15 -05:00
}
DataElement : : ~ DataElement ( ) {
2015-01-10 11:00:03 -05:00
if ( data_val ) {
2015-05-30 00:09:51 -04:00
delete [ ] data_val ;
2015-01-10 11:00:03 -05:00
data_val = NULL ;
}
2015-01-07 20:23:15 -05:00
}
void DataElement : : data_init ( long data_size_in ) {
2015-01-10 11:00:03 -05:00
if ( data_val ) {
2015-01-07 20:23:15 -05:00
delete data_val ;
2015-01-10 11:00:03 -05:00
data_val = NULL ;
}
2015-01-07 20:23:15 -05:00
data_size = data_size_in ;
2015-01-10 11:00:03 -05:00
if ( data_size ) {
data_val = new char [ data_size ] ;
}
}
char * DataElement : : getDataPointer ( ) {
return data_val ;
2015-01-07 20:23:15 -05:00
}
int DataElement : : getDataType ( ) {
return data_type ;
}
long DataElement : : getDataSize ( ) {
return data_size ;
}
2015-01-08 19:56:44 -05:00
int DataElement : : getUnitSize ( ) {
return unit_size ;
2015-01-07 20:23:15 -05:00
}
2015-01-08 19:56:44 -05:00
# define DataElementSetNumericDef(enumtype, datatype) void DataElement::set(const datatype& val_in) { \
data_type = enumtype ; \
2015-01-08 23:10:54 -05:00
unit_size = sizeof ( datatype ) ; \
2015-01-08 19:56:44 -05:00
data_init ( unit_size ) ; \
memcpy ( data_val , & val_in , data_size ) ; \
2015-01-07 20:23:15 -05:00
}
2015-01-08 19:56:44 -05:00
DataElementSetNumericDef ( DATA_CHAR , char )
DataElementSetNumericDef ( DATA_UCHAR , unsigned char )
DataElementSetNumericDef ( DATA_INT , int )
DataElementSetNumericDef ( DATA_UINT , unsigned int )
DataElementSetNumericDef ( DATA_LONG , long )
DataElementSetNumericDef ( DATA_ULONG , unsigned long )
DataElementSetNumericDef ( DATA_LONGLONG , long long )
DataElementSetNumericDef ( DATA_FLOAT , float )
DataElementSetNumericDef ( DATA_DOUBLE , double )
DataElementSetNumericDef ( DATA_LONGDOUBLE , long double )
2015-01-07 20:23:15 -05:00
void DataElement : : set ( const char * data_in , long size_in ) {
2015-01-08 19:56:44 -05:00
data_type = DATA_VOID ;
2015-01-10 11:00:03 -05:00
if ( ! data_size ) { return ; }
2015-01-07 20:23:15 -05:00
data_init ( size_in ) ;
memcpy ( data_val , data_in , data_size ) ;
}
void DataElement : : set ( const char * data_in ) {
2015-01-09 20:56:43 -05:00
data_type = DATA_STRING ;
2015-01-07 20:23:15 -05:00
data_init ( strlen ( data_in ) + 1 ) ;
memcpy ( data_val , data_in , data_size ) ;
}
void DataElement : : set ( const string & str_in ) {
data_type = DATA_STRING ;
data_init ( str_in . length ( ) + 1 ) ;
memcpy ( data_val , str_in . c_str ( ) , data_size ) ;
}
void DataElement : : set ( vector < string > & strvect_in ) {
vector < string > : : iterator i ;
long vectsize ;
long ptr ;
data_type = DATA_STR_VECTOR ;
vectsize = 0 ;
for ( i = strvect_in . begin ( ) ; i ! = strvect_in . end ( ) ; i + + ) {
vectsize + = ( * i ) . length ( ) + 1 ;
}
data_init ( vectsize ) ;
ptr = 0 ;
for ( i = strvect_in . begin ( ) ; i ! = strvect_in . end ( ) ; i + + ) {
int str_length ;
str_length = ( * i ) . length ( ) + 1 ;
memcpy ( data_val + ptr , ( * i ) . c_str ( ) , str_length ) ;
ptr + = str_length ;
}
}
void DataElement : : set ( std : : set < string > & strset_in ) {
std : : set < string > : : iterator i ;
vector < string > tmp_vect ;
for ( i = strset_in . begin ( ) ; i ! = strset_in . end ( ) ; i + + ) {
tmp_vect . push_back ( * i ) ;
}
set ( tmp_vect ) ;
}
2015-01-08 19:56:44 -05:00
# define DataElementSetNumericVectorDef(enumtype, datatype) void DataElement::set(vector<datatype>& val_in) { \
data_type = enumtype ; \
2015-01-08 23:10:54 -05:00
unit_size = sizeof ( datatype ) ; \
2015-01-08 19:56:44 -05:00
data_init ( unit_size * val_in . size ( ) ) ; \
memcpy ( data_val , & val_in [ 0 ] , data_size ) ; \
2015-01-08 18:33:37 -05:00
}
2015-01-08 19:56:44 -05:00
DataElementSetNumericVectorDef ( DATA_CHAR_VECTOR , char )
DataElementSetNumericVectorDef ( DATA_UCHAR_VECTOR , unsigned char )
DataElementSetNumericVectorDef ( DATA_INT_VECTOR , int )
DataElementSetNumericVectorDef ( DATA_UINT_VECTOR , unsigned int )
DataElementSetNumericVectorDef ( DATA_LONG_VECTOR , long )
DataElementSetNumericVectorDef ( DATA_ULONG_VECTOR , unsigned long )
DataElementSetNumericVectorDef ( DATA_LONGLONG_VECTOR , long long )
DataElementSetNumericVectorDef ( DATA_FLOAT_VECTOR , float )
DataElementSetNumericVectorDef ( DATA_DOUBLE_VECTOR , double )
DataElementSetNumericVectorDef ( DATA_LONGDOUBLE_VECTOR , long double )
2015-01-07 20:23:15 -05:00
2015-01-08 19:56:44 -05:00
# define DataElementGetNumericDef(enumtype, datatype, ...) void DataElement::get(datatype& val_out) throw (DataTypeMismatchException) { \
2015-01-08 18:33:37 -05:00
if ( ! data_type ) \
return ; \
2015-01-08 19:56:44 -05:00
int _compat [ ] = { __VA_ARGS__ } ; \
2015-01-08 18:33:37 -05:00
if ( data_type ! = enumtype ) { \
2015-01-08 19:56:44 -05:00
bool compat = false ; \
for ( int i = 0 ; i < sizeof ( _compat ) / sizeof ( int ) ; i + + ) { \
if ( _compat [ i ] = = data_type ) { \
compat = true ; \
break ; \
} \
} \
if ( ! compat ) { \
throw ( new DataTypeMismatchException ( " Type mismatch, element type " # enumtype " is not compatible with a " # datatype ) ) ; \
} \
2015-01-08 18:33:37 -05:00
if ( sizeof ( datatype ) < data_size ) { \
std : : cout < < " Warning, data type mismatch requested size for ' " < < # datatype < < " ( " < < sizeof ( datatype ) < < " )' < data size ' " < < data_size < < " '; possible loss of data. " ; \
} \
memset ( & val_out , 0 , sizeof ( datatype ) ) ; \
2015-01-09 20:56:43 -05:00
if ( sizeof ( datatype ) > 4 & & data_size < = 4 ) { \
int v = 0 ; memcpy ( & v , data_val , data_size ) ; \
val_out = ( datatype ) v ; \
return ; \
} else { \
memcpy ( & val_out , data_val , ( sizeof ( datatype ) < data_size ) ? sizeof ( datatype ) : data_size ) ; \
} \
2015-01-08 19:56:44 -05:00
return ; \
2015-01-08 18:33:37 -05:00
} \
memcpy ( & val_out , data_val , data_size ) ; \
}
2015-01-08 19:56:44 -05:00
DataElementGetNumericDef ( DATA_CHAR , char , DATA_UCHAR , DATA_UINT , DATA_ULONG , DATA_LONGLONG , DATA_LONGDOUBLE , DATA_INT , DATA_LONG )
DataElementGetNumericDef ( DATA_UCHAR , unsigned char , DATA_CHAR , DATA_UINT , DATA_ULONG , DATA_LONGLONG , DATA_LONGDOUBLE , DATA_INT , DATA_LONG )
DataElementGetNumericDef ( DATA_UINT , unsigned int , DATA_CHAR , DATA_UCHAR , DATA_ULONG , DATA_LONGLONG , DATA_LONGDOUBLE , DATA_INT , DATA_LONG )
DataElementGetNumericDef ( DATA_ULONG , unsigned long , DATA_CHAR , DATA_UCHAR , DATA_UINT , DATA_LONGLONG , DATA_LONGDOUBLE , DATA_INT , DATA_LONG )
DataElementGetNumericDef ( DATA_LONGLONG , long long , DATA_CHAR , DATA_UCHAR , DATA_UINT , DATA_ULONG , DATA_LONGDOUBLE , DATA_INT , DATA_LONG )
DataElementGetNumericDef ( DATA_LONGDOUBLE , long double , DATA_CHAR , DATA_UCHAR , DATA_UINT , DATA_ULONG , DATA_LONGLONG , DATA_INT , DATA_LONG )
DataElementGetNumericDef ( DATA_INT , int , DATA_CHAR , DATA_UCHAR , DATA_UINT , DATA_ULONG , DATA_LONGLONG , DATA_LONGDOUBLE , DATA_LONG )
DataElementGetNumericDef ( DATA_LONG , long , DATA_CHAR , DATA_UCHAR , DATA_UINT , DATA_ULONG , DATA_LONGLONG , DATA_LONGDOUBLE , DATA_INT )
2015-02-07 20:20:26 -05:00
# define DataElementGetFloatingPointDef(enumtype, datatype, ...) void DataElement::get(datatype& val_out) throw (DataTypeMismatchException) { \
if ( ! data_type ) \
return ; \
int _compat [ ] = { __VA_ARGS__ } ; \
if ( data_type ! = enumtype ) { \
bool compat = false ; \
for ( int i = 0 ; i < sizeof ( _compat ) / sizeof ( int ) ; i + + ) { \
if ( _compat [ i ] = = data_type ) { \
compat = true ; \
break ; \
} \
} \
if ( ! compat ) { \
throw ( new DataTypeMismatchException ( " Type mismatch, element type " # enumtype " is not compatible with a " # datatype ) ) ; \
} \
if ( data_type = = DATA_FLOAT | | data_type = = DATA_DOUBLE ) { \
if ( sizeof ( datatype ) < data_size ) { \
std : : cout < < " Warning, data type mismatch requested size for ' " < < # datatype < < " ( " < < sizeof ( datatype ) < < " )' < data size ' " < < data_size < < " '; possible loss of data. " ; \
} \
memset ( & val_out , 0 , sizeof ( datatype ) ) ; \
if ( sizeof ( datatype ) > 4 & & data_size < = 4 ) { \
int v = 0 ; memcpy ( & v , data_val , data_size ) ; \
val_out = ( datatype ) v ; \
return ; \
} else { \
memcpy ( & val_out , data_val , ( sizeof ( datatype ) < data_size ) ? sizeof ( datatype ) : data_size ) ; \
} \
} else { \
long long tmp_int ; \
get ( tmp_int ) ; \
datatype tmp_float = ( float ) tmp_int ; \
memcpy ( & val_out , & tmp_float , sizeof ( datatype ) ) ; \
} \
return ; \
} \
memcpy ( & val_out , data_val , data_size ) ; \
}
DataElementGetFloatingPointDef ( DATA_FLOAT , float , DATA_DOUBLE , DATA_CHAR , DATA_UCHAR , DATA_UINT , DATA_ULONG , DATA_LONGLONG , DATA_LONGDOUBLE , DATA_INT ,
2015-01-08 19:56:44 -05:00
DATA_LONG )
2015-02-07 20:20:26 -05:00
DataElementGetFloatingPointDef ( DATA_DOUBLE , double , DATA_FLOAT , DATA_CHAR , DATA_UCHAR , DATA_UINT , DATA_ULONG , DATA_LONGLONG , DATA_LONGDOUBLE , DATA_INT ,
2015-01-08 19:56:44 -05:00
DATA_LONG )
2015-01-07 20:23:15 -05:00
2015-01-08 18:33:37 -05:00
void DataElement : : get ( char * * data_in ) throw ( DataTypeMismatchException ) {
2015-01-08 19:56:44 -05:00
if ( data_type ! = DATA_VOID )
throw ( new DataTypeMismatchException ( " Type mismatch, not a CHAR* " ) ) ;
* data_in = new char [ data_size ] ;
memcpy ( * data_in , data_val , data_size ) ;
2015-01-07 20:23:15 -05:00
}
2015-01-08 18:33:37 -05:00
void DataElement : : get ( string & str_in ) throw ( DataTypeMismatchException ) {
2015-01-08 19:56:44 -05:00
if ( ! data_type )
return ;
2015-01-07 20:23:15 -05:00
2015-01-08 19:56:44 -05:00
if ( data_type ! = DATA_STRING )
throw ( new DataTypeMismatchException ( " Type mismatch, not a STRING " ) ) ;
2015-01-07 20:23:15 -05:00
2015-01-08 19:56:44 -05:00
if ( ! str_in . empty ( ) ) // flush the string
{
str_in . erase ( str_in . begin ( ) , str_in . end ( ) ) ;
}
2015-01-07 20:23:15 -05:00
2015-01-10 11:00:03 -05:00
if ( data_val ) {
str_in . append ( data_val ) ;
}
2015-01-07 20:23:15 -05:00
}
2015-01-08 18:33:37 -05:00
void DataElement : : get ( vector < string > & strvect_in ) throw ( DataTypeMismatchException ) {
2015-01-08 19:56:44 -05:00
long ptr ;
if ( ! data_type )
return ;
2015-01-07 20:23:15 -05:00
2015-01-08 19:56:44 -05:00
if ( data_type ! = DATA_STR_VECTOR )
throw ( new DataTypeMismatchException ( " Type mismatch, not a STRING VECTOR " ) ) ;
2015-01-07 20:23:15 -05:00
2015-01-08 19:56:44 -05:00
ptr = 0 ;
2015-01-07 20:23:15 -05:00
2015-01-08 19:56:44 -05:00
while ( ptr ! = data_size ) {
strvect_in . push_back ( string ( data_val + ptr ) ) ;
ptr + = strlen ( data_val + ptr ) + 1 ;
}
2015-01-07 20:23:15 -05:00
}
2015-01-08 18:33:37 -05:00
void DataElement : : get ( std : : set < string > & strset_in ) throw ( DataTypeMismatchException ) {
2015-01-08 19:56:44 -05:00
if ( ! data_type )
return ;
2015-01-07 20:23:15 -05:00
2015-01-08 19:56:44 -05:00
if ( data_type ! = DATA_STR_VECTOR )
throw ( new DataTypeMismatchException ( " Type mismatch, not a STRING VECTOR/SET " ) ) ;
2015-01-07 20:23:15 -05:00
2015-01-08 19:56:44 -05:00
std : : vector < string > tmp_vect ;
std : : vector < string > : : iterator i ;
2015-01-07 20:23:15 -05:00
2015-01-08 19:56:44 -05:00
get ( tmp_vect ) ;
2015-01-07 20:23:15 -05:00
2015-01-08 19:56:44 -05:00
for ( i = tmp_vect . begin ( ) ; i ! = tmp_vect . end ( ) ; i + + ) {
strset_in . insert ( * i ) ;
}
2015-01-07 20:23:15 -05:00
}
2015-01-08 19:56:44 -05:00
# define DataElementGetNumericVectorDef(enumtype, datatype, ...) void DataElement::get(vector<datatype>& val_out) throw (DataTypeMismatchException) { \
if ( ! data_type | | ! unit_size ) return ; \
if ( data_type ! = enumtype ) { \
int _compat [ ] = { __VA_ARGS__ } ; \
bool compat = false ; \
for ( int i = 0 ; i < sizeof ( _compat ) / sizeof ( int ) ; i + + ) { \
if ( _compat [ i ] = = data_type ) { \
compat = true ; \
break ; \
} \
} \
if ( ! compat ) { \
throw ( new DataTypeMismatchException ( " Type mismatch, element type is not compatible with a " # datatype ) ) ; \
} \
if ( sizeof ( datatype ) < unit_size ) { \
std : : cout < < " Warning, data type mismatch for vector< " # datatype " >; " # datatype " size " < < sizeof ( datatype ) < < " is less than unit size " < < unit_size < < " ; possible loss of data. " ; \
} \
datatype temp_val ; \
long ptr = 0 ; \
while ( ptr < data_size ) { \
temp_val = 0 ; \
memcpy ( & temp_val , data_val + ptr , ( unit_size > sizeof ( datatype ) ) ? sizeof ( datatype ) : unit_size ) ; \
val_out . push_back ( temp_val ) ; \
ptr + = unit_size ; \
} \
return ; \
} \
val_out . assign ( data_val , data_val + ( data_size / sizeof ( datatype ) ) ) ; \
}
DataElementGetNumericVectorDef ( DATA_CHAR_VECTOR , char , DATA_UCHAR_VECTOR , DATA_INT_VECTOR , DATA_UINT_VECTOR , DATA_LONG_VECTOR , DATA_ULONG_VECTOR ,
DATA_LONGLONG_VECTOR ) ;
DataElementGetNumericVectorDef ( DATA_UCHAR_VECTOR , unsigned char , DATA_CHAR_VECTOR , DATA_INT_VECTOR , DATA_UINT_VECTOR , DATA_LONG_VECTOR ,
DATA_ULONG_VECTOR , DATA_LONGLONG_VECTOR ) ;
DataElementGetNumericVectorDef ( DATA_INT_VECTOR , int , DATA_CHAR_VECTOR , DATA_UCHAR_VECTOR , DATA_UINT_VECTOR , DATA_LONG_VECTOR , DATA_ULONG_VECTOR ,
DATA_LONGLONG_VECTOR ) ;
DataElementGetNumericVectorDef ( DATA_UINT_VECTOR , unsigned int , DATA_CHAR_VECTOR , DATA_UCHAR_VECTOR , DATA_INT_VECTOR , DATA_LONG_VECTOR ,
DATA_ULONG_VECTOR , DATA_LONGLONG_VECTOR ) ;
DataElementGetNumericVectorDef ( DATA_LONG_VECTOR , long , DATA_CHAR_VECTOR , DATA_UCHAR_VECTOR , DATA_INT_VECTOR , DATA_UINT_VECTOR , DATA_ULONG_VECTOR ,
DATA_LONGLONG_VECTOR ) ;
DataElementGetNumericVectorDef ( DATA_ULONG_VECTOR , unsigned long , DATA_CHAR_VECTOR , DATA_UCHAR_VECTOR , DATA_INT_VECTOR , DATA_UINT_VECTOR ,
DATA_LONG_VECTOR , DATA_LONGLONG_VECTOR ) ;
DataElementGetNumericVectorDef ( DATA_LONGLONG_VECTOR , long long , DATA_CHAR_VECTOR , DATA_UCHAR_VECTOR , DATA_INT_VECTOR , DATA_UINT_VECTOR ,
DATA_LONG_VECTOR , DATA_ULONG_VECTOR ) ;
DataElementGetNumericVectorDef ( DATA_FLOAT_VECTOR , float , DATA_DOUBLE_VECTOR , DATA_LONGDOUBLE_VECTOR ) ;
DataElementGetNumericVectorDef ( DATA_DOUBLE_VECTOR , double , DATA_FLOAT_VECTOR , DATA_LONGDOUBLE_VECTOR ) ;
DataElementGetNumericVectorDef ( DATA_LONGDOUBLE_VECTOR , long double , DATA_DOUBLE_VECTOR , DATA_FLOAT_VECTOR ) ;
2015-01-07 20:23:15 -05:00
2015-01-08 18:33:37 -05:00
long DataElement : : getSerializedSize ( ) {
2015-01-09 20:56:43 -05:00
return sizeof ( int ) + sizeof ( long ) + data_size ;
2015-01-07 20:23:15 -05:00
}
2015-01-08 18:33:37 -05:00
long DataElement : : getSerialized ( char * * ser_str ) {
2015-01-08 19:56:44 -05:00
long ser_size = getSerializedSize ( ) ;
2015-01-07 20:23:15 -05:00
2015-01-08 19:56:44 -05:00
* ser_str = new char [ ser_size ] ;
2015-01-08 18:33:37 -05:00
2015-01-08 19:56:44 -05:00
char * ser_pointer ;
2015-01-08 18:33:37 -05:00
2015-01-08 19:56:44 -05:00
ser_pointer = * ser_str ;
2015-01-08 18:33:37 -05:00
2015-01-09 20:56:43 -05:00
memcpy ( ser_pointer , & data_type , sizeof ( int ) ) ;
ser_pointer + = sizeof ( int ) ;
memcpy ( ser_pointer , & data_size , sizeof ( long ) ) ;
ser_pointer + = sizeof ( long ) ;
2015-01-08 19:56:44 -05:00
memcpy ( ser_pointer , data_val , data_size ) ;
2015-01-08 18:33:37 -05:00
2015-01-08 19:56:44 -05:00
return ser_size ;
2015-01-07 20:23:15 -05:00
}
void DataElement : : setSerialized ( char * ser_str ) {
2015-01-08 19:56:44 -05:00
char * ser_pointer = ser_str ;
2015-01-07 20:23:15 -05:00
2015-01-08 19:56:44 -05:00
memcpy ( & data_type , ser_pointer , sizeof ( unsigned char ) ) ;
ser_pointer + = sizeof ( unsigned char ) ;
memcpy ( & data_size , ser_pointer , sizeof ( unsigned int ) ) ;
ser_pointer + = sizeof ( unsigned int ) ;
2015-01-07 20:23:15 -05:00
2015-01-08 19:56:44 -05:00
data_init ( data_size ) ;
memcpy ( data_val , ser_pointer , data_size ) ;
2015-01-07 20:23:15 -05:00
}
/* DataNode class */
2015-01-10 11:00:03 -05:00
DataNode : : DataNode ( ) : ptr ( 0 ) , parentNode ( NULL ) {
data_elem = new DataElement ( ) ;
2015-01-07 20:23:15 -05:00
}
2015-01-10 11:00:03 -05:00
DataNode : : DataNode ( const char * name_in ) : ptr ( 0 ) , parentNode ( NULL ) {
2015-01-08 19:56:44 -05:00
node_name = name_in ;
2015-01-10 11:00:03 -05:00
data_elem = new DataElement ( ) ;
2015-01-07 20:23:15 -05:00
}
DataNode : : ~ DataNode ( ) {
2015-01-10 11:00:03 -05:00
while ( children . size ( ) ) {
DataNode * del = children . back ( ) ;
children . pop_back ( ) ;
delete del ;
}
if ( data_elem ) {
delete data_elem ;
2015-01-08 19:56:44 -05:00
}
2015-01-07 20:23:15 -05:00
}
void DataNode : : setName ( const char * name_in ) {
2015-01-08 19:56:44 -05:00
node_name = name_in ;
2015-01-07 20:23:15 -05:00
}
2015-01-09 20:56:43 -05:00
DataElement * DataNode : : element ( ) {
2015-01-10 11:00:03 -05:00
return data_elem ;
2015-01-07 20:23:15 -05:00
}
2015-01-09 20:56:43 -05:00
DataNode * DataNode : : newChild ( const char * name_in ) {
2015-01-08 19:56:44 -05:00
children . push_back ( new DataNode ( name_in ) ) ;
childmap [ name_in ] . push_back ( children . back ( ) ) ;
2015-01-07 20:23:15 -05:00
2015-01-08 19:56:44 -05:00
children . back ( ) - > setParentNode ( * this ) ;
2015-01-07 20:23:15 -05:00
2015-01-09 20:56:43 -05:00
return children . back ( ) ;
2015-01-07 20:23:15 -05:00
}
2015-01-09 20:56:43 -05:00
DataNode * DataNode : : child ( const char * name_in , int index ) throw ( DataInvalidChildException ) {
2015-01-08 19:56:44 -05:00
DataNode * child_ret ;
2015-01-07 20:23:15 -05:00
2015-01-08 19:56:44 -05:00
child_ret = childmap [ name_in ] [ index ] ;
2015-01-07 20:23:15 -05:00
2015-01-08 19:56:44 -05:00
if ( ! child_ret ) {
stringstream error_str ;
error_str < < " no child ' " < < index < < " ' in DataNode ' " < < node_name < < " ' " ;
throw ( DataInvalidChildException ( error_str . str ( ) . c_str ( ) ) ) ;
}
2015-01-07 20:23:15 -05:00
2015-01-09 20:56:43 -05:00
return child_ret ;
2015-01-07 20:23:15 -05:00
}
2015-01-09 20:56:43 -05:00
DataNode * DataNode : : child ( int index ) throw ( DataInvalidChildException ) {
2015-01-07 20:23:15 -05:00
2015-01-08 19:56:44 -05:00
DataNode * child_ret ;
2015-01-07 20:23:15 -05:00
2015-01-08 19:56:44 -05:00
child_ret = children [ index ] ;
2015-01-07 20:23:15 -05:00
2015-01-08 19:56:44 -05:00
if ( ! child_ret ) {
stringstream error_str ;
error_str < < " no child ' " < < index < < " ' in DataNode ' " < < node_name < < " ' " ;
throw ( DataInvalidChildException ( error_str . str ( ) . c_str ( ) ) ) ;
}
2015-01-07 20:23:15 -05:00
2015-01-09 20:56:43 -05:00
return child_ret ;
2015-01-07 20:23:15 -05:00
}
int DataNode : : numChildren ( ) {
2015-01-08 19:56:44 -05:00
return children . size ( ) ;
2015-01-07 20:23:15 -05:00
}
int DataNode : : numChildren ( const char * name_in ) {
2015-01-08 19:56:44 -05:00
return childmap [ name_in ] . size ( ) ;
2015-01-07 20:23:15 -05:00
}
bool DataNode : : hasAnother ( ) {
2015-01-08 19:56:44 -05:00
return children . size ( ) ! = ptr ;
2015-01-07 20:23:15 -05:00
}
bool DataNode : : hasAnother ( const char * name_in ) {
2015-01-08 19:56:44 -05:00
return childmap [ name_in ] . size ( ) ! = childmap_ptr [ name_in ] ;
2015-01-07 20:23:15 -05:00
}
2015-01-09 20:56:43 -05:00
DataNode * DataNode : : getNext ( ) throw ( DataInvalidChildException ) {
2015-01-08 19:56:44 -05:00
return child ( ptr + + ) ;
2015-01-07 20:23:15 -05:00
}
2015-01-09 20:56:43 -05:00
DataNode * DataNode : : getNext ( const char * name_in ) throw ( DataInvalidChildException ) {
2015-01-08 19:56:44 -05:00
return child ( name_in , childmap_ptr [ name_in ] + + ) ;
2015-01-07 20:23:15 -05:00
}
void DataNode : : rewind ( ) {
2015-01-08 19:56:44 -05:00
ptr = 0 ;
2015-01-07 20:23:15 -05:00
}
void DataNode : : rewind ( const char * name_in ) {
2015-01-08 19:56:44 -05:00
childmap_ptr [ name_in ] = 0 ;
2015-01-07 20:23:15 -05:00
}
/* DataTree class */
DataTree : : DataTree ( const char * name_in ) {
2015-01-08 19:56:44 -05:00
dn_root . setName ( name_in ) ;
2015-01-07 20:23:15 -05:00
}
DataTree : : DataTree ( ) {
}
DataTree : : ~ DataTree ( ) {
}
;
2015-01-09 20:56:43 -05:00
DataNode * DataTree : : rootNode ( ) {
return & dn_root ;
2015-01-07 20:23:15 -05:00
}
std : : string trim ( std : : string & s , const std : : string & drop = " " ) {
2015-01-08 19:56:44 -05:00
std : : string r = s . erase ( s . find_last_not_of ( drop ) + 1 ) ;
return r . erase ( 0 , r . find_first_not_of ( drop ) ) ;
2015-01-07 20:23:15 -05:00
}
void DataTree : : decodeXMLText ( DataNode * elem , const char * src_text , DT_FloatingPointPolicy fpp ) {
2015-01-08 19:56:44 -05:00
int tmp_char ;
int tmp_int ;
long tmp_long ;
long long tmp_llong ;
double tmp_double ;
float tmp_float ;
string tmp_str ;
string tmp_str2 ;
std : : stringstream tmp_stream ;
std : : stringstream tmp_stream2 ;
vector < char > tmp_charvect ;
vector < int > tmp_intvect ;
vector < long > tmp_longvect ;
vector < long > tmp_llongvect ;
vector < long > : : iterator tmp_llongvect_i ;
vector < double > tmp_doublevect ;
vector < double > : : iterator tmp_doublevect_i ;
vector < float > tmp_floatvect ;
bool vChars = false ;
bool vInts = false ;
bool vLongs = false ;
string in_text = src_text ;
trim ( in_text ) ;
trim ( in_text , " \r \n " ) ;
tmp_stream . str ( " " ) ;
tmp_stream2 . str ( " " ) ;
if ( in_text . find_first_not_of ( " 0123456789- " ) = = string : : npos ) {
tmp_stream < < in_text ;
tmp_stream > > tmp_llong ;
2015-01-07 20:23:15 -05:00
2015-01-09 20:56:43 -05:00
tmp_int = ( int ) tmp_llong ;
tmp_long = ( long ) tmp_llong ;
2015-01-07 20:23:15 -05:00
2015-01-08 19:56:44 -05:00
if ( tmp_int = = tmp_llong ) {
2015-01-09 20:56:43 -05:00
elem - > element ( ) - > set ( tmp_int ) ;
2015-01-08 19:56:44 -05:00
} else if ( tmp_long = = tmp_llong ) {
2015-01-09 20:56:43 -05:00
elem - > element ( ) - > set ( tmp_long ) ;
2015-01-08 19:56:44 -05:00
} else {
2015-01-09 20:56:43 -05:00
elem - > element ( ) - > set ( tmp_llong ) ;
2015-01-08 19:56:44 -05:00
}
} else if ( in_text . find_first_not_of ( " 0123456789.e+- " ) = = string : : npos ) {
tmp_stream < < in_text ;
2015-01-07 20:23:15 -05:00
2015-01-08 19:56:44 -05:00
if ( fpp = = USE_FLOAT ) {
tmp_stream > > tmp_float ;
2015-01-07 20:23:15 -05:00
2015-01-09 20:56:43 -05:00
elem - > element ( ) - > set ( ( float ) tmp_float ) ;
2015-01-08 19:56:44 -05:00
} else {
tmp_stream > > tmp_double ;
2015-01-07 20:23:15 -05:00
2015-01-09 20:56:43 -05:00
elem - > element ( ) - > set ( ( double ) tmp_double ) ;
2015-01-07 20:23:15 -05:00
}
2015-01-08 19:56:44 -05:00
} else if ( in_text . find_first_not_of ( " 0123456789- " ) = = string : : npos ) {
tmp_stream < < in_text ;
vChars = true ;
vInts = true ;
vLongs = true ;
while ( ! tmp_stream . eof ( ) ) {
tmp_stream > > tmp_llong ;
tmp_char = tmp_llong ;
tmp_int = tmp_llong ;
tmp_long = tmp_llong ;
if ( tmp_char ! = tmp_llong ) {
vChars = false ;
}
if ( tmp_int ! = tmp_llong ) {
vInts = false ;
}
if ( tmp_long ! = tmp_llong ) {
vLongs = false ;
}
tmp_llongvect . push_back ( ( long ) tmp_long ) ;
2015-01-08 18:33:37 -05:00
}
2015-01-07 20:23:15 -05:00
2015-01-08 19:56:44 -05:00
if ( vChars ) {
for ( tmp_llongvect_i = tmp_llongvect . begin ( ) ; tmp_llongvect_i ! = tmp_llongvect . end ( ) ; tmp_llongvect_i + + ) {
tmp_charvect . push_back ( * tmp_llongvect_i ) ;
}
tmp_llongvect . clear ( ) ;
2015-01-09 20:56:43 -05:00
elem - > element ( ) - > set ( tmp_charvect ) ;
2015-01-08 19:56:44 -05:00
tmp_charvect . clear ( ) ;
2015-01-07 20:23:15 -05:00
2015-01-08 19:56:44 -05:00
} else if ( vInts ) {
for ( tmp_llongvect_i = tmp_llongvect . begin ( ) ; tmp_llongvect_i ! = tmp_llongvect . end ( ) ; tmp_llongvect_i + + ) {
tmp_intvect . push_back ( * tmp_llongvect_i ) ;
}
tmp_llongvect . clear ( ) ;
2015-01-09 20:56:43 -05:00
elem - > element ( ) - > set ( tmp_intvect ) ;
2015-01-08 19:56:44 -05:00
tmp_intvect . clear ( ) ;
} else if ( vLongs ) {
for ( tmp_llongvect_i = tmp_llongvect . begin ( ) ; tmp_llongvect_i ! = tmp_llongvect . end ( ) ; tmp_llongvect_i + + ) {
tmp_longvect . push_back ( * tmp_llongvect_i ) ;
}
tmp_llongvect . clear ( ) ;
2015-01-09 20:56:43 -05:00
elem - > element ( ) - > set ( tmp_longvect ) ;
2015-01-08 19:56:44 -05:00
tmp_longvect . clear ( ) ;
} else {
2015-01-09 20:56:43 -05:00
elem - > element ( ) - > set ( tmp_llongvect ) ;
2015-01-08 18:33:37 -05:00
}
2015-01-08 19:56:44 -05:00
} else if ( in_text . find_first_not_of ( " 0123456789.e-+ " ) = = string : : npos ) {
tmp_stream < < in_text ;
if ( fpp = = USE_FLOAT ) {
tmp_floatvect . clear ( ) ;
} else {
tmp_doublevect . clear ( ) ;
2015-01-07 20:23:15 -05:00
}
2015-01-08 19:56:44 -05:00
while ( ! tmp_stream . eof ( ) ) {
2015-01-07 20:23:15 -05:00
2015-01-08 19:56:44 -05:00
if ( fpp = = USE_FLOAT ) {
tmp_stream > > tmp_float ;
tmp_floatvect . push_back ( tmp_float ) ;
} else {
tmp_stream > > tmp_double ;
tmp_doublevect . push_back ( tmp_double ) ;
}
}
2015-01-07 20:23:15 -05:00
if ( fpp = = USE_FLOAT ) {
2015-01-09 20:56:43 -05:00
elem - > element ( ) - > set ( tmp_floatvect ) ;
2015-01-07 20:23:15 -05:00
} else {
2015-01-09 20:56:43 -05:00
elem - > element ( ) - > set ( tmp_doublevect ) ;
2015-01-07 20:23:15 -05:00
}
} else {
2015-01-09 20:56:43 -05:00
elem - > element ( ) - > set ( src_text ) ;
2015-01-08 19:56:44 -05:00
// printf( "Unhandled DataTree XML Field: [%s]", tmp_str.c_str() );
2015-01-07 20:23:15 -05:00
}
}
void DataTree : : setFromXML ( DataNode * elem , TiXmlNode * elxml , bool root_node , DT_FloatingPointPolicy fpp ) {
2015-01-08 19:56:44 -05:00
TiXmlText * pText ;
int t = elxml - > Type ( ) ;
string tmp_str ;
2015-01-07 20:23:15 -05:00
2015-01-08 19:56:44 -05:00
switch ( t ) {
case TiXmlNode : : DOCUMENT :
// printf( "Document" );
break ;
2015-01-07 20:23:15 -05:00
2015-01-08 19:56:44 -05:00
case TiXmlNode : : ELEMENT :
if ( ! root_node )
2015-01-09 20:56:43 -05:00
elem = elem - > newChild ( elxml - > Value ( ) ) ;
2015-01-07 20:23:15 -05:00
2015-01-08 19:56:44 -05:00
const TiXmlAttribute * attribs ;
attribs = elxml - > ToElement ( ) - > FirstAttribute ( ) ;
2015-01-07 20:23:15 -05:00
2015-01-08 19:56:44 -05:00
while ( attribs ) {
2015-01-07 20:23:15 -05:00
2015-01-08 19:56:44 -05:00
// following badgerfish xml->json and xml->ruby convention for attributes..
string attrName ( " @ " ) ;
attrName . append ( attribs - > Name ( ) ) ;
2015-01-07 20:23:15 -05:00
2015-01-09 20:56:43 -05:00
decodeXMLText ( elem - > newChild ( attrName . c_str ( ) ) , attribs - > Value ( ) , fpp ) ;
2015-01-07 20:23:15 -05:00
2015-01-08 19:56:44 -05:00
attribs = attribs - > Next ( ) ;
}
2015-01-07 20:23:15 -05:00
2015-01-08 19:56:44 -05:00
// printf( "Element \"%s\"", elxml->Value());
break ;
2015-01-07 20:23:15 -05:00
2015-01-08 19:56:44 -05:00
case TiXmlNode : : COMMENT :
// printf( "Comment: \"%s\"", elxml->Value());
break ;
2015-01-07 20:23:15 -05:00
2015-01-08 19:56:44 -05:00
case TiXmlNode : : UNKNOWN :
// printf( "Unknown" );
break ;
2015-01-07 20:23:15 -05:00
2015-01-08 19:56:44 -05:00
case TiXmlNode : : TEXT :
pText = elxml - > ToText ( ) ;
2015-01-07 20:23:15 -05:00
2015-01-08 19:56:44 -05:00
decodeXMLText ( elem , pText - > Value ( ) , fpp ) ;
2015-01-07 20:23:15 -05:00
2015-01-08 19:56:44 -05:00
// pText = elxml->ToText();
// printf( "Text: [%s]", pText->Value() );
break ;
2015-01-07 20:23:15 -05:00
2015-01-08 19:56:44 -05:00
case TiXmlNode : : DECLARATION :
// printf( "Declaration" );
break ;
default :
break ;
}
2015-01-07 20:23:15 -05:00
2015-01-08 18:33:37 -05:00
// printf( "\n" );
2015-01-07 20:23:15 -05:00
2015-01-08 19:56:44 -05:00
TiXmlNode * pChild ;
2015-01-07 20:23:15 -05:00
2015-01-08 19:56:44 -05:00
if ( ! elxml - > NoChildren ( ) ) {
if ( elxml - > FirstChild ( ) - > Type ( ) = = TiXmlNode : : ELEMENT ) {
if ( elxml - > FirstChild ( ) - > Value ( ) = = TIXML_STRING ( " str " ) ) {
std : : vector < std : : string > tmp_strvect ;
2015-01-07 20:23:15 -05:00
2015-01-08 19:56:44 -05:00
for ( pChild = elxml - > FirstChild ( ) ; pChild ! = 0 ; pChild = pChild - > NextSibling ( ) ) {
if ( pChild - > Value ( ) = = TIXML_STRING ( " str " ) ) {
if ( ! pChild - > FirstChild ( ) ) {
tmp_strvect . push_back ( " " ) ;
continue ;
}
2015-01-07 20:23:15 -05:00
2015-01-08 19:56:44 -05:00
pText = pChild - > FirstChild ( ) - > ToText ( ) ;
2015-01-07 20:23:15 -05:00
2015-01-08 19:56:44 -05:00
if ( pText ) {
tmp_str = pText - > Value ( ) ;
tmp_strvect . push_back ( tmp_str ) ;
}
2015-01-07 20:23:15 -05:00
}
}
2015-01-09 20:56:43 -05:00
elem - > element ( ) - > set ( tmp_strvect ) ;
2015-01-07 20:23:15 -05:00
2015-01-08 19:56:44 -05:00
return ;
}
2015-01-07 20:23:15 -05:00
}
}
2015-01-08 19:56:44 -05:00
for ( pChild = elxml - > FirstChild ( ) ; pChild ! = 0 ; pChild = pChild - > NextSibling ( ) ) {
setFromXML ( elem , pChild , false , fpp ) ;
}
2015-01-07 20:23:15 -05:00
}
void DataTree : : nodeToXML ( DataNode * elem , TiXmlElement * elxml ) {
2015-01-08 19:56:44 -05:00
DataNode * child ;
elem - > rewind ( ) ;
while ( elem - > hasAnother ( ) ) {
2015-01-09 20:56:43 -05:00
child = elem - > getNext ( ) ;
2015-01-08 19:56:44 -05:00
std : : string nodeName = child - > getName ( ) ;
TiXmlElement * element ;
element = new TiXmlElement ( nodeName . length ( ) ? nodeName . c_str ( ) : " node " ) ;
std : : string tmp ;
std : : stringstream tmp_stream ;
TiXmlText * text ;
std : : vector < float > tmp_floatvect ;
std : : vector < float > : : iterator tmp_floatvect_i ;
std : : vector < double > tmp_doublevect ;
std : : vector < double > : : iterator tmp_doublevect_i ;
std : : vector < int > tmp_intvect ;
std : : vector < int > : : iterator tmp_intvect_i ;
std : : vector < char > tmp_charvect ;
std : : vector < char > : : iterator tmp_charvect_i ;
std : : vector < unsigned char > tmp_ucharvect ;
std : : vector < unsigned char > : : iterator tmp_ucharvect_i ;
std : : vector < unsigned int > tmp_uintvect ;
std : : vector < unsigned int > : : iterator tmp_uintvect_i ;
std : : vector < long > tmp_longvect ;
std : : vector < long > : : iterator tmp_longvect_i ;
std : : vector < unsigned long > tmp_ulongvect ;
std : : vector < unsigned long > : : iterator tmp_ulongvect_i ;
std : : vector < long long > tmp_llongvect ;
std : : vector < long long > : : iterator tmp_llongvect_i ;
std : : vector < unsigned long long > tmp_ullongvect ;
std : : vector < unsigned long long > : : iterator tmp_ullongvect_i ;
std : : vector < string > tmp_stringvect ;
std : : vector < string > : : iterator tmp_stringvect_i ;
TiXmlElement * tmp_node ;
char * tmp_pstr ;
double tmp_double ;
long double tmp_ldouble ;
float tmp_float ;
char tmp_char ;
unsigned char tmp_uchar ;
int tmp_int ;
unsigned int tmp_uint ;
long tmp_long ;
unsigned long tmp_ulong ;
long long tmp_llong ;
2015-01-09 20:56:43 -05:00
switch ( child - > element ( ) - > getDataType ( ) ) {
2015-01-08 19:56:44 -05:00
case DATA_NULL :
break ;
case DATA_VOID :
2015-01-09 20:56:43 -05:00
child - > element ( ) - > get ( & tmp_pstr ) ;
2015-01-08 19:56:44 -05:00
// following badgerfish xml->json and xml->ruby convention for attributes..
if ( nodeName . substr ( 0 , 1 ) = = string ( " @ " ) ) {
elxml - > SetAttribute ( nodeName . substr ( 1 ) . c_str ( ) , tmp_pstr ) ;
delete element ;
element = NULL ;
} else {
text = new TiXmlText ( tmp_pstr ) ;
element - > LinkEndChild ( text ) ;
}
delete tmp_pstr ;
break ;
case DATA_CHAR :
2015-01-09 20:56:43 -05:00
child - > element ( ) - > get ( tmp_char ) ;
2015-01-07 20:23:15 -05:00
2015-01-08 19:56:44 -05:00
tmp_stream . str ( " " ) ;
2015-01-07 20:23:15 -05:00
2015-01-08 19:56:44 -05:00
tmp_stream < < tmp_char ;
2015-01-07 20:23:15 -05:00
2015-01-08 19:56:44 -05:00
text = new TiXmlText ( tmp_stream . str ( ) . c_str ( ) ) ;
2015-01-07 20:23:15 -05:00
element - > LinkEndChild ( text ) ;
2015-01-08 19:56:44 -05:00
break ;
case DATA_UCHAR :
2015-01-09 20:56:43 -05:00
child - > element ( ) - > get ( tmp_uchar ) ;
2015-01-07 20:23:15 -05:00
2015-01-08 19:56:44 -05:00
tmp_stream . str ( " " ) ;
2015-01-07 20:23:15 -05:00
2015-01-08 19:56:44 -05:00
tmp_stream < < tmp_uchar ;
2015-01-07 20:23:15 -05:00
2015-01-08 19:56:44 -05:00
text = new TiXmlText ( tmp_stream . str ( ) . c_str ( ) ) ;
element - > LinkEndChild ( text ) ;
break ;
case DATA_INT :
2015-01-09 20:56:43 -05:00
child - > element ( ) - > get ( tmp_int ) ;
2015-01-07 20:23:15 -05:00
2015-01-08 19:56:44 -05:00
tmp_stream . str ( " " ) ;
2015-01-07 20:23:15 -05:00
2015-01-08 19:56:44 -05:00
tmp_stream < < tmp_int ;
2015-01-07 20:23:15 -05:00
2015-01-08 19:56:44 -05:00
text = new TiXmlText ( tmp_stream . str ( ) . c_str ( ) ) ;
element - > LinkEndChild ( text ) ;
break ;
case DATA_UINT :
2015-01-09 20:56:43 -05:00
child - > element ( ) - > get ( tmp_uint ) ;
2015-01-07 20:23:15 -05:00
2015-01-08 19:56:44 -05:00
tmp_stream . str ( " " ) ;
2015-01-07 20:23:15 -05:00
2015-01-08 19:56:44 -05:00
tmp_stream < < tmp_uint ;
2015-01-07 20:23:15 -05:00
2015-01-08 19:56:44 -05:00
text = new TiXmlText ( tmp_stream . str ( ) . c_str ( ) ) ;
element - > LinkEndChild ( text ) ;
break ;
case DATA_LONG :
2015-01-09 20:56:43 -05:00
child - > element ( ) - > get ( tmp_long ) ;
2015-01-07 20:23:15 -05:00
2015-01-08 19:56:44 -05:00
tmp_stream . str ( " " ) ;
2015-01-07 20:23:15 -05:00
2015-01-08 19:56:44 -05:00
tmp_stream < < tmp_long ;
2015-01-07 20:23:15 -05:00
2015-01-08 19:56:44 -05:00
text = new TiXmlText ( tmp_stream . str ( ) . c_str ( ) ) ;
element - > LinkEndChild ( text ) ;
break ;
case DATA_ULONG :
2015-01-09 20:56:43 -05:00
child - > element ( ) - > get ( tmp_ulong ) ;
2015-01-07 20:23:15 -05:00
2015-01-08 19:56:44 -05:00
tmp_stream . str ( " " ) ;
2015-01-07 20:23:15 -05:00
2015-01-08 19:56:44 -05:00
tmp_stream < < tmp_ulong ;
2015-01-07 20:23:15 -05:00
2015-01-08 19:56:44 -05:00
text = new TiXmlText ( tmp_stream . str ( ) . c_str ( ) ) ;
element - > LinkEndChild ( text ) ;
break ;
case DATA_LONGLONG :
2015-01-09 20:56:43 -05:00
child - > element ( ) - > get ( tmp_llong ) ;
2015-01-07 20:23:15 -05:00
2015-01-08 19:56:44 -05:00
tmp_stream . str ( " " ) ;
2015-01-07 20:23:15 -05:00
2015-01-08 19:56:44 -05:00
tmp_stream < < tmp_llong ;
2015-01-07 20:23:15 -05:00
2015-01-08 19:56:44 -05:00
text = new TiXmlText ( tmp_stream . str ( ) . c_str ( ) ) ;
element - > LinkEndChild ( text ) ;
break ;
case DATA_FLOAT :
2015-01-09 20:56:43 -05:00
child - > element ( ) - > get ( tmp_float ) ;
2015-01-07 20:23:15 -05:00
2015-01-08 19:56:44 -05:00
tmp_stream . str ( " " ) ;
2015-01-07 20:23:15 -05:00
2015-01-08 19:56:44 -05:00
tmp_stream < < tmp_float ;
2015-01-07 20:23:15 -05:00
2015-01-08 19:56:44 -05:00
text = new TiXmlText ( tmp_stream . str ( ) . c_str ( ) ) ;
element - > LinkEndChild ( text ) ;
break ;
case DATA_DOUBLE :
2015-01-09 20:56:43 -05:00
child - > element ( ) - > get ( tmp_double ) ;
2015-01-07 20:23:15 -05:00
2015-01-08 19:56:44 -05:00
tmp_stream . str ( " " ) ;
2015-01-07 20:23:15 -05:00
2015-01-08 19:56:44 -05:00
tmp_stream < < tmp_double ;
2015-01-07 20:23:15 -05:00
2015-01-08 19:56:44 -05:00
text = new TiXmlText ( tmp_stream . str ( ) . c_str ( ) ) ;
element - > LinkEndChild ( text ) ;
break ;
case DATA_LONGDOUBLE :
2015-01-09 20:56:43 -05:00
child - > element ( ) - > get ( tmp_ldouble ) ;
2015-01-07 20:23:15 -05:00
2015-01-08 19:56:44 -05:00
tmp_stream . str ( " " ) ;
2015-01-07 20:23:15 -05:00
2015-01-08 19:56:44 -05:00
tmp_stream < < tmp_ldouble ;
2015-01-07 20:23:15 -05:00
2015-01-08 19:56:44 -05:00
text = new TiXmlText ( tmp_stream . str ( ) . c_str ( ) ) ;
2015-01-07 20:23:15 -05:00
element - > LinkEndChild ( text ) ;
2015-01-08 19:56:44 -05:00
break ;
case DATA_STRING :
2015-01-09 20:56:43 -05:00
child - > element ( ) - > get ( tmp ) ;
2015-01-08 19:56:44 -05:00
if ( nodeName . substr ( 0 , 1 ) = = string ( " @ " ) ) {
elxml - > SetAttribute ( nodeName . substr ( 1 ) . c_str ( ) , tmp . c_str ( ) ) ;
delete element ;
element = NULL ;
} else {
text = new TiXmlText ( tmp . c_str ( ) ) ;
element - > LinkEndChild ( text ) ;
}
break ;
2015-01-07 20:23:15 -05:00
2015-01-08 19:56:44 -05:00
case DATA_STR_VECTOR :
2015-01-09 20:56:43 -05:00
child - > element ( ) - > get ( tmp_stringvect ) ;
2015-01-07 20:23:15 -05:00
2015-01-08 19:56:44 -05:00
tmp_stream . str ( " " ) ;
2015-01-07 20:23:15 -05:00
2015-01-08 19:56:44 -05:00
for ( tmp_stringvect_i = tmp_stringvect . begin ( ) ; tmp_stringvect_i ! = tmp_stringvect . end ( ) ; tmp_stringvect_i + + ) {
tmp_node = new TiXmlElement ( " str " ) ;
text = new TiXmlText ( ( * tmp_stringvect_i ) . c_str ( ) ) ;
tmp_node - > LinkEndChild ( text ) ;
element - > LinkEndChild ( tmp_node ) ;
}
2015-01-07 20:23:15 -05:00
2015-01-08 19:56:44 -05:00
tmp_stringvect . clear ( ) ;
break ;
case DATA_CHAR_VECTOR :
2015-01-09 20:56:43 -05:00
child - > element ( ) - > get ( tmp_charvect ) ;
2015-01-07 20:23:15 -05:00
2015-01-08 19:56:44 -05:00
tmp_stream . str ( " " ) ;
2015-01-07 20:23:15 -05:00
2015-01-08 19:56:44 -05:00
for ( tmp_charvect_i = tmp_charvect . begin ( ) ; tmp_charvect_i ! = tmp_charvect . end ( ) ; tmp_charvect_i + + ) {
tmp_stream < < ( * tmp_charvect_i ) ;
if ( tmp_charvect_i ! = tmp_charvect . end ( ) - 1 )
tmp_stream < < " " ;
}
2015-01-07 20:23:15 -05:00
2015-01-08 19:56:44 -05:00
text = new TiXmlText ( tmp_stream . str ( ) . c_str ( ) ) ;
element - > LinkEndChild ( text ) ;
tmp_charvect . clear ( ) ;
break ;
case DATA_UCHAR_VECTOR :
2015-01-09 20:56:43 -05:00
child - > element ( ) - > get ( tmp_ucharvect ) ;
2015-01-07 20:23:15 -05:00
2015-01-08 19:56:44 -05:00
tmp_stream . str ( " " ) ;
2015-01-07 20:23:15 -05:00
2015-01-08 19:56:44 -05:00
for ( tmp_ucharvect_i = tmp_ucharvect . begin ( ) ; tmp_ucharvect_i ! = tmp_ucharvect . end ( ) ; tmp_ucharvect_i + + ) {
tmp_stream < < ( * tmp_ucharvect_i ) ;
if ( tmp_ucharvect_i ! = tmp_ucharvect . end ( ) - 1 )
tmp_stream < < " " ;
}
2015-01-07 20:23:15 -05:00
2015-01-08 19:56:44 -05:00
text = new TiXmlText ( tmp_stream . str ( ) . c_str ( ) ) ;
element - > LinkEndChild ( text ) ;
tmp_ucharvect . clear ( ) ;
break ;
case DATA_INT_VECTOR :
2015-01-09 20:56:43 -05:00
child - > element ( ) - > get ( tmp_intvect ) ;
2015-01-07 20:23:15 -05:00
2015-01-08 19:56:44 -05:00
tmp_stream . str ( " " ) ;
2015-01-07 20:23:15 -05:00
2015-01-08 19:56:44 -05:00
for ( tmp_intvect_i = tmp_intvect . begin ( ) ; tmp_intvect_i ! = tmp_intvect . end ( ) ; tmp_intvect_i + + ) {
tmp_stream < < ( * tmp_intvect_i ) ;
if ( tmp_intvect_i ! = tmp_intvect . end ( ) - 1 )
tmp_stream < < " " ;
}
2015-01-07 20:23:15 -05:00
2015-01-08 19:56:44 -05:00
text = new TiXmlText ( tmp_stream . str ( ) . c_str ( ) ) ;
element - > LinkEndChild ( text ) ;
tmp_intvect . clear ( ) ;
break ;
case DATA_UINT_VECTOR :
2015-01-09 20:56:43 -05:00
child - > element ( ) - > get ( tmp_uintvect ) ;
2015-01-07 20:23:15 -05:00
2015-01-08 19:56:44 -05:00
tmp_stream . str ( " " ) ;
2015-01-07 20:23:15 -05:00
2015-01-08 19:56:44 -05:00
for ( tmp_uintvect_i = tmp_uintvect . begin ( ) ; tmp_uintvect_i ! = tmp_uintvect . end ( ) ; tmp_uintvect_i + + ) {
tmp_stream < < ( * tmp_intvect_i ) ;
if ( tmp_uintvect_i ! = tmp_uintvect . end ( ) - 1 )
tmp_stream < < " " ;
}
2015-01-07 20:23:15 -05:00
2015-01-08 19:56:44 -05:00
text = new TiXmlText ( tmp_stream . str ( ) . c_str ( ) ) ;
element - > LinkEndChild ( text ) ;
tmp_uintvect . clear ( ) ;
break ;
case DATA_LONG_VECTOR :
2015-01-09 20:56:43 -05:00
child - > element ( ) - > get ( tmp_longvect ) ;
2015-01-07 20:23:15 -05:00
2015-01-08 19:56:44 -05:00
tmp_stream . str ( " " ) ;
2015-01-07 20:23:15 -05:00
2015-01-08 19:56:44 -05:00
for ( tmp_longvect_i = tmp_longvect . begin ( ) ; tmp_longvect_i ! = tmp_longvect . end ( ) ; tmp_longvect_i + + ) {
tmp_stream < < ( * tmp_longvect_i ) ;
if ( tmp_longvect_i ! = tmp_longvect . end ( ) - 1 )
tmp_stream < < " " ;
}
2015-01-07 20:23:15 -05:00
2015-01-08 19:56:44 -05:00
text = new TiXmlText ( tmp_stream . str ( ) . c_str ( ) ) ;
element - > LinkEndChild ( text ) ;
tmp_longvect . clear ( ) ;
break ;
case DATA_ULONG_VECTOR :
2015-01-09 20:56:43 -05:00
child - > element ( ) - > get ( tmp_ulongvect ) ;
2015-01-07 20:23:15 -05:00
2015-01-08 19:56:44 -05:00
tmp_stream . str ( " " ) ;
2015-01-07 20:23:15 -05:00
2015-01-08 19:56:44 -05:00
for ( tmp_ulongvect_i = tmp_ulongvect . begin ( ) ; tmp_ulongvect_i ! = tmp_ulongvect . end ( ) ; tmp_ulongvect_i + + ) {
tmp_stream < < ( * tmp_ulongvect_i ) ;
if ( tmp_ulongvect_i ! = tmp_ulongvect . end ( ) - 1 )
tmp_stream < < " " ;
}
2015-01-07 20:23:15 -05:00
2015-01-08 19:56:44 -05:00
text = new TiXmlText ( tmp_stream . str ( ) . c_str ( ) ) ;
element - > LinkEndChild ( text ) ;
tmp_ulongvect . clear ( ) ;
break ;
case DATA_LONGLONG_VECTOR :
2015-01-09 20:56:43 -05:00
child - > element ( ) - > get ( tmp_llongvect ) ;
2015-01-07 20:23:15 -05:00
2015-01-08 19:56:44 -05:00
tmp_stream . str ( " " ) ;
2015-01-07 20:23:15 -05:00
2015-01-08 19:56:44 -05:00
for ( tmp_llongvect_i = tmp_llongvect . begin ( ) ; tmp_llongvect_i ! = tmp_llongvect . end ( ) ; tmp_llongvect_i + + ) {
tmp_stream < < ( * tmp_llongvect_i ) ;
if ( tmp_llongvect_i ! = tmp_llongvect . end ( ) - 1 )
tmp_stream < < " " ;
}
2015-01-07 20:23:15 -05:00
2015-01-08 19:56:44 -05:00
text = new TiXmlText ( tmp_stream . str ( ) . c_str ( ) ) ;
element - > LinkEndChild ( text ) ;
tmp_llongvect . clear ( ) ;
break ;
case DATA_FLOAT_VECTOR :
2015-01-09 20:56:43 -05:00
child - > element ( ) - > get ( tmp_floatvect ) ;
2015-01-07 20:23:15 -05:00
2015-01-08 19:56:44 -05:00
tmp_stream . str ( " " ) ;
2015-01-08 18:33:37 -05:00
2015-01-08 19:56:44 -05:00
for ( tmp_floatvect_i = tmp_floatvect . begin ( ) ; tmp_floatvect_i ! = tmp_floatvect . end ( ) ; tmp_floatvect_i + + ) {
tmp_stream < < ( * tmp_floatvect_i ) ;
if ( tmp_floatvect_i ! = tmp_floatvect . end ( ) - 1 )
tmp_stream < < " " ;
}
2015-01-08 18:33:37 -05:00
2015-01-08 19:56:44 -05:00
text = new TiXmlText ( tmp_stream . str ( ) . c_str ( ) ) ;
element - > LinkEndChild ( text ) ;
tmp_floatvect . clear ( ) ;
break ;
case DATA_DOUBLE_VECTOR :
2015-01-09 20:56:43 -05:00
child - > element ( ) - > get ( tmp_doublevect ) ;
2015-01-08 18:33:37 -05:00
2015-01-08 19:56:44 -05:00
tmp_stream . str ( " " ) ;
2015-01-08 18:33:37 -05:00
2015-01-08 19:56:44 -05:00
for ( tmp_doublevect_i = tmp_doublevect . begin ( ) ; tmp_doublevect_i ! = tmp_doublevect . end ( ) ; tmp_doublevect_i + + ) {
tmp_stream < < ( * tmp_doublevect_i ) ;
if ( tmp_doublevect_i ! = tmp_doublevect . end ( ) - 1 )
tmp_stream < < " " ;
}
2015-01-08 18:33:37 -05:00
2015-01-08 19:56:44 -05:00
text = new TiXmlText ( tmp_stream . str ( ) . c_str ( ) ) ;
element - > LinkEndChild ( text ) ;
tmp_doublevect . clear ( ) ;
break ;
}
2015-01-07 20:23:15 -05:00
2015-01-08 19:56:44 -05:00
if ( element ) {
elxml - > LinkEndChild ( element ) ;
2015-01-08 18:33:37 -05:00
2015-01-08 19:56:44 -05:00
if ( child - > numChildren ( ) ) {
nodeToXML ( child , element ) ;
}
2015-01-08 18:33:37 -05:00
}
}
2015-01-08 19:56:44 -05:00
elem - > rewind ( ) ;
2015-01-07 20:23:15 -05:00
}
void DataTree : : printXML ( ) /* get serialized size + return node names header */
{
2015-01-08 19:56:44 -05:00
TiXmlDocument doc ;
TiXmlDeclaration * decl = new TiXmlDeclaration ( " 1.0 " , " " , " " ) ;
doc . LinkEndChild ( decl ) ;
2015-01-07 20:23:15 -05:00
2015-01-09 20:56:43 -05:00
DataNode * root = rootNode ( ) ;
2015-01-07 20:23:15 -05:00
2015-01-08 19:56:44 -05:00
string rootName = root - > getName ( ) ;
2015-01-07 20:23:15 -05:00
2015-01-08 19:56:44 -05:00
TiXmlElement * element = new TiXmlElement ( rootName . empty ( ) ? " root " : rootName . c_str ( ) ) ;
doc . LinkEndChild ( element ) ;
2015-01-07 20:23:15 -05:00
2015-01-08 19:56:44 -05:00
if ( ! root - > numChildren ( ) )
doc . Print ( ) ;
2015-01-07 20:23:15 -05:00
2015-01-08 19:56:44 -05:00
nodeToXML ( root , element ) ;
2015-01-07 20:23:15 -05:00
2015-01-08 19:56:44 -05:00
root - > rewind ( ) ;
2015-01-07 20:23:15 -05:00
2015-01-08 19:56:44 -05:00
doc . Print ( ) ;
2015-01-07 20:23:15 -05:00
}
long DataTree : : getSerializedSize ( DataElement & de_node_names , bool debug ) /* get serialized size + return node names header */
{
2015-01-08 19:56:44 -05:00
long total_size = 0 ;
2015-01-07 20:23:15 -05:00
2015-01-08 19:56:44 -05:00
stack < DataNode * > dn_stack ;
vector < string > node_names ;
map < string , int , string_less > node_name_index_map ;
2015-01-07 20:23:15 -05:00
2015-01-08 19:56:44 -05:00
DataElement de_name_index ; // just used for sizing purposes
DataElement de_num_children ;
2015-01-07 20:23:15 -05:00
2015-01-08 19:56:44 -05:00
de_name_index . set ( ( int ) 0 ) ;
de_num_children . set ( ( int ) 0 ) ;
2015-01-07 20:23:15 -05:00
2015-01-08 19:56:44 -05:00
int de_name_index_size = de_name_index . getSerializedSize ( ) ;
int de_num_children_size = de_num_children . getSerializedSize ( ) ;
2015-01-07 20:23:15 -05:00
2015-01-08 19:56:44 -05:00
dn_stack . push ( & dn_root ) ;
2015-01-07 20:23:15 -05:00
2015-01-08 19:56:44 -05:00
while ( ! dn_stack . empty ( ) ) {
int name_index ;
// int num_children;
2015-01-07 20:23:15 -05:00
2015-01-08 19:56:44 -05:00
/* build the name list */
if ( dn_stack . top ( ) - > getName ( ) . empty ( ) ) {
name_index = 0 ; /* empty string */
} else if ( node_name_index_map [ dn_stack . top ( ) - > getName ( ) . c_str ( ) ] = = 0 ) {
node_names . push_back ( string ( dn_stack . top ( ) - > getName ( ) ) ) ;
name_index = node_names . size ( ) ;
node_name_index_map [ dn_stack . top ( ) - > getName ( ) . c_str ( ) ] = name_index ;
} else {
name_index = node_name_index_map [ dn_stack . top ( ) - > getName ( ) . c_str ( ) ] ;
}
2015-01-07 20:23:15 -05:00
2015-01-08 19:56:44 -05:00
/* add on the size of the name index and number of children */
total_size + = de_name_index_size ;
total_size + = de_num_children_size ;
2015-01-09 20:56:43 -05:00
total_size + = dn_stack . top ( ) - > element ( ) - > getSerializedSize ( ) ;
2015-01-08 19:56:44 -05:00
/* debug output */
if ( debug ) {
for ( unsigned int i = 0 ; i < dn_stack . size ( ) - 1 ; i + + )
cout < < " -- " ;
2015-01-09 20:56:43 -05:00
cout < < ( dn_stack . top ( ) - > getName ( ) . empty ( ) ? " NULL " : dn_stack . top ( ) - > getName ( ) ) < < " ( " < < dn_stack . top ( ) - > element ( ) - > getSerializedSize ( )
2015-01-08 19:56:44 -05:00
< < " ) " ;
2015-01-09 20:56:43 -05:00
cout < < " type: " < < dn_stack . top ( ) - > element ( ) - > getDataType ( ) < < endl ;
2015-01-08 19:56:44 -05:00
//cout << " index: " << name_index << endl;
2015-01-07 20:23:15 -05:00
}
2015-01-08 19:56:44 -05:00
/* end debug output */
2015-01-07 20:23:15 -05:00
2015-01-08 19:56:44 -05:00
/* if it has children, traverse into them */
if ( dn_stack . top ( ) - > hasAnother ( ) ) {
2015-01-09 20:56:43 -05:00
dn_stack . push ( dn_stack . top ( ) - > getNext ( ) ) ;
2015-01-07 20:23:15 -05:00
dn_stack . top ( ) - > rewind ( ) ;
2015-01-08 19:56:44 -05:00
} else {
/* no more children, back out until we have children, then add next child to the top */
while ( ! dn_stack . empty ( ) ) {
if ( ! dn_stack . top ( ) - > hasAnother ( ) ) {
dn_stack . top ( ) - > rewind ( ) ;
dn_stack . pop ( ) ;
} else
break ;
}
if ( ! dn_stack . empty ( ) ) {
2015-01-09 20:56:43 -05:00
dn_stack . push ( dn_stack . top ( ) - > getNext ( ) ) ;
2015-01-08 19:56:44 -05:00
dn_stack . top ( ) - > rewind ( ) ;
}
2015-01-07 20:23:15 -05:00
}
}
2015-01-08 19:56:44 -05:00
/* set the header for use in serialization */
de_node_names . set ( node_names ) ;
2015-01-07 20:23:15 -05:00
2015-01-08 19:56:44 -05:00
total_size + = de_node_names . getSerializedSize ( ) ;
2015-01-07 20:23:15 -05:00
2015-01-08 19:56:44 -05:00
return total_size ;
2015-01-07 20:23:15 -05:00
}
void DataNode : : findAll ( const char * name_in , vector < DataNode * > & node_list_out ) {
2015-01-08 19:56:44 -05:00
stack < DataNode * > dn_stack ;
2015-01-07 20:23:15 -05:00
2015-01-08 19:56:44 -05:00
/* start at the root */
dn_stack . push ( this ) ;
2015-01-07 20:23:15 -05:00
2015-01-08 19:56:44 -05:00
if ( string ( getName ( ) ) = = string ( name_in ) )
node_list_out . push_back ( this ) ;
2015-01-07 20:23:15 -05:00
2015-01-08 19:56:44 -05:00
while ( ! dn_stack . empty ( ) ) {
while ( dn_stack . top ( ) - > hasAnother ( name_in ) ) {
2015-01-09 20:56:43 -05:00
node_list_out . push_back ( dn_stack . top ( ) - > getNext ( name_in ) ) ;
2015-01-07 20:23:15 -05:00
}
2015-01-08 19:56:44 -05:00
/* if it has children, traverse into them */
if ( dn_stack . top ( ) - > hasAnother ( ) ) {
2015-01-09 20:56:43 -05:00
dn_stack . push ( dn_stack . top ( ) - > getNext ( ) ) ;
2015-01-07 20:23:15 -05:00
dn_stack . top ( ) - > rewind ( ) ;
2015-01-08 19:56:44 -05:00
} else {
/* no more children, back out until we have children, then add next child to the top */
while ( ! dn_stack . empty ( ) ) {
if ( ! dn_stack . top ( ) - > hasAnother ( ) ) {
dn_stack . top ( ) - > rewind ( ) ;
dn_stack . pop ( ) ;
} else
break ;
}
if ( ! dn_stack . empty ( ) ) {
2015-01-09 20:56:43 -05:00
dn_stack . push ( dn_stack . top ( ) - > getNext ( ) ) ;
2015-01-08 19:56:44 -05:00
dn_stack . top ( ) - > rewind ( ) ;
}
2015-01-07 20:23:15 -05:00
}
}
}
long DataTree : : getSerialized ( char * * ser_str , bool debug ) {
2015-01-08 19:56:44 -05:00
long data_ptr = 0 ;
long data_size = 0 ;
2015-01-07 20:23:15 -05:00
2015-01-08 19:56:44 -05:00
stack < DataNode * > dn_stack ;
vector < string > node_names ;
map < string , int , string_less > node_name_index_map ;
2015-01-07 20:23:15 -05:00
2015-01-08 19:56:44 -05:00
/* header of node names, grabbed from getserializedsize to avoid having to memmove() or realloc() */
DataElement de_node_names ;
2015-01-07 20:23:15 -05:00
2015-01-08 19:56:44 -05:00
data_size = getSerializedSize ( de_node_names , debug ) ;
2015-01-07 20:23:15 -05:00
2015-01-08 19:56:44 -05:00
* ser_str = ( char * ) malloc ( data_size ) ;
2015-01-07 20:23:15 -05:00
2015-01-08 19:56:44 -05:00
char * data_out = * ser_str ;
2015-01-07 20:23:15 -05:00
2015-01-08 19:56:44 -05:00
/* name list header */
char * de_node_names_serialized ;
long de_node_names_serialized_size ;
2015-01-07 20:23:15 -05:00
2015-01-08 19:56:44 -05:00
de_node_names . getSerialized ( & de_node_names_serialized ) ;
de_node_names_serialized_size = de_node_names . getSerializedSize ( ) ;
2015-01-07 20:23:15 -05:00
2015-01-08 19:56:44 -05:00
/* copy the header and increase the pointer */
memcpy ( data_out , de_node_names_serialized , de_node_names_serialized_size ) ;
data_ptr + = de_node_names_serialized_size ;
2015-01-07 20:23:15 -05:00
2015-01-08 19:56:44 -05:00
/* start at the root */
dn_stack . push ( & dn_root ) ;
2015-01-07 20:23:15 -05:00
2015-01-08 19:56:44 -05:00
while ( ! dn_stack . empty ( ) ) {
int name_index ;
int num_children ;
2015-01-07 20:23:15 -05:00
2015-01-08 19:56:44 -05:00
DataElement de_name_index ;
DataElement de_num_children ;
2015-01-07 20:23:15 -05:00
2015-01-08 19:56:44 -05:00
char * de_name_index_serialized ;
char * de_num_children_serialized ;
char * element_serialized ;
long de_name_index_serialized_size ;
long de_num_children_serialized_size ;
long element_serialized_size ;
2015-01-07 20:23:15 -05:00
2015-01-08 19:56:44 -05:00
/* build the name list */
if ( dn_stack . top ( ) - > getName ( ) . empty ( ) ) {
name_index = 0 ; /* empty string */
} else if ( node_name_index_map [ dn_stack . top ( ) - > getName ( ) . c_str ( ) ] = = 0 ) {
node_names . push_back ( string ( dn_stack . top ( ) - > getName ( ) ) ) ;
name_index = node_names . size ( ) ;
node_name_index_map [ dn_stack . top ( ) - > getName ( ) . c_str ( ) ] = name_index ;
} else {
name_index = node_name_index_map [ dn_stack . top ( ) - > getName ( ) . c_str ( ) ] ;
}
2015-01-07 20:23:15 -05:00
2015-01-08 19:56:44 -05:00
num_children = dn_stack . top ( ) - > numChildren ( ) ;
2015-01-07 20:23:15 -05:00
2015-01-08 19:56:44 -05:00
de_name_index . set ( name_index ) ;
de_num_children . set ( num_children ) ;
2015-01-07 20:23:15 -05:00
2015-01-08 19:56:44 -05:00
de_name_index_serialized_size = de_name_index . getSerializedSize ( ) ;
de_num_children_serialized_size = de_num_children . getSerializedSize ( ) ;
2015-01-09 20:56:43 -05:00
element_serialized_size = dn_stack . top ( ) - > element ( ) - > getSerializedSize ( ) ;
2015-01-07 20:23:15 -05:00
2015-01-08 19:56:44 -05:00
de_name_index . getSerialized ( & de_name_index_serialized ) ;
de_num_children . getSerialized ( & de_num_children_serialized ) ;
2015-01-09 20:56:43 -05:00
dn_stack . top ( ) - > element ( ) - > getSerialized ( & element_serialized ) ;
2015-01-07 20:23:15 -05:00
2015-01-08 19:56:44 -05:00
/* add on the name index and number of children */
memcpy ( data_out + data_ptr , de_name_index_serialized , de_name_index_serialized_size ) ;
data_ptr + = de_name_index_serialized_size ;
2015-01-07 20:23:15 -05:00
2015-01-08 19:56:44 -05:00
memcpy ( data_out + data_ptr , de_num_children_serialized , de_num_children_serialized_size ) ;
data_ptr + = de_num_children_serialized_size ;
2015-01-07 20:23:15 -05:00
2015-01-08 19:56:44 -05:00
/* add on the data element */
memcpy ( data_out + data_ptr , element_serialized , element_serialized_size ) ;
data_ptr + = element_serialized_size ;
2015-01-07 20:23:15 -05:00
2015-05-30 00:09:51 -04:00
delete [ ] de_name_index_serialized ;
delete [ ] de_num_children_serialized ;
delete [ ] element_serialized ;
2015-01-07 20:23:15 -05:00
2015-01-08 19:56:44 -05:00
/* if it has children, traverse into them */
if ( dn_stack . top ( ) - > hasAnother ( ) ) {
2015-01-09 20:56:43 -05:00
dn_stack . push ( dn_stack . top ( ) - > getNext ( ) ) ;
2015-01-07 20:23:15 -05:00
dn_stack . top ( ) - > rewind ( ) ;
2015-01-08 19:56:44 -05:00
} else {
/* no more children, back out until we have children, then add next child to the top */
while ( ! dn_stack . empty ( ) ) {
if ( ! dn_stack . top ( ) - > hasAnother ( ) ) {
dn_stack . top ( ) - > rewind ( ) ;
dn_stack . pop ( ) ;
} else
break ;
}
if ( ! dn_stack . empty ( ) ) {
2015-01-09 20:56:43 -05:00
dn_stack . push ( dn_stack . top ( ) - > getNext ( ) ) ;
2015-01-08 19:56:44 -05:00
dn_stack . top ( ) - > rewind ( ) ;
}
2015-01-07 20:23:15 -05:00
}
}
2015-01-08 19:56:44 -05:00
return data_size ;
2015-01-07 20:23:15 -05:00
}
void DataTree : : setSerialized ( char * ser_str , bool debug ) {
2015-01-08 19:56:44 -05:00
long data_ptr = 0 ;
2015-01-08 18:33:37 -05:00
// long data_size = 0;
2015-01-07 20:23:15 -05:00
2015-01-08 19:56:44 -05:00
stack < DataNode * > dn_stack ;
stack < int > dn_childcount_stack ;
vector < string > node_names ;
2015-01-07 20:23:15 -05:00
2015-01-08 19:56:44 -05:00
DataElement de_node_names ;
2015-01-07 20:23:15 -05:00
2015-01-08 19:56:44 -05:00
de_node_names . setSerialized ( ser_str ) ;
data_ptr + = de_node_names . getSerializedSize ( ) ;
de_node_names . get ( node_names ) ;
2015-01-07 20:23:15 -05:00
2015-01-08 19:56:44 -05:00
DataElement de_name_index ;
DataElement de_num_children ;
DataElement de_element ;
2015-01-07 20:23:15 -05:00
2015-01-08 19:56:44 -05:00
dn_stack . push ( & dn_root ) ;
dn_childcount_stack . push ( 0 ) ; /* root (parent null) has no siblings */
2015-01-07 20:23:15 -05:00
2015-01-08 19:56:44 -05:00
/* unserialization is a little less straightforward since we have to do a countdown of remaining children */
while ( ! dn_stack . empty ( ) ) {
2015-05-30 00:09:51 -04:00
int name_index = 0 ;
int num_children = 0 ;
2015-01-07 20:23:15 -05:00
2015-01-08 19:56:44 -05:00
/* pull the index of the name of this node */
de_name_index . setSerialized ( ser_str + data_ptr ) ;
data_ptr + = de_name_index . getSerializedSize ( ) ;
2015-01-07 20:23:15 -05:00
2015-01-08 19:56:44 -05:00
/* pull the number of children this node has */
de_num_children . setSerialized ( ser_str + data_ptr ) ;
data_ptr + = de_num_children . getSerializedSize ( ) ;
2015-01-07 20:23:15 -05:00
2015-01-08 19:56:44 -05:00
/* get values from the temp dataelements */
de_name_index . get ( name_index ) ;
de_num_children . get ( num_children ) ;
/* pull the node's element */
2015-01-09 20:56:43 -05:00
dn_stack . top ( ) - > element ( ) - > setSerialized ( ser_str + data_ptr ) ;
data_ptr + = dn_stack . top ( ) - > element ( ) - > getSerializedSize ( ) ;
2015-01-08 19:56:44 -05:00
/* debug output */
if ( debug ) {
for ( unsigned int i = 0 ; i < dn_stack . size ( ) - 1 ; i + + )
cout < < " -- " ;
2015-01-09 20:56:43 -05:00
cout < < ( name_index ? node_names [ name_index - 1 ] : " NULL " ) < < " ( " < < dn_stack . top ( ) - > element ( ) - > getSerializedSize ( ) < < " ) " ;
2015-01-08 19:56:44 -05:00
cout < < " index: " < < name_index < < endl ;
}
/* end debug output */
2015-01-07 20:23:15 -05:00
2015-01-08 19:56:44 -05:00
/* name index >= 1 means it has a name */
2015-05-30 00:09:51 -04:00
if ( name_index > = 1 ) {
2015-01-08 19:56:44 -05:00
dn_stack . top ( ) - > setName ( node_names [ name_index - 1 ] . c_str ( ) ) ;
2015-01-08 18:33:37 -05:00
2015-01-08 19:56:44 -05:00
} else /* name is nil */
{
dn_stack . top ( ) - > setName ( " " ) ;
2015-01-08 18:33:37 -05:00
}
2015-01-08 19:56:44 -05:00
if ( num_children ) /* Has children, create first child and push it to the top */
2015-01-08 18:33:37 -05:00
{
2015-01-08 19:56:44 -05:00
dn_childcount_stack . push ( num_children ) ; /* push the child count onto the stack */
2015-01-07 20:23:15 -05:00
de_name_index . setSerialized ( ser_str + data_ptr ) ; /* peek at the new child name but don't increment pointer */
de_name_index . get ( name_index ) ;
2015-01-08 19:56:44 -05:00
/* add this child onto the top of the stack */
2015-01-09 20:56:43 -05:00
dn_stack . push ( dn_stack . top ( ) - > newChild ( ( name_index ? node_names [ name_index - 1 ] : string ( " " ) ) . c_str ( ) ) ) ;
2015-01-08 19:56:44 -05:00
dn_childcount_stack . top ( ) - - ; /* decrement to count the new child */
2015-01-07 20:23:15 -05:00
}
2015-01-08 19:56:44 -05:00
else /* No children, move on to the next sibling */
2015-01-07 20:23:15 -05:00
{
2015-01-08 19:56:44 -05:00
if ( dn_childcount_stack . top ( ) ) /* any siblings remaining? */
2015-01-07 20:23:15 -05:00
{
2015-01-08 19:56:44 -05:00
de_name_index . setSerialized ( ser_str + data_ptr ) ; /* peek at the new child name but don't increment pointer */
de_name_index . get ( name_index ) ;
2015-01-07 20:23:15 -05:00
2015-01-08 19:56:44 -05:00
dn_stack . pop ( ) ;
2015-01-09 20:56:43 -05:00
dn_stack . push ( dn_stack . top ( ) - > newChild ( ( name_index ? node_names [ name_index - 1 ] : string ( " " ) ) . c_str ( ) ) ) ; /* create the next sibling and throw it on the stack */
2015-01-08 19:56:44 -05:00
dn_childcount_stack . top ( ) - - ; /* decrement to count the new sibling */
}
else /* This is the last sibling, move up the stack and find the next */
{
while ( ! dn_stack . empty ( ) ) /* move up the stack until we find the next sibling */
2015-01-07 20:23:15 -05:00
{
2015-01-08 19:56:44 -05:00
if ( dn_childcount_stack . top ( ) ) {
de_name_index . setSerialized ( ser_str + data_ptr ) ; /* peek at the new child name but don't increment pointer */
de_name_index . get ( name_index ) ;
dn_stack . pop ( ) ;
2015-01-09 20:56:43 -05:00
dn_stack . push ( dn_stack . top ( ) - > newChild ( ( name_index ? node_names [ name_index - 1 ] : string ( " " ) ) . c_str ( ) ) ) ; /* throw it on the stack */
2015-01-08 19:56:44 -05:00
dn_childcount_stack . top ( ) - - ; /* count it */
break
; }
else
{
dn_childcount_stack . pop ( ) ;
dn_stack . pop ( ) ; /* if no more siblings found the stack will empty naturally */
}
2015-01-07 20:23:15 -05:00
}
}
}
}
}
bool DataTree : : LoadFromFileXML ( const std : : string & filename , DT_FloatingPointPolicy fpp ) {
TiXmlDocument doc ( filename . c_str ( ) ) ;
bool loadOkay = doc . LoadFile ( ) ;
if ( ! loadOkay ) {
std : : cout < < " LoadFromFileXML[error loading]: " < < filename < < std : : endl ;
return false ;
}
TiXmlNode * xml_root_node = doc . RootElement ( ) ;
if ( ! xml_root_node ) {
std : : cout < < " LoadFromFileXML[error no root]: " < < filename < < std : : endl ;
return false ;
}
2015-01-09 20:56:43 -05:00
rootNode ( ) - > setName ( xml_root_node - > ToElement ( ) - > Value ( ) ) ;
2015-01-07 20:23:15 -05:00
2015-01-09 20:56:43 -05:00
setFromXML ( rootNode ( ) , xml_root_node , true , fpp ) ;
2015-01-07 20:23:15 -05:00
return true ;
}
bool DataTree : : SaveToFileXML ( const std : : string & filename ) {
TiXmlDocument doc ;
TiXmlDeclaration * decl = new TiXmlDeclaration ( " 1.0 " , " " , " " ) ;
doc . LinkEndChild ( decl ) ;
2015-01-09 20:56:43 -05:00
string rootName = rootNode ( ) - > getName ( ) ;
2015-01-07 20:23:15 -05:00
TiXmlElement * element = new TiXmlElement ( rootName . empty ( ) ? " root " : rootName . c_str ( ) ) ;
doc . LinkEndChild ( element ) ;
2015-01-09 20:56:43 -05:00
nodeToXML ( rootNode ( ) , element ) ;
2015-01-07 20:23:15 -05:00
doc . SaveFile ( filename . c_str ( ) ) ;
return true ;
}
/*
bool DataTree : : SaveToFile ( const std : : string & filename )
{
char * serialized ;
long dataSize = getSerialized ( & serialized ) ;
std : : ofstream fout ( filename . c_str ( ) , ios : : binary ) ;
fout . write ( serialized , dataSize ) ;
fout < < flush ;
fout . close ( ) ;
delete serialized ;
return true ;
}
bool DataTree : : LoadFromFile ( const std : : string & filename )
{
char * serialized ;
long dataSize ;
ifstream fin ( filename . c_str ( ) , ios : : binary ) ;
fin . seekg ( 0 , ios : : end ) ;
dataSize = fin . tellg ( ) ;
fin . seekg ( 0 , ios : : beg ) ;
serialized = new char [ dataSize ] ;
fin . read ( serialized , dataSize ) ;
fin . close ( ) ;
setSerialized ( serialized ) ;
delete serialized ;
return true ;
}
*/
bool DataTree : : SaveToFile ( const std : : string & filename , bool compress , int compress_level ) {
long dataSize , compressedSize , headerSize ;
char * serialized , * hdr_serialized , * compressed ;
DataTree dtHeader ;
dataSize = getSerialized ( & serialized ) ;
# if USE_FASTLZ
if ( compress ) {
compressed = new char [ ( int ) ceil ( dataSize * 1.5 ) ] ;
compressedSize = fastlz_compress_level ( compress_level , serialized , dataSize , compressed ) ;
compressed = ( char * ) realloc ( compressed , compressedSize ) ;
delete serialized ;
}
# else
if ( compress ) {
std : : cout < < " Can't compress, FASTLZ disabled " ;
compress = false ;
}
# endif
2015-01-09 20:56:43 -05:00
DataNode * header = dtHeader . rootNode ( ) ;
2015-01-07 20:23:15 -05:00
2015-01-09 20:56:43 -05:00
* header - > newChild ( " version " ) = 1.0f ;
* header - > newChild ( " compression " ) = string ( compress ? " FastLZ " : " none " ) ;
* header - > newChild ( " uncompressed_size " ) = dataSize ;
2015-01-07 20:23:15 -05:00
headerSize = dtHeader . getSerialized ( & hdr_serialized ) ;
std : : ofstream fout ( filename . c_str ( ) , ios : : binary ) ;
fout . write ( ( char * ) & headerSize , sizeof ( long ) ) ;
fout . write ( ( char * ) & ( compress ? compressedSize : dataSize ) , sizeof ( long ) ) ;
fout . write ( hdr_serialized , headerSize ) ;
fout . write ( compress ? compressed : serialized , compress ? compressedSize : dataSize ) ;
fout < < flush ;
fout . close ( ) ;
2015-05-30 00:09:51 -04:00
free ( hdr_serialized ) ;
2015-01-07 20:23:15 -05:00
if ( ! compress ) {
2015-05-30 00:09:51 -04:00
free ( serialized ) ;
2015-01-07 20:23:15 -05:00
} else {
delete compressed ;
}
return true ;
}
bool DataTree : : LoadFromFile ( const std : : string & filename ) {
char * compressed , * serialized , * hdr_serialized ;
long dataSize , headerSize , compressedSize ;
ifstream fin ( filename . c_str ( ) , ios : : binary ) ;
fin . read ( ( char * ) & headerSize , sizeof ( long ) ) ;
fin . read ( ( char * ) & compressedSize , sizeof ( long ) ) ;
hdr_serialized = new char [ headerSize ] ;
fin . read ( hdr_serialized , headerSize ) ;
DataTree dtHeader ;
dtHeader . setSerialized ( hdr_serialized ) ;
2015-01-09 20:56:43 -05:00
DataNode * header = dtHeader . rootNode ( ) ;
2015-01-07 20:23:15 -05:00
2015-01-10 11:00:03 -05:00
string compressionType ( * header - > getNext ( " compression " ) ) ;
2015-01-09 20:56:43 -05:00
dataSize = * header - > getNext ( " uncompressed_size " ) ;
2015-01-07 20:23:15 -05:00
# if USE_FASTLZ
2015-08-03 23:41:37 -04:00
bool uncompress = false ;
2015-01-07 20:23:15 -05:00
if ( compressionType = = " FastLZ " ) {
uncompress = true ;
}
if ( uncompress ) {
compressed = new char [ compressedSize ] ;
fin . read ( compressed , compressedSize ) ;
serialized = new char [ dataSize ] ;
fastlz_decompress ( compressed , compressedSize , serialized , dataSize ) ;
delete compressed ;
} else {
serialized = new char [ dataSize ] ;
fin . read ( serialized , dataSize ) ;
}
# else
if ( compressionType = = " FastLZ " ) {
std : : cout < < " DataTree Unable to load FastLZ compressed file -- FastLZ is disabled " ;
return false ;
}
serialized = new char [ dataSize ] ;
fin . read ( serialized , dataSize ) ;
# endif
fin . close ( ) ;
setSerialized ( serialized ) ;
2015-05-30 00:09:51 -04:00
delete [ ] serialized ;
delete [ ] hdr_serialized ;
2015-01-07 20:23:15 -05:00
return true ;
}