MVJSON - my old lib for JSON reading / writing
/* | |
* | |
* Compact JSON format parsing lib (native cross-platform c++) | |
* | |
* Copyright (C) 2013 Victor Laskin (victor.laskin@gmail.com) | |
* Details: http://vitiy.info/?p=102 | |
* | |
* Redistribution and use in source and binary forms, with or without | |
* modification, are permitted provided that the following conditions | |
* are met: | |
* 1. Redistributions of source code must retain the above copyright | |
* notice, this list of conditions and the following disclaimer. | |
* 2. Redistributions in binary form must reproduce the above copyright | |
* notice, this list of conditions and the following disclaimer in | |
* the documentation and/or other materials provided with the | |
* distribution. | |
* 3. The names of the authors may not be used to endorse or promote | |
* products derived from this software without specific prior | |
* written permission. | |
* | |
* THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS | |
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY | |
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE | |
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER | |
* IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR | |
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN | |
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
* | |
*/ | |
#include "MVJSON.h" | |
namespace JSON { | |
MVJSONReader::MVJSONReader(const string & source) { | |
root = nullptr; | |
if (source == "") return; | |
if (source[0] == '{') | |
root = parse(source); | |
if (source[0] == '[') | |
root = parse("{\"root\":" + source + "}"); | |
} | |
MVJSONReader::~MVJSONReader() { | |
if (root != NULL) | |
delete root; | |
} | |
MVJSONNode::~MVJSONNode() { | |
if (values.size() > 0) | |
for (int i = 0; i < values.size(); i++) | |
delete values.at(i); | |
} | |
MVJSONNode* MVJSONReader::parse(string text) | |
{ | |
string s = trim(text); | |
if (s.length() < 2) return NULL; | |
// object | |
if ((s[0] == '{') && (s[s.length() - 1] == '}')) | |
{ | |
// erase last and first symbols | |
s.erase(0, 1); | |
s.erase(s.length() - 1, 1); | |
vector<string> parts; | |
splitList(s, parts); | |
MVJSONNode* node = new MVJSONNode(); | |
for (int i = 0; i < parts.size(); i++) | |
node->values.push_back(parseValue(parts.at(i), false)); | |
return node; | |
} | |
return NULL; | |
} | |
MVJSONValue* MVJSONReader::parseValue(string text, bool hasNoName) | |
{ | |
string key; | |
string s; | |
splitInHalf(text, ":", key, s); | |
key = trim(key); | |
s = trim(s); | |
if (key.length() > 2) | |
{ | |
// strip " | |
key.erase(0, 1); | |
key.erase(key.length() - 1, 1); | |
} | |
if (hasNoName) | |
{ | |
s = text; | |
key = ""; | |
} | |
if (s == "false") // bool | |
return new MVJSONValue(key, false); | |
if (s == "true") // bool | |
return new MVJSONValue(key, true); | |
if (s == "null") // null | |
return new MVJSONValue(key, MVJSON_TYPE_NULL); | |
char first = s[0]; | |
if (first == '"') // string | |
return new MVJSONValue(key, s.substr(1, s.length() - 2)); | |
if (first == '{') // object | |
return new MVJSONValue(key, parse(s)); | |
if (first == '[') // array | |
{ | |
s.erase(0, 1); | |
s.erase(s.length() - 1, 1); | |
MVJSONValue* val = new MVJSONValue(key, MVJSON_TYPE_ARRAY); | |
if (s != "") | |
{ | |
vector<string> parts; | |
splitList(s, parts); | |
for (int i = 0; i < parts.size(); i++) | |
val->arrayValue.push_back(parseValue(parts.at(i), true)); | |
} | |
return val; | |
} | |
// else its number! | |
if (s.find(".") == string::npos) | |
return new MVJSONValue(key, s, stringToLongLong(s)); | |
else | |
return new MVJSONValue(key, s, stringToDouble(s)); | |
return NULL; | |
} | |
MVJSONValue::~MVJSONValue() | |
{ | |
if (objValue != NULL) | |
delete objValue; | |
if (arrayValue.size() > 0) | |
for (int i = 0; i < arrayValue.size(); i++) | |
delete arrayValue.at(i); | |
} | |
void MVJSONValue::init(MVJSON_TYPE valueType) | |
{ | |
this->valueType = valueType; | |
objValue = NULL; | |
name = ""; | |
} | |
MVJSONValue::MVJSONValue(const string& name, MVJSON_TYPE valueType) | |
{ | |
init(valueType); | |
this->name = name; | |
} | |
MVJSONValue::MVJSONValue(const string& name, bool value) | |
{ | |
init(MVJSON_TYPE_BOOL); | |
this->name = name; | |
boolValue = value; | |
} | |
MVJSONValue::MVJSONValue(const string& name, const string& value) | |
{ | |
init(MVJSON_TYPE_STRING); | |
this->name = name; | |
stringValue = value; | |
// here we switch back special chars | |
// \" \\ \/ \b \f \n \r \t \u four-hex-digits | |
replace(stringValue, "\\\"", "\""); | |
replace(stringValue, "\\\\", "\\"); | |
replace(stringValue, "\\/", "/"); | |
replace(stringValue, "\\b", "\b"); | |
replace(stringValue, "\\f", "\f"); | |
replace(stringValue, "\\n", "\n"); | |
replace(stringValue, "\\r", "\r"); | |
replace(stringValue, "\\t", "\t"); | |
// TODO - \u four-hex-digits | |
// SS::replace(stringValue, "\\\\", "\\"); | |
} | |
MVJSONValue::MVJSONValue(const string& name, const string& source, long long value) | |
{ | |
init(MVJSON_TYPE_INT); | |
this->name = name; | |
stringValue = source; | |
intValue = value; | |
} | |
MVJSONValue::MVJSONValue(const string& name, const string& source, double value) | |
{ | |
init(MVJSON_TYPE_DOUBLE); | |
this->name = name; | |
stringValue = source; | |
doubleValue = value; | |
} | |
MVJSONValue::MVJSONValue(const string& name, MVJSONNode* value) | |
{ | |
init(MVJSON_TYPE_OBJECT); | |
this->name = name; | |
objValue = value; | |
} | |
bool MVJSONNode::hasField(const string& name) | |
{ | |
if (values.size() == 0) return false; | |
for (int i = 0; i < values.size(); i++) | |
if (values.at(i)->name == name) | |
return true; | |
return false; | |
} | |
MVJSONValue* MVJSONNode::getField(const string& name) | |
{ | |
if (values.size() == 0) return NULL; | |
for (int i = 0; i < values.size(); i++) | |
if (values.at(i)->name == name) | |
return values.at(i); | |
return NULL; | |
} | |
MVJSONValue* MVJSONValue::field(const string& name) { | |
return objValue->getField(name); | |
} | |
double MVJSONNode::getFieldDouble(const string& name) | |
{ | |
MVJSONValue* value = getField(name); | |
if (value == NULL) return 0; | |
if (value->valueType == MVJSON_TYPE_INT) return value->intValue; | |
if (value->valueType == MVJSON_TYPE_DOUBLE) return value->doubleValue; | |
return 0; | |
} | |
int MVJSONNode::getFieldInt(const string& name) | |
{ | |
MVJSONValue* value = getField(name); | |
if (value == NULL) return 0; | |
if (value->valueType == MVJSON_TYPE_INT) return (int)value->intValue; | |
return 0; | |
} | |
long long MVJSONNode::getFieldLongLong(const string& name) | |
{ | |
MVJSONValue* value = getField(name); | |
if (value == NULL) return 0; | |
if (value->valueType == MVJSON_TYPE_INT) return value->intValue; | |
return 0; | |
} | |
string MVJSONNode::getFieldString(const string& name) | |
{ | |
MVJSONValue* value = getField(name); | |
if (value == NULL) return ""; | |
if (value->valueType == MVJSON_TYPE_STRING) return value->stringValue; | |
if (value->valueType == MVJSON_TYPE_DOUBLE) return value->stringValue; | |
if (value->valueType == MVJSON_TYPE_INT) return value->stringValue; | |
return ""; | |
} | |
bool MVJSONNode::getFieldBool(const string& name) | |
{ | |
MVJSONValue* value = getField(name); | |
if (value == NULL) return false; | |
if (value->valueType == MVJSON_TYPE_INT) return (bool)value->intValue; | |
if (value->valueType == MVJSON_TYPE_BOOL) return value->boolValue; | |
return false; | |
} | |
double MVJSONValue::getFieldDouble(const string& name) | |
{ | |
if (objValue == NULL) return 0; | |
return objValue->getFieldDouble(name); | |
} | |
int MVJSONValue::getFieldInt(const string& name) | |
{ | |
if (objValue == NULL) return 0; | |
return objValue->getFieldInt(name); | |
} | |
long long MVJSONValue::getFieldLongLong(const string& name) | |
{ | |
if (objValue == NULL) return 0; | |
return objValue->getFieldLongLong(name); | |
} | |
string MVJSONValue::getFieldString(const string& name) | |
{ | |
if (objValue == NULL) return ""; | |
return objValue->getFieldString(name); | |
} | |
bool MVJSONValue::getFieldBool(const string& name) | |
{ | |
if (objValue == NULL) return false; | |
return objValue->getFieldBool(name); | |
} | |
// -------------------- writer --------------------------> | |
MVJSONWriter::MVJSONWriter() | |
{ | |
result = ""; | |
depth = 0; | |
counts.resize(50); | |
std::fill(counts.begin(), counts.end(), 0); | |
} | |
} /* namespace F2 */ |
/* | |
* | |
* Compact JSON format parsing lib (native cross-platform c++) | |
* | |
* Copyright (C) 2013 Victor Laskin (victor.laskin@gmail.com) | |
* Details: http://vitiy.info/compact-lib-for-json-parsing-cross-platform-c/ | |
* | |
* Redistribution and use in source and binary forms, with or without | |
* modification, are permitted provided that the following conditions | |
* are met: | |
* 1. Redistributions of source code must retain the above copyright | |
* notice, this list of conditions and the following disclaimer. | |
* 2. Redistributions in binary form must reproduce the above copyright | |
* notice, this list of conditions and the following disclaimer in | |
* the documentation and/or other materials provided with the | |
* distribution. | |
* 3. The names of the authors may not be used to endorse or promote | |
* products derived from this software without specific prior | |
* written permission. | |
* | |
* THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS | |
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY | |
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE | |
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER | |
* IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR | |
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN | |
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
* | |
*/ | |
#include <string> | |
#include <vector> | |
#include <sstream> | |
#include <stdlib.h> | |
#ifndef MVJSON_H_ | |
#define MVJSON_H_ | |
using namespace std; | |
namespace JSON { | |
/// JSON node types | |
enum MVJSON_TYPE | |
{ | |
MVJSON_TYPE_NULL, | |
MVJSON_TYPE_OBJECT, | |
MVJSON_TYPE_ARRAY, | |
MVJSON_TYPE_STRING, | |
MVJSON_TYPE_INT, | |
MVJSON_TYPE_DOUBLE, | |
MVJSON_TYPE_BOOL | |
}; | |
class MVJSONUtils { | |
protected: | |
// string parsing functions | |
inline static long long stringToLongLong(const string & s); ///< convert string to long long | |
inline static double stringToDouble(const string & s); ///< convert string to float | |
inline static bool symbolToBeTrimmed(const char& c); ///< check if symbol is space, tab or new line break | |
inline static string trim(const string & text); ///< trim spaces, tabs and line break | |
inline static void replace(string & target, const string & oldStr, const string & newStr); ///< replace all occurrences of substring | |
inline static void splitInHalf(const string & s, const string & separator, string & begin, string & end); ///< second half (output) | |
inline static void splitList(const string & s, vector<string> & parts); | |
}; | |
class MVJSONNode; | |
/// JSON Value | |
class MVJSONValue : public MVJSONUtils { | |
public: | |
MVJSONValue(const string& name, MVJSON_TYPE valueType); | |
MVJSONValue(const string& name, bool value); | |
MVJSONValue(const string& name, const string& value); | |
MVJSONValue(const string& name, const string& source, long long value); | |
MVJSONValue(const string& name, const string& source, double value); | |
MVJSONValue(const string& name, MVJSONNode* value); | |
virtual ~MVJSONValue(); | |
string name; ///< value name [optional] | |
MVJSON_TYPE valueType; ///< type of node | |
string stringValue; ///< value if data has string type | |
bool boolValue; ///< value if data has bool type | |
long long intValue; ///< value if data has int type | |
double doubleValue; ///< value if data has double type | |
MVJSONNode* objValue; ///< value if data has object type | |
vector<MVJSONValue*> arrayValue; ///< array of values | |
MVJSONValue* field(const string& name); | |
double getFieldDouble(const string& name); ///< get value of double field of VALUE OBJECT (objValue) | |
int getFieldInt(const string& name); ///< get value of int field of VALUE OBJECT (objValue) | |
string getFieldString(const string& name); ///< get value of string field of VALUE OBJECT (objValue) | |
bool getFieldBool(const string& name); ///< get value of bool field of VALUE OBJECT (objValue) | |
long long getFieldLongLong(const string& name); ///< get long long value from field | |
inline MVJSONValue* at(unsigned int i){ return arrayValue.at(i); } | |
inline int size() { if (valueType == MVJSON_TYPE_ARRAY) return arrayValue.size(); else return 1; } | |
private: | |
void init(MVJSON_TYPE valueType); | |
}; | |
template <typename T> struct is_vector { static const bool value = false; }; | |
template <typename T> struct is_vector< std::vector<T> > { static const bool value = true; }; | |
template <typename T> struct is_vector< const std::vector<T> > { static const bool value = true; }; | |
/// JSON Node (Object) | |
class MVJSONNode { | |
public: | |
virtual ~MVJSONNode(); | |
vector<MVJSONValue*> values; ///< values (props) | |
bool hasField(const string& name); ///< check that object has field | |
MVJSONValue* getField(const string& name); ///< get field by name | |
template<class T> | |
inline T getValue(const string& name, typename enable_if<!is_vector<T>::value, T>::type* = nullptr); ///< get value of specified type | |
template<class T> | |
inline T getValue(const string& name, typename enable_if<is_vector<T>::value, T>::type* = nullptr); ///< get value of specified type | |
double getFieldDouble(const string& name); ///< get value of double field | |
int getFieldInt(const string& name); ///< get value of int field | |
long long getFieldLongLong(const string& name); ///< get value of int field | |
string getFieldString(const string& name); ///< get value of string field | |
bool getFieldBool(const string& name); ///< get value of bool field | |
}; | |
/// Compact JSON parser (based on specification: http://www.json.org/) | |
class MVJSONReader : public MVJSONUtils { | |
public: | |
MVJSONReader(const string & source); ///< constructor from json source | |
virtual ~MVJSONReader(); | |
MVJSONNode* root; ///< root object (if its null - parsing was failed) | |
private: | |
MVJSONValue* parseValue(string text, bool hasNoName); ///< parse value | |
MVJSONNode* parse(string text); ///< parse node | |
}; | |
/// Simple writer into JSON format | |
class MVJSONWriter : public MVJSONUtils { | |
public: | |
MVJSONWriter(); | |
string result; | |
inline MVJSONWriter& begin(); | |
inline MVJSONWriter& begin(const string& name); | |
inline MVJSONWriter& end(); | |
inline MVJSONWriter& beginList(const string& name); | |
inline MVJSONWriter& endList(); | |
template< typename T > | |
inline MVJSONWriter& add(const string& name, const T& value); | |
template< typename T > | |
inline MVJSONWriter& add(const T& value); | |
inline MVJSONWriter& include(const string& json); | |
private: | |
inline void addComma(); | |
vector<int> counts; | |
int depth; | |
template< typename T > | |
inline string toString(const T& value); | |
template< typename T > | |
inline string toString(const vector<T>& value); | |
}; | |
// --------------- reader -------------------------------------> | |
template<class T> | |
//inline typename enable_if<!is_vector<T>::value, T>::type | |
inline T | |
MVJSONNode::getValue(const string& name, typename enable_if<!is_vector<T>::value, T>::type*) | |
{ | |
MVJSONValue* value = getField(name); | |
if (value == NULL) return ""; | |
return value->stringValue; | |
} | |
template<class T> | |
//inline typename enable_if<is_vector<T>::value, T>::type | |
inline T | |
MVJSONNode::getValue(const string& name, typename enable_if<is_vector<T>::value, T>::type*) | |
{ | |
typename std::remove_const<T>::type result; | |
MVJSONValue* value = getField(name); | |
if (value == NULL) return result; | |
for (auto item : value->arrayValue) | |
{ | |
result.push_back(remove_pointer<decltype(std::declval<T>().at(0).get())>::type::fromJSON(item->objValue)); | |
} | |
return result; | |
} | |
template<> | |
//inline typename enable_if<is_vector<T>::value, T>::type | |
inline const vector<int> | |
MVJSONNode::getValue(const string& name, typename enable_if<is_vector<const vector<int>>::value, const vector<int>>::type*) | |
{ | |
vector<int> result; | |
MVJSONValue* value = getField(name); | |
if (value == NULL) return result; | |
for (auto item : value->arrayValue) | |
{ | |
result.push_back((int)item->intValue); | |
} | |
return result; | |
} | |
template<> | |
inline const long long MVJSONNode::getValue(const string& name, typename enable_if<!is_vector<const long long>::value, const long long>::type*) | |
{ | |
MVJSONValue* value = getField(name); | |
if (value == NULL) return 0; | |
return value->intValue; | |
} | |
template<> | |
inline const long MVJSONNode::getValue(const string& name, typename enable_if<!is_vector<const long>::value, const long>::type*) | |
{ | |
MVJSONValue* value = getField(name); | |
if (value == NULL) return 0; | |
return (long)value->intValue; | |
} | |
template<> | |
inline const int MVJSONNode::getValue(const string& name, typename enable_if<!is_vector<const int>::value, const int>::type*) | |
{ | |
MVJSONValue* value = getField(name); | |
if (value == NULL) return 0; | |
return (int)value->intValue; | |
} | |
template<> | |
inline const bool MVJSONNode::getValue(const string& name, typename enable_if<!is_vector<const bool>::value, const bool>::type*) | |
{ | |
MVJSONValue* value = getField(name); | |
if (value == NULL) return false; | |
return value->boolValue; | |
} | |
template<> | |
inline const double MVJSONNode::getValue(const string& name, typename enable_if<!is_vector<const double>::value, const double>::type*) | |
{ | |
MVJSONValue* value = getField(name); | |
if (value == NULL) return 0.0; | |
return value->doubleValue; | |
} | |
template<> | |
inline const float MVJSONNode::getValue(const string& name, typename enable_if<!is_vector<const float>::value, const float>::type*) | |
{ | |
MVJSONValue* value = getField(name); | |
if (value == NULL) return 0.0; | |
return value->doubleValue; | |
} | |
// ------------------- inlined string processing functions -------------> | |
inline long long MVJSONUtils::stringToLongLong(const string & s) | |
{ | |
return atoll(s.c_str()); | |
} | |
inline double MVJSONUtils::stringToDouble(const string & s) | |
{ | |
return atof(s.c_str()); | |
} | |
inline bool MVJSONUtils::symbolToBeTrimmed(const char& c ///< the char to test | |
) | |
{ | |
if (c == ' ') return true; | |
if (c == '\n') return true; | |
if (c == '\r') return true; | |
if (c == '\t') return true; | |
return false; | |
} | |
inline string MVJSONUtils::trim(const string & text ///< the text to trim | |
) | |
{ | |
if (text.length() == 0) return ""; | |
int start = 0; | |
while ((start < text.length()) && (symbolToBeTrimmed(text[start]))) start++; | |
int end = text.length() - 1; | |
while ((end > 0) && (symbolToBeTrimmed(text[end]))) end--; | |
if (start > end) return ""; | |
return text.substr(start, end - start + 1); | |
} | |
inline void MVJSONUtils::splitInHalf(const string & s, ///< source string to split up | |
const string & separator, ///< separator string) | |
string & begin, ///< first part (output) | |
string & end ///< second half (output) | |
) | |
{ | |
int pos = s.find(separator); | |
if (pos == string::npos) { begin = s; end = ""; return; } | |
begin = s.substr(0, pos); | |
end = s.substr(pos + separator.length(), s.length() - pos - separator.length()); | |
} | |
/// split string by "," - ignore content inside of "{", "}", "[", "]" and quotations "...." | |
/// also take \" into account | |
/// (Code should be cleared of comments beforehand) | |
inline void MVJSONUtils::splitList(const string & s, ///< string to be splitted | |
vector<string> & parts ///< result parts | |
) | |
{ | |
bool isNotInQuotes = true; | |
int b1 = 0; | |
int b2 = 0; | |
int lastPos = 0; | |
const char* start = s.c_str(); | |
const char* ps = start; | |
while (*ps) // *ps != 0 | |
{ | |
if ((*ps == ',') && (isNotInQuotes) && (b1 == 0) && (b2 == 0)) | |
{ | |
parts.push_back(s.substr(lastPos, ps - start - lastPos)); | |
lastPos = ps - start + 1; | |
} | |
if (isNotInQuotes) | |
{ | |
if (*ps == '{') b1++; | |
if (*ps == '}') b1--; | |
if (*ps == '[') b2++; | |
if (*ps == ']') b2--; | |
} | |
if (*ps == '"') | |
{ | |
isNotInQuotes = !isNotInQuotes; | |
if (ps != start) | |
if (*(ps-1) == '\\') | |
isNotInQuotes = !isNotInQuotes; | |
} | |
ps++; | |
} | |
parts.push_back(s.substr(lastPos, s.length() - lastPos)); | |
} | |
inline void MVJSONUtils::replace(string & target, ///< text to be modified | |
const string & oldStr, ///< old string | |
const string & newStr ///< new string | |
) | |
{ | |
unsigned int pos = 0; | |
unsigned int oldLen = oldStr.length(); | |
unsigned int newLen = newStr.length(); | |
for (;;) | |
{ | |
pos = target.find(oldStr, pos); | |
if (pos == string::npos) break; | |
target.replace(pos, oldLen, newStr); | |
pos += newLen; | |
} | |
} | |
// ------------------------ writer -----------------------> | |
inline void MVJSONWriter::addComma() | |
{ | |
if (depth < 0) return; | |
if (counts[depth] > 0) result += ","; | |
} | |
inline MVJSONWriter& MVJSONWriter::begin() | |
{ | |
addComma(); | |
result += "{"; | |
counts[depth]++; | |
depth++; | |
counts[depth] = 0; | |
return *this; | |
} | |
inline MVJSONWriter& MVJSONWriter::begin(const string& name) | |
{ | |
addComma(); | |
result += "\"" + name + "\":{"; | |
counts[depth]++; | |
depth++; | |
counts[depth] = 0; | |
return *this; | |
} | |
inline MVJSONWriter& MVJSONWriter::end() | |
{ | |
result += "}"; | |
depth--; | |
return *this; | |
} | |
template< typename T > | |
inline MVJSONWriter& MVJSONWriter::add(const string& name, const T& value) | |
{ | |
addComma(); | |
result += "\"" + name + "\":" + toString(value); | |
counts[depth]++; | |
return *this; | |
} | |
template< typename T > | |
inline MVJSONWriter& MVJSONWriter::add(const T& value) | |
{ | |
addComma(); | |
result += toString(value); | |
counts[depth]++; | |
return *this; | |
} | |
inline MVJSONWriter& MVJSONWriter::include(const string& json) | |
{ | |
addComma(); | |
result += json; | |
counts[depth]++; | |
return *this; | |
} | |
inline MVJSONWriter& MVJSONWriter::beginList(const string& name) | |
{ | |
addComma(); | |
result += "\"" + name + "\":["; | |
counts[depth]++; | |
depth++; | |
counts[depth] = 0; | |
return *this; | |
} | |
inline MVJSONWriter& MVJSONWriter::endList() | |
{ | |
result += "]"; | |
depth--; | |
return *this; | |
} | |
template< typename T > | |
inline string MVJSONWriter::toString(const T& value) | |
{ | |
// default overload is for string-like types! | |
return "\"" + value + "\""; | |
/* | |
std::stringstream ss; | |
//ss.precision(6); | |
ss << value; | |
return ss.str(); | |
*/ | |
} | |
template< typename T > | |
inline string MVJSONWriter::toString(const vector<T>& value) | |
{ | |
string result = "["; | |
for (auto item : value) | |
result += ((result != "[") ? "," : "") + item->toJSON(); | |
result += "]"; | |
return result; | |
} | |
template<> | |
inline string MVJSONWriter::toString(const vector<int>& value) | |
{ | |
string result = "["; | |
for (auto item : value) | |
result += ((result != "[") ? "," : "") + std::to_string(item); | |
result += "]"; | |
return result; | |
} | |
template<> | |
inline string MVJSONWriter::toString(const int& value) | |
{ | |
return std::to_string(value); | |
} | |
template<> | |
inline string MVJSONWriter::toString(const double& value) | |
{ | |
std::ostringstream os ; | |
os.precision(10); | |
os << value ; | |
return os.str() ; | |
} | |
template<> | |
inline string MVJSONWriter::toString(const float& value) | |
{ | |
return std::to_string(value); | |
} | |
template<> | |
inline string MVJSONWriter::toString(const long long& value) | |
{ | |
return std::to_string(value); | |
} | |
template<> | |
inline string MVJSONWriter::toString(const bool& value) | |
{ | |
return value ? "true" : "false"; | |
} | |
#if defined(OS_LINUX) || defined(F2_EMSCRIPTEN) | |
template<> | |
inline string MVJSONWriter::toString(const time_t& value) | |
{ | |
return std::to_string(value); | |
} | |
#endif | |
template<> | |
inline string MVJSONWriter::toString(const string& value) | |
{ | |
return "\"" + value + "\""; | |
} | |
template<> | |
inline string MVJSONWriter::toString(const char* const & value) | |
{ | |
return "\"" + string(value) + "\""; | |
} | |
} /* namespace F2 */ | |
#endif /* MVJSON_H_ */ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment