git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@8545 d0543943-73ff-0310-b7d9-9358b9ac24b2
This commit is contained in:
Michael Jerris
2008-05-23 20:56:24 +00:00
parent d2290cfa3a
commit 00654d880e
338 changed files with 55725 additions and 19400 deletions

View File

@@ -1,6 +1,8 @@
#include <iostream>
#include <sstream>
#include <stdexcept>
#include <map>
#include <vector>
#include "xmlrpc-c/oldcppwrapper.hpp"
#include "DataType.hpp"
@@ -15,50 +17,66 @@ using namespace std;
// Instances of DataType know how generate code fragments for manipulating
// a specific XML-RPC data type.
string DataType::defaultParameterBaseName (int position) const {
ostringstream name_stream;
name_stream << typeName() << position << ends;
string name(name_stream.str());
return name;
string
DataType::defaultParameterBaseName(unsigned int const position) const {
ostringstream nameStream;
nameStream << typeName() << position;
return nameStream.str();
}
//=========================================================================
// class RawDataType
//=========================================================================
// We want to manipulate some XML-RPC data types as XmlRpcValue objects.
class RawDataType : public DataType {
public:
RawDataType (const string& type_name) : DataType(type_name) {}
RawDataType(string const& typeName) : DataType(typeName) {}
virtual string parameterFragment (const string& base_name) const;
virtual string inputConversionFragment (const string& base_name) const;
virtual string returnTypeFragment () const;
virtual string outputConversionFragment (const string& var_name) const;
virtual string
parameterFragment(string const& baseName) const;
virtual string
inputConversionFragment(string const& baseName) const;
virtual string
returnTypeFragment() const;
virtual string
outputConversionFragment(string const& varName) const;
};
string RawDataType::parameterFragment (const string& base_name) const {
return "XmlRpcValue /*" + typeName() + "*/ " + base_name;
string
RawDataType::parameterFragment(string const& baseName) const {
return "XmlRpcValue /*" + typeName() + "*/ " + baseName;
}
string RawDataType::inputConversionFragment (const string& base_name) const {
return base_name;
string
RawDataType::inputConversionFragment(string const& baseName) const {
return baseName;
}
string RawDataType::returnTypeFragment () const {
string
RawDataType::returnTypeFragment() const {
return "XmlRpcValue /*" + typeName() + "*/";
}
string RawDataType::outputConversionFragment (const string& var_name) const {
return var_name;
string
RawDataType::outputConversionFragment(string const& varName) const {
return varName;
}
//=========================================================================
// class SimpleDataType
//=========================================================================
// Other types can be easily converted to and from a single native type.
class SimpleDataType : public DataType {
string mNativeType;
@@ -66,130 +84,185 @@ class SimpleDataType : public DataType {
string mGetterFunc;
public:
SimpleDataType (const string& type_name,
const string& native_type,
const string& maker_func,
const string& getter_func);
SimpleDataType(string const& typeName,
string const& nativeType,
string const& makerFunc,
string const& getterFunc);
virtual string parameterFragment (const string& base_name) const;
virtual string inputConversionFragment (const string& base_name) const;
virtual string returnTypeFragment () const;
virtual string outputConversionFragment (const string& var_name) const;
virtual string
parameterFragment(string const& baseName) const;
virtual string
inputConversionFragment(string const& baseName) const;
virtual string
returnTypeFragment() const;
virtual string
outputConversionFragment(string const& varName) const;
};
SimpleDataType::SimpleDataType (const string& type_name,
const string& native_type,
const string& maker_func,
const string& getter_func)
: DataType(type_name),
mNativeType(native_type),
mMakerFunc(maker_func),
mGetterFunc(getter_func)
{
SimpleDataType::SimpleDataType(string const& typeName,
string const& nativeType,
string const& makerFunc,
string const& getterFunc)
: DataType(typeName),
mNativeType(nativeType),
mMakerFunc(makerFunc),
mGetterFunc(getterFunc) {
}
string SimpleDataType::parameterFragment (const string& base_name) const {
return mNativeType + " " + base_name;
string
SimpleDataType::parameterFragment(string const& baseName) const {
return mNativeType + " const " + baseName;
}
string SimpleDataType::inputConversionFragment (const string& base_name) const
{
return mMakerFunc + "(" + base_name + ")";
string
SimpleDataType::inputConversionFragment(string const& baseName) const {
return mMakerFunc + "(" + baseName + ")";
}
string SimpleDataType::returnTypeFragment () const {
string
SimpleDataType::returnTypeFragment() const {
return mNativeType;
}
string SimpleDataType::outputConversionFragment (const string& var_name) const
{
return var_name + "." + mGetterFunc + "()";
string
SimpleDataType::outputConversionFragment(string const& varName) const {
return varName + "." + mGetterFunc + "()";
}
//=========================================================================
// class VoidDataType
//=========================================================================
// Some XML-RPC servers declare functions as void. Such functions have
// an arbitrary return value which we should ignore.
class VoidDataType : public DataType {
public:
VoidDataType () : DataType("void") {}
VoidDataType() : DataType("void") {}
virtual string parameterFragment (const string& base_name) const;
virtual string inputConversionFragment (const string& base_name) const;
virtual string returnTypeFragment () const;
virtual string outputConversionFragment (const string& var_name) const;
virtual string
parameterFragment(string const& baseName) const;
virtual string
inputConversionFragment(string const& baseName) const;
virtual string
returnTypeFragment() const;
virtual string
outputConversionFragment(string const& varName) const;
};
string VoidDataType::parameterFragment (const string&) const {
throw domain_error("Can't handle functions with 'void' arguments'");
}
string VoidDataType::inputConversionFragment (const string&) const {
string
VoidDataType::parameterFragment(string const&) const {
throw domain_error("Can't handle functions with 'void' arguments'");
}
string VoidDataType::returnTypeFragment () const {
string
VoidDataType::inputConversionFragment(string const&) const {
throw domain_error("Can't handle functions with 'void' arguments'");
}
string
VoidDataType::returnTypeFragment () const {
return "void";
}
string VoidDataType::outputConversionFragment (const string&) const {
string
VoidDataType::outputConversionFragment(string const&) const {
return "/* Return value ignored. */";
}
//=========================================================================
// function findDataType
//=========================================================================
// Given the name of an XML-RPC data type, try to find a corresponding
// DataType object.
SimpleDataType intType ("int", "XmlRpcValue::int32",
"XmlRpcValue::makeInt",
"getInt");
SimpleDataType boolType ("bool", "bool",
"XmlRpcValue::makeBool",
"getBool");
SimpleDataType doubleType ("double", "double",
"XmlRpcValue::makeDouble",
"getDouble");
SimpleDataType stringType ("string", "string",
"XmlRpcValue::makeString",
"getString");
static SimpleDataType const intType ("int", "XmlRpcValue::int32",
"XmlRpcValue::makeInt",
"getInt");
static SimpleDataType const boolType ("bool", "bool",
"XmlRpcValue::makeBool",
"getBool");
static SimpleDataType const doubleType ("double", "double",
"XmlRpcValue::makeDouble",
"getDouble");
static SimpleDataType const stringType ("string", "std::string",
"XmlRpcValue::makeString",
"getString");
RawDataType dateTimeType ("dateTime");
RawDataType base64Type ("base64");
RawDataType structType ("struct");
RawDataType arrayType ("array");
static RawDataType const dateTimeType ("dateTime");
static RawDataType const base64Type ("base64");
static RawDataType const structType ("struct");
static RawDataType const arrayType ("array");
VoidDataType voidType;
static VoidDataType const voidType;
const DataType& findDataType (const string& name) {
const DataType&
findDataType(string const& name) {
/*----------------------------------------------------------------------------
Given the name of an XML-RPC data type, try to find a corresponding
DataType object.
-----------------------------------------------------------------------------*/
if (name == "int" || name == "i4")
return intType;
return intType;
else if (name == "boolean")
return boolType;
return boolType;
else if (name == "double")
return doubleType;
return doubleType;
else if (name == "string")
return stringType;
return stringType;
else if (name == "dateTime.iso8601")
return dateTimeType;
return dateTimeType;
else if (name == "base64")
return base64Type;
return base64Type;
else if (name == "struct")
return structType;
return structType;
else if (name == "array")
return arrayType;
return arrayType;
else if (name == "void")
return voidType;
return voidType;
else if (name == "INT")
return intType;
else if (name == "BOOLEAN")
return boolType;
else if (name == "DOUBLE")
return doubleType;
else if (name == "STRING")
return stringType;
else if (name == "DATETIME.ISO8601")
return dateTimeType;
else if (name == "BASE64")
return base64Type;
else if (name == "STRUCT")
return structType;
else if (name == "ARRAY")
return arrayType;
else if (name == "VOID")
return voidType;
else if (name == "NIL")
return voidType;
else
throw domain_error("Unknown XML-RPC type " + name);
// This code should never be executed.
XMLRPC_ASSERT(0);
return intType;
throw domain_error("Unknown XML-RPC type name '" + name + "'");
}

View File

@@ -23,7 +23,7 @@ public:
// Given a parameter position, calculate a unique base name for all
// parameter-related variables.
virtual std::string
defaultParameterBaseName(int position) const;
defaultParameterBaseName(unsigned int const position) const;
// Virtual functions for processing parameters.
virtual std::string

View File

@@ -1,21 +1,32 @@
ifeq ($(SRCDIR)x,x)
SRCDIR = $(CURDIR)/../..
BUILDDIR= $(SRCDIR)
ifeq ($(SRCDIR),)
updir = $(shell echo $(dir $(1)) | sed 's/.$$//')
TOOLSDIR := $(call updir,$(CURDIR))
SRCDIR := $(call updir,$(TOOLSDIR))
BLDDIR := $(SRCDIR)
endif
SUBDIR := tools/xml-rpc-api2cpp
default: all
include $(BUILDDIR)/Makefile.config
include $(BLDDIR)/config.mk
include ../Makefile.common
include $(SRCDIR)/tools/common.mk
INCLUDES = -I$(SRCDIR) -I$(SRCDIR)/include
INCLUDES = -I$(BLDDIR) -I$(BLDDIR)/include -I$(SRCDIR)/include
CXXFLAGS = $(INCLUDES) $(CXXFLAGS_COMMON) $(CFLAGS_PERSONAL) $(CADD)
LDFLAGS = $(CLIENT_LDFLAGS) $(LADD)
LDFLAGS = $(LADD)
all: xml-rpc-api2cpp
LDLIBS = -L$(BLDDIR)/src/cpp -lxmlrpc_cpp -lxmlrpc_server $(CLIENT_LDLIBS)
PROGS :=
ifeq ($(MUST_BUILD_CLIENT),yes)
PROGS += xml-rpc-api2cpp
endif
all: $(PROGS)
OBJECTS = \
xml-rpc-api2cpp.o \
@@ -30,17 +41,23 @@ xml-rpc-api2cpp: \
$(LIBXMLRPC_CLIENT) \
$(LIBXMLRPC_SERVER) \
$(LIBXMLRPC) \
$(LIBXML)
$(LIBTOOL) --mode=link $(CXXLD) -o $@ $(LDFLAGS) $^
$(LIBXMLRPC_XML) \
$(LIBXMLRPC_UTIL)
$(CXXLD) -o $@ $(LDFLAGS) $(OBJECTS) $(LDLIBS)
%.o:%.cpp
$(LIBTOOL) --mode=compile $(CXX) -c $(CXXFLAGS) $<
$(CXX) -c $(CXXFLAGS) $<
# This common.mk dependency makes sure the symlinks get built before
# this make file is used for anything.
$(SRCDIR)/common.mk: srcdir blddir
include Makefile.depend
.PHONY: clean
clean: clean-common
rm -f xml-rpc-api2cpp
rm -f $(PROGS)
.PHONY: distclean
distclean: clean distclean-common

View File

@@ -11,68 +11,74 @@ using namespace std;
#include "XmlRpcClass.hpp"
//=========================================================================
// XmlRpcClass
//=========================================================================
// This class stores information about a proxy class, and knows how to
// generate code.
XmlRpcClass::XmlRpcClass(string const& className) :
mClassName(className) {}
XmlRpcClass::XmlRpcClass (string class_name)
: mClassName(class_name)
{
}
XmlRpcClass::XmlRpcClass (const XmlRpcClass& c)
: mClassName(c.mClassName),
mFunctions(c.mFunctions)
{
}
XmlRpcClass& XmlRpcClass::operator= (const XmlRpcClass& c)
{
if (this == &c)
return *this;
mClassName = c.mClassName;
mFunctions = c.mFunctions;
XmlRpcClass::XmlRpcClass(XmlRpcClass const& c) :
mClassName(c.mClassName),
mFunctions(c.mFunctions) {}
XmlRpcClass&
XmlRpcClass::operator= (XmlRpcClass const& c) {
if (this != &c) {
this->mClassName = c.mClassName;
this->mFunctions = c.mFunctions;
}
return *this;
}
void XmlRpcClass::addFunction (const XmlRpcFunction& function)
{
void
XmlRpcClass::addFunction(XmlRpcFunction const& function) {
mFunctions.push_back(function);
}
void XmlRpcClass::printDeclaration (ostream&)
{
cout << "class " << mClassName << " {" << endl;
cout << " XmlRpcClient mClient;" << endl;
cout << endl;
cout << "public:" << endl;
cout << " " << mClassName << " (const XmlRpcClient& client)" << endl;
cout << " : mClient(client) {}" << endl;
cout << " " << mClassName << " (const string& server_url)" << endl;
cout << " : mClient(XmlRpcClient(server_url)) {}" << endl;
cout << " " << mClassName << " (const " << mClassName << "& o)" << endl;
cout << " : mClient(o.mClient) {}" << endl;
cout << endl;
cout << " " << mClassName << "& operator= (const "
<< mClassName << "& o) {" << endl;
cout << " if (this != &o) mClient = o.mClient;" << endl;
cout << " return *this;" << endl;
cout << " }" << endl;
vector<XmlRpcFunction>::iterator f;
void
XmlRpcClass::printDeclaration(ostream & out) const {
out << "class " << mClassName << " {" << endl;
out << " XmlRpcClient mClient;" << endl;
out << endl;
out << "public:" << endl;
out << " " << mClassName << " (const XmlRpcClient& client)" << endl;
out << " : mClient(client) {}" << endl;
out << " " << mClassName << " (const std::string& server_url)" << endl;
out << " : mClient(XmlRpcClient(server_url)) {}" << endl;
out << " " << mClassName << " (const " << mClassName << "& o)" << endl;
out << " : mClient(o.mClient) {}" << endl;
out << endl;
out << " " << mClassName << "& operator= (const "
<< mClassName << "& o) {" << endl;
out << " if (this != &o) mClient = o.mClient;" << endl;
out << " return *this;" << endl;
out << " }" << endl;
vector<XmlRpcFunction>::const_iterator f;
for (f = mFunctions.begin(); f < mFunctions.end(); ++f) {
f->printDeclarations(cout);
f->printDeclarations(out);
}
cout << "};" << endl;
out << "};" << endl;
}
void XmlRpcClass::printDefinition (ostream&)
{
vector<XmlRpcFunction>::iterator f;
void
XmlRpcClass::printDefinition(ostream & out) const {
vector<XmlRpcFunction>::const_iterator f;
for (f = mFunctions.begin(); f < mFunctions.end(); ++f) {
f->printDefinitions(cout, mClassName);
f->printDefinitions(out, mClassName);
}
}

View File

@@ -1,19 +1,22 @@
#include <vector>
class XmlRpcClass {
// An object of this class contains information about a proxy
// class, and knows how to generate code.
std::string mClassName;
std::vector<XmlRpcFunction> mFunctions;
public:
XmlRpcClass (std::string class_name);
XmlRpcClass (const XmlRpcClass&);
XmlRpcClass& operator= (const XmlRpcClass&);
XmlRpcClass (std::string const& className);
XmlRpcClass(XmlRpcClass const&);
XmlRpcClass& operator= (XmlRpcClass const&);
std::string className () const { return mClassName; }
void addFunction (const XmlRpcFunction& function);
void printDeclaration (ostream& out);
void printDefinition (ostream& out);
void printDeclaration (ostream& out) const;
void printDefinition (ostream& out) const;
};

View File

@@ -1,137 +1,216 @@
#include <iostream>
#include <sstream>
#include <stdexcept>
#include "xmlrpc-c/oldcppwrapper.hpp"
#include "DataType.hpp"
#include "XmlRpcFunction.hpp"
using std::domain_error;
using std::endl;
using namespace std;
//=========================================================================
// class XmlRpcFunction
//=========================================================================
// Contains everything we know about a given server function, and knows
// how to print local bindings.
XmlRpcFunction::XmlRpcFunction(string const& functionName,
string const& methodName,
string const& help,
XmlRpcValue const signatureList) :
mFunctionName(functionName),
mMethodName(methodName),
mHelp(help),
mSynopsis(signatureList) {}
XmlRpcFunction::XmlRpcFunction(const string& function_name,
const string& method_name,
const string& help,
XmlRpcValue synopsis)
: mFunctionName(function_name), mMethodName(method_name),
mHelp(help), mSynopsis(synopsis)
{
}
XmlRpcFunction::XmlRpcFunction (const XmlRpcFunction& f)
: mFunctionName(f.mFunctionName), mMethodName(f.mMethodName),
mHelp(f.mHelp), mSynopsis(f.mSynopsis)
{
}
XmlRpcFunction& XmlRpcFunction::operator= (const XmlRpcFunction& f) {
if (this == &f)
return *this;
mFunctionName = f.mFunctionName;
mMethodName = f.mMethodName;
mHelp = f.mHelp;
mSynopsis = f.mSynopsis;
XmlRpcFunction::XmlRpcFunction(XmlRpcFunction const& f) :
mFunctionName(f.mFunctionName),
mMethodName(f.mMethodName),
mHelp(f.mHelp),
mSynopsis(f.mSynopsis) {}
XmlRpcFunction&
XmlRpcFunction::operator= (XmlRpcFunction const& f) {
if (this != &f) {
this->mFunctionName = f.mFunctionName;
this->mMethodName = f.mMethodName;
this->mHelp = f.mHelp;
this->mSynopsis = f.mSynopsis;
}
return *this;
}
void XmlRpcFunction::printDeclarations (ostream& out) {
// XXX - Do a sloppy job of printing documentation.
out << endl << " /* " << mHelp << " */" << endl;
// Print each declaration.
size_t end = mSynopsis.arraySize();
for (size_t i = 0; i < end; i++)
printDeclaration(out, i);
}
void
XmlRpcFunction::printDeclarations(ostream & out) const {
void XmlRpcFunction::printDefinitions (ostream& out, const string& className) {
size_t end = mSynopsis.arraySize();
for (size_t i = 0; i < end; i++) {
out << endl;
printDefinition(out, className, i);
try {
// Print the method help as a comment
out << endl << " /* " << mHelp << " */" << endl;
size_t end;
try {
end = mSynopsis.arraySize();
} catch (XmlRpcFault const& fault) {
throw(logic_error("Failed to get size of signature array for "
"method " + this->mFunctionName + ". " +
fault.getFaultString()));
}
// Print the declarations for all the signatures of this
// XML-RPC method.
for (size_t i = 0; i < end; ++i)
printDeclaration(out, i);
} catch (exception const& e) {
throw(logic_error("Failed to generate declarations for method " +
this->mFunctionName + ". " + e.what()));
}
}
// Print the parameter declarations.
void XmlRpcFunction::printParameters (ostream& out, size_t synopsis_index) {
size_t end = parameterCount(synopsis_index);
bool first = true;
for (size_t i = 0; i < end; i++) {
if (first)
first = false;
else
out << ", ";
const DataType& ptype (parameterType(synopsis_index, i));
string basename = ptype.defaultParameterBaseName(i + 1);
out << ptype.parameterFragment(basename);
void
XmlRpcFunction::printDefinitions(ostream & out,
string const& className) const {
try {
size_t const end(mSynopsis.arraySize());
for (size_t i = 0; i < end; ++i) {
out << endl;
printDefinition(out, className, i);
}
} catch (XmlRpcFault const& fault) {
throw(logic_error("Failed to generate definitions for class " +
this->mFunctionName + ". " +
fault.getFaultString()));
}
}
void XmlRpcFunction::printDeclaration (ostream& out, size_t synopsis_index) {
const DataType& rtype (returnType(synopsis_index));
out << " " << rtype.returnTypeFragment() << " "
<< mFunctionName << " (";
printParameters(out, synopsis_index);
out << ");" << endl;
void
XmlRpcFunction::printParameters(ostream & out,
size_t const synopsisIndex) const {
/*----------------------------------------------------------------------------
Print the parameter declarations.
-----------------------------------------------------------------------------*/
size_t const end(parameterCount(synopsisIndex));
bool first;
first = true;
for (size_t i = 0; i < end; ++i) {
if (!first)
out << ", ";
DataType const& ptype(parameterType(synopsisIndex, i));
string const basename(ptype.defaultParameterBaseName(i + 1));
out << ptype.parameterFragment(basename);
first = false;
}
}
void XmlRpcFunction::printDefinition (ostream& out,
const string& className,
size_t synopsis_index)
{
const DataType& rtype (returnType(synopsis_index));
void
XmlRpcFunction::printDeclaration(ostream & out,
size_t const synopsisIndex) const {
try {
DataType const& rtype(returnType(synopsisIndex));
out << " " << rtype.returnTypeFragment() << " "
<< mFunctionName << " (";
printParameters(out, synopsisIndex);
out << ");" << endl;
} catch (XmlRpcFault const& fault) {
ostringstream msg;
msg << "Failed to generate header for signature "
<< synopsisIndex
<< " . "
<< fault.getFaultString();
throw(logic_error(msg.str()));
}
}
void
XmlRpcFunction::printDefinition(ostream & out,
string const& className,
size_t const synopsisIndex) const {
DataType const& rtype(returnType(synopsisIndex));
out << rtype.returnTypeFragment() << " "
<< className << "::" << mFunctionName << " (";
printParameters(out, synopsis_index);
<< className << "::" << mFunctionName << " (";
printParameters(out, synopsisIndex);
out << ") {" << endl;
out << " XmlRpcValue params = XmlRpcValue::makeArray();" << endl;
out << " XmlRpcValue params(XmlRpcValue::makeArray());" << endl;
/* Emit code to convert the parameters into an array of XML-RPC objects. */
size_t end = parameterCount(synopsis_index);
for (size_t i = 0; i < end; i++) {
const DataType& ptype (parameterType(synopsis_index, i));
string basename = ptype.defaultParameterBaseName(i + 1);
out << " params.arrayAppendItem("
<< ptype.inputConversionFragment(basename) << ");" << endl;
size_t const end(parameterCount(synopsisIndex));
for (size_t i = 0; i < end; ++i) {
DataType const& ptype(parameterType(synopsisIndex, i));
string const basename(ptype.defaultParameterBaseName(i + 1));
out << " params.arrayAppendItem("
<< ptype.inputConversionFragment(basename) << ");" << endl;
}
/* Emit the function call.*/
out << " XmlRpcValue result = this->mClient.call(\""
<< mMethodName << "\", params);" << endl;
out << " XmlRpcValue result(this->mClient.call(\""
<< mMethodName << "\", params));" << endl;
/* Emit the return statement. */
out << " return " << rtype.outputConversionFragment("result")
<< ";" << endl;
<< ";" << endl;
out << "}" << endl;
}
const DataType& XmlRpcFunction::returnType (size_t synopsis_index) {
XmlRpcValue func_synop = mSynopsis.arrayGetItem(synopsis_index);
return findDataType(func_synop.arrayGetItem(0).getString());
const DataType&
XmlRpcFunction::returnType(size_t const synopsisIndex) const {
XmlRpcValue const funcSynop(mSynopsis.arrayGetItem(synopsisIndex));
return findDataType(funcSynop.arrayGetItem(0).getString());
}
size_t XmlRpcFunction::parameterCount (size_t synopsis_index) {
XmlRpcValue func_synop = mSynopsis.arrayGetItem(synopsis_index);
size_t size = func_synop.arraySize();
size_t
XmlRpcFunction::parameterCount(size_t const synopsisIndex) const {
XmlRpcValue const funcSynop(mSynopsis.arrayGetItem(synopsisIndex));
size_t const size(funcSynop.arraySize());
if (size < 1)
throw domain_error("Synopsis contained no items");
throw domain_error("Synopsis contained no items");
return size - 1;
}
const DataType& XmlRpcFunction::parameterType (size_t synopsis_index,
size_t parameter_index)
{
XmlRpcValue func_synop = mSynopsis.arrayGetItem(synopsis_index);
XmlRpcValue param = func_synop.arrayGetItem(parameter_index + 1);
DataType const&
XmlRpcFunction::parameterType(size_t const synopsisIndex,
size_t const parameterIndex) const {
XmlRpcValue const funcSynop(mSynopsis.arrayGetItem(synopsisIndex));
XmlRpcValue const param(funcSynop.arrayGetItem(parameterIndex + 1));
return findDataType(param.getString());
}

View File

@@ -1,4 +1,3 @@
#include <string>
#include <iostream>
@@ -6,6 +5,9 @@ using std::string;
using std::ostream;
class XmlRpcFunction {
// An object of this class contains everything we know about a
// given XML-RPC method, and knows how to print local bindings.
string mFunctionName;
string mMethodName;
string mHelp;
@@ -13,25 +15,25 @@ class XmlRpcFunction {
public:
XmlRpcFunction(const string& function_name,
const string& method_name,
const string& help,
XmlRpcValue synopsis);
const string& method_name,
const string& help,
XmlRpcValue synopsis);
XmlRpcFunction (const XmlRpcFunction&);
XmlRpcFunction& operator= (const XmlRpcFunction&);
void printDeclarations (ostream& out);
void printDefinitions (ostream& out, const string& className);
void printDeclarations (ostream& out) const;
void printDefinitions (ostream& out, const string& className) const;
private:
void printParameters (ostream& out, size_t synopsis_index);
void printDeclaration (ostream& out, size_t synopsis_index);
void printParameters (ostream& out, size_t synopsis_index) const;
void printDeclaration (ostream& out, size_t synopsis_index) const;
void printDefinition (ostream& out,
const string& className,
size_t synopsis_index);
const string& className,
size_t synopsis_index) const;
const DataType& returnType (size_t synopsis_index);
size_t parameterCount (size_t synopsis_index);
const DataType& returnType (size_t synopsis_index) const;
size_t parameterCount (size_t synopsis_index) const;
const DataType& parameterType (size_t synopsis_index,
size_t parameter_index);
size_t parameter_index) const;
};

View File

@@ -14,144 +14,199 @@ using namespace std;
#define VERSION "0.1"
//=========================================================================
// function get_class_info
//=========================================================================
// Connect to a remote server and extract the information we'll need to
// build a proxy class.
/*----------------------------------------------------------------------------
Command line
-----------------------------------------------------------------------------*/
XmlRpcClass get_class_info (string server_url,
string class_prefix,
string class_name)
{
// Create a place to store our data.
XmlRpcClass info(class_name);
class cmdlineInfo {
public:
string serverUrl;
string methodPrefix;
string localClass;
// Create a proxy class.
SystemProxy system(server_url);
cmdlineInfo(int const argc,
const char ** const argv);
// Fetch the full list of methods, and process the ones we want.
XmlRpcValue methods = system.listMethods();
size_t end = methods.arraySize();
for (size_t i = 0; i < end; i++) {
private:
cmdlineInfo();
};
// Break the method name into two pieces.
string method_prefix;
string function_name;
string method_name = methods.arrayGetItem(i).getString();
size_t last_dot = method_name.rfind('.');
if (last_dot == string::npos) {
function_name = method_name;
} else {
method_prefix = string(method_name, 0, last_dot);
function_name = string(method_name, last_dot + 1);
}
// Decide whether we care about this function.
if (method_prefix == class_prefix) {
// Fetch some information about the function.
string help = system.methodHelp(method_name);
XmlRpcValue signature = system.methodSignature(method_name);
cmdlineInfo::cmdlineInfo(int const argc,
const char ** const argv) {
// Add this function to our class information.
XmlRpcFunction func(function_name, method_name, help, signature);
info.addFunction(func);
}
if (argc-1 != 3) {
cerr << argv[0] << ": Usage:" << endl
<< " xml-rpc-api2cpp <server_url> <method_prefix> <local_class>"
<< endl << endl
<< "Sample arguments:" << endl
<< " server_url = http://localhost/RPC2" << endl
<< " method_prefix = system" << endl
<< " local_class = SystemProxy" << endl;
exit(1);
}
this->serverUrl = string(argv[1]);
this->methodPrefix = string(argv[2]);
this->localClass = string(argv[3]);
}
static XmlRpcClass
getClassInfo(string const& serverUrl,
string const& classPrefix,
string const& className) {
/*----------------------------------------------------------------------------
Connect to a remote server and extract the information we'll need to
build a proxy class.
-----------------------------------------------------------------------------*/
XmlRpcClass info(className);
SystemProxy system(serverUrl);
XmlRpcValue const methods(system.listMethods());
size_t const end = methods.arraySize();
for (size_t i = 0; i < end; ++i) {
// Break the method name into two pieces.
string const methodName(methods.arrayGetItem(i).getString());
size_t const lastDot(methodName.rfind('.'));
string methodPrefix;
string functionName;
if (lastDot == string::npos) {
methodPrefix = "";
functionName = methodName;
} else {
methodPrefix = string(methodName, 0, lastDot);
functionName = string(methodName, lastDot + 1);
}
if (methodPrefix == classPrefix) {
// It's a method User cares about
string const help(system.methodHelp(methodName));
XmlRpcValue const signatureList(
system.methodSignature(methodName));
if (signatureList.getType() != XMLRPC_TYPE_ARRAY) {
// It must be the string "undef", meaning the server
// won't tell us any signatures.
cerr << "Skipping method " << methodName << " "
<< "because server does not report any signatures "
<< "for it (via system.methodSignature method)"
<< endl;
} else {
// Add this function to our class information.
XmlRpcFunction const method(functionName,
methodName,
help,
signatureList);
info.addFunction(method);
}
}
}
return info;
}
//=========================================================================
// function print_header
//=========================================================================
// Print a complete header for the specified class.
void print_header (ostream& out, XmlRpcClass& class_info) {
string class_name = class_info.className();
out << "// " << class_name << ".h - xmlrpc-c C++ proxy class" << endl;
out << "// Auto-generated by xml-rpc-api2cpp." << endl;
out << endl;
static void
printHeader(ostream & out,
XmlRpcClass const& classInfo) {
/*----------------------------------------------------------------------------
Print a complete header for the specified class.
-----------------------------------------------------------------------------*/
string const className(classInfo.className());
string header_symbol = "_" + class_name + "_H_";
out << "#ifndef " << header_symbol << endl;
out << "#define " << header_symbol << " 1" << endl;
out << endl;
out << "#include <XmlRpcCpp.h>" << endl;
out << endl;
try {
out << "// " << className << ".h - xmlrpc-c C++ proxy class" << endl;
out << "// Auto-generated by xml-rpc-api2cpp." << endl;
out << endl;
class_info.printDeclaration(cout);
string const headerSymbol("_" + className + "_H_");
out << endl;
out << "#endif /* " << header_symbol << " */" << endl;
}
out << "#ifndef " << headerSymbol << endl;
out << "#define " << headerSymbol << " 1" << endl;
out << endl;
out << "#include <xmlrpc-c/oldcppwrapper.hpp>" << endl;
out << endl;
classInfo.printDeclaration(cout);
//=========================================================================
// function print_cc_file
//=========================================================================
// Print a complete header for the specified class.
void print_cc_file (ostream& out, XmlRpcClass& class_info) {
string class_name = class_info.className();
out << "// " << class_name << ".cc - xmlrpc-c C++ proxy class" << endl;
out << "// Auto-generated by xml-rpc-api2cpp." << endl;
out << endl;
out << "#include <XmlRpcCpp.h>" << endl;
out << "#include \"" << class_name << ".h\"" << endl;
class_info.printDefinition(cout);
}
//=========================================================================
// function main
//=========================================================================
// For now, just a test harness.
int main (int argc, char **argv) {
/* Parse our command-line arguments. */
if (argc != 4) {
cerr << argv[0] << ": Usage:" << endl
<< " xml-rpc-api2cpp <server_url> <method_prefix> <local_class>"
<< endl << endl
<< "Sample arguments:" << endl
<< " server_url = http://localhost/RPC2" << endl
<< " method_prefix = system" << endl
<< " local_class = SystemProxy" << endl;
exit(1);
out << endl;
out << "#endif /* " << headerSymbol << " */" << endl;
} catch (exception const& e) {
throw(logic_error("Failed to generate header for class " +
className + ". " + e.what()));
}
string server_url = argv[1];
string method_prefix = argv[2];
string local_class = argv[3];
}
static void
printCppFile(ostream & out,
XmlRpcClass const& classInfo) {
/*----------------------------------------------------------------------------
Print a complete definition for the specified class.
-----------------------------------------------------------------------------*/
string const className(classInfo.className());
try {
out << "// " << className << ".cc - xmlrpc-c C++ proxy class" << endl;
out << "// Auto-generated by xml-rpc-api2cpp." << endl;
out << endl;
out << "#include <xmlrpc-c/oldcppwrapper.hpp>" << endl;
out << "#include \"" << className << ".h\"" << endl;
classInfo.printDefinition(cout);
} catch (XmlRpcFault const& fault) {
throw(logic_error("Failed to generate definition for class " +
className + ". " + fault.getFaultString()));
}
}
int
main(int const argc,
const char ** const argv) {
string const progName(argv[0]);
cmdlineInfo const cmdline(argc, argv);
int retval;
int status = 0;
XmlRpcClient::Initialize(NAME, VERSION);
try {
XmlRpcClass system = get_class_info(server_url,
method_prefix,
local_class);
print_header(cout, system);
cout << endl;
print_cc_file(cout, system);
XmlRpcClass system = getClassInfo(cmdline.serverUrl,
cmdline.methodPrefix,
cmdline.localClass);
printHeader(cout, system);
cout << endl;
printCppFile(cout, system);
retval = 0;
} catch (XmlRpcFault& fault) {
cerr << argv[0] << ": XML-RPC fault #" << fault.getFaultCode()
<< ": " << fault.getFaultString() << endl;
status = 1;
cerr << progName << ": XML-RPC fault #" << fault.getFaultCode()
<< ": " << fault.getFaultString() << endl;
retval = 1;
} catch (logic_error& err) {
cerr << argv[0] << ": " << err.what() << endl;
status = 1;
cerr << progName << ": " << err.what() << endl;
retval = 1;
} catch (...) {
cerr << argv[0] << ": Unknown exception" << endl;
status = 1;
cerr << progName << ": Unknown exception" << endl;
retval = 1;
}
XmlRpcClient::Terminate();
return status;
return retval;
}