diff --git a/src/cpp/ripple/ParameterTable.cpp b/src/cpp/ripple/ParameterTable.cpp new file mode 100644 index 000000000..cb61a064b --- /dev/null +++ b/src/cpp/ripple/ParameterTable.cpp @@ -0,0 +1,159 @@ +#include "ParameterTable.h" + +#include +#include + +#include "utils.h" + +bool ParameterNode::setValue(const std::string& name, const Json::Value& value, Json::Value& error) +{ + if (name.empty()) // this node + return setValue(value, error); + + size_t dot = name.find('.'); + if (dot == std::string::npos) // a child of this node + { + std::map::iterator it = mChildren.find(name); + if (it == mChildren.end()) + { + error = Json::objectValue; + error["error"] = "Name not found"; + error["name"] = name; + return false; + } + return it->second->setValue(value, error); + } + + std::map::iterator it = mChildren.find(name.substr(0, dot)); + if (it == mChildren.end()) + { + error = Json::objectValue; + error["error"] = "Name not found"; + error["name"] = name; + return false; + } + + ParameterNode* n = dynamic_cast(it->second.get()); + if (!n) + { + error = Json::objectValue; + error["error"] = "Node has no children"; + error["name"] = it->second->getName(); + } + + return n->setValue(name.substr(dot + 1), value, error); +} + +bool ParameterNode::addNode(const std::string& name, Parameter::ref node) +{ + if (name.empty()) // this node + return false; + + size_t dot = name.find('.'); + if (dot == std::string::npos) // a child of this node + { + std::map::iterator it = mChildren.find(name); + if (it != mChildren.end()) + return false; + mChildren[name] = node; + return true; + } + + std::map::iterator it = mChildren.find(name.substr(0, dot)); + ParameterNode* n; + if (it == mChildren.end()) + { // create a new inner node + ParameterNode::pointer node = boost::make_shared(getShared(), name.substr(0, dot)); + n = dynamic_cast(node.get()); + assert(n); + mChildren[name] = node; + } + else + { // existing node passed through must be inner + ParameterNode* n = dynamic_cast(it->second.get()); + if (!n) + return false; + } + + return n->addNode(name.substr(dot + 1), node); +} + +Json::Value ParameterNode::getValue(int i) const +{ + Json::Value v(Json::objectValue); + typedef std::pair string_ref_pair; + BOOST_FOREACH(const string_ref_pair& it, mChildren) + { + v[it.first] = it.second->getValue(i); + } + return v; +} + +bool ParameterNode::setValue(const Json::Value& value, Json::Value& error) +{ + error = Json::objectValue; + error["error"] = "Cannot end on an inner node"; + + Json::Value nodes(Json::arrayValue); + typedef std::pair string_ref_pair; + BOOST_FOREACH(const string_ref_pair& it, mChildren) + { + nodes.append(it.first); + } + error["legal_nodes"] = nodes; + return false; +} + +ParameterString::ParameterString(Parameter::ref parent, const std::string& name, const std::string& value) + : Parameter(parent, name), mValue(value) +{ ; } + +Json::Value ParameterString::getValue(int) const +{ + return Json::Value(mValue); +} + +bool ParameterString::setValue(const Json::Value& value, Json::Value& error) +{ + if (!value.isConvertibleTo(Json::stringValue)) + { + error = Json::objectValue; + error["error"] = "Cannot convert to string"; + error["value"] = value; + return false; + } + mValue = value.asString(); + return true; +} + +ParameterInt::ParameterInt(Parameter::ref parent, const std::string& name, int value) + : Parameter(parent, name), mValue(value) +{ ; } + +Json::Value ParameterInt::getValue(int) const +{ + return Json::Value(mValue); +} + +bool ParameterInt::setValue(const Json::Value& value, Json::Value& error) +{ + if (value.isConvertibleTo(Json::intValue)) + { + mValue = value.asInt(); + return true; + } + if (value.isConvertibleTo(Json::stringValue)) + { + try + { + mValue = lexical_cast_st(value.asString()); + } + catch (...) + { + } + } + error = Json::objectValue; + error["error"] = "Cannot convert to integer"; + error["value"] = value; + return false; +} diff --git a/src/cpp/ripple/ParameterTable.h b/src/cpp/ripple/ParameterTable.h new file mode 100644 index 000000000..897a8551f --- /dev/null +++ b/src/cpp/ripple/ParameterTable.h @@ -0,0 +1,72 @@ +#ifndef PARAMETER_TABLE__H +#define PARAMETER_TABLE__H + +#include +#include + +#include +#include + +#include "../json/value.h" + +class Parameter : public boost::enable_shared_from_this +{ // abstract base class parameters are derived from +public: + typedef boost::shared_ptr pointer; + typedef const boost::shared_ptr& ref; + +protected: + pointer mParent; + std::string mName; + +public: + Parameter(Parameter::ref parent, const std::string& name) : mParent(parent), mName(name) { ; } + virtual ~Parameter() { ; } + + const std::string& getName() const { return mName; } + + virtual Json::Value getValue(int) const = 0; + virtual bool setValue(const Json::Value& value, Json::Value& error) = 0; + + Parameter::pointer getShared() { return shared_from_this(); } +}; + +class ParameterNode : public Parameter +{ +protected: + std::map mChildren; + +public: + ParameterNode(Parameter::ref parent, const std::string& name) : Parameter(parent, name) { ; } + bool addChildNode(Parameter::ref node); + + bool setValue(const std::string& name, const Json::Value& value, Json::Value& error); + bool addNode(const std::string& name, Parameter::ref node); + + virtual Json::Value getValue(int) const; + virtual bool setValue(const Json::Value& value, Json::Value& error); +}; + +class ParameterString : public Parameter +{ +protected: + std::string mValue; + +public: + ParameterString(Parameter::ref parent, const std::string& name, const std::string& value); + virtual Json::Value getValue(int) const; + virtual bool setValue(const Json::Value& value, Json::Value& error); +}; + +class ParameterInt : public Parameter +{ +protected: + int mValue; + +public: + ParameterInt(Parameter::ref parent, const std::string& name, int value); + virtual Json::Value getValue(int) const; + virtual bool setValue(const Json::Value& value, Json::Value& error); +}; + +#endif