#include #include #include "xmlrpc-c/oldcppwrapper.hpp" #include "DataType.hpp" #include "XmlRpcFunction.hpp" using std::domain_error; using std::endl; //========================================================================= // class XmlRpcFunction //========================================================================= // Contains everything we know about a given server function, and knows // how to print local bindings. 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; 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::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); } } // 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::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::printDefinition (ostream& out, const string& className, size_t synopsis_index) { const DataType& rtype (returnType(synopsis_index)); out << rtype.returnTypeFragment() << " " << className << "::" << mFunctionName << " ("; printParameters(out, synopsis_index); out << ") {" << 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; } /* Emit the function call.*/ out << " XmlRpcValue result = this->mClient.call(\"" << mMethodName << "\", params);" << endl; /* Emit the return statement. */ out << " return " << rtype.outputConversionFragment("result") << ";" << 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()); } size_t XmlRpcFunction::parameterCount (size_t synopsis_index) { XmlRpcValue func_synop = mSynopsis.arrayGetItem(synopsis_index); size_t size = func_synop.arraySize(); if (size < 1) 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); return findDataType(param.getString()); }