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