- Main Page
- Namespaces
- Classes
- Files
- Related Pages

# /Users/fpy/titan-1-5-MBARI/Mers/Utils/Io/Xml/Dom/XMLSaveLoad.cpp

    00001
    00002 //
    00003 // Copyright (c) 2005           Model-based Embedded and Robotic Systems Group
    00004 // All Rights Reserved          Massachusetts Institute of Technology
    00005 //
    00006 // This software is provided as is. Model-based Embedded and Robotic Systems
    00007 // (MERS) group does not assume any responsibility.
    00008 //
    00010
    00011 #include "XMLSaveLoad.h"
    00012 #include <Mers/Utils/Io/Xml/ScopedTranscoder.h>
    00013 #include <Mers/Utils/Lang/String.h>
    00014 #include <Mers/Utils/Exceptions/RuntimeException.h>
    00015 #include <cassert>
    00016
    00018
    00019 using namespace Mers::Utils::Io::Xml::Dom;
    00020 using Mers::Utils::Lang::String;
    00021 using Mers::Utils::Exceptions::RuntimeException;
    00022 using Mers::Utils::Io::Xml::CScopedTranscoder;
    00023 using Mers::Utils::Io::Xml::XMLScopedTranscoder;
    00024 using XERCES_CPP_NAMESPACE::DOMDocument;
    00025 using XERCES_CPP_NAMESPACE::DOMNode;
    00026 using XERCES_CPP_NAMESPACE::DOMElement;
    00027
    00029
    00030 XMLSaveLoad::XMLSaveLoad( DOMDocument * document, eSaveOrLoad saveOrLoad,
    00031         unsigned int version )
    00032         : ISaveLoad( saveOrLoad, version ), m_document( document ),
    00033           m_currentElement( document->getDocumentElement() ),
    00034           m_recentChild( NULL )
    00035 {
    00036         saveLoadAttribute( "version", m_version );
    00037 }
    00038
    00040
    00041 void XMLSaveLoad::saveLoadComment( const char * message )
    00042 {
    00043         if( !isSaving() )
    00044                 // Don't do anything unless we're loading.
    00045                 return;
    00046
    00047         // Save this comment.
    00048         XMLScopedTranscoder xsComment( message );
    00049         DOMNode * comment = m_document->createComment( xsComment );
    00050
    00051         // Add it to our current context's children.
    00052         m_currentElement->appendChild( comment );
    00053 }
    00054
    00056
    00057 template< typename t_Basic >
    00058 void XMLSaveLoad::saveLoadNode( const char * elementName, t_Basic &obj )
    00059 {
    00060         // Push a new context.  This creates a node.
    00061         String name = pushContextNode( elementName );
    00062
    00063         // Save/Load an attribute called "value" for this node, with our
    00064         // basic type.
    00065         saveLoadAttribute( "value", obj );
    00066
    00067         // Pop our context.
    00068         popContext();
    00069 }
    00070
    00072
    00073 template<typename t_Integer>
    00074 void XMLSaveLoad::saveLoadInteger( const char * attributeName,
    00075         t_Integer &value )
    00076 {
    00077         // Transcode our attribute name.
    00078         XMLScopedTranscoder xsAttrName( attributeName );
    00079
    00080         if( isLoading() ) {
    00081                 // Load the attribute.
    00082                 const XMLCh * xsValue =
    00083                         m_currentElement->getAttribute( xsAttrName );
    00084                 assert( xsValue != NULL );
    00085
    00086                 // Translate to char *.
    00087                 CScopedTranscoder sValue( xsValue );
    00088
    00089                 // Translate to an integer.
    00090                 value = atoi( sValue );
    00091         } else { // Saving
    00092                 // Convert the value to a string.
    00093                 std::ostringstream oss;
    00094                 oss << (t_Integer)value;
    00095                 XMLScopedTranscoder xsValue( oss.str().c_str() );
    00096
    00097                 // Attach the attribute to the current node.
    00098                 m_currentElement->setAttribute( xsAttrName, xsValue );
    00099         }
    00100 }
    00101
    00103
    00104 template<typename t_Real>
    00105 void XMLSaveLoad::saveLoadReal( const char * attributeName,
    00106         t_Real &value )
    00107 {
    00108         // Transcode our attribute name.
    00109         XMLScopedTranscoder xsAttrName( attributeName );
    00110
    00111         if( isLoading() ) {
    00112                 // Load the attribute.
    00113                 const XMLCh * xsValue =
    00114                         m_currentElement->getAttribute( xsAttrName );
    00115                 assert( xsValue != NULL );
    00116
    00117                 // Translate to char *.
    00118                 CScopedTranscoder sValue( xsValue );
    00119
    00120                 // Translate to a real.
    00121                 double dValue;
    00122                 int numScanned = sscanf( sValue, "%lf", &dValue );
    00123                 assert( numScanned == 1 );
    00124                 value = static_cast< t_Real >(dValue);
    00125         } else { // Saving
    00126                 // Convert the value to a string.
    00127                 String s;
    00128                 s += value;
    00129                 XMLScopedTranscoder xsValue( s );
    00130
    00131                 // Attach the attribute to the current node.
    00132                 m_currentElement->setAttribute( xsAttrName, xsValue );
    00133         }
    00134 }
    00135
    00137
    00138 void XMLSaveLoad::saveLoadAttribute( const char * attributeName, bool &value )
    00139 {
    00140         // Transcode our attribute name.
    00141         XMLScopedTranscoder xsAttrName( attributeName );
    00142
    00143         if( isLoading() ) {
    00144                 // Load the attribute.
    00145                 const XMLCh * xsValue =
    00146                         m_currentElement->getAttribute( xsAttrName );
    00147                 assert( xsValue != NULL );
    00148
    00149                 // Translate to char *.
    00150                 CScopedTranscoder sValue( xsValue );
    00151
    00152                 // Translate to a Boolean.
    00153                 if( strcmp( sValue, "true" ) == 0 )
    00154                         value = true;
    00155                 else if( strcmp( sValue, "false" ) == 0 )
    00156                         value = false;
    00157                 else {
    00158                         const char * csVal = sValue;
    00159                         throw RuntimeException( String( "Invalid boolean value: " ) +
    00160                                 csVal, __FILE__, __LINE__ );
    00161                 }
    00162         } else { // Saving
    00163                 // Convert the value to a string.
    00164                 XMLScopedTranscoder xsValue( ( value ? "true" : "false" ) );
    00165
    00166                 // Attach the attribute to the current node.
    00167                 m_currentElement->setAttribute( xsAttrName, xsValue );
    00168         }
    00169 }
    00170
    00172
    00173 void XMLSaveLoad::saveLoadAttribute( const char * attributeName,
    00174         String &value )
    00175 {
    00176         // Transcode our attribute name.
    00177         XMLScopedTranscoder xsAttrName( attributeName );
    00178
    00179         if( isLoading() ) {
    00180                 // Load the attribute.
    00181                 const XMLCh * xsValue =
    00182                         m_currentElement->getAttribute( xsAttrName );
    00183                 assert( xsValue != NULL );
    00184
    00185                 // Translate to char *.
    00186                 CScopedTranscoder sValue( xsValue );
    00187
    00188                 // Translate to a String.
    00189                 value = sValue;
    00190         } else { // Saving
    00191                 // Convert the value to a string.
    00192                 XMLScopedTranscoder xsValue( value );
    00193
    00194                 // Attach the attribute to the current node.
    00195                 m_currentElement->setAttribute( xsAttrName, xsValue );
    00196         }
    00197 }
    00198
    00200
    00201 void XMLSaveLoad::saveLoadAttribute( const char * attributeName,
    00202         char * &value )
    00203 {
    00204         // Transcode our attribute name.
    00205         XMLScopedTranscoder xsAttrName( attributeName );
    00206
    00207         if( isLoading() ) {
    00208                 // Load the attribute.
    00209                 const XMLCh * xsValue =
    00210                         m_currentElement->getAttribute( xsAttrName );
    00211                 assert( xsValue != NULL );
    00212
    00213                 // Translate to char *.
    00214                 CScopedTranscoder sValue( xsValue );
    00215
    00216                 // Translate to a char *.
    00217                 value = new char[ strlen( sValue ) + 1 ];
    00218                 strcpy( value, sValue );
    00219         } else { // Saving
    00220                 // Convert the value to a string.
    00221                 XMLScopedTranscoder xsValue( value );
    00222
    00223                 // Attach the attribute to the current node.
    00224                 m_currentElement->setAttribute( xsAttrName, xsValue );
    00225         }
    00226 }
    00227
    00229
    00230 void XMLSaveLoad::saveLoadAttribute( const char * attributeName, int &value )
    00231 {
    00232         saveLoadInteger( attributeName, value );
    00233 }
    00234
    00236
    00237 void XMLSaveLoad::saveLoadAttribute( const char * attributeName,
    00238         unsigned int &value )
    00239 {
    00240         saveLoadInteger( attributeName, value );
    00241 }
    00242
    00244
    00245 void XMLSaveLoad::saveLoadAttribute( const char * attributeName, short &value )
    00246 {
    00247         saveLoadInteger( attributeName, value );
    00248 }
    00249
    00251
    00252 void XMLSaveLoad::saveLoadAttribute( const char * attributeName,
    00253         unsigned short &value )
    00254 {
    00255         saveLoadInteger( attributeName, value );
    00256 }
    00257
    00259
    00260 void XMLSaveLoad::saveLoadAttribute( const char * attributeName,
    00261         double &value )
    00262 {
    00263         saveLoadReal( attributeName, value );
    00264 }
    00265
    00267
    00268 void XMLSaveLoad::doSaveLoad( const char * name, bool &inout_value )
    00269 {
    00270         saveLoadNode< bool >( name, inout_value );
    00271 }
    00272
    00274
    00275 void XMLSaveLoad::doSaveLoad( const char * name, String &inout_value )
    00276 {
    00277         saveLoadNode< String >( name, inout_value );
    00278 }
    00279
    00281
    00282 void XMLSaveLoad::doSaveLoad( const char * name, char * &inout_value )
    00283 {
    00284         saveLoadNode< char * >( name, inout_value );
    00285 }
    00286
    00288
    00289 void XMLSaveLoad::doSaveLoad( const char * name, int &inout_value )
    00290 {
    00291         saveLoadNode< int >( name, inout_value );
    00292 }
    00293
    00295
    00296 void XMLSaveLoad::doSaveLoad( const char * name, unsigned int &inout_value )
    00297 {
    00298         saveLoadNode< unsigned int >( name, inout_value );
    00299 }
    00300
    00302
    00303 void XMLSaveLoad::doSaveLoad( const char * name, short &inout_value )
    00304 {
    00305         saveLoadNode< short >( name, inout_value );
    00306 }
    00307
    00309
    00310 void XMLSaveLoad::doSaveLoad( const char * name, unsigned short &inout_value )
    00311 {
    00312         saveLoadNode< unsigned short >( name, inout_value );
    00313 }
    00314
    00316
    00317 void XMLSaveLoad::doSaveLoad( const char * name, double &inout_value )
    00318 {
    00319         saveLoadNode< double >( name, inout_value );
    00320 }
    00321
    00323
    00324 String XMLSaveLoad::pushContext( const char * name )
    00325 {
    00326         // Push a context node.
    00327         String contextObjName = pushContextNode( "object" );
    00328
    00329         // Get the name of our context.
    00330         String contextClassName;
    00331         if( isSaving() )
    00332                 contextClassName = name;
    00333
    00334         // Save/Load our context.
    00335         saveLoadAttribute( "class", contextClassName );
    00336
    00337         //Return our context name
    00338         return contextClassName;
    00339 }
    00340
    00342
    00343 void XMLSaveLoad::popContext()
    00344 {
    00345         // To restore our context, we need to move up the tree.
    00346         m_recentChild = m_currentElement;
    00347         m_currentElement =
    00348                 dynamic_cast<DOMElement *>( m_currentElement->getParentNode() );
    00349
    00350         // We should never pop more than we push.  Thus,
    00351         // currentElement should never be NULL, as it starts out at
    00352         // the root of the tree.
    00353         assert( m_currentElement != NULL );
    00354 }
    00355
    00357
    00358 String XMLSaveLoad::pushContextNode( const char * name )
    00359 {
    00360         // If we're loading, we need to determine the name of this
    00361         // context.
    00362         if( isLoading() ) {
    00363                 // Get the next node.  This is either the first node or
    00364                 // the next sibling.
    00365                 DOMNode * node;
    00366                 if( m_recentChild == NULL )
    00367                         node = m_currentElement->getFirstChild();
    00368                 else
    00369                         node = m_recentChild->getNextSibling();
    00370
    00371                 // Loop over the children until we get to another element.
    00372                 while( node != NULL && dynamic_cast<DOMElement *>( node ) == NULL )
    00373                         node = node->getNextSibling();
    00374
    00375                 // We should probably handle the case where the user code
    00376                 // ran past the end of this context more elegantly,
    00377                 // eventually.  node should never become NULL again.
    00378                 assert( node != NULL );
    00379
    00380                 // We now point to this element.
    00381                 m_currentElement = dynamic_cast<DOMElement *>( node );
    00382                 // We also move recentChild to NULL since we just started
    00383                 // a new context.
    00384                 m_recentChild = NULL;
    00385
    00386                 // Get the class name from the contextName attribute and
    00387                 // convert it to ASCII.
    00388                 CScopedTranscoder sElementName( node->getNodeName() );
    00389
    00390                 // Return this element's name as our context.
    00391                 return String( sElementName );
    00392         } else {
    00393                 // Otherwise, we're saving.  Create a new named element to
    00394                 // store this new context.
    00395                 XMLScopedTranscoder xsElementName( name );
    00396                 m_recentChild = m_document->createElement( xsElementName );
    00397
    00398                 // Add it to our current context's children.
    00399                 m_currentElement->appendChild( m_recentChild );
    00400                 // Make it our new context.
    00401                 m_currentElement = m_recentChild;
    00402                 m_recentChild = NULL;
    00403
    00404                 // Return our known name as our context.
    00405                 return String( name );
    00406         }
    00407 }
    00408
    00410