1 // ---------------------------------------------------------------------------- 2 // 3 // flxmlrpc Copyright (c) 2015 by W1HKJ, Dave Freese <iam_w1hkj@w1hkj.com> 4 // 5 // XmlRpc++ Copyright (c) 2002-2008 by Chris Morley 6 // 7 // This file is part of fldigi 8 // 9 // flxmlrpc is free software; you can redistribute it and/or modify 10 // it under the terms of the GNU Lesser General Public License as published by 11 // the Free Software Foundation; either version 3 of the License, or 12 // (at your option) any later version. 13 // 14 // You should have received a copy of the GNU General Public License 15 // along with this program. If not, see <http://www.gnu.org/licenses/>. 16 // ---------------------------------------------------------------------------- 17 18 #ifndef _XMLRPCVALUE_H_ 19 #define _XMLRPCVALUE_H_ 20 21 #if defined(_MSC_VER) 22 # pragma warning(disable:4786) // identifier was truncated in debug info 23 #endif 24 25 #include <map> 26 #include <string> 27 #include <vector> 28 #include <time.h> 29 30 namespace XmlRpc { 31 32 enum xmlrpc_nil_t { nil }; 33 34 //! A class to represent RPC arguments and results. 35 //! Each XmlRpcValue object contains a typed value, 36 //! where the type is determined by the initial value 37 //! assigned to the object. 38 // should probably refcount them... 39 class XmlRpcValue { 40 public: 41 42 //! XmlRpcValue types 43 enum Type { 44 TypeInvalid, 45 TypeNil, 46 TypeBoolean, 47 TypeInt, 48 TypeUnsigned, 49 TypeLongLong, 50 TypeDouble, 51 TypeString, 52 TypeDateTime, 53 TypeBase64, 54 TypeArray, 55 TypeStruct 56 }; 57 58 // Non-primitive types 59 typedef std::vector<unsigned char> BinaryData; 60 typedef std::vector<XmlRpcValue> ValueArray; 61 typedef std::map<std::string, XmlRpcValue> ValueStruct; 62 63 64 // Constructors 65 //! Construct an empty XmlRpcValue XmlRpcValue()66 XmlRpcValue() : _type(TypeInvalid) { _value.asBinary = 0; } 67 68 //! Construct an XmlRpcValue with a nil value XmlRpcValue(xmlrpc_nil_t value)69 XmlRpcValue(xmlrpc_nil_t value) : _type(TypeNil) { } 70 71 //! Construct an XmlRpcValue with a bool value XmlRpcValue(bool value)72 XmlRpcValue(bool value) : _type(TypeBoolean) { _value.asBool = value; } 73 74 //! Construct an XmlRpcValue with an int value XmlRpcValue(int value)75 XmlRpcValue(int value) : _type(TypeInt) { _value.asInt = value; } 76 XmlRpcValue(unsigned int value)77 XmlRpcValue(unsigned int value) : _type(TypeUnsigned) { _value.asUnsigned = value; } 78 XmlRpcValue(long long value)79 XmlRpcValue(long long value) : _type(TypeLongLong) { _value.asLongLong = value; } 80 81 //! Construct an XmlRpcValue with a double value XmlRpcValue(double value)82 XmlRpcValue(double value) : _type(TypeDouble) { _value.asDouble = value; } 83 84 //! Construct an XmlRpcValue with a string value XmlRpcValue(std::string const & value)85 XmlRpcValue(std::string const& value) : _type(TypeString) 86 { _value.asString = new std::string(value); } 87 88 //! Construct an XmlRpcValue with a string value. 89 //! @param value A null-terminated (C) string. XmlRpcValue(const char * value)90 XmlRpcValue(const char* value) : _type(TypeString) 91 { _value.asString = new std::string(value); } 92 XmlRpcValue(BinaryData const & value)93 XmlRpcValue(BinaryData const& value) : _type(TypeBase64) 94 { _value.asBinary = new BinaryData(value); } 95 XmlRpcValue(ValueStruct const & value)96 XmlRpcValue(ValueStruct const& value) : _type(TypeStruct) 97 { _value.asStruct = new ValueStruct(value); } 98 XmlRpcValue(ValueArray const & value)99 XmlRpcValue(ValueArray const& value) : _type(TypeArray) 100 { _value.asArray = new ValueArray(value); } 101 102 //! Construct an XmlRpcValue with a date/time value. 103 //! @param value A pointer to a struct tm (see localtime) XmlRpcValue(struct tm * value)104 XmlRpcValue(struct tm* value) : _type(TypeDateTime) 105 { _value.asTime = new struct tm(*value); } 106 107 //! Construct an XmlRpcValue with a binary data value 108 //! @param value A pointer to data 109 //! @param nBytes The length of the data pointed to, in bytes XmlRpcValue(void * value,int nBytes)110 XmlRpcValue(void* value, int nBytes) : _type(TypeBase64) 111 { 112 _value.asBinary = new BinaryData((char*)value, ((char*)value)+nBytes); 113 } 114 115 //! Construct from xml, beginning at *offset chars into the string, updates offset XmlRpcValue(std::string const & xml,int * offset)116 XmlRpcValue(std::string const& xml, int* offset) : _type(TypeInvalid) 117 { if ( ! fromXml(xml,offset)) _type = TypeInvalid; } 118 119 //! Copy constructor XmlRpcValue(XmlRpcValue const & rhs)120 XmlRpcValue(XmlRpcValue const& rhs) : _type(TypeInvalid) { *this = rhs; } 121 122 //! Destructor (make virtual if you want to subclass) ~XmlRpcValue()123 /*virtual*/ ~XmlRpcValue() { invalidate(); } 124 125 //! Erase the current value clear()126 void clear() { invalidate(); } 127 128 // Operators 129 //! Assignment from one XmlRpcValue to this one. 130 //! @param rhs The value in rhs is copied to this value. 131 XmlRpcValue& operator=(XmlRpcValue const& rhs); 132 133 //! Assign nil to this XmlRpcValue. 134 XmlRpcValue& operator=(xmlrpc_nil_t const& rhs) { return operator=(XmlRpcValue(rhs)); } 135 136 //! Assign a bool to this XmlRpcValue. 137 XmlRpcValue& operator=(bool const& rhs) { return operator=(XmlRpcValue(rhs)); } 138 139 //! Assign an int to this XmlRpcValue. 140 XmlRpcValue& operator=(int const& rhs) { return operator=(XmlRpcValue(rhs)); } 141 142 //! Assign a double to this XmlRpcValue. 143 XmlRpcValue& operator=(double const& rhs) { return operator=(XmlRpcValue(rhs)); } 144 145 //! Assign a string to this XmlRpcValue. 146 XmlRpcValue& operator=(const char* rhs) { return operator=(XmlRpcValue(std::string(rhs))); } 147 148 //! Tests two XmlRpcValues for equality 149 bool operator==(XmlRpcValue const& other) const; 150 151 //! Tests two XmlRpcValues for inequality 152 bool operator!=(XmlRpcValue const& other) const; 153 154 //! Treat an XmlRpcValue as a bool. 155 //! Throws XmlRpcException if the value is initialized to 156 //! a type that is not TypeBoolean. 157 operator bool&() { assertType(TypeBoolean); return _value.asBool; } 158 operator bool() const { assertType(TypeBoolean); return _value.asBool; } 159 160 //! Treat an XmlRpcValue as an int. 161 //! Throws XmlRpcException if the value is initialized to 162 //! a type that is not TypeInt. 163 operator int&() { assertType(TypeInt); return _value.asInt; } 164 operator int() const { assertType(TypeInt); return _value.asInt; } 165 166 operator unsigned int&() { assertType(TypeUnsigned); return _value.asUnsigned; } 167 operator unsigned int() const { assertType(TypeUnsigned); return _value.asUnsigned; } 168 169 operator long long&() { assertType(TypeLongLong); return _value.asLongLong; } 170 operator long long() const { assertType(TypeLongLong); return _value.asLongLong; } 171 172 //! Treat an XmlRpcValue as a double. 173 //! Throws XmlRpcException if the value is initialized to 174 //! a type that is not TypeDouble. 175 operator double&() { assertType(TypeDouble); return _value.asDouble; } 176 operator double() const { assertType(TypeDouble); return _value.asDouble; } 177 178 //! Treat an XmlRpcValue as a string. 179 //! Throws XmlRpcException if the value is initialized to 180 //! a type that is not TypeString. 181 operator std::string&() { assertType(TypeString); return *_value.asString; } 182 operator std::string const&() const { assertType(TypeString); return *_value.asString; } 183 184 //! Access the BinaryData value. 185 //! Throws XmlRpcException if the value is initialized to 186 //! a type that is not TypeBase64. 187 operator BinaryData&() { assertType(TypeBase64); return *_value.asBinary; } 188 operator BinaryData const&() const { assertType(TypeBase64); return *_value.asBinary; } 189 190 //! Access the DateTime value. 191 //! Throws XmlRpcException if the value is initialized to 192 //! a type that is not TypeDateTime. 193 operator struct tm&() { assertType(TypeDateTime); return *_value.asTime; } 194 operator struct tm const&() const { assertType(TypeDateTime); return *_value.asTime; } 195 196 197 //! Const array value accessor. 198 //! Access the ith value of the array. 199 //! Throws XmlRpcException if the value is not an array or if the index i is 200 //! not a valid index for the array. 201 XmlRpcValue const& operator[](int i) const { assertArray(i+1); return _value.asArray->at(i); } 202 203 //! Array value accessor. 204 //! Access the ith value of the array, growing the array if necessary. 205 //! Throws XmlRpcException if the value is not an array. 206 XmlRpcValue& operator[](int i) { assertArray(i+1); return _value.asArray->at(i); } 207 208 //! Struct entry accessor. 209 //! Returns the value associated with the given entry, creating one if necessary. 210 XmlRpcValue& operator[](std::string const& k) { assertStruct(); return (*_value.asStruct)[k]; } 211 212 //! Struct entry accessor. 213 //! Returns the value associated with the given entry, creating one if necessary. 214 XmlRpcValue& operator[](const char* k) { assertStruct(); std::string s(k); return (*_value.asStruct)[s]; } 215 216 //! Access the struct value map. 217 //! Can be used to iterate over the entries in the map to find all defined entries. 218 operator ValueStruct const&() { assertStruct(); return *_value.asStruct; } 219 220 operator ValueArray const&() const { assertType(TypeArray); return *_value.asArray; } 221 222 // Accessors 223 //! Return true if the value has been set to something. valid()224 bool valid() const { return _type != TypeInvalid; } 225 226 //! Return the type of the value stored. \see Type. getType()227 Type const &getType() const { return _type; } 228 229 //! Return the size for string, base64, array, and struct values. 230 int size() const; 231 232 //! Specify the size for array values. Array values will grow beyond this size if needed. setSize(int size)233 void setSize(int size) { assertArray(size); } 234 235 //! Check for the existence of a struct member by name. 236 bool hasMember(const std::string& name) const; 237 238 //! Decode xml. Destroys any existing value. 239 bool fromXml(std::string const& valueXml, int* offset); 240 241 //! Encode the Value in xml 242 std::string toXml() const; 243 244 //! Write the value (no xml encoding) 245 std::ostream& write(std::ostream& os) const; 246 247 // Formatting 248 //! Return the format used to write double values. getDoubleFormat()249 static std::string const& getDoubleFormat() { return _doubleFormat; } 250 251 //! Specify the format used to write double values. setDoubleFormat(const char * f)252 static void setDoubleFormat(const char* f) { _doubleFormat = f; } 253 254 255 protected: 256 // Clean up 257 void invalidate(); 258 259 // Type checking. Non-const versions coerce to the desired type if currently un-typed. 260 void assertType(Type t) const; 261 void assertType(Type t); 262 void assertArray(int size) const; 263 void assertArray(int size); 264 void assertStruct(); 265 266 // XML decoding 267 bool boolFromXml(std::string const& valueXml, int* offset); 268 bool intFromXml(std::string const& valueXml, int* offset); 269 bool doubleFromXml(std::string const& valueXml, int* offset); 270 bool stringFromXml(std::string const& valueXml, int* offset); 271 bool timeFromXml(std::string const& valueXml, int* offset); 272 bool binaryFromXml(std::string const& valueXml, int* offset); 273 bool arrayFromXml(std::string const& valueXml, int* offset); 274 bool structFromXml(std::string const& valueXml, int* offset); 275 276 // XML encoding 277 std::string nilToXml() const; 278 std::string boolToXml() const; 279 std::string intToXml() const; 280 std::string doubleToXml() const; 281 std::string stringToXml() const; 282 std::string timeToXml() const; 283 std::string binaryToXml() const; 284 std::string arrayToXml() const; 285 std::string structToXml() const; 286 287 // Format strings 288 static std::string _doubleFormat; 289 290 // Type tag and values 291 Type _type; 292 293 // At some point I will split off Arrays and Structs into 294 // separate ref-counted objects for more efficient copying. 295 union { 296 bool asBool; 297 int asInt; 298 unsigned int asUnsigned; 299 long long asLongLong; 300 double asDouble; 301 struct tm* asTime; 302 std::string* asString; 303 BinaryData* asBinary; 304 ValueArray* asArray; 305 ValueStruct* asStruct; 306 } _value; 307 308 }; 309 } // namespace XmlRpc 310 311 312 std::ostream& operator<<(std::ostream& os, XmlRpc::XmlRpcValue& v); 313 314 315 #endif // _XMLRPCVALUE_H_ 316