Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- namespace Json {
- class Node : std::variant<std::vector<Node>,
- std::map<std::string, Node>,
- double,
- bool,
- std::string> {
- public:
- using variant::variant;
- const auto& AsArray() const {
- return std::get<std::vector<Node>>(*this);
- }
- const auto& AsMap() const {
- return std::get<std::map<std::string, Node>>(*this);
- }
- /*
- int AsInt() const {
- return std::get<int>(*this);
- }
- */
- double AsDouble() const {
- return std::get<double>(*this);
- }
- bool AsBool() const {
- return std::get<bool>(*this);
- }
- const auto& AsString() const {
- return std::get<std::string>(*this);
- }
- friend std::ostream &operator << ( std::ostream &os, const Json::Node &node ) ;
- };
- std::ostream &operator << ( std::ostream &os, const Json::Node &node ) {
- if ( std::holds_alternative<std::string>(node) ) {
- return os << "\"" << node.AsString() << "\"";
- }
- if ( std::holds_alternative<bool>(node) ) {
- return os << (node.AsBool()?"true":"false");
- }
- /*
- if ( std::holds_alternative<int>(node) ) {
- return os << node.AsInt();
- }
- */
- if ( std::holds_alternative<double>(node) ) {
- //return os << std::setprecision(8) << node.AsDouble();
- auto x= node.AsDouble();
- if ( fabs((long long)x-x) < 1e-7 )
- return os << static_cast<int>(x);
- return os << std::setprecision(8) << node.AsDouble();
- }
- if ( std::holds_alternative<std::map<std::string,Json::Node>>(node) ) {
- os << "{";
- bool flag= false;
- for ( const auto &it: node.AsMap() ) {
- os << (flag?",\n\t":"") << "\"" << it.first << "\"" << ": " << it.second;
- flag= true ;
- }
- return os << "}";
- }
- if ( std::holds_alternative<std::vector<Json::Node>>(node) ) {
- os << "[";
- bool flag= false;
- for ( const auto &x: node.AsArray() ) {
- os << (flag?",\n\t":"") << x;
- flag= true ;
- }
- return os << "]";
- }
- return os;
- }
- class Document {
- public:
- explicit Document(Node root) : root(move(root)) {}
- const Node& GetRoot() const {
- return root;
- }
- private:
- Node root;
- };
- Node LoadNode(istream& input) ;
- Node LoadArray(istream& input) {
- vector<Node> result;
- for (char c; input >> c && c != ']'; ) {
- if (c != ',') {
- input.putback(c);
- }
- result.push_back(LoadNode(input));
- }
- return Node(move(result));
- }
- /*
- Node LoadInt(istream& input) {
- int result = 0;
- while (isdigit(input.peek())) {
- result *= 10;
- result += input.get() - '0';
- }
- return Node(result);
- }
- */
- Node LoadDouble( istream &input ) {
- double x= 0, y= 0;
- int sign= 1;
- if ( input.peek() == '-' ) {
- sign= -1, input.get();
- }
- else if ( input.peek() == '+' )
- input.get();
- for ( ;isdigit(input.peek()); x*= 10, x+= input.get()-'0' ) ;
- if ( input.peek() == '.' ) {
- int len= 0;
- for ( input.get(); isdigit(input.peek()); y*= 10, y+= input.get()-'0', ++len ) ;
- y/= pow(10,len);
- }
- return Node(sign*(x+y));
- }
- Node LoadBool( istream &input ) {
- std::string s;
- for ( ;islower(input.peek()); s.push_back(input.get()) ) ;
- return Node(s == "true");
- }
- Node LoadString(istream& input) {
- string line;
- getline(input, line, '"');
- return Node(move(line));
- }
- Node LoadDict(istream& input) {
- map<string, Node> result;
- for (char c; input >> c && c != '}'; ) {
- if (c == ',') {
- input >> c;
- }
- string key = LoadString(input).AsString();
- input >> c;
- result.emplace(move(key), LoadNode(input));
- }
- return Node(move(result));
- }
- Node LoadDoubleFromString( std::string s ) {
- auto res= std::stringstream(s);
- return LoadDouble(res);
- }
- Node LoadIntFromString( std::string s ) {
- auto res= std::stringstream(s);
- return LoadDouble(res);
- //return LoadInt(res);
- }
- Node LoadNode(istream& input) {
- char c;
- input >> c;
- if (c == '[') {
- return LoadArray(input);
- } else if (c == '{') {
- return LoadDict(input);
- } else if (c == '"') {
- return LoadString(input);
- } else if ( c == 't' or c == 'f' ) {
- input.putback(c);
- return LoadBool(input);
- } else {
- input.putback(c);
- std::string s;
- for ( ;isdigit(input.peek()) or input.peek() == '.'; s.push_back(input.get()) ) ;
- auto pos= s.find('.');
- if ( pos == std::string::npos )
- return LoadIntFromString(std::move(s));
- return LoadDoubleFromString(std::move(s));
- }
- }
- Document Load(istream& input) {
- return Document{LoadNode(input)};
- }
- };
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement