subtly
10 years ago
61 changed files with 2071 additions and 988 deletions
Before Width: | Height: | Size: 171 KiB |
After Width: | Height: | Size: 14 KiB |
After Width: | Height: | Size: 34 KiB |
@ -0,0 +1,427 @@ |
|||||
|
/*
|
||||
|
This file is part of cpp-ethereum. |
||||
|
|
||||
|
cpp-ethereum is free software: you can redistribute it and/or modify |
||||
|
it under the terms of the GNU General Public License as published by |
||||
|
the Free Software Foundation, either version 3 of the License, or |
||||
|
(at your option) any later version. |
||||
|
|
||||
|
cpp-ethereum is distributed in the hope that it will be useful, |
||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
|
GNU General Public License for more details. |
||||
|
|
||||
|
You should have received a copy of the GNU General Public License |
||||
|
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
*/ |
||||
|
/** @file JsonHelper.cpp
|
||||
|
* @authors: |
||||
|
* Gav Wood <i@gavwood.com> |
||||
|
* @date 2014 |
||||
|
*/ |
||||
|
|
||||
|
#include "JsonHelper.h" |
||||
|
|
||||
|
#include <libevmcore/Instruction.h> |
||||
|
#include <liblll/Compiler.h> |
||||
|
#include <libethereum/Client.h> |
||||
|
#include <libwebthree/WebThree.h> |
||||
|
#include <libethcore/CommonJS.h> |
||||
|
#include <libwhisper/Message.h> |
||||
|
#include <libwhisper/WhisperHost.h> |
||||
|
using namespace std; |
||||
|
using namespace dev; |
||||
|
using namespace eth; |
||||
|
|
||||
|
namespace dev |
||||
|
{ |
||||
|
|
||||
|
Json::Value toJson(unordered_map<u256, u256> const& _storage) |
||||
|
{ |
||||
|
Json::Value res(Json::objectValue); |
||||
|
for (auto i: _storage) |
||||
|
res[toJS(i.first)] = toJS(i.second); |
||||
|
return res; |
||||
|
} |
||||
|
|
||||
|
Json::Value toJson(map<u256, u256> const& _storage) |
||||
|
{ |
||||
|
Json::Value res(Json::objectValue); |
||||
|
for (auto i: _storage) |
||||
|
res[toJS(i.first)] = toJS(i.second); |
||||
|
return res; |
||||
|
} |
||||
|
|
||||
|
// ////////////////////////////////////////////////////////////////////////////////
|
||||
|
// p2p
|
||||
|
// ////////////////////////////////////////////////////////////////////////////////
|
||||
|
namespace p2p |
||||
|
{ |
||||
|
|
||||
|
Json::Value toJson(p2p::PeerSessionInfo const& _p) |
||||
|
{ |
||||
|
Json::Value ret; |
||||
|
ret["id"] = _p.id.hex(); |
||||
|
ret["clientVersion"] = _p.clientVersion; |
||||
|
ret["host"] = _p.host; |
||||
|
ret["port"] = _p.port; |
||||
|
ret["lastPing"] = (int)chrono::duration_cast<chrono::milliseconds>(_p.lastPing).count(); |
||||
|
for (auto const& i: _p.notes) |
||||
|
ret["notes"][i.first] = i.second; |
||||
|
for (auto const& i: _p.caps) |
||||
|
ret["caps"][i.first] = (unsigned)i.second; |
||||
|
return ret; |
||||
|
} |
||||
|
|
||||
|
} |
||||
|
|
||||
|
// ////////////////////////////////////////////////////////////////////////////////
|
||||
|
// eth
|
||||
|
// ////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
||||
|
namespace eth |
||||
|
{ |
||||
|
|
||||
|
Json::Value toJson(dev::eth::BlockInfo const& _bi) |
||||
|
{ |
||||
|
Json::Value res; |
||||
|
if (_bi) |
||||
|
{ |
||||
|
res["hash"] = toJS(_bi.hash()); |
||||
|
res["parentHash"] = toJS(_bi.parentHash); |
||||
|
res["sha3Uncles"] = toJS(_bi.sha3Uncles); |
||||
|
res["miner"] = toJS(_bi.coinbaseAddress); |
||||
|
res["stateRoot"] = toJS(_bi.stateRoot); |
||||
|
res["transactionsRoot"] = toJS(_bi.transactionsRoot); |
||||
|
res["difficulty"] = toJS(_bi.difficulty); |
||||
|
res["number"] = toJS(_bi.number); |
||||
|
res["gasUsed"] = toJS(_bi.gasUsed); |
||||
|
res["gasLimit"] = toJS(_bi.gasLimit); |
||||
|
res["timestamp"] = toJS(_bi.timestamp); |
||||
|
res["extraData"] = toJS(_bi.extraData); |
||||
|
res["nonce"] = toJS(_bi.nonce); |
||||
|
res["logsBloom"] = toJS(_bi.logBloom); |
||||
|
|
||||
|
res["seedHash"] = toJS(_bi.seedHash()); |
||||
|
res["target"] = toJS(_bi.boundary()); |
||||
|
} |
||||
|
return res; |
||||
|
} |
||||
|
|
||||
|
Json::Value toJson(dev::eth::Transaction const& _t, std::pair<h256, unsigned> _location, BlockNumber _blockNumber) |
||||
|
{ |
||||
|
Json::Value res; |
||||
|
if (_t) |
||||
|
{ |
||||
|
res["hash"] = toJS(_t.sha3()); |
||||
|
res["input"] = toJS(_t.data()); |
||||
|
res["to"] = _t.isCreation() ? Json::Value() : toJS(_t.receiveAddress()); |
||||
|
res["from"] = toJS(_t.safeSender()); |
||||
|
res["gas"] = toJS(_t.gas()); |
||||
|
res["gasPrice"] = toJS(_t.gasPrice()); |
||||
|
res["nonce"] = toJS(_t.nonce()); |
||||
|
res["value"] = toJS(_t.value()); |
||||
|
res["blockHash"] = toJS(_location.first); |
||||
|
res["transactionIndex"] = toJS(_location.second); |
||||
|
res["blockNumber"] = toJS(_blockNumber); |
||||
|
} |
||||
|
return res; |
||||
|
} |
||||
|
|
||||
|
Json::Value toJson(dev::eth::BlockInfo const& _bi, BlockDetails const& _bd, UncleHashes const& _us, Transactions const& _ts) |
||||
|
{ |
||||
|
Json::Value res = toJson(_bi); |
||||
|
if (_bi) |
||||
|
{ |
||||
|
res["totalDifficulty"] = toJS(_bd.totalDifficulty); |
||||
|
res["uncles"] = Json::Value(Json::arrayValue); |
||||
|
for (h256 h: _us) |
||||
|
res["uncles"].append(toJS(h)); |
||||
|
res["transactions"] = Json::Value(Json::arrayValue); |
||||
|
for (unsigned i = 0; i < _ts.size(); i++) |
||||
|
res["transactions"].append(toJson(_ts[i], std::make_pair(_bi.hash(), i), (BlockNumber)_bi.number)); |
||||
|
} |
||||
|
return res; |
||||
|
} |
||||
|
|
||||
|
Json::Value toJson(dev::eth::BlockInfo const& _bi, BlockDetails const& _bd, UncleHashes const& _us, TransactionHashes const& _ts) |
||||
|
{ |
||||
|
Json::Value res = toJson(_bi); |
||||
|
if (_bi) |
||||
|
{ |
||||
|
res["totalDifficulty"] = toJS(_bd.totalDifficulty); |
||||
|
res["uncles"] = Json::Value(Json::arrayValue); |
||||
|
for (h256 h: _us) |
||||
|
res["uncles"].append(toJS(h)); |
||||
|
res["transactions"] = Json::Value(Json::arrayValue); |
||||
|
for (h256 const& t: _ts) |
||||
|
res["transactions"].append(toJS(t)); |
||||
|
} |
||||
|
return res; |
||||
|
} |
||||
|
|
||||
|
Json::Value toJson(dev::eth::TransactionSkeleton const& _t) |
||||
|
{ |
||||
|
Json::Value res; |
||||
|
res["to"] = _t.creation ? Json::Value() : toJS(_t.to); |
||||
|
res["from"] = toJS(_t.from); |
||||
|
res["gas"] = toJS(_t.gas); |
||||
|
res["gasPrice"] = toJS(_t.gasPrice); |
||||
|
res["value"] = toJS(_t.value); |
||||
|
res["data"] = toJS(_t.data, 32); |
||||
|
return res; |
||||
|
} |
||||
|
|
||||
|
Json::Value toJson(dev::eth::TransactionReceipt const& _t) |
||||
|
{ |
||||
|
Json::Value res; |
||||
|
res["stateRoot"] = toJS(_t.stateRoot()); |
||||
|
res["gasUsed"] = toJS(_t.gasUsed()); |
||||
|
res["bloom"] = toJS(_t.bloom()); |
||||
|
res["log"] = dev::toJson(_t.log()); |
||||
|
return res; |
||||
|
} |
||||
|
|
||||
|
Json::Value toJson(dev::eth::Transaction const& _t) |
||||
|
{ |
||||
|
Json::Value res; |
||||
|
res["to"] = _t.isCreation() ? Json::Value() : toJS(_t.to()); |
||||
|
res["from"] = toJS(_t.from()); |
||||
|
res["gas"] = toJS(_t.gas()); |
||||
|
res["gasPrice"] = toJS(_t.gasPrice()); |
||||
|
res["value"] = toJS(_t.value()); |
||||
|
res["data"] = toJS(_t.data(), 32); |
||||
|
res["nonce"] = toJS(_t.nonce()); |
||||
|
res["hash"] = toJS(_t.sha3(WithSignature)); |
||||
|
res["sighash"] = toJS(_t.sha3(WithoutSignature)); |
||||
|
res["r"] = toJS(_t.signature().r); |
||||
|
res["s"] = toJS(_t.signature().s); |
||||
|
res["v"] = toJS(_t.signature().v); |
||||
|
return res; |
||||
|
} |
||||
|
|
||||
|
Json::Value toJson(dev::eth::LocalisedLogEntry const& _e) |
||||
|
{ |
||||
|
Json::Value res; |
||||
|
|
||||
|
if (_e.isSpecial) |
||||
|
res = toJS(_e.special); |
||||
|
else |
||||
|
{ |
||||
|
res = toJson(static_cast<dev::eth::LogEntry const&>(_e)); |
||||
|
if (_e.mined) |
||||
|
{ |
||||
|
res["type"] = "mined"; |
||||
|
res["blockNumber"] = _e.blockNumber; |
||||
|
res["blockHash"] = toJS(_e.blockHash); |
||||
|
res["logIndex"] = _e.logIndex; |
||||
|
res["transactionHash"] = toJS(_e.transactionHash); |
||||
|
res["transactionIndex"] = _e.transactionIndex; |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
res["type"] = "pending"; |
||||
|
res["blockNumber"] = Json::Value(Json::nullValue); |
||||
|
res["blockHash"] = Json::Value(Json::nullValue); |
||||
|
res["logIndex"] = Json::Value(Json::nullValue); |
||||
|
res["transactionHash"] = Json::Value(Json::nullValue); |
||||
|
res["transactionIndex"] = Json::Value(Json::nullValue); |
||||
|
} |
||||
|
} |
||||
|
return res; |
||||
|
} |
||||
|
|
||||
|
Json::Value toJson(dev::eth::LogEntry const& _e) |
||||
|
{ |
||||
|
Json::Value res; |
||||
|
res["data"] = toJS(_e.data); |
||||
|
res["address"] = toJS(_e.address); |
||||
|
res["topics"] = Json::Value(Json::arrayValue); |
||||
|
for (auto const& t: _e.topics) |
||||
|
res["topics"].append(toJS(t)); |
||||
|
return res; |
||||
|
} |
||||
|
|
||||
|
TransactionSkeleton toTransactionSkeleton(Json::Value const& _json) |
||||
|
{ |
||||
|
TransactionSkeleton ret; |
||||
|
if (!_json.isObject() || _json.empty()) |
||||
|
return ret; |
||||
|
|
||||
|
if (!_json["from"].empty()) |
||||
|
ret.from = jsToAddress(_json["from"].asString()); |
||||
|
if (!_json["to"].empty() && _json["to"].asString() != "0x") |
||||
|
ret.to = jsToAddress(_json["to"].asString()); |
||||
|
else |
||||
|
ret.creation = true; |
||||
|
|
||||
|
if (!_json["value"].empty()) |
||||
|
ret.value = jsToU256(_json["value"].asString()); |
||||
|
|
||||
|
if (!_json["gas"].empty()) |
||||
|
ret.gas = jsToU256(_json["gas"].asString()); |
||||
|
|
||||
|
if (!_json["gasPrice"].empty()) |
||||
|
ret.gasPrice = jsToU256(_json["gasPrice"].asString()); |
||||
|
|
||||
|
if (!_json["data"].empty()) // ethereum.js has preconstructed the data array
|
||||
|
ret.data = jsToBytes(_json["data"].asString()); |
||||
|
|
||||
|
if (!_json["code"].empty()) |
||||
|
ret.data = jsToBytes(_json["code"].asString()); |
||||
|
return ret; |
||||
|
} |
||||
|
|
||||
|
dev::eth::LogFilter toLogFilter(Json::Value const& _json) |
||||
|
{ |
||||
|
dev::eth::LogFilter filter; |
||||
|
if (!_json.isObject() || _json.empty()) |
||||
|
return filter; |
||||
|
|
||||
|
// check only !empty. it should throw exceptions if input params are incorrect
|
||||
|
if (!_json["fromBlock"].empty()) |
||||
|
filter.withEarliest(jsToFixed<32>(_json["fromBlock"].asString())); |
||||
|
if (!_json["toBlock"].empty()) |
||||
|
filter.withLatest(jsToFixed<32>(_json["toBlock"].asString())); |
||||
|
if (!_json["address"].empty()) |
||||
|
{ |
||||
|
if (_json["address"].isArray()) |
||||
|
for (auto i : _json["address"]) |
||||
|
filter.address(jsToAddress(i.asString())); |
||||
|
else |
||||
|
filter.address(jsToAddress(_json["address"].asString())); |
||||
|
} |
||||
|
if (!_json["topics"].empty()) |
||||
|
for (unsigned i = 0; i < _json["topics"].size(); i++) |
||||
|
{ |
||||
|
if (_json["topics"][i].isArray()) |
||||
|
{ |
||||
|
for (auto t: _json["topics"][i]) |
||||
|
if (!t.isNull()) |
||||
|
filter.topic(i, jsToFixed<32>(t.asString())); |
||||
|
} |
||||
|
else if (!_json["topics"][i].isNull()) // if it is anything else then string, it should and will fail
|
||||
|
filter.topic(i, jsToFixed<32>(_json["topics"][i].asString())); |
||||
|
} |
||||
|
return filter; |
||||
|
} |
||||
|
|
||||
|
// TODO: this should be removed once we decide to remove backward compatibility with old log filters
|
||||
|
dev::eth::LogFilter toLogFilter(Json::Value const& _json, Interface const& _client) // commented to avoid warning. Uncomment once in use @ PoC-7.
|
||||
|
{ |
||||
|
dev::eth::LogFilter filter; |
||||
|
if (!_json.isObject() || _json.empty()) |
||||
|
return filter; |
||||
|
|
||||
|
// check only !empty. it should throw exceptions if input params are incorrect
|
||||
|
if (!_json["fromBlock"].empty()) |
||||
|
filter.withEarliest(_client.hashFromNumber(jsToBlockNumber(_json["fromBlock"].asString()))); |
||||
|
if (!_json["toBlock"].empty()) |
||||
|
filter.withLatest(_client.hashFromNumber(jsToBlockNumber(_json["toBlock"].asString()))); |
||||
|
if (!_json["address"].empty()) |
||||
|
{ |
||||
|
if (_json["address"].isArray()) |
||||
|
for (auto i : _json["address"]) |
||||
|
filter.address(jsToAddress(i.asString())); |
||||
|
else |
||||
|
filter.address(jsToAddress(_json["address"].asString())); |
||||
|
} |
||||
|
if (!_json["topics"].empty()) |
||||
|
for (unsigned i = 0; i < _json["topics"].size(); i++) |
||||
|
{ |
||||
|
if (_json["topics"][i].isArray()) |
||||
|
{ |
||||
|
for (auto t: _json["topics"][i]) |
||||
|
if (!t.isNull()) |
||||
|
filter.topic(i, jsToFixed<32>(t.asString())); |
||||
|
} |
||||
|
else if (!_json["topics"][i].isNull()) // if it is anything else then string, it should and will fail
|
||||
|
filter.topic(i, jsToFixed<32>(_json["topics"][i].asString())); |
||||
|
} |
||||
|
return filter; |
||||
|
} |
||||
|
|
||||
|
} |
||||
|
|
||||
|
// ////////////////////////////////////////////////////////////////////////////////////
|
||||
|
// shh
|
||||
|
// ////////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
||||
|
namespace shh |
||||
|
{ |
||||
|
|
||||
|
Json::Value toJson(h256 const& _h, shh::Envelope const& _e, shh::Message const& _m) |
||||
|
{ |
||||
|
Json::Value res; |
||||
|
res["hash"] = toJS(_h); |
||||
|
res["expiry"] = toJS(_e.expiry()); |
||||
|
res["sent"] = toJS(_e.sent()); |
||||
|
res["ttl"] = toJS(_e.ttl()); |
||||
|
res["workProved"] = toJS(_e.workProved()); |
||||
|
res["topics"] = Json::Value(Json::arrayValue); |
||||
|
for (auto const& t: _e.topic()) |
||||
|
res["topics"].append(toJS(t)); |
||||
|
res["payload"] = toJS(_m.payload()); |
||||
|
res["from"] = toJS(_m.from()); |
||||
|
res["to"] = toJS(_m.to()); |
||||
|
return res; |
||||
|
} |
||||
|
|
||||
|
shh::Message toMessage(Json::Value const& _json) |
||||
|
{ |
||||
|
shh::Message ret; |
||||
|
if (!_json["from"].empty()) |
||||
|
ret.setFrom(jsToPublic(_json["from"].asString())); |
||||
|
if (!_json["to"].empty()) |
||||
|
ret.setTo(jsToPublic(_json["to"].asString())); |
||||
|
if (!_json["payload"].empty()) |
||||
|
ret.setPayload(jsToBytes(_json["payload"].asString())); |
||||
|
return ret; |
||||
|
} |
||||
|
|
||||
|
shh::Envelope toSealed(Json::Value const& _json, shh::Message const& _m, Secret _from) |
||||
|
{ |
||||
|
unsigned ttl = 50; |
||||
|
unsigned workToProve = 50; |
||||
|
shh::BuildTopic bt; |
||||
|
|
||||
|
if (!_json["ttl"].empty()) |
||||
|
ttl = jsToInt(_json["ttl"].asString()); |
||||
|
|
||||
|
if (!_json["workToProve"].empty()) |
||||
|
workToProve = jsToInt(_json["workToProve"].asString()); |
||||
|
|
||||
|
if (!_json["topics"].empty()) |
||||
|
for (auto i: _json["topics"]) |
||||
|
{ |
||||
|
if (i.isArray()) |
||||
|
{ |
||||
|
for (auto j: i) |
||||
|
if (!j.isNull()) |
||||
|
bt.shift(jsToBytes(j.asString())); |
||||
|
} |
||||
|
else if (!i.isNull()) // if it is anything else then string, it should and will fail
|
||||
|
bt.shift(jsToBytes(i.asString())); |
||||
|
} |
||||
|
|
||||
|
return _m.seal(_from, bt, ttl, workToProve); |
||||
|
} |
||||
|
|
||||
|
pair<shh::Topics, Public> toWatch(Json::Value const& _json) |
||||
|
{ |
||||
|
shh::BuildTopic bt; |
||||
|
Public to; |
||||
|
|
||||
|
if (!_json["to"].empty()) |
||||
|
to = jsToPublic(_json["to"].asString()); |
||||
|
|
||||
|
if (!_json["topics"].empty()) |
||||
|
for (auto i: _json["topics"]) |
||||
|
bt.shift(jsToBytes(i.asString())); |
||||
|
|
||||
|
return make_pair(bt, to); |
||||
|
} |
||||
|
|
||||
|
} |
||||
|
|
||||
|
} |
@ -0,0 +1,104 @@ |
|||||
|
/*
|
||||
|
This file is part of cpp-ethereum. |
||||
|
|
||||
|
cpp-ethereum is free software: you can redistribute it and/or modify |
||||
|
it under the terms of the GNU General Public License as published by |
||||
|
the Free Software Foundation, either version 3 of the License, or |
||||
|
(at your option) any later version. |
||||
|
|
||||
|
cpp-ethereum is distributed in the hope that it will be useful, |
||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
|
GNU General Public License for more details. |
||||
|
|
||||
|
You should have received a copy of the GNU General Public License |
||||
|
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
*/ |
||||
|
/** @file JsonHelper.h
|
||||
|
* @authors: |
||||
|
* Gav Wood <i@gavwood.com> |
||||
|
* @date 2015 |
||||
|
*/ |
||||
|
#pragma once |
||||
|
|
||||
|
#include <json/json.h> |
||||
|
#include <libethcore/Common.h> |
||||
|
#include <libethereum/LogFilter.h> |
||||
|
#include <libwhisper/Message.h> |
||||
|
|
||||
|
namespace dev |
||||
|
{ |
||||
|
|
||||
|
Json::Value toJson(std::map<u256, u256> const& _storage); |
||||
|
Json::Value toJson(std::unordered_map<u256, u256> const& _storage); |
||||
|
|
||||
|
namespace p2p |
||||
|
{ |
||||
|
|
||||
|
Json::Value toJson(PeerSessionInfo const& _p); |
||||
|
|
||||
|
} |
||||
|
|
||||
|
namespace eth |
||||
|
{ |
||||
|
|
||||
|
class Transaction; |
||||
|
class BlockDetails; |
||||
|
class Interface; |
||||
|
using Transactions = std::vector<Transaction>; |
||||
|
using UncleHashes = h256s; |
||||
|
using TransactionHashes = h256s; |
||||
|
|
||||
|
Json::Value toJson(BlockInfo const& _bi); |
||||
|
Json::Value toJson(Transaction const& _t, std::pair<h256, unsigned> _location, BlockNumber _blockNumber); |
||||
|
Json::Value toJson(BlockInfo const& _bi, BlockDetails const& _bd, UncleHashes const& _us, Transactions const& _ts); |
||||
|
Json::Value toJson(BlockInfo const& _bi, BlockDetails const& _bd, UncleHashes const& _us, TransactionHashes const& _ts); |
||||
|
Json::Value toJson(TransactionSkeleton const& _t); |
||||
|
Json::Value toJson(Transaction const& _t); |
||||
|
Json::Value toJson(TransactionReceipt const& _t); |
||||
|
Json::Value toJson(LocalisedLogEntry const& _e); |
||||
|
Json::Value toJson(LogEntry const& _e); |
||||
|
TransactionSkeleton toTransactionSkeleton(Json::Value const& _json); |
||||
|
LogFilter toLogFilter(Json::Value const& _json); |
||||
|
LogFilter toLogFilter(Json::Value const& _json, Interface const& _client); // commented to avoid warning. Uncomment once in use @ PoC-7.
|
||||
|
|
||||
|
} |
||||
|
|
||||
|
namespace shh |
||||
|
{ |
||||
|
|
||||
|
Json::Value toJson(h256 const& _h, Envelope const& _e, Message const& _m); |
||||
|
Message toMessage(Json::Value const& _json); |
||||
|
Envelope toSealed(Json::Value const& _json, Message const& _m, Secret _from); |
||||
|
std::pair<Topics, Public> toWatch(Json::Value const& _json); |
||||
|
|
||||
|
} |
||||
|
|
||||
|
template <class T> |
||||
|
Json::Value toJson(std::vector<T> const& _es) |
||||
|
{ |
||||
|
Json::Value res(Json::arrayValue); |
||||
|
for (auto const& e: _es) |
||||
|
res.append(toJson(e)); |
||||
|
return res; |
||||
|
} |
||||
|
|
||||
|
template <class T> |
||||
|
Json::Value toJson(std::unordered_set<T> const& _es) |
||||
|
{ |
||||
|
Json::Value res(Json::arrayValue); |
||||
|
for (auto const& e: _es) |
||||
|
res.append(toJson(e)); |
||||
|
return res; |
||||
|
} |
||||
|
|
||||
|
template <class T> |
||||
|
Json::Value toJson(std::set<T> const& _es) |
||||
|
{ |
||||
|
Json::Value res(Json::arrayValue); |
||||
|
for (auto const& e: _es) |
||||
|
res.append(toJson(e)); |
||||
|
return res; |
||||
|
} |
||||
|
|
||||
|
} |
Loading…
Reference in new issue