mirror of https://github.com/GOSTSec/poolserver
Intel
11 years ago
12 changed files with 571 additions and 101 deletions
@ -1,22 +1,109 @@ |
|||||||
#include "JSON.h" |
#include "JSON.h" |
||||||
|
#include "JSONReader.h" |
||||||
#include <sstream> |
#include <sstream> |
||||||
#include <algorithm> |
#include <algorithm> |
||||||
#include <vector> |
#include <vector> |
||||||
#include <boost/foreach.hpp> |
#include <boost/foreach.hpp> |
||||||
|
#include <boost/assign.hpp> |
||||||
|
#include <boost/algorithm/string.hpp> |
||||||
|
#include <boost/lexical_cast.hpp> |
||||||
|
#include "Log.h" |
||||||
|
|
||||||
JSON JSON::FromString(std::string jsonstring) |
JSON JSON::FromString(std::string jsonstring) |
||||||
{ |
{ |
||||||
JSON json; |
JSON node; |
||||||
json.pt = new boost::property_tree::ptree(); |
JSONReader::Parse(jsonstring, node); |
||||||
std::stringstream ss; |
return node; |
||||||
ss.str(jsonstring); |
|
||||||
boost::property_tree::json_parser::read_json(ss, *json.pt); |
|
||||||
return json; |
|
||||||
} |
} |
||||||
|
|
||||||
std::string JSON::ToString() |
std::string JSON::ToString() |
||||||
{ |
{ |
||||||
std::stringstream ss; |
std::stringstream ss; |
||||||
boost::property_tree::json_parser::write_json(ss, *pt); |
Write(ss); |
||||||
return ss.str(); |
std::string json = ss.str(); |
||||||
|
|
||||||
|
// If it's array we have to wrap json into {}
|
||||||
|
if (json[0] == '[') |
||||||
|
return "{" + json + "}"; |
||||||
|
else |
||||||
|
return json; |
||||||
|
} |
||||||
|
|
||||||
|
void JSON::Write(std::stringstream& ss) |
||||||
|
{ |
||||||
|
switch (_type) |
||||||
|
{ |
||||||
|
case JSON_NULL: |
||||||
|
ss << "null"; |
||||||
|
break; |
||||||
|
case JSON_BOOL: |
||||||
|
if (GetBool()) |
||||||
|
ss << "true"; |
||||||
|
else |
||||||
|
ss << "false"; |
||||||
|
break; |
||||||
|
case JSON_INTEGER: |
||||||
|
ss << GetInt(); |
||||||
|
break; |
||||||
|
case JSON_DOUBLE: |
||||||
|
ss << GetDouble(); |
||||||
|
break; |
||||||
|
case JSON_STRING: |
||||||
|
ss << '"' << EscapeString(GetString()) << '"'; |
||||||
|
break; |
||||||
|
case JSON_ARRAY: |
||||||
|
{ |
||||||
|
ss << '['; |
||||||
|
for (uint32 i = 0; i < _vec.size(); ++i) |
||||||
|
{ |
||||||
|
if (i) |
||||||
|
ss << ", "; |
||||||
|
_vec[i].Write(ss); |
||||||
|
} |
||||||
|
ss << ']'; |
||||||
|
break; |
||||||
|
} |
||||||
|
case JSON_OBJECT: |
||||||
|
{ |
||||||
|
ss << '{'; |
||||||
|
for (uint64 i = 0; i < _mapOrder.size(); ++i) |
||||||
|
{ |
||||||
|
if (i) |
||||||
|
ss << ','; |
||||||
|
std::string key = _mapOrder[i]; |
||||||
|
ss << '"' << key << "\":"; |
||||||
|
_map[key].Write(ss); |
||||||
|
} |
||||||
|
ss << '}'; |
||||||
|
break; |
||||||
|
} |
||||||
|
default: |
||||||
|
throw "Unknown type"; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
std::string JSON::EscapeString(std::string str) |
||||||
|
{ |
||||||
|
static std::map<char, std::string> escapes = boost::assign::map_list_of |
||||||
|
('"', "\\\"") |
||||||
|
('\'', "\\'"); |
||||||
|
/*('\\', "\\\\")
|
||||||
|
('/', "\\/") |
||||||
|
('b', "\\b") |
||||||
|
('f', "\\f") |
||||||
|
('n', "\\n") |
||||||
|
('r', "\\r") |
||||||
|
('t', "\\t") |
||||||
|
('u', "\\u");*/ |
||||||
|
|
||||||
|
for (uint32 i = 0; i < str.length(); ++i) |
||||||
|
{ |
||||||
|
if (escapes.count(str[i])) { |
||||||
|
std::string esc = escapes[str[i]]; |
||||||
|
str.replace(i, 1, esc.c_str(), esc.length()); |
||||||
|
i += esc.length()-1; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
return str; |
||||||
} |
} |
||||||
|
@ -0,0 +1,183 @@ |
|||||||
|
#ifndef JSON_READER_H_ |
||||||
|
#define JSON_READER_H_ |
||||||
|
|
||||||
|
#include "Common.h" |
||||||
|
#include "JSON.h" |
||||||
|
|
||||||
|
#include <boost/spirit/include/qi.hpp> |
||||||
|
#include <boost/function.hpp> |
||||||
|
#include <boost/bind.hpp> |
||||||
|
#include <string> |
||||||
|
|
||||||
|
namespace qi = boost::spirit::qi; |
||||||
|
namespace ascii = boost::spirit::ascii; |
||||||
|
|
||||||
|
namespace JSONReader |
||||||
|
{ |
||||||
|
class SemanticFunctions |
||||||
|
{ |
||||||
|
public: |
||||||
|
SemanticFunctions(JSON& node) |
||||||
|
{ |
||||||
|
_stack.push_back(&node); |
||||||
|
} |
||||||
|
|
||||||
|
void BeginObject(char ch) |
||||||
|
{ |
||||||
|
if (_stack.back()->GetType() == JSON_NULL) |
||||||
|
_stack.back()->SetType(JSON_OBJECT); |
||||||
|
else { |
||||||
|
JSON* node = new JSON(JSON_OBJECT); |
||||||
|
_stack.push_back(node); |
||||||
|
} |
||||||
|
} |
||||||
|
void EndObject(char ch) |
||||||
|
{ |
||||||
|
JSON* node = _stack.back(); |
||||||
|
_stack.pop_back(); |
||||||
|
if (_stack.size()) { |
||||||
|
SetData(*node); |
||||||
|
delete node; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
void BeginArray(char ch) |
||||||
|
{ |
||||||
|
if (_stack.back()->GetType() == JSON_NULL) |
||||||
|
_stack.back()->SetType(JSON_ARRAY); |
||||||
|
else { |
||||||
|
JSON* node = new JSON(JSON_ARRAY); |
||||||
|
_stack.push_back(node); |
||||||
|
} |
||||||
|
} |
||||||
|
void EndArray(char ch) |
||||||
|
{ |
||||||
|
JSON* node = _stack.back(); |
||||||
|
_stack.pop_back(); |
||||||
|
if (_stack.size()) { |
||||||
|
SetData(*node); |
||||||
|
delete node; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
void ObjectKey(std::string str) |
||||||
|
{ |
||||||
|
_nameStack.push_back(str); |
||||||
|
} |
||||||
|
|
||||||
|
void String(std::string str) |
||||||
|
{ |
||||||
|
SetData(str); |
||||||
|
} |
||||||
|
|
||||||
|
void BoolTrue(std::string str) |
||||||
|
{ |
||||||
|
SetData(true); |
||||||
|
} |
||||||
|
|
||||||
|
void BoolFalse(std::string str) |
||||||
|
{ |
||||||
|
SetData(false); |
||||||
|
} |
||||||
|
|
||||||
|
void Null(std::string str) |
||||||
|
{ |
||||||
|
SetData(JSON(JSON_NULL)); |
||||||
|
} |
||||||
|
|
||||||
|
void Integer(int64 val) |
||||||
|
{ |
||||||
|
SetData(val); |
||||||
|
} |
||||||
|
|
||||||
|
void Double(double val) |
||||||
|
{ |
||||||
|
SetData(val); |
||||||
|
} |
||||||
|
|
||||||
|
template<typename T> |
||||||
|
void SetData(T data) |
||||||
|
{ |
||||||
|
if (_stack.back()->GetType() == JSON_OBJECT) { |
||||||
|
_stack.back()->Set<T>(_nameStack.back(), data); |
||||||
|
_nameStack.pop_back(); |
||||||
|
} else if (_stack.back()->GetType() == JSON_ARRAY) |
||||||
|
_stack.back()->Add<T>(data); |
||||||
|
else |
||||||
|
throw "fail"; |
||||||
|
} |
||||||
|
private: |
||||||
|
// Push all nested nodes here
|
||||||
|
std::vector<JSON*> _stack; |
||||||
|
// Node is added to the main tree when is closed so we need a name stack
|
||||||
|
std::vector<std::string> _nameStack; |
||||||
|
}; |
||||||
|
|
||||||
|
template<typename T> |
||||||
|
struct strict_real_policies : qi::real_policies<T> |
||||||
|
{ |
||||||
|
static bool const expect_dot = true; |
||||||
|
}; |
||||||
|
|
||||||
|
qi::real_parser<double, strict_real_policies<double> > strict_double; |
||||||
|
|
||||||
|
template<typename Iterator> |
||||||
|
struct Grammar : qi::grammar<Iterator, ascii::space_type> |
||||||
|
{ |
||||||
|
Grammar(SemanticFunctions& smfunc) : _smfunc(smfunc), Grammar::base_type(json) |
||||||
|
{ |
||||||
|
typedef boost::function<void(char, qi::unused_type, qi::unused_type)> CharFunc; |
||||||
|
typedef boost::function<void(std::string, qi::unused_type, qi::unused_type)> StrFunc; |
||||||
|
typedef boost::function<void(double, qi::unused_type, qi::unused_type)> DoubleFunc; |
||||||
|
typedef boost::function<void(int64, qi::unused_type, qi::unused_type)> IntFunc; |
||||||
|
|
||||||
|
CharFunc BeginObj(boost::bind(&SemanticFunctions::BeginObject, &_smfunc, _1)); |
||||||
|
CharFunc EndObj(boost::bind(&SemanticFunctions::EndObject, &_smfunc, _1)); |
||||||
|
CharFunc BeginArray(boost::bind(&SemanticFunctions::BeginArray, &_smfunc, _1)); |
||||||
|
CharFunc EndArray(boost::bind(&SemanticFunctions::EndArray, &_smfunc, _1)); |
||||||
|
StrFunc NewKey(boost::bind(&SemanticFunctions::ObjectKey, &_smfunc, _1)); |
||||||
|
StrFunc NewStr(boost::bind(&SemanticFunctions::String, &_smfunc, _1)); |
||||||
|
StrFunc NewTrue(boost::bind(&SemanticFunctions::BoolTrue, &_smfunc, _1)); |
||||||
|
StrFunc NewFalse(boost::bind(&SemanticFunctions::BoolFalse, &_smfunc, _1)); |
||||||
|
StrFunc NewNull(boost::bind(&SemanticFunctions::Null, &_smfunc, _1)); |
||||||
|
DoubleFunc NewDouble(boost::bind(&SemanticFunctions::Double, &_smfunc, _1)); |
||||||
|
IntFunc NewInt(boost::bind(&SemanticFunctions::Integer, &_smfunc, _1)); |
||||||
|
|
||||||
|
json = object | array; |
||||||
|
object = qi::char_('{')[BeginObj] >> -members >> qi::char_('}')[EndObj]; |
||||||
|
members = pair % ','; |
||||||
|
pair = string[NewKey] >> ':' >> value; |
||||||
|
array = qi::char_('[')[BeginArray] >> -elements >> qi::char_(']')[EndArray]; |
||||||
|
elements = value % ','; |
||||||
|
value = object | array | string[NewStr] | number | qi::string("true")[NewTrue] | qi::string("false")[NewFalse] | qi::string("null")[NewNull]; |
||||||
|
string = qi::lexeme['"' >> *(qi::char_ - '"') >> '"']; |
||||||
|
number = strict_double[NewDouble] | qi::long_long[NewInt]; |
||||||
|
} |
||||||
|
|
||||||
|
qi::rule<Iterator, ascii::space_type> json; |
||||||
|
qi::rule<Iterator, ascii::space_type> object; |
||||||
|
qi::rule<Iterator, ascii::space_type> members; |
||||||
|
qi::rule<Iterator, ascii::space_type> pair; |
||||||
|
qi::rule<Iterator, ascii::space_type> array; |
||||||
|
qi::rule<Iterator, ascii::space_type> elements; |
||||||
|
qi::rule<Iterator, ascii::space_type> value; |
||||||
|
qi::rule<Iterator, std::string(), ascii::space_type> string; |
||||||
|
qi::rule<Iterator, ascii::space_type> number; |
||||||
|
|
||||||
|
// Functions
|
||||||
|
SemanticFunctions& _smfunc; |
||||||
|
}; |
||||||
|
|
||||||
|
inline void Parse(std::string str, JSON& node) |
||||||
|
{ |
||||||
|
SemanticFunctions smfunc(node); |
||||||
|
Grammar<std::string::const_iterator> g(smfunc); |
||||||
|
|
||||||
|
std::string::const_iterator begin = str.begin(); |
||||||
|
std::string::const_iterator end = str.end(); |
||||||
|
|
||||||
|
qi::phrase_parse(begin, end, g, ascii::space); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
#endif |
Loading…
Reference in new issue