From c4275c6d806e4e3e5148c247e3ffe4215908e8ff Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Mon, 1 Oct 2012 08:32:23 -0700 Subject: [PATCH] More work on the JSON conversion code. --- src/FieldNames.cpp | 13 ++++ src/FieldNames.h | 1 + src/LedgerFormats.cpp | 4 +- src/SerializedObject.cpp | 126 ++++++++++++++++++++++++++++++++++++++- src/SerializedObject.h | 5 +- src/SerializedTypes.h | 28 ++++----- 6 files changed, 157 insertions(+), 20 deletions(-) diff --git a/src/FieldNames.cpp b/src/FieldNames.cpp index e6af94ad26..612d250c97 100644 --- a/src/FieldNames.cpp +++ b/src/FieldNames.cpp @@ -5,6 +5,7 @@ #include #include +#include // These must stay at the top of this file @@ -82,3 +83,15 @@ std::string SField::getName() const return boost::lexical_cast(static_cast(fieldType)) + "/" + boost::lexical_cast(fieldValue); } + +SField::ref SField::getField(const std::string& fieldName) +{ // OPTIMIZEME me with a map. CHECKME this is case sensitive + boost::mutex::scoped_lock sl(mapMutex); + typedef std::pair int_sfref_pair; + BOOST_FOREACH(const int_sfref_pair& fieldPair, codeToField) + { + if (fieldPair.second->fieldName == fieldName) + return *(fieldPair.second); + } + return sfInvalid; +} diff --git a/src/FieldNames.h b/src/FieldNames.h index 4d966c547c..ed51006499 100644 --- a/src/FieldNames.h +++ b/src/FieldNames.h @@ -58,6 +58,7 @@ public: static SField::ref getField(int fieldCode); static SField::ref getField(int fieldType, int fieldValue); + static SField::ref getField(const std::string& fieldName); static SField::ref getField(SerializedTypeID type, int value) { return getField(FIELD_CODE(type, value)); } std::string getName() const; diff --git a/src/LedgerFormats.cpp b/src/LedgerFormats.cpp index 84aaf73d14..bc4ab86ed1 100644 --- a/src/LedgerFormats.cpp +++ b/src/LedgerFormats.cpp @@ -2,9 +2,9 @@ #include "LedgerFormats.h" #define LEF_BASE \ + { sfLedgerIndex, SOE_OPTIONAL }, \ { sfLedgerEntryType, SOE_REQUIRED }, \ - { sfFlags, SOE_REQUIRED }, \ - { sfLedgerIndex, SOE_OPTIONAL }, + { sfFlags, SOE_REQUIRED }, LedgerEntryFormat LedgerFormats[]= { diff --git a/src/SerializedObject.cpp b/src/SerializedObject.cpp index af7ac0c47b..0bfab6c928 100644 --- a/src/SerializedObject.cpp +++ b/src/SerializedObject.cpp @@ -429,6 +429,20 @@ void STObject::makeFieldAbsent(SField::ref field) mData.replace(index, makeDefaultObject(f.getFName())); } +bool STObject::delField(SField::ref field) +{ + int index = getFieldIndex(field); + if (index == -1) + return false; + delField(index); + return true; +} + +void STObject::delField(int index) +{ + mData.erase(mData.begin() + index); +} + std::string STObject::getFieldString(SField::ref field) const { const SerializedType* rf = peekAtPField(field); @@ -777,18 +791,126 @@ STArray* STArray::construct(SerializerIterator& sit, SField::ref field) return new STArray(field, value); } -STObject::STObject(const Json::Value& object, SField::ref name) : SerializedType(name) +std::auto_ptr STObject::parseJson(const Json::Value& object, SField::ref name, int depth) { if (!object.isObject()) throw std::runtime_error("Value is not an object"); + boost::ptr_vector data; Json::Value::Members members(object.getMemberNames()); for (Json::Value::Members::iterator it = members.begin(), end = members.end(); it != end; ++it) { const std::string& name = *it; const Json::Value& value = object[name]; - // WRITEME + + SField::ref field = SField::getField(name); + if (field == sfInvalid) + throw std::runtime_error("Unknown field: " + name); + + switch (field.fieldType) + { + case STI_UINT8: + if (value.isString()) + data.push_back(new STUInt8(field, boost::lexical_cast(value.asString()))); + else if (value.isInt()) + data.push_back(new STUInt8(field, boost::lexical_cast(value.asInt()))); + else if (value.isUInt()) + data.push_back(new STUInt8(field, boost::lexical_cast(value.asUInt()))); + else + throw std::runtime_error("Incorrect type"); + break; + + case STI_UINT16: + if (value.isString()) + { + std::string strValue = value.asString(); + if (!strValue.empty() && (strValue[0]<'0' || strValue[0]>'9')) + { + if (field == sfTransactionType) + { + // WRITEME + } + else if (field == sfLedgerEntryType) + { + // WRITEME + } + else + throw std::runtime_error("Invalid field data"); + } + data.push_back(new STUInt16(field, boost::lexical_cast(strValue))); + } + else if (value.isInt()) + data.push_back(new STUInt16(field, boost::lexical_cast(value.asInt()))); + else if (value.isUInt()) + data.push_back(new STUInt16(field, boost::lexical_cast(value.asUInt()))); + else + throw std::runtime_error("Incorrect type"); + break; + + case STI_UINT32: + if (value.isString()) + data.push_back(new STUInt32(field, boost::lexical_cast(value.asString()))); + else if (value.isInt()) + data.push_back(new STUInt32(field, boost::lexical_cast(value.asInt()))); + else if (value.isUInt()) + data.push_back(new STUInt32(field, boost::lexical_cast(value.asUInt()))); + else + throw std::runtime_error("Incorrect type"); + break; + + case STI_UINT64: + if (value.isString()) + data.push_back(new STUInt64(field, boost::lexical_cast(value.asString()))); + else if (value.isInt()) + data.push_back(new STUInt64(field, boost::lexical_cast(value.asInt()))); + else if (value.isUInt()) + data.push_back(new STUInt64(field, boost::lexical_cast(value.asUInt()))); + else + throw std::runtime_error("Incorrect type"); + break; + + + case STI_HASH128: + // WRITEME + + case STI_HASH160: + // WRITEME + + case STI_HASH256: + // WRITEME + + case STI_VL: + // WRITEME + + case STI_AMOUNT: + // WRITEME + + case STI_VECTOR256: + // WRITEME + + case STI_PATHSET: + // WRITEME + + case STI_OBJECT: + case STI_ACCOUNT: + case STI_TRANSACTION: + case STI_LEDGERENTRY: + case STI_VALIDATION: + if (!value.isObject()) + throw std::runtime_error("Inner value is not an object"); + if (depth > 64) + throw std::runtime_error("Json nest depth exceeded"); + data.push_back(parseJson(value, field, depth + 1)); + break; + + case STI_ARRAY: + // WRITEME + + default: + throw std::runtime_error("Invalid field type"); + } } + return std::auto_ptr(new STObject(name, data)); } #if 0 diff --git a/src/SerializedObject.h b/src/SerializedObject.h index bfcc7c090c..58a926d983 100644 --- a/src/SerializedObject.h +++ b/src/SerializedObject.h @@ -28,6 +28,7 @@ protected: std::vector mType; STObject* duplicate() const { return new STObject(*this); } + STObject(SField::ref name, boost::ptr_vector& data) : SerializedType(name) { mData.swap(data); } public: STObject() { ; } @@ -40,7 +41,7 @@ public: STObject(SOElement::ptrList type, SerializerIterator& sit, SField::ref name) : SerializedType(name) { set(sit); setType(type); } - STObject(const Json::Value& value, SField::ref name); + static std::auto_ptr parseJson(const Json::Value& value, SField::ref name, int depth = 0); virtual ~STObject() { ; } @@ -127,6 +128,8 @@ public: bool isFieldPresent(SField::ref field) const; SerializedType* makeFieldPresent(SField::ref field); void makeFieldAbsent(SField::ref field); + bool delField(SField::ref field); + void delField(int index); static std::auto_ptr makeDefaultObject(SerializedTypeID id, SField::ref name); static std::auto_ptr makeDeserializedObject(SerializedTypeID id, SField::ref name, diff --git a/src/SerializedTypes.h b/src/SerializedTypes.h index 33706ae456..de1fb75eb6 100644 --- a/src/SerializedTypes.h +++ b/src/SerializedTypes.h @@ -91,7 +91,7 @@ protected: public: STUInt8(unsigned char v = 0) : value(v) { ; } - STUInt8(SField::ref n, unsigned char v=0) : SerializedType(n), value(v) { ; } + STUInt8(SField::ref n, unsigned char v = 0) : SerializedType(n), value(v) { ; } static std::auto_ptr deserialize(SerializerIterator& sit, SField::ref name) { return std::auto_ptr(construct(sit, name)); } @@ -116,8 +116,8 @@ protected: public: - STUInt16(uint16 v=0) : value(v) { ; } - STUInt16(SField::ref n, uint16 v=0) : SerializedType(n), value(v) { ; } + STUInt16(uint16 v = 0) : value(v) { ; } + STUInt16(SField::ref n, uint16 v = 0) : SerializedType(n), value(v) { ; } static std::auto_ptr deserialize(SerializerIterator& sit, SField::ref name) { return std::auto_ptr(construct(sit, name)); } @@ -143,7 +143,7 @@ protected: public: STUInt32(uint32 v = 0) : value(v) { ; } - STUInt32(SField::ref n, uint32 v=0) : SerializedType(n), value(v) { ; } + STUInt32(SField::ref n, uint32 v = 0) : SerializedType(n), value(v) { ; } static std::auto_ptr deserialize(SerializerIterator& sit, SField::ref name) { return std::auto_ptr(construct(sit, name)); } @@ -168,8 +168,8 @@ protected: public: - STUInt64(uint64 v=0) : value(v) { ; } - STUInt64(SField::ref n, uint64 v=0) : SerializedType(n), value(v) { ; } + STUInt64(uint64 v = 0) : value(v) { ; } + STUInt64(SField::ref n, uint64 v = 0) : SerializedType(n), value(v) { ; } static std::auto_ptr deserialize(SerializerIterator& sit, SField::ref name) { return std::auto_ptr(construct(sit, name)); } @@ -225,6 +225,8 @@ protected: : SerializedType(name), mCurrency(cur), mIssuer(iss), mValue(val), mOffset(off), mIsNative(isNat), mIsNegative(isNeg) { ; } + STAmount(SField::ref name, const Json::Value& value); + uint64 toUInt64() const; static uint64 muldiv(uint64, uint64, uint64); @@ -232,13 +234,13 @@ public: static uint64 uRateOne; STAmount(uint64 v = 0, bool isNeg = false) : mValue(v), mOffset(0), mIsNative(true), mIsNegative(isNeg) - { if (v==0) mIsNegative = false; } + { if (v == 0) mIsNegative = false; } STAmount(SField::ref n, uint64 v = 0) : SerializedType(n), mValue(v), mOffset(0), mIsNative(true), mIsNegative(false) { ; } - STAmount(const uint160& uCurrencyID, const uint160& uIssuerID, uint64 uV=0, int iOff=0, bool bNegative=false) + STAmount(const uint160& uCurrencyID, const uint160& uIssuerID, uint64 uV = 0, int iOff = 0, bool bNegative = false) : mCurrency(uCurrencyID), mIssuer(uIssuerID), mValue(uV), mOffset(iOff), mIsNegative(bNegative) { canonicalize(); } @@ -254,14 +256,10 @@ public: { return std::auto_ptr(construct(sit, name)); } static STAmount saFromRate(uint64 uRate = 0) - { - return STAmount(CURRENCY_ONE, ACCOUNT_ONE, uRate, -9, false); - } + { return STAmount(CURRENCY_ONE, ACCOUNT_ONE, uRate, -9, false); } - static STAmount saFromSigned(const uint160& uCurrencyID, const uint160& uIssuerID, int64 iV=0, int iOff=0) - { - return STAmount(uCurrencyID, uIssuerID, iV < 0 ? -iV : iV, iOff, iV < 0); - } + static STAmount saFromSigned(const uint160& uCurrencyID, const uint160& uIssuerID, int64 iV = 0, int iOff = 0) + { return STAmount(uCurrencyID, uIssuerID, iV < 0 ? -iV : iV, iOff, iV < 0); } SerializedTypeID getSType() const { return STI_AMOUNT; } std::string getText() const;