File size: 4,442 Bytes
fd49381 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 |
#include <string>
#include <cstring>
#include "xmlrpc-c/girerr.hpp"
using girerr::error;
#include "xmlrpc-c/env_wrap.hpp"
#include "xmlrpc-c/base.h"
#include "xmlrpc-c/base.hpp"
#include "xmlrpc-c/client.hpp"
#include <xmlrpc-c/client.hpp>
#include "xmlrpc-c/client_simple.hpp"
using namespace std;
using namespace xmlrpc_c;
namespace xmlrpc_c {
namespace {
class cValueWrapper {
/*----------------------------------------------------------------------------
Use an object of this class to set up to remove a reference to an
xmlrpc_value object (a C object with manual reference management)
at then end of a scope -- even if the scope ends with a throw.
-----------------------------------------------------------------------------*/
xmlrpc_value * valueP;
public:
cValueWrapper(xmlrpc_value * valueP) : valueP(valueP) {}
~cValueWrapper() { xmlrpc_DECREF(valueP); }
};
} // namespace
clientSimple::clientSimple() {
clientXmlTransportPtr const transportP(clientXmlTransport_http::create());
this->clientP = clientPtr(new client_xml(transportP));
}
void
clientSimple::call(string const serverUrl,
string const methodName,
value * const resultP) {
carriageParm_http0 carriageParm(serverUrl);
rpcPtr rpcPtr(methodName, paramList());
rpcPtr->call(this->clientP.get(), &carriageParm);
*resultP = rpcPtr->getResult();
}
namespace {
void
makeParamArray(string const format,
xmlrpc_value ** const paramArrayPP,
va_list args) {
env_wrap env;
/* The format is a sequence of parameter specifications, such as
"iiii" for 4 integer parameters. We add parentheses to make it
an array of those parameters: "(iiii)".
*/
string const arrayFormat("(" + string(format) + ")");
const char * tail;
xmlrpc_build_value_va(&env.env_c, arrayFormat.c_str(),
args, paramArrayPP, &tail);
if (env.env_c.fault_occurred)
throw(error(env.env_c.fault_string));
if (strlen(tail) != 0) {
/* xmlrpc_build_value_va() parses off a single value specification
from its format string, and 'tail' points to whatever is after
it. Our format string should have been a single array value,
meaning tail is end-of-string. If it's not, that means
something closed our array early.
*/
xmlrpc_DECREF(*paramArrayPP);
throw(error("format string is invalid. It apparently has a "
"stray right parenthesis"));
}
}
} // namespace
void
clientSimple::call(string const serverUrl,
string const methodName,
string const format,
value * const resultP,
...) {
carriageParm_http0 carriageParm(serverUrl);
env_wrap env;
xmlrpc_value * paramArrayP;
va_list args;
va_start(args, resultP);
makeParamArray(format, ¶mArrayP, args);
va_end(args);
if (env.env_c.fault_occurred)
throw(error(env.env_c.fault_string));
else {
cValueWrapper paramArrayWrapper(paramArrayP); // ensure destruction
unsigned int const paramCount(
xmlrpc_array_size(&env.env_c, paramArrayP));
if (env.env_c.fault_occurred)
throw(error(env.env_c.fault_string));
paramList paramList;
for (unsigned int i = 0; i < paramCount; ++i) {
xmlrpc_value * paramP;
xmlrpc_array_read_item(&env.env_c, paramArrayP, i, ¶mP);
if (env.env_c.fault_occurred)
throw(error(env.env_c.fault_string));
else {
cValueWrapper paramWrapper(paramP); // ensure destruction
paramList.add(value(paramP));
}
}
rpcPtr rpcPtr(methodName, paramList);
rpcPtr->call(this->clientP.get(), &carriageParm);
*resultP = rpcPtr->getResult();
}
}
void
clientSimple::call(string const serverUrl,
string const methodName,
paramList const& paramList,
value * const resultP) {
carriageParm_http0 carriageParm(serverUrl);
rpcPtr rpcPtr(methodName, paramList);
rpcPtr->call(this->clientP.get(), &carriageParm);
*resultP = rpcPtr->getResult();
}
} // namespace
|