From 1607af4e867357f991f317f4471e7b708a3b4dd7 Mon Sep 17 00:00:00 2001 From: yann300 Date: Mon, 20 Jul 2015 18:05:02 +0200 Subject: [PATCH] arrays decoding --- mix/ContractCallDataEncoder.cpp | 68 ++++++++++++++++++++++++++++++--- mix/ContractCallDataEncoder.h | 4 ++ 2 files changed, 66 insertions(+), 6 deletions(-) diff --git a/mix/ContractCallDataEncoder.cpp b/mix/ContractCallDataEncoder.cpp index da21869e4..ff858efbf 100644 --- a/mix/ContractCallDataEncoder.cpp +++ b/mix/ContractCallDataEncoder.cpp @@ -237,6 +237,48 @@ QString ContractCallDataEncoder::toChar(dev::bytes const& _b) return str; } +QJsonValue ContractCallDataEncoder::decodeArrayContent(SolidityType const& _type, bytes const& _value, int& pos) +{ + if (_type.baseType->array) + { + QJsonArray sub = decodeArray(*_type.baseType, _value, pos); + if (_type.baseType->dynamicSize) + pos = pos + 32; + return sub; + } + else + { + bytesConstRef value(_value.data() + pos, 32); + bytes rawParam(32); + value.populate(&rawParam); + QVariant i = decode(*_type.baseType, rawParam); + pos = pos + 32; + return i.toString(); + } +} + +QJsonArray ContractCallDataEncoder::decodeArray(SolidityType const& _type, bytes const& _value, int& pos) +{ + QJsonArray array; + bytesConstRef value(&_value); + int count = 0; + if (!_type.dynamicSize) + count = _type.count; + else + { + bytesConstRef value(_value.data() + pos, 32); // offset + bytes rawParam(32); + value.populate(&rawParam); + bigint offset = decodeInt(rawParam); + pos = static_cast(offset) + 32; + value = bytesConstRef(_value.data() + static_cast(offset), 32); // offset + value.populate(&rawParam); + count = static_cast(decodeInt(rawParam)); + } + for (int k = 0; k < count; ++k) + array.append(decodeArrayContent(_type, _value, pos)); + return array; +} QVariant ContractCallDataEncoder::decode(SolidityType const& _type, bytes const& _value) { @@ -268,17 +310,31 @@ QString ContractCallDataEncoder::decode(QVariableDeclaration* const& _param, byt QStringList ContractCallDataEncoder::decode(QList const& _returnParameters, bytes _value) { - bytesConstRef value(&_value); - bytes rawParam(32); + bytes _v = _value; QStringList r; - + int readPosition = 0; for (int k = 0; k <_returnParameters.length(); k++) { - value.populate(&rawParam); - value = value.cropped(32); QVariableDeclaration* dec = static_cast(_returnParameters.at(k)); SolidityType const& type = dec->type()->type(); - r.append(decode(type, rawParam).toString()); + if (type.array) + { + QJsonArray array = decodeArray(type, _v, readPosition); + QJsonDocument jsonDoc = QJsonDocument::fromVariant(array.toVariantList()); + r.append(jsonDoc.toJson(QJsonDocument::Compact)); + if (type.dynamicSize) + readPosition++; + else + readPosition = type.count; + } + else + { + bytesConstRef value(_value.data() + (readPosition * 32), 32); + bytes rawParam(32); + value.populate(&rawParam); + r.append(decode(type, rawParam).toString()); + readPosition++; + } } return r; } diff --git a/mix/ContractCallDataEncoder.h b/mix/ContractCallDataEncoder.h index be11a5772..8eb1569e4 100644 --- a/mix/ContractCallDataEncoder.h +++ b/mix/ContractCallDataEncoder.h @@ -60,6 +60,10 @@ public: dev::bytes encodeBytes(QString const& _str); /// Decode bytes from ABI dev::bytes decodeBytes(dev::bytes const& _rawValue); + /// Decode array + QJsonArray decodeArray(SolidityType const& _type, bytes const& _value, int& pos); + /// Decode array items + QJsonValue decodeArrayContent(SolidityType const& _type, bytes const& _value, int& pos); private: unsigned encodeSingleItem(QString const& _data, SolidityType const& _type, bytes& _dest);