#include "json.h" #include #include #include namespace qi = boost::spirit::qi; using namespace JSON; bool JSON::parse(const std::string& s, Value& v) { typedef std::string::const_iterator Iterator; qi::rule bool_p = qi::lit("false")[qi::_val = false] | qi::lit("true")[qi::_val = true]; qi::rule()> number_p = (qi::int_ >> !(qi::lit('.') | 'e' | 'E')) | qi::float_; qi::rule char_p = (qi::char_ - '\"' - '\\') | '\\' >> ( qi::char_('\"') | qi::char_('\\') | qi::char_('/') | 'b' >> qi::attr('\b') | 'f' >> qi::attr('\f') | 'n' >> qi::attr('\n') | 'r' >> qi::attr('\r') | 't' >> qi::attr('\t') ); qi::rule string_p = '\"' >> *(char_p) >> '\"'; qi::rule value_p; qi::rule array_p = '[' >> -(value_p % ',') >> ']'; qi::rule()> key_value_p = string_p >> ":" >> value_p; qi::rule object_p = '{' >> -(key_value_p % ',') >> '}'; value_p = qi::omit[*qi::space] >> (bool_p | number_p | string_p | array_p | object_p) >> qi::omit[*qi::space]; return qi::parse(s.begin(), s.end(), value_p, v); } struct generate : public boost::static_visitor { std::ostream& stream; generate(std::ostream& s) : stream(s) {} std::ostream& operator()(const bool& x) const { return stream << (x ? "true" : "false"); } std::ostream& operator()(const int& x) const { return stream << x; } std::ostream& operator()(const float& x) const { return stream << x; } std::ostream& operator()(const std::string& x) const { stream << '\"'; for(std::string::const_iterator it = x.begin(); it != x.end(); it++) { switch(*it) { case '\"': case '\\': stream << '\\' << *it; break; case '\b': stream << "\\b"; break; case '\f': stream << "\\f"; break; case '\n': stream << "\\n"; break; case '\r': stream << "\\r"; break; case '\t': stream << "\\t"; break; default: stream << *it; } } return stream << '\"'; } std::ostream& operator()(const Array& x) const { stream << "["; for(Array::const_iterator it = x.begin();;) { boost::apply_visitor(generate(stream), *it); if(++it == x.end()) { break; } stream << ", "; } return stream << "]"; } std::ostream& operator()(const Object& x) const { stream << "{"; for(Object::const_iterator it = x.begin();;) { (*this)(it->first); stream << ": "; boost::apply_visitor(generate(stream), it->second); if(++it == x.end()) { break; } stream << ", "; } return stream << "}"; } }; std::ostream& operator<<(std::ostream& s, const Value& v) { return boost::apply_visitor(generate(s), v); }