#include "parser.hpp" #include #include #include #include /* Implementation. */ class json_object : public json_value{ std::map kvlist; public: json_object(std::string &s){ if (!correct_object(s)){throw json_error("Value is not an array, an object or an integer");} if (!s.empty()) { try{ std::stringstream my_objects(s); std::string kvpair; std::string key; std::string value; while(std::getline(my_objects, kvpair, ',')) { key = kvpair.substr(0, kvpair.find(':')); value = kvpair.substr(kvpair.find(':') + 1, kvpair.size() - key.size() - 1); if (std::isspace(value.at(0))){value = value.substr(1, value.size() - 1);} if (!check_key(key) || value.empty()){throw json_error("Value is not an array, an object or an integer");} if (value.at(0) == '['){get_nonint(value, my_objects, '[', ']');} if (value.at(0) == '{'){get_nonint(value, my_objects, '{', '}');} json_ptr tmp = json_parse_tmp(value, false); if (kvlist.find(key) != kvlist.end()){throw json_error("Key is already in kvlist");} kvlist.try_emplace(key, std::move(tmp)); } } catch(...){ throw json_error("Value is not an array, an object or an integer"); } } } json_type type() const override{ return json_type::object; } int int_value() const override{ return 0; } json_ref item_at( int i) const override{ int count = 0; auto j = kvlist.begin(); while (j != kvlist.end()) { if (count == i){ return *j->second; } j++; count++; } throw std::out_of_range("Element does not exists"); } json_ref item_at( const std::string &s ) const override{ auto j = kvlist.begin(); while ( j != kvlist.end()) { if (s == j->first){ return *j->second; } j++; } throw std::out_of_range("Element does not exists"); } int length() const override{ return kvlist.size(); } private: bool correct_object(std::string &s){ if (s.at(s.length() - 1) != '}'){ return false; } s = s.substr(1, s.size() - 2); return true; } bool check_key(std::string &key){ if (std::isspace(key.at(0))){ key = key.substr(1, key.size() - 1); } if (std::isspace(key.at(key.size() - 1))){ key = key.substr(0, key.size() - 1); } if (key.empty()){ return false; } for (char k : key){ if (!isalpha(k)){ return false; } } return true; } }; class json_array : public json_value{ std::vector valist; public: json_array(std::string &s){ if (!correct_array(s)){throw json_error("Value is not an array, an object or an integer");} try{ std::stringstream my_array(s); std::string value; while(std::getline(my_array, value, ',')) { if (std::isspace(value.at(0))){value = value.substr(1, value.size() - 1);} if (value.at(0) == '['){get_nonint(value, my_array, '[', ']');} if (value.at(0) == '{'){get_nonint(value, my_array, '{', '}');} json_ptr tmp = json_parse_tmp(value, false); valist.push_back(std::move(tmp)); } } catch(...){ throw json_error("Value is not an array, an object or an integer"); } } json_type type() const override{ return json_type::array; } int int_value() const override{ return 0; } json_ref item_at( int i) const override{ int val_size = static_cast(valist.size()); if ((i >= val_size) || (i < 0)) { throw std::out_of_range("Element does not exists"); } return *valist[i].get(); } json_ref item_at( const std::string &s ) const override{ (void)s; throw std::out_of_range("Element does not exists"); } int length() const override{ return valist.size(); } private: bool correct_array(std::string &s){ if (s.at(s.length() - 1) != ']'){ return false; } s = s.substr(1, s.size() - 2); return true; } }; class json_int : public json_value{ int value; public: json_int(std::string &s){ if (!correct_int(s)){throw json_error("Value is not an array, an object or an integer");} try{ value = std::stoi(s); } catch(std::out_of_range &er){ value = 0; } catch(...){ throw json_error("Value is not an array, an object or an integer"); } } json_type type() const override{ return json_type::integer; } int int_value() const override{ return value; } json_ref item_at( int i) const override{ if (i == 0){ return *this; } throw std::out_of_range("Element does not exists"); } json_ref item_at( const std::string &s ) const override{ (void)s; throw std::out_of_range("Element does not exists"); return *this; } int length() const override{ return 0; } private: bool correct_int(std::string &s){ if ((s.size() > 1) && (s[0] =='0')){ return false; } if (((s.size() <= 1) && (s[0] =='-')) || ((s[0] =='-') && (s[1] == '0'))){ return false; } bool fst = true; for (char k : s){ if (fst && k =='-'){ fst = false; continue; } if (!isdigit(k)){ return false; } } return (!s.empty()); } }; json_ptr json_parse( const std::string &s){ return json_parse_tmp( s, true); } json_ptr json_parse_tmp( const std::string &s, bool swtch){ std::string value_wo_b = s; if (swtch){ if (s.find(",,") != std::string::npos || s.find(",]") != std::string::npos || s.find(",}") != std::string::npos){throw json_error("Empty input");} size_t left_ar = count(s.begin(), s.end(), '['); size_t right_ar = count(s.begin(), s.end(), ']'); size_t left_ob = count(s.begin(), s.end(), '{'); size_t right_ob = count(s.begin(), s.end(), '}'); if ((left_ar != right_ar) || (left_ob != right_ob)) {throw json_error("Wrong input");} } if(s.empty() || (s.size() == 1 && std::isspace(s.at(0))) || (s.size() == 2 && std::isspace(s.at(0)) && std::isspace(s.at(1)))){throw json_error("Empty input");} if (std::isspace(s.at(0))){ value_wo_b = value_wo_b.substr(1, value_wo_b.size() - 1); } if (std::isspace(s.at(s.size() - 1))){ value_wo_b = value_wo_b.substr(0, value_wo_b.size() - 1); } std::unique_ptr v = nullptr; switch (value_wo_b.at(0)){ case '[': v = std::make_unique(value_wo_b); break; case '{': v = std::make_unique(value_wo_b); break; default: v = std::make_unique(value_wo_b); } return v; }