-
Notifications
You must be signed in to change notification settings - Fork 18
Expand file tree
/
Copy pathvalue_guest.c
More file actions
212 lines (189 loc) · 5.24 KB
/
value_guest.c
File metadata and controls
212 lines (189 loc) · 5.24 KB
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
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
#include "mruby_engine_private.h"
#include "value.h"
#include <mruby.h>
#include <mruby/array.h>
#include <mruby/class.h>
#include <mruby/dump.h>
#include <mruby/error.h>
#include <mruby/hash.h>
#include <mruby/string.h>
#include <mruby/variable.h>
static me_host_value_t me_value_to_host_r(
struct me_mruby_engine *self,
mrb_value value,
int depth,
struct me_value_err *err)
{
if (depth > ME_HOST_DATA_DEPTH_MAX) {
*err = (struct me_value_err){ .type = ME_VALUE_TOO_DEEP };
return ME_HOST_NIL;
}
if (mrb_nil_p(value)) {
return ME_HOST_NIL;
}
enum mrb_vtype type = mrb_type(value);
switch (type) {
case MRB_TT_FALSE:
return ME_HOST_FALSE;
case MRB_TT_TRUE:
return ME_HOST_TRUE;
case MRB_TT_FIXNUM:
return me_value_host_fixnum_new(mrb_fixnum(value), err);
case MRB_TT_STRING:
return me_value_host_string_new(RSTRING_PTR(value), RSTRING_LEN(value), err);
case MRB_TT_SYMBOL:
{
mrb_int len;
const char *p = mrb_sym2name_len(self->state, mrb_symbol(value), &len);
return me_value_host_symbol_new(p, len, err);
}
case MRB_TT_ARRAY:
{
me_host_value_t array = me_value_host_array_new(err);
if (err->type != ME_VALUE_NO_ERR) {
return ME_HOST_NIL;
}
for (mrb_int i = 0, f = RARRAY_LEN(value); i < f; ++i) {
me_host_value_t element = me_value_to_host_r(
self, mrb_ary_ref(self->state, value, i), depth + 1, err);
if (err->type != ME_VALUE_NO_ERR) {
return ME_HOST_NIL;
}
me_value_host_array_push(array, element, err);
if (err->type != ME_VALUE_NO_ERR) {
return ME_HOST_NIL;
}
}
return array;
}
case MRB_TT_HASH:
{
me_host_value_t hash = me_value_host_hash_new(err);
if (err->type != ME_VALUE_NO_ERR) {
return ME_HOST_NIL;
}
mrb_value keys = mrb_hash_keys(self->state, value);
mrb_int len = RARRAY_LEN(keys);
for (mrb_int i = 0; i < len; ++i) {
mrb_value k = mrb_ary_ref(self->state, keys, i);
me_host_value_t key = me_value_to_host_r(
self, k, depth + 1, err);
if (err->type != ME_VALUE_NO_ERR) {
return ME_HOST_NIL;
}
me_host_value_t element = me_value_to_host_r(
self, mrb_hash_get(self->state, value, k), depth + 1, err);
if (err->type != ME_VALUE_NO_ERR) {
return ME_HOST_NIL;
}
me_value_host_hash_assoc(hash, key, element, err);
if (err->type != ME_VALUE_NO_ERR) {
return ME_HOST_NIL;
}
}
return hash;
}
default:
{
*err = (struct me_value_err){ .type = ME_VALUE_UNSUPPORTED };
return ME_HOST_NIL;
}
}
}
me_host_value_t me_value_to_host(
struct me_mruby_engine *self,
me_guest_value_t value,
struct me_value_err *err)
{
return me_value_to_host_r(self, (mrb_value){ .w = value }, 0, err);
}
me_guest_value_t me_value_guest_nil_new(void) {
return mrb_nil_value().w;
}
me_guest_value_t me_value_guest_false_new(void) {
return mrb_false_value().w;
}
me_guest_value_t me_value_guest_true_new(void) {
return mrb_true_value().w;
}
static void me_value_guest_check_exception(
struct me_mruby_engine *engine,
struct me_value_err *err)
{
me_host_exception_t guest_err = me_mruby_engine_get_exception(engine);
if (guest_err == ME_HOST_NIL) {
return;
}
*err = (struct me_value_err){
.type = ME_VALUE_GUEST_ERR,
.guest_err = { .err = guest_err },
};
}
me_guest_value_t me_value_guest_fixnum_new(
struct me_mruby_engine *engine,
long value,
struct me_value_err *err)
{
mrb_value v = mrb_fixnum_value(value);
me_value_guest_check_exception(engine, err);
return v.w;
}
me_guest_value_t me_value_guest_string_new(
struct me_mruby_engine *engine,
const char *bytes,
size_t size,
struct me_value_err *err)
{
mrb_value v = mrb_str_new(engine->state, bytes, size);
me_value_guest_check_exception(engine, err);
return v.w;
}
me_guest_value_t me_value_guest_symbol_new(
struct me_mruby_engine *engine,
const char *bytes,
size_t size,
struct me_value_err *err)
{
mrb_sym v = mrb_intern(engine->state, bytes, size);
me_value_guest_check_exception(engine, err);
return mrb_symbol_value(v).w;
}
me_guest_value_t me_value_guest_array_new(
struct me_mruby_engine *engine,
struct me_value_err *err)
{
mrb_value v = mrb_ary_new(engine->state);
me_value_guest_check_exception(engine, err);
return v.w;
}
void me_value_guest_array_push(
struct me_mruby_engine *engine,
me_guest_value_t array,
me_guest_value_t element,
struct me_value_err *err)
{
mrb_ary_push(engine->state, (mrb_value){ .w = array }, (mrb_value){ .w = element });
me_value_guest_check_exception(engine, err);
}
me_guest_value_t me_value_guest_hash_new(
struct me_mruby_engine *engine,
struct me_value_err *err)
{
mrb_value v = mrb_hash_new(engine->state);
me_value_guest_check_exception(engine, err);
return v.w;
}
void me_value_guest_hash_assoc(
struct me_mruby_engine *engine,
me_guest_value_t hash,
me_guest_value_t key,
me_guest_value_t value,
struct me_value_err *err)
{
mrb_hash_set(
engine->state,
(mrb_value){ .w = hash },
(mrb_value){ .w = key },
(mrb_value){ .w = value });
me_value_guest_check_exception(engine, err);
}