initial load of upstream version 1.06.32
[xmlrpc-c] / src / cpp / xml.cpp
1 #include <string>
2
3 #include "xmlrpc-c/girerr.hpp"
4 using girerr::error;
5 using girerr::throwf;
6 #include "xmlrpc-c/base.h"
7 #include "xmlrpc-c/string_int.h"
8 #include "xmlrpc-c/base.hpp"
9 #include "env_wrap.hpp"
10
11 #include "xmlrpc-c/xml.hpp"
12
13 using namespace std;
14 using namespace xmlrpc_c;
15
16
17 namespace {
18
19 class cValueWrapper {
20 /*----------------------------------------------------------------------------
21    Use an object of this class to set up to remove a reference to an
22    xmlrpc_value object (a C object with manual reference management)
23    at then end of a scope -- even if the scope ends with a throw.
24 -----------------------------------------------------------------------------*/
25 public:
26     xmlrpc_value * valueP;
27     cValueWrapper(xmlrpc_value * valueP) : valueP(valueP) {}
28     ~cValueWrapper() { xmlrpc_DECREF(valueP); }
29 };
30
31 xmlrpc_value *
32 cArrayFromParamList(paramList const& paramList) {
33
34     env_wrap env;
35
36     xmlrpc_value * paramArrayP;
37
38     paramArrayP = xmlrpc_array_new(&env.env_c);
39     if (!env.env_c.fault_occurred) {
40         for (unsigned int i = 0;
41              i < paramList.size() && !env.env_c.fault_occurred;
42              ++i) {
43             cValueWrapper const param(paramList[i].cValue());
44
45             xmlrpc_array_append_item(&env.env_c, paramArrayP, param.valueP);
46         }
47     }
48     if (env.env_c.fault_occurred) {
49         xmlrpc_DECREF(paramArrayP);
50         throw(error(env.env_c.fault_string));
51     }
52     return paramArrayP;
53 }
54
55 } // namespace
56
57
58 namespace xmlrpc_c {
59 namespace xml {
60
61
62 void
63 generateCall(string    const& methodName,
64              paramList const& paramList,
65              string *  const  callXmlP) {
66 /*----------------------------------------------------------------------------
67    Generate the XML for an XML-RPC call, given a method name and parameter
68    list.
69 -----------------------------------------------------------------------------*/
70     class memblockWrapper {
71         xmlrpc_mem_block * const memblockP;
72     public:
73         memblockWrapper(xmlrpc_mem_block * const memblockP) :
74             memblockP(memblockP) {}
75
76         ~memblockWrapper() {
77             XMLRPC_MEMBLOCK_FREE(char, memblockP);
78         }
79     };
80
81     xmlrpc_mem_block * callXmlMP;
82     env_wrap env;
83
84     callXmlMP = XMLRPC_MEMBLOCK_NEW(char, &env.env_c, 0);
85     if (!env.env_c.fault_occurred) {
86         memblockWrapper callXmlHolder(callXmlMP);
87             // Makes callXmlMP get freed at end of scope
88
89         xmlrpc_value * const paramArrayP(cArrayFromParamList(paramList));
90
91         xmlrpc_serialize_call(&env.env_c, callXmlMP, methodName.c_str(),
92                               paramArrayP);
93         
94         *callXmlP = string(XMLRPC_MEMBLOCK_CONTENTS(char, callXmlMP),
95                            XMLRPC_MEMBLOCK_SIZE(char, callXmlMP));
96         
97         xmlrpc_DECREF(paramArrayP);
98     }
99     if (env.env_c.fault_occurred)
100         throw(error(env.env_c.fault_string));
101 }
102
103
104
105 void
106 parseResponse(string       const& responseXml,
107               rpcOutcome * const  outcomeP) {
108 /*----------------------------------------------------------------------------
109    Parse the XML for an XML-RPC response into an XML-RPC result value.
110 -----------------------------------------------------------------------------*/
111     env_wrap env;
112
113     xmlrpc_value * c_resultP;
114     int faultCode;
115     const char * faultString;
116
117     xmlrpc_parse_response2(&env.env_c, responseXml.c_str(), responseXml.size(),
118                            &c_resultP, &faultCode, &faultString);
119
120     if (env.env_c.fault_occurred)
121         throwf("Unable to find XML-RPC response in what server sent back.  %s",
122                env.env_c.fault_string);
123     else {
124         if (faultString) {
125             *outcomeP =
126                 rpcOutcome(fault(faultString,
127                                  static_cast<fault::code_t>(faultCode)));
128             xmlrpc_strfree(faultString);
129         } else {
130             XMLRPC_ASSERT_VALUE_OK(c_resultP);
131             *outcomeP = rpcOutcome(value(c_resultP));
132             xmlrpc_DECREF(c_resultP);
133         }
134     }
135 }
136
137
138
139 void
140 parseSuccessfulResponse(string  const& responseXml,
141                         value * const  resultP) {
142 /*----------------------------------------------------------------------------
143    Same as parseResponse(), but expects the response to indicate success;
144    throws an error if it doesn't.
145 -----------------------------------------------------------------------------*/
146     rpcOutcome outcome;
147
148     parseResponse(responseXml, &outcome);
149
150     if (!outcome.succeeded())
151         throwf("RPC response indicates it failed.  %s",
152                outcome.getFault().getDescription().c_str());
153
154     *resultP = outcome.getResult();
155 }
156
157
158
159 void
160 trace(string const& label,
161       string const& xml) {
162     
163     xmlrpc_traceXml(label.c_str(), xml.c_str(), xml.size());
164
165 }
166
167
168 }} // namespace