def.c 34 KB

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