542 lines
14 KiB
C++
542 lines
14 KiB
C++
#ifndef XMLRPC_BASE_HPP_INCLUDED
|
|
#define XMLRPC_BASE_HPP_INCLUDED
|
|
|
|
#include <xmlrpc-c/config.h>
|
|
|
|
#include <climits>
|
|
#include <cfloat>
|
|
#include <ctime>
|
|
#include <vector>
|
|
#include <map>
|
|
#include <string>
|
|
#if XMLRPC_HAVE_TIMEVAL
|
|
#include <sys/time.h>
|
|
#endif
|
|
|
|
#include <xmlrpc-c/c_util.h>
|
|
#include <xmlrpc-c/base.h>
|
|
|
|
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<unsigned char> 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<std::string, xmlrpc_c::value> 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<xmlrpc_c::value> 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<class InputIterator> 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<class MemberClass> 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<class K, class V> xmlrpc_c::value_struct
|
|
toValue(std::map<K, V> const& in) {
|
|
/*----------------------------------------------------------------------------
|
|
convert C++ map to XML-RPC structure
|
|
-----------------------------------------------------------------------------*/
|
|
cstruct ret;
|
|
for (typename std::map<std::string, V>::const_iterator p = in.begin();
|
|
p != in.end();
|
|
++p) {
|
|
ret[p->first] = toValue(p->second);
|
|
}
|
|
return xmlrpc_c::value_struct(ret);
|
|
}
|
|
|
|
template<class T> inline xmlrpc_c::value_array
|
|
toValue(std::vector<T> 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<class K, class V> inline void
|
|
fromValue(std::map<K, V> & 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<std::string, xmlrpc_c::value>::const_iterator p = m.begin();
|
|
p != m.end();
|
|
++p) {
|
|
fromValue(y[p->first], p->second);
|
|
}
|
|
}
|
|
|
|
template<class T> inline void
|
|
fromValue(std::vector<T> & 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<class T > 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<xmlrpc_c::value> paramVector;
|
|
};
|
|
|
|
} // namespace
|
|
|
|
#endif
|