#include <XmlRpcValue.h>
Public Types | |
typedef std::vector< char > | BinaryData |
enum | Type { TypeInvalid, TypeBoolean, TypeInt, TypeDouble, TypeString, TypeDateTime, TypeBase64, TypeArray, TypeStruct } |
typedef std::vector< XmlRpcValue > | ValueArray |
typedef std::map< std::string, XmlRpcValue > | ValueStruct |
Public Member Functions | |
void | clear () |
Erase the current value. | |
bool | fromXml (std::string const &valueXml, int *offset) |
Decode xml. Destroys any existing value. | |
Type const & | getType () const |
Return the type of the value stored. Type. | |
bool | hasMember (const std::string &name) const |
Check for the existence of a struct member by name. | |
operator BinaryData & () | |
operator bool & () | |
operator double & () | |
operator int & () | |
operator std::string & () | |
operator struct tm & () | |
bool | operator!= (XmlRpcValue const &other) const |
XmlRpcValue & | operator= (const char *rhs) |
XmlRpcValue & | operator= (double const &rhs) |
XmlRpcValue & | operator= (int const &rhs) |
XmlRpcValue & | operator= (XmlRpcValue const &rhs) |
bool | operator== (XmlRpcValue const &other) const |
XmlRpcValue & | operator[] (const char *k) |
XmlRpcValue & | operator[] (std::string const &k) |
XmlRpcValue & | operator[] (int i) |
XmlRpcValue const & | operator[] (int i) const |
void | setSize (int size) |
Specify the size for array values. Array values will grow beyond this size if needed. | |
int | size () const |
Return the size for string, base64, array, and struct values. | |
std::string | toXml () const |
Encode the Value in xml. | |
bool | valid () const |
Return true if the value has been set to something. | |
std::ostream & | write (std::ostream &os) const |
Write the value (no xml encoding). | |
XmlRpcValue (XmlRpcValue const &rhs) | |
Copy. | |
XmlRpcValue (std::string const &xml, int *offset) | |
Construct from xml, beginning at *offset chars into the string, updates offset. | |
XmlRpcValue (void *value, int nBytes) | |
XmlRpcValue (struct tm *value) | |
XmlRpcValue (const char *value) | |
XmlRpcValue (std::string const &value) | |
XmlRpcValue (double value) | |
XmlRpcValue (int value) | |
XmlRpcValue (bool value) | |
XmlRpcValue () | |
Constructors. | |
~XmlRpcValue () | |
Destructor (make virtual if you want to subclass). | |
Static Public Member Functions | |
std::string const & | getDoubleFormat () |
Return the format used to write double values. | |
void | setDoubleFormat (const char *f) |
Specify the format used to write double values. | |
Protected Member Functions | |
bool | arrayFromXml (std::string const &valueXml, int *offset) |
std::string | arrayToXml () const |
void | assertArray (int size) |
void | assertArray (int size) const |
void | assertStruct () |
void | assertTypeOrInvalid (Type t) |
bool | binaryFromXml (std::string const &valueXml, int *offset) |
std::string | binaryToXml () const |
bool | boolFromXml (std::string const &valueXml, int *offset) |
std::string | boolToXml () const |
bool | doubleFromXml (std::string const &valueXml, int *offset) |
std::string | doubleToXml () const |
bool | intFromXml (std::string const &valueXml, int *offset) |
std::string | intToXml () const |
void | invalidate () |
bool | stringFromXml (std::string const &valueXml, int *offset) |
std::string | stringToXml () const |
bool | structFromXml (std::string const &valueXml, int *offset) |
std::string | structToXml () const |
bool | timeFromXml (std::string const &valueXml, int *offset) |
std::string | timeToXml () const |
Protected Attributes | |
Type | _type |
union { | |
ValueArray * asArray | |
BinaryData * asBinary | |
bool asBool | |
double asDouble | |
int asInt | |
std::string * asString | |
ValueStruct * asStruct | |
tm * asTime | |
} | _value |
Static Protected Attributes | |
std::string | _doubleFormat |
|
|
|
|
|
|
|
00026 { 00027 TypeInvalid, 00028 TypeBoolean, 00029 TypeInt, 00030 TypeDouble, 00031 TypeString, 00032 TypeDateTime, 00033 TypeBase64, 00034 TypeArray, 00035 TypeStruct 00036 };
|
|
Constructors.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
00060 : _type(TypeBase64) 00061 { 00062 _value.asBinary = new BinaryData((char*)value, ((char*)value)+nBytes); 00063 }
|
|
Construct from xml, beginning at *offset chars into the string, updates offset.
|
|
Copy.
00070 : _type(TypeInvalid) { *this = rhs; }
|
|
Destructor (make virtual if you want to subclass).
00073 { invalidate(); }
|
|
00460 { 00461 if ( ! XmlRpcUtil::nextTagIs(DATA_TAG, valueXml, offset)) 00462 return false; 00463 00464 _type = TypeArray; 00465 _value.asArray = new ValueArray; 00466 XmlRpcValue v; 00467 while (v.fromXml(valueXml, offset)) 00468 _value.asArray->push_back(v); // copy... 00469 00470 // Skip the trailing </data> 00471 (void) XmlRpcUtil::nextTagIs(DATA_ETAG, valueXml, offset); 00472 return true; 00473 }
|
|
00479 { 00480 std::string xml = VALUE_TAG; 00481 xml += ARRAY_TAG; 00482 xml += DATA_TAG; 00483 00484 int s = int(_value.asArray->size()); 00485 for (int i=0; i<s; ++i) 00486 xml += _value.asArray->at(i).toXml(); 00487 00488 xml += DATA_ETAG; 00489 xml += ARRAY_ETAG; 00490 xml += VALUE_ETAG; 00491 return xml; 00492 }
|
|
00097 { 00098 if (_type == TypeInvalid) { 00099 _type = TypeArray; 00100 _value.asArray = new ValueArray(size); 00101 } else if (_type == TypeArray) { 00102 if (int(_value.asArray->size()) < size) 00103 _value.asArray->resize(size); 00104 } else 00105 throw XmlRpcException("type error: expected an array"); 00106 }
|
|
00088 { 00089 if (_type != TypeArray) 00090 throw XmlRpcException("type error: expected an array"); 00091 else if (int(_value.asArray->size()) < size) 00092 throw XmlRpcException("range error: array index too large"); 00093 }
|
|
00109 { 00110 if (_type == TypeInvalid) { 00111 _type = TypeStruct; 00112 _value.asStruct = new ValueStruct(); 00113 } else if (_type != TypeStruct) 00114 throw XmlRpcException("type error: expected a struct"); 00115 }
|
|
00070 { 00071 if (_type == TypeInvalid) 00072 { 00073 _type = t; 00074 switch (_type) { // Ensure there is a valid value for the type 00075 case TypeString: _value.asString = new std::string(); break; 00076 case TypeDateTime: _value.asTime = new struct tm(); break; 00077 case TypeBase64: _value.asBinary = new BinaryData(); break; 00078 case TypeArray: _value.asArray = new ValueArray(); break; 00079 case TypeStruct: _value.asStruct = new ValueStruct(); break; 00080 default: _value.asBinary = 0; break; 00081 } 00082 } 00083 else if (_type != t) 00084 throw XmlRpcException("type error"); 00085 }
|
|
00418 { 00419 size_t valueEnd = valueXml.find('<', *offset); 00420 if (valueEnd == std::string::npos) 00421 return false; // No end tag; 00422 00423 _type = TypeBase64; 00424 std::string asString = valueXml.substr(*offset, valueEnd-*offset); 00425 _value.asBinary = new BinaryData(); 00426 // check whether base64 encodings can contain chars xml encodes... 00427 00428 // convert from base64 to binary 00429 int iostatus = 0; 00430 base64<char> decoder; 00431 std::back_insert_iterator<BinaryData> ins = std::back_inserter(*(_value.asBinary)); 00432 decoder.get(asString.begin(), asString.end(), ins, iostatus); 00433 00434 *offset += int(asString.length()); 00435 return true; 00436 }
|
|
00440 { 00441 // convert to base64 00442 std::vector<char> base64data; 00443 int iostatus = 0; 00444 base64<char> encoder; 00445 std::back_insert_iterator<std::vector<char> > ins = std::back_inserter(base64data); 00446 encoder.put(_value.asBinary->begin(), _value.asBinary->end(), ins, iostatus, base64<>::crlf()); 00447 00448 // Wrap with xml 00449 std::string xml = VALUE_TAG; 00450 xml += BASE64_TAG; 00451 xml.append(base64data.begin(), base64data.end()); 00452 xml += BASE64_ETAG; 00453 xml += VALUE_ETAG; 00454 return xml; 00455 }
|
|
00276 { 00277 const char* valueStart = valueXml.c_str() + *offset; 00278 char* valueEnd; 00279 long ivalue = strtol(valueStart, &valueEnd, 10); 00280 if (valueEnd == valueStart || (ivalue != 0 && ivalue != 1)) 00281 return false; 00282 00283 _type = TypeBoolean; 00284 _value.asBool = (ivalue == 1); 00285 *offset += int(valueEnd - valueStart); 00286 return true; 00287 }
|
|
00290 { 00291 std::string xml = VALUE_TAG; 00292 xml += BOOLEAN_TAG; 00293 xml += (_value.asBool ? "1" : "0"); 00294 xml += BOOLEAN_ETAG; 00295 xml += VALUE_ETAG; 00296 return xml; 00297 }
|
|
Erase the current value.
00076 { invalidate(); }
|
|
00329 { 00330 const char* valueStart = valueXml.c_str() + *offset; 00331 char* valueEnd; 00332 double dvalue = strtod(valueStart, &valueEnd); 00333 if (valueEnd == valueStart) 00334 return false; 00335 00336 _type = TypeDouble; 00337 _value.asDouble = dvalue; 00338 *offset += int(valueEnd - valueStart); 00339 return true; 00340 }
|
|
00343 { 00344 char buf[256]; 00345 snprintf(buf, sizeof(buf)-1, getDoubleFormat().c_str(), _value.asDouble); 00346 buf[sizeof(buf)-1] = 0; 00347 00348 std::string xml = VALUE_TAG; 00349 xml += DOUBLE_TAG; 00350 xml += buf; 00351 xml += DOUBLE_ETAG; 00352 xml += VALUE_ETAG; 00353 return xml; 00354 }
|
|
Decode xml. Destroys any existing value.
00215 { 00216 int savedOffset = *offset; 00217 00218 invalidate(); 00219 if ( ! XmlRpcUtil::nextTagIs(VALUE_TAG, valueXml, offset)) 00220 return false; // Not a value, offset not updated 00221 00222 int afterValueOffset = *offset; 00223 std::string typeTag = XmlRpcUtil::getNextTag(valueXml, offset); 00224 bool result = false; 00225 if (typeTag == BOOLEAN_TAG) 00226 result = boolFromXml(valueXml, offset); 00227 else if (typeTag == I4_TAG || typeTag == INT_TAG) 00228 result = intFromXml(valueXml, offset); 00229 else if (typeTag == DOUBLE_TAG) 00230 result = doubleFromXml(valueXml, offset); 00231 else if (typeTag.empty() || typeTag == STRING_TAG) 00232 result = stringFromXml(valueXml, offset); 00233 else if (typeTag == DATETIME_TAG) 00234 result = timeFromXml(valueXml, offset); 00235 else if (typeTag == BASE64_TAG) 00236 result = binaryFromXml(valueXml, offset); 00237 else if (typeTag == ARRAY_TAG) 00238 result = arrayFromXml(valueXml, offset); 00239 else if (typeTag == STRUCT_TAG) 00240 result = structFromXml(valueXml, offset); 00241 // Watch for empty/blank strings with no <string>tag 00242 else if (typeTag == VALUE_ETAG) 00243 { 00244 *offset = afterValueOffset; // back up & try again 00245 result = stringFromXml(valueXml, offset); 00246 } 00247 00248 if (result) // Skip over the </value> tag 00249 XmlRpcUtil::findTag(VALUE_ETAG, valueXml, offset); 00250 else // Unrecognized tag after <value> 00251 *offset = savedOffset; 00252 00253 return result; 00254 }
|
|
Return the format used to write double values.
00127 { return _doubleFormat; }
|
|
Return the type of the value stored. Type.
00105 { return _type; }
|
|
Check for the existence of a struct member by name.
00208 { 00209 return _type == TypeStruct && _value.asStruct->find(name) != _value.asStruct->end(); 00210 }
|
|
00301 { 00302 const char* valueStart = valueXml.c_str() + *offset; 00303 char* valueEnd; 00304 long ivalue = strtol(valueStart, &valueEnd, 10); 00305 if (valueEnd == valueStart) 00306 return false; 00307 00308 _type = TypeInt; 00309 _value.asInt = int(ivalue); 00310 *offset += int(valueEnd - valueStart); 00311 return true; 00312 }
|
|
00315 { 00316 char buf[256]; 00317 snprintf(buf, sizeof(buf)-1, "%d", _value.asInt); 00318 buf[sizeof(buf)-1] = 0; 00319 std::string xml = VALUE_TAG; 00320 xml += I4_TAG; 00321 xml += buf; 00322 xml += I4_ETAG; 00323 xml += VALUE_ETAG; 00324 return xml; 00325 }
|
|
00054 { 00055 switch (_type) { 00056 case TypeString: delete _value.asString; break; 00057 case TypeDateTime: delete _value.asTime; break; 00058 case TypeBase64: delete _value.asBinary; break; 00059 case TypeArray: delete _value.asArray; break; 00060 case TypeStruct: delete _value.asStruct; break; 00061 default: break; 00062 } 00063 _type = TypeInvalid; 00064 _value.asBinary = 0; 00065 }
|
|
00091 { assertTypeOrInvalid(TypeBase64); return *_value.asBinary; }
|
|
00087 { assertTypeOrInvalid(TypeBoolean); return _value.asBool; }
|
|
00089 { assertTypeOrInvalid(TypeDouble); return _value.asDouble; }
|
|
00088 { assertTypeOrInvalid(TypeInt); return _value.asInt; }
|
|
00090 { assertTypeOrInvalid(TypeString); return *_value.asString; }
|
|
00092 { assertTypeOrInvalid(TypeDateTime); return *_value.asTime; }
|
|
00187 { 00188 return !(*this == other); 00189 }
|
|
00082 { return operator=(XmlRpcValue(std::string(rhs))); }
|
|
00081 { return operator=(XmlRpcValue(rhs)); }
|
|
00080 { return operator=(XmlRpcValue(rhs)); }
|
|
00120 { 00121 if (this != &rhs) 00122 { 00123 invalidate(); 00124 _type = rhs._type; 00125 switch (_type) { 00126 case TypeBoolean: _value.asBool = rhs._value.asBool; break; 00127 case TypeInt: _value.asInt = rhs._value.asInt; break; 00128 case TypeDouble: _value.asDouble = rhs._value.asDouble; break; 00129 case TypeDateTime: _value.asTime = new struct tm(*rhs._value.asTime); break; 00130 case TypeString: _value.asString = new std::string(*rhs._value.asString); break; 00131 case TypeBase64: _value.asBinary = new BinaryData(*rhs._value.asBinary); break; 00132 case TypeArray: _value.asArray = new ValueArray(*rhs._value.asArray); break; 00133 case TypeStruct: _value.asStruct = new ValueStruct(*rhs._value.asStruct); break; 00134 default: _value.asBinary = 0; break; 00135 } 00136 } 00137 return *this; 00138 }
|
|
00149 { 00150 if (_type != other._type) 00151 return false; 00152 00153 switch (_type) { 00154 case TypeBoolean: return ( !_value.asBool && !other._value.asBool) || 00155 ( _value.asBool && other._value.asBool); 00156 case TypeInt: return _value.asInt == other._value.asInt; 00157 case TypeDouble: return _value.asDouble == other._value.asDouble; 00158 case TypeDateTime: return tmEq(*_value.asTime, *other._value.asTime); 00159 case TypeString: return *_value.asString == *other._value.asString; 00160 case TypeBase64: return *_value.asBinary == *other._value.asBinary; 00161 case TypeArray: return *_value.asArray == *other._value.asArray; 00162 00163 // The map<>::operator== requires the definition of value< for kcc 00164 case TypeStruct: //return *_value.asStruct == *other._value.asStruct; 00165 { 00166 if (_value.asStruct->size() != other._value.asStruct->size()) 00167 return false; 00168 00169 ValueStruct::const_iterator it1=_value.asStruct->begin(); 00170 ValueStruct::const_iterator it2=other._value.asStruct->begin(); 00171 while (it1 != _value.asStruct->end()) { 00172 const XmlRpcValue& v1 = it1->second; 00173 const XmlRpcValue& v2 = it2->second; 00174 if ( ! (v1 == v2)) 00175 return false; 00176 it1++; 00177 it2++; 00178 } 00179 return true; 00180 } 00181 default: break; 00182 } 00183 return true; // Both invalid values ... 00184 }
|
|
00098 { assertStruct(); std::string s(k); return (*_value.asStruct)[s]; }
|
|
00097 { assertStruct(); return (*_value.asStruct)[k]; }
|
|
00095 { assertArray(i+1); return _value.asArray->at(i); }
|
|
00094 { assertArray(i+1); return _value.asArray->at(i); }
|
|
Specify the format used to write double values.
00130 { _doubleFormat = f; }
|
|
Specify the size for array values. Array values will grow beyond this size if needed.
00111 { assertArray(size); }
|
|
Return the size for string, base64, array, and struct values.
00194 { 00195 switch (_type) { 00196 case TypeString: return int(_value.asString->size()); 00197 case TypeBase64: return int(_value.asBinary->size()); 00198 case TypeArray: return int(_value.asArray->size()); 00199 case TypeStruct: return int(_value.asStruct->size()); 00200 default: break; 00201 } 00202 00203 throw XmlRpcException("type error"); 00204 }
|
|
00358 { 00359 size_t valueEnd = valueXml.find('<', *offset); 00360 if (valueEnd == std::string::npos) 00361 return false; // No end tag; 00362 00363 _type = TypeString; 00364 _value.asString = new std::string(XmlRpcUtil::xmlDecode(valueXml.substr(*offset, valueEnd-*offset))); 00365 *offset += int(_value.asString->length()); 00366 return true; 00367 }
|
|
00370 { 00371 std::string xml = VALUE_TAG; 00372 //xml += STRING_TAG; optional 00373 xml += XmlRpcUtil::xmlEncode(*_value.asString); 00374 //xml += STRING_ETAG; 00375 xml += VALUE_ETAG; 00376 return xml; 00377 }
|
|
00497 { 00498 _type = TypeStruct; 00499 _value.asStruct = new ValueStruct; 00500 00501 while (XmlRpcUtil::nextTagIs(MEMBER_TAG, valueXml, offset)) { 00502 // name 00503 const std::string name = XmlRpcUtil::parseTag(NAME_TAG, valueXml, offset); 00504 // value 00505 XmlRpcValue val(valueXml, offset); 00506 if ( ! val.valid()) { 00507 invalidate(); 00508 return false; 00509 } 00510 const std::pair<const std::string, XmlRpcValue> p(name, val); 00511 _value.asStruct->insert(p); 00512 00513 (void) XmlRpcUtil::nextTagIs(MEMBER_ETAG, valueXml, offset); 00514 } 00515 return true; 00516 }
|
|
00522 { 00523 std::string xml = VALUE_TAG; 00524 xml += STRUCT_TAG; 00525 00526 ValueStruct::const_iterator it; 00527 for (it=_value.asStruct->begin(); it!=_value.asStruct->end(); ++it) { 00528 xml += MEMBER_TAG; 00529 xml += NAME_TAG; 00530 xml += XmlRpcUtil::xmlEncode(it->first); 00531 xml += NAME_ETAG; 00532 xml += it->second.toXml(); 00533 xml += MEMBER_ETAG; 00534 } 00535 00536 xml += STRUCT_ETAG; 00537 xml += VALUE_ETAG; 00538 return xml; 00539 }
|
|
00381 { 00382 size_t valueEnd = valueXml.find('<', *offset); 00383 if (valueEnd == std::string::npos) 00384 return false; // No end tag; 00385 00386 std::string stime = valueXml.substr(*offset, valueEnd-*offset); 00387 00388 struct tm t; 00389 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) 00390 return false; 00391 00392 t.tm_isdst = -1; 00393 _type = TypeDateTime; 00394 _value.asTime = new struct tm(t); 00395 *offset += int(stime.length()); 00396 return true; 00397 }
|
|
00400 { 00401 struct tm* t = _value.asTime; 00402 char buf[20]; 00403 snprintf(buf, sizeof(buf)-1, "%4d%02d%02dT%02d:%02d:%02d", 00404 t->tm_year,t->tm_mon,t->tm_mday,t->tm_hour,t->tm_min,t->tm_sec); 00405 buf[sizeof(buf)-1] = 0; 00406 00407 std::string xml = VALUE_TAG; 00408 xml += DATETIME_TAG; 00409 xml += buf; 00410 xml += DATETIME_ETAG; 00411 xml += VALUE_ETAG; 00412 return xml; 00413 }
|
|
Encode the Value in xml.
00258 { 00259 switch (_type) { 00260 case TypeBoolean: return boolToXml(); 00261 case TypeInt: return intToXml(); 00262 case TypeDouble: return doubleToXml(); 00263 case TypeString: return stringToXml(); 00264 case TypeDateTime: return timeToXml(); 00265 case TypeBase64: return binaryToXml(); 00266 case TypeArray: return arrayToXml(); 00267 case TypeStruct: return structToXml(); 00268 default: break; 00269 } 00270 return std::string(); // Invalid value 00271 }
|
|
Return true if the value has been set to something.
00102 { return _type != TypeInvalid; }
|
|
Write the value (no xml encoding).
00544 { 00545 switch (_type) { 00546 default: break; 00547 case TypeBoolean: os << _value.asBool; break; 00548 case TypeInt: os << _value.asInt; break; 00549 case TypeDouble: os << _value.asDouble; break; 00550 case TypeString: os << *_value.asString; break; 00551 case TypeDateTime: 00552 { 00553 struct tm* t = _value.asTime; 00554 char buf[20]; 00555 snprintf(buf, sizeof(buf)-1, "%4d%02d%02dT%02d:%02d:%02d", 00556 t->tm_year,t->tm_mon,t->tm_mday,t->tm_hour,t->tm_min,t->tm_sec); 00557 buf[sizeof(buf)-1] = 0; 00558 os << buf; 00559 break; 00560 } 00561 case TypeBase64: 00562 { 00563 int iostatus = 0; 00564 std::ostreambuf_iterator<char> out(os); 00565 base64<char> encoder; 00566 encoder.put(_value.asBinary->begin(), _value.asBinary->end(), out, iostatus, base64<>::crlf()); 00567 break; 00568 } 00569 case TypeArray: 00570 { 00571 int s = int(_value.asArray->size()); 00572 os << '{'; 00573 for (int i=0; i<s; ++i) 00574 { 00575 if (i > 0) os << ','; 00576 _value.asArray->at(i).write(os); 00577 } 00578 os << '}'; 00579 break; 00580 } 00581 case TypeStruct: 00582 { 00583 os << '['; 00584 ValueStruct::const_iterator it; 00585 for (it=_value.asStruct->begin(); it!=_value.asStruct->end(); ++it) 00586 { 00587 if (it!=_value.asStruct->begin()) os << ','; 00588 os << it->first << ':'; 00589 it->second.write(os); 00590 } 00591 os << ']'; 00592 break; 00593 } 00594 00595 } 00596 00597 return os; 00598 }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|