#ifndef XMLRPC_BASE_HPP_INCLUDED #define XMLRPC_BASE_HPP_INCLUDED #include #include #include #include #include #include #include #if XMLRPC_HAVE_TIMEVAL #include #endif #include #include namespace xmlrpc_c { class XMLRPC_DLLEXPORT value { // This is a handle. You don't want to create a pointer to this; // it is in fact a pointer itself. public: value(); // This creates a placeholder. It can't be used for anything, but // holds memory. instantiate() can turn it into a real object. value(xmlrpc_c::value const &value); // copy constructor ~value(); enum type_t { // These are designed to be identical to the values for // enum xmlrpc_type in the C library. TYPE_INT = 0, TYPE_BOOLEAN = 1, TYPE_DOUBLE = 2, TYPE_DATETIME = 3, TYPE_STRING = 4, TYPE_BYTESTRING = 5, TYPE_ARRAY = 6, TYPE_STRUCT = 7, TYPE_C_PTR = 8, TYPE_NIL = 9, TYPE_I8 = 10, TYPE_DEAD = 0xDEAD }; type_t type() const; xmlrpc_c::value& operator=(xmlrpc_c::value const&); bool isInstantiated() const; // The following are not meant to be public to users, but just to // other Xmlrpc-c library modules. If we ever go to a pure C++ // implementation, not based on C xmlrpc_value objects, this shouldn't // be necessary. void appendToCArray(xmlrpc_value * const arrayP) const; void addToCStruct(xmlrpc_value * const structP, std::string const key) const; xmlrpc_value * cValue() const; // Not to be confused with public 'cvalue' method that all the derived // classes have. value(xmlrpc_value * const valueP); void instantiate(xmlrpc_value * const valueP); // Works only on a placeholder object created by the no-argument // constructor. xmlrpc_value * cValueP; // NULL means this is merely a placeholder object. protected: void validateInstantiated() const; }; std::ostream& operator<<(std::ostream& out, xmlrpc_c::value::type_t const& type); class XMLRPC_DLLEXPORT value_int : public value { public: value_int(int const cvalue); value_int(xmlrpc_c::value const baseValue); operator int() const; int cvalue() const; }; class XMLRPC_DLLEXPORT value_boolean : public value { public: value_boolean(bool const cvalue); value_boolean(xmlrpc_c::value const baseValue); operator bool() const; bool cvalue() const; }; class XMLRPC_DLLEXPORT value_string : public value { public: enum nlCode {nlCode_all, nlCode_lf}; value_string(std::string const& cppvalue, nlCode const nlCode); value_string(std::string const& cppvalue); value_string(xmlrpc_c::value const baseValue); std::string crlfValue() const; operator std::string() const; std::string cvalue() const; }; class XMLRPC_DLLEXPORT value_double : public value { public: value_double(double const cvalue); value_double(xmlrpc_c::value const baseValue); operator double() const; double cvalue() const; }; class XMLRPC_DLLEXPORT value_datetime : public value { public: value_datetime(std::string const cvalue); value_datetime(time_t const cvalue); #if XMLRPC_HAVE_TIMEVAL value_datetime(struct timeval const& cvalue); operator timeval() const; #endif #if XMLRPC_HAVE_TIMESPEC value_datetime(struct timespec const& cvalue); operator timespec() const; #endif value_datetime(xmlrpc_c::value const baseValue); operator time_t() const; time_t cvalue() const; }; typedef std::vector cbytestring; class XMLRPC_DLLEXPORT value_bytestring : public value { public: value_bytestring(cbytestring const& cvalue); value_bytestring(xmlrpc_c::value const baseValue); // You can't cast to a vector because the compiler can't tell which // constructor to use (complains about ambiguity). So we have this: cbytestring vectorUcharValue() const; cbytestring cvalue() const; size_t length() const; }; typedef std::map cstruct; class XMLRPC_DLLEXPORT value_struct : public value { public: value_struct(cstruct const& cvalue); value_struct(xmlrpc_c::value const baseValue); operator cstruct() const; cstruct cvalue() const; }; typedef std::vector carray; class XMLRPC_DLLEXPORT value_array : public value { public: value_array(carray const& cvalue); value_array(xmlrpc_c::value const baseValue); // You can't cast to a vector because the compiler can't tell which // constructor to use (complains about ambiguity). So we have this: carray vectorValueValue() const; carray cvalue() const; size_t size() const; }; template xmlrpc_c::value_array arrayValueSlice(InputIterator begin, InputIterator end) { /*---------------------------------------------------------------------------- convert C++ iterator pair to XML-RPC array -----------------------------------------------------------------------------*/ carray ret; for (InputIterator p = begin; p != end; ++p) { ret.push_back(toValue(*p)); } return xmlrpc_c::value_array(ret); } template inline xmlrpc_c::value_array arrayValueArray(const MemberClass * const in, size_t const size) { /*---------------------------------------------------------------------------- convert C++ array to XML-RPC array -----------------------------------------------------------------------------*/ return arrayValueSlice(in, in + size); } class XMLRPC_DLLEXPORT value_nil : public value { public: value_nil(); value_nil(xmlrpc_c::value const baseValue); void * cvalue() const; }; class XMLRPC_DLLEXPORT value_i8 : public value { public: value_i8(xmlrpc_int64 const cvalue); value_i8(xmlrpc_c::value const baseValue); operator xmlrpc_int64() const; xmlrpc_int64 cvalue() const; }; inline xmlrpc_c::value_string toValue(const char * const x) { return xmlrpc_c::value_string(x); } inline xmlrpc_c::value_string toValue(std::string const& x) { return xmlrpc_c::value_string(x); } inline xmlrpc_c::value_int toValue(int const x) { return xmlrpc_c::value_int(x); } inline xmlrpc_c::value_boolean toValue(bool const x) { return xmlrpc_c::value_boolean(x); } inline xmlrpc_c::value_double toValue(double const x) { return xmlrpc_c::value_double(x); } inline xmlrpc_c::value_bytestring toValue(cbytestring const& x) { return xmlrpc_c::value_bytestring(x); } inline const xmlrpc_c::value & toValue(xmlrpc_c::value const& v) { /*---------------------------------------------------------------------------- This does a null conversion; you use it to catch all the XML-RPC types that have no usable C++ equivalent, so you can do a toValue() of any XML-RPC type at all. In particular: 'value_datetime', 'value_nil'. -----------------------------------------------------------------------------*/ return v; } template xmlrpc_c::value_struct toValue(std::map const& in) { /*---------------------------------------------------------------------------- convert C++ map to XML-RPC structure -----------------------------------------------------------------------------*/ cstruct ret; for (typename std::map::const_iterator p = in.begin(); p != in.end(); ++p) { ret[p->first] = toValue(p->second); } return xmlrpc_c::value_struct(ret); } template inline xmlrpc_c::value_array toValue(std::vector const& in) { /*---------------------------------------------------------------------------- convert C++ vector to XML-RPC array -----------------------------------------------------------------------------*/ return arrayValueSlice(in.begin(), in.end()); } // fromValue() returns via reference argument instead of by return value // so the compiler can tell which version of it to invoke based on the // desired output type. inline void fromValue(std::string & y, xmlrpc_c::value const& x) { y = xmlrpc_c::value_string(x); } inline void fromValue(int & y, xmlrpc_c::value const& x) { y = xmlrpc_c::value_int(x); } inline void fromValue(bool & y, xmlrpc_c::value const& x) { y = xmlrpc_c::value_boolean(x); } inline void fromValue(double & y, xmlrpc_c::value const& x) { y = xmlrpc_c::value_double(x); } inline void fromValue(cbytestring & y, xmlrpc_c::value const& x) { y = xmlrpc_c::value_bytestring(x).vectorUcharValue(); } inline void fromValue(xmlrpc_c::value & y, xmlrpc_c::value const& x) { /*---------------------------------------------------------------------------- This does a null conversion; it's so you can use fromValue() with an XML-RPC value or C++ value without having to know which it is. One reason you would have an XML-RPC value lying around with C++ values is that some XML-RPC values don't have a common C++ equivalent. -----------------------------------------------------------------------------*/ y = x; } template inline void fromValue(std::map & y, xmlrpc_c::value const& x) { /*---------------------------------------------------------------------------- Convert XML-RPC structure to C++ map. -----------------------------------------------------------------------------*/ cstruct m = xmlrpc_c::value_struct(x); y.clear(); for (std::map::const_iterator p = m.begin(); p != m.end(); ++p) { fromValue(y[p->first], p->second); } } template inline void fromValue(std::vector & y, xmlrpc_c::value const& x) { /*---------------------------------------------------------------------------- Convert XML-RPC array to C++ vector. -----------------------------------------------------------------------------*/ carray v = xmlrpc_c::value_array(x).vectorValueValue(); y.resize(v.size()); for (unsigned int i = 0; i < v.size(); ++i) { fromValue(y[i], v[i]); } } class XMLRPC_DLLEXPORT fault { /*---------------------------------------------------------------------------- This is an XML-RPC fault. This object is not intended to be used to represent a fault in the execution of XML-RPC client/server software -- just a fault in an XML-RPC RPC as described by the XML-RPC spec. There is no way to represent "no fault" with this object. The object is meaningful only in the context of some fault. -----------------------------------------------------------------------------*/ public: enum code_t { CODE_UNSPECIFIED = 0, CODE_INTERNAL = -500, CODE_TYPE = -501, CODE_INDEX = -502, CODE_PARSE = -503, CODE_NETWORK = -504, CODE_TIMEOUT = -505, CODE_NO_SUCH_METHOD = -506, CODE_REQUEST_REFUSED = -507, CODE_INTROSPECTION_DISABLED = -508, CODE_LIMIT_EXCEEDED = -509, CODE_INVALID_UTF8 = -510 }; fault(); fault(std::string const _faultString, xmlrpc_c::fault::code_t const _faultCode = xmlrpc_c::fault::CODE_UNSPECIFIED ); xmlrpc_c::fault::code_t getCode() const; std::string getDescription() const; private: bool valid; xmlrpc_c::fault::code_t code; std::string description; }; class XMLRPC_DLLEXPORT rpcOutcome { /*---------------------------------------------------------------------------- The outcome of a validly executed RPC -- either an XML-RPC fault or an XML-RPC value of the result. -----------------------------------------------------------------------------*/ public: rpcOutcome(); rpcOutcome(xmlrpc_c::value const result); rpcOutcome(xmlrpc_c::fault const fault); bool succeeded() const; xmlrpc_c::fault getFault() const; xmlrpc_c::value getResult() const; private: bool valid; // This is false in a placeholder variable -- i.e. an object you // create with the no-argument constructor, which is waiting to be // assigned a value. When false, nothing below is valid. bool _succeeded; xmlrpc_c::value result; // valid if 'succeeded' xmlrpc_c::fault fault; // valid if not 'succeeded' }; class XMLRPC_DLLEXPORT paramList { /*---------------------------------------------------------------------------- A parameter list of an XML-RPC call. -----------------------------------------------------------------------------*/ public: paramList(unsigned int const paramCount = 0); paramList& add(xmlrpc_c::value const param); paramList& addx(xmlrpc_c::value const param); template paramList& addc(const T & x) { xmlrpc_c::paramList::add(toValue(x)); return *this; } unsigned int size() const; xmlrpc_c::value operator[](unsigned int const subscript) const; int getInt(unsigned int const paramNumber, int const minimum = INT_MIN, int const maximum = INT_MAX) const; bool getBoolean(unsigned int const paramNumber) const; double getDouble(unsigned int const paramNumber, double const minimum = -DBL_MAX, double const maximum = DBL_MAX) const; enum timeConstraint {TC_ANY, TC_NO_PAST, TC_NO_FUTURE}; time_t getDatetime_sec(unsigned int const paramNumber, timeConstraint const constraint = paramList::TC_ANY) const; std::string getString(unsigned int const paramNumber) const; cbytestring getBytestring(unsigned int const paramNumber) const; carray getArray(unsigned int const paramNumber, unsigned int const minSize = 0, unsigned int const maxSize = UINT_MAX) const; cstruct getStruct(unsigned int const paramNumber) const; void getNil(unsigned int const paramNumber) const; xmlrpc_int64 getI8(unsigned int const paramNumber, xmlrpc_int64 const minimum = XMLRPC_INT64_MIN, xmlrpc_int64 const maximum = XMLRPC_INT64_MAX) const; void verifyEnd(unsigned int const paramNumber) const; private: std::vector paramVector; }; } // namespace #endif