Orocos Real-Time Toolkit  2.9.0
CPFMarshaller.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  tag: FMTC Tue Mar 11 21:49:20 CET 2008 CPFMarshaller.cpp
3 
4  CPFMarshaller.cpp - description
5  -------------------
6  begin : Tue March 11 2008
7  copyright : (C) 2008 FMTC
8  email : peter.soetens@fmtc.be
9 
10  ***************************************************************************
11  * This library is free software; you can redistribute it and/or *
12  * modify it under the terms of the GNU General Public *
13  * License as published by the Free Software Foundation; *
14  * version 2 of the License. *
15  * *
16  * As a special exception, you may use this file as part of a free *
17  * software library without restriction. Specifically, if other files *
18  * instantiate templates or use macros or inline functions from this *
19  * file, or you compile this file and link it with other files to *
20  * produce an executable, this file does not by itself cause the *
21  * resulting executable to be covered by the GNU General Public *
22  * License. This exception does not however invalidate any other *
23  * reasons why the executable file might be covered by the GNU General *
24  * Public License. *
25  * *
26  * This library is distributed in the hope that it will be useful, *
27  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
28  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
29  * Lesser General Public License for more details. *
30  * *
31  * You should have received a copy of the GNU General Public *
32  * License along with this library; if not, write to the Free Software *
33  * Foundation, Inc., 59 Temple Place, *
34  * Suite 330, Boston, MA 02111-1307 USA *
35  * *
36  ***************************************************************************/
37 
38 
39 #include "CPFMarshaller.hpp"
40 #include "../rtt-config.h"
41 
42 #include <iostream>
43 using namespace std;
44 namespace RTT {
45  using namespace detail;
46  template<class T>
47  void CPFMarshaller<std::ostream>::doWrite( const Property<T> &v, const std::string& type )
48  {
49  *(this->s) <<indent << "<simple ";
50  if ( !v.getName().empty() )
51  *(this->s) <<"name=\"" << this->escape( v.getName() ) <<"\" ";
52  *(this->s) << "type=\""<< type <<"\">";
53  if ( !v.getDescription().empty() )
54  *(this->s) << "<description>"<< this->escape( v.getDescription() ) << "</description>";
55  *(this->s) << "<value>" << v.get() << "</value></simple>\n";
56  }
57 
58  void CPFMarshaller<std::ostream>::doWrite( const Property<std::string> &v, const std::string& type )
59  {
60  *(this->s) <<indent << "<simple ";
61  if ( !v.getName().empty() )
62  *(this->s) <<"name=\"" << this->escape( v.getName() ) <<"\" ";
63  *(this->s) << "type=\""<< type <<"\">";
64  if ( !v.getDescription().empty() )
65  *(this->s) << "<description>"<< this->escape( v.getDescription() ) << "</description>";
66  *(this->s) << "<value>" << this->escape( v.get() ) << "</value></simple>\n";
67  }
68 
69 
70  void CPFMarshaller<std::ostream>::doWrite( const Property<char> &v, const std::string& type )
71  {
72  *(this->s) <<indent << "<simple ";
73  if ( !v.getName().empty() )
74  *(this->s) <<"name=\"" << this->escape( v.getName() ) <<"\" ";
75  *(this->s) << "type=\""<< type <<"\">";
76  if ( !v.getDescription().empty() )
77  *(this->s) << "<description>"<< this->escape( v.getDescription() ) << "</description>";
78  if ( v.get() == '\0' )
79  *(this->s)<< "<value></value></simple>\n";
80  else {
81  std::string toescape(1, v.get());
82  *(this->s) << "<value>" << this->escape( toescape ) << "</value></simple>\n";
83  }
84  }
85 
86 
87  std::string CPFMarshaller<std::ostream>::escape(std::string s)
88  {
89  std::string::size_type n=0;
90  // replace amps first.
91  while ((n = s.find("&",n)) != s.npos) {
92  s.replace(n, 1, std::string("&amp;"));
93  n += 5;
94  }
95 
96  n=0;
97  while ((n = s.find("<",n)) != s.npos) {
98  s.replace(n, 1, std::string("&lt;"));
99  n += 4;
100  }
101 
102  n=0;
103  while ((n = s.find(">",n)) != s.npos) {
104  s.replace(n, 1, std::string("&gt;"));
105  n += 4;
106  }
107 
108  // TODO: Added escapes for other XML entities
109  return s;
110  }
111 
112 
113  void CPFMarshaller<std::ostream>::introspect(PropertyBase* pb)
114  {
115  if (dynamic_cast<Property<unsigned char>* >(pb) )
116  return introspect( *static_cast<Property<unsigned char>* >(pb) );
117  if (dynamic_cast<Property<float>* >(pb) )
118  return introspect( *static_cast<Property<float>* >(pb) );
119  // Since the CPFDemarshaller maps 'short' and 'ushort' to int, we don't write out shorts as it would break
120  // lots of existing files, where users use 'short' and 'long' interchangingly.
121  // This could be finally resolved by using a conversion constructor, but the RTT typekit does not support
122  // shorts...
123  // if (dynamic_cast<Property<unsigned short>* >(pb) )
124  // return introspect( *static_cast<Property<unsigned short>* >(pb) );
125  // if (dynamic_cast<Property<short>* >(pb) )
126  // return introspect( *static_cast<Property<>* >(pb) );
127  log(Error) << "Couldn't write "<< pb->getName() << " to XML file because the " << pb->getType() << " type is not supported by the CPF format." <<endlog();
128  log(Error) << "If your type is a C++ struct or sequence, you can register it with a type info object." <<endlog();
129  log(Error) << "We only support these primitive types: boolean|char|double|float|long|octet|string|ulong." <<endlog();
130  }
131 
132 
133  void CPFMarshaller<std::ostream>::introspect(Property<bool> &v)
134  {
135  doWrite( v, "boolean");
136  }
137 
138 
139  void CPFMarshaller<std::ostream>::introspect(Property<char> &v)
140  {
141  doWrite( v, "char");
142  }
143 
144  void CPFMarshaller<std::ostream>::introspect(Property<unsigned char> &v)
145  {
146  doWrite( v, "octet");
147  }
148 
149 
150  void CPFMarshaller<std::ostream>::introspect(Property<int> &v)
151  {
152  doWrite( v, "long");
153  }
154 
155 
156  void CPFMarshaller<std::ostream>::introspect(Property<unsigned int> &v)
157  {
158  doWrite( v, "ulong");
159  }
160 
161  void CPFMarshaller<std::ostream>::introspect(Property<short> &v)
162  {
163  doWrite( v, "short");
164  }
165 
166 
167  void CPFMarshaller<std::ostream>::introspect(Property<unsigned short> &v)
168  {
169  doWrite( v, "ushort");
170  }
171 
172  void CPFMarshaller<std::ostream>::introspect(Property<long long> &v)
173  {
174  doWrite( v, "llong");
175  }
176 
177  void CPFMarshaller<std::ostream>::introspect(Property<unsigned long long> &v)
178  {
179  doWrite( v, "ullong");
180  }
181 
182  void CPFMarshaller<std::ostream>::introspect(Property<float> &v)
183  {
184  (this->s)->precision(15);
185  doWrite( v, "float");
186  }
187 
188  void CPFMarshaller<std::ostream>::introspect(Property<double> &v)
189  {
190  (this->s)->precision(25);
191  doWrite( v, "double");
192  }
193 
194 
195  void CPFMarshaller<std::ostream>::introspect(Property<std::string> &v)
196  {
197  doWrite( v, "string");
198  }
199 
200 
201  void CPFMarshaller<std::ostream>::introspect(Property<PropertyBag> &b)
202  {
203  PropertyBag v = b.get();
204  *(this->s) <<indent<<"<struct name=\""<<escape(b.getName())<<"\" type=\""<< escape(v.getType())<< "\">\n";
205  indent +=" ";
206  if ( !b.getDescription().empty() )
207  *(this->s) <<indent<<"<description>" <<escape(b.getDescription()) << "</description>\n";
208 
209  b.value().identify(this);
210 
211  indent = indent.substr(0, indent.length()-3);
212  *(this->s) <<indent<<"</struct>\n";
213  }
214 
215  CPFMarshaller<std::ostream>::CPFMarshaller(std::ostream &os)
216  : StreamProcessor<std::ostream>(os), indent(" ")
217  {
218  }
219 
220  CPFMarshaller<std::ostream>::CPFMarshaller(const std::string& filename)
221  : StreamProcessor<std::ostream>(mfile),
222  mfile(filename.c_str(), std::fstream::out),
223  indent(" ")
224  {
225  if ( !mfile ) {
226  s = 0;
227  log(Error) << "Could not open file for writing: "<<filename <<endlog();
228  }
229  }
230 
231 
232  void CPFMarshaller<std::ostream>::serialize(PropertyBase* v)
233  {
234  if (s)
235  v->identify( this );
236  }
237 
238 
239  void CPFMarshaller<std::ostream>::serialize(const PropertyBag &v)
240  {
241  if ( !s )
242  return;
243  *(this->s) <<"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
244  <<"<!DOCTYPE properties SYSTEM \"cpf.dtd\">\n";
245  *(this->s) <<"<properties>\n";
246 
247  v.identify(this);
248 
249  *(this->s) << "</properties>\n";
250  }
251 
252 
254  {
255  if (s)
256  this->s->flush();
257  }
258 }
259 
STL namespace.
void serialize(Archive &a, RTT::ConnPolicy &c, unsigned int)
Serializes RTT::ConnPolicy objects.
Contains TaskContext, Activity, OperationCaller, Operation, Property, InputPort, OutputPort, Attribute.
Definition: Activity.cpp:52
CPFMarshaller(std::ostream &os)
Construct a CPFMarshaller from a stream.
virtual void flush()
Flush all buffers, write footers.