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 "def.h"
32
33 #include <php.h>
34
35 // This is not self-contained: it must be after other Zend includes.
36 #include <Zend/zend_exceptions.h>
37
38 #include "names.h"
39 #include "php-upb.h"
40 #include "protobuf.h"
41
CheckUpbStatus(const upb_status * status,const char * msg)42 static void CheckUpbStatus(const upb_status* status, const char* msg) {
43 if (!upb_ok(status)) {
44 zend_error(E_ERROR, "%s: %s\n", msg, upb_status_errmsg(status));
45 }
46 }
47
48 static void FieldDescriptor_FromFieldDef(zval *val, const upb_fielddef *f);
49
50 // We use this for objects that should not be created directly from PHP.
CreateHandler_ReturnNull(zend_class_entry * class_type)51 static zend_object *CreateHandler_ReturnNull(zend_class_entry *class_type) {
52 return NULL; // Nobody should call this.
53 }
54
55 ZEND_BEGIN_ARG_INFO_EX(arginfo_getByIndex, 0, 0, 1)
56 ZEND_ARG_INFO(0, index)
57 ZEND_END_ARG_INFO()
58
59 // -----------------------------------------------------------------------------
60 // EnumValueDescriptor
61 // -----------------------------------------------------------------------------
62
63 typedef struct {
64 zend_object std;
65 const char *name;
66 int32_t number;
67 } EnumValueDescriptor;
68
69 zend_class_entry *EnumValueDescriptor_class_entry;
70 static zend_object_handlers EnumValueDescriptor_object_handlers;
71
72 /*
73 * EnumValueDescriptor_Make()
74 *
75 * Function to create an EnumValueDescriptor object from C.
76 */
EnumValueDescriptor_Make(zval * val,const char * name,int32_t number)77 static void EnumValueDescriptor_Make(zval *val, const char *name,
78 int32_t number) {
79 EnumValueDescriptor *intern = emalloc(sizeof(EnumValueDescriptor));
80 zend_object_std_init(&intern->std, EnumValueDescriptor_class_entry);
81 intern->std.handlers = &EnumValueDescriptor_object_handlers;
82 intern->name = name;
83 intern->number = number;
84 // Skip object_properties_init(), we don't allow derived classes.
85 ZVAL_OBJ(val, &intern->std);
86 }
87
88 /*
89 * EnumValueDescriptor::getName()
90 *
91 * Returns the name for this enum value.
92 */
PHP_METHOD(EnumValueDescriptor,getName)93 PHP_METHOD(EnumValueDescriptor, getName) {
94 EnumValueDescriptor *intern = (EnumValueDescriptor*)Z_OBJ_P(getThis());
95 RETURN_STRING(intern->name);
96 }
97
98 /*
99 * EnumValueDescriptor::getNumber()
100 *
101 * Returns the number for this enum value.
102 */
PHP_METHOD(EnumValueDescriptor,getNumber)103 PHP_METHOD(EnumValueDescriptor, getNumber) {
104 EnumValueDescriptor *intern = (EnumValueDescriptor*)Z_OBJ_P(getThis());
105 RETURN_LONG(intern->number);
106 }
107
108 static zend_function_entry EnumValueDescriptor_methods[] = {
109 PHP_ME(EnumValueDescriptor, getName, arginfo_void, ZEND_ACC_PUBLIC)
110 PHP_ME(EnumValueDescriptor, getNumber, arginfo_void, ZEND_ACC_PUBLIC)
111 ZEND_FE_END
112 };
113
114 // -----------------------------------------------------------------------------
115 // EnumDescriptor
116 // -----------------------------------------------------------------------------
117
118 typedef struct {
119 zend_object std;
120 const upb_enumdef *enumdef;
121 void *cache_key;
122 } EnumDescriptor;
123
124 zend_class_entry *EnumDescriptor_class_entry;
125 static zend_object_handlers EnumDescriptor_object_handlers;
126
EnumDescriptor_destructor(zend_object * obj)127 static void EnumDescriptor_destructor(zend_object* obj) {
128 EnumDescriptor *intern = (EnumDescriptor*)obj;
129 ObjCache_Delete(intern->cache_key);
130 }
131
132 // Caller owns a ref on the returned zval.
EnumDescriptor_FromClassEntry(zval * val,zend_class_entry * ce)133 static void EnumDescriptor_FromClassEntry(zval *val, zend_class_entry *ce) {
134 // To differentiate enums from classes, we pointer-tag the class entry.
135 void* key = (void*)((uintptr_t)ce | 1);
136 PBPHP_ASSERT(key != ce);
137
138 if (ce == NULL) {
139 ZVAL_NULL(val);
140 return;
141 }
142
143 if (!ObjCache_Get(key, val)) {
144 const upb_enumdef *e = NameMap_GetEnum(ce);
145 if (!e) {
146 ZVAL_NULL(val);
147 return;
148 }
149 EnumDescriptor* ret = emalloc(sizeof(EnumDescriptor));
150 zend_object_std_init(&ret->std, EnumDescriptor_class_entry);
151 ret->std.handlers = &EnumDescriptor_object_handlers;
152 ret->enumdef = e;
153 ret->cache_key = key;
154 ObjCache_Add(key, &ret->std);
155 ZVAL_OBJ(val, &ret->std);
156 }
157 }
158
159 // Caller owns a ref on the returned zval.
EnumDescriptor_FromEnumDef(zval * val,const upb_enumdef * m)160 static void EnumDescriptor_FromEnumDef(zval *val, const upb_enumdef *m) {
161 if (!m) {
162 ZVAL_NULL(val);
163 } else {
164 char *classname =
165 GetPhpClassname(upb_enumdef_file(m), upb_enumdef_fullname(m));
166 zend_string *str = zend_string_init(classname, strlen(classname), 0);
167 zend_class_entry *ce = zend_lookup_class(str); // May autoload the class.
168
169 zend_string_release (str);
170
171 if (!ce) {
172 zend_error(E_ERROR, "Couldn't load generated class %s", classname);
173 }
174
175 free(classname);
176 EnumDescriptor_FromClassEntry(val, ce);
177 }
178 }
179
180 /*
181 * EnumDescriptor::getValue()
182 *
183 * Returns an EnumValueDescriptor for this index. Note: we are not looking
184 * up by numeric enum value, but by the index in the list of enum values.
185 */
PHP_METHOD(EnumDescriptor,getValue)186 PHP_METHOD(EnumDescriptor, getValue) {
187 EnumDescriptor *intern = (EnumDescriptor*)Z_OBJ_P(getThis());
188 zend_long index;
189 zval ret;
190
191 if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &index) == FAILURE) {
192 zend_error(E_USER_ERROR, "Expect integer for index.\n");
193 return;
194 }
195
196 int field_num = upb_enumdef_numvals(intern->enumdef);
197 if (index < 0 || index >= field_num) {
198 zend_error(E_USER_ERROR, "Cannot get element at %ld.\n", index);
199 return;
200 }
201
202 upb_enum_iter iter;
203 int i;
204 for(upb_enum_begin(&iter, intern->enumdef), i = 0;
205 !upb_enum_done(&iter) && i < index;
206 upb_enum_next(&iter), i++);
207
208 EnumValueDescriptor_Make(&ret, upb_enum_iter_name(&iter),
209 upb_enum_iter_number(&iter));
210 RETURN_COPY_VALUE(&ret);
211 }
212
213 /*
214 * EnumDescriptor::getValueCount()
215 *
216 * Returns the number of values in this enum.
217 */
PHP_METHOD(EnumDescriptor,getValueCount)218 PHP_METHOD(EnumDescriptor, getValueCount) {
219 EnumDescriptor *intern = (EnumDescriptor*)Z_OBJ_P(getThis());
220 RETURN_LONG(upb_enumdef_numvals(intern->enumdef));
221 }
222
223 /*
224 * EnumDescriptor::getPublicDescriptor()
225 *
226 * Returns this EnumDescriptor. Unlike the pure-PHP descriptor, we do not
227 * have two separate EnumDescriptor classes. We use a single class for both
228 * the public and private descriptor.
229 */
PHP_METHOD(EnumDescriptor,getPublicDescriptor)230 PHP_METHOD(EnumDescriptor, getPublicDescriptor) {
231 RETURN_COPY(getThis());
232 }
233
234 static zend_function_entry EnumDescriptor_methods[] = {
235 PHP_ME(EnumDescriptor, getPublicDescriptor, arginfo_void, ZEND_ACC_PUBLIC)
236 PHP_ME(EnumDescriptor, getValueCount, arginfo_void, ZEND_ACC_PUBLIC)
237 PHP_ME(EnumDescriptor, getValue, arginfo_getByIndex, ZEND_ACC_PUBLIC)
238 ZEND_FE_END
239 };
240
241 // -----------------------------------------------------------------------------
242 // Oneof
243 // -----------------------------------------------------------------------------
244
245 typedef struct {
246 zend_object std;
247 const upb_oneofdef *oneofdef;
248 } OneofDescriptor;
249
250 zend_class_entry *OneofDescriptor_class_entry;
251 static zend_object_handlers OneofDescriptor_object_handlers;
252
OneofDescriptor_destructor(zend_object * obj)253 static void OneofDescriptor_destructor(zend_object* obj) {
254 OneofDescriptor *intern = (OneofDescriptor*)obj;
255 ObjCache_Delete(intern->oneofdef);
256 }
257
OneofDescriptor_FromOneofDef(zval * val,const upb_oneofdef * o)258 static void OneofDescriptor_FromOneofDef(zval *val, const upb_oneofdef *o) {
259 if (o == NULL) {
260 ZVAL_NULL(val);
261 return;
262 }
263
264 if (!ObjCache_Get(o, val)) {
265 OneofDescriptor* ret = emalloc(sizeof(OneofDescriptor));
266 zend_object_std_init(&ret->std, OneofDescriptor_class_entry);
267 ret->std.handlers = &OneofDescriptor_object_handlers;
268 ret->oneofdef = o;
269 ObjCache_Add(o, &ret->std);
270 ZVAL_OBJ(val, &ret->std);
271 }
272 }
273
274 /*
275 * OneofDescriptor::getName()
276 *
277 * Returns the name of this oneof.
278 */
PHP_METHOD(OneofDescriptor,getName)279 PHP_METHOD(OneofDescriptor, getName) {
280 OneofDescriptor *intern = (OneofDescriptor*)Z_OBJ_P(getThis());
281 RETURN_STRING(upb_oneofdef_name(intern->oneofdef));
282 }
283
284 /*
285 * OneofDescriptor::getField()
286 *
287 * Returns a field from this oneof. The given index must be in the range
288 * [0, getFieldCount() - 1].
289 */
PHP_METHOD(OneofDescriptor,getField)290 PHP_METHOD(OneofDescriptor, getField) {
291 OneofDescriptor *intern = (OneofDescriptor*)Z_OBJ_P(getThis());
292 zend_long index;
293 zval ret;
294
295 if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &index) == FAILURE) {
296 zend_error(E_USER_ERROR, "Expect integer for index.\n");
297 return;
298 }
299
300 int field_num = upb_oneofdef_numfields(intern->oneofdef);
301 if (index < 0 || index >= field_num) {
302 zend_error(E_USER_ERROR, "Cannot get element at %ld.\n", index);
303 return;
304 }
305
306 upb_oneof_iter iter;
307 int i;
308 for(upb_oneof_begin(&iter, intern->oneofdef), i = 0;
309 !upb_oneof_done(&iter) && i < index;
310 upb_oneof_next(&iter), i++);
311 const upb_fielddef *field = upb_oneof_iter_field(&iter);
312
313 FieldDescriptor_FromFieldDef(&ret, field);
314 RETURN_COPY_VALUE(&ret);
315 }
316
317 /*
318 * OneofDescriptor::getFieldCount()
319 *
320 * Returns the number of fields in this oneof.
321 */
PHP_METHOD(OneofDescriptor,getFieldCount)322 PHP_METHOD(OneofDescriptor, getFieldCount) {
323 OneofDescriptor *intern = (OneofDescriptor*)Z_OBJ_P(getThis());
324 RETURN_LONG(upb_oneofdef_numfields(intern->oneofdef));
325 }
326
327 static zend_function_entry OneofDescriptor_methods[] = {
328 PHP_ME(OneofDescriptor, getName, arginfo_void, ZEND_ACC_PUBLIC)
329 PHP_ME(OneofDescriptor, getField, arginfo_getByIndex, ZEND_ACC_PUBLIC)
330 PHP_ME(OneofDescriptor, getFieldCount, arginfo_void, ZEND_ACC_PUBLIC)
331 ZEND_FE_END
332 };
333
334 // -----------------------------------------------------------------------------
335 // FieldDescriptor
336 // -----------------------------------------------------------------------------
337
338 typedef struct {
339 zend_object std;
340 const upb_fielddef *fielddef;
341 } FieldDescriptor;
342
343 zend_class_entry *FieldDescriptor_class_entry;
344 static zend_object_handlers FieldDescriptor_object_handlers;
345
FieldDescriptor_destructor(zend_object * obj)346 static void FieldDescriptor_destructor(zend_object* obj) {
347 FieldDescriptor *intern = (FieldDescriptor*)obj;
348 ObjCache_Delete(intern->fielddef);
349 }
350
351 // Caller owns a ref on the returned zval.
FieldDescriptor_FromFieldDef(zval * val,const upb_fielddef * f)352 static void FieldDescriptor_FromFieldDef(zval *val, const upb_fielddef *f) {
353 if (f == NULL) {
354 ZVAL_NULL(val);
355 return;
356 }
357
358 if (!ObjCache_Get(f, val)) {
359 FieldDescriptor* ret = emalloc(sizeof(FieldDescriptor));
360 zend_object_std_init(&ret->std, FieldDescriptor_class_entry);
361 ret->std.handlers = &FieldDescriptor_object_handlers;
362 ret->fielddef = f;
363 ObjCache_Add(f, &ret->std);
364 ZVAL_OBJ(val, &ret->std);
365 }
366 }
367
to_fieldtype(upb_descriptortype_t type)368 upb_fieldtype_t to_fieldtype(upb_descriptortype_t type) {
369 switch (type) {
370 #define CASE(descriptor_type, type) \
371 case UPB_DESCRIPTOR_TYPE_##descriptor_type: \
372 return UPB_TYPE_##type;
373
374 CASE(FLOAT, FLOAT);
375 CASE(DOUBLE, DOUBLE);
376 CASE(BOOL, BOOL);
377 CASE(STRING, STRING);
378 CASE(BYTES, BYTES);
379 CASE(MESSAGE, MESSAGE);
380 CASE(GROUP, MESSAGE);
381 CASE(ENUM, ENUM);
382 CASE(INT32, INT32);
383 CASE(INT64, INT64);
384 CASE(UINT32, UINT32);
385 CASE(UINT64, UINT64);
386 CASE(SINT32, INT32);
387 CASE(SINT64, INT64);
388 CASE(FIXED32, UINT32);
389 CASE(FIXED64, UINT64);
390 CASE(SFIXED32, INT32);
391 CASE(SFIXED64, INT64);
392
393 #undef CONVERT
394
395 }
396
397 zend_error(E_ERROR, "Unknown field type.");
398 return 0;
399 }
400
401 /*
402 * FieldDescriptor::getName()
403 *
404 * Returns the name of this field.
405 */
PHP_METHOD(FieldDescriptor,getName)406 PHP_METHOD(FieldDescriptor, getName) {
407 FieldDescriptor *intern = (FieldDescriptor*)Z_OBJ_P(getThis());
408 RETURN_STRING(upb_fielddef_name(intern->fielddef));
409 }
410
411 /*
412 * FieldDescriptor::getNumber()
413 *
414 * Returns the number of this field.
415 */
PHP_METHOD(FieldDescriptor,getNumber)416 PHP_METHOD(FieldDescriptor, getNumber) {
417 FieldDescriptor *intern = (FieldDescriptor*)Z_OBJ_P(getThis());
418 RETURN_LONG(upb_fielddef_number(intern->fielddef));
419 }
420
421 /*
422 * FieldDescriptor::getLabel()
423 *
424 * Returns the label of this field as an integer.
425 */
PHP_METHOD(FieldDescriptor,getLabel)426 PHP_METHOD(FieldDescriptor, getLabel) {
427 FieldDescriptor *intern = (FieldDescriptor*)Z_OBJ_P(getThis());
428 RETURN_LONG(upb_fielddef_label(intern->fielddef));
429 }
430
431 /*
432 * FieldDescriptor::getType()
433 *
434 * Returns the type of this field as an integer.
435 */
PHP_METHOD(FieldDescriptor,getType)436 PHP_METHOD(FieldDescriptor, getType) {
437 FieldDescriptor *intern = (FieldDescriptor*)Z_OBJ_P(getThis());
438 RETURN_LONG(upb_fielddef_descriptortype(intern->fielddef));
439 }
440
441 /*
442 * FieldDescriptor::isMap()
443 *
444 * Returns true if this field is a map.
445 */
PHP_METHOD(FieldDescriptor,isMap)446 PHP_METHOD(FieldDescriptor, isMap) {
447 FieldDescriptor *intern = (FieldDescriptor*)Z_OBJ_P(getThis());
448 RETURN_BOOL(upb_fielddef_ismap(intern->fielddef));
449 }
450
451 /*
452 * FieldDescriptor::getEnumType()
453 *
454 * Returns the EnumDescriptor for this field, which must be an enum.
455 */
PHP_METHOD(FieldDescriptor,getEnumType)456 PHP_METHOD(FieldDescriptor, getEnumType) {
457 FieldDescriptor *intern = (FieldDescriptor*)Z_OBJ_P(getThis());
458 const upb_enumdef *e = upb_fielddef_enumsubdef(intern->fielddef);
459 zval ret;
460
461 if (!e) {
462 zend_throw_exception_ex(NULL, 0,
463 "Cannot get enum type for non-enum field '%s'",
464 upb_fielddef_name(intern->fielddef));
465 return;
466 }
467
468 EnumDescriptor_FromEnumDef(&ret, e);
469 RETURN_COPY_VALUE(&ret);
470 }
471
472 /*
473 * FieldDescriptor::getMessageType()
474 *
475 * Returns the Descriptor for this field, which must be a message.
476 */
PHP_METHOD(FieldDescriptor,getMessageType)477 PHP_METHOD(FieldDescriptor, getMessageType) {
478 FieldDescriptor *intern = (FieldDescriptor*)Z_OBJ_P(getThis());
479 Descriptor* desc = Descriptor_GetFromFieldDef(intern->fielddef);
480
481 if (!desc) {
482 zend_throw_exception_ex(
483 NULL, 0, "Cannot get message type for non-message field '%s'",
484 upb_fielddef_name(intern->fielddef));
485 return;
486 }
487
488 RETURN_OBJ_COPY(&desc->std);
489 }
490
491 static zend_function_entry FieldDescriptor_methods[] = {
492 PHP_ME(FieldDescriptor, getName, arginfo_void, ZEND_ACC_PUBLIC)
493 PHP_ME(FieldDescriptor, getNumber, arginfo_void, ZEND_ACC_PUBLIC)
494 PHP_ME(FieldDescriptor, getLabel, arginfo_void, ZEND_ACC_PUBLIC)
495 PHP_ME(FieldDescriptor, getType, arginfo_void, ZEND_ACC_PUBLIC)
496 PHP_ME(FieldDescriptor, isMap, arginfo_void, ZEND_ACC_PUBLIC)
497 PHP_ME(FieldDescriptor, getEnumType, arginfo_void, ZEND_ACC_PUBLIC)
498 PHP_ME(FieldDescriptor, getMessageType, arginfo_void, ZEND_ACC_PUBLIC)
499 ZEND_FE_END
500 };
501
502 // -----------------------------------------------------------------------------
503 // Descriptor
504 // -----------------------------------------------------------------------------
505
506 zend_class_entry *Descriptor_class_entry;
507 static zend_object_handlers Descriptor_object_handlers;
508
Descriptor_destructor(zend_object * obj)509 static void Descriptor_destructor(zend_object* obj) {
510 // We don't really need to do anything here, we don't allow this to be
511 // collected before the end of the request.
512 }
513
Descriptor_GetGeneratedClass(const upb_msgdef * m)514 static zend_class_entry *Descriptor_GetGeneratedClass(const upb_msgdef *m) {
515 char *classname =
516 GetPhpClassname(upb_msgdef_file(m), upb_msgdef_fullname(m));
517 zend_string *str = zend_string_init(classname, strlen(classname), 0);
518 zend_class_entry *ce = zend_lookup_class(str); // May autoload the class.
519
520 zend_string_release (str);
521
522 if (!ce) {
523 zend_error(E_ERROR, "Couldn't load generated class %s", classname);
524 }
525
526 free(classname);
527 return ce;
528 }
529
Descriptor_FromMessageDef(zval * val,const upb_msgdef * m)530 void Descriptor_FromMessageDef(zval *val, const upb_msgdef *m) {
531 if (m == NULL) {
532 ZVAL_NULL(val);
533 return;
534 }
535
536 if (!ObjCache_Get(m, val)) {
537 zend_class_entry *ce = NULL;
538 if (!upb_msgdef_mapentry(m)) { // Map entries don't have a class.
539 ce = Descriptor_GetGeneratedClass(m);
540 if (!ce) {
541 ZVAL_NULL(val);
542 return;
543 }
544 }
545 Descriptor* ret = emalloc(sizeof(Descriptor));
546 zend_object_std_init(&ret->std, Descriptor_class_entry);
547 ret->std.handlers = &Descriptor_object_handlers;
548 ret->class_entry = ce;
549 ret->msgdef = m;
550 ObjCache_Add(m, &ret->std);
551 Descriptors_Add(&ret->std);
552 ZVAL_OBJ(val, &ret->std);
553 }
554 }
555
Descriptor_FromClassEntry(zval * val,zend_class_entry * ce)556 static void Descriptor_FromClassEntry(zval *val, zend_class_entry *ce) {
557 if (ce) {
558 Descriptor_FromMessageDef(val, NameMap_GetMessage(ce));
559 } else {
560 ZVAL_NULL(val);
561 }
562 }
563
Descriptor_GetFromZval(zval * val)564 static Descriptor* Descriptor_GetFromZval(zval *val) {
565 if (Z_TYPE_P(val) == IS_NULL) {
566 return NULL;
567 } else {
568 zend_object* ret = Z_OBJ_P(val);
569 zval_ptr_dtor(val);
570 return (Descriptor*)ret;
571 }
572 }
573
574 // C Functions from def.h //////////////////////////////////////////////////////
575
576 // These are documented in the header file.
577
Descriptor_GetFromClassEntry(zend_class_entry * ce)578 Descriptor* Descriptor_GetFromClassEntry(zend_class_entry *ce) {
579 zval desc;
580 Descriptor_FromClassEntry(&desc, ce);
581 return Descriptor_GetFromZval(&desc);
582 }
583
Descriptor_GetFromMessageDef(const upb_msgdef * m)584 Descriptor* Descriptor_GetFromMessageDef(const upb_msgdef *m) {
585 zval desc;
586 Descriptor_FromMessageDef(&desc, m);
587 return Descriptor_GetFromZval(&desc);
588 }
589
Descriptor_GetFromFieldDef(const upb_fielddef * f)590 Descriptor* Descriptor_GetFromFieldDef(const upb_fielddef *f) {
591 return Descriptor_GetFromMessageDef(upb_fielddef_msgsubdef(f));
592 }
593
594 /*
595 * Descriptor::getPublicDescriptor()
596 *
597 * Returns this EnumDescriptor. Unlike the pure-PHP descriptor, we do not
598 * have two separate EnumDescriptor classes. We use a single class for both
599 * the public and private descriptor.
600 */
PHP_METHOD(Descriptor,getPublicDescriptor)601 PHP_METHOD(Descriptor, getPublicDescriptor) {
602 RETURN_COPY(getThis());
603 }
604
605 /*
606 * Descriptor::getFullName()
607 *
608 * Returns the full name for this message type.
609 */
PHP_METHOD(Descriptor,getFullName)610 PHP_METHOD(Descriptor, getFullName) {
611 Descriptor *intern = (Descriptor*)Z_OBJ_P(getThis());
612 RETURN_STRING(upb_msgdef_fullname(intern->msgdef));
613 }
614
615 /*
616 * Descriptor::getField()
617 *
618 * Returns a FieldDescriptor for the given index, which must be in the range
619 * [0, getFieldCount()-1].
620 */
PHP_METHOD(Descriptor,getField)621 PHP_METHOD(Descriptor, getField) {
622 Descriptor *intern = (Descriptor*)Z_OBJ_P(getThis());
623 int count = upb_msgdef_numfields(intern->msgdef);
624 zval ret;
625 zend_long index;
626
627 if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &index) == FAILURE) {
628 zend_error(E_USER_ERROR, "Expect integer for index.\n");
629 return;
630 }
631
632 if (index < 0 || index >= count) {
633 zend_error(E_USER_ERROR, "Cannot get element at %ld.\n", index);
634 return;
635 }
636
637 FieldDescriptor_FromFieldDef(&ret, upb_msgdef_field(intern->msgdef, index));
638 RETURN_COPY_VALUE(&ret);
639 }
640
641 /*
642 * Descriptor::getFieldCount()
643 *
644 * Returns the number of fields in this message.
645 */
PHP_METHOD(Descriptor,getFieldCount)646 PHP_METHOD(Descriptor, getFieldCount) {
647 Descriptor *intern = (Descriptor*)Z_OBJ_P(getThis());
648 RETURN_LONG(upb_msgdef_numfields(intern->msgdef));
649 }
650
651 /*
652 * Descriptor::getOneofDecl()
653 *
654 * Returns a OneofDescriptor for the given index, which must be in the range
655 * [0, getOneofDeclCount()].
656 */
PHP_METHOD(Descriptor,getOneofDecl)657 PHP_METHOD(Descriptor, getOneofDecl) {
658 Descriptor *intern = (Descriptor*)Z_OBJ_P(getThis());
659 zend_long index;
660 zval ret;
661
662 if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &index) == FAILURE) {
663 zend_error(E_USER_ERROR, "Expect integer for index.\n");
664 return;
665 }
666
667 int field_num = upb_msgdef_numoneofs(intern->msgdef);
668 if (index < 0 || index >= field_num) {
669 zend_error(E_USER_ERROR, "Cannot get element at %ld.\n", index);
670 return;
671 }
672
673 upb_msg_oneof_iter iter;
674 int i;
675 for(upb_msg_oneof_begin(&iter, intern->msgdef), i = 0;
676 !upb_msg_oneof_done(&iter) && i < index;
677 upb_msg_oneof_next(&iter), i++);
678 const upb_oneofdef *oneof = upb_msg_iter_oneof(&iter);
679
680 OneofDescriptor_FromOneofDef(&ret, oneof);
681 RETURN_COPY_VALUE(&ret);
682 }
683
684 /*
685 * Descriptor::getOneofDeclCount()
686 *
687 * Returns the number of oneofs in this message.
688 */
PHP_METHOD(Descriptor,getOneofDeclCount)689 PHP_METHOD(Descriptor, getOneofDeclCount) {
690 Descriptor *intern = (Descriptor*)Z_OBJ_P(getThis());
691 RETURN_LONG(upb_msgdef_numoneofs(intern->msgdef));
692 }
693
694 /*
695 * Descriptor::getClass()
696 *
697 * Returns the name of the PHP class for this message.
698 */
PHP_METHOD(Descriptor,getClass)699 PHP_METHOD(Descriptor, getClass) {
700 Descriptor *intern = (Descriptor*)Z_OBJ_P(getThis());
701 const char* classname = ZSTR_VAL(intern->class_entry->name);
702 RETURN_STRING(classname);
703 }
704
705
706 static zend_function_entry Descriptor_methods[] = {
707 PHP_ME(Descriptor, getClass, arginfo_void, ZEND_ACC_PUBLIC)
708 PHP_ME(Descriptor, getFullName, arginfo_void, ZEND_ACC_PUBLIC)
709 PHP_ME(Descriptor, getField, arginfo_getByIndex, ZEND_ACC_PUBLIC)
710 PHP_ME(Descriptor, getFieldCount, arginfo_void, ZEND_ACC_PUBLIC)
711 PHP_ME(Descriptor, getOneofDecl, arginfo_getByIndex, ZEND_ACC_PUBLIC)
712 PHP_ME(Descriptor, getOneofDeclCount, arginfo_void, ZEND_ACC_PUBLIC)
713 PHP_ME(Descriptor, getPublicDescriptor, arginfo_void, ZEND_ACC_PUBLIC)
714 ZEND_FE_END
715 };
716
717 // -----------------------------------------------------------------------------
718 // DescriptorPool
719 // -----------------------------------------------------------------------------
720
721 typedef struct DescriptorPool {
722 zend_object std;
723 upb_symtab *symtab;
724 } DescriptorPool;
725
726 zend_class_entry *DescriptorPool_class_entry;
727 static zend_object_handlers DescriptorPool_object_handlers;
728
GetPool(const zval * this_ptr)729 static DescriptorPool *GetPool(const zval* this_ptr) {
730 return (DescriptorPool*)Z_OBJ_P(this_ptr);
731 }
732
733 /**
734 * Object handler to free an DescriptorPool.
735 */
DescriptorPool_destructor(zend_object * obj)736 static void DescriptorPool_destructor(zend_object* obj) {
737 DescriptorPool* intern = (DescriptorPool*)obj;
738
739 // We can't free our underlying symtab here, because user code may create
740 // messages from destructors that will refer to it. The symtab will be freed
741 // by our RSHUTDOWN() handler in protobuf.c
742
743 zend_object_std_dtor(&intern->std);
744 }
745
DescriptorPool_CreateWithSymbolTable(zval * zv,upb_symtab * symtab)746 void DescriptorPool_CreateWithSymbolTable(zval *zv, upb_symtab *symtab) {
747 DescriptorPool *intern = emalloc(sizeof(DescriptorPool));
748 zend_object_std_init(&intern->std, DescriptorPool_class_entry);
749 intern->std.handlers = &DescriptorPool_object_handlers;
750 intern->symtab = symtab;
751
752 ZVAL_OBJ(zv, &intern->std);
753 }
754
DescriptorPool_GetSymbolTable()755 upb_symtab *DescriptorPool_GetSymbolTable() {
756 DescriptorPool *intern = GetPool(get_generated_pool());
757 return intern->symtab;
758 }
759
760
761 /*
762 * DescriptorPool::getGeneratedPool()
763 *
764 * Returns the generated DescriptorPool.
765 */
PHP_METHOD(DescriptorPool,getGeneratedPool)766 PHP_METHOD(DescriptorPool, getGeneratedPool) {
767 zval ret;
768 ZVAL_COPY(&ret, get_generated_pool());
769 RETURN_COPY_VALUE(&ret);
770 }
771
772 /*
773 * DescriptorPool::getDescriptorByClassName()
774 *
775 * Returns a Descriptor object for the given PHP class name.
776 */
PHP_METHOD(DescriptorPool,getDescriptorByClassName)777 PHP_METHOD(DescriptorPool, getDescriptorByClassName) {
778 char *classname = NULL;
779 zend_long classname_len;
780 zend_class_entry *ce;
781 zend_string *str;
782 zval ret;
783
784 if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &classname, &classname_len) ==
785 FAILURE) {
786 return;
787 }
788
789 str = zend_string_init(classname, strlen(classname), 0);
790 ce = zend_lookup_class(str); // May autoload the class.
791 zend_string_release (str);
792
793 if (!ce) {
794 RETURN_NULL();
795 }
796
797 Descriptor_FromClassEntry(&ret, ce);
798 RETURN_COPY_VALUE(&ret);
799 }
800
801 /*
802 * DescriptorPool::getEnumDescriptorByClassName()
803 *
804 * Returns a EnumDescriptor object for the given PHP class name.
805 */
PHP_METHOD(DescriptorPool,getEnumDescriptorByClassName)806 PHP_METHOD(DescriptorPool, getEnumDescriptorByClassName) {
807 char *classname = NULL;
808 zend_long classname_len;
809 zend_class_entry *ce;
810 zend_string *str;
811 zval ret;
812
813 if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &classname, &classname_len) ==
814 FAILURE) {
815 return;
816 }
817
818 str = zend_string_init(classname, strlen(classname), 0);
819 ce = zend_lookup_class(str); // May autoload the class.
820 zend_string_release (str);
821
822 if (!ce) {
823 RETURN_NULL();
824 }
825
826 EnumDescriptor_FromClassEntry(&ret, ce);
827 RETURN_COPY_VALUE(&ret);
828 }
829
830 /*
831 * DescriptorPool::getEnumDescriptorByProtoName()
832 *
833 * Returns a Descriptor object for the given protobuf message name.
834 */
PHP_METHOD(DescriptorPool,getDescriptorByProtoName)835 PHP_METHOD(DescriptorPool, getDescriptorByProtoName) {
836 DescriptorPool *intern = GetPool(getThis());
837 char *protoname = NULL;
838 zend_long protoname_len;
839 const upb_msgdef *m;
840
841 if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &protoname, &protoname_len) ==
842 FAILURE) {
843 return;
844 }
845
846 if (*protoname == '.') protoname++;
847
848 m = upb_symtab_lookupmsg(intern->symtab, protoname);
849
850 if (m) {
851 RETURN_OBJ_COPY(&Descriptor_GetFromMessageDef(m)->std);
852 } else {
853 RETURN_NULL();
854 }
855 }
856
857 /*
858 * depends_on_descriptor()
859 *
860 * Returns true if this FileDescriptorProto depends on descriptor.proto.
861 */
depends_on_descriptor(const google_protobuf_FileDescriptorProto * file)862 bool depends_on_descriptor(const google_protobuf_FileDescriptorProto* file) {
863 const upb_strview *deps;
864 upb_strview name = upb_strview_makez("google/protobuf/descriptor.proto");
865 size_t i, n;
866
867 deps = google_protobuf_FileDescriptorProto_dependency(file, &n);
868 for (i = 0; i < n; i++) {
869 if (upb_strview_eql(deps[i], name)) {
870 return true;
871 }
872 }
873
874 return false;
875 }
876
877 /*
878 * add_name_mappings()
879 *
880 * Adds the messages and enums in this file to the NameMap.
881 */
add_name_mappings(const upb_filedef * file)882 static void add_name_mappings(const upb_filedef *file) {
883 size_t i;
884 for (i = 0; i < upb_filedef_msgcount(file); i++) {
885 NameMap_AddMessage(upb_filedef_msg(file, i));
886 }
887
888 for (i = 0; i < upb_filedef_enumcount(file); i++) {
889 NameMap_AddEnum(upb_filedef_enum(file, i));
890 }
891 }
892
add_descriptor(DescriptorPool * pool,const google_protobuf_FileDescriptorProto * file)893 static void add_descriptor(DescriptorPool *pool,
894 const google_protobuf_FileDescriptorProto *file) {
895 upb_strview name = google_protobuf_FileDescriptorProto_name(file);
896 upb_status status;
897 const upb_filedef *file_def;
898 upb_status_clear(&status);
899
900 if (upb_symtab_lookupfile2(pool->symtab, name.data, name.size)) {
901 // Already added.
902 // TODO(teboring): Re-enable this warning when aggregate metadata is
903 // deprecated.
904 // zend_error(E_USER_WARNING,
905 // "proto descriptor was previously loaded (included in multiple "
906 // "metadata bundles?): " UPB_STRVIEW_FORMAT,
907 // UPB_STRVIEW_ARGS(name));
908 return;
909 }
910
911 // The PHP code generator currently special-cases descriptor.proto. It
912 // doesn't add it as a dependency even if the proto file actually does
913 // depend on it.
914 if (depends_on_descriptor(file)) {
915 google_protobuf_FileDescriptorProto_getmsgdef(pool->symtab);
916 }
917
918 file_def = upb_symtab_addfile(pool->symtab, file, &status);
919 CheckUpbStatus(&status, "Unable to load descriptor");
920 add_name_mappings(file_def);
921 }
922
923 /*
924 * add_descriptor()
925 *
926 * Adds the given descriptor data to this DescriptorPool.
927 */
add_descriptor_set(DescriptorPool * pool,const char * data,int data_len,upb_arena * arena)928 static void add_descriptor_set(DescriptorPool *pool, const char *data,
929 int data_len, upb_arena *arena) {
930 size_t i, n;
931 google_protobuf_FileDescriptorSet *set;
932 const google_protobuf_FileDescriptorProto* const* files;
933
934 set = google_protobuf_FileDescriptorSet_parse(data, data_len, arena);
935
936 if (!set) {
937 zend_error(E_ERROR, "Failed to parse binary descriptor\n");
938 return;
939 }
940
941 files = google_protobuf_FileDescriptorSet_file(set, &n);
942
943 for (i = 0; i < n; i++) {
944 const google_protobuf_FileDescriptorProto* file = files[i];
945 add_descriptor(pool, file);
946 }
947 }
948
DescriptorPool_HasFile(const char * filename)949 bool DescriptorPool_HasFile(const char *filename) {
950 DescriptorPool *intern = GetPool(get_generated_pool());
951 return upb_symtab_lookupfile(intern->symtab, filename) != NULL;
952 }
953
DescriptorPool_AddDescriptor(const char * filename,const char * data,int size)954 void DescriptorPool_AddDescriptor(const char *filename, const char *data,
955 int size) {
956 upb_arena *arena = upb_arena_new();
957 const google_protobuf_FileDescriptorProto *file =
958 google_protobuf_FileDescriptorProto_parse(data, size, arena);
959
960 if (!file) {
961 zend_error(E_ERROR, "Failed to parse binary descriptor for %s\n", filename);
962 return;
963 }
964
965 add_descriptor(GetPool(get_generated_pool()), file);
966 upb_arena_free(arena);
967 }
968
969 /*
970 * DescriptorPool::internalAddGeneratedFile()
971 *
972 * Adds the given descriptor data to this DescriptorPool.
973 */
PHP_METHOD(DescriptorPool,internalAddGeneratedFile)974 PHP_METHOD(DescriptorPool, internalAddGeneratedFile) {
975 DescriptorPool *intern = GetPool(getThis());
976 char *data = NULL;
977 zend_long data_len;
978 zend_bool use_nested_submsg = false;
979 upb_arena *arena;
980
981 if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|b", &data, &data_len,
982 &use_nested_submsg) != SUCCESS) {
983 return;
984 }
985
986 arena = upb_arena_new();
987 add_descriptor_set(intern, data, data_len, arena);
988 upb_arena_free(arena);
989 }
990
991 ZEND_BEGIN_ARG_INFO_EX(arginfo_lookupByName, 0, 0, 1)
992 ZEND_ARG_INFO(0, name)
993 ZEND_END_ARG_INFO()
994
995 ZEND_BEGIN_ARG_INFO_EX(arginfo_addgeneratedfile, 0, 0, 2)
996 ZEND_ARG_INFO(0, data)
997 ZEND_ARG_INFO(0, data_len)
998 ZEND_END_ARG_INFO()
999
1000 static zend_function_entry DescriptorPool_methods[] = {
1001 PHP_ME(DescriptorPool, getGeneratedPool, arginfo_void,
1002 ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
1003 PHP_ME(DescriptorPool, getDescriptorByClassName, arginfo_lookupByName, ZEND_ACC_PUBLIC)
1004 PHP_ME(DescriptorPool, getDescriptorByProtoName, arginfo_lookupByName, ZEND_ACC_PUBLIC)
1005 PHP_ME(DescriptorPool, getEnumDescriptorByClassName, arginfo_lookupByName, ZEND_ACC_PUBLIC)
1006 PHP_ME(DescriptorPool, internalAddGeneratedFile, arginfo_addgeneratedfile, ZEND_ACC_PUBLIC)
1007 ZEND_FE_END
1008 };
1009
1010 // -----------------------------------------------------------------------------
1011 // InternalDescriptorPool
1012 // -----------------------------------------------------------------------------
1013
1014 // For the C extension, Google\Protobuf\Internal\DescriptorPool is not a
1015 // separate instantiable object, it just returns a
1016 // Google\Protobuf\DescriptorPool.
1017
1018 zend_class_entry *InternalDescriptorPool_class_entry;
1019
1020 /*
1021 * InternalDescriptorPool::getGeneratedPool()
1022 *
1023 * Returns the generated DescriptorPool. Note that this is identical to
1024 * DescriptorPool::getGeneratedPool(), and in fact returns a DescriptorPool
1025 * instance.
1026 */
PHP_METHOD(InternalDescriptorPool,getGeneratedPool)1027 PHP_METHOD(InternalDescriptorPool, getGeneratedPool) {
1028 RETURN_COPY(get_generated_pool());
1029 }
1030
1031 static zend_function_entry InternalDescriptorPool_methods[] = {
1032 PHP_ME(InternalDescriptorPool, getGeneratedPool, arginfo_void,
1033 ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
1034 ZEND_FE_END
1035 };
1036
1037 // -----------------------------------------------------------------------------
1038 // GPBType
1039 // -----------------------------------------------------------------------------
1040
1041 zend_class_entry* gpb_type_type;
1042
1043 static zend_function_entry gpb_type_methods[] = {
1044 ZEND_FE_END
1045 };
1046
1047 // -----------------------------------------------------------------------------
1048 // Module Init
1049 // -----------------------------------------------------------------------------
1050
Def_ModuleInit()1051 void Def_ModuleInit() {
1052 zend_class_entry tmp_ce;
1053 zend_object_handlers *h;
1054
1055 INIT_CLASS_ENTRY(tmp_ce, "Google\\Protobuf\\OneofDescriptor",
1056 OneofDescriptor_methods);
1057 OneofDescriptor_class_entry = zend_register_internal_class(&tmp_ce);
1058 OneofDescriptor_class_entry->ce_flags |= ZEND_ACC_FINAL;
1059 OneofDescriptor_class_entry->create_object = CreateHandler_ReturnNull;
1060 h = &OneofDescriptor_object_handlers;
1061 memcpy(h, &std_object_handlers, sizeof(zend_object_handlers));
1062 h->dtor_obj = &OneofDescriptor_destructor;
1063
1064 INIT_CLASS_ENTRY(tmp_ce, "Google\\Protobuf\\EnumValueDescriptor",
1065 EnumValueDescriptor_methods);
1066 EnumValueDescriptor_class_entry = zend_register_internal_class(&tmp_ce);
1067 EnumValueDescriptor_class_entry->ce_flags |= ZEND_ACC_FINAL;
1068 EnumValueDescriptor_class_entry->create_object = CreateHandler_ReturnNull;
1069 h = &EnumValueDescriptor_object_handlers;
1070 memcpy(h, &std_object_handlers, sizeof(zend_object_handlers));
1071
1072 INIT_CLASS_ENTRY(tmp_ce, "Google\\Protobuf\\EnumDescriptor",
1073 EnumDescriptor_methods);
1074 EnumDescriptor_class_entry = zend_register_internal_class(&tmp_ce);
1075 EnumDescriptor_class_entry->ce_flags |= ZEND_ACC_FINAL;
1076 EnumDescriptor_class_entry->create_object = CreateHandler_ReturnNull;
1077 h = &EnumDescriptor_object_handlers;
1078 memcpy(h, &std_object_handlers, sizeof(zend_object_handlers));
1079 h->dtor_obj = &EnumDescriptor_destructor;
1080
1081 INIT_CLASS_ENTRY(tmp_ce, "Google\\Protobuf\\Descriptor",
1082 Descriptor_methods);
1083
1084 Descriptor_class_entry = zend_register_internal_class(&tmp_ce);
1085 Descriptor_class_entry->ce_flags |= ZEND_ACC_FINAL;
1086 Descriptor_class_entry->create_object = CreateHandler_ReturnNull;
1087 h = &Descriptor_object_handlers;
1088 memcpy(h, &std_object_handlers, sizeof(zend_object_handlers));
1089 h->dtor_obj = Descriptor_destructor;
1090
1091 INIT_CLASS_ENTRY(tmp_ce, "Google\\Protobuf\\FieldDescriptor",
1092 FieldDescriptor_methods);
1093 FieldDescriptor_class_entry = zend_register_internal_class(&tmp_ce);
1094 FieldDescriptor_class_entry->ce_flags |= ZEND_ACC_FINAL;
1095 FieldDescriptor_class_entry->create_object = CreateHandler_ReturnNull;
1096 h = &FieldDescriptor_object_handlers;
1097 memcpy(h, &std_object_handlers, sizeof(zend_object_handlers));
1098 h->dtor_obj = &FieldDescriptor_destructor;
1099
1100 INIT_CLASS_ENTRY(tmp_ce, "Google\\Protobuf\\DescriptorPool",
1101 DescriptorPool_methods);
1102 DescriptorPool_class_entry = zend_register_internal_class(&tmp_ce);
1103 DescriptorPool_class_entry->ce_flags |= ZEND_ACC_FINAL;
1104 DescriptorPool_class_entry->create_object = CreateHandler_ReturnNull;
1105 h = &DescriptorPool_object_handlers;
1106 memcpy(h, &std_object_handlers, sizeof(zend_object_handlers));
1107 h->dtor_obj = DescriptorPool_destructor;
1108
1109 INIT_CLASS_ENTRY(tmp_ce, "Google\\Protobuf\\Internal\\DescriptorPool",
1110 InternalDescriptorPool_methods);
1111 InternalDescriptorPool_class_entry = zend_register_internal_class(&tmp_ce);
1112
1113 // GPBType.
1114 #define STR(str) (str), strlen(str)
1115 zend_class_entry class_type;
1116 INIT_CLASS_ENTRY(class_type, "Google\\Protobuf\\Internal\\GPBType",
1117 gpb_type_methods);
1118 gpb_type_type = zend_register_internal_class(&class_type);
1119 zend_declare_class_constant_long(gpb_type_type, STR("DOUBLE"), 1);
1120 zend_declare_class_constant_long(gpb_type_type, STR("FLOAT"), 2);
1121 zend_declare_class_constant_long(gpb_type_type, STR("INT64"), 3);
1122 zend_declare_class_constant_long(gpb_type_type, STR("UINT64"), 4);
1123 zend_declare_class_constant_long(gpb_type_type, STR("INT32"), 5);
1124 zend_declare_class_constant_long(gpb_type_type, STR("FIXED64"), 6);
1125 zend_declare_class_constant_long(gpb_type_type, STR("FIXED32"), 7);
1126 zend_declare_class_constant_long(gpb_type_type, STR("BOOL"), 8);
1127 zend_declare_class_constant_long(gpb_type_type, STR("STRING"), 9);
1128 zend_declare_class_constant_long(gpb_type_type, STR("GROUP"), 10);
1129 zend_declare_class_constant_long(gpb_type_type, STR("MESSAGE"), 11);
1130 zend_declare_class_constant_long(gpb_type_type, STR("BYTES"), 12);
1131 zend_declare_class_constant_long(gpb_type_type, STR("UINT32"), 13);
1132 zend_declare_class_constant_long(gpb_type_type, STR("ENUM"), 14);
1133 zend_declare_class_constant_long(gpb_type_type, STR("SFIXED32"), 15);
1134 zend_declare_class_constant_long(gpb_type_type, STR("SFIXED64"), 16);
1135 zend_declare_class_constant_long(gpb_type_type, STR("SINT32"), 17);
1136 zend_declare_class_constant_long(gpb_type_type, STR("SINT64"), 18);
1137 #undef STR
1138 }
1139