Skip to content
Snippets Groups Projects
Select Git revision
  • 9162d34b4af7dd34cbeba01372d7492dfd05886d
  • master default protected
  • johannes
  • partial_parser
  • Aloui_Dary
  • ignore_punct
  • AC
  • classifier
  • fixhelp
  • libmacaon2
  • error_predictor
  • morpho
  • ssrnn
  • tfparsing
  • silvio
  • tagger_options
  • maca_trans_frame_parser
  • alexis
  • new_config
  • tagparse
  • maca_graph_parser
21 results

json.h

Blame
  • json.h 7.44 KiB
    #pragma once
    
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    
    #include <iostream>
    #include <string>
    #include <sstream>
    #include <vector>
    #include <map>
    
    namespace json {
    
        typedef enum { Null, True, False, Number, String, List, Object } Type;
    
        std::string replace_all(std::string subject, const std::string& search, const std::string& replace) {
            size_t pos = 0;
            while ((pos = subject.find(search, pos)) != std::string::npos) {
                subject.replace(pos, search.length(), replace);
                pos += replace.length();
            }
            return subject;
        }
    
        class Value {
            public:
            Type type;
            double number;
            std::string string;
            std::vector<Value> list;
            std::map<std::string, Value> object;
            public:
            Value() : type(Null) { }
            Value(Type _type) : type(_type) { }
            Value(const std::string& text) : type(String), string(text) { }
            Value(double _number) : type(Number), number(_number) { }
            void append(const Value& v) { list.push_back(v); }
            Value& operator[](int index) { return list[index]; }
            Value& operator[](const std::string& key) { 
                return object[key]; }
            int length() const {
                if(type == List) { return list.size(); }
                if(type == Object) { return object.size(); }
                if(type == String) { return string.length(); }
                return 1;
            }
            std::string to_json() const {
                std::stringstream out;
                if(type == String) out << "\"" << replace_all(string, "\"", "\\\"") << "\""; 
                else if(type == Null) out << "null";
                else if(type == True) out << "true";
                else if(type == False) out << "false";
                else if(type == Number) out << number;
                else if(type == List) {
                    out << "[";
                    for(int i = 0; i < length(); i++) {
                        if(i > 0) out << ",";
                        out << list[i].to_json();
                    }
                    out << "]";
                } else if(type == Object) {
                    out << "{";
                    for(std::map<std::string, Value>::const_iterator i = begin(); i != end(); i++) {
                        if(i != begin()) out << ",";
                        out << "\"" << i->first << "\":" << i->second.to_json();
                    }
                    out << "}";
                } else {
                    out << "error";
                }
                return out.str();
            }
            std::string to_string() const { return string; }
            int to_int() const { return (int) number; }
            double to_double() const { return (double) number; }
            std::map<std::string, Value>::const_iterator begin() const { return object.begin(); }
            std::map<std::string, Value>::const_iterator end() const { return object.end(); }
        };
    
        class Iterator {
            const Value& backend;
            std::map<std::string, Value>::const_iterator iterator;
            public:
            Iterator(const Value& target) : backend(target), iterator(target.begin()) { }
            const std::string key() { return iterator->first; }
            const Value value() { return iterator->second; }
            bool hasNext() { return iterator != backend.end(); }
            void next() { iterator++; }
        };
    
        class Parser {
            const char* input;
    
            void error() {
                throw std::string("error at \"" + std::string(input) + "\"");
            }
    
            void space() {
                while(*input != '\0' && (*input == ' ' || *input == '\t' || *input == '\n' || *input == '\r')) input++;
            }
    
            Value null() {
                input += 4;
                return Value(Null);
            }
    
            Value _false() {
                input += 5;
                return Value(False);
            }
    
            Value _true() {
                input += 4;
                return Value(True);
            }
    
            Value number() {
                char* end = NULL;
                double value = strtod(input, &end);
                input = end;
                return Value(value);
            }
    
            Value string() {
                input++;
                char prev = '"';
                const char* start = input;
                while(*input != '\0') {
                    if(*input == '"' && prev != '\\') {
                        char text[input - start + 1];
                        strncpy(text, start, input - start);
                        text[input - start] = '\0';
                        input++;
                        return Value(replace_all(text, "\\\"", "\""));
                    }
                    prev = *input;
                    input++;
                }
                error();
                return Value(Null);
            }
    
            Value list() {
                input++;
                Value l(List);
                while(*input != '\0') {
                    space();
                    if(*input == ']') {
                        input++;
                        return l;
                    }
                    l.append(value());
                    space();
                    if(*input == ']') {
                        input++;
                        return l;
                    } else if(*input == ',') {
                        input++;
                    } else {
                        error();
                    }
                }
                error();
                return Value(Null);
            }
    
            Value object() {
                input++;
                Value o(Object);
                while(*input != '\0') {
                    space();
                    if(*input == '}') {
                        input++;
                        return o;
                    }
                    std::string key = string().to_string();
                    space();
                    if(*input != ':') error();
                    else {
                        input++;
                        space();
                        o[key] = value();
                        space();
                    }
                    if(*input == '}') {
                        input++;
                        return o;
                    } else if(*input == ',') {
                        input++;
                    } else {
                        error();
                        return Value(Null);
                    }
                }
                error();
                return Value(Null);
            }
    
            Value value() {
                if(*input == '{') return object();
                else if(*input == '[') return list();
                else if(*input == '"') return string();
                else if(!strncmp(input, "true", 4)) return _true();
                else if(!strncmp(input, "false", 5)) return _false();
                else if(!strncmp(input, "null", 4)) return null();
                else return number();
            }
    
            public:
            Value parse(const char* p) {
                input = p;
                space();
                Value v = value();
                space();
                if(*input != '\0') error();
                return v;
            }
        };
    
        Value parse(const std::string& str) {
            return Parser().parse(str.c_str());
        }
        Value parse(const char* input) {
            return Parser().parse(input);
        }
        Value parse_file(const char* filename) {
            FILE* fp = fopen(filename, "r");
            if(!fp) { std::cerr << "ERROR: cannot load file \"" << filename << "\"\n"; exit(1); }
            fseek(fp, 0, SEEK_END);
            off_t length = ftell(fp);
            char* content = new char[length + 1];
            fseek(fp, 0, SEEK_SET);
            size_t read = fread(content, length, 1, fp);
            if(read != 1) { std::cerr << "ERROR: could not read content of \"" << filename << "\"\n"; exit(1); }
            fclose(fp);
            content[length] = '\0';
            Value v = parse(content);
            delete[] content;
            return v;
        }
    
    }