OLD | NEW |
| (Empty) |
1 // Protocol Buffers - Google's data interchange format | |
2 // Copyright 2008 Google Inc. All rights reserved. | |
3 // https://developers.google.com/protocol-buffers/ | |
4 // | |
5 // Redistribution and use in source and binary forms, with or without | |
6 // modification, are permitted provided that the following conditions are | |
7 // met: | |
8 // | |
9 // * Redistributions of source code must retain the above copyright | |
10 // notice, this list of conditions and the following disclaimer. | |
11 // * Redistributions in binary form must reproduce the above | |
12 // copyright notice, this list of conditions and the following disclaimer | |
13 // in the documentation and/or other materials provided with the | |
14 // distribution. | |
15 // * Neither the name of Google Inc. nor the names of its | |
16 // contributors may be used to endorse or promote products derived from | |
17 // this software without specific prior written permission. | |
18 // | |
19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
20 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
21 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | |
22 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | |
23 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
24 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |
25 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
26 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
27 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
28 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
29 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
30 | |
31 #include "protobuf.h" | |
32 #include "utf8.h" | |
33 | |
34 /* stringsink *****************************************************************/ | |
35 | |
36 typedef struct { | |
37 upb_byteshandler handler; | |
38 upb_bytessink sink; | |
39 char *ptr; | |
40 size_t len, size; | |
41 } stringsink; | |
42 | |
43 | |
44 static void *stringsink_start(void *_sink, const void *hd, size_t size_hint) { | |
45 stringsink *sink = _sink; | |
46 sink->len = 0; | |
47 return sink; | |
48 } | |
49 | |
50 static size_t stringsink_string(void *_sink, const void *hd, const char *ptr, | |
51 size_t len, const upb_bufhandle *handle) { | |
52 stringsink *sink = _sink; | |
53 size_t new_size = sink->size; | |
54 | |
55 UPB_UNUSED(hd); | |
56 UPB_UNUSED(handle); | |
57 | |
58 while (sink->len + len > new_size) { | |
59 new_size *= 2; | |
60 } | |
61 | |
62 if (new_size != sink->size) { | |
63 sink->ptr = realloc(sink->ptr, new_size); | |
64 sink->size = new_size; | |
65 } | |
66 | |
67 memcpy(sink->ptr + sink->len, ptr, len); | |
68 sink->len += len; | |
69 | |
70 return len; | |
71 } | |
72 | |
73 void stringsink_init(stringsink *sink) { | |
74 upb_byteshandler_init(&sink->handler); | |
75 upb_byteshandler_setstartstr(&sink->handler, stringsink_start, NULL); | |
76 upb_byteshandler_setstring(&sink->handler, stringsink_string, NULL); | |
77 | |
78 upb_bytessink_reset(&sink->sink, &sink->handler, sink); | |
79 | |
80 sink->size = 32; | |
81 sink->ptr = malloc(sink->size); | |
82 sink->len = 0; | |
83 } | |
84 | |
85 void stringsink_uninit(stringsink *sink) { free(sink->ptr); } | |
86 | |
87 /* stackenv *****************************************************************/ | |
88 | |
89 // Stack-allocated context during an encode/decode operation. Contains the upb | |
90 // environment and its stack-based allocator, an initial buffer for allocations | |
91 // to avoid malloc() when possible, and a template for PHP exception messages | |
92 // if any error occurs. | |
93 #define STACK_ENV_STACKBYTES 4096 | |
94 typedef struct { | |
95 upb_env env; | |
96 const char *php_error_template; | |
97 char allocbuf[STACK_ENV_STACKBYTES]; | |
98 } stackenv; | |
99 | |
100 | |
101 static void stackenv_init(stackenv* se, const char* errmsg); | |
102 static void stackenv_uninit(stackenv* se); | |
103 | |
104 // Callback invoked by upb if any error occurs during parsing or serialization. | |
105 static bool env_error_func(void* ud, const upb_status* status) { | |
106 stackenv* se = ud; | |
107 // Free the env -- zend_error will longjmp up the stack past the | |
108 // encode/decode function so it would not otherwise have been freed. | |
109 stackenv_uninit(se); | |
110 | |
111 // TODO(teboring): have a way to verify that this is actually a parse error, | |
112 // instead of just throwing "parse error" unconditionally. | |
113 zend_error(E_ERROR, se->php_error_template, upb_status_errmsg(status)); | |
114 // Never reached. | |
115 return false; | |
116 } | |
117 | |
118 static void stackenv_init(stackenv* se, const char* errmsg) { | |
119 se->php_error_template = errmsg; | |
120 upb_env_init2(&se->env, se->allocbuf, sizeof(se->allocbuf), NULL); | |
121 upb_env_seterrorfunc(&se->env, env_error_func, se); | |
122 } | |
123 | |
124 static void stackenv_uninit(stackenv* se) { | |
125 upb_env_uninit(&se->env); | |
126 } | |
127 | |
128 // ----------------------------------------------------------------------------- | |
129 // Parsing. | |
130 // ----------------------------------------------------------------------------- | |
131 | |
132 #define DEREF(msg, ofs, type) *(type*)(((uint8_t *)msg) + ofs) | |
133 | |
134 // Creates a handlerdata that simply contains the offset for this field. | |
135 static const void* newhandlerdata(upb_handlers* h, uint32_t ofs) { | |
136 size_t* hd_ofs = (size_t*)malloc(sizeof(size_t)); | |
137 *hd_ofs = ofs; | |
138 upb_handlers_addcleanup(h, hd_ofs, free); | |
139 return hd_ofs; | |
140 } | |
141 | |
142 typedef struct { | |
143 size_t ofs; | |
144 const upb_msgdef *md; | |
145 } submsg_handlerdata_t; | |
146 | |
147 // Creates a handlerdata that contains offset and submessage type information. | |
148 static const void *newsubmsghandlerdata(upb_handlers* h, uint32_t ofs, | |
149 const upb_fielddef* f) { | |
150 submsg_handlerdata_t* hd = | |
151 (submsg_handlerdata_t*)malloc(sizeof(submsg_handlerdata_t)); | |
152 hd->ofs = ofs; | |
153 hd->md = upb_fielddef_msgsubdef(f); | |
154 upb_handlers_addcleanup(h, hd, free); | |
155 return hd; | |
156 } | |
157 | |
158 typedef struct { | |
159 size_t ofs; // union data slot | |
160 size_t case_ofs; // oneof_case field | |
161 int property_ofs; // properties table cache | |
162 uint32_t oneof_case_num; // oneof-case number to place in oneof_case field | |
163 const upb_msgdef *md; // msgdef, for oneof submessage handler | |
164 } oneof_handlerdata_t; | |
165 | |
166 static const void *newoneofhandlerdata(upb_handlers *h, | |
167 uint32_t ofs, | |
168 uint32_t case_ofs, | |
169 int property_ofs, | |
170 const upb_fielddef *f) { | |
171 oneof_handlerdata_t* hd = | |
172 (oneof_handlerdata_t*)malloc(sizeof(oneof_handlerdata_t)); | |
173 hd->ofs = ofs; | |
174 hd->case_ofs = case_ofs; | |
175 hd->property_ofs = property_ofs; | |
176 // We reuse the field tag number as a oneof union discriminant tag. Note that | |
177 // we don't expose these numbers to the user, so the only requirement is that | |
178 // we have some unique ID for each union case/possibility. The field tag | |
179 // numbers are already present and are easy to use so there's no reason to | |
180 // create a separate ID space. In addition, using the field tag number here | |
181 // lets us easily look up the field in the oneof accessor. | |
182 hd->oneof_case_num = upb_fielddef_number(f); | |
183 if (upb_fielddef_type(f) == UPB_TYPE_MESSAGE) { | |
184 hd->md = upb_fielddef_msgsubdef(f); | |
185 } else { | |
186 hd->md = NULL; | |
187 } | |
188 upb_handlers_addcleanup(h, hd, free); | |
189 return hd; | |
190 } | |
191 | |
192 // A handler that starts a repeated field. Gets the Repeated*Field instance for | |
193 // this field (such an instance always exists even in an empty message). | |
194 static void *startseq_handler(void* closure, const void* hd) { | |
195 MessageHeader* msg = closure; | |
196 const size_t *ofs = hd; | |
197 return (void*)(*DEREF(msg, *ofs, zval**)); | |
198 } | |
199 | |
200 // Handlers that append primitive values to a repeated field. | |
201 #define DEFINE_APPEND_HANDLER(type, ctype) \ | |
202 static bool append##type##_handler(void* closure, const void* hd, \ | |
203 ctype val) { \ | |
204 zval* array = (zval*)closure; \ | |
205 TSRMLS_FETCH(); \ | |
206 RepeatedField* intern = \ | |
207 (RepeatedField*)zend_object_store_get_object(array TSRMLS_CC); \ | |
208 repeated_field_push_native(intern, &val TSRMLS_CC); \ | |
209 return true; \ | |
210 } | |
211 | |
212 DEFINE_APPEND_HANDLER(bool, bool) | |
213 DEFINE_APPEND_HANDLER(int32, int32_t) | |
214 DEFINE_APPEND_HANDLER(uint32, uint32_t) | |
215 DEFINE_APPEND_HANDLER(float, float) | |
216 DEFINE_APPEND_HANDLER(int64, int64_t) | |
217 DEFINE_APPEND_HANDLER(uint64, uint64_t) | |
218 DEFINE_APPEND_HANDLER(double, double) | |
219 | |
220 // Appends a string to a repeated field. | |
221 static void* appendstr_handler(void *closure, | |
222 const void *hd, | |
223 size_t size_hint) { | |
224 zval* array = (zval*)closure; | |
225 TSRMLS_FETCH(); | |
226 RepeatedField* intern = | |
227 (RepeatedField*)zend_object_store_get_object(array TSRMLS_CC); | |
228 | |
229 zval* str; | |
230 MAKE_STD_ZVAL(str); | |
231 ZVAL_STRING(str, "", 1); | |
232 | |
233 repeated_field_push_native(intern, &str TSRMLS_CC); | |
234 return (void*)str; | |
235 } | |
236 | |
237 // Appends a 'bytes' string to a repeated field. | |
238 static void* appendbytes_handler(void *closure, | |
239 const void *hd, | |
240 size_t size_hint) { | |
241 zval* array = (zval*)closure; | |
242 TSRMLS_FETCH(); | |
243 RepeatedField* intern = | |
244 (RepeatedField*)zend_object_store_get_object(array TSRMLS_CC); | |
245 | |
246 zval* str; | |
247 MAKE_STD_ZVAL(str); | |
248 ZVAL_STRING(str, "", 1); | |
249 | |
250 repeated_field_push_native(intern, &str TSRMLS_CC); | |
251 return (void*)str; | |
252 } | |
253 | |
254 static void *empty_php_string(zval** value_ptr) { | |
255 SEPARATE_ZVAL_IF_NOT_REF(value_ptr); | |
256 zval* str = *value_ptr; | |
257 zval_dtor(str); | |
258 ZVAL_STRINGL(str, "", 0, 1); | |
259 return (void*)str; | |
260 } | |
261 | |
262 // Sets a non-repeated string field in a message. | |
263 static void* str_handler(void *closure, | |
264 const void *hd, | |
265 size_t size_hint) { | |
266 MessageHeader* msg = closure; | |
267 const size_t *ofs = hd; | |
268 return empty_php_string(DEREF(msg, *ofs, zval**)); | |
269 } | |
270 | |
271 // Sets a non-repeated 'bytes' field in a message. | |
272 static void* bytes_handler(void *closure, | |
273 const void *hd, | |
274 size_t size_hint) { | |
275 MessageHeader* msg = closure; | |
276 const size_t *ofs = hd; | |
277 return empty_php_string(DEREF(msg, *ofs, zval**)); | |
278 } | |
279 | |
280 static size_t stringdata_handler(void* closure, const void* hd, | |
281 const char* str, size_t len, | |
282 const upb_bufhandle* handle) { | |
283 zval* php_str = (zval*)closure; | |
284 | |
285 char* old_str = Z_STRVAL_P(php_str); | |
286 size_t old_len = Z_STRLEN_P(php_str); | |
287 assert(old_str != NULL); | |
288 | |
289 char* new_str = emalloc(old_len + len + 1); | |
290 | |
291 memcpy(new_str, old_str, old_len); | |
292 memcpy(new_str + old_len, str, len); | |
293 new_str[old_len + len] = 0; | |
294 FREE(old_str); | |
295 | |
296 Z_STRVAL_P(php_str) = new_str; | |
297 Z_STRLEN_P(php_str) = old_len + len; | |
298 | |
299 return len; | |
300 } | |
301 | |
302 // Appends a submessage to a repeated field. | |
303 static void *appendsubmsg_handler(void *closure, const void *hd) { | |
304 zval* array = (zval*)closure; | |
305 TSRMLS_FETCH(); | |
306 RepeatedField* intern = | |
307 (RepeatedField*)zend_object_store_get_object(array TSRMLS_CC); | |
308 | |
309 const submsg_handlerdata_t *submsgdata = hd; | |
310 zval* subdesc_php = get_def_obj((void*)submsgdata->md); | |
311 Descriptor* subdesc = zend_object_store_get_object(subdesc_php TSRMLS_CC); | |
312 zend_class_entry* subklass = subdesc->klass; | |
313 MessageHeader* submsg; | |
314 | |
315 zval* val = NULL; | |
316 MAKE_STD_ZVAL(val); | |
317 Z_TYPE_P(val) = IS_OBJECT; | |
318 Z_OBJVAL_P(val) = subklass->create_object(subklass TSRMLS_CC); | |
319 | |
320 repeated_field_push_native(intern, &val TSRMLS_CC); | |
321 | |
322 submsg = zend_object_store_get_object(val TSRMLS_CC); | |
323 return submsg; | |
324 } | |
325 | |
326 // Sets a non-repeated submessage field in a message. | |
327 static void *submsg_handler(void *closure, const void *hd) { | |
328 MessageHeader* msg = closure; | |
329 const submsg_handlerdata_t* submsgdata = hd; | |
330 zval* subdesc_php = get_def_obj((void*)submsgdata->md); | |
331 TSRMLS_FETCH(); | |
332 Descriptor* subdesc = zend_object_store_get_object(subdesc_php TSRMLS_CC); | |
333 zend_class_entry* subklass = subdesc->klass; | |
334 zval* submsg_php; | |
335 MessageHeader* submsg; | |
336 | |
337 if (Z_TYPE_P(*DEREF(msg, submsgdata->ofs, zval**)) == IS_NULL) { | |
338 zval* val = NULL; | |
339 MAKE_STD_ZVAL(val); | |
340 Z_TYPE_P(val) = IS_OBJECT; | |
341 Z_OBJVAL_P(val) = subklass->create_object(subklass TSRMLS_CC); | |
342 | |
343 zval_ptr_dtor(DEREF(msg, submsgdata->ofs, zval**)); | |
344 *DEREF(msg, submsgdata->ofs, zval**) = val; | |
345 } | |
346 | |
347 submsg_php = *DEREF(msg, submsgdata->ofs, zval**); | |
348 | |
349 submsg = zend_object_store_get_object(submsg_php TSRMLS_CC); | |
350 return submsg; | |
351 } | |
352 | |
353 // Handler data for startmap/endmap handlers. | |
354 typedef struct { | |
355 size_t ofs; | |
356 upb_fieldtype_t key_field_type; | |
357 upb_fieldtype_t value_field_type; | |
358 | |
359 // We know that we can hold this reference because the handlerdata has the | |
360 // same lifetime as the upb_handlers struct, and the upb_handlers struct holds | |
361 // a reference to the upb_msgdef, which in turn has references to its subdefs. | |
362 const upb_def* value_field_subdef; | |
363 } map_handlerdata_t; | |
364 | |
365 // Temporary frame for map parsing: at the beginning of a map entry message, a | |
366 // submsg handler allocates a frame to hold (i) a reference to the Map object | |
367 // into which this message will be inserted and (ii) storage slots to | |
368 // temporarily hold the key and value for this map entry until the end of the | |
369 // submessage. When the submessage ends, another handler is called to insert the | |
370 // value into the map. | |
371 typedef struct { | |
372 zval* map; | |
373 char key_storage[NATIVE_SLOT_MAX_SIZE]; | |
374 char value_storage[NATIVE_SLOT_MAX_SIZE]; | |
375 } map_parse_frame_t; | |
376 | |
377 static void map_slot_init(void* memory, upb_fieldtype_t type) { | |
378 switch (type) { | |
379 case UPB_TYPE_STRING: | |
380 case UPB_TYPE_BYTES: { | |
381 // Store zval** in memory in order to be consistent with the layout of | |
382 // singular fields. | |
383 zval** holder = ALLOC(zval*); | |
384 zval* tmp; | |
385 MAKE_STD_ZVAL(tmp); | |
386 ZVAL_STRINGL(tmp, "", 0, 1); | |
387 *holder = tmp; | |
388 *(zval***)memory = holder; | |
389 break; | |
390 } | |
391 case UPB_TYPE_MESSAGE: { | |
392 zval** holder = ALLOC(zval*); | |
393 zval* tmp; | |
394 MAKE_STD_ZVAL(tmp); | |
395 ZVAL_NULL(tmp); | |
396 *holder = tmp; | |
397 *(zval***)memory = holder; | |
398 break; | |
399 } | |
400 default: | |
401 native_slot_init(type, memory, NULL); | |
402 } | |
403 } | |
404 | |
405 static void map_slot_uninit(void* memory, upb_fieldtype_t type) { | |
406 switch (type) { | |
407 case UPB_TYPE_MESSAGE: | |
408 case UPB_TYPE_STRING: | |
409 case UPB_TYPE_BYTES: { | |
410 zval** holder = *(zval***)memory; | |
411 zval_ptr_dtor(holder); | |
412 FREE(holder); | |
413 break; | |
414 } | |
415 default: | |
416 break; | |
417 } | |
418 } | |
419 | |
420 static void map_slot_key(upb_fieldtype_t type, const void* from, | |
421 const char** keyval, | |
422 size_t* length) { | |
423 if (type == UPB_TYPE_STRING) { | |
424 zval* key_php = **(zval***)from; | |
425 *keyval = Z_STRVAL_P(key_php); | |
426 *length = Z_STRLEN_P(key_php); | |
427 } else { | |
428 *keyval = from; | |
429 *length = native_slot_size(type); | |
430 } | |
431 } | |
432 | |
433 static void map_slot_value(upb_fieldtype_t type, const void* from, | |
434 upb_value* v) { | |
435 size_t len; | |
436 void* to = upb_value_memory(v); | |
437 #ifndef NDEBUG | |
438 v->ctype = UPB_CTYPE_UINT64; | |
439 #endif | |
440 | |
441 memset(to, 0, native_slot_size(type)); | |
442 | |
443 switch (type) { | |
444 case UPB_TYPE_STRING: | |
445 case UPB_TYPE_BYTES: | |
446 case UPB_TYPE_MESSAGE: { | |
447 *(zval**)to = **(zval***)from; | |
448 Z_ADDREF_PP((zval**)to); | |
449 break; | |
450 } | |
451 default: | |
452 len = native_slot_size(type); | |
453 memcpy(to, from, len); | |
454 } | |
455 } | |
456 | |
457 // Handler to begin a map entry: allocates a temporary frame. This is the | |
458 // 'startsubmsg' handler on the msgdef that contains the map field. | |
459 static void *startmapentry_handler(void *closure, const void *hd) { | |
460 MessageHeader* msg = closure; | |
461 const map_handlerdata_t* mapdata = hd; | |
462 zval* map = *DEREF(msg, mapdata->ofs, zval**); | |
463 | |
464 map_parse_frame_t* frame = ALLOC(map_parse_frame_t); | |
465 frame->map = map; | |
466 | |
467 map_slot_init(&frame->key_storage, mapdata->key_field_type); | |
468 map_slot_init(&frame->value_storage, mapdata->value_field_type); | |
469 | |
470 return frame; | |
471 } | |
472 | |
473 // Handler to end a map entry: inserts the value defined during the message into | |
474 // the map. This is the 'endmsg' handler on the map entry msgdef. | |
475 static bool endmap_handler(void* closure, const void* hd, upb_status* s) { | |
476 map_parse_frame_t* frame = closure; | |
477 const map_handlerdata_t* mapdata = hd; | |
478 | |
479 TSRMLS_FETCH(); | |
480 Map *map = (Map *)zend_object_store_get_object(frame->map TSRMLS_CC); | |
481 | |
482 const char* keyval = NULL; | |
483 upb_value v; | |
484 size_t length; | |
485 | |
486 map_slot_key(map->key_type, &frame->key_storage, &keyval, &length); | |
487 map_slot_value(map->value_type, &frame->value_storage, &v); | |
488 | |
489 map_index_set(map, keyval, length, v); | |
490 | |
491 map_slot_uninit(&frame->key_storage, mapdata->key_field_type); | |
492 map_slot_uninit(&frame->value_storage, mapdata->value_field_type); | |
493 FREE(frame); | |
494 | |
495 return true; | |
496 } | |
497 | |
498 // Allocates a new map_handlerdata_t given the map entry message definition. If | |
499 // the offset of the field within the parent message is also given, that is | |
500 // added to the handler data as well. Note that this is called *twice* per map | |
501 // field: once in the parent message handler setup when setting the startsubmsg | |
502 // handler and once in the map entry message handler setup when setting the | |
503 // key/value and endmsg handlers. The reason is that there is no easy way to | |
504 // pass the handlerdata down to the sub-message handler setup. | |
505 static map_handlerdata_t* new_map_handlerdata( | |
506 size_t ofs, | |
507 const upb_msgdef* mapentry_def, | |
508 Descriptor* desc) { | |
509 const upb_fielddef* key_field; | |
510 const upb_fielddef* value_field; | |
511 // TODO(teboring): Use emalloc and efree. | |
512 map_handlerdata_t* hd = | |
513 (map_handlerdata_t*)malloc(sizeof(map_handlerdata_t)); | |
514 | |
515 hd->ofs = ofs; | |
516 key_field = upb_msgdef_itof(mapentry_def, MAP_KEY_FIELD); | |
517 assert(key_field != NULL); | |
518 hd->key_field_type = upb_fielddef_type(key_field); | |
519 value_field = upb_msgdef_itof(mapentry_def, MAP_VALUE_FIELD); | |
520 assert(value_field != NULL); | |
521 hd->value_field_type = upb_fielddef_type(value_field); | |
522 hd->value_field_subdef = upb_fielddef_subdef(value_field); | |
523 | |
524 return hd; | |
525 } | |
526 | |
527 // Handlers that set primitive values in oneofs. | |
528 #define DEFINE_ONEOF_HANDLER(type, ctype) \ | |
529 static bool oneof##type##_handler(void *closure, const void *hd, \ | |
530 ctype val) { \ | |
531 const oneof_handlerdata_t *oneofdata = hd; \ | |
532 DEREF(closure, oneofdata->case_ofs, uint32_t) = \ | |
533 oneofdata->oneof_case_num; \ | |
534 DEREF(closure, oneofdata->ofs, ctype) = val; \ | |
535 return true; \ | |
536 } | |
537 | |
538 DEFINE_ONEOF_HANDLER(bool, bool) | |
539 DEFINE_ONEOF_HANDLER(int32, int32_t) | |
540 DEFINE_ONEOF_HANDLER(uint32, uint32_t) | |
541 DEFINE_ONEOF_HANDLER(float, float) | |
542 DEFINE_ONEOF_HANDLER(int64, int64_t) | |
543 DEFINE_ONEOF_HANDLER(uint64, uint64_t) | |
544 DEFINE_ONEOF_HANDLER(double, double) | |
545 | |
546 #undef DEFINE_ONEOF_HANDLER | |
547 | |
548 // Handlers for strings in a oneof. | |
549 static void *oneofstr_handler(void *closure, | |
550 const void *hd, | |
551 size_t size_hint) { | |
552 MessageHeader* msg = closure; | |
553 const oneof_handlerdata_t *oneofdata = hd; | |
554 | |
555 DEREF(msg, oneofdata->case_ofs, uint32_t) = | |
556 oneofdata->oneof_case_num; | |
557 DEREF(msg, oneofdata->ofs, zval**) = | |
558 &(msg->std.properties_table)[oneofdata->property_ofs]; | |
559 | |
560 return empty_php_string(DEREF(msg, oneofdata->ofs, zval**)); | |
561 } | |
562 | |
563 static void *oneofbytes_handler(void *closure, | |
564 const void *hd, | |
565 size_t size_hint) { | |
566 MessageHeader* msg = closure; | |
567 const oneof_handlerdata_t *oneofdata = hd; | |
568 | |
569 DEREF(msg, oneofdata->case_ofs, uint32_t) = | |
570 oneofdata->oneof_case_num; | |
571 DEREF(msg, oneofdata->ofs, zval**) = | |
572 &(msg->std.properties_table)[oneofdata->property_ofs]; | |
573 | |
574 // TODO(teboring): Add it back. | |
575 // rb_enc_associate(str, kRubyString8bitEncoding); | |
576 | |
577 SEPARATE_ZVAL_IF_NOT_REF(DEREF(msg, oneofdata->ofs, zval**)); | |
578 zval* str = *DEREF(msg, oneofdata->ofs, zval**); | |
579 zval_dtor(str); | |
580 ZVAL_STRINGL(str, "", 0, 1); | |
581 return (void*)str; | |
582 } | |
583 | |
584 // Handler for a submessage field in a oneof. | |
585 static void* oneofsubmsg_handler(void* closure, const void* hd) { | |
586 MessageHeader* msg = closure; | |
587 const oneof_handlerdata_t *oneofdata = hd; | |
588 uint32_t oldcase = DEREF(msg, oneofdata->case_ofs, uint32_t); | |
589 zval* subdesc_php = get_def_obj((void*)oneofdata->md); | |
590 TSRMLS_FETCH(); | |
591 Descriptor* subdesc = zend_object_store_get_object(subdesc_php TSRMLS_CC); | |
592 zend_class_entry* subklass = subdesc->klass; | |
593 zval* submsg_php; | |
594 MessageHeader* submsg; | |
595 | |
596 if (oldcase != oneofdata->oneof_case_num) { | |
597 DEREF(msg, oneofdata->ofs, zval**) = | |
598 &(msg->std.properties_table)[oneofdata->property_ofs]; | |
599 } | |
600 | |
601 if (Z_TYPE_P(*DEREF(msg, oneofdata->ofs, zval**)) == IS_NULL) { | |
602 zval* val = NULL; | |
603 MAKE_STD_ZVAL(val); | |
604 Z_TYPE_P(val) = IS_OBJECT; | |
605 Z_OBJVAL_P(val) = subklass->create_object(subklass TSRMLS_CC); | |
606 | |
607 zval_ptr_dtor(DEREF(msg, oneofdata->ofs, zval**)); | |
608 *DEREF(msg, oneofdata->ofs, zval**) = val; | |
609 } | |
610 | |
611 DEREF(msg, oneofdata->case_ofs, uint32_t) = | |
612 oneofdata->oneof_case_num; | |
613 | |
614 submsg_php = *DEREF(msg, oneofdata->ofs, zval**); | |
615 submsg = zend_object_store_get_object(submsg_php TSRMLS_CC); | |
616 return submsg; | |
617 } | |
618 | |
619 // Set up handlers for a repeated field. | |
620 static void add_handlers_for_repeated_field(upb_handlers *h, | |
621 const upb_fielddef *f, | |
622 size_t offset) { | |
623 upb_handlerattr attr = UPB_HANDLERATTR_INITIALIZER; | |
624 upb_handlerattr_sethandlerdata(&attr, newhandlerdata(h, offset)); | |
625 upb_handlers_setstartseq(h, f, startseq_handler, &attr); | |
626 upb_handlerattr_uninit(&attr); | |
627 | |
628 switch (upb_fielddef_type(f)) { | |
629 | |
630 #define SET_HANDLER(utype, ltype) \ | |
631 case utype: \ | |
632 upb_handlers_set##ltype(h, f, append##ltype##_handler, NULL); \ | |
633 break; | |
634 | |
635 SET_HANDLER(UPB_TYPE_BOOL, bool); | |
636 SET_HANDLER(UPB_TYPE_INT32, int32); | |
637 SET_HANDLER(UPB_TYPE_UINT32, uint32); | |
638 SET_HANDLER(UPB_TYPE_ENUM, int32); | |
639 SET_HANDLER(UPB_TYPE_FLOAT, float); | |
640 SET_HANDLER(UPB_TYPE_INT64, int64); | |
641 SET_HANDLER(UPB_TYPE_UINT64, uint64); | |
642 SET_HANDLER(UPB_TYPE_DOUBLE, double); | |
643 | |
644 #undef SET_HANDLER | |
645 | |
646 case UPB_TYPE_STRING: | |
647 case UPB_TYPE_BYTES: { | |
648 bool is_bytes = upb_fielddef_type(f) == UPB_TYPE_BYTES; | |
649 upb_handlers_setstartstr(h, f, is_bytes ? | |
650 appendbytes_handler : appendstr_handler, | |
651 NULL); | |
652 upb_handlers_setstring(h, f, stringdata_handler, NULL); | |
653 break; | |
654 } | |
655 case UPB_TYPE_MESSAGE: { | |
656 upb_handlerattr attr = UPB_HANDLERATTR_INITIALIZER; | |
657 upb_handlerattr_sethandlerdata(&attr, newsubmsghandlerdata(h, 0, f)); | |
658 upb_handlers_setstartsubmsg(h, f, appendsubmsg_handler, &attr); | |
659 upb_handlerattr_uninit(&attr); | |
660 break; | |
661 } | |
662 } | |
663 } | |
664 | |
665 // Set up handlers for a singular field. | |
666 static void add_handlers_for_singular_field(upb_handlers *h, | |
667 const upb_fielddef *f, | |
668 size_t offset) { | |
669 switch (upb_fielddef_type(f)) { | |
670 case UPB_TYPE_BOOL: | |
671 case UPB_TYPE_INT32: | |
672 case UPB_TYPE_UINT32: | |
673 case UPB_TYPE_ENUM: | |
674 case UPB_TYPE_FLOAT: | |
675 case UPB_TYPE_INT64: | |
676 case UPB_TYPE_UINT64: | |
677 case UPB_TYPE_DOUBLE: | |
678 upb_shim_set(h, f, offset, -1); | |
679 break; | |
680 case UPB_TYPE_STRING: | |
681 case UPB_TYPE_BYTES: { | |
682 bool is_bytes = upb_fielddef_type(f) == UPB_TYPE_BYTES; | |
683 upb_handlerattr attr = UPB_HANDLERATTR_INITIALIZER; | |
684 upb_handlerattr_sethandlerdata(&attr, newhandlerdata(h, offset)); | |
685 upb_handlers_setstartstr(h, f, | |
686 is_bytes ? bytes_handler : str_handler, | |
687 &attr); | |
688 upb_handlers_setstring(h, f, stringdata_handler, &attr); | |
689 upb_handlerattr_uninit(&attr); | |
690 break; | |
691 } | |
692 case UPB_TYPE_MESSAGE: { | |
693 upb_handlerattr attr = UPB_HANDLERATTR_INITIALIZER; | |
694 upb_handlerattr_sethandlerdata(&attr, newsubmsghandlerdata(h, offset, f)); | |
695 upb_handlers_setstartsubmsg(h, f, submsg_handler, &attr); | |
696 upb_handlerattr_uninit(&attr); | |
697 break; | |
698 } | |
699 } | |
700 } | |
701 | |
702 // Adds handlers to a map field. | |
703 static void add_handlers_for_mapfield(upb_handlers* h, | |
704 const upb_fielddef* fielddef, | |
705 size_t offset, | |
706 Descriptor* desc) { | |
707 const upb_msgdef* map_msgdef = upb_fielddef_msgsubdef(fielddef); | |
708 map_handlerdata_t* hd = new_map_handlerdata(offset, map_msgdef, desc); | |
709 upb_handlerattr attr = UPB_HANDLERATTR_INITIALIZER; | |
710 | |
711 upb_handlers_addcleanup(h, hd, free); | |
712 upb_handlerattr_sethandlerdata(&attr, hd); | |
713 upb_handlers_setstartsubmsg(h, fielddef, startmapentry_handler, &attr); | |
714 upb_handlerattr_uninit(&attr); | |
715 } | |
716 | |
717 // Adds handlers to a map-entry msgdef. | |
718 static void add_handlers_for_mapentry(const upb_msgdef* msgdef, upb_handlers* h, | |
719 Descriptor* desc) { | |
720 const upb_fielddef* key_field = map_entry_key(msgdef); | |
721 const upb_fielddef* value_field = map_entry_value(msgdef); | |
722 map_handlerdata_t* hd = new_map_handlerdata(0, msgdef, desc); | |
723 upb_handlerattr attr = UPB_HANDLERATTR_INITIALIZER; | |
724 | |
725 upb_handlers_addcleanup(h, hd, free); | |
726 upb_handlerattr_sethandlerdata(&attr, hd); | |
727 upb_handlers_setendmsg(h, endmap_handler, &attr); | |
728 | |
729 add_handlers_for_singular_field(h, key_field, | |
730 offsetof(map_parse_frame_t, key_storage)); | |
731 add_handlers_for_singular_field(h, value_field, | |
732 offsetof(map_parse_frame_t, value_storage)); | |
733 } | |
734 | |
735 // Set up handlers for a oneof field. | |
736 static void add_handlers_for_oneof_field(upb_handlers *h, | |
737 const upb_fielddef *f, | |
738 size_t offset, | |
739 size_t oneof_case_offset, | |
740 int property_cache_offset) { | |
741 | |
742 upb_handlerattr attr = UPB_HANDLERATTR_INITIALIZER; | |
743 upb_handlerattr_sethandlerdata( | |
744 &attr, newoneofhandlerdata(h, offset, oneof_case_offset, | |
745 property_cache_offset, f)); | |
746 | |
747 switch (upb_fielddef_type(f)) { | |
748 | |
749 #define SET_HANDLER(utype, ltype) \ | |
750 case utype: \ | |
751 upb_handlers_set##ltype(h, f, oneof##ltype##_handler, &attr); \ | |
752 break; | |
753 | |
754 SET_HANDLER(UPB_TYPE_BOOL, bool); | |
755 SET_HANDLER(UPB_TYPE_INT32, int32); | |
756 SET_HANDLER(UPB_TYPE_UINT32, uint32); | |
757 SET_HANDLER(UPB_TYPE_ENUM, int32); | |
758 SET_HANDLER(UPB_TYPE_FLOAT, float); | |
759 SET_HANDLER(UPB_TYPE_INT64, int64); | |
760 SET_HANDLER(UPB_TYPE_UINT64, uint64); | |
761 SET_HANDLER(UPB_TYPE_DOUBLE, double); | |
762 | |
763 #undef SET_HANDLER | |
764 | |
765 case UPB_TYPE_STRING: | |
766 case UPB_TYPE_BYTES: { | |
767 bool is_bytes = upb_fielddef_type(f) == UPB_TYPE_BYTES; | |
768 upb_handlers_setstartstr(h, f, is_bytes ? | |
769 oneofbytes_handler : oneofstr_handler, | |
770 &attr); | |
771 upb_handlers_setstring(h, f, stringdata_handler, NULL); | |
772 break; | |
773 } | |
774 case UPB_TYPE_MESSAGE: { | |
775 upb_handlers_setstartsubmsg(h, f, oneofsubmsg_handler, &attr); | |
776 break; | |
777 } | |
778 } | |
779 | |
780 upb_handlerattr_uninit(&attr); | |
781 } | |
782 | |
783 static void add_handlers_for_message(const void* closure, | |
784 upb_handlers* h) { | |
785 const upb_msgdef* msgdef = upb_handlers_msgdef(h); | |
786 TSRMLS_FETCH(); | |
787 Descriptor* desc = (Descriptor*)zend_object_store_get_object( | |
788 get_def_obj((void*)msgdef) TSRMLS_CC); | |
789 upb_msg_field_iter i; | |
790 | |
791 // If this is a mapentry message type, set up a special set of handlers and | |
792 // bail out of the normal (user-defined) message type handling. | |
793 if (upb_msgdef_mapentry(msgdef)) { | |
794 add_handlers_for_mapentry(msgdef, h, desc); | |
795 return; | |
796 } | |
797 | |
798 // Ensure layout exists. We may be invoked to create handlers for a given | |
799 // message if we are included as a submsg of another message type before our | |
800 // class is actually built, so to work around this, we just create the layout | |
801 // (and handlers, in the class-building function) on-demand. | |
802 if (desc->layout == NULL) { | |
803 desc->layout = create_layout(desc->msgdef); | |
804 } | |
805 | |
806 for (upb_msg_field_begin(&i, desc->msgdef); | |
807 !upb_msg_field_done(&i); | |
808 upb_msg_field_next(&i)) { | |
809 const upb_fielddef *f = upb_msg_iter_field(&i); | |
810 size_t offset = desc->layout->fields[upb_fielddef_index(f)].offset + | |
811 sizeof(MessageHeader); | |
812 | |
813 if (upb_fielddef_containingoneof(f)) { | |
814 size_t oneof_case_offset = | |
815 desc->layout->fields[upb_fielddef_index(f)].case_offset + | |
816 sizeof(MessageHeader); | |
817 int property_cache_index = | |
818 desc->layout->fields[upb_fielddef_index(f)].cache_index; | |
819 add_handlers_for_oneof_field(h, f, offset, oneof_case_offset, | |
820 property_cache_index); | |
821 } else if (is_map_field(f)) { | |
822 add_handlers_for_mapfield(h, f, offset, desc); | |
823 } else if (upb_fielddef_isseq(f)) { | |
824 add_handlers_for_repeated_field(h, f, offset); | |
825 } else { | |
826 add_handlers_for_singular_field(h, f, offset); | |
827 } | |
828 } | |
829 } | |
830 | |
831 // Creates upb handlers for populating a message. | |
832 static const upb_handlers *new_fill_handlers(Descriptor* desc, | |
833 const void* owner) { | |
834 // TODO(cfallin, haberman): once upb gets a caching/memoization layer for | |
835 // handlers, reuse subdef handlers so that e.g. if we already parse | |
836 // B-with-field-of-type-C, we don't have to rebuild the whole hierarchy to | |
837 // parse A-with-field-of-type-B-with-field-of-type-C. | |
838 return upb_handlers_newfrozen(desc->msgdef, owner, | |
839 add_handlers_for_message, NULL); | |
840 } | |
841 | |
842 // Constructs the handlers for filling a message's data into an in-memory | |
843 // object. | |
844 const upb_handlers* get_fill_handlers(Descriptor* desc) { | |
845 if (!desc->fill_handlers) { | |
846 desc->fill_handlers = | |
847 new_fill_handlers(desc, &desc->fill_handlers); | |
848 } | |
849 return desc->fill_handlers; | |
850 } | |
851 | |
852 const upb_pbdecodermethod *new_fillmsg_decodermethod(Descriptor* desc, | |
853 const void* owner) { | |
854 const upb_handlers* handlers = get_fill_handlers(desc); | |
855 upb_pbdecodermethodopts opts; | |
856 upb_pbdecodermethodopts_init(&opts, handlers); | |
857 | |
858 return upb_pbdecodermethod_new(&opts, owner); | |
859 } | |
860 | |
861 static const upb_pbdecodermethod *msgdef_decodermethod(Descriptor* desc) { | |
862 if (desc->fill_method == NULL) { | |
863 desc->fill_method = new_fillmsg_decodermethod( | |
864 desc, &desc->fill_method); | |
865 } | |
866 return desc->fill_method; | |
867 } | |
868 | |
869 // ----------------------------------------------------------------------------- | |
870 // Serializing. | |
871 // ----------------------------------------------------------------------------- | |
872 | |
873 static void putmsg(zval* msg, const Descriptor* desc, upb_sink* sink, | |
874 int depth TSRMLS_DC); | |
875 | |
876 static void putstr(zval* str, const upb_fielddef* f, upb_sink* sink); | |
877 | |
878 static void putrawstr(const char* str, int len, const upb_fielddef* f, | |
879 upb_sink* sink); | |
880 | |
881 static void putsubmsg(zval* submsg, const upb_fielddef* f, upb_sink* sink, | |
882 int depth TSRMLS_DC); | |
883 | |
884 static void putarray(zval* array, const upb_fielddef* f, upb_sink* sink, | |
885 int depth TSRMLS_DC); | |
886 static void putmap(zval* map, const upb_fielddef* f, upb_sink* sink, int depth | |
887 TSRMLS_DC); | |
888 | |
889 static upb_selector_t getsel(const upb_fielddef* f, upb_handlertype_t type) { | |
890 upb_selector_t ret; | |
891 bool ok = upb_handlers_getselector(f, type, &ret); | |
892 UPB_ASSERT(ok); | |
893 return ret; | |
894 } | |
895 | |
896 static void put_optional_value(const void* memory, int len, const upb_fielddef*
f, | |
897 int depth, upb_sink* sink TSRMLS_DC) { | |
898 assert(upb_fielddef_label(f) == UPB_LABEL_OPTIONAL); | |
899 | |
900 switch (upb_fielddef_type(f)) { | |
901 #define T(upbtypeconst, upbtype, ctype, default_value) \ | |
902 case upbtypeconst: { \ | |
903 ctype value = DEREF(memory, 0, ctype); \ | |
904 if (value != default_value) { \ | |
905 upb_selector_t sel = getsel(f, upb_handlers_getprimitivehandlertype(f)); \ | |
906 upb_sink_put##upbtype(sink, sel, value); \ | |
907 } \ | |
908 } break; | |
909 | |
910 T(UPB_TYPE_FLOAT, float, float, 0.0) | |
911 T(UPB_TYPE_DOUBLE, double, double, 0.0) | |
912 T(UPB_TYPE_BOOL, bool, uint8_t, 0) | |
913 T(UPB_TYPE_ENUM, int32, int32_t, 0) | |
914 T(UPB_TYPE_INT32, int32, int32_t, 0) | |
915 T(UPB_TYPE_UINT32, uint32, uint32_t, 0) | |
916 T(UPB_TYPE_INT64, int64, int64_t, 0) | |
917 T(UPB_TYPE_UINT64, uint64, uint64_t, 0) | |
918 | |
919 #undef T | |
920 case UPB_TYPE_STRING: | |
921 case UPB_TYPE_BYTES: | |
922 putrawstr(memory, len, f, sink); | |
923 break; | |
924 case UPB_TYPE_MESSAGE: { | |
925 zval* submsg = *(zval**)memory; | |
926 putsubmsg(submsg, f, sink, depth TSRMLS_CC); | |
927 break; | |
928 } | |
929 default: | |
930 assert(false); | |
931 } | |
932 } | |
933 | |
934 // Only string/bytes fields are stored as zval. | |
935 static const char* raw_value(void* memory, const upb_fielddef* f) { | |
936 switch (upb_fielddef_type(f)) { | |
937 case UPB_TYPE_STRING: | |
938 case UPB_TYPE_BYTES: | |
939 return Z_STRVAL_PP((zval**)memory); | |
940 break; | |
941 default: | |
942 return memory; | |
943 } | |
944 } | |
945 | |
946 static int raw_value_len(void* memory, int len, const upb_fielddef* f) { | |
947 switch (upb_fielddef_type(f)) { | |
948 case UPB_TYPE_STRING: | |
949 case UPB_TYPE_BYTES: | |
950 return Z_STRLEN_PP((zval**)memory); | |
951 break; | |
952 default: | |
953 return len; | |
954 } | |
955 } | |
956 | |
957 static void putmap(zval* map, const upb_fielddef* f, upb_sink* sink, | |
958 int depth TSRMLS_DC) { | |
959 Map* self; | |
960 upb_sink subsink; | |
961 const upb_fielddef* key_field; | |
962 const upb_fielddef* value_field; | |
963 MapIter it; | |
964 int len; | |
965 | |
966 if (map == NULL) return; | |
967 self = UNBOX(Map, map); | |
968 | |
969 upb_sink_startseq(sink, getsel(f, UPB_HANDLER_STARTSEQ), &subsink); | |
970 | |
971 assert(upb_fielddef_type(f) == UPB_TYPE_MESSAGE); | |
972 key_field = map_field_key(f); | |
973 value_field = map_field_value(f); | |
974 | |
975 for (map_begin(map, &it TSRMLS_CC); !map_done(&it); map_next(&it)) { | |
976 upb_status status; | |
977 | |
978 upb_sink entry_sink; | |
979 upb_sink_startsubmsg(&subsink, getsel(f, UPB_HANDLER_STARTSUBMSG), | |
980 &entry_sink); | |
981 upb_sink_startmsg(&entry_sink); | |
982 | |
983 // Serialize key. | |
984 const char *key = map_iter_key(&it, &len); | |
985 put_optional_value(key, len, key_field, depth + 1, &entry_sink TSRMLS_CC); | |
986 | |
987 // Serialize value. | |
988 upb_value value = map_iter_value(&it, &len); | |
989 put_optional_value(raw_value(upb_value_memory(&value), value_field), | |
990 raw_value_len(upb_value_memory(&value), len, value_field)
, | |
991 value_field, depth + 1, &entry_sink TSRMLS_CC); | |
992 | |
993 upb_sink_endmsg(&entry_sink, &status); | |
994 upb_sink_endsubmsg(&subsink, getsel(f, UPB_HANDLER_ENDSUBMSG)); | |
995 } | |
996 | |
997 upb_sink_endseq(sink, getsel(f, UPB_HANDLER_ENDSEQ)); | |
998 } | |
999 | |
1000 static void putmsg(zval* msg_php, const Descriptor* desc, upb_sink* sink, | |
1001 int depth TSRMLS_DC) { | |
1002 upb_msg_field_iter i; | |
1003 upb_status status; | |
1004 | |
1005 upb_sink_startmsg(sink); | |
1006 | |
1007 // Protect against cycles (possible because users may freely reassign message | |
1008 // and repeated fields) by imposing a maximum recursion depth. | |
1009 if (depth > ENCODE_MAX_NESTING) { | |
1010 zend_error(E_ERROR, | |
1011 "Maximum recursion depth exceeded during encoding."); | |
1012 } | |
1013 | |
1014 MessageHeader* msg = zend_object_store_get_object(msg_php TSRMLS_CC); | |
1015 | |
1016 for (upb_msg_field_begin(&i, desc->msgdef); !upb_msg_field_done(&i); | |
1017 upb_msg_field_next(&i)) { | |
1018 upb_fielddef* f = upb_msg_iter_field(&i); | |
1019 uint32_t offset = desc->layout->fields[upb_fielddef_index(f)].offset + | |
1020 sizeof(MessageHeader); | |
1021 | |
1022 if (upb_fielddef_containingoneof(f)) { | |
1023 uint32_t oneof_case_offset = | |
1024 desc->layout->fields[upb_fielddef_index(f)].case_offset + | |
1025 sizeof(MessageHeader); | |
1026 // For a oneof, check that this field is actually present -- skip all the | |
1027 // below if not. | |
1028 if (DEREF(msg, oneof_case_offset, uint32_t) != upb_fielddef_number(f)) { | |
1029 continue; | |
1030 } | |
1031 // Otherwise, fall through to the appropriate singular-field handler | |
1032 // below. | |
1033 } | |
1034 | |
1035 if (is_map_field(f)) { | |
1036 zval* map = *DEREF(msg, offset, zval**); | |
1037 if (map != NULL) { | |
1038 putmap(map, f, sink, depth TSRMLS_CC); | |
1039 } | |
1040 } else if (upb_fielddef_isseq(f)) { | |
1041 zval* array = *DEREF(msg, offset, zval**); | |
1042 if (array != NULL) { | |
1043 putarray(array, f, sink, depth TSRMLS_CC); | |
1044 } | |
1045 } else if (upb_fielddef_isstring(f)) { | |
1046 zval* str = *DEREF(msg, offset, zval**); | |
1047 if (Z_STRLEN_P(str) > 0) { | |
1048 putstr(str, f, sink); | |
1049 } | |
1050 } else if (upb_fielddef_issubmsg(f)) { | |
1051 putsubmsg(*DEREF(msg, offset, zval**), f, sink, depth TSRMLS_CC); | |
1052 } else { | |
1053 upb_selector_t sel = getsel(f, upb_handlers_getprimitivehandlertype(f)); | |
1054 | |
1055 #define T(upbtypeconst, upbtype, ctype, default_value) \ | |
1056 case upbtypeconst: { \ | |
1057 ctype value = DEREF(msg, offset, ctype); \ | |
1058 if (value != default_value) { \ | |
1059 upb_sink_put##upbtype(sink, sel, value); \ | |
1060 } \ | |
1061 } break; | |
1062 | |
1063 switch (upb_fielddef_type(f)) { | |
1064 T(UPB_TYPE_FLOAT, float, float, 0.0) | |
1065 T(UPB_TYPE_DOUBLE, double, double, 0.0) | |
1066 T(UPB_TYPE_BOOL, bool, uint8_t, 0) | |
1067 case UPB_TYPE_ENUM: | |
1068 T(UPB_TYPE_INT32, int32, int32_t, 0) | |
1069 T(UPB_TYPE_UINT32, uint32, uint32_t, 0) | |
1070 T(UPB_TYPE_INT64, int64, int64_t, 0) | |
1071 T(UPB_TYPE_UINT64, uint64, uint64_t, 0) | |
1072 | |
1073 case UPB_TYPE_STRING: | |
1074 case UPB_TYPE_BYTES: | |
1075 case UPB_TYPE_MESSAGE: | |
1076 zend_error(E_ERROR, "Internal error."); | |
1077 } | |
1078 | |
1079 #undef T | |
1080 } | |
1081 } | |
1082 | |
1083 upb_sink_endmsg(sink, &status); | |
1084 } | |
1085 | |
1086 static void putstr(zval* str, const upb_fielddef *f, upb_sink *sink) { | |
1087 upb_sink subsink; | |
1088 | |
1089 if (ZVAL_IS_NULL(str)) return; | |
1090 | |
1091 assert(Z_TYPE_P(str) == IS_STRING); | |
1092 | |
1093 // Ensure that the string has the correct encoding. We also check at field-set | |
1094 // time, but the user may have mutated the string object since then. | |
1095 if (upb_fielddef_type(f) == UPB_TYPE_STRING && | |
1096 !is_structurally_valid_utf8(Z_STRVAL_P(str), Z_STRLEN_P(str))) { | |
1097 zend_error(E_USER_ERROR, "Given string is not UTF8 encoded."); | |
1098 return; | |
1099 } | |
1100 | |
1101 upb_sink_startstr(sink, getsel(f, UPB_HANDLER_STARTSTR), Z_STRLEN_P(str), | |
1102 &subsink); | |
1103 upb_sink_putstring(&subsink, getsel(f, UPB_HANDLER_STRING), Z_STRVAL_P(str), | |
1104 Z_STRLEN_P(str), NULL); | |
1105 upb_sink_endstr(sink, getsel(f, UPB_HANDLER_ENDSTR)); | |
1106 } | |
1107 | |
1108 static void putrawstr(const char* str, int len, const upb_fielddef* f, | |
1109 upb_sink* sink) { | |
1110 upb_sink subsink; | |
1111 | |
1112 if (len == 0) return; | |
1113 | |
1114 // Ensure that the string has the correct encoding. We also check at field-set | |
1115 // time, but the user may have mutated the string object since then. | |
1116 if (upb_fielddef_type(f) == UPB_TYPE_STRING && | |
1117 !is_structurally_valid_utf8(str, len)) { | |
1118 zend_error(E_USER_ERROR, "Given string is not UTF8 encoded."); | |
1119 return; | |
1120 } | |
1121 | |
1122 upb_sink_startstr(sink, getsel(f, UPB_HANDLER_STARTSTR), len, &subsink); | |
1123 upb_sink_putstring(&subsink, getsel(f, UPB_HANDLER_STRING), str, len, NULL); | |
1124 upb_sink_endstr(sink, getsel(f, UPB_HANDLER_ENDSTR)); | |
1125 } | |
1126 | |
1127 static void putsubmsg(zval* submsg, const upb_fielddef* f, upb_sink* sink, | |
1128 int depth TSRMLS_DC) { | |
1129 upb_sink subsink; | |
1130 | |
1131 if (Z_TYPE_P(submsg) == IS_NULL) return; | |
1132 | |
1133 zval* php_descriptor = get_def_obj(upb_fielddef_msgsubdef(f)); | |
1134 Descriptor* subdesc = | |
1135 (Descriptor*)zend_object_store_get_object(php_descriptor TSRMLS_CC); | |
1136 | |
1137 upb_sink_startsubmsg(sink, getsel(f, UPB_HANDLER_STARTSUBMSG), &subsink); | |
1138 putmsg(submsg, subdesc, &subsink, depth + 1 TSRMLS_CC); | |
1139 upb_sink_endsubmsg(sink, getsel(f, UPB_HANDLER_ENDSUBMSG)); | |
1140 } | |
1141 | |
1142 static void putarray(zval* array, const upb_fielddef* f, upb_sink* sink, | |
1143 int depth TSRMLS_DC) { | |
1144 upb_sink subsink; | |
1145 upb_fieldtype_t type = upb_fielddef_type(f); | |
1146 upb_selector_t sel = 0; | |
1147 int size, i; | |
1148 | |
1149 assert(array != NULL); | |
1150 RepeatedField* intern = | |
1151 (RepeatedField*)zend_object_store_get_object(array TSRMLS_CC); | |
1152 size = zend_hash_num_elements(HASH_OF(intern->array)); | |
1153 if (size == 0) return; | |
1154 | |
1155 upb_sink_startseq(sink, getsel(f, UPB_HANDLER_STARTSEQ), &subsink); | |
1156 | |
1157 if (upb_fielddef_isprimitive(f)) { | |
1158 sel = getsel(f, upb_handlers_getprimitivehandlertype(f)); | |
1159 } | |
1160 | |
1161 for (i = 0; i < size; i++) { | |
1162 void* memory = repeated_field_index_native(intern, i TSRMLS_CC); | |
1163 switch (type) { | |
1164 #define T(upbtypeconst, upbtype, ctype) \ | |
1165 case upbtypeconst: \ | |
1166 upb_sink_put##upbtype(&subsink, sel, *((ctype*)memory)); \ | |
1167 break; | |
1168 | |
1169 T(UPB_TYPE_FLOAT, float, float) | |
1170 T(UPB_TYPE_DOUBLE, double, double) | |
1171 T(UPB_TYPE_BOOL, bool, int8_t) | |
1172 case UPB_TYPE_ENUM: | |
1173 T(UPB_TYPE_INT32, int32, int32_t) | |
1174 T(UPB_TYPE_UINT32, uint32, uint32_t) | |
1175 T(UPB_TYPE_INT64, int64, int64_t) | |
1176 T(UPB_TYPE_UINT64, uint64, uint64_t) | |
1177 | |
1178 case UPB_TYPE_STRING: | |
1179 case UPB_TYPE_BYTES: | |
1180 putstr(*((zval**)memory), f, &subsink); | |
1181 break; | |
1182 case UPB_TYPE_MESSAGE: | |
1183 putsubmsg(*((zval**)memory), f, &subsink, depth TSRMLS_CC); | |
1184 break; | |
1185 | |
1186 #undef T | |
1187 } | |
1188 } | |
1189 upb_sink_endseq(sink, getsel(f, UPB_HANDLER_ENDSEQ)); | |
1190 } | |
1191 | |
1192 static const upb_handlers* msgdef_pb_serialize_handlers(Descriptor* desc) { | |
1193 if (desc->pb_serialize_handlers == NULL) { | |
1194 desc->pb_serialize_handlers = | |
1195 upb_pb_encoder_newhandlers(desc->msgdef, &desc->pb_serialize_handlers); | |
1196 } | |
1197 return desc->pb_serialize_handlers; | |
1198 } | |
1199 | |
1200 // ----------------------------------------------------------------------------- | |
1201 // PHP encode/decode methods | |
1202 // ----------------------------------------------------------------------------- | |
1203 | |
1204 PHP_METHOD(Message, encode) { | |
1205 zval* php_descriptor = get_ce_obj(Z_OBJCE_P(getThis())); | |
1206 Descriptor* desc = | |
1207 (Descriptor*)zend_object_store_get_object(php_descriptor TSRMLS_CC); | |
1208 | |
1209 stringsink sink; | |
1210 stringsink_init(&sink); | |
1211 | |
1212 { | |
1213 const upb_handlers* serialize_handlers = msgdef_pb_serialize_handlers(desc); | |
1214 | |
1215 stackenv se; | |
1216 upb_pb_encoder* encoder; | |
1217 | |
1218 stackenv_init(&se, "Error occurred during encoding: %s"); | |
1219 encoder = upb_pb_encoder_create(&se.env, serialize_handlers, &sink.sink); | |
1220 | |
1221 putmsg(getThis(), desc, upb_pb_encoder_input(encoder), 0 TSRMLS_CC); | |
1222 | |
1223 RETVAL_STRINGL(sink.ptr, sink.len, 1); | |
1224 | |
1225 stackenv_uninit(&se); | |
1226 stringsink_uninit(&sink); | |
1227 } | |
1228 } | |
1229 | |
1230 PHP_METHOD(Message, decode) { | |
1231 zval* php_descriptor = get_ce_obj(Z_OBJCE_P(getThis())); | |
1232 Descriptor* desc = | |
1233 (Descriptor*)zend_object_store_get_object(php_descriptor TSRMLS_CC); | |
1234 MessageHeader* msg = zend_object_store_get_object(getThis() TSRMLS_CC); | |
1235 | |
1236 char *data = NULL; | |
1237 int data_len; | |
1238 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &data, &data_len) == | |
1239 FAILURE) { | |
1240 return; | |
1241 } | |
1242 | |
1243 { | |
1244 const upb_pbdecodermethod* method = msgdef_decodermethod(desc); | |
1245 const upb_handlers* h = upb_pbdecodermethod_desthandlers(method); | |
1246 stackenv se; | |
1247 upb_sink sink; | |
1248 upb_pbdecoder* decoder; | |
1249 stackenv_init(&se, "Error occurred during parsing: %s"); | |
1250 | |
1251 upb_sink_reset(&sink, h, msg); | |
1252 decoder = upb_pbdecoder_create(&se.env, method, &sink); | |
1253 upb_bufsrc_putbuf(data, data_len, upb_pbdecoder_input(decoder)); | |
1254 | |
1255 stackenv_uninit(&se); | |
1256 } | |
1257 } | |
OLD | NEW |