// SSPHH/Fluxions/Unicornfish/Viperfish/Hatchetfish/Sunfish/KASL/GLUT Extensions // Copyright (C) 2017 Jonathan Metzgar // All rights reserved. // // This program is free software : you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as // published by the Free Software Foundation, either version 3 of the // License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the // GNU Affero General Public License for more details. // // You should have received a copy of the GNU Affero General Public License // along with this program.If not, see . // // For any other type of licensing, please contact me at jmetzgar@outlook.com #ifndef KASL_JSON_HPP #define KASL_JSON_HPP #include #include #include #include #include #include namespace KASL { class JSON; using JSONPtr = std::shared_ptr; class JSON : public std::enable_shared_from_this { public: using SharedPtr = shared_ptr; enum class Type { Object, Array, String, Number, True, False, Null }; protected: JSON() { } JSON(const JSON &json); public: JSON(Type whichType); JSON(const int ival) { type_ = Type::Number; dval_ = ival; } JSON(const double dval) { type_ = Type::Number; dval_ = dval; } JSON(const std::string &sval) { type_ = Type::String; sval_ = sval; } explicit JSON(initializer_list numberList) { type_ = Type::Array; for (auto it = numberList.begin(); it != numberList.end(); it++) { array_.push_back(JSON::MakeNumber(*it)); } } explicit JSON(const vector & numberList) { type_ = Type::Array; for (auto it = numberList.begin(); it != numberList.end(); it++) { array_.push_back(JSON::MakeNumber(*it)); } } explicit JSON(initializer_list numberList) { type_ = Type::Array; for (auto it = numberList.begin(); it != numberList.end(); it++) { array_.push_back(JSON::MakeNumber(*it)); } } explicit JSON(const vector & numberList) { type_ = Type::Array; for (auto it = numberList.begin(); it != numberList.end(); it++) { array_.push_back(JSON::MakeNumber(*it)); } } explicit JSON(initializer_list numberList) { type_ = Type::Array; for (auto it = numberList.begin(); it != numberList.end(); it++) { array_.push_back(JSON::MakeNumber(*it)); } } explicit JSON(const vector & numberList) { type_ = Type::Array; for (auto it = numberList.begin(); it != numberList.end(); it++) { array_.push_back(JSON::MakeNumber(*it)); } } explicit JSON(initializer_list stringList) { type_ = Type::Array; for (auto it = stringList.begin(); it != stringList.end(); it++) { array_.push_back(JSON::MakeString(*it)); } } explicit JSON(const vector & stringList) { type_ = Type::Array; for (auto it = stringList.begin(); it != stringList.end(); it++) { array_.push_back(JSON::MakeString(*it)); } } explicit JSON(initializer_list> members) { type_ = Type::Object; for (auto it = members.begin(); it != members.end(); it++) { map_[it->first] = it->second; } } explicit JSON(const map & members) { type_ = Type::Object; for (auto it = members.begin(); it != members.end(); it++) { map_[it->first] = it->second; } } JSON(const JSONPtr & json); ~JSON(); static JSONPtr MakeNull() { return make_shared(Type::Null); } static JSONPtr MakeBool(bool state = false) { return make_shared(state ? Type::True : Type::False); } static JSONPtr MakeString(const string & sval) { return make_shared(sval); } static JSONPtr MakeString() { return make_shared(""); } static JSONPtr MakeNumber(int ival = 0) { return make_shared(ival); } static JSONPtr MakeNumber(double dval = 0.0) { return make_shared(dval); } static JSONPtr MakeArray() { return make_shared(Type::Array); } static JSONPtr MakeArray(const vector & numberList) { return make_shared(numberList); } static JSONPtr MakeArray(initializer_list numberList) { return make_shared(numberList); } static JSONPtr MakeArray(const vector & numberList) { return make_shared(numberList); } static JSONPtr MakeArray(initializer_list numberList) { return make_shared(numberList); } static JSONPtr MakeArray(const vector & numberList) { return make_shared(numberList); } static JSONPtr MakeArray(initializer_list numberList) { return make_shared(numberList); } static JSONPtr MakeArray(const vector & stringList) { return make_shared(stringList); } static JSONPtr MakeArray(initializer_list stringList) { return make_shared(stringList); } static JSONPtr MakeObject() { return make_shared(Type::Object); } static JSONPtr MakeObject(initializer_list> members) { return make_shared(members); } static JSONPtr MakeObject(const map members) { return make_shared(members); } const JSONPtr &operator = (const JSONPtr &rhs); inline const JSONPtr &operator = (int ival) { Clear(); dval_ = ival; type_ = Type::Number; return shared_from_this(); } inline const JSONPtr &operator = (double dval) { Clear(); dval_ = dval; type_ = Type::Number; return shared_from_this(); } inline const JSONPtr &operator = (const std::string &sval) { Clear(); sval_ = sval; type_ = Type::String; return shared_from_this(); } inline const bool operator==(int ival) const { return IsNumber() && dval_ == (double)ival; } inline const bool operator==(const std::string &sval) const { return IsString() && sval_ == sval; } inline const bool operator==(bool bval) const { return (bval && IsTrue()) ? true : (!bval && IsFalse()) ? true : false; } inline const bool operator==(const JSONPtr &rhs) const { return Equals(rhs); } inline const bool operator==(const void *ptr) const { if (ptr == nullptr && IsNull()) return true; if (ptr == this) return true; return false; } std::string Serialize() const; bool Deserialize(const std::string &json); long DeserializeParseTokens(const TokenVector &tokens, long i = 0); inline bool IsNull() const { return type_ == Type::Null; } inline bool IsTrue() const { return type_ == Type::True; } inline bool IsFalse() const { return type_ == Type::False; } inline bool IsBoolean() const { return type_ == Type::True || type_ == Type::False; } inline bool IsFinite() const { return type_ == Type::Number && isfinite(dval_); } inline bool IsNaN() const { return type_ == Type::Number && isnan(dval_); } inline bool IsNumber() const { return type_ == Type::Number; } inline bool IsString() const { return type_ == Type::String; } inline bool IsArray() const { return type_ == Type::Array; } inline bool IsObject() const { return type_ == Type::Object; } static JSONPtr NewArray() { return make_shared(Type::Array); } static JSONPtr NewObject() { return make_shared(Type::Object); } static JSONPtr NewNumber(const double value) { return make_shared(value); } static JSONPtr NewBoolean(const bool value) { return make_shared(value); } static JSONPtr NewString(const string & value) { return make_shared(value); } static JSONPtr New(const JSONPtr & value) { return make_shared(value); } static JSONPtr New() { return make_shared(Type::Null); } inline int Size() const { if (IsArray()) return (int)array_.size(); if (IsObject()) return (int)map_.size(); return 0; } inline bool Empty() const { if (IsArray()) return array_.empty(); if (IsObject()) return map_.empty(); return true; } void Clear() { type_ = Type::Null; dval_ = 0.0; sval_.clear(); array_.clear(); map_.clear(); } inline int AsInt() const { return IsNumber() ? (int)dval_ : 0; } inline int64_t AsInt64() const { return IsNumber() ? (int64_t)dval_ : 0; } inline double AsDouble() const { return IsNumber() ? dval_ : 0.0; } inline float AsFloat() const { return IsNumber() ? float(dval_) : 0.0f; } inline size_t Length() const { return IsArray() ? array_.size() : IsObject() ? map_.size() : 0; } inline std::map & AsObject() noexcept { return map_; } inline const std::map & AsObject() const noexcept { return map_; } inline std::vector & AsArray() noexcept { return array_; } inline const std::vector & AsArray() const noexcept { return array_; } inline vector AsIntArray() const noexcept { vector result; for (auto & e : array_) { if (e) result.push_back(e->AsInt()); } return result; } inline vector AsFloatArray() const noexcept { vector result; for (auto & e : array_) { if (e) result.push_back(e->AsFloat()); } return result; } inline vector AsDoubleArray() const noexcept { vector result; for (auto & e : array_) { if (e) result.push_back(e->AsDouble()); } return result; } inline JSON & AsJSON() noexcept { return *this; } inline const JSON & AsJSON() const noexcept { return *this; } inline bool Has(const string & key) const noexcept { if (!IsObject()) return false; if (map_.find(key) == map_.end()) return false; return true; } inline bool HasKeyOfType(const string & key, Type type) const noexcept { auto it = map_.find(key); if (it != map_.end() && it->second->type_ == type) return true; return false; } inline JSONPtr & operator[] (int index) { if (IsArray()) return array_.at(index); throw std::runtime_error("JSON object is not an array"); } inline const JSONPtr & operator[] (int index) const { if (IsArray()) return array_.at(index); throw std::runtime_error("JSON object is not an array"); } inline JSONPtr & operator[] (const string & key) { if (IsObject()) return map_.at(key); throw std::runtime_error("JSON object is not an object"); } inline const JSONPtr & operator[] (const string & key) const { if (IsObject()) return map_.at(key); throw std::runtime_error("JSON object is not an object"); } inline JSONPtr & getElement(int index) { if (IsArray()) return array_.at(index); throw std::runtime_error("JSON object is not an array"); } inline const JSONPtr & getElement(int index) const { if (IsArray()) return array_.at(index); throw std::runtime_error("JSON object is not an array"); } inline JSONPtr & getMember(const string & key) { if (IsObject()) return map_.at(key); throw std::runtime_error("JSON object is not an object"); } inline const JSONPtr & getMember(const string & key) const { if (IsObject()) return map_.at(key); throw std::runtime_error("JSON object is not an object"); } inline JSONPtr & set(Type whichType) { Clear(); type_ = whichType; return shared_from_this(); } inline JSONPtr & set(const int ival) { Clear(); type_ = Type::Number; dval_ = ival; return shared_from_this(); } inline JSONPtr & set(const double dval) { Clear(); type_ = Type::Number; dval_ = dval; return shared_from_this(); } inline JSONPtr & set(const std::string &sval) { Clear(); type_ = Type::String; sval_ = sval; return shared_from_this(); } inline JSONPtr & set(initializer_list numberList) { Clear(); type_ = Type::Array; for (auto it = numberList.begin(); it != numberList.end(); it++) { array_.push_back(JSON::MakeNumber(*it)); } return shared_from_this(); } inline JSONPtr & set(const vector & numberList) { Clear(); type_ = Type::Array; for (auto it = numberList.begin(); it != numberList.end(); it++) { array_.push_back(JSON::MakeNumber(*it)); } return shared_from_this(); } inline JSONPtr & set(initializer_list numberList) { Clear(); type_ = Type::Array; for (auto it = numberList.begin(); it != numberList.end(); it++) { array_.push_back(JSON::MakeNumber(*it)); } return shared_from_this(); } inline JSONPtr & set(const vector & numberList) { Clear(); type_ = Type::Array; for (auto it = numberList.begin(); it != numberList.end(); it++) { array_.push_back(JSON::MakeNumber(*it)); } return shared_from_this(); } inline JSONPtr & set(initializer_list numberList) { Clear(); type_ = Type::Array; for (auto it = numberList.begin(); it != numberList.end(); it++) { array_.push_back(JSON::MakeNumber(*it)); } return shared_from_this(); } inline JSONPtr & set(const vector & numberList) { Clear(); type_ = Type::Array; for (auto it = numberList.begin(); it != numberList.end(); it++) { array_.push_back(JSON::MakeNumber(*it)); } return shared_from_this(); } inline JSONPtr & set(initializer_list stringList) { Clear(); type_ = Type::Array; for (auto it = stringList.begin(); it != stringList.end(); it++) { array_.push_back(JSON::MakeString(*it)); } return shared_from_this(); } inline JSONPtr & set(const vector & stringList) { Clear(); type_ = Type::Array; for (auto it = stringList.begin(); it != stringList.end(); it++) { array_.push_back(JSON::MakeString(*it)); } return shared_from_this(); } inline JSONPtr & set (initializer_list> members) { Clear(); type_ = Type::Object; for (auto it = members.begin(); it != members.end(); it++) { map_[it->first] = it->second; } return shared_from_this(); } inline JSONPtr & set(const map & members) { Clear(); type_ = Type::Object; for (auto it = members.begin(); it != members.end(); it++) { map_[it->first] = it->second; } return shared_from_this(); } inline JSONPtr & set(const JSONPtr & json) { Clear(); if (!json) return shared_from_this(); type_ = json->type_; if (IsNumber()) dval_ = json->dval_; if (IsString()) sval_ = json->sval_; if (IsArray()) array_ = json->array_; if (IsObject()) map_ = json->map_; return shared_from_this(); } inline JSONPtr & PushBack(JSONPtr & json) { if (!json || !IsArray()) throw std::runtime_error("JSON object is not an array"); array_.push_back(json); return shared_from_this(); } inline JSONPtr & PopBack() { if (!IsArray()) std::runtime_error("JSON object is not an array"); if (array_.empty()) return JSONPtr(); JSONPtr json = array_.back(); array_.pop_back(); return json; } inline Type GetType() const { return type_; } inline bool InstanceOf(const Type t) const { return type_ == t; } bool Equals(const JSONPtr &rhs) const; private: Type type_ = Type::Null; double dval_ = 0.0; std::string sval_; std::vector array_; std::map map_; void copyArray(const std::vector &a); void copyMap(const std::map &m); }; inline bool operator == (const JSONPtr &lhs, const JSONPtr &rhs) { if (!lhs || !rhs) return false; return lhs->Equals(rhs); } inline bool operator != (const JSONPtr &lhs, const JSONPtr &rhs) { if (!lhs || !rhs) return false; return !lhs->Equals(rhs); } } #endif