BOSS 8.0.0
BESIII Offline Software System
Loading...
Searching...
No Matches
XmlRpcValue.cpp
Go to the documentation of this file.
1
2#include "XmlRpcValue.h"
3#include "XmlRpcException.h"
4#include "XmlRpcUtil.h"
5#include "base64.h"
6
7#ifndef MAKEDEPEND
8# include <iostream>
9# include <ostream>
10# include <stdio.h>
11# include <stdlib.h>
12#endif
13
14namespace XmlRpc {
15
16 static const char VALUE_TAG[] = "<value>";
17 static const char VALUE_ETAG[] = "</value>";
18
19 static const char BOOLEAN_TAG[] = "<boolean>";
20 static const char BOOLEAN_ETAG[] = "</boolean>";
21 static const char DOUBLE_TAG[] = "<double>";
22 static const char DOUBLE_ETAG[] = "</double>";
23 static const char INT_TAG[] = "<int>";
24 static const char I4_TAG[] = "<i4>";
25 static const char I4_ETAG[] = "</i4>";
26 static const char STRING_TAG[] = "<string>";
27 static const char DATETIME_TAG[] = "<dateTime.iso8601>";
28 static const char DATETIME_ETAG[] = "</dateTime.iso8601>";
29 static const char BASE64_TAG[] = "<base64>";
30 static const char BASE64_ETAG[] = "</base64>";
31
32 static const char ARRAY_TAG[] = "<array>";
33 static const char DATA_TAG[] = "<data>";
34 static const char DATA_ETAG[] = "</data>";
35 static const char ARRAY_ETAG[] = "</array>";
36
37 static const char STRUCT_TAG[] = "<struct>";
38 static const char MEMBER_TAG[] = "<member>";
39 static const char NAME_TAG[] = "<name>";
40 static const char NAME_ETAG[] = "</name>";
41 static const char MEMBER_ETAG[] = "</member>";
42 static const char STRUCT_ETAG[] = "</struct>";
43
44 // Format strings
45 std::string XmlRpcValue::_doubleFormat( "%f" );
46
47 // Clean up
49 switch ( _type )
50 {
51 case TypeString: delete _value.asString; break;
52 case TypeDateTime: delete _value.asTime; break;
53 case TypeBase64: delete _value.asBinary; break;
54 case TypeArray: delete _value.asArray; break;
55 case TypeStruct: delete _value.asStruct; break;
56 default: break;
57 }
59 _value.asBinary = 0;
60 }
61
62 // Type checking
64 if ( _type == TypeInvalid )
65 {
66 _type = t;
67 switch ( _type )
68 { // Ensure there is a valid value for the type
69 case TypeString: _value.asString = new std::string(); break;
70 case TypeDateTime: _value.asTime = new struct tm(); break;
71 case TypeBase64: _value.asBinary = new BinaryData(); break;
72 case TypeArray: _value.asArray = new ValueArray(); break;
73 case TypeStruct: _value.asStruct = new ValueStruct(); break;
74 default: _value.asBinary = 0; break;
75 }
76 }
77 else if ( _type != t ) throw XmlRpcException( "type error" );
78 }
79
80 void XmlRpcValue::assertArray( int size ) const {
81 if ( _type != TypeArray ) throw XmlRpcException( "type error: expected an array" );
82 else if ( int( _value.asArray->size() ) < size )
83 throw XmlRpcException( "range error: array index too large" );
84 }
85
87 if ( _type == TypeInvalid )
88 {
90 _value.asArray = new ValueArray( size );
91 }
92 else if ( _type == TypeArray )
93 {
94 if ( int( _value.asArray->size() ) < size ) _value.asArray->resize( size );
95 }
96 else throw XmlRpcException( "type error: expected an array" );
97 }
98
100 if ( _type == TypeInvalid )
101 {
103 _value.asStruct = new ValueStruct();
104 }
105 else if ( _type != TypeStruct ) throw XmlRpcException( "type error: expected a struct" );
106 }
107
108 // Operators
110 if ( this != &rhs )
111 {
112 invalidate();
113 _type = rhs._type;
114 switch ( _type )
115 {
116 case TypeBoolean: _value.asBool = rhs._value.asBool; break;
117 case TypeInt: _value.asInt = rhs._value.asInt; break;
118 case TypeDouble: _value.asDouble = rhs._value.asDouble; break;
119 case TypeDateTime: _value.asTime = new struct tm( *rhs._value.asTime ); break;
120 case TypeString: _value.asString = new std::string( *rhs._value.asString ); break;
121 case TypeBase64: _value.asBinary = new BinaryData( *rhs._value.asBinary ); break;
122 case TypeArray: _value.asArray = new ValueArray( *rhs._value.asArray ); break;
123 case TypeStruct: _value.asStruct = new ValueStruct( *rhs._value.asStruct ); break;
124 default: _value.asBinary = 0; break;
125 }
126 }
127 return *this;
128 }
129
130 // Predicate for tm equality
131 static bool tmEq( struct tm const& t1, struct tm const& t2 ) {
132 return t1.tm_sec == t2.tm_sec && t1.tm_min == t2.tm_min && t1.tm_hour == t2.tm_hour &&
133 t1.tm_mday == t1.tm_mday && t1.tm_mon == t2.tm_mon && t1.tm_year == t2.tm_year;
134 }
135
136 bool XmlRpcValue::operator==( XmlRpcValue const& other ) const {
137 if ( _type != other._type ) return false;
138
139 switch ( _type )
140 {
141 case TypeBoolean:
142 return ( !_value.asBool && !other._value.asBool ) ||
143 ( _value.asBool && other._value.asBool );
144 case TypeInt: return _value.asInt == other._value.asInt;
145 case TypeDouble: return _value.asDouble == other._value.asDouble;
146 case TypeDateTime: return tmEq( *_value.asTime, *other._value.asTime );
147 case TypeString: return *_value.asString == *other._value.asString;
148 case TypeBase64: return *_value.asBinary == *other._value.asBinary;
149 case TypeArray: return *_value.asArray == *other._value.asArray;
150
151 // The map<>::operator== requires the definition of value< for kcc
152 case TypeStruct: // return *_value.asStruct == *other._value.asStruct;
153 {
154 if ( _value.asStruct->size() != other._value.asStruct->size() ) return false;
155
156 ValueStruct::const_iterator it1 = _value.asStruct->begin();
157 ValueStruct::const_iterator it2 = other._value.asStruct->begin();
158 while ( it1 != _value.asStruct->end() )
159 {
160 const XmlRpcValue& v1 = it1->second;
161 const XmlRpcValue& v2 = it2->second;
162 if ( !( v1 == v2 ) ) return false;
163 it1++;
164 it2++;
165 }
166 return true;
167 }
168 default: break;
169 }
170 return true; // Both invalid values ...
171 }
172
173 bool XmlRpcValue::operator!=( XmlRpcValue const& other ) const {
174 return !( *this == other );
175 }
176
177 // Works for strings, binary data, arrays, and structs.
178 int XmlRpcValue::size() const {
179 switch ( _type )
180 {
181 case TypeString: return int( _value.asString->size() );
182 case TypeBase64: return int( _value.asBinary->size() );
183 case TypeArray: return int( _value.asArray->size() );
184 case TypeStruct: return int( _value.asStruct->size() );
185 default: break;
186 }
187
188 throw XmlRpcException( "type error" );
189 }
190
191 // Checks for existence of struct member
192 bool XmlRpcValue::hasMember( const std::string& name ) const {
193 return _type == TypeStruct && _value.asStruct->find( name ) != _value.asStruct->end();
194 }
195
196 // Set the value from xml. The chars at *offset into valueXml
197 // should be the start of a <value> tag. Destroys any existing value.
198 bool XmlRpcValue::fromXml( std::string const& valueXml, int* offset ) {
199 int savedOffset = *offset;
200
201 invalidate();
202 if ( !XmlRpcUtil::nextTagIs( VALUE_TAG, valueXml, offset ) )
203 return false; // Not a value, offset not updated
204
205 int afterValueOffset = *offset;
206 std::string typeTag = XmlRpcUtil::getNextTag( valueXml, offset );
207 bool result = false;
208 if ( typeTag == BOOLEAN_TAG ) result = boolFromXml( valueXml, offset );
209 else if ( typeTag == I4_TAG || typeTag == INT_TAG )
210 result = intFromXml( valueXml, offset );
211 else if ( typeTag == DOUBLE_TAG ) result = doubleFromXml( valueXml, offset );
212 else if ( typeTag.empty() || typeTag == STRING_TAG )
213 result = stringFromXml( valueXml, offset );
214 else if ( typeTag == DATETIME_TAG ) result = timeFromXml( valueXml, offset );
215 else if ( typeTag == BASE64_TAG ) result = binaryFromXml( valueXml, offset );
216 else if ( typeTag == ARRAY_TAG ) result = arrayFromXml( valueXml, offset );
217 else if ( typeTag == STRUCT_TAG ) result = structFromXml( valueXml, offset );
218 // Watch for empty/blank strings with no <string>tag
219 else if ( typeTag == VALUE_ETAG )
220 {
221 *offset = afterValueOffset; // back up & try again
222 result = stringFromXml( valueXml, offset );
223 }
224
225 if ( result ) // Skip over the </value> tag
226 XmlRpcUtil::findTag( VALUE_ETAG, valueXml, offset );
227 else // Unrecognized tag after <value>
228 *offset = savedOffset;
229
230 return result;
231 }
232
233 // Encode the Value in xml
234 std::string XmlRpcValue::toXml() const {
235 switch ( _type )
236 {
237 case TypeBoolean: return boolToXml();
238 case TypeInt: return intToXml();
239 case TypeDouble: return doubleToXml();
240 case TypeString: return stringToXml();
241 case TypeDateTime: return timeToXml();
242 case TypeBase64: return binaryToXml();
243 case TypeArray: return arrayToXml();
244 case TypeStruct: return structToXml();
245 default: break;
246 }
247 return std::string(); // Invalid value
248 }
249
250 // Boolean
251 bool XmlRpcValue::boolFromXml( std::string const& valueXml, int* offset ) {
252 const char* valueStart = valueXml.c_str() + *offset;
253 char* valueEnd;
254 long ivalue = strtol( valueStart, &valueEnd, 10 );
255 if ( valueEnd == valueStart || ( ivalue != 0 && ivalue != 1 ) ) return false;
256
258 _value.asBool = ( ivalue == 1 );
259 *offset += int( valueEnd - valueStart );
260 return true;
261 }
262
263 std::string XmlRpcValue::boolToXml() const {
264 std::string xml = VALUE_TAG;
265 xml += BOOLEAN_TAG;
266 xml += ( _value.asBool ? "1" : "0" );
267 xml += BOOLEAN_ETAG;
268 xml += VALUE_ETAG;
269 return xml;
270 }
271
272 // Int
273 bool XmlRpcValue::intFromXml( std::string const& valueXml, int* offset ) {
274 const char* valueStart = valueXml.c_str() + *offset;
275 char* valueEnd;
276 long ivalue = strtol( valueStart, &valueEnd, 10 );
277 if ( valueEnd == valueStart ) return false;
278
279 _type = TypeInt;
280 _value.asInt = int( ivalue );
281 *offset += int( valueEnd - valueStart );
282 return true;
283 }
284
285 std::string XmlRpcValue::intToXml() const {
286 char buf[256];
287 snprintf( buf, sizeof( buf ) - 1, "%d", _value.asInt );
288 buf[sizeof( buf ) - 1] = 0;
289 std::string xml = VALUE_TAG;
290 xml += I4_TAG;
291 xml += buf;
292 xml += I4_ETAG;
293 xml += VALUE_ETAG;
294 return xml;
295 }
296
297 // Double
298 bool XmlRpcValue::doubleFromXml( std::string const& valueXml, int* offset ) {
299 const char* valueStart = valueXml.c_str() + *offset;
300 char* valueEnd;
301 double dvalue = strtod( valueStart, &valueEnd );
302 if ( valueEnd == valueStart ) return false;
303
305 _value.asDouble = dvalue;
306 *offset += int( valueEnd - valueStart );
307 return true;
308 }
309
310 std::string XmlRpcValue::doubleToXml() const {
311 char buf[256];
312 snprintf( buf, sizeof( buf ) - 1, getDoubleFormat().c_str(), _value.asDouble );
313 buf[sizeof( buf ) - 1] = 0;
314
315 std::string xml = VALUE_TAG;
316 xml += DOUBLE_TAG;
317 xml += buf;
318 xml += DOUBLE_ETAG;
319 xml += VALUE_ETAG;
320 return xml;
321 }
322
323 // String
324 bool XmlRpcValue::stringFromXml( std::string const& valueXml, int* offset ) {
325 size_t valueEnd = valueXml.find( '<', *offset );
326 if ( valueEnd == std::string::npos ) return false; // No end tag;
327
329 _value.asString = new std::string(
330 XmlRpcUtil::xmlDecode( valueXml.substr( *offset, valueEnd - *offset ) ) );
331 *offset += int( _value.asString->length() );
332 return true;
333 }
334
335 std::string XmlRpcValue::stringToXml() const {
336 std::string xml = VALUE_TAG;
337 // xml += STRING_TAG; optional
338 xml += XmlRpcUtil::xmlEncode( *_value.asString );
339 // xml += STRING_ETAG;
340 xml += VALUE_ETAG;
341 return xml;
342 }
343
344 // DateTime (stored as a struct tm)
345 bool XmlRpcValue::timeFromXml( std::string const& valueXml, int* offset ) {
346 size_t valueEnd = valueXml.find( '<', *offset );
347 if ( valueEnd == std::string::npos ) return false; // No end tag;
348
349 std::string stime = valueXml.substr( *offset, valueEnd - *offset );
350
351 struct tm t;
352 if ( sscanf( stime.c_str(), "%4d%2d%2dT%2d:%2d:%2d", &t.tm_year, &t.tm_mon, &t.tm_mday,
353 &t.tm_hour, &t.tm_min, &t.tm_sec ) != 6 )
354 return false;
355
356 t.tm_isdst = -1;
358 _value.asTime = new struct tm( t );
359 *offset += int( stime.length() );
360 return true;
361 }
362
363 std::string XmlRpcValue::timeToXml() const {
364 struct tm* t = _value.asTime;
365 char buf[20];
366 snprintf( buf, sizeof( buf ) - 1, "%4d%02d%02dT%02d:%02d:%02d", t->tm_year, t->tm_mon,
367 t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec );
368 buf[sizeof( buf ) - 1] = 0;
369
370 std::string xml = VALUE_TAG;
371 xml += DATETIME_TAG;
372 xml += buf;
373 xml += DATETIME_ETAG;
374 xml += VALUE_ETAG;
375 return xml;
376 }
377
378 // Base64
379 bool XmlRpcValue::binaryFromXml( std::string const& valueXml, int* offset ) {
380 size_t valueEnd = valueXml.find( '<', *offset );
381 if ( valueEnd == std::string::npos ) return false; // No end tag;
382
384 std::string asString = valueXml.substr( *offset, valueEnd - *offset );
385 _value.asBinary = new BinaryData();
386 // check whether base64 encodings can contain chars xml encodes...
387
388 // convert from base64 to binary
389 int iostatus = 0;
390 base64<char> decoder;
391 std::back_insert_iterator<BinaryData> ins = std::back_inserter( *( _value.asBinary ) );
392 decoder.get( asString.begin(), asString.end(), ins, iostatus );
393
394 *offset += int( asString.length() );
395 return true;
396 }
397
398 std::string XmlRpcValue::binaryToXml() const {
399 // convert to base64
400 std::vector<char> base64data;
401 int iostatus = 0;
402 base64<char> encoder;
403 std::back_insert_iterator<std::vector<char>> ins = std::back_inserter( base64data );
404 encoder.put( _value.asBinary->begin(), _value.asBinary->end(), ins, iostatus,
405 base64<>::crlf() );
406
407 // Wrap with xml
408 std::string xml = VALUE_TAG;
409 xml += BASE64_TAG;
410 xml.append( base64data.begin(), base64data.end() );
411 xml += BASE64_ETAG;
412 xml += VALUE_ETAG;
413 return xml;
414 }
415
416 // Array
417 bool XmlRpcValue::arrayFromXml( std::string const& valueXml, int* offset ) {
418 if ( !XmlRpcUtil::nextTagIs( DATA_TAG, valueXml, offset ) ) return false;
419
421 _value.asArray = new ValueArray;
423 while ( v.fromXml( valueXml, offset ) ) _value.asArray->push_back( v ); // copy...
424
425 // Skip the trailing </data>
426 (void)XmlRpcUtil::nextTagIs( DATA_ETAG, valueXml, offset );
427 return true;
428 }
429
430 // In general, its preferable to generate the xml of each element of the
431 // array as it is needed rather than glomming up one big string.
432 std::string XmlRpcValue::arrayToXml() const {
433 std::string xml = VALUE_TAG;
434 xml += ARRAY_TAG;
435 xml += DATA_TAG;
436
437 int s = int( _value.asArray->size() );
438 for ( int i = 0; i < s; ++i ) xml += _value.asArray->at( i ).toXml();
439
440 xml += DATA_ETAG;
441 xml += ARRAY_ETAG;
442 xml += VALUE_ETAG;
443 return xml;
444 }
445
446 // Struct
447 bool XmlRpcValue::structFromXml( std::string const& valueXml, int* offset ) {
449 _value.asStruct = new ValueStruct;
450
451 while ( XmlRpcUtil::nextTagIs( MEMBER_TAG, valueXml, offset ) )
452 {
453 // name
454 const std::string name = XmlRpcUtil::parseTag( NAME_TAG, valueXml, offset );
455 // value
456 XmlRpcValue val( valueXml, offset );
457 if ( !val.valid() )
458 {
459 invalidate();
460 return false;
461 }
462 const std::pair<const std::string, XmlRpcValue> p( name, val );
463 _value.asStruct->insert( p );
464
465 (void)XmlRpcUtil::nextTagIs( MEMBER_ETAG, valueXml, offset );
466 }
467 return true;
468 }
469
470 // In general, its preferable to generate the xml of each element
471 // as it is needed rather than glomming up one big string.
472 std::string XmlRpcValue::structToXml() const {
473 std::string xml = VALUE_TAG;
474 xml += STRUCT_TAG;
475
476 ValueStruct::const_iterator it;
477 for ( it = _value.asStruct->begin(); it != _value.asStruct->end(); ++it )
478 {
479 xml += MEMBER_TAG;
480 xml += NAME_TAG;
481 xml += XmlRpcUtil::xmlEncode( it->first );
482 xml += NAME_ETAG;
483 xml += it->second.toXml();
484 xml += MEMBER_ETAG;
485 }
486
487 xml += STRUCT_ETAG;
488 xml += VALUE_ETAG;
489 return xml;
490 }
491
492 // Write the value without xml encoding it
493 std::ostream& XmlRpcValue::write( std::ostream& os ) const {
494 switch ( _type )
495 {
496 default: break;
497 case TypeBoolean: os << _value.asBool; break;
498 case TypeInt: os << _value.asInt; break;
499 case TypeDouble: os << _value.asDouble; break;
500 case TypeString: os << *_value.asString; break;
501 case TypeDateTime: {
502 struct tm* t = _value.asTime;
503 char buf[20];
504 snprintf( buf, sizeof( buf ) - 1, "%4d%02d%02dT%02d:%02d:%02d", t->tm_year, t->tm_mon,
505 t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec );
506 buf[sizeof( buf ) - 1] = 0;
507 os << buf;
508 break;
509 }
510 case TypeBase64: {
511 int iostatus = 0;
512 std::ostreambuf_iterator<char> out( os );
513 base64<char> encoder;
514 encoder.put( _value.asBinary->begin(), _value.asBinary->end(), out, iostatus,
515 base64<>::crlf() );
516 break;
517 }
518 case TypeArray: {
519 int s = int( _value.asArray->size() );
520 os << '{';
521 for ( int i = 0; i < s; ++i )
522 {
523 if ( i > 0 ) os << ',';
524 _value.asArray->at( i ).write( os );
525 }
526 os << '}';
527 break;
528 }
529 case TypeStruct: {
530 os << '[';
531 ValueStruct::const_iterator it;
532 for ( it = _value.asStruct->begin(); it != _value.asStruct->end(); ++it )
533 {
534 if ( it != _value.asStruct->begin() ) os << ',';
535 os << it->first << ':';
536 it->second.write( os );
537 }
538 os << ']';
539 break;
540 }
541 }
542
543 return os;
544 }
545
546} // namespace XmlRpc
547
548// ostream
549std::ostream& operator<<( std::ostream& os, XmlRpc::XmlRpcValue& v ) {
550 // If you want to output in xml format:
551 // return os << v.toXml();
552 return v.write( os );
553}
XmlRpcServer s
**********Class see also m_nmax DOUBLE PRECISION m_amel DOUBLE PRECISION m_x2 DOUBLE PRECISION m_alfinv DOUBLE PRECISION m_Xenph INTEGER m_KeyWtm INTEGER m_idyfs DOUBLE PRECISION m_zini DOUBLE PRECISION m_q2 DOUBLE PRECISION m_Wt_KF DOUBLE PRECISION m_WtCut INTEGER m_KFfin *COMMON c_KarLud $ !Input CMS energy[GeV] $ !CMS energy after beam spread beam strahlung[GeV] $ !Beam energy spread[GeV] $ !z boost due to beam spread $ !electron beam mass *ff pair spectrum $ !minimum v
Definition KarLud.h:35
std::ostream & operator<<(std::ostream &os, XmlRpc::XmlRpcValue &v)
static bool nextTagIs(const char *tag, std::string const &xml, int *offset)
static std::string parseTag(const char *tag, std::string const &xml, int *offset)
Returns contents between <tag> and </tag>, updates offset to char after </tag>.
static std::string xmlEncode(const std::string &raw)
Convert raw text to encoded xml.
static bool findTag(const char *tag, std::string const &xml, int *offset)
Returns true if the tag is found and updates offset to the char after the tag.
static std::string getNextTag(std::string const &xml, int *offset)
static std::string xmlDecode(const std::string &encoded)
Convert encoded xml to raw text.
RPC method arguments and results are represented by Values.
Definition XmlRpcValue.h:22
std::vector< char > BinaryData
Definition XmlRpcValue.h:37
std::string intToXml() const
std::string doubleToXml() const
bool timeFromXml(std::string const &valueXml, int *offset)
bool hasMember(const std::string &name) const
Check for the existence of a struct member by name.
ValueStruct * asStruct
bool operator==(XmlRpcValue const &other) const
bool binaryFromXml(std::string const &valueXml, int *offset)
int size() const
Return the size for string, base64, array, and struct values.
XmlRpcValue & operator=(XmlRpcValue const &rhs)
bool intFromXml(std::string const &valueXml, int *offset)
void assertArray(int size) const
std::string arrayToXml() const
std::string timeToXml() const
void assertTypeOrInvalid(Type t)
std::string structToXml() const
bool doubleFromXml(std::string const &valueXml, int *offset)
ValueArray * asArray
bool arrayFromXml(std::string const &valueXml, int *offset)
bool operator!=(XmlRpcValue const &other) const
std::string * asString
bool fromXml(std::string const &valueXml, int *offset)
Decode xml. Destroys any existing value.
bool structFromXml(std::string const &valueXml, int *offset)
std::string binaryToXml() const
static std::string _doubleFormat
union XmlRpc::XmlRpcValue::@050363270230164230256327115202057142222030207371 _value
std::map< std::string, XmlRpcValue > ValueStruct
Definition XmlRpcValue.h:39
std::string boolToXml() const
static std::string const & getDoubleFormat()
Return the format used to write double values.
std::vector< XmlRpcValue > ValueArray
Definition XmlRpcValue.h:38
bool stringFromXml(std::string const &valueXml, int *offset)
std::ostream & write(std::ostream &os) const
Write the value (no xml encoding).
bool valid() const
Return true if the value has been set to something.
bool boolFromXml(std::string const &valueXml, int *offset)
BinaryData * asBinary
std::string toXml() const
Encode the Value in xml.
std::string stringToXml() const
XmlRpcValue()
Constructors.
Definition XmlRpcValue.h:42
_II put(_II _First, _II _Last, _OI _To, _State &_St, _Endline _Endl) const
Definition base64.h:129
_II get(_II _First, _II _Last, _OI _To, _State &_St) const
Definition base64.h:198
int t()
Definition t.c:1