TinyDemarshaller.cpp
Go to the documentation of this file.
00001 /***************************************************************************
00002   tag: FMTC  Tue Mar 11 21:49:20 CET 2008  TinyDemarshaller.cpp
00003 
00004                         TinyDemarshaller.cpp -  description
00005                            -------------------
00006     begin                : Tue March 11 2008
00007     copyright            : (C) 2008 FMTC
00008     email                : peter.soetens@fmtc.be
00009 
00010  ***************************************************************************
00011  *   This library is free software; you can redistribute it and/or         *
00012  *   modify it under the terms of the GNU General Public                   *
00013  *   License as published by the Free Software Foundation;                 *
00014  *   version 2 of the License.                                             *
00015  *                                                                         *
00016  *   As a special exception, you may use this file as part of a free       *
00017  *   software library without restriction.  Specifically, if other files   *
00018  *   instantiate templates or use macros or inline functions from this     *
00019  *   file, or you compile this file and link it with other files to        *
00020  *   produce an executable, this file does not by itself cause the         *
00021  *   resulting executable to be covered by the GNU General Public          *
00022  *   License.  This exception does not however invalidate any other        *
00023  *   reasons why the executable file might be covered by the GNU General   *
00024  *   Public License.                                                       *
00025  *                                                                         *
00026  *   This library is distributed in the hope that it will be useful,       *
00027  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00028  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU     *
00029  *   Lesser General Public License for more details.                       *
00030  *                                                                         *
00031  *   You should have received a copy of the GNU General Public             *
00032  *   License along with this library; if not, write to the Free Software   *
00033  *   Foundation, Inc., 59 Temple Place,                                    *
00034  *   Suite 330, Boston, MA  02111-1307  USA                                *
00035  *                                                                         *
00036  ***************************************************************************/
00037 
00038 
00039 #include "TinyDemarshaller.hpp"
00040 
00041 
00042 // Modified tinyxml* to include it in the RTT namespace to avoid clashes
00043 // with possible other libraries.
00044 #include "tinyxml.h"
00045 
00046 // This is currently not defined:
00047 #ifdef TIXML_USE_STL
00048 #include <iostream>
00049 #include <sstream>
00050 using namespace std;
00051 #else
00052 #include <cstdio>
00053 #endif
00054 
00055 #include <stack>
00056 #include <Property.hpp>
00057 #include <PropertyBag.hpp>
00058 #include <Logger.hpp>
00059 
00060 namespace RTT
00061 {
00062     namespace marsh
00063     {
00064         class Tiny2CPFHandler
00065         {
00069             PropertyBag &bag;
00070             std::stack< std::pair<PropertyBag*, Property<PropertyBag>*> > bag_stack;
00071 
00072             enum Tag { TAG_STRUCT, TAG_SIMPLE, TAG_SEQUENCE, TAG_PROPERTIES, TAG_DESCRIPTION, TAG_VALUE, TAG_UNKNOWN};
00073             std::stack<Tag> tag_stack;
00074 
00078             std::string name;
00079             std::string description;
00080             std::string type;
00081             std::string value_string;
00082 
00083         public:
00084 
00085             Tiny2CPFHandler( PropertyBag &b ) : bag( b )
00086             {
00087                 Property<PropertyBag>* dummy = 0;
00088                 bag_stack.push(std::make_pair(&bag, dummy));
00089             }
00090 
00091             bool endElement()
00092             {
00093                 switch ( tag_stack.top() )
00094                     {
00095                     case TAG_SIMPLE:
00096                         if ( type == "boolean" )
00097                         {
00098                             if ( value_string == "1" || value_string == "true")
00099                                 bag_stack.top().first->add
00100                                 ( new Property<bool>( name, description, true ) );
00101                             else if ( value_string == "0" || value_string == "false")
00102                                 bag_stack.top().first->add
00103                                 ( new Property<bool>( name, description, false ) );
00104                             else {
00105                                 log(Error)<< "Wrong value for property '"+type+"'." \
00106                                     " Value should contain '0' or '1', got '"+ value_string +"'." << endlog();
00107                                 return false;
00108                             }
00109                         }
00110                         else if ( type == "char" ) {
00111                             if ( value_string.length() > 1 ) {
00112                                 log(Error) << "Wrong value for property '"+type+"'." \
00113                                     " Value should contain a single character, got '"+ value_string +"'." << endlog();
00114                                 return false;
00115                             }
00116                             else
00117                                 bag_stack.top().first->add
00118                                     ( new Property<char>( name, description, value_string.empty() ? '\0' : value_string[0] ) );
00119                         }
00120                         else if ( type == "uchar" || type == "octet" ) {
00121                             if ( value_string.length() > 1 ) {
00122                                 log(Error) << "Wrong value for property '"+type+"'." \
00123                                     " Value should contain a single unsigned character, got '"+ value_string +"'." << endlog();
00124                                 return false;
00125                             }
00126                             else
00127                                 bag_stack.top().first->add
00128                                     ( new Property<unsigned char>( name, description, value_string.empty() ? '\0' : value_string[0] ) );
00129                         }
00130                         else if ( type == "long" || type == "short")
00131                         {
00132                             if (type == "short") {
00133                                 log(Warning) << "Use type='long' instead of type='short' for Property '"<< name << "', since 16bit integers are not supported." <<endlog();
00134                                 log(Warning) << "Future versions of RTT will no longer map XML 'short' to C++ 'int' but to C++ 'short' Property objects." <<endlog();
00135                             }
00136                             int v;
00137                             if ( sscanf(value_string.c_str(), "%d", &v) == 1)
00138                                 bag_stack.top().first->add( new Property<int>( name, description, v ) );
00139                             else {
00140                                 log(Error) << "Wrong value for property '"+type+"'." \
00141                                     " Value should contain an integer value, got '"+ value_string +"'." << endlog();
00142                                 return false;
00143                             }
00144                         }
00145                         else if ( type == "ulong" || type == "ushort")
00146                         {
00147                             if (type == "ushort") {
00148                                 log(Warning) << "Use type='ulong' instead of type='ushort' for Property '"<< name << "', since 16bit integers are not supported." <<endlog();
00149                                 log(Warning) << "Future versions of RTT will no longer map XML 'ushort' to C++ 'unsigned int' but to C++ 'unsigned short' Property objects." <<endlog();
00150                             }
00151                             unsigned int v;
00152                             if ( sscanf(value_string.c_str(), "%u", &v) == 1)
00153                                 bag_stack.top().first->add( new Property<unsigned int>( name, description, v ) );
00154                             else {
00155                                 log(Error) << "Wrong value for property '"+type+"'." \
00156                                     " Value should contain an integer value, got '"+ value_string +"'." << endlog();
00157                                 return false;
00158                             }
00159                         }
00160                         else if ( type == "double")
00161                         {
00162                             double v;
00163                             if ( sscanf(value_string.c_str(), "%lf", &v) == 1 )
00164                                 bag_stack.top().first->add
00165                                     ( new Property<double>( name, description, v ) );
00166                             else {
00167                                 log(Error) << "Wrong value for property '"+type+"'." \
00168                                     " Value should contain a double value, got '"+ value_string +"'." << endlog();
00169                                 return false;
00170                             }
00171                         }
00172                         else if ( type == "float")
00173                         {
00174                             float v;
00175                             if ( sscanf(value_string.c_str(), "%f", &v) == 1 )
00176                                 bag_stack.top().first->add
00177                                     ( new Property<float>( name, description, v ) );
00178                             else {
00179                                 log(Error) << "Wrong value for property '"+type+"'." \
00180                                     " Value should contain a float value, got '"+ value_string +"'." << endlog();
00181                                 return false;
00182                             }
00183                         }
00184                         else if ( type == "string")
00185                             bag_stack.top().first->add
00186                             ( new Property<std::string>( name, description, value_string ) );
00187                         else{
00188                                 log(Error)<<"Unknown type \""<<type<< "\" for for tag simple"<<endlog();
00189                                 return false;
00190                         }
00191                         tag_stack.pop();
00192                         value_string.clear(); // cleanup
00193                         description.clear();
00194                         name.clear();
00195                         break;
00196 
00197                     case TAG_SEQUENCE:
00198                     case TAG_STRUCT:
00199                         {
00200                             Property<PropertyBag>* prop = bag_stack.top().second;
00201                             bag_stack.pop();
00202                             bag_stack.top().first->add( prop );
00203                             //( new Property<PropertyBag>( pn, description, *pb ) );
00204                             //delete pb;
00205                             tag_stack.pop();
00206                             description.clear();
00207                             name.clear();
00208                             type.clear();
00209                         }
00210                         break;
00211 
00212                     case TAG_DESCRIPTION:
00213                         tag_stack.pop();
00214                         if ( tag_stack.top() == TAG_STRUCT ) {
00215                             // it is a description of a struct that ended
00216                             bag_stack.top().second->setDescription(description);
00217                             description.clear();
00218                         }
00219                         break;
00220                     case TAG_VALUE:
00221                     case TAG_PROPERTIES:
00222                     case TAG_UNKNOWN:
00223                         tag_stack.pop();
00224                         break;
00225 
00226                     }
00227                 return true;
00228             }
00229 
00230 
00231             void startElement(const char* localname,
00232                               const TiXmlAttribute* attributes )
00233             {
00234                 std::string ln = localname;
00235 
00236                 if ( ln == "properties" )
00237                     tag_stack.push( TAG_PROPERTIES );
00238                 else
00239                     if ( ln == "simple" )
00240                     {
00241                         tag_stack.push( TAG_SIMPLE );
00242                         name.clear();
00243                         type.clear();
00244                         while (attributes)
00245                         {
00246                             std::string an = attributes->Name();
00247                             if ( an == "name")
00248                             {
00249                                 name = attributes->Value();
00250                             }
00251                             else if ( an == "type")
00252                             {
00253                                 type = attributes->Value();
00254                             }
00255                             attributes = attributes->Next();
00256                         }
00257                     }
00258                     else
00259                         if ( ln == "struct" || ln == "sequence")
00260                         {
00261                             name.clear();
00262                             type.clear();
00263                             while (attributes)
00264                                 {
00265                                     std::string an = attributes->Name();
00266                                     if ( an == "name")
00267                                         {
00268                                             name = attributes->Value();
00269                                         }
00270                                     else if ( an == "type")
00271                                         {
00272                                             type = attributes->Value();
00273                                         }
00274                                     attributes = attributes->Next();
00275                                 }
00276                             if ( ln == "struct" )
00277                                 tag_stack.push( TAG_STRUCT );
00278                             else {
00279                                 tag_stack.push( TAG_SEQUENCE );
00280                                 type = "Sequence"; // override
00281                             }
00282 
00283                             Property<PropertyBag> *prop;
00284                             prop = new Property<PropertyBag>(name,"",PropertyBag(type));
00285 
00286                             // take reference to bag itself !
00287                             bag_stack.push(std::make_pair( &(prop->value()), prop));
00288                         }
00289                         else
00290                                 if ( ln == "description")
00291                                     tag_stack.push( TAG_DESCRIPTION );
00292                                 else
00293                                     if ( ln == "value"  )
00294                                         tag_stack.push( TAG_VALUE );
00295                                     else {
00296                                         log(Warning) << "Unrecognised XML tag :"<< ln <<": ignoring." << endlog();
00297                                         tag_stack.push( TAG_UNKNOWN );
00298                                     }
00299             }
00300 
00301             void characters( const char* chars )
00302             {
00303                 switch ( tag_stack.top() )
00304                 {
00305                     case TAG_DESCRIPTION:
00306                         description = chars;
00307                         break;
00308 
00309                     case TAG_VALUE:
00310                         value_string = chars;;
00311                         break;
00312                     case TAG_STRUCT:
00313                     case TAG_SIMPLE:
00314                     case TAG_SEQUENCE:
00315                     case TAG_PROPERTIES:
00316                     case TAG_UNKNOWN:
00317                         break;
00318                 }
00319             }
00320 
00321             bool populateBag(TiXmlNode* pParent)
00322             {
00323                 if ( !pParent )
00324                     return false;
00325 
00326                 TiXmlNode* pChild;
00327                 TiXmlText* pText;
00328                 int t = pParent->Type();
00329 
00330                 switch ( t )
00331                     {
00332                     case TiXmlNode::ELEMENT:
00333                         // notify start of new element
00334                         this->startElement( pParent->Value(), pParent->ToElement()->FirstAttribute() );
00335 
00336                         // recurse in children, if any
00337                         for ( pChild = pParent->FirstChild(); pChild != 0; pChild = pChild->NextSibling())
00338                             {
00339                                 if ( this->populateBag( pChild ) == false){
00340                                         log(Error)<<"Error in element at line "<<pChild->Row() << endlog();
00341                                     return false;
00342                                 }
00343                             }
00344 
00345                         // notify end of element
00346                         if ( this->endElement() == false )
00347                             return false;
00348                         break;
00349 
00350                     case TiXmlNode::TEXT:
00351                         pText = pParent->ToText();
00352                         this->characters( pText->Value() );
00353                         break;
00354 
00355                         // not interested in these...
00356                     case TiXmlNode::DECLARATION:
00357                     case TiXmlNode::COMMENT:
00358                     case TiXmlNode::UNKNOWN:
00359                     case TiXmlNode::DOCUMENT:
00360                     default:
00361                         break;
00362                     }
00363             return true;
00364             }
00365         };
00366     }
00367 
00368     using namespace detail;
00369 
00370     class TinyDemarshaller::D {
00371     public:
00372         D(const std::string& f) : doc( f.c_str() ), loadOkay(false) {}
00373         TiXmlDocument doc;
00374         bool loadOkay;
00375     };
00376 
00377     TinyDemarshaller::TinyDemarshaller( const std::string& filename )
00378         : d( new TinyDemarshaller::D(filename) )
00379     {
00380         Logger::In in("TinyDemarshaller");
00381         d->loadOkay = d->doc.LoadFile();
00382 
00383         if ( !d->loadOkay ) {
00384             log(Error) << "Could not load " << filename << " Error: "<< d->doc.ErrorDesc() << endlog();
00385             return;
00386         }
00387 
00388     }
00389 
00390     TinyDemarshaller::~TinyDemarshaller()
00391     {
00392         delete d;
00393     }
00394 
00395     bool TinyDemarshaller::deserialize( PropertyBag &v )
00396     {
00397         Logger::In in("TinyDemarshaller");
00398 
00399         if ( !d->loadOkay )
00400             return false;
00401 
00402                 TiXmlHandle docHandle( &d->doc );
00403                 TiXmlHandle propHandle = docHandle.FirstChildElement( "properties" );
00404 
00405         if ( ! propHandle.Node() ) {
00406             log(Error) << "No <properties> element found in document!"<< endlog();
00407             return false;
00408         }
00409 
00410         detail::Tiny2CPFHandler proc( v );
00411 
00412         if ( proc.populateBag( propHandle.Node() ) == false) {
00413             deleteProperties( v );
00414             return false;
00415         }
00416         return true;
00417     }
00418 
00419 }
00420 


rtt
Author(s): RTT Developers
autogenerated on Wed Aug 26 2015 16:16:19