microwerx icon

kasl_json.hpp

microwerx | PRO | 12/30/17 11:53:32 PM UTC | 0 ⭐ | 991 👁️ | Never ⏰ | []
C++ |

15.62 KB

|

None

|

0 👍

/

0 👎

// 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 <https://www.gnu.org/licenses/>.
//
// For any other type of licensing, please contact me at [email protected]
#ifndef KASL_JSON_HPP
#define KASL_JSON_HPP
 
 
#include <memory>
#include <vector>
#include <map>
#include <string>
#include <initializer_list>
#include <kasl.hpp>
 
 
namespace KASL
{
    class JSON;
    using JSONPtr = std::shared_ptr<JSON>;
 
    class JSON : public std::enable_shared_from_this<JSON>
    {
    public:
        using SharedPtr = shared_ptr<JSON>;
 
        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<int> numberList)
        {
            type_ = Type::Array;
            for (auto it = numberList.begin(); it != numberList.end(); it++)
            {
                array_.push_back(JSON::MakeNumber(*it));
            }
        }
        
        explicit JSON(const vector<int> & numberList)
        {
            type_ = Type::Array;
            for (auto it = numberList.begin(); it != numberList.end(); it++)
            {
                array_.push_back(JSON::MakeNumber(*it));
            }
        }
        
        explicit JSON(initializer_list<float> numberList)
        {
            type_ = Type::Array;
            for (auto it = numberList.begin(); it != numberList.end(); it++)
            {
                array_.push_back(JSON::MakeNumber(*it));
            }
        }
 
        explicit JSON(const vector<float> & numberList)
        {
            type_ = Type::Array;
            for (auto it = numberList.begin(); it != numberList.end(); it++)
            {
                array_.push_back(JSON::MakeNumber(*it));
            }
        }
 
        explicit JSON(initializer_list<double> numberList)
        {
            type_ = Type::Array;
            for (auto it = numberList.begin(); it != numberList.end(); it++)
            {
                array_.push_back(JSON::MakeNumber(*it));
            }
        }
 
        explicit JSON(const vector<double> & numberList)
        {
            type_ = Type::Array;
            for (auto it = numberList.begin(); it != numberList.end(); it++)
            {
                array_.push_back(JSON::MakeNumber(*it));
            }
        }
 
        explicit JSON(initializer_list<string> stringList)
        {
            type_ = Type::Array;
            for (auto it = stringList.begin(); it != stringList.end(); it++)
            {
                array_.push_back(JSON::MakeString(*it));
            }
        }
 
        explicit JSON(const vector<string> & stringList)
        {
            type_ = Type::Array;
            for (auto it = stringList.begin(); it != stringList.end(); it++)
            {
                array_.push_back(JSON::MakeString(*it));
            }
        }
 
        explicit JSON(initializer_list<pair<string, JSONPtr>> members)
        {
            type_ = Type::Object;
            for (auto it = members.begin(); it != members.end(); it++)
            {
                map_[it->first] = it->second;
            }
        }
 
        explicit JSON(const map<string, JSONPtr> & 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<JSON>(Type::Null); }
        static JSONPtr MakeBool(bool state = false) { return make_shared<JSON>(state ? Type::True : Type::False); }
        static JSONPtr MakeString(const string & sval) { return make_shared<JSON>(sval); }
        static JSONPtr MakeString() { return make_shared<JSON>(""); }
        static JSONPtr MakeNumber(int ival = 0) { return make_shared<JSON>(ival); }
        static JSONPtr MakeNumber(double dval = 0.0) { return make_shared<JSON>(dval); }
        static JSONPtr MakeArray() { return make_shared<JSON>(Type::Array); }
        static JSONPtr MakeArray(const vector<int> & numberList) { return make_shared<JSON>(numberList); }
        static JSONPtr MakeArray(initializer_list<int> numberList) { return make_shared<JSON>(numberList); }
        static JSONPtr MakeArray(const vector<float> & numberList) { return make_shared<JSON>(numberList); }
        static JSONPtr MakeArray(initializer_list<float> numberList) { return make_shared<JSON>(numberList); }
        static JSONPtr MakeArray(const vector<double> & numberList) { return make_shared<JSON>(numberList); }
        static JSONPtr MakeArray(initializer_list<double> numberList) { return make_shared<JSON>(numberList); }
        static JSONPtr MakeArray(const vector<string> & stringList) { return make_shared<JSON>(stringList); }
        static JSONPtr MakeArray(initializer_list<string> stringList) { return make_shared<JSON>(stringList); }
        static JSONPtr MakeObject() { return make_shared<JSON>(Type::Object); }
        static JSONPtr MakeObject(initializer_list<pair<string, JSONPtr>> members) { return make_shared<JSON>(members); }
        static JSONPtr MakeObject(const map<string, JSONPtr> members) { return make_shared<JSON>(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<JSON>(Type::Array); }
        static JSONPtr NewObject() { return make_shared<JSON>(Type::Object); }
        static JSONPtr NewNumber(const double value) { return make_shared<JSON>(value); }
        static JSONPtr NewBoolean(const bool value) { return make_shared<JSON>(value); }
        static JSONPtr NewString(const string & value) { return make_shared<JSON>(value); }
        static JSONPtr New(const JSONPtr & value) { return make_shared<JSON>(value); }
        static JSONPtr New() { return make_shared<JSON>(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<std::string, JSONPtr> & AsObject() noexcept { return map_; }
        inline const std::map<std::string, JSONPtr> & AsObject() const noexcept { return map_; }
        inline std::vector<JSONPtr> & AsArray() noexcept { return array_; }
        inline const std::vector<JSONPtr> & AsArray() const noexcept { return array_; }
 
        inline vector<int> AsIntArray() const noexcept
        {
            vector<int> result;
            for (auto & e : array_)
            {
                if (e)
                    result.push_back(e->AsInt());
            }
            return result;
        }
 
        inline vector<float> AsFloatArray() const noexcept
        {
            vector<float> result;
            for (auto & e : array_)
            {
                if (e)
                    result.push_back(e->AsFloat());
            }
            return result;
        }
 
        inline vector<double> AsDoubleArray() const noexcept
        {
            vector<double> 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<int> 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<int> & 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<float> 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<float> & 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<double> 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<double> & 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<string> 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<string> & 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<pair<string, JSONPtr>> 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<string, JSONPtr> & 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<JSONPtr> array_;
        std::map<std::string, JSONPtr> map_;
 
        void copyArray(const std::vector<JSONPtr> &a);
        void copyMap(const std::map<std::string, JSONPtr> &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

Comments