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
18namespace 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
46    XmlRpcValue() : _type(TypeInvalid) { _value.asBinary = 0; }
47    XmlRpcValue(bool value) : _type(TypeBoolean) { _value.asBool = value; }
48    XmlRpcValue(int value)  : _type(TypeInt) { _value.asInt = value; }
49    XmlRpcValue(double value)  : _type(TypeDouble) { _value.asDouble = value; }
50
51    XmlRpcValue(std::string const& value) : _type(TypeString)
52    { _value.asString = new std::string(value); }
53
54    XmlRpcValue(const char* value)  : _type(TypeString)
55    { _value.asString = new std::string(value); }
56
57    XmlRpcValue(struct tm* value)  : _type(TypeDateTime)
58    { _value.asTime = new struct tm(*value); }
59
60
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
67    XmlRpcValue(std::string const& xml, int* offset) : _type(TypeInvalid)
68    { if ( ! fromXml(xml,offset)) _type = TypeInvalid; }
69
70    //! Copy
71    XmlRpcValue(XmlRpcValue const& rhs) : _type(TypeInvalid) { *this = rhs; }
72
73    //! Destructor (make virtual if you want to subclass)
74    /*virtual*/ ~XmlRpcValue() { invalidate(); }
75
76    //! Erase the current value
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.
103    bool valid() const { return _type != TypeInvalid; }
104
105    //! Return the type of the value stored. \see Type.
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.
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.
128    static std::string const& getDoubleFormat() { return _doubleFormat; }
129
130    //! Specify the format used to write double values.
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.
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
191std::ostream& operator<<(std::ostream& os, XmlRpc::XmlRpcValue& v);
192
193
194#endif // _XMLRPCVALUE_H_
195