Orocos Real-Time Toolkit
2.5.0
|
00001 /*************************************************************************** 00002 tag: FMTC Tue Mar 11 21:49:20 CET 2008 CPFMarshaller.cpp 00003 00004 CPFMarshaller.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 "CPFMarshaller.hpp" 00040 #include "../rtt-config.h" 00041 00042 #include <iostream> 00043 using namespace std; 00044 namespace RTT { 00045 using namespace detail; 00046 template<class T> 00047 void CPFMarshaller<std::ostream>::doWrite( const Property<T> &v, const std::string& type ) 00048 { 00049 *(this->s) <<indent << "<simple "; 00050 if ( !v.getName().empty() ) 00051 *(this->s) <<"name=\"" << this->escape( v.getName() ) <<"\" "; 00052 *(this->s) << "type=\""<< type <<"\">"; 00053 if ( !v.getDescription().empty() ) 00054 *(this->s) << "<description>"<< this->escape( v.getDescription() ) << "</description>"; 00055 *(this->s) << "<value>" << v.get() << "</value></simple>\n"; 00056 } 00057 00058 void CPFMarshaller<std::ostream>::doWrite( const Property<std::string> &v, const std::string& type ) 00059 { 00060 *(this->s) <<indent << "<simple "; 00061 if ( !v.getName().empty() ) 00062 *(this->s) <<"name=\"" << this->escape( v.getName() ) <<"\" "; 00063 *(this->s) << "type=\""<< type <<"\">"; 00064 if ( !v.getDescription().empty() ) 00065 *(this->s) << "<description>"<< this->escape( v.getDescription() ) << "</description>"; 00066 *(this->s) << "<value>" << this->escape( v.get() ) << "</value></simple>\n"; 00067 } 00068 00069 00070 void CPFMarshaller<std::ostream>::doWrite( const Property<char> &v, const std::string& type ) 00071 { 00072 *(this->s) <<indent << "<simple "; 00073 if ( !v.getName().empty() ) 00074 *(this->s) <<"name=\"" << this->escape( v.getName() ) <<"\" "; 00075 *(this->s) << "type=\""<< type <<"\">"; 00076 if ( !v.getDescription().empty() ) 00077 *(this->s) << "<description>"<< this->escape( v.getDescription() ) << "</description>"; 00078 if ( v.get() == '\0' ) 00079 *(this->s)<< "<value></value></simple>\n"; 00080 else { 00081 std::string toescape(1, v.get()); 00082 *(this->s) << "<value>" << this->escape( toescape ) << "</value></simple>\n"; 00083 } 00084 } 00085 00086 00087 std::string CPFMarshaller<std::ostream>::escape(std::string s) 00088 { 00089 std::string::size_type n=0; 00090 // replace amps first. 00091 while ((n = s.find("&",n)) != s.npos) { 00092 s.replace(n, 1, std::string("&")); 00093 n += 5; 00094 } 00095 00096 n=0; 00097 while ((n = s.find("<",n)) != s.npos) { 00098 s.replace(n, 1, std::string("<")); 00099 n += 4; 00100 } 00101 00102 n=0; 00103 while ((n = s.find(">",n)) != s.npos) { 00104 s.replace(n, 1, std::string(">")); 00105 n += 4; 00106 } 00107 00108 // TODO: Added escapes for other XML entities 00109 return s; 00110 } 00111 00112 00113 void CPFMarshaller<std::ostream>::introspect(PropertyBase* pb) 00114 { 00115 if (dynamic_cast<Property<unsigned char>* >(pb) ) 00116 return introspect( *static_cast<Property<unsigned char>* >(pb) ); 00117 if (dynamic_cast<Property<float>* >(pb) ) 00118 return introspect( *static_cast<Property<float>* >(pb) ); 00119 // Since the CPFDemarshaller maps 'short' and 'ushort' to int, we don't write out shorts as it would break 00120 // lots of existing files, where users use 'short' and 'long' interchangingly. 00121 // This could be finally resolved by using a conversion constructor, but the RTT typekit does not support 00122 // shorts... 00123 // if (dynamic_cast<Property<unsigned short>* >(pb) ) 00124 // return introspect( *static_cast<Property<unsigned short>* >(pb) ); 00125 // if (dynamic_cast<Property<short>* >(pb) ) 00126 // return introspect( *static_cast<Property<>* >(pb) ); 00127 log(Error) << "Couldn't write "<< pb->getName() << " to XML file because the " << pb->getType() << " type is not supported by the CPF format." <<endlog(); 00128 log(Error) << "If your type is a C++ struct or sequence, you can register it with a type info object." <<endlog(); 00129 log(Error) << "We only support these primitive types: boolean|char|double|float|long|octet|string|ulong." <<endlog(); 00130 } 00131 00132 00133 void CPFMarshaller<std::ostream>::introspect(Property<bool> &v) 00134 { 00135 doWrite( v, "boolean"); 00136 } 00137 00138 00139 void CPFMarshaller<std::ostream>::introspect(Property<char> &v) 00140 { 00141 doWrite( v, "char"); 00142 } 00143 00144 void CPFMarshaller<std::ostream>::introspect(Property<unsigned char> &v) 00145 { 00146 doWrite( v, "octet"); 00147 } 00148 00149 00150 void CPFMarshaller<std::ostream>::introspect(Property<int> &v) 00151 { 00152 doWrite( v, "long"); 00153 } 00154 00155 00156 void CPFMarshaller<std::ostream>::introspect(Property<unsigned int> &v) 00157 { 00158 doWrite( v, "ulong"); 00159 } 00160 00161 void CPFMarshaller<std::ostream>::introspect(Property<short> &v) 00162 { 00163 doWrite( v, "short"); 00164 } 00165 00166 00167 void CPFMarshaller<std::ostream>::introspect(Property<unsigned short> &v) 00168 { 00169 doWrite( v, "ushort"); 00170 } 00171 00172 void CPFMarshaller<std::ostream>::introspect(Property<float> &v) 00173 { 00174 (this->s)->precision(15); 00175 doWrite( v, "float"); 00176 } 00177 00178 void CPFMarshaller<std::ostream>::introspect(Property<double> &v) 00179 { 00180 (this->s)->precision(25); 00181 doWrite( v, "double"); 00182 } 00183 00184 00185 void CPFMarshaller<std::ostream>::introspect(Property<std::string> &v) 00186 { 00187 doWrite( v, "string"); 00188 } 00189 00190 00191 void CPFMarshaller<std::ostream>::introspect(Property<PropertyBag> &b) 00192 { 00193 PropertyBag v = b.get(); 00194 *(this->s) <<indent<<"<struct name=\""<<escape(b.getName())<<"\" type=\""<< escape(v.getType())<< "\">\n"; 00195 indent +=" "; 00196 if ( !b.getDescription().empty() ) 00197 *(this->s) <<indent<<"<description>" <<escape(b.getDescription()) << "</description>\n"; 00198 00199 b.value().identify(this); 00200 00201 indent = indent.substr(0, indent.length()-3); 00202 *(this->s) <<indent<<"</struct>\n"; 00203 } 00204 00205 CPFMarshaller<std::ostream>::CPFMarshaller(std::ostream &os) 00206 : StreamProcessor<std::ostream>(os), indent(" ") 00207 { 00208 } 00209 00210 CPFMarshaller<std::ostream>::CPFMarshaller(const std::string& filename) 00211 : StreamProcessor<std::ostream>(mfile), 00212 mfile(filename.c_str(), std::fstream::out), 00213 indent(" ") 00214 { 00215 if ( !mfile ) { 00216 s = 0; 00217 log(Error) << "Could not open file for writing: "<<filename <<endlog(); 00218 } 00219 } 00220 00221 00222 void CPFMarshaller<std::ostream>::serialize(PropertyBase* v) 00223 { 00224 if (s) 00225 v->identify( this ); 00226 } 00227 00228 00229 void CPFMarshaller<std::ostream>::serialize(const PropertyBag &v) 00230 { 00231 if ( !s ) 00232 return; 00233 *(this->s) <<"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" 00234 <<"<!DOCTYPE properties SYSTEM \"cpf.dtd\">\n"; 00235 *(this->s) <<"<properties>\n"; 00236 00237 v.identify(this); 00238 00239 *(this->s) << "</properties>\n"; 00240 } 00241 00242 00243 void CPFMarshaller<std::ostream>::flush() 00244 { 00245 if (s) 00246 this->s->flush(); 00247 } 00248 } 00249