This chapter describes the functions in the libxmlrpc++ function library, which is part of XML-RPC For C/C++ (Xmlrpc-c). Also see General Library Information - C++.
libxmlrpc++ provides low-level classes that are useful in XML-RPC clients and servers. For example, it includes classes for the various data types defined by XML-RPC. You use these classes with every other Xmlrpc-c C++ library, and those libraries also use libxmlrpc++ internally. Few Xmlrpc-c applications use only libxmlrpc++.
You must know something about XML-RPC (the protocol) to understand this chapter. You don't have to know the details of the protocol, since Xmlrpc-c is meant to spare you from learning that, but you do have to know the kinds of things that make up an XML-RPC transaction.
Everything you need to know about XML-RPC is here.
Everything described in this chapter is new in XML-RPC For C/C++ 1.03 (June 2005).
The interfaces to the various facilities of libxmlrpc++ are declared by the header files <xmlrpc-c/base.hpp>, <xmlrpc-c/xml.hpp>, <xmlrpc-c/girerr.hpp>, and <xmlrpc-c/timeout.hpp>.
Documentation of each class tells you which interface header file to use.
You'll have to figure out where on your system this file lives and how to make your compiler look there for it. Or use xmlrpc-c-config.
The classic Unix name for the file containing the libxmlrpc++ library is libxmlrpc++.a or libxmlrpc++.so. The classic linker option to cause the library to be linked into your program is -l xmlrpc++. These are hints; you'll have to modify this according to conventions of your particular platform. You'll also have to figure out where the library resides and how to make your linker look there for it. Or use xmlrpc-c-config.
There is an older generation C++ library, not documented, that older programs (probably written before June 2005) use. That library is libxmlrpc_cpp.a.
The following libraries are prerequisites of libxmlrpc++, so you'll need to link them in too:
An object of class girerr::error represents an error that caused an Xmlrpc-c method to fail. It is derived from standard C++ class std::exception.
You ordinarily see one of these objects when it gets thrown, as described in Success/Failure.
This class is declared in header file xmlrpc-c/girerr.hpp.
The only constructor takes a std::string as an argument. The string is the text description of the error.
Example:
throw(error("Everything's basically gone to Hell"));
The what method returns a text description of the error.
Example:
try {
rpcP->call();
} catch (std::exception const e) {
cerr << "call failed because "
<< e.what() << endl;
}
Xmlrpc-c uses shared automatic pointers extensively. With shared automatic pointers, an object always knows how many pointers exist to it and the object gets destroyed automatically when the last pointer to it gets destroyed. That way, your code never has to explicitly destroy an object or worry that it might use a stale pointer.
To do this, Xmlrpc-c defines a class girmem::autoObject (the girmem namespace name is essentially arbitrary). This is an abstract base class; various Xmlrpc-c classes are derived from it, for example xmlrpc_c::client and xmlrpc_c::method.
Another class, xmlrpc_c::autoObjectPtr, is for the pointers. An object of class autoObjectPtr points to an object of class autoObject. autoObjectPtr is also an abstract base class. For each class derived from autoObject, there is a corresponding class derived from autoObjectPtr, named the same except with a "Ptr" suffix. For example, xmlrpc_c::clientPtr and xmlrpc_c::methodPtr.
In our discussion of auto-objects and their pointers, we refer to objects of the derived classes as being objects of class autoObject and autoObjectPtr, though strict C++ terminology probably says that isn't right. It's just a lot more convenient to treat the base class as a superclass.
The constructor, destructor, copy constructor, and assignment operator of autoObjectPtr maintain the reference count of the associated autoObject.
Each autoObjectPtr object has a pointer dereference operator so you can use it like you expect to use a pointer:
void foo callIt(clientPtr const clientP) {
clientP->call(...);
}
You create an autoObjectPtr like this:
clientPtr const clientP(new client(...));
If the new fails for lack of memory and returns a NULL pointer, the autoObjectPtr constructor throws an error.
An autoObjectPtr object can point to nothing. Such an object exists just to hold a place -- an undefined variable waiting to be assigned. But unlike a C++ pointer, when you try to dereference such a pointer, you don't get a crash or wild reference, but a thrown error. You create an undefined autoObjectPtr with the no-argument constructor.
You cannot assign to an autoObjectPtr that already points to something. An attempt to do so throws an error.
To use an autoObject properly, you must create it dynamically (with new). Automatic and static storage class don't work. (But see below, because you obviously don't need autoObject behavior with those storage classes).
To use an autoObject properly, you must never refer to it except via an autoObjectPtr, but sometimes the vagaries of C++ require you to have a C++ pointer to it. For that purpose, an autoObjectPtr has a get method that returns a C++ pointer to the associated autoObject. If you use this, you must make sure that you use that pointer (and any copy of it) only while an autoObjectPtr to the same object exists.
Alternatively, you can ignore this whole topic and use an autoObject like any other C++ object, managing its lifetime the conventional way. The autoObject characteristics appear only when you create an autoObjectPtr for it. For example, you can have an automatic variable of type xmlrpc-c::client:
{
client myClient(...);
myClient.call(...);
}
Or you can refer to it exclusively by C++ pointers:
client * myClientP = new client(...);
myClientP->call();
delete(myClientP);
C++ itself does not provide a way for a method to have named parameters, and there's no practical way to have optional parameters. Both of these are especially useful on constructor methods, so many of the Xmlrpc-c classes have a constructor that follows a paradigm that provides the equivalent, as in the following example:
country canada(country::constrOpt()
.population(5)
.landarea(10)
.un_member(true)
At first sight, this doesn't even look like C++, but if you look
more closely, you can see that it is. The periods before the
parameter names are the "member of" operator. A more normal
way (but not as convenient for the present purpose) to write this
would be:
country:constrOpt().population(5).landarea(10)...
constrOpt is a subclass of country, so the construction country::constrOpt() constructs one. population is a method of Class constrOpt whose return value is a reference to its own object. The same is true of landarea and un_member. So the code above simply calls the population, landarea, and un_member methods, in succession, on a new object of Class constrOpt and passes a reference to that new object to the country constructor.
The constructor for Class country is simple:
country(country::constrOpt const& opt);
country::constrOpt is defined such that the constructor of canada can find out which of constrOpt's methods where called, and with what argument, thus making the paradigm shown above the equivalent of having named optional parameters on the constructor.
In Xmlrpc-c, this constructor option subclass is always named "constrOpt" when it exists. But not all classes have this kind of constructor.
You can put the options in any order and omit any you like, so long as the particular class constructor is OK with that. Results are undefined if you specify the same option name twice.
The form of the arguments of the option methods (e.g. country::constrOpt::population) depends on the method. In this example, population and landarea each take one unsigned integer and un_member takes a boolean.
If you have a more complex construction to do, you can always build up the constrOpt object more explicitly:
country::constrOpt opt;
opt.population(5);
if (areaIsKnown)
opt.landArea(landArea);
country const canada(opt);
An object of class xmlrpc_c::value is an XML-RPC value (i.e. what you could represent with a <value> XML element).
You will typically use this for the parameters in an XML-RPC call and the result from an XML-RPC response, both in Xmlrpc-c clients and servers.
Unlike with Xmlrpc-c's C interfaces, this class is never used for anything other than an actual XML-RPC value.
Examples of the kinds of values an object of this class can represent are:
XML-RPC values are, by design, the same kinds of things you can represent with basic data types in a language such as C++. The only reason we have a special class for them in Xmlrpc-c is to make the connection between your code and the XML-RPC protocol more clear. You can easily convert between the two (for example, between an XML-RPC integer and a regular old C++ integer) and will normally do all your processing in the regular C++ types and use xmlrpc_c::value only as direct inputs and outputs of Xmlrpc-c.
There is a derived class of xmlrpc_c::value for each of the XML-RPC types. (Note that the XML-RPC types are defined in the XML-RPC spec). They are, with the obvious mappings to the XML-RPC types:
If you're familiar with the Xmlrpc-c C interface, you'll note that there is no equivalent above to its XMLRPC_TYPE_C_PTR type. That's because unlike the C xmlrpc_value type, xmlrpc_c::value isn't used to represent anything except XML-RPC types.
xmlrpc_c::value_nil is not really an XML-RPC type. It goes with the common extension of XML-RPC that defines a nil type (with XML element type "nil").
Similarly, xmlrpc_c::value_i8 corresponds to the <i8> 64 bit integer extension type.
xmlrpc_c::value is not an abstract base class. That means you can't operate on a variable of type xmlrpc_c::value and get behavior specific to the derived class xmlrpc_c::value_struct. You also can't dynamic cast a xmlrpc_c::value * to xmlrpc_c::value_struct *. See below for instructions for using a base class object.
For each of the type-specific derived classes, there are constructors to create an object from the usual C++ equivalent data type (e.g. to create an xmlrpc_c::value_int from an int). There are also cast operators to cast such an object to the usual type. Except in cases where the language just doesn't make casting possible, that is. In such a case, there is a converter method to accomplish the same thing.
Example:
int const planetCount(9);
xmlrpc_c::value_int const planetCountX(planetCount);
int const bodyCount(static_cast<int>(planetCountX) + moonCount);
For each of the type-specific derived classes, there is a constructor to create an object out of an object of the base class (xmlrpc_c::value) type. It throws an error if the object represents a value not of the corresponding type (e.g. you try to construct an xmlrpc_c::value_int from an XML-RPC string value).
Example:
xmlrpc_c::value rpcResult;
// Just a placeholder variable. Not yet an actual XML-RPC value.
doMyRpc(&rpcResult);
// doMyRpc() does an RPC that is supposed to return an integer result.
int const intResult(xmlrpc_c::value_int(rpcResult));
// This construction throws an error if what the RPC returned wasn't
// really an integer.
cout << "RPC returned" <<
static_cast<int>(intResult)
As mentioned above, xmlrpc_c::value is not an abstract base class, but there are situations where code is agnostic to the specific type of XML-RPC value (e.g. doesn't care whether it is an integer or a string), so represents the value merely as an object of the base class xmlrpc_c::value. The object actually contains all the information specific to the particular XML-RPC type; you just can't access it in the usual C++ way. Instead, construct an object of the appropriate derived class, giving the base class object as a constructor argument, as in the example above, and then operate on that.
As noted above, the constructor fails if the XML-RPC value isn't of the corresponding type (e.g. it's a string and you tried to construct an xmlrpc_c::value_int from it). If you don't know at coding time what the XML-RPC value type should be, you can use the type method (see below) to find out what it actually is, and then construct an object that fits.
A placeholder xmlrpc_c::value does not represent an XML-RPC value; it is just a variable to which you can assign another xmlrpc_c::value. You can't use it for anything else. You construct a placeholder xmlrpc_c::value with the no-argument constructor and it stops being a placeholder as soon as you assign some value to it. A xmlrpc_c::value variable that is not a place holder is said to be "instantiated." Use the isInstantiated method to determine whether a xmlrpc_c::value is a placeholder.
If you do attempt to do something with a placeholder xmlrpc_c::value other than assign a value to it, that throws an exception.
This class is declared in header file xmlrpc-c/base.hpp.
The no-argument constructor creates a place-holder object as described above.
There is a copy constructor.
type_t is an enumerated type that represents one of the types of XML-RPC values. Its values are, with obvious meaning:
There is an output operator for type type_t that generates text such as "int" and "array" for its values.
Example:
value::type_t const myType(value::TYPE_STRUCT);
cerr << "The type of value is: " << myType << endl;
This operator was new in Xmlrpc-c 1.26 (March 2011). Before that, the compiler defaults to the integer output operator, using the integer equivalent of the enumerations. E.g. TYPE_ARRAY displays as "6".
The type method returns the type of XML-RPC value that the object represents.
Prototype:
xmlrpc_c::value::type_t type() const;
The cvalue method returns the value of XML-RPC value as a native C++ data type, such as an integer.
Example:
xmlrpc_c::value_int val1(7);
xmlrpc_c::value_string val2("hello world");
cout << "Value 1: " << val1.cvalue()
<< "Value 2: " << val2.cvalue();
There isn't really a cvalue method of the xmlrpc_c::value base class, but each of the derived classes implements one of its own. (And it's not a virtual method either, because it's different in each derived class, since it has various return value types).
Every derived class has other means of converting the XML-RPC value to a native C++ value, and those means (such as typecasts) are generally clearer, since they make it obvious to what type they convert. The point of cvalue is that it has the same name in all the derived classes. That sometimes makes code easier to write.
Each derived class picks one native C++ type to associate with its cvalue method. If that isn't the type you want, the derived class often has other methods available.
cvalue was new in Xmlrpc-c 1.19 (June 2009).
The isInstantiated method tells whether the object represents an actual XML-RPC value or is just a placeholder (see above). It returns true in the former case; false in the latter.
Prototype:
bool isInstantiated() const;
This method was new in Xmlrpc-c 1.13 (December 2007).
There is an assign-to operator for assigning an xmlrpc_c::value value to an xmlrpc_c::value variable. However, you can assign only to a placeholder variable as described above. The operator throws an error if you try to change the value of a fully instantiated object.
This is a derived class of xmlrpc_c::value. It represents an XML-RPC integer value (XML element type "int").
More specifically, it represents an integer value with 4 byte (32 bit) range (XML element type "i8"). I.e. it can represent integers in the range from -2**32 through 2**32 - 1.
This class is declared in header file xmlrpc-c/base.hpp.
You construct an xmlrpc_c::value_int object from a C++ int:
xmlrpc_c::value_int const param1(7);
You can also construct one from an object of the base class type, as described under Class xmlrpc_c::value.
You can cast an xmlrpc_c::value_int object to a C++ int:
xmlrpc_c::value_int const param1(7);
int const param1Value(static_cast<int>(param1));
See general documentation of cvalue.
This method returns a value of type int.
This is a derived class of xmlrpc_c::value. It represents an XML-RPC 8 byte integer value (XML element type "i8"). I.e. it can represent an integer in the range from -2**64 through 2**64 - 1.
This class is declared in header file xmlrpc-c/base.hpp.
This class was new in Xmlrpc-c 1.07 (October 2006).
You construct an xmlrpc_c::value_i8 object from a C++ long long:
xmlrpc_c::value_i8 const param1(7);
You can also construct one from an object of the base class type, as described under Class xmlrpc_c::value.
You can cast an xmlrpc_c::value_i8 object to a C++ long long:
xmlrpc_c::value_i8 const param1(7);
long long const param1Value(static_cast<long long>(param1));
See general documentation of cvalue.
This method returns a value of type long long.
This is a derived class of xmlrpc_c::value. It represents an XML-RPC boolean (logical; true/false) value (XML element type "boolean").
This class is declared in header file xmlrpc-c/base.hpp.
You construct an xmlrpc_c::value_boolean object from a C++ bool:
xmlrpc_c::value_boolean const param1(true);
You can also construct one from an object of the base class type, as described under Class xmlrpc_c::value.
You can cast an xmlrpc_c::value_boolean object to a C++ bool:
xmlrpc_c::value_boolean const param1(true);
bool const param1Value(static_cast<bool>(param1));
See general documentation of cvalue.
This method returns a value of type bool.
This is a derived class of xmlrpc_c::value. It represents an XML-RPC string value (XML element type "string"). It uses the same definition of XML-RPC string as the C version.
This class is declared in header file xmlrpc-c/base.hpp.
You construct an xmlrpc_c::value_string object from a C++ string:
xmlrpc_c::value_string const param1("hello");
xmlrpc_c::value_string const param1("Line 1\nLine 2\n");
xmlrpc_c::value_string const param1("Line 1\r\nLine 2\r\n");
xmlrpc_c::value_string const param1("embedded\rCR", xmlrpc_c::value_string::nlCode_lf);
Prototypes:
value_string(std::string const& cppvalue);
enum nlCode {nlCode_all, nlCode_lf};
value_string(std::string const& cppvalue,
nlCode const nlCode);
The nlCode argument tells what kind of line delimiters you use in your cppvalue argument. nlCode_all means, LF (line feed), CR (carriage return), and CRLF all mean a line delimiter, while nlCode_lf means only LF does and CR is just a character in a line.
The constructor that doesn't have the nlCode behaves as if nlCode=nlCode_all.
The constructor with nl_Code was new in Xmlrpc-c 1.11 (June 2007).
cppvalue is a UTF-8 string.
ASCII strings are a subset of UTF-8 strings, so if you don't want to learn what UTF-8 and UTF-16 are all about, just stick to ASCII. Note that all ASCII codes have zero for the high order bit of the byte, so if you're taking this easy route, make sure you never have a one in your high order bit.
You can also construct a xmlrpc_c::value_string from an object of the base class type, as described under Class xmlrpc_c::value.
Prototype:
value_string(xmlrpc_c::value const baseValue);
You can cast an xmlrpc_c::value_string object to a C++ string:
xmlrpc_c::value_string const param1("hello");
string const param1Value(static_cast<string>(param1));
The string you get uses LF (line feed, unix newline) to represent a line delimiter. If you want CRLF instead, see crlfValue.
This method returns the value of the object as a C++ string, in which a line delimiter is represented by the two character sequence CRLF (carriage return, line feed).
If you want plain unix newline (LF) instead, see Cast Operators. Example:
xmlrpc_c::value_string const httpDoc("Line 1\nLine 2\n");
string const httpDoc(value.crlfValue());
assert(httpDoc == "Line 1\r\nLine 2\r\n");
Prototype:
std::string
crlfValue() const;
Use validate to be sure the string value you created doesn't result in invalid XML when you use it in an XML-RPC call or response, as described in the explanation of the String data type. If the string is OK, it does nothing; otherwise, it throws an error. What makes a string fail this test is that you supplied non-XML characters when you constructed the object. If you are sure you didn't supply any control characters other than newline, carriage return, and tab, you don't need validate(). Also, if you know that whatever interprets the XML-RPC call or response you generate with this string value is OK with non-XML characters, you don't need it.
validate() was new in Xmlrpc-c 1.42 (June 2015).
See general documentation of cvalue.
This method returns a value of type std::string.
This is a derived class of xmlrpc_c::value. It represents an XML-RPC floating point number value (XML element type "double").
This class is declared in header file xmlrpc-c/base.hpp.
You construct an xmlrpc_c::value_double object from a C++ double:
xmlrpc_c::value_double const param1(3.14);
You can also construct one from an object of the base class type, as described under Class xmlrpc_c::value.
You can cast an xmlrpc_c::value_double object to a C++ double:
xmlrpc_c::value_double const param1(3.14);
double const param1Value(static_cast<double>(param1));
See general documentation of cvalue.
This method returns a value of type double.
This is a derived class of xmlrpc_c::value. It represents an XML-RPC point in time value (XML element type "dateTime.iso8601").
This class is declared in header file xmlrpc-c/base.hpp.
You can construct an xmlrpc_c::value_datetime object from any of various C++ data types:
time_t const now_sec(date());
xmlrpc_c::value_datetime const param1(now_sec);
struct timeval now_microsec;
gettimeofday(&now_microsec, NULL);
xmlrpc_c::value_datetime const param2(now_microsec);
struct timespec now_nanosec;
gettimeofday_nsec(&now_nanonsec);
xmlrpc_c::value_datetime const param3(now_nanosec);
xmlrpc_c::value_datetime const param4("19980717T14:08:55");
The string constructor needs more explanation: The string value specifies the point in time in the same strange quasi-ISO8601 format that is used in XML-RPC XML. The format follows the example given above.
It is not the case that when you use the string constructor, you are controlling the XML at a lower level and are supplying the actual text for the XML. You are fundamentally identifying a point in time and an Xmlrpc-c facility that generates XML encodes a point in time independently. This is not really a useful constructor, except for backward compatibility with older versions of Xmlrpc-c's C interface.
You can also construct one from an object of the base class type, as described under Class xmlrpc_c::value.
You can cast an xmlrpc_c::value_datetime object to a C++ time_t, timeval, or timespec, or xmlrpc_datetime:
xmlrpc_c::value_datetime const param1(time(NULL));
time_t const param1Value(static_cast<time_t>(param1));
timeval const param1ValueTv(static_cast<timeval>(param1));
timespec const param1ValueTs(static_cast<timespec>(param1));
xmlrpc_datetime const param1ValueX(static_cast<xmlrpc_datetime>(param1);
The timeval and timespec cast operators wer new in Xmlrpc-c 1.15 (June 2008). The xmlrpc_datetime operator was new in Xmlrpc-c 1.31 (June 2012).
See general documentation of cvalue.
This method returns a value of type time_t.
This method returns the datetime as an ISO 8601 string, the same as the C function xmlrpc_read_datetime_8601().
This method was new in Xmlrpc-c 1.31 (June 2012).
This is a derived class of xmlrpc_c::value. It represents an XML-RPC byte string value (XML element type "base64").
This class is declared in header file xmlrpc-c/base.hpp.
The cbytestring type is a natural C++ analog to the XML-RPC byte string type, and is convenient in several xmlrpc_c::value_bytestring methods.
typedef std::vector<unsigned char> cbytestring;
cbytestring was new in Xmlrpc-c 1.22 (March 2010).
You construct an xmlrpc_c::value_bytestring object from a C++ vector<unsigned char>:
unsigned char myByteAry[] = {0x10, 0x11, 0x12, 0x13, 0x14};
vector<unsigned char> const myBytes(&myByteAry[0], &myByteAry[4]);
xmlrpc_c::value_bytestring const param1(myBytes);
You can also construct one from an object of the base class type, as described under Class xmlrpc_c::value.
There are none.
You might think there should be a cast operator to cast an xmlrpc_c::value_bytestring object to a C++ vector<unsigned char>, but the vector template is a little too complex for that; the compiler can't figure out which constructor to use.
Instead, use the vectorUcharValue converter method.
The vectorUcharValue method returns the value of the object as a C++ vector<unsigned char> data structure:
unsigned char const myByteAry[] = {0x10, 0x11, 0x12, 0x13, 0x14};
vector<unsigned char> const myBytes(&myByteAry[0], &myByteAry[4]);
xmlrpc_c::value_bytestring const param1(myBytes);
vector<unsigned char > const param1Value(param1.vectorUcharValue());
See general documentation of cvalue.
This method returns a value of type std::vector<unsigned char>.
The length method returns the number of bytes in the byte string.
Prototype:
size_t length() const;
This is a derived class of xmlrpc_c::value. It represents a non-value or absence of a value (a type defined by a common XML-RPC extension) XML-RPC integer value (XML element type "nil").
This class is declared in header file xmlrpc-c/base.hpp.
You construct an xmlrpc_c::value_int object with no arguments:
xmlrpc_c::value_int const param1;
You can also construct one from an object of the base class type, as described under Class xmlrpc_c::value.
There are none.
See general documentation of cvalue.
This method returns a value of type void *, value NULL (0).
This is a derived class of xmlrpc_c::value. It represents an XML-RPC structure value, analogous to a C++ struct. (XML element type "struct").
An XML-RPC structure value is a mapping of a string to another XML-RPC value. I.e. it is a set of members and each member is an ordered pair of (key, value). The key is the name of the member, and is a text string. The value is any XML-RPC value.
This class is declared in header file xmlrpc-c/base.hpp.
The cstruct type is a natural C++ analog to the XML-RPC structure type, and is convenient in several xmlrpc_c::value_struct methods.
typedef std::map<std::string, xmlrpc_c::value> cstruct;
cstruct was new in Xmlrpc-c 1.22 (March 2010).
You construct an xmlrpc_c::value_struct object from a C++ map<std::string, xmlrpc_c::value>:
// Make the map value 'structData'
map<std::string, xmlrpc_c::value> structData;
pair<std::string, xmlrpc_c::value> member("the_integer",
xmlrpc_c::value_int(9));
structData.insert(member);
// Make an XML-RPC struct out of it
xmlrpc_c::value_struct const param1(structData);
You can also construct one from an object of the base class type, as described under Class xmlrpc_c::value.
You can cast an xmlrpc_c::value_struct object to a C++ map<string, xmlrpc_c::value>:
xmlrpc_c::value_struct const param1(whatever);
map<std::string, xmlrpc_c::value> const param1Value(
static_cast<map<std::string, xmlrpc_c::value> >(param1));
See general documentation of cvalue.
This method returns a value of type std::map<std::string, xmlrpc_c::value>.
This is a derived class of xmlrpc_c::value. It represents an XML-RPC array value. (XML element type "array").
An XML-RPC array value is a finite array of other XML-RPC values. The elements of the array need not be of uniform type.
This class is declared in header file xmlrpc-c/base.hpp.
The carray type is a natural C++ analog to the XML-RPC array type, and is convenient in several xmlrpc_c::value_array methods.
typedef std::vector<xmlrpc_c::value> carray;
carray was new in Xmlrpc-c 1.22 (March 2010).
You construct an xmlrpc_c::value_array object from a C++ vector<xmlrpc_c::value>:
// Make the vector value 'arrayData'
vector<xmlrpc_c::value> arrayData;
arrayData.push_back(xmlrpc_c::value_int(7));
arrayData.push_back(xmlrpc_c::value_double(2.78));
arrayData.push_back(xmlrpc_c::value_string("hello world"));
// Make an XML-RPC array out of it
xmlrpc_c::value_array array1(arrayData);
You can also construct one from an object of the base class type, as described under Class xmlrpc_c::value.
There are none.
You might think there should be a cast operator to cast an xmlrpc_c::value_array object to a C++ vector<xmlrpc_c::value>, but the vector template is a little too complex for that; the compiler can't figure out which constructor to use.
Instead, use the vectorValueValue converter method.
The vectorValueValue method returns the value of the object as a C++ vector<xmlrpc_c::value> data structure:
xmlrpc_c::value_array array1(...);
vector<xmlrpc_c::value> const param1Value(param1.vectorValueValue());
See general documentation of cvalue.
This method returns a value of type std::map<xmlrpc_c::value>.
The size method returns the number of elements in the array.
Prototype:
unsigned int size() const;
The arrayValueArray function generates an XML-RPC array object from a C++ array. The type of the array elements corresponds to the type of the C++ array element, in the same way as ParamList.addc() arguments.
In the following example, we construct myArray, an XML-RPC array with three boolean elements.
bool boolarray[] = { true, false, true };
xmlrpc_c::value_array myArray(arrayValueArray(boolarray, 3));
arrayValueArray was new in Xmlrpc-c 1.19 (June 2009).
The arrayValueSlice function generates an XML-RPC array object from a pair of iterators. The array contains elements from the thing the first iterator points to up to (but not including) the thing the second iterator points to. The type of the elements depends upon the type of the thing the iterator points to, in the same way as ParamList.addc() arguments.
int intarray[] = { 1, 2, 3, 5, 8, 13, 21 };
xmlrpc_c::value_array mySlice(
arrayValueSlice(&intarray[5], &intarray[7]));
In this example, we construct mySlice, an XML-RPC array with two integer elements.
arrayValueSlice was new in Xmlrpc-c 1.19 (June 2009).
XML-RPC has a concept of a "fault." A fault is something that causes an RPC to fail. When an RPC fails, there is always one fault associated with the RPC. It is described in the RPC's response.
An XML-RPC fault embodies two pieces of information:
I frankly recommend that you just ignore the fault code. While there is a long tradition in programming of representing error information in integers, text descriptions are usually much more useful. Integers are more convenient for programs to interpret, but in reality programs hardly ever interpret errors beyond a binary success/failure. Where an RPC can have certain well-defined failures on which the calling program can act, the RPC really shouldn't fail at all. For example, if an RPC has a file name as an argument and the program is fully prepared to respond to the eventuality that a file by that name does not exist, then "file does not exist" is not a failure. It's a legitimate successful result of that RPC.
An object of this class represents an XML-RPC fault.
The xmlrpc_c::fault::code_t type is an XML-RPC fault code. It is an enumerated type, equivalent to an integer. Its enumerated values are basically a recommendation; you should feel free to cast it to any other enumeration or a plain integer and assign any meaning to the values.
The XML-RPC specification does not standardize any values.
Note that Xmlrpc-c does not conform to any part of the Fault Code Interoperability standard. Xmlrpc-c suggests these negative values for low level failures, and uses them in its own low-level implementation. Xmlrpc-c recommends you use positive values for higher level method-specific failures.
The enumerated values are:
You construct a xmlrpc_c::fault object from a std::string fault string and an int fault code:
xmlrpc_c::fault("The rapture has begun.", 666);
The getDescription method returns the text description of the fault (the fault string).
Prototype:
std::string getDescription();
The getCode method returns the fault code of the fault.
Prototype:
xmlrpc_c::fault::code_t getCode();
An XML-RPC RPC has a parameter list. It's part of the call, and a copy is provided in the response as well. The parameter list is simply a list of parameters. It may contain any number of parameters, including zero. The parameters are ordered, and not named. There's no such thing as a missing parameter (but consider the nil value).
An object of this class represents the parameters to an XML-RPC call. You see such objects when you make an XML-RPC call from a client or process one in a server, using the higher level Xmlrpc-c facilities.
Examples:
xmlrpc:c::paramList myParams; myParams.add(xmlrpc_c::value_int(5); myParams.add(xmlrpc_c::value_int(7); assert(myParams.size() == 2); assert(static_cast<int<(myParams[1]) == 7); // The above are all you need to extract the contents of a parameter list, // but the following show convenient extraction with validation. assert(myParams.getInt(0) == 7); myParams.getString(0); // throws because param 0 isn't a string myParams.verifyEnd(2); // does nothing because 2 _is_ the end of the list myParams.verifyEnd(1); // throws because there are more parameters xmlrpc:c::paramList myParams2(2); myParams.add(xmlrpc_c::value_string("hello"); myParams.add(xmlrpc_c::value_datetime(now());
xmlrpc_c::serverAccessor rainFallDb(...); xmlrpc_c::rpcOutcome outcome; rainFallDb.call("addCityRainfall", paramList() .add(value_string("Seattle") .add(value_double(39.2))), &outcome);
xmlrpc_c::serverAccessor rainFallDb(...); xmlrpc_c::rpcOutcome outcome; rainFallDb.call("addCityRainfall", paramList().addc("Seattle").addc(39.2), &outcome);
Prototype:
paramList(unsigned int paramCount = 0);
A xmlrpc_c::paramList always starts life empty (you add parameters to it later), so there is only one constructor argument, and even it is optional. The argument is a hint as to the number of parameters the object ultimately will have. Using a good hint can improve efficiency.
The add method adds a parameter to the parameter list. As you probably surmise, the order in which you add parameters is the order of the parameters for XML-RPC purposes.
Prototype:
xmlrpc_c::paramList &
add(xmlrpc_c::value const param);
The method returns a reference to the object so that you can stack up calls to make more compact, readable code as in the "addCityRainfall" example above.
Before Xmlrpc-c 1.10 (March 2007), the return value is void; you cannot stack up calls. So if your program uses the return value and you link it to an old Xmlrpc-c library, the results are undefined (i.e. your program will probably crash). If you want to get a link-time error instead in this situation, use addx. If you want it actually to work with an old library, use add and don't use the return value.
This is identical to add, but did not exist before Xmlrpc-c 1.10. That means there is no way to get undefined behavior from an old Xmlrpc-c library, unlike with add.
This is like add, except that the argument can be any of various standard C++ types and the method creates a parameter of a corresponding XML-RPC type. Example:
xmlrpc_c::paramList myParams;
myParams.addc(7);
myParams.addc("hello world");
std::vector<std::string> array1;
...
myParams.addc(array1);
This example creates a parameter list containing three parameters: an XML-RPC integer, an XML-RPC string, and an XML-RPC array of strings.
addc is a template function with prototype:
template<class T > xmlrpc_c::paramList& addc(const T & x)
The argument may also be an XML-RPC value object (xmlrpc_c::value), which makes addc do the same thing as add.
The correspondence between the C++ type of the addc argument and the XML-RPC type of the RPC parameter is:
C++ type | XML-RPC parameter type |
---|---|
const char * | string |
std::string | text string |
int | integer, 32 bit precision |
bool | boolean |
double | floating point number |
xmlrpc_c::value | various |
std::map<std:string, X> | Structure. Type of members is determined by C++ data type of X. |
std::vector<X> | Array. Type of elements is determined by C++ data type of X. |
std::vector<unsigned char> | Byte string |
The return value of addc is a reference to the parameter list object to which it belongs, so you can chain calls like this if you like:
mParams.addc(5).addc(7);
addc was new in Xmlrpc-c 1.19 (June 2009).
The size method returns the size of the parameter list (how many parameters are in it).
Prototype:
unsigned int size();
The subscript operator does the obvious thing: it returns the parameter (as an xmlrpc_c::value) whose position is the subscript. The first parameter is position 0.
If you specify a subscript that is not a position that exists in the parameter list (e.g. there are 3 parameters and you specify position 9), the method throws a girerr::error.
These methods let you do the boring work of validating and interpreting parameter lists with very few lines of code in the most common cases.
If you want to do more sophisticated handling of wrong types, or process a parameter that could have various types, get the parameter as an xmlrpc_c::value object with the subscript operator and process that. Also use the size method to make sure the parameter exists.
The getInt method gets the value of an integer parameter. It throws a girerr::error if the parameter you identify does not exist or is not an integer.
You may also specify a minimum and maximum acceptable value for the parameter. If the value doesn't conform, the method throws a girerr:error.
The other methods are similar, for the other XML-RPC data types.
Prototypes:
int
getInt(unsigned int paramNumber,
int minimum = INT_MIN,
int maximum = INT_MAX) const;
bool
getBoolean(unsigned int paramNumber) const;
double
getDouble(unsigned int paramNumber,
double minimum = DBL_MIN,
double maximum = DBL_MAX) const;
enum timeConstraint {TC_ANY, TC_NO_PAST, TC_NO_FUTURE};
time_t
getDatetime_sec(unsigned int paramNumber,
timeConstraint constraint
= paramList::TC_ANY) const;
std::string
getString(unsigned int paramNumber) const;
std::vector<unsigned char>
getBytestring(unsigned int paramNumber) const;
std::vector<xmlrpc_c::value>
getArray(unsigned int paramNumber,
unsigned int minSize = 0,
unsigned int maxSize = UINT_MAX) const;
std::map<std::string, xmlrpc_c::value>
getStruct(unsigned int paramNumber) const;
void
getNil(unsigned int const paramNumber) const;
long long
getI8(unsigned int const paramNumber,
long long const minimum = XMLRPC_INT64_MIN,
long long const maximum = XMLRPC_INT64_MAX) const;
In the constraint argument of getDatetime_sec method, TC_ANY means any datetime is acceptable; TC_NO_PAST means datetimes in the past are not acceptable; TC_NO_FUTURE means datetimes in the future are not acceptable. Note that using these time constraints can cause some slightly unpredictable behavior because what's acceptable depends no exactly when you check the parameter. What was valid when the RPC started might be invalid by the time it's checked. A datetime that is properly in the future when you get the parameter might be in the past by the time you do something with the datetime. But as long as you're willing to accept somewhat arbitrary behavior when the time is close to the present, the constraints can still be quite useful.
getNil obviously doesn't actually get anything. You would use this either for the sake of causing an error to be thrown if the parameter is not the nil value or just for logical completeness.
getI8() was new in Xmlrpc-c 1.11 (June 2007).
Prototypes:
void
verifyEnd(unsigned int paramNumber) const;
The verifyEnd method verifies that a specified position is the end of the parameter list (e.g. if there are 3 parameters, there are parameters in positions 0, 1, and 2, and position 3 is the end of the list).
If the specified position is the end of the parameter list, the method does nothing at all. If it is not, the method throws a girerr::error.
If you want to do more sophisticated handling of incorrect parameter list size, use the size method.
A completed XML-RPC RPC has an outcome. That outcome is one of two things:
Don't confuse the various ways an RPC can fail to execute with an RPC outcome. If an RPC fails to execute, there is no outcome. An example of an RPC failing to execute is where the server you identify doesn't exist. When an RPC fails to execute, there is usually an error thrown, for example from the call method of the serverAccessor object you used to attempt the RPC.
An object of this class represents the outcome of an XML-RPC call. You see such objects when you make an XML-RPC call from a client or process one in a server, using the higher level Xmlrpc-c facilities. For example, the call method of serverAccessor returns a rpcOutcome object.
Examples:
xmlrpc_c::serverAccessor rainFallDb(...);
xmlrpc_c::rpcOutcome outcome;
employeeDb.call("getCityRainFall",
paramList().add(value_string("Seattle")),
&outcome);
if (outcome.succeeded())
cout << "Rainfall is "
<< static_cast<double>(outcome.getResult())
<< endl;
else
cout << "getCityRainFall failed: "
<< outcome.getFault().getDescription()
<< endl;
A placeholder rpcOutcome object is one that doesn't actually represent an RPC outcome; it's just something to which you can assign the value of another RPC outcome. Any attempt to do anything else with it throws an error.
Prototype:
rpcOutcome();
rpcOutcome(xmlrpc_c::value result);
rpcOutcome(xmlrpc_c::fault fault);
To create a successful RPC outcome (an RPC result), use the value constructor.
To create a failed RPC outcome (a fault) use the fault constructor.
To create a placeholder RPC outcome, which you can use only to subsequently assign another RPC outcome to it, use the default (no-argument) constructor.
The succeeded method tells you whether the outcome is a success or failure.
Prototype:
bool succeeded() const;
The getResult method tells you the result of the RPC, assuming it has one (i.e. it succeeded). If the outcome is not success (the RPC has no result), the method throws an error.
Prototype:
xmlrpc_value getResult() const;
If your program does not need to distinguish between XML-RPC failures and failures at other levels in your program, you can just "assume" all RPCs succeed and call getResult on the outcome. Where the RPC fails, your code will throw an error.
The getFault method tells you how the RPC failed, assuming it did. If the outcome is not failure, the method throws an error.
Prototype:
xmlrpc_value getFault() const;
You ordinarily call success first to determine that the RPC did in fact fail.
These are the facilities for generating the XML of an XML-RPC call and interpreting the XML of an XML-RPC response. They translate between XML and the classes described earlier in this chapter.
Xmlrpc-c has higher level facilities that make and take XML-RPC calls and responses and take care of this XML stuff for you; you don't need this section if you use the high level client and server facilities.
In these functions, we distinguish subtly between XML text and actual XML. Actual XML is a sequence of Unicode code points, whereas the inputs and outputs of these functions are just is just the text which is implied by such code points (as a C++ std::string); if Unicode is involved at all, it is at a lower layer.
This function generates XML text for an XML-RPC call.
Example:
xmlrpc_c::paramList myParamList;
myParamList.add(value_int(5));
myParamList.add(value_int(7));
string callXml;
xmlrpc_c::xml::generateCall("sample.add", myParamList, &callXml);
cout << "The XML is: " << callXml <<endl;
Prototype:
void generateCall(std::string methodName,
xmlrpc_c::paramList paramList,
std::string * callXmlP);
This function parses the XML text for an XML-RPC call.
Example:
string const callXml(
"<?xml version="1.0" encoding="UTF-8"?>\r\n"
"<methodCall>\r\n"
"<methodName>sample.add</methodName>\r\n"
"<params>\r\n"
"<param><value><i4>5</i4></value></param>\r\n"
"<param><value><i4>7</i4></value></param>\r\n"
"</params>\r\n"
"</methodCall>\r\n"
);
string methodName;
xmlrpc_c::paramList paramListP;
xmlrpc_c::parseCall(callXml, &methodName, ¶mList);
cout << "It is a call of method " << methodName
<< "with " << paramList.size() <<parameters
<< endl;
Prototype:
void parseCall(std::string callXml,
std::string * methodNameP,
xmlrpc_c::paramList * paramListP,);
This function was new in Xmlrpc-c 1.23 (June 2010).
This function generates XML text for an XML-RPC response.
Example:
xmlrpc_c::rpcOutcome outcome(xmlrpc_c::value_int(7));
string responseXml;
xmlrpc_c::xml::generateResponse(outcome, &responseXml);
cout << "The XML is: " << responseXml <<endl;
Prototype:
void generateResponse(xmlrpc_c::rpcOutcome outcome,
std::string * responseXmlP);
This function was new in Xmlrpc-c 1.23 (June 2010).
This function parses XML text for an XML-RPC response.
Example:
string const responseXml(
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n"
"<methodResponse>\r\n"
"<params>\r\n"
"<param><value><i4>12</i4></value></param>\r\n"
"</params>\r\n"
"</methodResponse>\r\n"
);
xmlrpc_c::value result;
xmlrpc_c::fault rpcFault;
xmlrpc_c::xml::parseResponse(responseXml, &succeeded, &result, &rpcFault);
if (succeeded)
cout << "The response is: "
<< static_cast<int>(value_int(result))
<< endl;
else
// Doesn't happen because our responseXml indicates successful RPC
cout << "The RPC failed! Reason: "
<< rpcFault.getDescription()
<< endl;
Prototype:
void parseResponse(std::string responseXml,
bool * succeededP
xmlrpc_c::value * resultP,
xmlrpc_c::fault * faultP);
If the XML text is a success response, the function returns *succeededP true and returns the RPC result as *resultP. It leaves *faultP undefined.
If the XML text is a failure response, the function returns *succeededP false and returns the XML-RPC fault information as *faultP. It leaves *resultP undefined.
If the XML text is not a valid XML-RPC response, the function may throw a girerr::error or return arbitrary results consistent with similar valid XML text.
Because of an implementation weakness, when the XML text is not valid, the function usually behaves as if it indicated some kind of RPC failure. Some day, that will be fixed, but you really can't expect much out of a program when you feed it invalid data anyway.
This is the same as parseResponse, except that it presumes the response being parsed indicates a successful RPC and throws an error if it doesn't.
Prototype:
void parseResponseSuccessful(std::string responseXml,
xmlrpc_c::value * resultP);
Base64 is a code for representing an arbitrary byte string as a text string. And that text string is simple enough (uses a basic enough character set) that it should be processable without corruption by any facility that processes text -- email, for example.
A Base64 code is a text string. It's not bits or bytes; it's not ASCII; it's just text. Of course, in a computer, text is encoded somehow into bits and the code for that is usually ASCII. But that's beyond the scope of Base64.
XML-RPC uses Base64 to represent byte strings, in its <base64> XML element type.
This function encodes raw bytes (represented by the C type for raw bytes: unsigned char) into Base64.
Example:
unsigned char const myarray[] = {1, 2, 3, 5, 7};
vector<unsigned char> const mybytes(&myarray[0],
&myarray[sizeof(myarray)]);
string const mybase64(xmlrpc_c::base64FromBytes(mybytes));
assert(mybase64 == "AQIDBQc=\n");
Prototype:
std::string base64FromBytes(std::vector<unsigned char> bytes,
xmlrpc::newlineCtl newlineCtl);
newlineCtl tells whether you want the base64 code to contain newline characters. In a base64 code, newline characters can be anywhere and don't affect what bytes the code represents. People put in newlines to make large base64 codes easy to handle -- for example, when displayed on a screen. But some processors of base64 codes don't properly handle newline characters, so you might not want them.
newlineCtl can be either xmlrpc::NEWLINE_YES or xmlrpc::NEWLINE_NO. If xmlrpc::NEWLINE_YES, you get newlines such that the code consists of 76 character lines, with the possible exception of the last line, and the code always ends in a newline. If xmlrpc::NEWLINE_NO, you get no newlines.
The default is xmlrpc::NEWLINE_YES.
This function was new in Xmlrpc-c 1.04 (November 2005).
This function decodes a Base64 text string into the C type for raw byts: unsigned char.
Example:
string const mybase64("AQIDBQc=\n");
assert(mybase64 == );
vector<unsigned char> const mybytes(
xmlrpc_c::bytesFromBase64(mybase64));
assert(mybytes.size() == 5);
assert(mybytes[0] = 1);
assert(mybytes[4] = 7);
This function was new in Xmlrpc-c 1.04 (November 2005).