mirror of
https://github.com/ultimatepp/ultimatepp.git
synced 2026-07-11 22:03:01 -06:00
New XmlRpc package
git-svn-id: svn://ultimatepp.org/upp/trunk@1821 f0d560ea-af0d-0410-9eb7-867de7ffcac7
This commit is contained in:
parent
643bc28dd6
commit
6dbea1df2e
10 changed files with 680 additions and 0 deletions
43
uppsrc/XmlRpc/Client.cpp
Normal file
43
uppsrc/XmlRpc/Client.cpp
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
#include "XmlRpc.h"
|
||||
|
||||
#define LLOG(x) LOG(x)
|
||||
|
||||
Value XmlRpcCall::Execute()
|
||||
{
|
||||
String request = XmlHeader();
|
||||
request << XmlTag("methodCall")(XmlTag("methodName")(method) + FormatXmlRpcParams(data.out));
|
||||
String response = server.Post(request).TimeoutMsecs(timeout).ExecuteRedirect();
|
||||
LLOG("response: " << response);
|
||||
if(IsNull(response)) {
|
||||
return ErrorValue("Http request failed: " + server.GetError());
|
||||
}
|
||||
XmlParser p(response);
|
||||
try {
|
||||
p.ReadPI();
|
||||
p.PassTag("methodResponse");
|
||||
if(p.Tag("fault")) {
|
||||
Value m = ParseXmlRpcValue(p);
|
||||
if(IsValueMap(m)) {
|
||||
ValueMap mm = m;
|
||||
String s;
|
||||
s << "Failed '" << mm["faultString"] << "' (" << mm["faultCode"] << ')';
|
||||
error = s;
|
||||
LLOG(s);
|
||||
return ErrorValue(s);
|
||||
}
|
||||
}
|
||||
else {
|
||||
data.in = ParseXmlRpcParams(p);
|
||||
data.ii = 0;
|
||||
p.PassEnd();
|
||||
}
|
||||
}
|
||||
catch(XmlError e) {
|
||||
String s;
|
||||
s << "XmlError " << e << ": " << p.GetPtr();
|
||||
LOG(s);
|
||||
error = s;
|
||||
return ErrorValue(s);
|
||||
}
|
||||
return data.in.GetCount() ? data.in[0] : Null;
|
||||
}
|
||||
107
uppsrc/XmlRpc/Server.cpp
Normal file
107
uppsrc/XmlRpc/Server.cpp
Normal file
|
|
@ -0,0 +1,107 @@
|
|||
#include "XmlRpc.h"
|
||||
#include "XmlRpc.h"
|
||||
|
||||
#define LLOG(x) // LOG(x)
|
||||
|
||||
VectorMap< String, void (*)(XmlRpcData&) >& XmlRpcMap(const char *group)
|
||||
{
|
||||
static VectorMap<String, VectorMap< String, void (*)(XmlRpcData&) > > mm;
|
||||
return mm.GetAdd(group);
|
||||
}
|
||||
|
||||
void Register(const char *name, void (*method)(XmlRpcData&), const char *group)
|
||||
{
|
||||
XmlRpcMap(group).Add(name, method);
|
||||
}
|
||||
|
||||
String XmlRpcExecute(const String& request, const char *group)
|
||||
{
|
||||
VectorMap< String, void (*)(XmlRpcData&) >& xmlrpcmap = XmlRpcMap(group);
|
||||
XmlParser p(request);
|
||||
XmlRpcData data;
|
||||
String methodname;
|
||||
try {
|
||||
String r = XmlHeader();
|
||||
r << "<methodResponse>\r\n";
|
||||
p.ReadPI();
|
||||
p.PassTag("methodCall");
|
||||
p.PassTag("methodName");
|
||||
methodname = p.ReadText();
|
||||
LLOG("method name: " << methodname);
|
||||
p.PassEnd();
|
||||
data.in = ParseXmlRpcParams(p);
|
||||
int q = xmlrpcmap.Find(methodname);
|
||||
if(q < 0)
|
||||
return FormatXmlRpcError(4, methodname + " method is unknown");
|
||||
else {
|
||||
(*xmlrpcmap[q])(data);
|
||||
if(IsValueArray(data.out)) {
|
||||
if(IsError(data.out[0])) {
|
||||
LLOG("ProcessingError");
|
||||
return FormatXmlRpcError(3, methodname + " Processing error: " + GetErrorText(data.out[0]));
|
||||
}
|
||||
r << FormatXmlRpcParams(data.out);
|
||||
}
|
||||
r << "\r\n</methodResponse>\r\n";
|
||||
}
|
||||
p.PassEnd();
|
||||
return r;
|
||||
}
|
||||
catch(XmlError e) {
|
||||
LLOG("XmlError " << e << ": " << p.GetPtr());
|
||||
return FormatXmlRpcError(1, methodname + " XML Error: " + e);
|
||||
}
|
||||
catch(ValueTypeMismatch) {
|
||||
LLOG("ValueTypeMismatch at parameter " << data.ii);
|
||||
return FormatXmlRpcError(2, methodname + " Value type mismatch at parameter " + AsString(data.ii));
|
||||
}
|
||||
return Null;
|
||||
}
|
||||
|
||||
int CharFilterNoCr(int c)
|
||||
{
|
||||
return c == '\r' ? 0 : c;
|
||||
}
|
||||
|
||||
String ReadLine(Socket& s)
|
||||
{
|
||||
return Filter(s.ReadUntil('\n'), CharFilterNoCr);
|
||||
}
|
||||
|
||||
bool XmlRpcServer(int port, const char *group)
|
||||
{
|
||||
Socket rpc;
|
||||
if(!ServerSocket(rpc, 1234, true, 5))
|
||||
return false;
|
||||
for(;;) {
|
||||
Socket http;
|
||||
if(rpc.Accept(http)) {
|
||||
LLOG("=== Accepted connection ===================================================");
|
||||
String request = ReadLine(http);
|
||||
if(http.IsError()) continue;
|
||||
VectorMap<String, String> hdr;
|
||||
for(;;) {
|
||||
String s = ReadLine(http);
|
||||
if(s.IsEmpty()) break;
|
||||
LLOG(s);
|
||||
int q = s.Find(':');
|
||||
if(q >= 0)
|
||||
hdr.GetAdd(s.Mid(0, q)) = TrimLeft(s.Mid(q + 1));
|
||||
}
|
||||
if(http.IsError()) continue;
|
||||
String r = XmlRpcExecute(http.ReadCount(atoi(hdr.Get("Content-Length", "")), 90000), group);
|
||||
LLOG("--------- Server response:\n" << r << "=============");
|
||||
String response;
|
||||
response <<
|
||||
"HTTP/1.1 200 OK\r\n"
|
||||
"Date: Mon, 23 May 2005 22:38:34 GMT\r\n"
|
||||
"Server: U++\r\n"
|
||||
"Last-Modified: Wed, 08 Jan 2003 23:11:55 GMT\r\n"
|
||||
"Accept-Ranges: bytes\r\n"
|
||||
"Content-Length: " << r.GetCount() << "\r\n"
|
||||
"Connection: close\r\n"
|
||||
"Content-Type: application/soap+xml; charset=utf-8\r\n\r\n" << r;
|
||||
http.Write(response);
|
||||
}
|
||||
}
|
||||
}
|
||||
110
uppsrc/XmlRpc/Value.cpp
Normal file
110
uppsrc/XmlRpc/Value.cpp
Normal file
|
|
@ -0,0 +1,110 @@
|
|||
#include "XmlRpc.h"
|
||||
|
||||
void ValueCheck(bool b)
|
||||
{
|
||||
if(!b)
|
||||
throw ValueTypeMismatch();
|
||||
}
|
||||
|
||||
void ValueGet(int& n, const Value& v)
|
||||
{
|
||||
ValueCheck(IsNumber(v));
|
||||
n = v;
|
||||
}
|
||||
|
||||
void ValueGet(String& s, const Value& v)
|
||||
{
|
||||
ValueCheck(IsString(s));
|
||||
s = v;
|
||||
}
|
||||
|
||||
void ValueGet(double& x, const Value& v)
|
||||
{
|
||||
ValueCheck(IsNumber(v));
|
||||
x = v;
|
||||
}
|
||||
|
||||
void ValueGet(bool& x, const Value& v)
|
||||
{
|
||||
ValueCheck(IsNumber(x));
|
||||
x = v;
|
||||
}
|
||||
|
||||
void ValueGet(Date& x, const Value& v)
|
||||
{
|
||||
ValueCheck(IsDateTime(v));
|
||||
x = v;
|
||||
}
|
||||
|
||||
void ValueGet(Time& x, const Value& v)
|
||||
{
|
||||
ValueCheck(IsDateTime(v));
|
||||
x = v;
|
||||
}
|
||||
|
||||
void ValueGet(Value& t, const Value& v)
|
||||
{
|
||||
t = v;
|
||||
}
|
||||
|
||||
void ValueGet(ValueArray& va, const Value& v)
|
||||
{
|
||||
ValueCheck(IsValueArray(v));
|
||||
va = v;
|
||||
}
|
||||
|
||||
void ValueGet(ValueMap& vm, const Value& v)
|
||||
{
|
||||
ValueCheck(IsValueMap(v));
|
||||
vm = v;
|
||||
}
|
||||
|
||||
void ValuePut(Value& v, int n)
|
||||
{
|
||||
v = n;
|
||||
}
|
||||
|
||||
void ValuePut(Value& v, const String& s)
|
||||
{
|
||||
v = s;
|
||||
}
|
||||
|
||||
void ValuePut(Value& v, const char *s)
|
||||
{
|
||||
ValuePut(v, String(s));
|
||||
}
|
||||
|
||||
void ValuePut(Value& v, double x)
|
||||
{
|
||||
v = x;
|
||||
}
|
||||
|
||||
void ValuePut(Value& v, bool x)
|
||||
{
|
||||
v = x;
|
||||
}
|
||||
|
||||
void ValuePut(Value& v, const Date& x)
|
||||
{
|
||||
v = x;
|
||||
}
|
||||
|
||||
void ValuePut(Value& v, const Time& x)
|
||||
{
|
||||
v = x;
|
||||
}
|
||||
|
||||
void ValuePut(Value& v, const Value& t)
|
||||
{
|
||||
v = t;
|
||||
}
|
||||
|
||||
void ValuePut(Value& v, const ValueArray& va)
|
||||
{
|
||||
v = va;
|
||||
}
|
||||
|
||||
void ValuePut(Value& v, const ValueMap& vm)
|
||||
{
|
||||
v = vm;
|
||||
}
|
||||
170
uppsrc/XmlRpc/Xml.cpp
Normal file
170
uppsrc/XmlRpc/Xml.cpp
Normal file
|
|
@ -0,0 +1,170 @@
|
|||
#include "XmlRpc.h"
|
||||
|
||||
Value ParseXmlRpcValue(XmlParser& p)
|
||||
{
|
||||
Value r;
|
||||
p.PassTag("value");
|
||||
if(p.Tag("int") || p.Tag("i4")) {
|
||||
String s = p.ReadText();
|
||||
CParser p(s);
|
||||
if(!p.IsInt())
|
||||
throw XmlError("integer expected");
|
||||
r = p.ReadInt();
|
||||
}
|
||||
else
|
||||
if(p.Tag("boolean")) {
|
||||
int n = StrInt(p.ReadText());
|
||||
if(n != 0 && n != 1)
|
||||
throw XmlError("boolean expected");
|
||||
r = (bool)n;
|
||||
}
|
||||
else
|
||||
if(p.Tag("double")) {
|
||||
String s = p.ReadText();
|
||||
CParser p(s);
|
||||
if(!p.IsDouble())
|
||||
throw XmlError("double expected");
|
||||
r = p.ReadDouble();
|
||||
}
|
||||
else
|
||||
if(p.Tag("string") || p.Tag("base64"))
|
||||
r = p.ReadText();
|
||||
else
|
||||
if(p.Tag("dateTime.iso8601")) {
|
||||
String s = TrimBoth(p.ReadText());
|
||||
// 19980717T14:08:55
|
||||
// 01234567890123456
|
||||
if(s.GetCount() != 17 || s[8] != 'T' || s[11] != ':' || s[14] != ':')
|
||||
throw XmlError("invalid dateTime format");
|
||||
Time tm;
|
||||
tm.year = atoi(s.Mid(0, 4));
|
||||
tm.month = atoi(s.Mid(4, 2));
|
||||
tm.day = atoi(s.Mid(6, 2));
|
||||
tm.hour = atoi(s.Mid(9, 2));
|
||||
tm.minute = atoi(s.Mid(12, 2));
|
||||
tm.second = atoi(s.Mid(15, 2));
|
||||
r = tm;
|
||||
}
|
||||
else
|
||||
if(p.Tag("array")) {
|
||||
ValueArray va;
|
||||
p.PassTag("data");
|
||||
while(!p.End())
|
||||
va.Add(ParseXmlRpcValue(p));
|
||||
r = va;
|
||||
}
|
||||
else
|
||||
if(p.Tag("struct")) {
|
||||
ValueMap vm;
|
||||
while(p.Tag("member")) {
|
||||
p.PassTag("name");
|
||||
String name = p.ReadText();
|
||||
p.PassEnd();
|
||||
vm.Add((Value)name, ParseXmlRpcValue(p));
|
||||
p.PassEnd();
|
||||
}
|
||||
r = vm;
|
||||
}
|
||||
else
|
||||
throw XmlError("unknown value type");
|
||||
p.PassEnd();
|
||||
p.PassEnd();
|
||||
return r;
|
||||
}
|
||||
|
||||
Value ParseXmlRpcParam(XmlParser& p)
|
||||
{
|
||||
p.PassTag("param");
|
||||
Value v = ParseXmlRpcValue(p);
|
||||
p.PassEnd();
|
||||
return v;
|
||||
}
|
||||
|
||||
ValueArray ParseXmlRpcParams(XmlParser& p)
|
||||
{
|
||||
ValueArray va;
|
||||
if(p.Tag("params"))
|
||||
while(!p.End())
|
||||
va.Add(ParseXmlRpcParam(p));
|
||||
return va;
|
||||
}
|
||||
|
||||
String FormatXmlRpcValue(const Value& v)
|
||||
{
|
||||
String r;
|
||||
if(v.GetType() == INT_V)
|
||||
r = XmlTag("int")(Format("%d", (int)v));
|
||||
else
|
||||
if(v.GetType() == BOOL_V)
|
||||
r = XmlTag("boolean")(AsString(v));
|
||||
else
|
||||
if(IsNumber(v))
|
||||
r = XmlTag("double")(Format("%d", (double)v));
|
||||
else
|
||||
if(IsDateTime(v)) {
|
||||
Time t = v;
|
||||
r = XmlTag("dateTime.iso8601")
|
||||
(Format("%04.4d%02.2d%02.2d`T%02.2d`:%02.2d`:%02.2d",
|
||||
t.year, t.month, t.day, t.hour, t.minute, t.second));
|
||||
}
|
||||
else
|
||||
if(v.GetType() == VALUEMAP_V) {
|
||||
r = "<struct>";
|
||||
ValueMap vm = v;
|
||||
const Index<Value>& k = vm.GetKeys();
|
||||
ValueArray va = vm.GetValues();
|
||||
for(int i = 0; i < k.GetCount(); i++)
|
||||
r << XmlTag("member")(XmlTag("name")(k[i]) + FormatXmlRpcValue(va[i]));
|
||||
r << "</struct>";
|
||||
}
|
||||
else
|
||||
if( v.GetType() == VALUEARRAY_V) {
|
||||
r = "<array><data>";
|
||||
ValueArray va = v;
|
||||
for(int i = 0; i < va.GetCount(); i++)
|
||||
r << FormatXmlRpcValue(va[i]);
|
||||
r << "</data></array>";
|
||||
}
|
||||
else
|
||||
r = XmlTag("string")(AsString(v));
|
||||
return XmlTag("value")(r);
|
||||
}
|
||||
|
||||
String FormatXmlRpcParam(const Value& param)
|
||||
{
|
||||
return XmlTag("param")(FormatXmlRpcValue(param));
|
||||
}
|
||||
|
||||
String FormatXmlRpcParams(const ValueArray& params)
|
||||
{
|
||||
String r;
|
||||
r = "<params>";
|
||||
for(int i = 0; i < params.GetCount(); i++)
|
||||
r << FormatXmlRpcParam(params[i]);
|
||||
r << "</params>";
|
||||
return r;
|
||||
}
|
||||
|
||||
struct XmlRpcErrorStruct {
|
||||
int code;
|
||||
String text;
|
||||
|
||||
void Map(ValueMapper& m) {
|
||||
m("faultCode", code)("faultString", text);
|
||||
}
|
||||
};
|
||||
|
||||
String FormatXmlRpcError(int code, const char *text)
|
||||
{
|
||||
XmlRpcErrorStruct e;
|
||||
e.code = code;
|
||||
e.text = text;
|
||||
XmlRpcData d;
|
||||
d << e;
|
||||
String r;
|
||||
r << XmlHeader()
|
||||
<< "<methodResponse><fault>\r\n"
|
||||
<< FormatXmlRpcValue(d.out[0])
|
||||
<< "</fault></methodResponse>\r\n";
|
||||
return r;
|
||||
}
|
||||
169
uppsrc/XmlRpc/XmlRpc.h
Normal file
169
uppsrc/XmlRpc/XmlRpc.h
Normal file
|
|
@ -0,0 +1,169 @@
|
|||
#ifndef _XmlRpc_XmlRpc_h
|
||||
#define _XmlRpc_XmlRpc_h
|
||||
|
||||
#include <Web/Web.h>
|
||||
|
||||
using namespace Upp;
|
||||
|
||||
struct ValueTypeMismatch {};
|
||||
|
||||
void ValueCheck(bool b);
|
||||
|
||||
void ValueGet(int& n, const Value& v);
|
||||
void ValueGet(bool& b, const Value& v);
|
||||
void ValueGet(String& s, const Value& v);
|
||||
void ValueGet(double& x, const Value& v);
|
||||
void ValueGet(Date& x, const Value& v);
|
||||
void ValueGet(Time& x, const Value& v);
|
||||
void ValueGet(Value& t, const Value& v);
|
||||
void ValueGet(ValueArray& va, const Value& v);
|
||||
void ValueGet(ValueMap& vm, const Value& v);
|
||||
|
||||
template <class T>
|
||||
void ValueGet(Array<T>& x, Value v) {
|
||||
ValueCheck(IsValueArray(v));
|
||||
ValueArray va = v;
|
||||
x.SetCount(va.GetCount());
|
||||
for(int i = 0; i < va.GetCount(); i++)
|
||||
ValueGet(x[i], va[i]);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void ValueGet(Vector<T>& x, Value v) {
|
||||
ValueCheck(IsValueArray(v));
|
||||
ValueArray va = v;
|
||||
x.SetCount(va.GetCount());
|
||||
for(int i = 0; i < va.GetCount(); i++)
|
||||
ValueGet(x[i], va[i]);
|
||||
}
|
||||
|
||||
void ValuePut(Value& v, int n);
|
||||
void ValuePut(Value& v, const String& s);
|
||||
void ValuePut(Value& v, const char *s);
|
||||
void ValuePut(Value& v, double x);
|
||||
void ValuePut(Value& v, bool x);
|
||||
void ValuePut(Value& v, const Date& x);
|
||||
void ValuePut(Value& v, const Time& x);
|
||||
void ValuePut(Value& v, const Value& t);
|
||||
void ValuePut(Value& v, const ValueArray& va);
|
||||
void ValuePut(Value& v, const ValueMap& vm);
|
||||
|
||||
struct ValueMapper {
|
||||
ValueMap map;
|
||||
bool get;
|
||||
|
||||
template <class T>
|
||||
ValueMapper& operator()(const char *name, T& x) {
|
||||
if(get)
|
||||
ValueGet(x, map[name]);
|
||||
else {
|
||||
Value v;
|
||||
ValuePut(v, x);
|
||||
map.Add(name, v);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
void ValueGet(T& x, const Value& v) {
|
||||
ValueMapper m;
|
||||
m.map = v;
|
||||
m.get = true;
|
||||
x.Map(m);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void ValuePut(Value& v, const T& x) {
|
||||
ValueMapper m;
|
||||
m.get = false;
|
||||
const_cast<T&>(x).Map(m);
|
||||
v = m.map;
|
||||
}
|
||||
|
||||
Value ParseXmlRpcValue(XmlParser& p);
|
||||
Value ParseXmlRpcParam(XmlParser& p);
|
||||
ValueArray ParseXmlRpcParams(XmlParser& p);
|
||||
|
||||
struct XmlRpcData {
|
||||
ValueArray in;
|
||||
int ii;
|
||||
ValueArray out;
|
||||
|
||||
Value Get() { if(ii >= in.GetCount()) throw ValueTypeMismatch(); return in[ii++]; }
|
||||
|
||||
template <class T>
|
||||
XmlRpcData& operator>>(T& x) { ValueGet(x, Get()); return *this; }
|
||||
|
||||
template <class T>
|
||||
XmlRpcData& operator<<(const T& x) { Value v; ValuePut(v, x); out.Add(v); return *this; }
|
||||
|
||||
void Reset() { in.Clear(); out.Clear(); ii = 0; }
|
||||
|
||||
XmlRpcData() { ii = 0; }
|
||||
};
|
||||
|
||||
String FormatXmlRpcValue(const Value& value);
|
||||
String FormatXmlRpcParam(const Value& param);
|
||||
String FormatXmlRpcParams(const ValueArray& params);
|
||||
|
||||
String FormatXmlRpcError(int code, const char *text);
|
||||
|
||||
void Register(const char *name, void (*method)(XmlRpcData&), const char *group = NULL);
|
||||
bool XmlRpcServer(int port = 80, const char *group = NULL);
|
||||
|
||||
#define XMLRPC_METHOD(x) \
|
||||
void xmlrpc##x(XmlRpcData& rpc); \
|
||||
INITBLOCK { Register(#x, xmlrpc##x); } \
|
||||
void xmlrpc##x(XmlRpcData& rpc)
|
||||
|
||||
#define XMLRPC_GMETHOD(x, group) \
|
||||
void xmlrpc##x(XmlRpcData& rpc); \
|
||||
INITBLOCK { Register(#x, xmlrpc##x, group); } \
|
||||
void xmlrpc##x(XmlRpcData& rpc)
|
||||
|
||||
class XmlRpcCall {
|
||||
HttpClient server;
|
||||
XmlRpcData data;
|
||||
String method;
|
||||
String error;
|
||||
int timeout;
|
||||
|
||||
public:
|
||||
XmlRpcCall& Method(const char *name) { method = name; data.Reset(); error.Clear(); return *this; }
|
||||
|
||||
template <class T>
|
||||
XmlRpcCall& operator<<(const T& x) { data << x; return *this; }
|
||||
|
||||
Value Execute();
|
||||
|
||||
template <class T>
|
||||
bool operator>>(T& x) { if(IsError(Execute())) return false; try { data >> x; } catch(ValueTypeMismatch) { return false; } return true; }
|
||||
|
||||
XmlRpcCall& operator()(const char *method) { Method(method); return *this; }
|
||||
|
||||
#define E__Templ(I) class COMBINE(T, I)
|
||||
#define E__Decl(I) const COMBINE(T, I)& COMBINE(p, I)
|
||||
#define E__Param(I) *this << COMBINE(p, I)
|
||||
#define E__Body(I) \
|
||||
template <__List##I(E__Templ)> \
|
||||
XmlRpcCall& operator()(const char *method, __List##I(E__Decl)) { \
|
||||
Method(method); \
|
||||
__List##I(E__Param); \
|
||||
return *this; \
|
||||
}
|
||||
|
||||
__Expand20(E__Body)
|
||||
|
||||
#undef E__Templ
|
||||
#undef E__Decl
|
||||
#undef E__Param
|
||||
#undef E__Body
|
||||
|
||||
String GetError() const { return error; }
|
||||
XmlRpcCall& TimeOut(int msec) { timeout = msec; }
|
||||
|
||||
XmlRpcCall(const char *url) : server(url) { server.ContentType("text/xml"); timeout = 30000; }
|
||||
};
|
||||
|
||||
#endif
|
||||
14
uppsrc/XmlRpc/XmlRpc.upp
Normal file
14
uppsrc/XmlRpc/XmlRpc.upp
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
uses
|
||||
Web;
|
||||
|
||||
file
|
||||
XmlRpc.h,
|
||||
Value.cpp,
|
||||
Xml.cpp,
|
||||
Client.cpp,
|
||||
Server.cpp,
|
||||
xrs readonly separator,
|
||||
xrs_header.h,
|
||||
xrs_source.h,
|
||||
xrs.h;
|
||||
|
||||
4
uppsrc/XmlRpc/init
Normal file
4
uppsrc/XmlRpc/init
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
#ifndef _XmlRpc_icpp_init_stub
|
||||
#define _XmlRpc_icpp_init_stub
|
||||
#include "Web/init"
|
||||
#endif
|
||||
9
uppsrc/XmlRpc/xrs.h
Normal file
9
uppsrc/XmlRpc/xrs.h
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
#ifndef _XmlRpc_xrs_h_
|
||||
#define _XmlRpc_xrs_h_
|
||||
|
||||
#define XRS_KEEP
|
||||
#include <XmlRpc/xrs_header.h>
|
||||
#undef XRS_KEEP
|
||||
#include <XmlRpc/xrs_source.h>
|
||||
|
||||
#endif
|
||||
27
uppsrc/XmlRpc/xrs_header.h
Normal file
27
uppsrc/XmlRpc/xrs_header.h
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
#include "XmlRpc.h"
|
||||
|
||||
#define STRUCT(id) struct id {
|
||||
#define VAR(type, id) type id;
|
||||
#define INT(id) int id;
|
||||
#define BOOL(id) bool id;
|
||||
#define STRING(id) String id;
|
||||
#define DOUBLE(id) double id;
|
||||
#define DATE(id) Date id;
|
||||
#define TIME(id) Time id;
|
||||
#define END_STRUCT void Map(ValueMapper& m); };
|
||||
|
||||
#include XRSFILE
|
||||
|
||||
#undef STRUCT
|
||||
#undef VAR
|
||||
#undef INT
|
||||
#undef BOOL
|
||||
#undef STRING
|
||||
#undef DOUBLE
|
||||
#undef DATE
|
||||
#undef TIME
|
||||
#undef END_STRUCT
|
||||
|
||||
#ifndef XRS_KEEP
|
||||
#undef XRSFILE
|
||||
#endif
|
||||
27
uppsrc/XmlRpc/xrs_source.h
Normal file
27
uppsrc/XmlRpc/xrs_source.h
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
#include "XmlRpc.h"
|
||||
|
||||
#define STRUCT(id) void id::Map(ValueMapper& m) {
|
||||
#define VAR(type, id) m(#id, id);
|
||||
#define INT(id) m(#id, id);
|
||||
#define BOOL(id) m(#id, id);
|
||||
#define STRING(id) m(#id, id);
|
||||
#define DOUBLE(id) m(#id, id);
|
||||
#define DATE(id) m(#id, id);
|
||||
#define TIME(id) m(#id, id);
|
||||
#define END_STRUCT };
|
||||
|
||||
#include XRSFILE
|
||||
|
||||
#undef STRUCT
|
||||
#undef VAR
|
||||
#undef INT
|
||||
#undef BOOL
|
||||
#undef STRING
|
||||
#undef DOUBLE
|
||||
#undef DATE
|
||||
#undef TIME
|
||||
#undef END_STRUCT
|
||||
|
||||
#ifndef XRS_KEEP
|
||||
#undef XRSFILE
|
||||
#endif
|
||||
Loading…
Add table
Add a link
Reference in a new issue