mirror of https://github.com/GOSTSec/poolserver
Intel
11 years ago
12 changed files with 571 additions and 101 deletions
@ -1,22 +1,109 @@
@@ -1,22 +1,109 @@
|
||||
#include "JSON.h" |
||||
#include "JSONReader.h" |
||||
#include <sstream> |
||||
#include <algorithm> |
||||
#include <vector> |
||||
#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; |
||||
json.pt = new boost::property_tree::ptree(); |
||||
std::stringstream ss; |
||||
ss.str(jsonstring); |
||||
boost::property_tree::json_parser::read_json(ss, *json.pt); |
||||
return json; |
||||
JSON node; |
||||
JSONReader::Parse(jsonstring, node); |
||||
return node; |
||||
} |
||||
|
||||
std::string JSON::ToString() |
||||
{ |
||||
std::stringstream ss; |
||||
boost::property_tree::json_parser::write_json(ss, *pt); |
||||
return ss.str(); |
||||
Write(ss); |
||||
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 @@
@@ -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