1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
|
#include "values.hpp"
#include "luax.hpp"
using rapidjson::Value;
using rapidjson::SizeType;
namespace values
{
namespace details
{
static Value NumberValue(lua_State* L, int idx);
static Value StringValue(lua_State* L, int idx, Allocator& allocator);
static Value TableValue(lua_State* L, int idx, int depth, Allocator& allocator);
static Value ObjectValue(lua_State* L, int idx, int depth, Allocator& allocator);
static Value ArrayValue(lua_State* L, int idx, int depth, Allocator& allocator);
Value toValue(lua_State* L, int idx, int depth, Allocator& allocator)
{
auto t = lua_type(L, idx);
switch (t)
{
case LUA_TBOOLEAN:
return Value(lua_toboolean(L, idx) != 0);
case LUA_TNUMBER:
return NumberValue(L, idx);
case LUA_TSTRING:
return StringValue(L, idx, allocator);
case LUA_TTABLE:
return TableValue(L, idx, depth + 1, allocator);
case LUA_TNIL:
return Value();
case LUA_TFUNCTION:
if (isnull(L, idx))
return Value();
// otherwise fall thought
case LUA_TLIGHTUSERDATA: // fall thought
case LUA_TUSERDATA: // fall thought
case LUA_TTHREAD: // fall thought
case LUA_TNONE: // fall thought
default:
luaL_error(L, "value type %s is not a valid json value", lua_typename(L, t));
return Value(); // Just make compiler happy
}
}
Value NumberValue(lua_State* L, int idx)
{
int64_t integer;
return luax::isinteger(L, idx, &integer) ? Value(integer) : Value(lua_tonumber(L, idx));
}
Value StringValue(lua_State* L, int idx, Allocator& allocator)
{
size_t len;
const char* s = lua_tolstring(L, idx, &len);
return Value(s, static_cast<SizeType>(len), allocator);
}
Value TableValue(lua_State* L, int idx, int depth, Allocator& allocator)
{
if (depth > 1024)
luaL_error(L, "nested too depth");
if (!lua_checkstack(L, 4)) // requires at least 4 slots in stack: table, key, value, key
luaL_error(L, "stack overflow");
return isarray(L, idx) ? ArrayValue(L, idx, depth, allocator) : ObjectValue(L, idx, depth, allocator);
}
Value ObjectValue(lua_State* L, int idx, int depth, Allocator& allocator)
{
Value object(rapidjson::kObjectType);
lua_pushvalue(L, idx);
lua_pushnil(L);
while (lua_next(L, -2))
{
if (lua_type(L, -2) == LUA_TSTRING)
{
object.AddMember(StringValue(L, -2, allocator), toValue(L, -1, depth, allocator), allocator);
}
// pop value, leaving original key
lua_pop(L, 1);
}
lua_pop(L, 1);
return object;
}
Value ArrayValue(lua_State* L, int idx, int depth, Allocator& allocator)
{
Value array(rapidjson::kArrayType);
auto MAX = static_cast<int>(luax::rawlen(L, idx)); // luax::rawlen always returns size_t (>= 0)
for (auto n = 1; n <= MAX; ++n)
{
lua_rawgeti(L, idx, n);
array.PushBack(toValue(L, -1, depth, allocator), allocator);
lua_pop(L, 1);
}
return array;
}
}
}
|