diff --git a/CMakeLists.txt b/CMakeLists.txt
index 09493a73..c2794e7b 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -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()
diff --git a/src/serialization/BinaryInputStreamSerializer.cpp b/src/serialization/BinaryInputStreamSerializer.cpp
new file mode 100644
index 00000000..31a85b32
--- /dev/null
+++ b/src/serialization/BinaryInputStreamSerializer.cpp
@@ -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 .
+
+#include "BinaryInputStreamSerializer.h"
+#include "SerializationOverloads.h"
+
+#include
+#include
+#include
+
+namespace {
+
+void deserialize(std::istream& stream, uint8_t& v) {
+ char c;
+ stream.get(c);
+ v = static_cast(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(c);
+
+ stream.get(c);
+ v += static_cast(c) << 8;
+
+ stream.get(c);
+ v += static_cast(c) << 16;
+
+ stream.get(c);
+ v += static_cast(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(c);
+ v = uc;
+
+ stream.get(c);
+ uc = static_cast(c);
+ v += (uc << 8);
+
+ stream.get(c);
+ uc = static_cast(c);
+ v += (uc << 16);
+
+ stream.get(c);
+ uc = static_cast(c);
+ v += (uc << 24);
+
+ stream.get(c);
+ uc = static_cast(c);
+ v += (uc << 32);
+
+ stream.get(c);
+ uc = static_cast(c);
+ v += (uc << 40);
+
+ stream.get(c);
+ uc = static_cast(c);
+ v += (uc << 48);
+
+ stream.get(c);
+ uc = static_cast(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 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;
+}
+
+}
diff --git a/src/serialization/BinaryInputStreamSerializer.h b/src/serialization/BinaryInputStreamSerializer.h
new file mode 100644
index 00000000..50ee18e8
--- /dev/null
+++ b/src/serialization/BinaryInputStreamSerializer.h
@@ -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 .
+
+#pragma once
+
+#include "ISerializer.h"
+#include "SerializationOverloads.h"
+
+#include
+
+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
+ ISerializer& operator()(T& value, const std::string& name) {
+ return ISerializer::operator()(value, name);
+ }
+
+private:
+ std::istream& stream;
+};
+
+}
diff --git a/src/serialization/BinaryOutputStreamSerializer.cpp b/src/serialization/BinaryOutputStreamSerializer.cpp
new file mode 100644
index 00000000..eba6bba3
--- /dev/null
+++ b/src/serialization/BinaryOutputStreamSerializer.cpp
@@ -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 .
+
+#include "BinaryOutputStreamSerializer.h"
+
+#include
+#include
+
+namespace {
+
+void serializeInteger(std::ostream& stream, uint8_t v) {
+ stream.put(static_cast(v));
+}
+
+void serializeBool(std::ostream& stream, bool v) {
+ serializeInteger(stream, static_cast(v));
+}
+
+void serializeInteger(std::ostream& stream, uint32_t v) {
+ stream.put(static_cast(v & 0xff));
+ v >>= 8;
+
+ stream.put(static_cast(v & 0xff));
+ v >>= 8;
+
+ stream.put(static_cast(v & 0xff));
+ v >>= 8;
+
+ stream.put(static_cast(v & 0xff));
+}
+
+void serializeInteger(std::ostream& stream, uint64_t v) {
+ stream.put(static_cast(v & 0xff));
+ v >>= 8;
+
+ stream.put(static_cast(v & 0xff));
+ v >>= 8;
+
+ stream.put(static_cast(v & 0xff));
+ v >>= 8;
+
+ stream.put(static_cast(v & 0xff));
+ v >>= 8;
+
+ stream.put(static_cast(v & 0xff));
+ v >>= 8;
+
+ stream.put(static_cast(v & 0xff));
+ v >>= 8;
+
+ stream.put(static_cast(v & 0xff));
+ v >>= 8;
+
+ stream.put(static_cast(v & 0xff));
+}
+
+void serializeInteger(std::ostream& stream, int64_t v) {
+ serializeInteger(stream, static_cast(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;
+}
+
+}
diff --git a/src/serialization/BinaryOutputStreamSerializer.h b/src/serialization/BinaryOutputStreamSerializer.h
new file mode 100644
index 00000000..dc4bf80f
--- /dev/null
+++ b/src/serialization/BinaryOutputStreamSerializer.h
@@ -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 .
+
+#pragma once
+
+#include "ISerializer.h"
+#include "SerializationOverloads.h"
+
+#include
+
+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
+ ISerializer& operator()(T& value, const std::string& name) {
+ return ISerializer::operator()(value, name);
+ }
+
+private:
+ std::ostream& stream;
+};
+
+}
diff --git a/src/serialization/ISerializer.h b/src/serialization/ISerializer.h
new file mode 100644
index 00000000..fe83f7b0
--- /dev/null
+++ b/src/serialization/ISerializer.h
@@ -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 .
+
+#pragma once
+
+#include
+#include
+
+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
+ ISerializer& operator()(T& value, const std::string& name);
+};
+
+template
+ISerializer& ISerializer::operator()(T& value, const std::string& name) {
+ serialize(value, name, *this);
+ return *this;
+}
+
+template
+void serialize(T& value, const std::string& name, ISerializer& serializer) {
+ value.serialize(serializer, name);
+ return;
+}
+
+/*
+template
+void serialize(std::vector& value, const std::string& name);
+
+template
+void serialize(std::unordered_map& value, const std::string& name);
+
+
+
+template
+void ISerializer::serialize(std::vector& 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
+void ISerializer::serialize(std::unordered_map& 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;
+}
+*/
+
+}
diff --git a/src/serialization/JsonInputStreamSerializer.cpp b/src/serialization/JsonInputStreamSerializer.cpp
new file mode 100644
index 00000000..124b172a
--- /dev/null
+++ b/src/serialization/JsonInputStreamSerializer.cpp
@@ -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 .
+
+#include "serialization/JsonInputStreamSerializer.h"
+
+#include
+#include
+
+namespace cryptonote {
+
+JsonInputStreamSerializer::JsonInputStreamSerializer(std::istream& stream) {
+ stream >> root;
+ JsonInputValueSerializer::setJsonValue(&root);
+}
+
+JsonInputStreamSerializer::~JsonInputStreamSerializer() {
+}
+
+} //namespace cryptonote
diff --git a/src/serialization/JsonInputStreamSerializer.h b/src/serialization/JsonInputStreamSerializer.h
new file mode 100644
index 00000000..ff67f951
--- /dev/null
+++ b/src/serialization/JsonInputStreamSerializer.h
@@ -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 .
+
+#pragma once
+
+#include
+#include
+#include
+
+//#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;
+};
+
+}
diff --git a/src/serialization/JsonInputValueSerializer.cpp b/src/serialization/JsonInputValueSerializer.cpp
new file mode 100644
index 00000000..7a1d385a
--- /dev/null
+++ b/src/serialization/JsonInputValueSerializer.cpp
@@ -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 .
+
+#include "serialization/JsonInputValueSerializer.h"
+
+#include
+#include
+
+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(value);
+ operator()(v, name);
+ value = static_cast(v);
+ return *this;
+}
+
+ISerializer& JsonInputValueSerializer::operator()(int32_t& value, const std::string& name) {
+ assert(root);
+
+ int64_t v = static_cast(value);
+ operator()(v, name);
+ value = static_cast(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(value);
+ operator()(v, name);
+ value = static_cast(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(value);
+ operator()(v, name);
+ value = static_cast(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;
+}
+
+}
diff --git a/src/serialization/JsonInputValueSerializer.h b/src/serialization/JsonInputValueSerializer.h
new file mode 100644
index 00000000..04647fdd
--- /dev/null
+++ b/src/serialization/JsonInputValueSerializer.h
@@ -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 .
+
+#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
+ ISerializer& operator()(T& value, const std::string& name) {
+ return ISerializer::operator()(value, name);
+ }
+
+private:
+ const JsonValue* root;
+ std::vector chain;
+ std::vector idxs;
+};
+
+}
diff --git a/src/serialization/JsonOutputStreamSerializer.cpp b/src/serialization/JsonOutputStreamSerializer.cpp
new file mode 100644
index 00000000..bb470295
--- /dev/null
+++ b/src/serialization/JsonOutputStreamSerializer.cpp
@@ -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 .
+
+#include "serialization/JsonOutputStreamSerializer.h"
+
+#include
+#include
+
+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(value);
+ return operator()(v, name);
+}
+
+ISerializer& JsonOutputStreamSerializer::operator()(uint32_t& value, const std::string& name) {
+ uint64_t v = static_cast(value);
+ return operator()(v, name);
+}
+
+ISerializer& JsonOutputStreamSerializer::operator()(int32_t& value, const std::string& name) {
+ int64_t v = static_cast(value);
+ return operator()(v, name);
+}
+
+ISerializer& JsonOutputStreamSerializer::operator()(int64_t& value, const std::string& name) {
+ JsonValue* val = chain.back();
+ JsonValue v;
+ v = static_cast(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(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(value);
+ return operator()(v, name);
+}
+
+ISerializer& JsonOutputStreamSerializer::operator()(bool& value, const std::string& name) {
+ JsonValue* val = chain.back();
+ JsonValue v;
+ v = static_cast(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;
+}
+
+}
+
+
diff --git a/src/serialization/JsonOutputStreamSerializer.h b/src/serialization/JsonOutputStreamSerializer.h
new file mode 100644
index 00000000..fd6ebff7
--- /dev/null
+++ b/src/serialization/JsonOutputStreamSerializer.h
@@ -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 .
+
+#pragma once
+
+#include "serialization/ISerializer.h"
+#include "serialization/JsonValue.h"
+
+#include
+
+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
+ 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 chain;
+};
+
+} // namespace cryptonote
diff --git a/src/serialization/JsonSerializationDispatcher.h b/src/serialization/JsonSerializationDispatcher.h
new file mode 100644
index 00000000..94f26e2e
--- /dev/null
+++ b/src/serialization/JsonSerializationDispatcher.h
@@ -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 .
+
+#pragma once
+
+#include
+#include
+#include
+
+#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
+inline typename std::enable_if::value, void>::type SerializeToJson(T& obj, std::string& jsonBuff) {
+ std::stringstream stream;
+ JsonOutputStreamSerializer serializer;
+
+ obj.serialize(serializer, "");
+
+ stream << serializer;
+ jsonBuff = stream.str();
+}
+
+template
+inline typename std::enable_if::value, void>::type LoadFromJson(T& obj, const std::string& jsonBuff) {
+ std::stringstream stream(jsonBuff);
+ JsonInputStreamSerializer serializer(stream);
+
+ obj.serialize(serializer, "");
+}
+
+//old epee serialization
+
+template
+inline typename std::enable_if::value, void>::type SerializeToJson(T& obj, std::string& jsonBuff) {
+ epee::serialization::store_t_to_json(obj, jsonBuff);
+}
+
+template
+inline typename std::enable_if::value, void>::type LoadFromJson(T& obj, const std::string& jsonBuff) {
+ epee::serialization::load_t_from_json(obj, jsonBuff);
+}
+
+} //namespace cryptonote
diff --git a/src/serialization/JsonValue.cpp b/src/serialization/JsonValue.cpp
new file mode 100644
index 00000000..c9ef17ba
--- /dev/null
+++ b/src/serialization/JsonValue.cpp
@@ -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 .
+
+#include "JsonValue.h"
+#include
+#include
+#include
+
+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(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(other.d_valueObject));
+ break;
+ case DOUBLE:
+ d_valueDouble = other.d_valueDouble;
+ break;
+ case STRING:
+ new(d_valueString)std::string(*reinterpret_cast(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(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(d_valueString);
+}
+
+const JsonValue& JsonValue::operator()(const std::string& name) const {
+ assert(d_type == OBJECT);
+ assert(reinterpret_cast(d_valueObject)->count(name) > 0);
+ if (d_type != OBJECT) {
+ throw(std::runtime_error("Value type is not OBJECT"));
+ }
+
+ return reinterpret_cast(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(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(d_valueArray)->at(index);
+}
+
+size_t JsonValue::size() const {
+ assert(d_type == ARRAY || d_type == OBJECT);
+ switch (d_type) {
+ case OBJECT:
+ return reinterpret_cast(d_valueString)->size();
+ case ARRAY:
+ return reinterpret_cast(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(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(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(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(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(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(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(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(jsonValue.d_valueString) << '"';
+ } else {
+ throw(std::runtime_error("Invalid type"));
+ }
+
+ return out;
+}
+
+void JsonValue::destructValue() {
+ switch (d_type) {
+ case ARRAY:
+ reinterpret_cast(d_valueArray)->~Array();
+ break;
+ case OBJECT:
+ reinterpret_cast