1 
2 #ifndef _XMLRPCVALUE_H_
3 #define _XMLRPCVALUE_H_
4 //
5 // XmlRpc++ Copyright (c) 2002-2003 by Chris Morley
6 //
7 #if defined(_MSC_VER)
8 # pragma warning(disable:4786)    // identifier was truncated in debug info
9 #endif
10 
11 #ifndef MAKEDEPEND
12 # include <map>
13 # include <string>
14 # include <vector>
15 # include <time.h>
16 #endif
17 
18 namespace XmlRpc {
19 
20   //! RPC method arguments and results are represented by Values
21   //   should probably refcount them...
22   class XmlRpcValue {
23   public:
24 
25 
26     enum Type {
27       TypeInvalid,
28       TypeBoolean,
29       TypeInt,
30       TypeDouble,
31       TypeString,
32       TypeDateTime,
33       TypeBase64,
34       TypeArray,
35       TypeStruct,
36       TypeNil
37     };
38 
39     // Non-primitive types
40     typedef std::vector<char> BinaryData;
41     typedef std::vector<XmlRpcValue> ValueArray;
42     typedef std::map<std::string, XmlRpcValue> ValueStruct;
43 
44 
45     //! Constructors
XmlRpcValue()46     XmlRpcValue() : _type(TypeInvalid) { _value.asBinary = 0; }
XmlRpcValue(bool value)47     XmlRpcValue(bool value) : _type(TypeBoolean) { _value.asBool = value; }
XmlRpcValue(int value)48     XmlRpcValue(int value)  : _type(TypeInt) { _value.asInt = value; }
XmlRpcValue(double value)49     XmlRpcValue(double value)  : _type(TypeDouble) { _value.asDouble = value; }
50 
XmlRpcValue(std::string const & value)51     XmlRpcValue(std::string const& value) : _type(TypeString)
52     { _value.asString = new std::string(value); }
53 
XmlRpcValue(const char * value)54     XmlRpcValue(const char* value)  : _type(TypeString)
55     { _value.asString = new std::string(value); }
56 
XmlRpcValue(struct tm * value)57     XmlRpcValue(struct tm* value)  : _type(TypeDateTime)
58     { _value.asTime = new struct tm(*value); }
59 
60 
XmlRpcValue(void * value,int nBytes)61     XmlRpcValue(void* value, int nBytes)  : _type(TypeBase64)
62     {
63       _value.asBinary = new BinaryData((char*)value, ((char*)value)+nBytes);
64     }
65 
66     //! Construct from xml, beginning at *offset chars into the string, updates offset
XmlRpcValue(std::string const & xml,int * offset)67     XmlRpcValue(std::string const& xml, int* offset) : _type(TypeInvalid)
68     { if ( ! fromXml(xml,offset)) _type = TypeInvalid; }
69 
70     //! Copy
XmlRpcValue(XmlRpcValue const & rhs)71     XmlRpcValue(XmlRpcValue const& rhs) : _type(TypeInvalid) { *this = rhs; }
72 
73     //! Destructor (make virtual if you want to subclass)
~XmlRpcValue()74     /*virtual*/ ~XmlRpcValue() { invalidate(); }
75 
76     //! Erase the current value
clear()77     void clear() { invalidate(); }
78 
79     // Operators
80     XmlRpcValue& operator=(XmlRpcValue const& rhs);
81     XmlRpcValue& operator=(int const& rhs) { return operator=(XmlRpcValue(rhs)); }
82     XmlRpcValue& operator=(double const& rhs) { return operator=(XmlRpcValue(rhs)); }
83     XmlRpcValue& operator=(const char* rhs) { return operator=(XmlRpcValue(std::string(rhs))); }
84 
85     bool operator==(XmlRpcValue const& other) const;
86     bool operator!=(XmlRpcValue const& other) const;
87 
88     operator bool&()          { assertTypeOrInvalid(TypeBoolean); return _value.asBool; }
89     operator int&()           { assertTypeOrInvalid(TypeInt); return _value.asInt; }
90     operator double&()        { assertTypeOrInvalid(TypeDouble); return _value.asDouble; }
91     operator std::string&()   { assertTypeOrInvalid(TypeString); return *_value.asString; }
92     operator BinaryData&()    { assertTypeOrInvalid(TypeBase64); return *_value.asBinary; }
93     operator struct tm&()     { assertTypeOrInvalid(TypeDateTime); return *_value.asTime; }
94 
95     XmlRpcValue const& operator[](int i) const { assertArray(i+1); return _value.asArray->at(i); }
96     XmlRpcValue& operator[](int i)             { assertArray(i+1); return _value.asArray->at(i); }
97 
98     XmlRpcValue& operator[](std::string const& k) { assertStruct(); return (*_value.asStruct)[k]; }
99     XmlRpcValue& operator[](const char* k) { assertStruct(); std::string s(k); return (*_value.asStruct)[s]; }
100 
101     // Accessors
102     //! Return true if the value has been set to something.
valid()103     bool valid() const { return _type != TypeInvalid; }
104 
105     //! Return the type of the value stored. \see Type.
getType()106     Type const &getType() const { return _type; }
107 
108     //! Return the size for string, base64, array, and struct values.
109     int size() const;
110 
111     //! Specify the size for array values. Array values will grow beyond this size if needed.
setSize(int size)112     void setSize(int size)    { assertArray(size); }
113 
114     //! Check for the existence of a struct member by name.
115     bool hasMember(const std::string& name) const;
116 
117     //! Decode xml. Destroys any existing value.
118     bool fromXml(std::string const& valueXml, int* offset);
119 
120     //! Encode the Value in xml
121     std::string toXml() const;
122 
123     //! Write the value (no xml encoding)
124     std::ostream& write(std::ostream& os) const;
125 
126     // Formatting
127     //! Return the format used to write double values.
getDoubleFormat()128     static std::string const& getDoubleFormat() { return _doubleFormat; }
129 
130     //! Specify the format used to write double values.
setDoubleFormat(const char * f)131     static void setDoubleFormat(const char* f) { _doubleFormat = f; }
132 
133     //! Set the value type to Nil. This value will be encoded as <nil/> xml tag.
setToNil()134     void setToNil() { assertTypeOrInvalid(TypeNil); }
135 
136   protected:
137     // Clean up
138     void invalidate();
139 
140     // Type checking
141     void assertTypeOrInvalid(Type t);
142     void assertArray(int size) const;
143     void assertArray(int size);
144     void assertStruct();
145 
146     // XML decoding
147     bool nilFromXml(std::string const& valueXml, int* offset);
148     bool boolFromXml(std::string const& valueXml, int* offset);
149     bool intFromXml(std::string const& valueXml, int* offset);
150     bool doubleFromXml(std::string const& valueXml, int* offset);
151     bool stringFromXml(std::string const& valueXml, int* offset);
152     bool timeFromXml(std::string const& valueXml, int* offset);
153     bool binaryFromXml(std::string const& valueXml, int* offset);
154     bool arrayFromXml(std::string const& valueXml, int* offset);
155     bool structFromXml(std::string const& valueXml, int* offset);
156 
157     // XML encoding
158     std::string nilToXml() const;
159     std::string boolToXml() const;
160     std::string intToXml() const;
161     std::string doubleToXml() const;
162     std::string stringToXml() const;
163     std::string timeToXml() const;
164     std::string binaryToXml() const;
165     std::string arrayToXml() const;
166     std::string structToXml() const;
167 
168     // Format strings
169     static std::string _doubleFormat;
170 
171     // Type tag and values
172     Type _type;
173 
174     // At some point I will split off Arrays and Structs into
175     // separate ref-counted objects for more efficient copying.
176     union {
177       bool          asBool;
178       int           asInt;
179       double        asDouble;
180       struct tm*    asTime;
181       std::string*  asString;
182       BinaryData*   asBinary;
183       ValueArray*   asArray;
184       ValueStruct*  asStruct;
185     } _value;
186 
187   };
188 } // namespace XmlRpc
189 
190 
191 std::ostream& operator<<(std::ostream& os, XmlRpc::XmlRpcValue& v);
192 
193 
194 #endif // _XMLRPCVALUE_H_
195