lua json library
This commit is contained in:
parent
30a38035e2
commit
8e4f8004f7
@ -110,6 +110,11 @@ List& List::put(bool value) {
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
List& List::put(std::unique_ptr<Value> value) {
|
||||||
|
values.emplace_back(std::move(value));
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
List& List::put(Map* value) {
|
List& List::put(Map* value) {
|
||||||
values.push_back(std::make_unique<Value>(valtype::map, value));
|
values.push_back(std::make_unique<Value>(valtype::map, value));
|
||||||
return *this;
|
return *this;
|
||||||
@ -346,6 +351,10 @@ bool Map::has(std::string key) {
|
|||||||
return values.find(key) != values.end();
|
return values.find(key) != values.end();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t Map::size() const {
|
||||||
|
return values.size();
|
||||||
|
}
|
||||||
|
|
||||||
Value::Value(valtype type, valvalue value) : type(type), value(value) {
|
Value::Value(valtype type, valvalue value) : type(type), value(value) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -358,18 +367,18 @@ Value::~Value() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Value Value::boolean(bool value) {
|
std::unique_ptr<Value> Value::boolean(bool value) {
|
||||||
return Value(valtype::boolean, value);
|
return std::make_unique<Value>(valtype::boolean, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
Value Value::of(number_u value) {
|
std::unique_ptr<Value> Value::of(number_u value) {
|
||||||
if (std::holds_alternative<integer_t>(value)) {
|
if (std::holds_alternative<integer_t>(value)) {
|
||||||
return Value(valtype::integer, std::get<integer_t>(value));
|
return std::make_unique<Value>(valtype::integer, std::get<integer_t>(value));
|
||||||
} else {
|
} else {
|
||||||
return Value(valtype::number, std::get<number_t>(value));
|
return std::make_unique<Value>(valtype::number, std::get<number_t>(value));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Value Value::of(const std::string& value) {
|
std::unique_ptr<Value> Value::of(const std::string& value) {
|
||||||
return Value(valtype::string, value);
|
return std::make_unique<Value>(valtype::string, value);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -33,9 +33,9 @@ namespace dynamic {
|
|||||||
Value(valtype type, valvalue value);
|
Value(valtype type, valvalue value);
|
||||||
~Value();
|
~Value();
|
||||||
|
|
||||||
static Value boolean(bool value);
|
static std::unique_ptr<Value> boolean(bool value);
|
||||||
static Value of(number_u value);
|
static std::unique_ptr<Value> of(number_u value);
|
||||||
static Value of(const std::string& value);
|
static std::unique_ptr<Value> of(const std::string& value);
|
||||||
};
|
};
|
||||||
|
|
||||||
class List {
|
class List {
|
||||||
@ -68,6 +68,7 @@ namespace dynamic {
|
|||||||
List& put(Map* value);
|
List& put(Map* value);
|
||||||
List& put(List* value);
|
List& put(List* value);
|
||||||
List& put(bool value);
|
List& put(bool value);
|
||||||
|
List& put(std::unique_ptr<Value> value);
|
||||||
|
|
||||||
Value* getValueWriteable(size_t index) const;
|
Value* getValueWriteable(size_t index) const;
|
||||||
|
|
||||||
@ -121,6 +122,7 @@ namespace dynamic {
|
|||||||
Map& putMap(std::string key);
|
Map& putMap(std::string key);
|
||||||
|
|
||||||
bool has(std::string key);
|
bool has(std::string key);
|
||||||
|
size_t size() const;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -30,7 +30,7 @@ SettingsHandler::SettingsHandler(EngineSettings& settings) {
|
|||||||
map.emplace("graphics.backlight", &settings.graphics.backlight);
|
map.emplace("graphics.backlight", &settings.graphics.backlight);
|
||||||
}
|
}
|
||||||
|
|
||||||
dynamic::Value SettingsHandler::getValue(const std::string& name) const {
|
std::unique_ptr<dynamic::Value> SettingsHandler::getValue(const std::string& name) const {
|
||||||
auto found = map.find(name);
|
auto found = map.find(name);
|
||||||
if (found == map.end()) {
|
if (found == map.end()) {
|
||||||
throw std::runtime_error("setting '"+name+"' does not exist");
|
throw std::runtime_error("setting '"+name+"' does not exist");
|
||||||
@ -65,7 +65,7 @@ Setting* SettingsHandler::getSetting(const std::string& name) const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
static void set_numeric_value(T* setting, dynamic::Value& value) {
|
static void set_numeric_value(T* setting, const dynamic::Value& value) {
|
||||||
switch (value.type) {
|
switch (value.type) {
|
||||||
case dynamic::valtype::integer:
|
case dynamic::valtype::integer:
|
||||||
setting->set(std::get<integer_t>(value.value));
|
setting->set(std::get<integer_t>(value.value));
|
||||||
@ -81,10 +81,10 @@ static void set_numeric_value(T* setting, dynamic::Value& value) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SettingsHandler::setValue(const std::string& name, dynamic::Value value) {
|
void SettingsHandler::setValue(const std::string& name, const dynamic::Value& value) {
|
||||||
auto found = map.find(name);
|
auto found = map.find(name);
|
||||||
if (found == map.end()) {
|
if (found == map.end()) {
|
||||||
throw std::runtime_error("setting '"+name+"' does not exist");
|
throw std::runtime_error("setting '"+name+"' does Pnot exist");
|
||||||
}
|
}
|
||||||
auto setting = found->second;
|
auto setting = found->second;
|
||||||
if (auto number = dynamic_cast<NumberSetting*>(setting)) {
|
if (auto number = dynamic_cast<NumberSetting*>(setting)) {
|
||||||
|
|||||||
@ -2,6 +2,7 @@
|
|||||||
#define FILES_SETTINGS_IO_H_
|
#define FILES_SETTINGS_IO_H_
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <memory>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include "../settings.h"
|
#include "../settings.h"
|
||||||
#include "../data/dynamic.h"
|
#include "../data/dynamic.h"
|
||||||
@ -15,8 +16,8 @@ class SettingsHandler {
|
|||||||
public:
|
public:
|
||||||
SettingsHandler(EngineSettings& settings);
|
SettingsHandler(EngineSettings& settings);
|
||||||
|
|
||||||
dynamic::Value getValue(const std::string& name) const;
|
std::unique_ptr<dynamic::Value> getValue(const std::string& name) const;
|
||||||
void setValue(const std::string& name, dynamic::Value value);
|
void setValue(const std::string& name, const dynamic::Value& value);
|
||||||
std::string toString(const std::string& name) const;
|
std::string toString(const std::string& name) const;
|
||||||
Setting* getSetting(const std::string& name) const;
|
Setting* getSetting(const std::string& name) const;
|
||||||
};
|
};
|
||||||
|
|||||||
@ -128,6 +128,7 @@ void lua::LuaState::createLibs() {
|
|||||||
openlib("player", playerlib, 0);
|
openlib("player", playerlib, 0);
|
||||||
openlib("time", timelib, 0);
|
openlib("time", timelib, 0);
|
||||||
openlib("world", worldlib, 0);
|
openlib("world", worldlib, 0);
|
||||||
|
openlib("json", jsonlib, 0);
|
||||||
|
|
||||||
addfunc("print", lua_wrap_errors<l_print>);
|
addfunc("print", lua_wrap_errors<l_print>);
|
||||||
}
|
}
|
||||||
@ -226,10 +227,24 @@ int lua::LuaState::pushvalue(const dynamic::Value& value) {
|
|||||||
case valtype::none:
|
case valtype::none:
|
||||||
pushnil();
|
pushnil();
|
||||||
break;
|
break;
|
||||||
case valtype::list:
|
case valtype::list: {
|
||||||
throw std::runtime_error("type 'list' is not implemented");
|
auto list = std::get<dynamic::List*>(value.value);
|
||||||
case valtype::map:
|
lua_createtable(L, list->size(), 0);
|
||||||
throw std::runtime_error("type 'map' is not implemented");
|
for (size_t i = 0; i < list->size(); i++) {
|
||||||
|
pushvalue(*list->get(i));
|
||||||
|
lua_rawseti(L, -2, i+1);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case valtype::map: {
|
||||||
|
auto map = std::get<dynamic::Map*>(value.value);
|
||||||
|
lua_createtable(L, 0, map->size());
|
||||||
|
for (auto& entry : map->values) {
|
||||||
|
pushvalue(*entry.second);
|
||||||
|
lua_setfield(L, -2, entry.first.c_str());
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@ -277,28 +292,56 @@ const char* lua::LuaState::tostring(int idx) {
|
|||||||
return lua_tostring(L, idx);
|
return lua_tostring(L, idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
dynamic::Value lua::LuaState::tovalue(int idx) {
|
std::unique_ptr<dynamic::Value> lua::LuaState::tovalue(int idx) {
|
||||||
using dynamic::valtype;
|
using namespace dynamic;
|
||||||
auto type = lua_type(L, idx);
|
auto type = lua_type(L, idx);
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case LUA_TNIL:
|
case LUA_TNIL:
|
||||||
case LUA_TNONE:
|
case LUA_TNONE:
|
||||||
return dynamic::Value(valtype::none, (integer_t)0);
|
return std::make_unique<Value>(valtype::none, (integer_t)0);
|
||||||
case LUA_TBOOLEAN:
|
case LUA_TBOOLEAN:
|
||||||
return dynamic::Value::boolean(lua_toboolean(L, idx) == 1);
|
return Value::boolean(lua_toboolean(L, idx) == 1);
|
||||||
case LUA_TNUMBER: {
|
case LUA_TNUMBER: {
|
||||||
auto number = lua_tonumber(L, idx);
|
auto number = lua_tonumber(L, idx);
|
||||||
auto integer = lua_tointeger(L, idx);
|
auto integer = lua_tointeger(L, idx);
|
||||||
if (number == (lua_Number)integer) {
|
if (number == (lua_Number)integer) {
|
||||||
return dynamic::Value::of(integer);
|
return Value::of(integer);
|
||||||
} else {
|
} else {
|
||||||
return dynamic::Value::of(number);
|
return Value::of(number);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case LUA_TSTRING:
|
case LUA_TSTRING:
|
||||||
return dynamic::Value::of(lua_tostring(L, idx));
|
return Value::of(lua_tostring(L, idx));
|
||||||
|
case LUA_TTABLE: {
|
||||||
|
int len = lua_objlen(L, idx);
|
||||||
|
if (len) {
|
||||||
|
// array
|
||||||
|
auto list = std::make_unique<List>();
|
||||||
|
for (int i = 1; i <= len; i++) {
|
||||||
|
lua_rawgeti(L, idx, i);
|
||||||
|
list->put(tovalue(-1));
|
||||||
|
lua_pop(L, 1);
|
||||||
|
}
|
||||||
|
return std::make_unique<Value>(valtype::list, list.release());
|
||||||
|
} else {
|
||||||
|
// table
|
||||||
|
auto map = std::make_unique<Map>();
|
||||||
|
lua_pushvalue(L, idx);
|
||||||
|
lua_pushnil(L);
|
||||||
|
while (lua_next(L, -2)) {
|
||||||
|
lua_pushvalue(L, -2);
|
||||||
|
auto key = lua_tostring(L, -1);
|
||||||
|
map->put(key, tovalue(-2));
|
||||||
|
lua_pop(L, 2);
|
||||||
|
}
|
||||||
|
lua_pop(L, 1);
|
||||||
|
return std::make_unique<Value>(valtype::map, map.release());
|
||||||
|
}
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
throw std::runtime_error("lua type "+std::to_string(type)+" is not supported");
|
throw std::runtime_error(
|
||||||
|
"lua type "+std::to_string(type)+" is not supported"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -47,7 +47,7 @@ namespace lua {
|
|||||||
bool toboolean(int idx);
|
bool toboolean(int idx);
|
||||||
luaint tointeger(int idx);
|
luaint tointeger(int idx);
|
||||||
luanumber tonumber(int idx);
|
luanumber tonumber(int idx);
|
||||||
dynamic::Value tovalue(int idx);
|
std::unique_ptr<dynamic::Value> tovalue(int idx);
|
||||||
const char* tostring(int idx);
|
const char* tostring(int idx);
|
||||||
bool isstring(int idx);
|
bool isstring(int idx);
|
||||||
bool isfunction(int idx);
|
bool isfunction(int idx);
|
||||||
|
|||||||
@ -17,6 +17,7 @@ extern const luaL_Reg packlib [];
|
|||||||
extern const luaL_Reg playerlib [];
|
extern const luaL_Reg playerlib [];
|
||||||
extern const luaL_Reg timelib [];
|
extern const luaL_Reg timelib [];
|
||||||
extern const luaL_Reg worldlib [];
|
extern const luaL_Reg worldlib [];
|
||||||
|
extern const luaL_Reg jsonlib [];
|
||||||
|
|
||||||
|
|
||||||
// Lua Overrides
|
// Lua Overrides
|
||||||
|
|||||||
@ -118,14 +118,14 @@ static int l_get_bindings(lua_State* L) {
|
|||||||
static int l_get_setting(lua_State* L) {
|
static int l_get_setting(lua_State* L) {
|
||||||
auto name = lua_tostring(L, 1);
|
auto name = lua_tostring(L, 1);
|
||||||
const auto value = scripting::engine->getSettingsHandler().getValue(name);
|
const auto value = scripting::engine->getSettingsHandler().getValue(name);
|
||||||
scripting::state->pushvalue(value);
|
scripting::state->pushvalue(*value);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int l_set_setting(lua_State* L) {
|
static int l_set_setting(lua_State* L) {
|
||||||
auto name = lua_tostring(L, 1);
|
auto name = lua_tostring(L, 1);
|
||||||
const auto value = scripting::state->tovalue(2);
|
const auto value = scripting::state->tovalue(2);
|
||||||
scripting::engine->getSettingsHandler().setValue(name, value);
|
scripting::engine->getSettingsHandler().setValue(name, *value);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
39
src/logic/scripting/lua/libjson.cpp
Normal file
39
src/logic/scripting/lua/libjson.cpp
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
#include "api_lua.h"
|
||||||
|
#include "lua_commons.h"
|
||||||
|
|
||||||
|
#include "LuaState.h"
|
||||||
|
|
||||||
|
#include "../../../coders/json.h"
|
||||||
|
#include "../../../data/dynamic.h"
|
||||||
|
|
||||||
|
namespace scripting {
|
||||||
|
extern lua::LuaState* state;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int l_json_stringify(lua_State* L) {
|
||||||
|
auto value = scripting::state->tovalue(1);
|
||||||
|
if (value->type != dynamic::valtype::map) {
|
||||||
|
luaL_error(L, "table expected");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
bool nice = lua_toboolean(L, 2);
|
||||||
|
auto string = json::stringify(std::get<dynamic::Map*>(value->value), nice, " ");
|
||||||
|
lua_pushstring(L, string.c_str());
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int l_json_parse(lua_State* L) {
|
||||||
|
auto string = lua_tostring(L, 1);
|
||||||
|
auto element = json::parse("<string>", string);
|
||||||
|
auto value = std::make_unique<dynamic::Value>(
|
||||||
|
dynamic::valtype::map, element.release()
|
||||||
|
);
|
||||||
|
scripting::state->pushvalue(*value);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
const luaL_Reg jsonlib [] = {
|
||||||
|
{"stringify", lua_wrap_errors<l_json_stringify>},
|
||||||
|
{"parse", lua_wrap_errors<l_json_parse>},
|
||||||
|
{NULL, NULL}
|
||||||
|
};
|
||||||
Loading…
x
Reference in New Issue
Block a user