mirror of https://github.com/GOSTSec/poolserver
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
184 lines
6.0 KiB
184 lines
6.0 KiB
#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(); |
|
|
|
if (!qi::phrase_parse(begin, end, g, ascii::space)) |
|
throw JSONException("Failed to parse JSON"); |
|
} |
|
} |
|
|
|
#endif |