New JSON serialization

This commit is contained in:
jezal 2014-09-15 21:33:47 +04:00
parent 640efb3e15
commit 257a2bf339
17 changed files with 2248 additions and 2 deletions

View file

@ -31,9 +31,9 @@ else()
else()
set(ARCH_FLAG "-march=${ARCH}")
endif()
set(WARNINGS "-Wall -Wextra -Wpointer-arith -Wundef -Wvla -Wwrite-strings -Werror -Wno-error=extra -Wno-error=deprecated-declarations -Wno-error=sign-compare -Wno-error=strict-aliasing -Wno-error=type-limits -Wno-unused-parameter -Wno-error=unused-variable -Wno-error=undef -Wno-error=uninitialized")
set(WARNINGS "-Wall -Wextra -Wpointer-arith -Wundef -Wvla -Wwrite-strings -Werror -Wno-error=extra -Wno-error=deprecated-declarations -Wno-error=sign-compare -Wno-error=strict-aliasing -Wno-error=type-limits -Wno-unused-parameter -Wno-error=unused-variable -Wno-error=undef -Wno-error=uninitialized -Wno-error=unused-result")
if(CMAKE_C_COMPILER_ID STREQUAL "Clang")
set(WARNINGS "${WARNINGS} -Wno-error=mismatched-tags -Wno-error=null-conversion -Wno-overloaded-shift-op-parentheses -Wno-error=shift-count-overflow -Wno-error=tautological-constant-out-of-range-compare -Wno-error=unused-private-field -Wno-error=unneeded-internal-declaration")
set(WARNINGS "${WARNINGS} -Wno-error=mismatched-tags -Wno-error=null-conversion -Wno-overloaded-shift-op-parentheses -Wno-error=shift-count-overflow -Wno-error=tautological-constant-out-of-range-compare -Wno-error=unused-private-field -Wno-error=unneeded-internal-declaration -Wno-error=unused-function")
else()
set(WARNINGS "${WARNINGS} -Wlogical-op -Wno-error=maybe-uninitialized")
endif()

View file

@ -0,0 +1,242 @@
// Copyright (c) 2012-2014, The CryptoNote developers, The Bytecoin developers
//
// This file is part of Bytecoin.
//
// Bytecoin is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Bytecoin 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 Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with Bytecoin. If not, see <http://www.gnu.org/licenses/>.
#include "BinaryInputStreamSerializer.h"
#include "SerializationOverloads.h"
#include <algorithm>
#include <cassert>
#include <stdexcept>
namespace {
void deserialize(std::istream& stream, uint8_t& v) {
char c;
stream.get(c);
v = static_cast<uint8_t>(c);
}
void deserialize(std::istream& stream, int8_t& v) {
uint8_t val;
deserialize(stream, val);
v = val;
}
void deserialize(std::istream& stream, bool& v) {
uint8_t val;
deserialize(stream, val);
v = val;
}
void deserialize(std::istream& stream, uint32_t& v) {
char c;
stream.get(c);
v = static_cast<uint8_t>(c);
stream.get(c);
v += static_cast<uint8_t>(c) << 8;
stream.get(c);
v += static_cast<uint8_t>(c) << 16;
stream.get(c);
v += static_cast<uint8_t>(c) << 24;
}
void deserialize(std::istream& stream, int32_t& v) {
uint32_t val;
deserialize(stream, val);
v = val;
}
void deserialize(std::istream& stream, uint64_t& v) {
char c;
uint64_t uc;
stream.get(c);
uc = static_cast<unsigned char>(c);
v = uc;
stream.get(c);
uc = static_cast<unsigned char>(c);
v += (uc << 8);
stream.get(c);
uc = static_cast<unsigned char>(c);
v += (uc << 16);
stream.get(c);
uc = static_cast<unsigned char>(c);
v += (uc << 24);
stream.get(c);
uc = static_cast<unsigned char>(c);
v += (uc << 32);
stream.get(c);
uc = static_cast<unsigned char>(c);
v += (uc << 40);
stream.get(c);
uc = static_cast<unsigned char>(c);
v += (uc << 48);
stream.get(c);
uc = static_cast<unsigned char>(c);
v += (uc << 56);
}
void deserialize(std::istream& stream, int64_t& v) {
uint64_t val;
deserialize(stream, val);
v = val;
}
void deserialize(std::istream& stream, char* buf, size_t len) {
const size_t chunk = 1000;
// stream.read(buf, len);
// looks redundant, but i had a bug with it
while (len && stream) {
size_t toRead = std::min(len, chunk);
stream.read(buf, toRead);
len -= toRead;
buf += toRead;
}
}
}
namespace cryptonote {
ISerializer::SerializerType BinaryInputStreamSerializer::type() const {
return ISerializer::INPUT;
}
ISerializer& BinaryInputStreamSerializer::beginObject(const std::string& name) {
return *this;
}
ISerializer& BinaryInputStreamSerializer::endObject() {
return *this;
}
ISerializer& BinaryInputStreamSerializer::beginArray(std::size_t& size, const std::string& name) {
uint64_t val;
serializeVarint(val, name, *this);
size = val;
return *this;
}
ISerializer& BinaryInputStreamSerializer::endArray() {
return *this;
}
ISerializer& BinaryInputStreamSerializer::operator()(uint8_t& value, const std::string& name) {
deserialize(stream, value);
return *this;
}
ISerializer& BinaryInputStreamSerializer::operator()(uint32_t& value, const std::string& name) {
deserialize(stream, value);
return *this;
}
ISerializer& BinaryInputStreamSerializer::operator()(int32_t& value, const std::string& name) {
uint32_t v;
operator()(v, name);
value = v;
return *this;
}
ISerializer& BinaryInputStreamSerializer::operator()(int64_t& value, const std::string& name) {
deserialize(stream, value);
return *this;
}
ISerializer& BinaryInputStreamSerializer::operator()(uint64_t& value, const std::string& name) {
deserialize(stream, value);
return *this;
}
ISerializer& BinaryInputStreamSerializer::operator()(bool& value, const std::string& name) {
deserialize(stream, value);
return *this;
}
ISerializer& BinaryInputStreamSerializer::operator()(std::string& value, const std::string& name) {
uint64_t size;
serializeVarint(size, name, *this);
std::vector<char> temp;
temp.resize(size);
deserialize(stream, &temp[0], size);
value.reserve(size);
value.assign(&temp[0], size);
return *this;
}
ISerializer& BinaryInputStreamSerializer::operator()(char* value, std::size_t size, const std::string& name) {
stream.read(value, size);
return *this;
}
ISerializer& BinaryInputStreamSerializer::tag(const std::string& name) {
return *this;
}
ISerializer& BinaryInputStreamSerializer::untagged(uint8_t& value) {
char v;
stream.get(v);
value = v;
return *this;
}
ISerializer& BinaryInputStreamSerializer::endTag() {
return *this;
}
bool BinaryInputStreamSerializer::hasObject(const std::string& name) {
assert(false); //the method is not supported for this type of serialization
throw std::runtime_error("hasObject method is not supported in BinaryInputStreamSerializer");
return false;
}
ISerializer& BinaryInputStreamSerializer::operator()(double& value, const std::string& name) {
assert(false); //the method is not supported for this type of serialization
throw std::runtime_error("double serialization is not supported in BinaryInputStreamSerializer");
return *this;
}
}

View file

@ -0,0 +1,66 @@
// Copyright (c) 2012-2014, The CryptoNote developers, The Bytecoin developers
//
// This file is part of Bytecoin.
//
// Bytecoin is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Bytecoin 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 Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with Bytecoin. If not, see <http://www.gnu.org/licenses/>.
#pragma once
#include "ISerializer.h"
#include "SerializationOverloads.h"
#include <istream>
namespace cryptonote {
class BinaryInputStreamSerializer : public ISerializer {
public:
BinaryInputStreamSerializer(std::istream& strm) : stream(strm) {}
virtual ~BinaryInputStreamSerializer() {}
virtual ISerializer::SerializerType type() const;
virtual ISerializer& beginObject(const std::string& name) override;
virtual ISerializer& endObject() override;
virtual ISerializer& beginArray(std::size_t& size, const std::string& name) override;
virtual ISerializer& endArray() override;
virtual ISerializer& operator()(uint8_t& value, const std::string& name) override;
virtual ISerializer& operator()(int32_t& value, const std::string& name) override;
virtual ISerializer& operator()(uint32_t& value, const std::string& name) override;
virtual ISerializer& operator()(int64_t& value, const std::string& name) override;
virtual ISerializer& operator()(uint64_t& value, const std::string& name) override;
virtual ISerializer& operator()(double& value, const std::string& name) override;
virtual ISerializer& operator()(bool& value, const std::string& name) override;
virtual ISerializer& operator()(std::string& value, const std::string& name) override;
virtual ISerializer& operator()(char* value, std::size_t size, const std::string& name);
virtual ISerializer& tag(const std::string& name) override;
virtual ISerializer& untagged(uint8_t& value) override;
virtual ISerializer& endTag() override;
virtual bool hasObject(const std::string& name) override;
template<typename T>
ISerializer& operator()(T& value, const std::string& name) {
return ISerializer::operator()(value, name);
}
private:
std::istream& stream;
};
}

View file

@ -0,0 +1,185 @@
// Copyright (c) 2012-2014, The CryptoNote developers, The Bytecoin developers
//
// This file is part of Bytecoin.
//
// Bytecoin is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Bytecoin 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 Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with Bytecoin. If not, see <http://www.gnu.org/licenses/>.
#include "BinaryOutputStreamSerializer.h"
#include <cassert>
#include <stdexcept>
namespace {
void serializeInteger(std::ostream& stream, uint8_t v) {
stream.put(static_cast<char>(v));
}
void serializeBool(std::ostream& stream, bool v) {
serializeInteger(stream, static_cast<uint8_t>(v));
}
void serializeInteger(std::ostream& stream, uint32_t v) {
stream.put(static_cast<char>(v & 0xff));
v >>= 8;
stream.put(static_cast<char>(v & 0xff));
v >>= 8;
stream.put(static_cast<char>(v & 0xff));
v >>= 8;
stream.put(static_cast<char>(v & 0xff));
}
void serializeInteger(std::ostream& stream, uint64_t v) {
stream.put(static_cast<unsigned char>(v & 0xff));
v >>= 8;
stream.put(static_cast<unsigned char>(v & 0xff));
v >>= 8;
stream.put(static_cast<unsigned char>(v & 0xff));
v >>= 8;
stream.put(static_cast<unsigned char>(v & 0xff));
v >>= 8;
stream.put(static_cast<unsigned char>(v & 0xff));
v >>= 8;
stream.put(static_cast<unsigned char>(v & 0xff));
v >>= 8;
stream.put(static_cast<unsigned char>(v & 0xff));
v >>= 8;
stream.put(static_cast<unsigned char>(v & 0xff));
}
void serializeInteger(std::ostream& stream, int64_t v) {
serializeInteger(stream, static_cast<uint64_t>(v));
}
void serializeData(std::ostream& stream, const char* buf, size_t len) {
stream.write(buf, len);
}
}
namespace cryptonote {
ISerializer::SerializerType BinaryOutputStreamSerializer::type() const {
return ISerializer::OUTPUT;
}
ISerializer& BinaryOutputStreamSerializer::beginObject(const std::string& name) {
return *this;
}
ISerializer& BinaryOutputStreamSerializer::endObject() {
return *this;
}
ISerializer& BinaryOutputStreamSerializer::beginArray(std::size_t& size, const std::string& name) {
uint64_t size64 = size;
serializeVarint(size64, name, *this);
size = size64;
return *this;
}
ISerializer& BinaryOutputStreamSerializer::endArray() {
return *this;
}
ISerializer& BinaryOutputStreamSerializer::operator()(uint8_t& value, const std::string& name) {
serializeInteger(stream, value);
return *this;
}
ISerializer& BinaryOutputStreamSerializer::operator()(uint32_t& value, const std::string& name) {
serializeInteger(stream, value);
return *this;
}
ISerializer& BinaryOutputStreamSerializer::operator()(int32_t& value, const std::string& name) {
uint32_t v = value;
operator()(v, name);
return *this;
}
ISerializer& BinaryOutputStreamSerializer::operator()(int64_t& value, const std::string& name) {
serializeInteger(stream, value);
return *this;
}
ISerializer& BinaryOutputStreamSerializer::operator()(uint64_t& value, const std::string& name) {
serializeInteger(stream, value);
return *this;
}
ISerializer& BinaryOutputStreamSerializer::operator()(bool& value, const std::string& name) {
serializeBool(stream, value);
return *this;
}
ISerializer& BinaryOutputStreamSerializer::operator()(std::string& value, const std::string& name) {
uint64_t size = value.size();
serializeVarint(size, name, *this);
serializeData(stream, value.c_str(), value.size());
return *this;
}
ISerializer& BinaryOutputStreamSerializer::operator()(char* value, std::size_t size, const std::string& name) {
serializeData(stream, value, size);
return *this;
}
ISerializer& BinaryOutputStreamSerializer::tag(const std::string& name) {
return *this;
}
ISerializer& BinaryOutputStreamSerializer::untagged(uint8_t& value) {
stream.put(value);
return *this;
}
ISerializer& BinaryOutputStreamSerializer::endTag() {
return *this;
}
bool BinaryOutputStreamSerializer::hasObject(const std::string& name) {
assert(false); //the method is not supported for this type of serialization
throw std::runtime_error("hasObject method is not supported in BinaryOutputStreamSerializer");
return false;
}
ISerializer& BinaryOutputStreamSerializer::operator()(double& value, const std::string& name) {
assert(false); //the method is not supported for this type of serialization
throw std::runtime_error("double serialization is not supported in BinaryOutputStreamSerializer");
return *this;
}
}

View file

@ -0,0 +1,65 @@
// Copyright (c) 2012-2014, The CryptoNote developers, The Bytecoin developers
//
// This file is part of Bytecoin.
//
// Bytecoin is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Bytecoin 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 Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with Bytecoin. If not, see <http://www.gnu.org/licenses/>.
#pragma once
#include "ISerializer.h"
#include "SerializationOverloads.h"
#include <ostream>
namespace cryptonote {
class BinaryOutputStreamSerializer : public ISerializer {
public:
BinaryOutputStreamSerializer(std::ostream& strm) : stream(strm) {}
virtual ~BinaryOutputStreamSerializer() {}
virtual ISerializer::SerializerType type() const;
virtual ISerializer& beginObject(const std::string& name) override;
virtual ISerializer& endObject() override;
virtual ISerializer& beginArray(std::size_t& size, const std::string& name) override;
virtual ISerializer& endArray() override;
virtual ISerializer& operator()(uint8_t& value, const std::string& name) override;
virtual ISerializer& operator()(int32_t& value, const std::string& name) override;
virtual ISerializer& operator()(uint32_t& value, const std::string& name) override;
virtual ISerializer& operator()(int64_t& value, const std::string& name) override;
virtual ISerializer& operator()(uint64_t& value, const std::string& name) override;
virtual ISerializer& operator()(double& value, const std::string& name) override;
virtual ISerializer& operator()(bool& value, const std::string& name) override;
virtual ISerializer& operator()(std::string& value, const std::string& name) override;
virtual ISerializer& operator()(char* value, std::size_t size, const std::string& name) override;
virtual ISerializer& tag(const std::string& name) override;
virtual ISerializer& untagged(uint8_t& value) override;
virtual ISerializer& endTag() override;
virtual bool hasObject(const std::string& name) override;
template<typename T>
ISerializer& operator()(T& value, const std::string& name) {
return ISerializer::operator()(value, name);
}
private:
std::ostream& stream;
};
}

View file

@ -0,0 +1,135 @@
// Copyright (c) 2012-2014, The CryptoNote developers, The Bytecoin developers
//
// This file is part of Bytecoin.
//
// Bytecoin is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Bytecoin 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 Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with Bytecoin. If not, see <http://www.gnu.org/licenses/>.
#pragma once
#include <string>
#include <cstdint>
namespace cryptonote {
class ISerializer {
public:
enum SerializerType {
INPUT,
OUTPUT
};
virtual ~ISerializer() {}
virtual SerializerType type() const = 0;
virtual ISerializer& beginObject(const std::string& name) = 0;
virtual ISerializer& endObject() = 0;
virtual ISerializer& beginArray(std::size_t& size, const std::string& name) = 0;
virtual ISerializer& endArray() = 0;
virtual ISerializer& operator()(uint8_t& value, const std::string& name) = 0;
virtual ISerializer& operator()(int32_t& value, const std::string& name) = 0;
virtual ISerializer& operator()(uint32_t& value, const std::string& name) = 0;
virtual ISerializer& operator()(int64_t& value, const std::string& name) = 0;
virtual ISerializer& operator()(uint64_t& value, const std::string& name) = 0;
virtual ISerializer& operator()(double& value, const std::string& name) = 0;
virtual ISerializer& operator()(bool& value, const std::string& name) = 0;
virtual ISerializer& operator()(char* value, std::size_t size, const std::string& name) = 0;
virtual ISerializer& operator()(std::string& value, const std::string& name) = 0;
virtual ISerializer& tag(const std::string& name) = 0;
virtual ISerializer& untagged(uint8_t& value) = 0;
virtual ISerializer& endTag() = 0;
virtual bool hasObject(const std::string& name) = 0;
template<typename T>
ISerializer& operator()(T& value, const std::string& name);
};
template<typename T>
ISerializer& ISerializer::operator()(T& value, const std::string& name) {
serialize(value, name, *this);
return *this;
}
template<typename T>
void serialize(T& value, const std::string& name, ISerializer& serializer) {
value.serialize(serializer, name);
return;
}
/*
template<typename T>
void serialize(std::vector<T>& value, const std::string& name);
template<typename K, typename V>
void serialize(std::unordered_map<K, V>& value, const std::string& name);
template<typename T>
void ISerializer::serialize(std::vector<T>& value, const std::string& name) {
std::size_t size = value.size();
beginArray(size, name);
value.resize(size);
for (size_t i = 0; i < size; ++i) {
serialize(value[i], "");
}
endArray();
return *this;
}
template<typename K, typename V>
void ISerializer::serialize(std::unordered_map<K, V>& value, const std::string& name) {
std::size_t size;
size = value.size();
beginArray(size, name);
if (type() == INPUT) {
value.reserve(size);
for (size_t i = 0; i < size; ++i) {
K key;
V v;
beginObject("");
serialize(key, "");
serialize(v, "");
endObject();
value[key] = v;
}
} else {
for (auto kv: value) {
K key;
key = kv.first;
beginObject("");
serialize(key, "");
serialize(kv.second, "");
endObject();
}
}
endArray();
return *this;
}
*/
}

View file

@ -0,0 +1,33 @@
// Copyright (c) 2012-2014, The CryptoNote developers, The Bytecoin developers
//
// This file is part of Bytecoin.
//
// Bytecoin is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Bytecoin 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 Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with Bytecoin. If not, see <http://www.gnu.org/licenses/>.
#include "serialization/JsonInputStreamSerializer.h"
#include <ctype.h>
#include <exception>
namespace cryptonote {
JsonInputStreamSerializer::JsonInputStreamSerializer(std::istream& stream) {
stream >> root;
JsonInputValueSerializer::setJsonValue(&root);
}
JsonInputStreamSerializer::~JsonInputStreamSerializer() {
}
} //namespace cryptonote

View file

@ -0,0 +1,40 @@
// Copyright (c) 2012-2014, The CryptoNote developers, The Bytecoin developers
//
// This file is part of Bytecoin.
//
// Bytecoin is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Bytecoin 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 Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with Bytecoin. If not, see <http://www.gnu.org/licenses/>.
#pragma once
#include <iosfwd>
#include <string>
#include <vector>
//#include "serialization/Enumerator.h"
#include "serialization/JsonInputValueSerializer.h"
#include "serialization/JsonValue.h"
namespace cryptonote {
//deserialization
class JsonInputStreamSerializer : public JsonInputValueSerializer {
public:
JsonInputStreamSerializer(std::istream& stream);
virtual ~JsonInputStreamSerializer();
private:
JsonValue root;
};
}

View file

@ -0,0 +1,216 @@
// Copyright (c) 2012-2014, The CryptoNote developers, The Bytecoin developers
//
// This file is part of Bytecoin.
//
// Bytecoin is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Bytecoin 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 Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with Bytecoin. If not, see <http://www.gnu.org/licenses/>.
#include "serialization/JsonInputValueSerializer.h"
#include <cassert>
#include <stdexcept>
namespace cryptonote {
JsonInputValueSerializer::JsonInputValueSerializer() : root(nullptr) {
}
JsonInputValueSerializer::~JsonInputValueSerializer() {
}
void JsonInputValueSerializer::setJsonValue(const JsonValue* value) {
root = value;
}
ISerializer::SerializerType JsonInputValueSerializer::type() const {
return ISerializer::INPUT;
}
ISerializer& JsonInputValueSerializer::beginObject(const std::string& name) {
assert(root);
if (chain.size() == 0) {
chain.push_back(root);
return *this;
}
const JsonValue* parent = chain.back();
if (parent->isArray()) {
const JsonValue& v = (*parent)[idxs.back()++];
chain.push_back(&v);
} else {
const JsonValue& v = (*parent)(name);
chain.push_back(&v);
}
return *this;
}
ISerializer& JsonInputValueSerializer::endObject() {
assert(root);
chain.pop_back();
return *this;
}
ISerializer& JsonInputValueSerializer::beginArray(std::size_t& size, const std::string& name) {
assert(root);
const JsonValue* parent = chain.back();
const JsonValue& arr = (*parent)(name);
size = arr.size();
chain.push_back(&arr);
idxs.push_back(0);
return *this;
}
ISerializer& JsonInputValueSerializer::endArray() {
assert(root);
chain.pop_back();
idxs.pop_back();
return *this;
}
ISerializer& JsonInputValueSerializer::operator()(uint32_t& value, const std::string& name) {
assert(root);
int64_t v = static_cast<int64_t>(value);
operator()(v, name);
value = static_cast<uint64_t>(v);
return *this;
}
ISerializer& JsonInputValueSerializer::operator()(int32_t& value, const std::string& name) {
assert(root);
int64_t v = static_cast<int64_t>(value);
operator()(v, name);
value = static_cast<uint64_t>(v);
return *this;
}
ISerializer& JsonInputValueSerializer::operator()(int64_t& value, const std::string& name) {
assert(root);
const JsonValue* val = chain.back();
if (val->isArray()) {
const JsonValue& v = (*val)[idxs.back()++];
value = v.getNumber();
} else {
const JsonValue& v = (*val)(name);
value = v.getNumber();
}
return *this;
}
ISerializer& JsonInputValueSerializer::operator()(uint64_t& value, const std::string& name) {
assert(root);
int64_t v = static_cast<int64_t>(value);
operator()(v, name);
value = static_cast<uint64_t>(v);
return *this;
}
ISerializer& JsonInputValueSerializer::operator()(double& value, const std::string& name) {
assert(root);
const JsonValue* val = chain.back();
if (val->isArray()) {
value = (*val)[idxs.back()++].getDouble();
} else {
value = (*val)(name).getDouble();
}
return *this;
}
ISerializer& JsonInputValueSerializer::operator()(std::string& value, const std::string& name) {
assert(root);
const JsonValue* val = chain.back();
if (val->isArray()) {
value = (*val)[idxs.back()++].getString();
} else {
value = (*val)(name).getString();
}
return *this;
}
ISerializer& JsonInputValueSerializer::operator()(uint8_t& value, const std::string& name) {
assert(root);
uint64_t v = static_cast<uint64_t>(value);
operator()(v, name);
value = static_cast<uint8_t>(value);
return *this;
}
ISerializer& JsonInputValueSerializer::operator()(bool& value, const std::string& name) {
assert(root);
const JsonValue* val = chain.back();
if (val->isArray()) {
value = (*val)[idxs.back()++].getBool();
} else {
value = (*val)(name).getBool();
}
return *this;
}
bool JsonInputValueSerializer::hasObject(const std::string& name) {
const JsonValue* val = chain.back();
return val->count(name) != 0;
}
ISerializer& JsonInputValueSerializer::operator()(char* value, std::size_t size, const std::string& name) {
assert(false);
throw std::runtime_error("JsonInputValueSerializer doesn't support this type of serialization");
return *this;
}
ISerializer& JsonInputValueSerializer::tag(const std::string& name) {
assert(false);
throw std::runtime_error("JsonInputValueSerializer doesn't support this type of serialization");
return *this;
}
ISerializer& JsonInputValueSerializer::untagged(uint8_t& value) {
assert(false);
throw std::runtime_error("JsonInputValueSerializer doesn't support this type of serialization");
return *this;
}
ISerializer& JsonInputValueSerializer::endTag() {
assert(false);
throw std::runtime_error("JsonInputValueSerializer doesn't support this type of serialization");
return *this;
}
}

View file

@ -0,0 +1,67 @@
// Copyright (c) 2012-2014, The CryptoNote developers, The Bytecoin developers
//
// This file is part of Bytecoin.
//
// Bytecoin is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Bytecoin 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 Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with Bytecoin. If not, see <http://www.gnu.org/licenses/>.
#pragma once
#include "serialization/ISerializer.h"
#include "serialization/JsonValue.h"
namespace cryptonote {
//deserialization
class JsonInputValueSerializer : public ISerializer {
public:
JsonInputValueSerializer();
virtual ~JsonInputValueSerializer();
void setJsonValue(const JsonValue* value);
SerializerType type() const;
virtual ISerializer& beginObject(const std::string& name) override;
virtual ISerializer& endObject() override;
virtual ISerializer& beginArray(std::size_t& size, const std::string& name) override;
virtual ISerializer& endArray() override;
virtual ISerializer& operator()(int32_t& value, const std::string& name) override;
virtual ISerializer& operator()(uint32_t& value, const std::string& name) override;
virtual ISerializer& operator()(int64_t& value, const std::string& name) override;
virtual ISerializer& operator()(uint64_t& value, const std::string& name) override;
virtual ISerializer& operator()(double& value, const std::string& name) override;
virtual ISerializer& operator()(std::string& value, const std::string& name) override;
virtual ISerializer& operator()(uint8_t& value, const std::string& name) override;
virtual ISerializer& operator()(bool& value, const std::string& name) override;
virtual ISerializer& operator()(char* value, std::size_t size, const std::string& name) override;
virtual ISerializer& tag(const std::string& name) override;
virtual ISerializer& untagged(uint8_t& value) override;
virtual ISerializer& endTag() override;
virtual bool hasObject(const std::string& name) override;
template<typename T>
ISerializer& operator()(T& value, const std::string& name) {
return ISerializer::operator()(value, name);
}
private:
const JsonValue* root;
std::vector<const JsonValue*> chain;
std::vector<size_t> idxs;
};
}

View file

@ -0,0 +1,189 @@
// Copyright (c) 2012-2014, The CryptoNote developers, The Bytecoin developers
//
// This file is part of Bytecoin.
//
// Bytecoin is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Bytecoin 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 Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with Bytecoin. If not, see <http://www.gnu.org/licenses/>.
#include "serialization/JsonOutputStreamSerializer.h"
#include <cassert>
#include <stdexcept>
namespace cryptonote {
JsonOutputStreamSerializer::JsonOutputStreamSerializer() : root(JsonValue::OBJECT) {
}
JsonOutputStreamSerializer::~JsonOutputStreamSerializer() {
}
std::ostream& operator<<(std::ostream& out, const JsonOutputStreamSerializer& enumerator) {
out << enumerator.root;
return out;
}
JsonValue JsonOutputStreamSerializer::getJsonValue() const {
return root;
}
ISerializer::SerializerType JsonOutputStreamSerializer::type() const {
return ISerializer::OUTPUT;
}
ISerializer& JsonOutputStreamSerializer::beginObject(const std::string& name) {
if (chain.size() == 0) {
chain.push_back(&root);
return *this;
}
JsonValue* parent = chain.back();
JsonValue obj(JsonValue::OBJECT);
if (parent->isObject()) {
JsonValue& res = parent->insert(name, obj);
chain.push_back(&res);
} else {
JsonValue& res = parent->pushBack(obj);
chain.push_back(&res);
}
return *this;
}
ISerializer& JsonOutputStreamSerializer::endObject() {
chain.pop_back();
return *this;
}
ISerializer& JsonOutputStreamSerializer::beginArray(std::size_t& size, const std::string& name) {
JsonValue val(JsonValue::ARRAY);
JsonValue& res = chain.back()->insert(name, val);
chain.push_back(&res);
return *this;
}
ISerializer& JsonOutputStreamSerializer::endArray() {
chain.pop_back();
return *this;
}
ISerializer& JsonOutputStreamSerializer::operator()(uint64_t& value, const std::string& name) {
int64_t v = static_cast<int64_t>(value);
return operator()(v, name);
}
ISerializer& JsonOutputStreamSerializer::operator()(uint32_t& value, const std::string& name) {
uint64_t v = static_cast<uint64_t>(value);
return operator()(v, name);
}
ISerializer& JsonOutputStreamSerializer::operator()(int32_t& value, const std::string& name) {
int64_t v = static_cast<int64_t>(value);
return operator()(v, name);
}
ISerializer& JsonOutputStreamSerializer::operator()(int64_t& value, const std::string& name) {
JsonValue* val = chain.back();
JsonValue v;
v = static_cast<int64_t>(value);
if (val->isArray()) {
val->pushBack(v);
} else {
val->insert(name, v);
}
return *this;
}
ISerializer& JsonOutputStreamSerializer::operator()(double& value, const std::string& name) {
JsonValue* val = chain.back();
JsonValue v;
v = static_cast<double>(value);
if (val->isArray()) {
val->pushBack(v);
} else {
val->insert(name, v);
}
return *this;
}
ISerializer& JsonOutputStreamSerializer::operator()(std::string& value, const std::string& name) {
JsonValue* val = chain.back();
JsonValue v;
v = value;
if (val->isArray()) {
val->pushBack(v);
} else {
val->insert(name, v);
}
return *this;
}
ISerializer& JsonOutputStreamSerializer::operator()(uint8_t& value, const std::string& name) {
uint64_t v = static_cast<uint64_t>(value);
return operator()(v, name);
}
ISerializer& JsonOutputStreamSerializer::operator()(bool& value, const std::string& name) {
JsonValue* val = chain.back();
JsonValue v;
v = static_cast<bool>(value);
if (val->isArray()) {
val->pushBack(v);
} else {
val->insert(name, v);
}
return *this;
}
ISerializer& JsonOutputStreamSerializer::operator()(char* value, std::size_t size, const std::string& name) {
assert(false);
throw std::runtime_error("JsonOutputStreamSerializer doesn't support \"char *\" type of serialization");
return *this;
}
ISerializer& JsonOutputStreamSerializer::tag(const std::string& name) {
assert(false);
throw std::runtime_error("JsonOutputStreamSerializer doesn't support this type of serialization");
return *this;
}
ISerializer& JsonOutputStreamSerializer::untagged(uint8_t& value) {
assert(false);
throw std::runtime_error("JsonOutputStreamSerializer doesn't support this type of serialization");
return *this;
}
ISerializer& JsonOutputStreamSerializer::endTag() {
assert(false);
throw std::runtime_error("JsonOutputStreamSerializer doesn't support this type of serialization");
return *this;
}
bool JsonOutputStreamSerializer::hasObject(const std::string& name) {
assert(false);
throw std::runtime_error("JsonOutputStreamSerializer doesn't support this type of serialization");
return false;
}
}

View file

@ -0,0 +1,69 @@
// Copyright (c) 2012-2014, The CryptoNote developers, The Bytecoin developers
//
// This file is part of Bytecoin.
//
// Bytecoin is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Bytecoin 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 Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with Bytecoin. If not, see <http://www.gnu.org/licenses/>.
#pragma once
#include "serialization/ISerializer.h"
#include "serialization/JsonValue.h"
#include <iostream>
namespace cryptonote {
class JsonOutputStreamSerializer : public ISerializer {
public:
JsonOutputStreamSerializer();
virtual ~JsonOutputStreamSerializer();
JsonValue getJsonValue() const;
SerializerType type() const;
virtual ISerializer& beginObject(const std::string& name) override;
virtual ISerializer& endObject() override;
virtual ISerializer& beginArray(std::size_t& size, const std::string& name) override;
virtual ISerializer& endArray() override;
virtual ISerializer& operator()(int32_t& value, const std::string& name) override;
virtual ISerializer& operator()(uint32_t& value, const std::string& name) override;
virtual ISerializer& operator()(int64_t& value, const std::string& name) override;
virtual ISerializer& operator()(uint64_t& value, const std::string& name) override;
virtual ISerializer& operator()(double& value, const std::string& name) override;
virtual ISerializer& operator()(std::string& value, const std::string& name) override;
virtual ISerializer& operator()(uint8_t& value, const std::string& name) override;
virtual ISerializer& operator()(bool& value, const std::string& name) override;
virtual ISerializer& operator()(char* value, std::size_t size, const std::string& name) override;
virtual ISerializer& tag(const std::string& name) override;
virtual ISerializer& untagged(uint8_t& value) override;
virtual ISerializer& endTag() override;
virtual bool hasObject(const std::string& name) override;
template<typename T>
ISerializer& operator()(T& value, const std::string& name) {
return ISerializer::operator()(value, name);
}
friend std::ostream& operator<<(std::ostream& out, const JsonOutputStreamSerializer& enumerator);
private:
JsonValue root;
std::vector<JsonValue*> chain;
};
} // namespace cryptonote

View file

@ -0,0 +1,65 @@
// Copyright (c) 2012-2014, The CryptoNote developers, The Bytecoin developers
//
// This file is part of Bytecoin.
//
// Bytecoin is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Bytecoin 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 Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with Bytecoin. If not, see <http://www.gnu.org/licenses/>.
#pragma once
#include <sstream>
#include <type_traits>
#include <boost/tti/has_member_function.hpp>
#include "serialization/JsonOutputStreamSerializer.h"
#include "serialization/JsonInputStreamSerializer.h"
#include "storages/portable_storage_template_helper.h"
namespace {
BOOST_TTI_HAS_MEMBER_FUNCTION(serialize)
} //namespace
namespace cryptonote {
template<class T>
inline typename std::enable_if<has_member_function_serialize<void (T::*)(ISerializer&, const std::string&)>::value, void>::type SerializeToJson(T& obj, std::string& jsonBuff) {
std::stringstream stream;
JsonOutputStreamSerializer serializer;
obj.serialize(serializer, "");
stream << serializer;
jsonBuff = stream.str();
}
template<class T>
inline typename std::enable_if<has_member_function_serialize<void (T::*)(ISerializer&, const std::string&)>::value, void>::type LoadFromJson(T& obj, const std::string& jsonBuff) {
std::stringstream stream(jsonBuff);
JsonInputStreamSerializer serializer(stream);
obj.serialize(serializer, "");
}
//old epee serialization
template<class T>
inline typename std::enable_if<!has_member_function_serialize<void (T::*)(ISerializer&, const std::string&)>::value, void>::type SerializeToJson(T& obj, std::string& jsonBuff) {
epee::serialization::store_t_to_json(obj, jsonBuff);
}
template<class T>
inline typename std::enable_if<!has_member_function_serialize<void (T::*)(ISerializer&, const std::string&)>::value, void>::type LoadFromJson(T& obj, const std::string& jsonBuff) {
epee::serialization::load_t_from_json(obj, jsonBuff);
}
} //namespace cryptonote

View file

@ -0,0 +1,612 @@
// Copyright (c) 2012-2014, The CryptoNote developers, The Bytecoin developers
//
// This file is part of Bytecoin.
//
// Bytecoin is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Bytecoin 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 Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with Bytecoin. If not, see <http://www.gnu.org/licenses/>.
#include "JsonValue.h"
#include <iomanip>
#include <sstream>
#include <assert.h>
namespace cryptonote {
JsonValue::JsonValue() : d_type(NIL) {
}
JsonValue::JsonValue(JsonValue::Type type) {
switch(type) {
case OBJECT:
new(d_valueObject)JsonValue::Object();
break;
case ARRAY:
new(d_valueArray)JsonValue::Array();
break;
default:
throw std::runtime_error("Wrong JsonValue type. Object or Array are possible only");
}
d_type = type;
}
JsonValue::JsonValue(const JsonValue& other) : d_type(other.d_type) {
switch (d_type) {
case ARRAY:
new(d_valueArray)JsonValue::Array(*reinterpret_cast<const Array*>(other.d_valueArray));
break;
case BOOL:
d_valueBool = other.d_valueBool;
break;
case INT64:
d_valueInt64 = other.d_valueInt64;
break;
case NIL:
break;
case OBJECT:
new(d_valueObject)JsonValue::Object(*reinterpret_cast<const Object*>(other.d_valueObject));
break;
case DOUBLE:
d_valueDouble = other.d_valueDouble;
break;
case STRING:
new(d_valueString)std::string(*reinterpret_cast<const std::string*>(other.d_valueString));
break;
default:
throw(std::runtime_error("Invalid type"));
}
}
JsonValue::~JsonValue() {
destructValue();
}
bool JsonValue::isArray() const {
return d_type == ARRAY;
}
bool JsonValue::isBool() const {
return d_type == BOOL;
}
bool JsonValue::isInt64() const {
return d_type == INT64;
}
bool JsonValue::isNil() const {
return d_type == NIL;
}
bool JsonValue::isObject() const {
return d_type == OBJECT;
}
bool JsonValue::isDouble() const {
return d_type == DOUBLE;
}
bool JsonValue::isString() const {
return d_type == STRING;
}
bool JsonValue::getBool() const {
assert(d_type == BOOL);
if (d_type != BOOL) {
throw(std::runtime_error("Value type is not BOOL"));
}
return d_valueBool;
}
int64_t JsonValue::getNumber() const {
assert(d_type == INT64);
if (d_type != INT64) {
throw(std::runtime_error("Value type is not INT64"));
}
return d_valueInt64;
}
const JsonValue::Object& JsonValue::getObject() const {
assert(d_type == OBJECT);
if (d_type != OBJECT) {
throw(std::runtime_error("Value type is not OBJECT"));
}
return *reinterpret_cast<const Object*>(d_valueObject);
}
double JsonValue::getDouble() const {
assert(d_type == DOUBLE);
if (d_type != DOUBLE) {
throw(std::runtime_error("Value type is not DOUBLE"));
}
return d_valueDouble;
}
std::string JsonValue::getString() const {
assert(d_type == STRING);
if (d_type != STRING) {
throw(std::runtime_error("Value type is not STRING"));
}
return *reinterpret_cast<const std::string*>(d_valueString);
}
const JsonValue& JsonValue::operator()(const std::string& name) const {
assert(d_type == OBJECT);
assert(reinterpret_cast<const Object*>(d_valueObject)->count(name) > 0);
if (d_type != OBJECT) {
throw(std::runtime_error("Value type is not OBJECT"));
}
return reinterpret_cast<const Object*>(d_valueObject)->at(name);
}
size_t JsonValue::count(const std::string& name) const {
assert(d_type == OBJECT);
if (d_type != OBJECT) {
throw(std::runtime_error("Value type is not OBJECT"));
}
return reinterpret_cast<const Object*>(d_valueObject)->count(name);
}
const JsonValue& JsonValue::operator[](size_t index) const {
assert(d_type == ARRAY);
if (d_type != ARRAY) {
throw(std::runtime_error("Value type is not ARRAY"));
}
return reinterpret_cast<const Array*>(d_valueArray)->at(index);
}
size_t JsonValue::size() const {
assert(d_type == ARRAY || d_type == OBJECT);
switch (d_type) {
case OBJECT:
return reinterpret_cast<const Object*>(d_valueString)->size();
case ARRAY:
return reinterpret_cast<const Array*>(d_valueString)->size();
default:
throw(std::runtime_error("Value type is not ARRAY or OBJECT"));
}
}
JsonValue::Array::const_iterator JsonValue::begin() const {
assert(d_type == ARRAY);
if (d_type != ARRAY) {
throw(std::runtime_error("Value type is not ARRAY"));
}
return reinterpret_cast<const Array*>(d_valueArray)->begin();
}
JsonValue::Array::const_iterator JsonValue::end() const {
assert(d_type == ARRAY);
if (d_type != ARRAY) {
throw(std::runtime_error("Value type is not ARRAY"));
}
return reinterpret_cast<const Array*>(d_valueArray)->end();
}
void JsonValue::readArray(std::istream& in) {
char c;
JsonValue::Array value;
c = in.peek();
while (true) {
if (!isspace(in.peek())) break;
in.read(&c, 1);
}
if (c != ']') {
for (;;) {
value.resize(value.size() + 1);
in >> value.back();
in >> c;
while (isspace(c)) in >> c;
if (c == ']') {
break;
}
if (c != ',') {
throw(std::runtime_error("Unable to parse"));
}
}
}
if (d_type != JsonValue::ARRAY) {
destructValue();
d_type = JsonValue::NIL;
new(d_valueArray)JsonValue::Array;
d_type = JsonValue::ARRAY;
}
reinterpret_cast<JsonValue::Array*>(d_valueArray)->swap(value);
}
void JsonValue::readTrue(std::istream& in) {
char data[3];
in.read(data, 3);
if (data[0] != 'r' || data[1] != 'u' || data[2] != 'e') {
throw(std::runtime_error("Unable to parse"));
}
if (d_type != JsonValue::BOOL) {
destructValue();
d_type = JsonValue::BOOL;
}
d_valueBool = true;
}
void JsonValue::readFalse(std::istream& in) {
char data[4];
in.read(data, 4);
if (data[0] != 'a' || data[1] != 'l' || data[2] != 's' || data[3] != 'e') {
throw(std::runtime_error("Unable to parse"));
}
if (d_type != JsonValue::BOOL) {
destructValue();
d_type = JsonValue::BOOL;
}
d_valueBool = false;
}
void JsonValue::readNumber(std::istream& in, char c) {
std::string text;
text += c;
size_t dots = 0;
for (;;) {
int i = in.peek();
if (i >= '0' && i <= '9') {
in.read(&c, 1);
text += c;
} else if (i == '.') {
in.read(&c, 1);
text += '.';
++dots;
} else {
break;
}
}
if (dots > 0) {
if (dots > 1) {
throw(std::runtime_error("Unable to parse"));
}
int i = in.peek();
if (in.peek() == 'e') {
in.read(&c, 1);
text += c;
i = in.peek();
if (i == '+') {
in.read(&c, 1);
text += c;
i = in.peek();
} else if (i == '-') {
in.read(&c, 1);
text += c;
i = in.peek();
}
if (i < '0' || i > '9') {
throw(std::runtime_error("Unable to parse"));
}
do {
in.read(&c, 1);
text += c;
i = in.peek();
} while (i >= '0' && i <= '9');
}
double value;
std::istringstream(text) >> value;
if (d_type != JsonValue::DOUBLE) {
destructValue();
d_type = JsonValue::DOUBLE;
}
d_valueDouble = value;
} else {
if (text.size() > 1 && ((text[0] == '0') || (text[0] == '-' && text[1] == '0'))) {
throw(std::runtime_error("Unable to parse"));
}
int64_t value;
std::istringstream(text) >> value;
if (d_type != JsonValue::INT64) {
destructValue();
d_type = JsonValue::INT64;
}
d_valueInt64 = value;
}
}
void JsonValue::readNull(std::istream& in) {
char data[3];
in.read(data, 3);
if (data[0] != 'u' || data[1] != 'l' || data[2] != 'l') {
throw(std::runtime_error("Unable to parse"));
}
if (d_type != JsonValue::NIL) {
destructValue();
d_type = JsonValue::NIL;
}
}
void JsonValue::readObject(std::istream& in) {
char c;
JsonValue::Object value;
in >> c;
while (isspace(c)) in >> c;
if (c != '}') {
std::string name;
for (;;) {
if (c != '"') {
throw(std::runtime_error("Unable to parse"));
}
name.clear();
for (;;) {
in >> c;
if (c == '"') {
break;
}
if (c == '\\') {
name += c;
in >> c;
}
name += c;
}
in >> c;
while (isspace(c)) in >> c;
if (c != ':') {
throw(std::runtime_error("Unable to parse"));
}
in >> value[name];
in >> c;
while (isspace(c)) in >> c;
if (c == '}') {
break;
}
if (c != ',') {
throw(std::runtime_error("Unable to parse"));
}
in >> c;
while (isspace(c)) in >> c;
}
}
if (d_type != JsonValue::OBJECT) {
destructValue();
d_type = JsonValue::NIL;
new(d_valueObject)JsonValue::Object;
d_type = JsonValue::OBJECT;
}
reinterpret_cast<JsonValue::Object*>(d_valueObject)->swap(value);
}
void JsonValue::readString(std::istream& in) {
char c;
std::string value;
for (;;) {
in.read(&c, 1);
if (c == '"') {
break;
}
if (c == '\\') {
value += c;
in >> c;
}
value += c;
}
if (d_type != JsonValue::STRING) {
destructValue();
d_type = JsonValue::NIL;
new(d_valueString)std::string;
d_type = JsonValue::STRING;
}
reinterpret_cast<std::string*>(d_valueString)->swap(value);
}
std::istream& operator>>(std::istream& in, JsonValue& jsonValue) {
char c;
in >> c;
while (isspace(c)) in >> c;
if (c == '[') {
jsonValue.readArray(in);
} else if (c == 't') {
jsonValue.readTrue(in);
} else if (c == 'f') {
jsonValue.readFalse(in);
} else if ((c == '-') || (c >= '0' && c <= '9')) {
jsonValue.readNumber(in, c);
} else if (c == 'n') {
jsonValue.readNull(in);
} else if (c == '{') {
jsonValue.readObject(in);
} else if (c == '"') {
jsonValue.readString(in);
} else {
throw(std::runtime_error("Unable to parse"));
}
return in;
}
std::ostream& operator<<(std::ostream& out, const JsonValue& jsonValue) {
if (jsonValue.d_type == JsonValue::ARRAY) {
const JsonValue::Array& array = *reinterpret_cast<const JsonValue::Array*>(jsonValue.d_valueArray);
out << '[';
if (array.size() > 0) {
out << array[0];
for (size_t i = 1; i < array.size(); ++i) {
out << ',' << array[i];
}
}
out << ']';
} else if (jsonValue.d_type == JsonValue::BOOL) {
out << (jsonValue.d_valueBool ? "true" : "false");
} else if (jsonValue.d_type == JsonValue::INT64) {
out << jsonValue.d_valueInt64;
} else if (jsonValue.d_type == JsonValue::NIL) {
out << "null";
} else if (jsonValue.d_type == JsonValue::OBJECT) {
const JsonValue::Object& object = *reinterpret_cast<const JsonValue::Object*>(jsonValue.d_valueObject);
out << '{';
auto iter = object.begin();
if (iter != object.end()) {
out << '"' << iter->first << "\":" << iter->second;
++iter;
for (; iter != object.end(); ++iter) {
out << ",\"" << iter->first << "\":" << iter->second;
}
}
out << '}';
} else if (jsonValue.d_type == JsonValue::DOUBLE) {
std::ostringstream stream;
stream << std::fixed << std::setprecision(11) << jsonValue.d_valueDouble;
std::string value = stream.str();
while (value.size() > 1 && value[value.size() - 2] != '.' && value[value.size() - 1] == '0') {
value.resize(value.size() - 1);
}
out << value;
} else if (jsonValue.d_type == JsonValue::STRING) {
out << '"' << *reinterpret_cast<const std::string*>(jsonValue.d_valueString) << '"';
} else {
throw(std::runtime_error("Invalid type"));
}
return out;
}
void JsonValue::destructValue() {
switch (d_type) {
case ARRAY:
reinterpret_cast<Array*>(d_valueArray)->~Array();
break;
case OBJECT:
reinterpret_cast<Object*>(d_valueObject)->~Object();
break;
case STRING:
reinterpret_cast<std::string*>(d_valueString)->~basic_string();
break;
default:
break;
}
}
JsonValue& JsonValue::pushBack(const JsonValue& val) {
if (d_type != ARRAY) {
throw std::runtime_error("JsonValue error. pushBack is only possible for arrays");
}
Array* array = reinterpret_cast<Array*>(d_valueArray);
array->push_back(val);
return array->back();
}
JsonValue& JsonValue::insert(const std::string key, const JsonValue& value) {
if (d_type != OBJECT) {
throw std::runtime_error("JsonValue error. insert is only possible for objects");
}
Object* obj = reinterpret_cast<Object*>(d_valueObject);
auto res = obj->insert(std::make_pair(key, value));
return res.first->second;
}
JsonValue& JsonValue::operator=(bool value) {
if (d_type != BOOL) {
destructValue();
d_type = BOOL;
}
d_valueBool = value;
return *this;
}
JsonValue& JsonValue::operator=(int64_t value) {
if (d_type != INT64) {
destructValue();
d_type = INT64;
}
d_valueInt64 = value;
return *this;
}
//JsonValue& JsonValue::operator=(NilType value) {
// if (d_type != NIL) {
// destructValue();
// d_type = NIL;
// }
//}
JsonValue& JsonValue::operator=(double value) {
if (d_type != DOUBLE) {
destructValue();
d_type = DOUBLE;
}
d_valueDouble = value;
return *this;
}
JsonValue& JsonValue::operator=(const std::string& value) {
if (d_type != STRING) {
destructValue();
new(d_valueString)std::string;
d_type = STRING;
}
reinterpret_cast<std::string*>(d_valueString)->assign(value.data(), value.size());
return *this;
}
JsonValue& JsonValue::operator=(const char* value) {
return operator=(std::string(value));
}
} //namespace cryptonote

View file

@ -0,0 +1,103 @@
// Copyright (c) 2012-2014, The CryptoNote developers, The Bytecoin developers
//
// This file is part of Bytecoin.
//
// Bytecoin is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Bytecoin 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 Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with Bytecoin. If not, see <http://www.gnu.org/licenses/>.
#pragma once
#include <map>
#include <vector>
#include <string>
#include <stdint.h>
namespace cryptonote {
class JsonValue {
public:
typedef std::vector<JsonValue> Array;
typedef std::map<std::string, JsonValue> Object;
enum Type {
ARRAY,
BOOL,
INT64,
NIL,
OBJECT,
DOUBLE,
STRING
};
JsonValue();
JsonValue(Type type);
JsonValue(const JsonValue& other);
~JsonValue();
JsonValue& operator=(const JsonValue& other) = delete;
bool isArray() const;
bool isBool() const;
bool isInt64() const;
bool isNil() const;
bool isObject() const;
bool isDouble() const;
bool isString() const;
bool getBool() const;
int64_t getNumber() const;
const Object& getObject() const;
double getDouble() const;
std::string getString() const;
const JsonValue& operator()(const std::string& name) const;
size_t count(const std::string& name) const;
const JsonValue& operator[](size_t index) const;
size_t size() const;
Array::const_iterator begin() const;
Array::const_iterator end() const;
JsonValue& pushBack(const JsonValue& val);
JsonValue& insert(const std::string key, const JsonValue& value);
JsonValue& operator=(bool value);
JsonValue& operator=(int64_t value);
// JsonValue& operator=(NilType value);
JsonValue& operator=(double value);
JsonValue& operator=(const std::string& value);
JsonValue& operator=(const char* value);
friend std::istream& operator>>(std::istream& in, JsonValue& jsonValue);
friend std::ostream& operator<<(std::ostream& out, const JsonValue& jsonValue);
private:
size_t d_type;
union {
uint8_t d_valueArray[sizeof(Array)];
bool d_valueBool;
int64_t d_valueInt64;
uint8_t d_valueObject[sizeof(Object)];
double d_valueDouble;
uint8_t d_valueString[sizeof(std::string)];
};
void destructValue();
void readArray(std::istream& in);
void readTrue(std::istream& in);
void readFalse(std::istream& in);
void readNumber(std::istream& in, char c);
void readNull(std::istream& in);
void readObject(std::istream& in);
void readString(std::istream& in);
};
} //namespace cryptonote

View file

@ -0,0 +1,81 @@
// Copyright (c) 2012-2014, The CryptoNote developers, The Bytecoin developers
//
// This file is part of Bytecoin.
//
// Bytecoin is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Bytecoin 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 Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with Bytecoin. If not, see <http://www.gnu.org/licenses/>.
#include "SerializationOverloads.h"
#include <limits>
namespace cryptonote {
void readVarint(uint64_t& value, cryptonote::ISerializer& serializer) {
const int bits = std::numeric_limits<uint64_t>::digits;
uint64_t v = 0;
for (int shift = 0;; shift += 7) {
uint8_t b;
serializer.untagged(b);
if (shift + 7 >= bits && b >= 1 << (bits - shift)) {
throw std::runtime_error("Varint overflow");
}
if (b == 0 && shift != 0) {
throw std::runtime_error("Non-canonical varint representation");
}
v |= static_cast<uint64_t>(b & 0x7f) << shift;
if ((b & 0x80) == 0) {
break;
}
}
value = v;
}
void writeVarint(uint64_t& value, cryptonote::ISerializer& serializer) {
uint64_t v = value;
while (v >= 0x80) {
uint8_t b = (static_cast<uint8_t>(v) & 0x7f) | 0x80;
serializer.untagged(b);
v >>= 7;
}
uint8_t b = static_cast<uint8_t>(v);
serializer.untagged(b);
}
void serializeVarint(uint64_t& value, const std::string& name, cryptonote::ISerializer& serializer) {
serializer.tag(name);
if (serializer.type() == cryptonote::ISerializer::INPUT) {
readVarint(value, serializer);
} else {
writeVarint(value, serializer);
}
serializer.endTag();
}
void serializeVarint(uint32_t& value, const std::string& name, cryptonote::ISerializer& serializer) {
uint64_t v = value;
serializeVarint(v, name, serializer);
value = static_cast<uint32_t>(v);
}
}

View file

@ -0,0 +1,78 @@
// Copyright (c) 2012-2014, The CryptoNote developers, The Bytecoin developers
//
// This file is part of Bytecoin.
//
// Bytecoin is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Bytecoin 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 Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with Bytecoin. If not, see <http://www.gnu.org/licenses/>.
#pragma once
#include "ISerializer.h"
#include <string>
#include <vector>
#include <unordered_map>
namespace cryptonote {
void serializeVarint(uint64_t& value, const std::string& name, cryptonote::ISerializer& serializer);
void serializeVarint(uint32_t& value, const std::string& name, cryptonote::ISerializer& serializer);
template<typename T>
void serialize(std::vector<T>& value, const std::string& name, cryptonote::ISerializer& serializer) {
std::size_t size = value.size();
serializer.beginArray(size, name);
value.resize(size);
for (size_t i = 0; i < size; ++i) {
serializer(value[i], "");
}
serializer.endArray();
}
template<typename K, typename V>
void serialize(std::unordered_map<K, V>& value, const std::string& name, cryptonote::ISerializer& serializer) {
std::size_t size;
size = value.size();
serializer.beginArray(size, name);
if (serializer.type() == cryptonote::ISerializer::INPUT) {
value.reserve(size);
for (size_t i = 0; i < size; ++i) {
K key;
V v;
serializer.beginObject("");
serializer(key, "");
serializer(v, "");
serializer.endObject();
value[key] = v;
}
} else {
for (auto kv: value) {
K key;
key = kv.first;
serializer.beginObject("");
serializer(key, "");
serializer(kv.second, "");
serializer.endObject();
}
}
serializer.endArray();
}
}