diff --git a/JsonCpp.vcxproj b/JsonCpp.vcxproj new file mode 100644 index 000000000..3c5a77a8f --- /dev/null +++ b/JsonCpp.vcxproj @@ -0,0 +1,177 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + + + + + + + + + + + + + + + + + + + + + {8B925520-1F2F-496F-BDF3-A49BB386846F} + Win32Proj + JsonCpp + 10.0.17763.0 + + + + StaticLibrary + true + Unicode + v141 + + + StaticLibrary + true + Unicode + v141 + + + StaticLibrary + false + true + Unicode + v141 + + + StaticLibrary + false + true + Unicode + v141 + + + + + + + + + + + + + + + + + + + $(SolutionDir)lib\$(Configuration)_$(PlatformShortName)\$(ProjectName)\ + $(SolutionDir)build\$(Configuration)_$(PlatformShortName)\$(ProjectName)\ + + + $(SolutionDir)lib\$(Configuration)_$(PlatformShortName)\$(ProjectName)\ + $(SolutionDir)build\$(Configuration)_$(PlatformShortName)\$(ProjectName)\ + + + $(SolutionDir)lib\$(Configuration)_$(PlatformShortName)\$(ProjectName)\ + $(SolutionDir)build\$(Configuration)_$(PlatformShortName)\$(ProjectName)\ + + + $(SolutionDir)lib\$(Configuration)_$(PlatformShortName)\$(ProjectName)\ + $(SolutionDir)build\$(Configuration)_$(PlatformShortName)\$(ProjectName)\ + + + + + + Level3 + Disabled + _ITERATOR_DEBUG_LEVEL=0;WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) + include + stdcpp17 + + + Windows + true + + + + + + + Level3 + Disabled + WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) + include + stdcpp17 + + + Windows + true + + + + + Level3 + + + MaxSpeed + true + true + WIN32;_ITERATOR_DEBUG_LEVEL=0;NDEBUG;_LIB;%(PreprocessorDefinitions) + include + stdcpp17 + + + Windows + true + true + true + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) + include + stdcpp17 + + + Windows + true + true + true + + + + + + \ No newline at end of file diff --git a/JsonCpp.vcxproj.filters b/JsonCpp.vcxproj.filters new file mode 100644 index 000000000..44c195ed4 --- /dev/null +++ b/JsonCpp.vcxproj.filters @@ -0,0 +1,62 @@ + + + + + {efe9ea6e-e506-49b7-bd1d-f1eba404fc00} + + + {25362820-7c73-465e-ab0d-81088e935eb0} + + + {93ccfe8f-3fb1-4610-aafd-7e72557fcab4} + + + + + include\json + + + include\json + + + include\json + + + include\json + + + include\json + + + include\json + + + include\json + + + include\json + + + include + + + lib_json + + + + + lib_json + + + lib_json + + + lib_json + + + + + lib_json + + + \ No newline at end of file diff --git a/include/JsonSerializer.h b/include/JsonSerializer.h new file mode 100644 index 000000000..5db17f2e8 --- /dev/null +++ b/include/JsonSerializer.h @@ -0,0 +1,454 @@ +/* + * Copyright (c) 2011-2012 Promit Roy + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef JSONSERIALIZER_H +#define JSONSERIALIZER_H + +#include +#include +#include + +enum class SerializerMode +{ + Reader, + Writer +}; + +class JsonSerializer +{ +private: + //SFINAE garbage to detect whether a type has a Serialize member + typedef char SerializeNotFound; + struct SerializeFound { char x[2]; }; + struct SerializeFoundStatic { char x[3]; }; + + template + struct SerializeTester { }; + template + struct SerializeTesterStatic { }; + template + static SerializeFound SerializeTest(SerializeTester*); + template + static SerializeFoundStatic SerializeTest(SerializeTesterStatic*); + template + static SerializeNotFound SerializeTest(...); + + template + struct HasSerialize + { + static const bool value = sizeof(SerializeTest(0)) == sizeof(SerializeFound); + }; + + //Serialize using a free function defined for the type (default fallback) + template + void SerializeImpl(TValue& value, + typename std::enable_if::value >::type* dummy = 0) + { + //prototype for the serialize free function, so we will get a link error if it's missing + //this way we don't need a header with all the serialize functions for misc types (eg math) + void Serialize(TValue&, JsonSerializer&); + + Serialize(value, *this); + } + + //Serialize using a member function Serialize(JsonSerializer&) + template + void SerializeImpl(TValue& value, typename std::enable_if::value >::type* dummy = 0) + { + value.Serialize(*this); + } + +public: + JsonSerializer(bool isWriter) + : IsWriter(isWriter) + { } + JsonSerializer(bool isWriter, Json::Value value) + : IsWriter(isWriter), JsonValue(value) + { } + JsonSerializer(SerializerMode mode) + : IsWriter(mode == SerializerMode::Writer) + { } + + template + void Serialize(TKey key, TValue& value, typename std::enable_if::value >::type* dummy = 0) + { + JsonSerializer subVal(IsWriter); + if(!IsWriter) + { + subVal.JsonValue = JsonValue[key]; + if(subVal.JsonValue.isNull()) + return; + } + + subVal.SerializeImpl(value); + + if(IsWriter) + JsonValue[key] = subVal.JsonValue; + } + + //Serialize a string value + template + void Serialize(TKey key, std::string& value) + { + if(IsWriter) + Write(key, value); + else + Read(key, value); + } + + //Serialize a non class type directly using JsonCpp + template + void Serialize(TKey key, TValue& value, typename std::enable_if::value >::type* dummy = 0) + { + if(IsWriter) + Write(key, value); + else + Read(key, value); + } + + //Serialize an enum type to JsonCpp + template + void Serialize(TKey key, TEnum& value, typename std::enable_if::value >::type* dummy = 0) + { + int ival = (int) value; + if(IsWriter) + { + Write(key, ival); + } + else + { + Read(key, ival); + value = (TEnum) ival; + } + } + + //Serialize only when writing (saving), useful for r-values + template + void WriteOnly(TKey key, TValue value, typename std::enable_if::value >::type* dummy = 0) + { + if(IsWriter) + Write(key, value); + } + + //Serialize a series of items by start and end iterators + template + void WriteOnly(TKey key, TItor first, TItor last) + { + if(!IsWriter) + return; + + JsonSerializer subVal(IsWriter); + int index = 0; + subVal.JsonValue = Json::arrayValue; + for(TItor it = first; it != last; ++it) + { + subVal.Serialize(index, *it); + ++index; + } + JsonValue[key] = subVal.JsonValue; + } + + template + void ReadOnly(TKey key, TValue& value, typename std::enable_if::value >::type* dummy = 0) + { + if(!IsWriter) + Read(key, value); + } + + template + void ReadOnly(std::vector& vec) + { + if(IsWriter) + return; + if(!JsonValue.isArray()) + return; + + vec.clear(); + vec.reserve(vec.size() + JsonValue.size()); + for(int i = 0; i < JsonValue.size(); ++i) + { + TValue val; + Serialize(i, val); + vec.push_back(val); + } + } + + template + void Serialize(TKey key, std::vector& vec) + { + if(IsWriter) + { + WriteOnly(key, vec.begin(), vec.end()); + } + else + { + JsonSerializer subVal(IsWriter); + subVal.JsonValue = JsonValue[key]; + subVal.ReadOnly(vec); + } + } + + template + void ReadOnly(std::deque& dq) + { + if(IsWriter) + return; + if(!JsonValue.isArray()) + return; + + dq.clear(); + for(int i = 0; i < JsonValue.size(); ++i) + { + TValue val; + Serialize(i, val); + dq.push_back(val); + } + } + + template + void Serialize(TKey key, std::deque& dq) + { + if(IsWriter) + { + WriteOnly(key, dq.begin(), dq.end()); + } + else + { + JsonSerializer subVal(IsWriter); + subVal.JsonValue = JsonValue[key]; + subVal.ReadOnly(dq); + } + } + + template + void ReadOnly(std::map& m) + { + if(IsWriter) + return; + if(!JsonValue.isObject()) + return; + + m.clear(); + for(auto it = JsonValue.begin(); it != JsonValue.end(); ++it) + { + JsonSerializer subVal(IsWriter); + subVal.JsonValue = *it; + std::string key = it.key().asString(); + TValue value; + Serialize(key, value); + m[key] = value; + } + } + + template + void WriteOnly(TKey key, std::map& m) + { + if(!IsWriter) + return; + + JsonSerializer subVal(IsWriter); + for(auto it = m.begin(); it != m.end(); ++it) + { + subVal.Serialize(it->first, it->second); + } + JsonValue[key] = subVal.JsonValue; + } + + template + void Serialize(TKey key, std::map& m) + { + if(IsWriter) + { + WriteOnly(key, m); + } + else + { + JsonSerializer subVal(IsWriter); + subVal.JsonValue = JsonValue[key]; + subVal.ReadOnly(m); + } + } + + //Append a Json::Value directly + template + void WriteOnly(TKey key, const Json::Value& value) + { + Write(key, value); + } + + //Forward a pointer + template + void Serialize(TKey key, TValue* value, typename std::enable_if::value >::type* dummy = 0) + { + Serialize(key, *value); + } + + template + void WriteOnly(TKey key, TValue* value, typename std::enable_if::value >::type* dummy = 0) + { + Serialize(key, *value); + } + + template + void ReadOnly(TKey key, TValue* value, typename std::enable_if::value >::type* dummy = 0) + { + ReadOnly(key, *value); + } + + //intellisense hack, doesn't do anything + template + void SerializeNVP(T name) + { + } + + //Shorthand operator to serialize + template + void operator()(TKey key, TValue&& value) + { + Serialize(key, value); + } + + Json::Value JsonValue; + bool IsWriter; + +private: + template + void Write(TKey key, TValue value) + { + JsonValue[key] = value; + } + + template + void Write(TKey key, long value) + { + JsonValue[key] = (int) value; + } + + template + void Write(TKey key, unsigned long value) + { + JsonValue[key] = (unsigned int) value; + } + + template + void Write(TKey key, size_t value) + { + JsonValue[key] = (unsigned int)value; + } + + template + void Read(TKey key, TValue& value, typename std::enable_if::value >::type* dummy = 0) + { + Json::Value subval = JsonValue[key]; + if(subval.isNull()) + return; + int ival = subval.asInt(); + value = (TValue) ival; + } + + template + void Read(TKey key, bool& value) + { + Json::Value subval = JsonValue[key]; + if(subval.isNull()) + return; + value = subval.asBool(); + } + + template + void Read(TKey key, int& value) + { + Json::Value subval = JsonValue[key]; + if(subval.isNull()) + return; + value = subval.asInt(); + } + + template + void Read(TKey key, long& value) + { + Json::Value subval = JsonValue[key]; + if(subval.isNull()) + return; + value = subval.asInt(); + } + + template + void Read(TKey key, unsigned int& value) + { + Json::Value subval = JsonValue[key]; + if(subval.isNull()) + return; + value = subval.asUInt(); + } + + template + void Read(TKey key, unsigned long& value) + { + Json::Value subval = JsonValue[key]; + if(subval.isNull()) + return; + value = subval.asUInt(); + } + + /*template + void Read(TKey key, size_t& value) + { + Json::Value subval = JsonValue[key]; + if(subval.isNull()) + return; + value = subval.asUInt(); + }*/ + + template + void Read(TKey key, float& value) + { + Json::Value subval = JsonValue[key]; + if(subval.isNull()) + return; + value = subval.asFloat(); + } + + template + void Read(TKey key, double& value) + { + Json::Value subval = JsonValue[key]; + if(subval.isNull()) + return; + value = subval.asDouble(); + } + + template + void Read(TKey key, std::string& value) + { + Json::Value subval = JsonValue[key]; + if(subval.isNull()) + return; + value = subval.asString(); + } +}; + +//"name value pair", derived from boost::serialization terminology +#define NVP(name) #name, name +#define SerializeNVP(name) Serialize(NVP(name)) + +#endif