forked from jarjin/tolua_runtime_V2
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathbootstrap.c
303 lines (261 loc) · 7.17 KB
/
bootstrap.c
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
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
#include "pbc.h"
#include "map.h"
#include "context.h"
#include "pattern.h"
#include "proto.h"
#include "alloc.h"
#include "bootstrap.h"
#include "stringpool.h"
#include "array.h"
#include "descriptor.pbc.h"
#include <stdlib.h>
#include <stddef.h>
#include <string.h>
#include <stdint.h>
/*
// Descriptor
// google.protobuf.Descriptor.proto encoded in descriptor.pbc.h with proto pbc.file .
package pbc;
message field {
optional string name = 1;
optional int32 id = 2;
optional int32 label = 3; // 0 optional 1 required 2 repeated
optional int32 type = 4; // type_id
optional string type_name = 5;
optional int32 default_int = 6;
optional string default_string = 7;
optional double default_real = 8;
}
message file {
optional string name = 1;
repeated string dependency = 2;
repeated string message_name = 3;
repeated int32 message_size = 4;
repeated field message_field = 5;
repeated string enum_name = 6;
repeated int32 enum_size = 7;
repeated string enum_string = 8;
repeated int32 enum_id = 9;
}
*/
struct field_t {
struct pbc_slice name;
int32_t id;
int32_t label;
int32_t type;
struct pbc_slice type_name;
int32_t default_integer;
struct pbc_slice default_string;
double default_real;
};
struct file_t {
struct pbc_slice name; // string
pbc_array dependency; // string
pbc_array message_name; // string
pbc_array message_size; // int32
pbc_array message_field; // field_t
pbc_array enum_name; // string
pbc_array enum_size; // int32
pbc_array enum_string; // string
pbc_array enum_id; // int32
};
static void
set_enum_one(struct pbc_env *p, struct file_t *file, const char *name, int start, int sz) {
struct map_kv *table = (struct map_kv *)malloc(sz * sizeof(struct map_kv));
int i;
for (i=0;i<sz;i++) {
pbc_var id;
pbc_var string;
_pbcA_index(file->enum_id, start+i, id);
_pbcA_index(file->enum_string, start+i, string);
table[i].id = (int)id->integer.low;
table[i].pointer = (void *)string->s.str;
}
_pbcP_push_enum(p,name,table,sz);
free(table);
}
static void
set_enums(struct pbc_env *p, struct file_t *file) {
int n = pbc_array_size(file->enum_size);
int i;
int start = 0;
for (i=0;i<n;i++) {
pbc_var name;
_pbcA_index(file->enum_name,i,name);
pbc_var var;
_pbcA_index(file->enum_size,i,var);
set_enum_one(p, file, name->s.str, start , (int)var->integer.low);
start += var->integer.low;
}
}
static void
set_default(struct _field *f, struct field_t *input) {
switch (f->type) {
case PTYPE_DOUBLE:
case PTYPE_FLOAT:
f->default_v->real = input->default_real;
break;
case PTYPE_STRING:
case PTYPE_ENUM:
f->default_v->m = input->default_string;
break;
default:
f->default_v->integer.low = input->default_integer;
break;
}
}
static void
set_msg_one(struct pbc_pattern * FIELD_T, struct pbc_env *p, struct file_t *file, const char *name, int start, int sz , pbc_array queue) {
int i;
for (i=0;i<sz;i++) {
pbc_var _field;
_pbcA_index(file->message_field, start+i, _field);
struct field_t field;
int ret = pbc_pattern_unpack(FIELD_T, &_field->m, &field);
if (ret != 0) {
continue;
}
struct _field f;
f.id = field.id;
f.name = (const char *)field.name.buffer;
f.type = field.type;
f.label = field.label;
f.type_name.n = (const char *)field.type_name.buffer;
set_default(&f, &field);
_pbcP_push_message(p,name, &f , queue);
// don't need to close pattern since no array
}
_pbcP_init_message(p, name);
}
static void
set_msgs(struct pbc_pattern * FIELD_T, struct pbc_env *p, struct file_t *file , pbc_array queue) {
int n = pbc_array_size(file->message_size);
int i;
int start = 0;
for (i=0;i<n;i++) {
pbc_var name;
_pbcA_index(file->message_name,i,name);
pbc_var sz;
_pbcA_index(file->message_size,i,sz);
set_msg_one(FIELD_T, p, file, name->s.str, start , (int)sz->integer.low , queue);
start += sz->integer.low;
}
}
static void
set_field_one(struct pbc_env *p, struct _field *f) {
const char * type_name = f->type_name.n;
if (f->type == PTYPE_MESSAGE) {
f->type_name.m = (struct _message *)_pbcM_sp_query(p->msgs, type_name);
// printf("MESSAGE: %s %p\n",type_name, f->type_name.m);
} else if (f->type == PTYPE_ENUM) {
f->type_name.e = (struct _enum *)_pbcM_sp_query(p->enums, type_name);
// printf("ENUM: %s %p ",type_name, f->type_name.e);
const char * str = f->default_v->s.str;
if (str && str[0]) {
int err = _pbcM_si_query(f->type_name.e->name, str , &(f->default_v->e.id));
if (err < 0)
goto _default;
f->default_v->e.name = (const char *)_pbcM_ip_query(f->type_name.e->id, f->default_v->e.id);
// printf("[%s %d]\n",str,f->default_v->e.id);
} else {
_default:
memcpy(f->default_v, f->type_name.e->default_v, sizeof(pbc_var));
// printf("(%s %d)\n",f->default_v->e.name,f->default_v->e.id);
}
}
}
void
_pbcB_register_fields(struct pbc_env *p, pbc_array queue) {
int sz = pbc_array_size(queue);
int i;
for (i=0;i<sz;i++) {
pbc_var atom;
_pbcA_index(queue,i,atom);
struct _field * f = (struct _field *)atom->m.buffer;
set_field_one(p, f);
}
}
static void
_set_string(struct _pattern_field * f) {
f->ptype = PTYPE_STRING;
f->ctype = CTYPE_VAR;
f->defv->s.str = "";
f->defv->s.len = 0;
}
static void
_set_int32(struct _pattern_field * f) {
f->ptype = PTYPE_INT32;
f->ctype = CTYPE_INT32;
}
static void
_set_double(struct _pattern_field * f) {
f->ptype = PTYPE_DOUBLE;
f->ctype = CTYPE_DOUBLE;
}
static void
_set_message_array(struct _pattern_field *f) {
f->ptype = PTYPE_MESSAGE;
f->ctype = CTYPE_ARRAY;
}
static void
_set_string_array(struct _pattern_field * f) {
f->ptype = PTYPE_STRING;
f->ctype = CTYPE_ARRAY;
}
static void
_set_int32_array(struct _pattern_field * f) {
f->ptype = PTYPE_INT32;
f->ctype = CTYPE_ARRAY;
}
#define SET_PATTERN(pat , idx , pat_type, field_name , type) \
pat->f[idx].id = idx+1 ; \
pat->f[idx].offset = offsetof(struct pat_type, field_name); \
_set_##type(&pat->f[idx]);
#define F(idx,field_name,type) SET_PATTERN(FIELD_T, idx, field_t ,field_name, type)
#define D(idx,field_name,type) SET_PATTERN(FILE_T, idx, file_t ,field_name, type)
static int
register_internal(struct pbc_env * p, struct pbc_slice *slice) {
struct pbc_pattern * FIELD_T = _pbcP_new(p,8);
F(0,name,string);
F(1,id,int32);
F(2,label,int32);
F(3,type,int32);
F(4,type_name,string);
F(5,default_integer,int32);
F(6,default_string,string);
F(7,default_real,double);
struct pbc_pattern * FILE_T = _pbcP_new(p,10);
D(0,name,string);
D(1,dependency,string_array);
D(2,message_name,string_array);
D(3,message_size,int32_array);
D(4,message_field,message_array);
D(5,enum_name,string_array);
D(6,enum_size,int32_array);
D(7,enum_string,string_array);
D(8,enum_id,int32_array);
int ret = 0;
struct file_t file;
int r = pbc_pattern_unpack(FILE_T, slice, &file);
if (r != 0) {
ret = 1;
goto _return;
}
_pbcM_sp_insert(p->files , (const char *)file.name.buffer, NULL);
pbc_array queue;
_pbcA_open(queue);
set_enums(p, &file);
set_msgs(FIELD_T, p, &file, queue);
_pbcB_register_fields(p, queue);
_pbcA_close(queue);
pbc_pattern_close_arrays(FILE_T, &file);
_return:
free(FIELD_T);
free(FILE_T);
return ret;
}
void
_pbcB_init(struct pbc_env * p) {
struct pbc_slice slice = { pbc_descriptor,sizeof(pbc_descriptor) };
register_internal(p,&slice);
}