#ifndef RPC_H #define RPC_H #include #include #include class RPCValue; typedef enum { RPCNull, RPCBoolean, RPCInteger, RPCString, RPCArray, RPCObject } RPCValueType; typedef std::map RPCObjectContainer; typedef std::vector RPCArrayContainer; class RPCValue : public classbase { protected: RPCValueType type; void *value; double *CastInteger() { return (double*)value; } std::string *CastString() { return (std::string*)value; } RPCObjectContainer *CastObject() { return (RPCObjectContainer*)value; } RPCArrayContainer *CastArray() { return (RPCArrayContainer*)value; } void DestroyValue() { // Some versions of GCC complain about declaration in switch statements RPCArrayContainer *a; RPCObjectContainer *o; switch (type) { case RPCInteger: delete this->CastInteger(); break; case RPCString: delete this->CastString(); break; case RPCArray: a = this->CastArray(); for (RPCArrayContainer::iterator i = a->begin(); i != a->end(); i++) delete *i; delete a; break; case RPCObject: o = this->CastObject(); for (RPCObjectContainer::iterator i = o->begin(); i != o->end(); i++) delete i->second; delete o; break; default: break; } value = NULL; } void InitValue() { switch (type) { case RPCNull: case RPCBoolean: value = NULL; break; case RPCInteger: value = new double; break; case RPCString: value = new std::string; break; case RPCArray: value = new RPCArrayContainer; break; case RPCObject: value = new RPCObjectContainer; break; } } RPCValue(const RPCValue &v) { } public: RPCValue *parent; RPCValue(RPCValue *parent = NULL) : type(RPCNull), value(NULL), parent(parent) { } RPCValue(RPCValueType type, RPCValue *parent = NULL) : type(type), value(NULL), parent(parent) { InitValue(); } RPCValue(bool nvalue, RPCValue *parent = NULL) : type(RPCBoolean), value((void*)nvalue), parent(parent) { } RPCValue(double nvalue, RPCValue *parent = NULL) : type(RPCInteger), parent(parent) { value = new double(nvalue); } RPCValue(const std::string &nvalue, RPCValue *parent = NULL) : type(RPCString), parent(parent) { value = new std::string(nvalue); } virtual ~RPCValue() { DestroyValue(); } RPCValueType GetType() { return type; } void SetNull() { DestroyValue(); type = RPCNull; } void SetBoolean(bool nvalue) { DestroyValue(); value = (void*)nvalue; type = RPCBoolean; } void SetInteger(double nvalue) { if (type == RPCInteger) { *this->CastInteger() = nvalue; } else { DestroyValue(); value = new double(nvalue); type = RPCInteger; } } void SetString(const std::string &nvalue) { if (type == RPCString) { this->CastString()->assign(nvalue); } else { DestroyValue(); value = new std::string(nvalue); type = RPCString; } } void SetArray() { if (type == RPCArray) { this->CastArray()->clear(); } else { DestroyValue(); type = RPCArray; InitValue(); } } void SetObject() { if (type == RPCObject) { this->CastObject()->clear(); } else { DestroyValue(); type = RPCObject; InitValue(); } } void ArrayAdd(RPCValue *nvalue) { if (type != RPCArray) return; RPCArrayContainer *a = this->CastArray(); a->push_back(nvalue); nvalue->parent = this; } void ObjectAdd(const std::string &key, RPCValue *nvalue) { if (type != RPCObject) return; RPCObjectContainer *o = this->CastObject(); o->insert(std::make_pair(key, nvalue)); nvalue->parent = this; } RPCValue *GetArray(int i) { if (type != RPCArray) return NULL; RPCArrayContainer *a = this->CastArray(); if ((i < 0) || (i >= (signed)a->size())) return NULL; return a->at(i); } int ArraySize() { if (type != RPCArray) return 0; RPCArrayContainer *a = this->CastArray(); return a->size(); } RPCValue *GetObject(const std::string &key) { if (type != RPCObject) return NULL; RPCObjectContainer *o = this->CastObject(); RPCObjectContainer::iterator it = o->find(key); if (it == o->end()) return NULL; return it->second; } std::pair GetObjectIterator() throw() { if (type != RPCObject) throw std::runtime_error("Cannot get iterator for a non-object RPC value"); RPCObjectContainer *o = this->CastObject(); return std::make_pair(o->begin(), o->end()); } std::string GetString() { if (type != RPCString) return std::string(); return *this->CastString(); } double GetInt() { if (type != RPCInteger) return 0; return *this->CastInteger(); } bool GetBool() { if (type != RPCBoolean) return 0; return (value != NULL); } }; class RPCRequest : public classbase { protected: public: std::string method; RPCValue *parameters; RPCValue *result; std::string provider; bool claimed; std::string error; RPCRequest(const std::string &provider, const std::string &method, RPCValue *parameters) : method(method), parameters(parameters), provider(provider), claimed(false) { result = new RPCValue(); } ~RPCRequest() { if (result) delete result; } }; #endif