--- /dev/null
+#include <string>
+
+#include "xmlrpc-c/girerr.hpp"
+using girerr::error;
+using girerr::throwf;
+#include "xmlrpc-c/base.h"
+#include "xmlrpc-c/string_int.h"
+#include "xmlrpc-c/base.hpp"
+#include "env_wrap.hpp"
+
+#include "xmlrpc-c/xml.hpp"
+
+using namespace std;
+using 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.
+-----------------------------------------------------------------------------*/
+public:
+ xmlrpc_value * valueP;
+ cValueWrapper(xmlrpc_value * valueP) : valueP(valueP) {}
+ ~cValueWrapper() { xmlrpc_DECREF(valueP); }
+};
+
+xmlrpc_value *
+cArrayFromParamList(paramList const& paramList) {
+
+ env_wrap env;
+
+ xmlrpc_value * paramArrayP;
+
+ paramArrayP = xmlrpc_array_new(&env.env_c);
+ if (!env.env_c.fault_occurred) {
+ for (unsigned int i = 0;
+ i < paramList.size() && !env.env_c.fault_occurred;
+ ++i) {
+ cValueWrapper const param(paramList[i].cValue());
+
+ xmlrpc_array_append_item(&env.env_c, paramArrayP, param.valueP);
+ }
+ }
+ if (env.env_c.fault_occurred) {
+ xmlrpc_DECREF(paramArrayP);
+ throw(error(env.env_c.fault_string));
+ }
+ return paramArrayP;
+}
+
+} // namespace
+
+
+namespace xmlrpc_c {
+namespace xml {
+
+
+void
+generateCall(string const& methodName,
+ paramList const& paramList,
+ string * const callXmlP) {
+/*----------------------------------------------------------------------------
+ Generate the XML for an XML-RPC call, given a method name and parameter
+ list.
+-----------------------------------------------------------------------------*/
+ class memblockWrapper {
+ xmlrpc_mem_block * const memblockP;
+ public:
+ memblockWrapper(xmlrpc_mem_block * const memblockP) :
+ memblockP(memblockP) {}
+
+ ~memblockWrapper() {
+ XMLRPC_MEMBLOCK_FREE(char, memblockP);
+ }
+ };
+
+ xmlrpc_mem_block * callXmlMP;
+ env_wrap env;
+
+ callXmlMP = XMLRPC_MEMBLOCK_NEW(char, &env.env_c, 0);
+ if (!env.env_c.fault_occurred) {
+ memblockWrapper callXmlHolder(callXmlMP);
+ // Makes callXmlMP get freed at end of scope
+
+ xmlrpc_value * const paramArrayP(cArrayFromParamList(paramList));
+
+ xmlrpc_serialize_call(&env.env_c, callXmlMP, methodName.c_str(),
+ paramArrayP);
+
+ *callXmlP = string(XMLRPC_MEMBLOCK_CONTENTS(char, callXmlMP),
+ XMLRPC_MEMBLOCK_SIZE(char, callXmlMP));
+
+ xmlrpc_DECREF(paramArrayP);
+ }
+ if (env.env_c.fault_occurred)
+ throw(error(env.env_c.fault_string));
+}
+
+
+
+void
+parseResponse(string const& responseXml,
+ rpcOutcome * const outcomeP) {
+/*----------------------------------------------------------------------------
+ Parse the XML for an XML-RPC response into an XML-RPC result value.
+-----------------------------------------------------------------------------*/
+ env_wrap env;
+
+ xmlrpc_value * c_resultP;
+ int faultCode;
+ const char * faultString;
+
+ xmlrpc_parse_response2(&env.env_c, responseXml.c_str(), responseXml.size(),
+ &c_resultP, &faultCode, &faultString);
+
+ if (env.env_c.fault_occurred)
+ throwf("Unable to find XML-RPC response in what server sent back. %s",
+ env.env_c.fault_string);
+ else {
+ if (faultString) {
+ *outcomeP =
+ rpcOutcome(fault(faultString,
+ static_cast<fault::code_t>(faultCode)));
+ xmlrpc_strfree(faultString);
+ } else {
+ XMLRPC_ASSERT_VALUE_OK(c_resultP);
+ *outcomeP = rpcOutcome(value(c_resultP));
+ xmlrpc_DECREF(c_resultP);
+ }
+ }
+}
+
+
+
+void
+parseSuccessfulResponse(string const& responseXml,
+ value * const resultP) {
+/*----------------------------------------------------------------------------
+ Same as parseResponse(), but expects the response to indicate success;
+ throws an error if it doesn't.
+-----------------------------------------------------------------------------*/
+ rpcOutcome outcome;
+
+ parseResponse(responseXml, &outcome);
+
+ if (!outcome.succeeded())
+ throwf("RPC response indicates it failed. %s",
+ outcome.getFault().getDescription().c_str());
+
+ *resultP = outcome.getResult();
+}
+
+
+
+void
+trace(string const& label,
+ string const& xml) {
+
+ xmlrpc_traceXml(label.c_str(), xml.c_str(), xml.size());
+
+}
+
+
+}} // namespace