~ubuntu-branches/ubuntu/wily/flrig/wily

« back to all changes in this revision

Viewing changes to .pc/0001-License-Declaration.patch/src/xmlrpcpp/XmlRpcValue.cpp

  • Committer: Package Import Robot
  • Author(s): Kamal Mostafa
  • Date: 2014-06-07 11:28:52 UTC
  • Revision ID: package-import@ubuntu.com-20140607112852-pj9xhtlvwpgqjy5x
Tags: 1.3.15-1
* Initial release (Closes: #750861)
  flrig version 1.3.15 plus the following upstream commits:
  - 0001-License-Declaration.patch
  - 0002-FL_APPS-folder.patch
  - 0003-rig-home-dir.patch
  - 0004-RTS-DTR-restore.patch

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
//
 
2
// XmlRpc++ Copyright (c) 2002-2008 by Chris Morley
 
3
//
 
4
 
 
5
#include "XmlRpcValue.h"
 
6
#include "XmlRpcException.h"
 
7
#include "XmlRpcUtil.h"
 
8
#include "base64.h"
 
9
 
 
10
#include <iostream>
 
11
#include <ostream>
 
12
#include <stdlib.h>
 
13
#include <stdio.h>
 
14
 
 
15
 
 
16
namespace XmlRpc {
 
17
 
 
18
 
 
19
  static const char VALUE_TAG[]     = "value";
 
20
  static const char NIL_TAG[]       = "nil";
 
21
  static const char BOOLEAN_TAG[]   = "boolean";
 
22
  static const char DOUBLE_TAG[]    = "double";
 
23
  static const char INT_TAG[]       = "int";
 
24
  static const char I4_TAG[]        = "i4";
 
25
  static const char STRING_TAG[]    = "string";
 
26
  static const char DATETIME_TAG[]  = "dateTime.iso8601";
 
27
  static const char BASE64_TAG[]    = "base64";
 
28
 
 
29
  static const char ARRAY_TAG[]     = "array";
 
30
  static const char DATA_TAG[]      = "data";
 
31
 
 
32
  static const char STRUCT_TAG[]    = "struct";
 
33
  static const char MEMBER_TAG[]    = "member";
 
34
  static const char NAME_TAG[]      = "name";
 
35
 
 
36
      
 
37
  // Format strings
 
38
  std::string XmlRpcValue::_doubleFormat("%f");
 
39
 
 
40
 
 
41
 
 
42
  // Clean up
 
43
  void XmlRpcValue::invalidate()
 
44
  {
 
45
    switch (_type) {
 
46
      case TypeString:    delete _value.asString; break;
 
47
      case TypeDateTime:  delete _value.asTime;   break;
 
48
      case TypeBase64:    delete _value.asBinary; break;
 
49
      case TypeArray:     delete _value.asArray;  break;
 
50
      case TypeStruct:    delete _value.asStruct; break;
 
51
      default: break;
 
52
    }
 
53
    _type = TypeInvalid;
 
54
    _value.asBinary = 0;
 
55
  }
 
56
 
 
57
  
 
58
  // Type checking
 
59
  void XmlRpcValue::assertType(Type t) const
 
60
  {
 
61
    if (_type != t)
 
62
    {
 
63
      throw XmlRpcException("type error");
 
64
    }
 
65
  }
 
66
 
 
67
  void XmlRpcValue::assertType(Type t)
 
68
  {
 
69
    if (_type == TypeInvalid)
 
70
    {
 
71
      _type = t;
 
72
      switch (_type) {    // Ensure there is a valid value for the type
 
73
        case TypeString:   _value.asString = new std::string(); break;
 
74
        case TypeDateTime: _value.asTime = new struct tm();     break;
 
75
        case TypeBase64:   _value.asBinary = new BinaryData();  break;
 
76
        case TypeArray:    _value.asArray = new ValueArray();   break;
 
77
        case TypeStruct:   _value.asStruct = new ValueStruct(); break;
 
78
        default:           _value.asBinary = 0; break;
 
79
      }
 
80
    }
 
81
    else if (_type != t)
 
82
    {
 
83
      throw XmlRpcException("type error");
 
84
    }
 
85
  }
 
86
 
 
87
  void XmlRpcValue::assertArray(int size) const
 
88
  {
 
89
    if (_type != TypeArray)
 
90
      throw XmlRpcException("type error: expected an array");
 
91
    else if (int(_value.asArray->size()) < size)
 
92
      throw XmlRpcException("range error: array index too large");
 
93
  }
 
94
 
 
95
 
 
96
  void XmlRpcValue::assertArray(int size)
 
97
  {
 
98
    if (_type == TypeInvalid) {
 
99
      _type = TypeArray;
 
100
      _value.asArray = new ValueArray(size);
 
101
    } else if (_type == TypeArray) {
 
102
      if (int(_value.asArray->size()) < size)
 
103
        _value.asArray->resize(size);
 
104
    } else
 
105
      throw XmlRpcException("type error: expected an array");
 
106
  }
 
107
 
 
108
  void XmlRpcValue::assertStruct()
 
109
  {
 
110
    if (_type == TypeInvalid) {
 
111
      _type = TypeStruct;
 
112
      _value.asStruct = new ValueStruct();
 
113
    } else if (_type != TypeStruct)
 
114
      throw XmlRpcException("type error: expected a struct");
 
115
  }
 
116
 
 
117
 
 
118
  // Operators
 
119
  XmlRpcValue& XmlRpcValue::operator=(XmlRpcValue const& rhs)
 
120
  {
 
121
    if (this != &rhs)
 
122
    {
 
123
      invalidate();
 
124
      _type = rhs._type;
 
125
      switch (_type) {
 
126
        case TypeBoolean:  _value.asBool = rhs._value.asBool; break;
 
127
        case TypeInt:      _value.asInt = rhs._value.asInt; break;
 
128
        case TypeDouble:   _value.asDouble = rhs._value.asDouble; break;
 
129
        case TypeDateTime: _value.asTime = new struct tm(*rhs._value.asTime); break;
 
130
        case TypeString:   _value.asString = new std::string(*rhs._value.asString); break;
 
131
        case TypeBase64:   _value.asBinary = new BinaryData(*rhs._value.asBinary); break;
 
132
        case TypeArray:    _value.asArray = new ValueArray(*rhs._value.asArray); break;
 
133
        case TypeStruct:   _value.asStruct = new ValueStruct(*rhs._value.asStruct); break;
 
134
        default:           _value.asBinary = 0; break;
 
135
      }
 
136
    }
 
137
    return *this;
 
138
  }
 
139
 
 
140
 
 
141
  // Predicate for tm equality
 
142
  static bool tmEq(struct tm const& t1, struct tm const& t2) {
 
143
    return t1.tm_sec == t2.tm_sec && t1.tm_min == t2.tm_min &&
 
144
            t1.tm_hour == t2.tm_hour && t1.tm_mday == t1.tm_mday &&
 
145
            t1.tm_mon == t2.tm_mon && t1.tm_year == t2.tm_year;
 
146
  }
 
147
 
 
148
  bool XmlRpcValue::operator==(XmlRpcValue const& other) const
 
149
  {
 
150
    if (_type != other._type)
 
151
      return false;
 
152
 
 
153
    switch (_type) {
 
154
      case TypeBoolean:  return ( !_value.asBool && !other._value.asBool) ||
 
155
                                ( _value.asBool && other._value.asBool);
 
156
      case TypeInt:      return _value.asInt == other._value.asInt;
 
157
      case TypeDouble:   return _value.asDouble == other._value.asDouble;
 
158
      case TypeDateTime: return tmEq(*_value.asTime, *other._value.asTime);
 
159
      case TypeString:   return *_value.asString == *other._value.asString;
 
160
      case TypeBase64:   return *_value.asBinary == *other._value.asBinary;
 
161
      case TypeArray:    return *_value.asArray == *other._value.asArray;
 
162
 
 
163
      // The map<>::operator== requires the definition of value< for kcc
 
164
      case TypeStruct:   //return *_value.asStruct == *other._value.asStruct;
 
165
        {
 
166
          if (_value.asStruct->size() != other._value.asStruct->size())
 
167
            return false;
 
168
          
 
169
          ValueStruct::const_iterator it1=_value.asStruct->begin();
 
170
          ValueStruct::const_iterator it2=other._value.asStruct->begin();
 
171
          while (it1 != _value.asStruct->end()) {
 
172
            const XmlRpcValue& v1 = it1->second;
 
173
            const XmlRpcValue& v2 = it2->second;
 
174
            if ( ! (v1 == v2))
 
175
              return false;
 
176
            it1++;
 
177
            it2++;
 
178
          }
 
179
          return true;
 
180
        }
 
181
      default: break;
 
182
    }
 
183
    return true;    // Both invalid values ...
 
184
  }
 
185
 
 
186
  bool XmlRpcValue::operator!=(XmlRpcValue const& other) const
 
187
  {
 
188
    return !(*this == other);
 
189
  }
 
190
 
 
191
 
 
192
  // Works for strings, binary data, arrays, and structs.
 
193
  int XmlRpcValue::size() const
 
194
  {
 
195
    switch (_type) {
 
196
      case TypeString: return int(_value.asString->size());
 
197
      case TypeBase64: return int(_value.asBinary->size());
 
198
      case TypeArray:  return int(_value.asArray->size());
 
199
      case TypeStruct: return int(_value.asStruct->size());
 
200
      default: break;
 
201
    }
 
202
 
 
203
    throw XmlRpcException("type error");
 
204
  }
 
205
 
 
206
  // Checks for existence of struct member
 
207
  bool XmlRpcValue::hasMember(const std::string& name) const
 
208
  {
 
209
    return _type == TypeStruct && _value.asStruct->find(name) != _value.asStruct->end();
 
210
  }
 
211
 
 
212
 
 
213
  // Set the value from xml. The chars at *offset into valueXml 
 
214
  // should be the start of a <value> tag. Destroys any existing value.
 
215
  bool XmlRpcValue::fromXml(std::string const& valueXml, int* offset)
 
216
  {
 
217
    int savedOffset = *offset;
 
218
 
 
219
    invalidate();
 
220
    bool emptyTag;
 
221
    if ( ! XmlRpcUtil::nextTagIs(VALUE_TAG, valueXml, offset, &emptyTag))
 
222
      return false;       // Not a value, offset not updated
 
223
 
 
224
    // No value? Pretend its an empty string...
 
225
    if (emptyTag)
 
226
    {
 
227
      *this = "";
 
228
      return true;
 
229
    }
 
230
 
 
231
    // No type tag? Assume string
 
232
    bool result = true;
 
233
    int valueOffset = *offset;
 
234
    if (XmlRpcUtil::nextTagIsEnd(VALUE_TAG, valueXml, offset))
 
235
    {
 
236
      return stringFromXml(valueXml, &valueOffset);
 
237
    }
 
238
    else if (XmlRpcUtil::nextTagIs(NIL_TAG, valueXml, offset, &emptyTag))
 
239
    {
 
240
      _type = TypeNil;
 
241
      result = true;
 
242
    }
 
243
    else if (XmlRpcUtil::nextTagIs(BOOLEAN_TAG, valueXml, offset, &emptyTag))
 
244
    {
 
245
      if (emptyTag)
 
246
        *this = false;
 
247
      else
 
248
        result = boolFromXml(valueXml, offset) && 
 
249
                 XmlRpcUtil::nextTagIsEnd(BOOLEAN_TAG, valueXml, offset);
 
250
    }
 
251
    else if (XmlRpcUtil::nextTagIs(I4_TAG, valueXml, offset, &emptyTag))
 
252
    {
 
253
      if (emptyTag)
 
254
        *this = 0;
 
255
      else
 
256
        result = intFromXml(valueXml, offset) && 
 
257
                 XmlRpcUtil::nextTagIsEnd(I4_TAG, valueXml, offset);
 
258
    }
 
259
    else if (XmlRpcUtil::nextTagIs(INT_TAG, valueXml, offset, &emptyTag))
 
260
    {
 
261
      if (emptyTag)
 
262
        *this = 0;
 
263
      else
 
264
        result = intFromXml(valueXml, offset) && 
 
265
                 XmlRpcUtil::nextTagIsEnd(INT_TAG, valueXml, offset);
 
266
    }
 
267
    else if (XmlRpcUtil::nextTagIs(DOUBLE_TAG, valueXml, offset, &emptyTag))
 
268
    {
 
269
      if (emptyTag)
 
270
        *this = 0.0;
 
271
      else
 
272
        result = doubleFromXml(valueXml, offset) && 
 
273
                 XmlRpcUtil::nextTagIsEnd(DOUBLE_TAG, valueXml, offset);
 
274
    }
 
275
    else if (XmlRpcUtil::nextTagIs(STRING_TAG, valueXml, offset, &emptyTag))
 
276
    {
 
277
      if (emptyTag)
 
278
        *this = "";
 
279
      else
 
280
        result = stringFromXml(valueXml, offset) && 
 
281
                 XmlRpcUtil::nextTagIsEnd(STRING_TAG, valueXml, offset);
 
282
    }
 
283
    else if (XmlRpcUtil::nextTagIs(DATETIME_TAG, valueXml, offset, &emptyTag))
 
284
    {
 
285
      if (emptyTag)
 
286
        result = false;
 
287
      else
 
288
        result = timeFromXml(valueXml, offset) && 
 
289
                 XmlRpcUtil::nextTagIsEnd(DATETIME_TAG, valueXml, offset);
 
290
    }
 
291
    else if (XmlRpcUtil::nextTagIs(BASE64_TAG, valueXml, offset, &emptyTag))
 
292
    {
 
293
      if (emptyTag)
 
294
        result = binaryFromXml("", 0);
 
295
      else
 
296
        result = binaryFromXml(valueXml, offset) && 
 
297
                 XmlRpcUtil::nextTagIsEnd(BASE64_TAG, valueXml, offset);
 
298
    }
 
299
    else if (XmlRpcUtil::nextTagIs(ARRAY_TAG, valueXml, offset, &emptyTag))
 
300
    {
 
301
      if (emptyTag)
 
302
        result = false;
 
303
      else
 
304
        result = arrayFromXml(valueXml, offset) && 
 
305
                 XmlRpcUtil::nextTagIsEnd(ARRAY_TAG, valueXml, offset);
 
306
    }
 
307
    else if (XmlRpcUtil::nextTagIs(STRUCT_TAG, valueXml, offset, &emptyTag))
 
308
    {
 
309
      if (emptyTag)
 
310
        result = false;
 
311
      else
 
312
        result = structFromXml(valueXml, offset) && 
 
313
                 XmlRpcUtil::nextTagIsEnd(STRUCT_TAG, valueXml, offset);
 
314
    }
 
315
 
 
316
    // Unrecognized tag after <value> or no </value>
 
317
    if ( ! result || ! XmlRpcUtil::nextTagIsEnd(VALUE_TAG, valueXml, offset))
 
318
    {
 
319
      *offset = savedOffset;
 
320
      return false;
 
321
    }
 
322
 
 
323
    return true;
 
324
  }
 
325
 
 
326
  // Encode the Value in xml
 
327
  std::string XmlRpcValue::toXml() const
 
328
  {
 
329
    switch (_type) {
 
330
      case TypeNil:      return nilToXml();
 
331
      case TypeBoolean:  return boolToXml();
 
332
      case TypeInt:      return intToXml();
 
333
      case TypeDouble:   return doubleToXml();
 
334
      case TypeString:   return stringToXml();
 
335
      case TypeDateTime: return timeToXml();
 
336
      case TypeBase64:   return binaryToXml();
 
337
      case TypeArray:    return arrayToXml();
 
338
      case TypeStruct:   return structToXml();
 
339
      default: break;
 
340
    }
 
341
    return std::string();   // Invalid value
 
342
  }
 
343
 
 
344
 
 
345
  // Boolean
 
346
  bool XmlRpcValue::boolFromXml(std::string const& valueXml, int* offset)
 
347
  {
 
348
    const char* valueStart = valueXml.c_str() + *offset;
 
349
    char* valueEnd;
 
350
    long ivalue = strtol(valueStart, &valueEnd, 10);
 
351
    if (valueEnd == valueStart || (ivalue != 0 && ivalue != 1))
 
352
      return false;
 
353
 
 
354
    _type = TypeBoolean;
 
355
    _value.asBool = (ivalue == 1);
 
356
    *offset += int(valueEnd - valueStart);
 
357
    return true;
 
358
  }
 
359
 
 
360
  std::string XmlRpcValue::nilToXml() const
 
361
  {
 
362
    return "<value><nil/></value>";
 
363
  }
 
364
 
 
365
  std::string XmlRpcValue::boolToXml() const
 
366
  {
 
367
    static std::string booleanTrueXml("<value><boolean>1</boolean></value>");
 
368
    static std::string booleanFalseXml("<value><boolean>0</boolean></value>");
 
369
    return _value.asBool ? booleanTrueXml : booleanFalseXml;
 
370
  }
 
371
 
 
372
  // Int
 
373
  bool XmlRpcValue::intFromXml(std::string const& valueXml, int* offset)
 
374
  {
 
375
    const char* valueStart = valueXml.c_str() + *offset;
 
376
    char* valueEnd;
 
377
    long ivalue = strtol(valueStart, &valueEnd, 10);
 
378
    if (valueEnd == valueStart)
 
379
      return false;
 
380
 
 
381
    _type = TypeInt;
 
382
    _value.asInt = int(ivalue);
 
383
    *offset += int(valueEnd - valueStart);
 
384
    return true;
 
385
  }
 
386
 
 
387
  std::string XmlRpcValue::intToXml() const
 
388
  {
 
389
    char buf[256];
 
390
    snprintf(buf, sizeof(buf)-1, "<value><i4>%d</i4></value>", _value.asInt);
 
391
    buf[sizeof(buf)-1] = 0;
 
392
 
 
393
    return std::string(buf);
 
394
  }
 
395
 
 
396
  // Double
 
397
  bool XmlRpcValue::doubleFromXml(std::string const& valueXml, int* offset)
 
398
  {
 
399
    const char* valueStart = valueXml.c_str() + *offset;
 
400
    char* valueEnd;
 
401
    double dvalue = strtod(valueStart, &valueEnd);
 
402
    if (valueEnd == valueStart)
 
403
      return false;
 
404
 
 
405
    _type = TypeDouble;
 
406
    _value.asDouble = dvalue;
 
407
    *offset += int(valueEnd - valueStart);
 
408
    return true;
 
409
  }
 
410
 
 
411
  std::string XmlRpcValue::doubleToXml() const
 
412
  {
 
413
    char fmtbuf[256], buf[256];
 
414
    snprintf(fmtbuf, sizeof(fmtbuf)-1, "<value><double>%s</double></value>", getDoubleFormat().c_str());
 
415
    fmtbuf[sizeof(fmtbuf)-1] = 0;
 
416
    snprintf(buf, sizeof(buf)-1, fmtbuf, _value.asDouble);
 
417
    buf[sizeof(buf)-1] = 0;
 
418
 
 
419
    return std::string(buf);
 
420
  }
 
421
 
 
422
  // String
 
423
  bool XmlRpcValue::stringFromXml(std::string const& valueXml, int* offset)
 
424
  {
 
425
    size_t valueEnd = valueXml.find('<', *offset);
 
426
    if (valueEnd == std::string::npos)
 
427
      return false;     // No end tag;
 
428
 
 
429
    _type = TypeString;
 
430
    _value.asString = new std::string(XmlRpcUtil::xmlDecode(valueXml.substr(*offset, valueEnd-*offset)));
 
431
    *offset += int(_value.asString->length());
 
432
    return true;
 
433
  }
 
434
 
 
435
  std::string XmlRpcValue::stringToXml() const
 
436
  {
 
437
    return std::string("<value>") + XmlRpcUtil::xmlEncode(*_value.asString) + std::string("</value>");
 
438
  }
 
439
 
 
440
  // DateTime (stored as a struct tm)
 
441
  bool XmlRpcValue::timeFromXml(std::string const& valueXml, int* offset)
 
442
  {
 
443
    size_t valueEnd = valueXml.find('<', *offset);
 
444
    if (valueEnd == std::string::npos)
 
445
      return false;     // No end tag;
 
446
 
 
447
    std::string stime = valueXml.substr(*offset, valueEnd-*offset);
 
448
 
 
449
    struct tm t;
 
450
    if (sscanf(stime.c_str(),"%4d%2d%2dT%2d:%2d:%2d",&t.tm_year,&t.tm_mon,&t.tm_mday,&t.tm_hour,&t.tm_min,&t.tm_sec) != 6)
 
451
      return false;
 
452
 
 
453
    t.tm_year -= 1900;    //    years since 1900
 
454
    t.tm_mon -= 1;        //    months 0..11
 
455
    t.tm_isdst = -1;
 
456
    _type = TypeDateTime;
 
457
    _value.asTime = new struct tm(t);
 
458
    *offset += int(stime.length());
 
459
    return true;
 
460
  }
 
461
 
 
462
  std::string XmlRpcValue::timeToXml() const
 
463
  {
 
464
    struct tm* t = _value.asTime;
 
465
    char buf[20];
 
466
    snprintf(buf, sizeof(buf)-1, "%04d%02d%02dT%02d:%02d:%02d", 
 
467
      1900+t->tm_year,1+t->tm_mon,t->tm_mday,t->tm_hour,t->tm_min,t->tm_sec);
 
468
    buf[sizeof(buf)-1] = 0;
 
469
 
 
470
    return std::string("<value><dateTime.iso8601>") + buf + std::string("</dateTime.iso8601></value>");
 
471
  }
 
472
 
 
473
 
 
474
  // Base64
 
475
  bool XmlRpcValue::binaryFromXml(std::string const& valueXml, int* offset)
 
476
  {
 
477
    size_t valueEnd = valueXml.find('<', *offset);
 
478
    if (valueEnd == std::string::npos)
 
479
      return false;     // No end tag;
 
480
 
 
481
    _type = TypeBase64;
 
482
    std::string asString = valueXml.substr(*offset, valueEnd-*offset);
 
483
    _value.asBinary = new BinaryData();
 
484
    // check whether base64 encodings can contain chars xml encodes...
 
485
 
 
486
    // convert from base64 to binary
 
487
    int iostatus = 0;
 
488
          base64<char> decoder;
 
489
    std::back_insert_iterator<BinaryData> ins = std::back_inserter(*(_value.asBinary));
 
490
                decoder.get(asString.begin(), asString.end(), ins, iostatus);
 
491
 
 
492
    *offset += int(asString.length());
 
493
    return true;
 
494
  }
 
495
 
 
496
 
 
497
  std::string XmlRpcValue::binaryToXml() const
 
498
  {
 
499
    // convert to base64
 
500
    std::vector<char> base64data;
 
501
    int iostatus = 0;
 
502
    base64<char> encoder;
 
503
    std::back_insert_iterator<std::vector<char> > ins = std::back_inserter(base64data);
 
504
    encoder.put(_value.asBinary->begin(), _value.asBinary->end(), ins, iostatus, base64<>::crlf());
 
505
 
 
506
    // Wrap with xml
 
507
    std::string xml = "<value><base64>";
 
508
    xml.append(base64data.begin(), base64data.end());
 
509
    xml += "</base64></value>";
 
510
    return xml;
 
511
  }
 
512
 
 
513
 
 
514
  // Array
 
515
  bool XmlRpcValue::arrayFromXml(std::string const& valueXml, int* offset)
 
516
  {
 
517
    bool emptyTag;
 
518
    if ( ! XmlRpcUtil::nextTagIs(DATA_TAG, valueXml, offset, &emptyTag))
 
519
      return false;
 
520
 
 
521
    _type = TypeArray;
 
522
    _value.asArray = new ValueArray;
 
523
 
 
524
    if ( ! emptyTag)
 
525
    {
 
526
      XmlRpcValue v;
 
527
      while (v.fromXml(valueXml, offset))
 
528
        _value.asArray->push_back(v);       // copy...
 
529
 
 
530
      // Skip the trailing </data>
 
531
      (void) XmlRpcUtil::nextTagIsEnd(DATA_TAG, valueXml, offset);
 
532
    }
 
533
    return true;
 
534
  }
 
535
 
 
536
 
 
537
  // In general, its preferable to generate the xml of each element of the
 
538
  // array as it is needed rather than glomming up one big string.
 
539
  std::string XmlRpcValue::arrayToXml() const
 
540
  {
 
541
    std::string xml = "<value><array><data>";
 
542
 
 
543
    int s = int(_value.asArray->size());
 
544
    for (int i=0; i<s; ++i)
 
545
       xml += _value.asArray->at(i).toXml();
 
546
 
 
547
    xml += "</data></array></value>";
 
548
    return xml;
 
549
  }
 
550
 
 
551
 
 
552
  // Struct
 
553
  bool XmlRpcValue::structFromXml(std::string const& valueXml, int* offset)
 
554
  {
 
555
    _type = TypeStruct;
 
556
    _value.asStruct = new ValueStruct;
 
557
 
 
558
    std::string name;
 
559
    bool emptyTag;
 
560
    while (XmlRpcUtil::nextTagIs(MEMBER_TAG, valueXml, offset, &emptyTag))
 
561
    {
 
562
      if ( ! emptyTag)
 
563
      {
 
564
        if (XmlRpcUtil::parseTag(NAME_TAG, valueXml, offset, name))
 
565
        {
 
566
          // value
 
567
          XmlRpcValue val(valueXml, offset);
 
568
          if ( ! val.valid()) {
 
569
            invalidate();
 
570
            return false;
 
571
          }
 
572
          const std::pair<const std::string, XmlRpcValue> p(name, val);
 
573
          _value.asStruct->insert(p);
 
574
 
 
575
          (void) XmlRpcUtil::nextTagIsEnd(MEMBER_TAG, valueXml, offset);
 
576
        }
 
577
      }
 
578
    }
 
579
 
 
580
    return true;
 
581
  }
 
582
 
 
583
 
 
584
  // In general, its preferable to generate the xml of each element
 
585
  // as it is needed rather than glomming up one big string.
 
586
  std::string XmlRpcValue::structToXml() const
 
587
  {
 
588
    std::string xml = "<value><struct>";
 
589
 
 
590
    ValueStruct::const_iterator it;
 
591
    for (it=_value.asStruct->begin(); it!=_value.asStruct->end(); ++it)
 
592
    {
 
593
      xml += "<member><name>";
 
594
      xml += XmlRpcUtil::xmlEncode(it->first);
 
595
      xml += "</name>";
 
596
      xml += it->second.toXml();
 
597
      xml += "</member>";
 
598
    }
 
599
 
 
600
    xml += "</struct></value>";
 
601
    return xml;
 
602
  }
 
603
 
 
604
 
 
605
 
 
606
  // Write the value without xml encoding it
 
607
  std::ostream& XmlRpcValue::write(std::ostream& os) const {
 
608
    switch (_type) {
 
609
      default:           break;
 
610
      case TypeBoolean:  os << _value.asBool; break;
 
611
      case TypeInt:      os << _value.asInt; break;
 
612
      case TypeDouble:   os << _value.asDouble; break;
 
613
      case TypeString:   os << *_value.asString; break;
 
614
      case TypeDateTime:
 
615
        {
 
616
          struct tm* t = _value.asTime;
 
617
          char buf[20];
 
618
          snprintf(buf, sizeof(buf)-1, "%4d%02d%02dT%02d:%02d:%02d", 
 
619
            t->tm_year,t->tm_mon,t->tm_mday,t->tm_hour,t->tm_min,t->tm_sec);
 
620
          buf[sizeof(buf)-1] = 0;
 
621
          os << buf;
 
622
          break;
 
623
        }
 
624
      case TypeBase64:
 
625
        {
 
626
          int iostatus = 0;
 
627
          std::ostreambuf_iterator<char> out(os);
 
628
          base64<char> encoder;
 
629
          encoder.put(_value.asBinary->begin(), _value.asBinary->end(), out, iostatus, base64<>::crlf());
 
630
          break;
 
631
        }
 
632
      case TypeArray:
 
633
        {
 
634
          int s = int(_value.asArray->size());
 
635
          os << '{';
 
636
          for (int i=0; i<s; ++i)
 
637
          {
 
638
            if (i > 0) os << ',';
 
639
            _value.asArray->at(i).write(os);
 
640
          }
 
641
          os << '}';
 
642
          break;
 
643
        }
 
644
      case TypeStruct:
 
645
        {
 
646
          os << '[';
 
647
          ValueStruct::const_iterator it;
 
648
          for (it=_value.asStruct->begin(); it!=_value.asStruct->end(); ++it)
 
649
          {
 
650
            if (it!=_value.asStruct->begin()) os << ',';
 
651
            os << it->first << ':';
 
652
            it->second.write(os);
 
653
          }
 
654
          os << ']';
 
655
          break;
 
656
        }
 
657
      
 
658
    }
 
659
    
 
660
    return os;
 
661
  }
 
662
 
 
663
} // namespace XmlRpc
 
664
 
 
665
 
 
666
// ostream
 
667
std::ostream& operator<<(std::ostream& os, XmlRpc::XmlRpcValue& v) 
 
668
 
669
  // If you want to output in xml format:
 
670
  //return os << v.toXml(); 
 
671
  return v.write(os);
 
672
}
 
673