Jump to content

Recommended Posts

Posted

It's clear after working with this for a while that what is needed is a table-like class in C++ that is mostly interchangeable with JSON and can be quickly accessed by both C++ and Lua.

The problem with JSON is that nodes can behave like STL maps or vectors, and when you try to derive from both those types there's a lot of problems binding it with sol.

So I will paste this here before I go tearing it apart.

enum JsonType
{
    JSON_NULL,
    JSON_INTEGER,
    JSON_FLOAT,
    JSON_BOOLEAN,
    JSON_STRING,
    JSON_OBJECT,
    JSON_ARRAY
};

class Json : private std::map<std::string, Json>, std::vector<Json>
{
    typedef std::map<std::string, Json> JsonObject;
    typedef std::vector<Json> JsonArray;

    float f;
    int i;
    bool b;
    std::string s;
    JsonType t;

    friend JsonObject;
    friend JsonArray;

public:

    Json()
    {
        f = 0;
        i = 0;
        b = false;
        t = JSON_NULL;
    }

    JsonObject::iterator begin()
    {
        return JsonObject::begin();
    }

    JsonObject::iterator end()
    {
        return JsonObject::end();
    }

    static Json Object()
    {
        Json j;
        j.t = JSON_OBJECT;
        return j;
    }

    static Json Array()
    {
        Json j;
        j.t = JSON_ARRAY;
        return j;
    }

    JsonType GetType()
    {
        return t;
    }

    operator int()
    {
        if (t == JSON_INTEGER) return i;
        if (t == JSON_FLOAT) return f;
        if (t == JSON_BOOLEAN) return b;
        return 0;
    }

    operator float()
    {
        if (t == JSON_FLOAT) return f;
        if (t == JSON_INTEGER) return i;
        if (t == JSON_BOOLEAN) return b;
        return 0.0f;
    }

    operator std::string()
    {
        if (t == JSON_STRING) return s;
        if (t == JSON_FLOAT) return String(f);
        if (t == JSON_INTEGER) return String(i);
        if (t == JSON_BOOLEAN) return String(b);
        return "";
    }

    void clear()
    {
        i = 0;
        f = 0;
        b = false;
        s.clear();
        JsonArray::clear();
        JsonObject::clear();
    }

    Json(const int i_)
    {
        clear();
        i = i_;
        t = JSON_INTEGER;
    }

    Json(const bool b_)
    {
        clear();
        b = b_;
        t = JSON_BOOLEAN;
    }

    Json(const float f_)
    {
        clear();
        f = f_;
        t = JSON_FLOAT;
    }

    Json(const std::string& s_)
    {
        clear();
        s = s_;
        t = JSON_STRING;
    }

    Json(const JsonObject& j3)
    {
        clear();
        t = JSON_OBJECT;
        for (const auto& pair : j3)
        {
            JsonObject::insert(pair);
        }
        //JsonObject::insert(JsonObject::end(), j3.begin(), j3.end());
    }

    Json(const JsonArray& j3)
    {
        clear();
        t = JSON_ARRAY;
        JsonArray::insert(JsonArray::end(), j3.begin(), j3.end());
    }

    Json& operator[](const std::string& key)
    {
        if (t != JSON_OBJECT) RuntimeError("JSON value is not an object");
        auto it = JsonObject::find(key);
        if (it == JsonObject::end())
        {
            auto pair = std::pair<std::string, Json>(key, {});
            JsonObject::insert(pair);
            it = JsonObject::find(key);
            Assert(it != JsonObject::end());
        }
        return it->second;
    }

    Json& operator[](const int index)
    {
        if (t != JSON_ARRAY) RuntimeError("JSON value is not an array");
        return JsonArray::at(index);
    }

    void resize(const size_t sz)
    {
        if (t != JSON_ARRAY) RuntimeError("JSON value is not an array");
        JsonArray::resize(sz);
    }

    void reserve(const size_t sz)
    {
        if (t != JSON_ARRAY) RuntimeError("JSON value is not an array");
        JsonArray::reserve(sz);
    }

    size_t capacity()
    {
        if (t != JSON_ARRAY) RuntimeError("JSON value is not an array");
        return JsonArray::capacity();
    }

    size_t size()
    {
        if (t != JSON_ARRAY) RuntimeError("JSON value is not an array");
        return JsonArray::size();
    }

    void push_back(const Json& j3)
    {
        if (t != JSON_ARRAY) RuntimeError("JSON value is not an array");
        JsonArray::push_back(j3);
    }
};

Example usage:

auto j3 = Json::Object();

    j3["health"] = 100;
    j3["windowsettings"] = Json::Object();
    j3["windowsettings"]["position"] = 3;

    int g = j3["health"];

    for (auto a : j3)
    {
        Print(a.first);
        Print(std::string(a.second));
    }

    auto arr = Json::Array();
    arr.push_back(1);
    arr.push_back(2);
    arr.push_back(3);
    arr.push_back(4);
    arr.push_back(5);

    for (int n = 0; n < arr.size(); ++n)
    {
        Print(std::string(arr[n]));
    }

    Print(std::string(j3["health"]));

 

  • Like 1

Let's build cool stuff and have fun. :)

Posted

My current implementation, working in Lua with indexes and keys. This is very very touchy:

#include "UltraEngine.h"

using namespace UltraEngine;

enum JsonType
{
    JSON_NULL,
    JSON_INTEGER,
    JSON_FLOAT,
    JSON_BOOLEAN,
    JSON_STRING,
    JSON_OBJECT,
    JSON_ARRAY
};

class Json : public std::map<std::string, Json>
{
    typedef std::map<std::string, Json> JsonObject;
    
    std::vector<Json> v;
    double f;
    int64_t i;
    bool b;
    std::string s;
    JsonType t;

public:

    Json()
    {
        f = 0;
        i = 0;
        b = false;
        t = JSON_NULL;
    }

    Json::iterator begin()
    {
        return JsonObject::begin();
    }

    Json::iterator end()
    {
        return JsonObject::end();
    }

    //Json::iterator erase(Json::iterator it)
    //{
    //    if (t != JSON_OBJECT) RuntimeError("JSON value is not an object");
    //    return JsonObject::erase(it);
       //}

    Json::iterator find(const std::string& s)
    {
        return JsonObject::find(s);
    }

    std::pair<Json::iterator, bool> insert(std::pair<std::string, Json> pair)
    {
        return JsonObject::insert(pair);
    }

    static Json Object()
    {
        Json j;
        j.t = JSON_OBJECT;
        return j;
    }

    static Json Array()
    {
        Json j;
        j.t = JSON_ARRAY;
        return j;
    }

    JsonType GetType() const
    {
        return t;
    }

    operator bool() const
    {
        if (t == JSON_BOOLEAN) return b;
        return false;
    }

    operator int() const
    {
        if (t == JSON_INTEGER) return i;
        if (t == JSON_FLOAT) return f;
        if (t == JSON_BOOLEAN) return b;
        return 0;
    }

    operator int64_t() const
    {
        if (t == JSON_INTEGER) return i;
        if (t == JSON_FLOAT) return f;
        if (t == JSON_BOOLEAN) return b;
        return 0;
    }

    operator float() const
    {
        if (t == JSON_FLOAT) return f;
        if (t == JSON_INTEGER) return i;
        if (t == JSON_BOOLEAN) return b;
        return 0.0f;
    }

    operator double() const
    {
        if (t == JSON_FLOAT) return f;
        if (t == JSON_INTEGER) return i;
        if (t == JSON_BOOLEAN) return b;
        return 0.0f;
    }

    operator std::string() const
    {
        if (t == JSON_STRING) return s;
        if (t == JSON_FLOAT) return String(f);
        if (t == JSON_INTEGER) return String(i);
        if (t == JSON_BOOLEAN) return String(b);
        return "";
    }

    void clear()
    {
        i = 0;
        f = 0;
        b = false;
        s.clear();
        JsonObject::clear();
        v.clear();
    }

    Json(const int i_)
    {
        clear();
        i = i_;
        t = JSON_INTEGER;
    }

    Json(const int64_t i_)
    {
        clear();
        i = i_;
        t = JSON_INTEGER;
    }

    Json(const bool b_)
    {
        clear();
        b = b_;
        t = JSON_BOOLEAN;
    }

    Json(const float f_)
    {
        clear();
        f = f_;
        t = JSON_FLOAT;
    }

    Json(const double f_)
    {
        clear();
        f = f_;
        t = JSON_FLOAT;
    }

    Json(const std::string& s_)
    {
        clear();
        s = s_;
        t = JSON_STRING;
    }

    Json(const JsonObject& j3)
    {
        clear();
        t = JSON_OBJECT;
        for (const auto& pair : j3)
        {
            JsonObject::insert(pair);
        }
        //JsonObject::insert(JsonObject::end(), j3.begin(), j3.end());
    }

    Json& operator[](const char* c)
    {
        return (*this)[std::string(c)];
    }

    Json& operator[](const std::string& key)
    {
        if (t != JSON_OBJECT) RuntimeError("JSON value is not an object");
        auto it = find(key);
        if (it == end())
        {
            auto pair = std::pair<std::string, Json>(key, {});
            JsonObject::insert(pair);
            it = JsonObject::find(key);
            Assert(it != JsonObject::end());
        }
        return it->second;
    }

    Json& operator[](const size_t index)
    {
        if (t != JSON_ARRAY) RuntimeError("JSON value is not an array");
        if (index >= size()) RuntimeError("Index out of bounds");
        return v[index];
    }

    size_t size()
    {
        if (t != JSON_ARRAY) RuntimeError("JSON value is not an array");
        return v.size();
    }

    void push_back(const Json& j3)
    {
        if (t != JSON_ARRAY) RuntimeError("JSON value is not an array");
        v.push_back(j3);
    }

    void resize(const size_t sz)
    {
        if (t != JSON_ARRAY) RuntimeError("JSON value is not an array");
        v.resize(sz);
    }

    void reserve(const size_t sz)
    {
        if (t != JSON_ARRAY) RuntimeError("JSON value is not an array");
        v.reserve(sz);
    }

    size_t capacity()
    {
        if (t != JSON_ARRAY) RuntimeError("JSON value is not an array");
        return v.capacity();
    }
};

/*namespace sol {
    template <>
    struct is_container<Json> : std::true_type {};
}*/

/*namespace sol {
    template <>
    struct is_container<Json> : std::true_type {};

    template <>
    struct usertype_container<Json> {

        ...
            // see below for implemetation details
    };
}*/

int main(int argc, const char* argv[])
{
    auto L = GetLuaState();

    L->new_usertype<Json>("MYJSON",
        sol::meta_function::to_string, [](const Json& v)
        {
            std::string s = v;
            return s;
        },
        sol::meta_function::index, sol::overload(
            [](Json& v, std::string key) {
                auto L = GetLuaState()->lua_state();
                auto val = v[key];
                switch (val.GetType())
                {
                case JSON_INTEGER:
                    return sol::make_object(L, int64_t(val));
                case JSON_FLOAT:
                    return sol::make_object(L, double(val));
                case JSON_BOOLEAN:
                    return sol::make_object(L, bool(val));
                case JSON_STRING:
                    return sol::make_object(L, std::string(val));
                case JSON_ARRAY:
                case JSON_OBJECT:
                    return sol::make_object(L, val);
                }
            },
            [](Json& v, int64_t index) {
                auto L = GetLuaState()->lua_state();
                if (index < 0 or index >= v.size()) sol::make_object(L, sol::lua_nil);
                --index;
                auto val = v[index];
                switch (val.GetType())
                {
                case JSON_INTEGER:
                    return sol::make_object(L, int64_t(val));
                case JSON_FLOAT:
                    return sol::make_object(L, double(val));
                case JSON_BOOLEAN:
                    return sol::make_object(L, bool(val));
                case JSON_STRING:
                    return sol::make_object(L, std::string(val));
                case JSON_ARRAY:
                case JSON_OBJECT:
                    return sol::make_object(L, val);
                }
            }
        ),
        sol::meta_function::new_index, sol::overload(
            [](Json& v, int64_t index, double x)
            {
                --index;
                if (index < 0) return;
                if (index >= v.size()) v.resize(index + 1);
                v[index] = x;
            },
            [](Json& v, std::string key, double x)
            {
                v[key] = x;
            },
            [](Json& v, int64_t index, std::string x)
            {
                --index;
                if (index < 0) return;
                if (index >= v.size()) v.resize(index + 1);
                v[index] = x;
            },
                [](Json& v, std::string key, std::string x)
            {
                v[key] = x;
            },
            [](Json& v, int64_t index, bool x)
            {
                --index;
                if (index < 0) return;
                if (index >= v.size()) v.resize(index + 1);
                v[index] = x;
            },
            [](Json& v, std::string key, bool x)
            {
                v[key] = x;
            },
            [](Json& v, int64_t index, const Json& x)
            {
                --index;
                if (index < 0) return;
                if (index >= v.size()) v.resize(index + 1);
                v[index] = x;
            },
            [](Json& v, std::string key, const Json& x)
            {
                v[key] = x;
            }
        )
    );
    L->set_function("JsonObject", Json::Object);
    L->set_function("JsonArray", Json::Array);
    auto j3 = Json::Object();

    /*j3["health"] = 100;
    j3["windowsettings"] = Json::Object();
    j3["windowsettings"]["position"] = 3;

    int gf = j3["windowsettings"]["position"];

    int g = j3["health"];

    for (auto a : j3)
    {
        Print(a.first);
        std::string s = a.second;
        Print(s);
    }

    auto arr = Json::Array();
    arr.push_back(1);
    arr.push_back(2);
    arr.push_back(3);
    arr.push_back(4);
    arr.push_back(5);

    for (int n = 0; n < arr.size(); ++n)
    {
        Print(std::string(arr[n]));
    }

    Print(std::string(j3["health"]));
    */
    //Get commandline settings
    auto settings = ParseCommandLine(argc, argv);

    //Enable the debugger if needed
    shared_ptr<Timer> debugtimer;
    if (settings["debug"].is_boolean() and settings["debug"] == true)
    {
        RunScript("Scripts/System/Debugger.lua");
        debugtimer = CreateTimer(510);
        ListenEvent(EVENT_TIMERTICK, debugtimer, std::bind(PollDebugger, 500));
    }

    //Run main script
    RunScript("Scripts/Main.lua");

    return 0;
}

 

Let's build cool stuff and have fun. :)

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...