def.c 32 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081
  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, NULL, ZEND_ACC_PUBLIC)
  92. PHP_ME(EnumValueDescriptor, getNumber, NULL, 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, NULL, ZEND_ACC_PUBLIC)
  193. PHP_ME(EnumDescriptor, getValueCount, NULL, ZEND_ACC_PUBLIC)
  194. PHP_ME(EnumDescriptor, getValue, NULL, 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, NULL, ZEND_ACC_PUBLIC)
  270. PHP_ME(OneofDescriptor, getField, NULL, ZEND_ACC_PUBLIC)
  271. PHP_ME(OneofDescriptor, getFieldCount, NULL, 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, NULL, ZEND_ACC_PUBLIC)
  410. PHP_ME(FieldDescriptor, getNumber, NULL, ZEND_ACC_PUBLIC)
  411. PHP_ME(FieldDescriptor, getLabel, NULL, ZEND_ACC_PUBLIC)
  412. PHP_ME(FieldDescriptor, getType, NULL, ZEND_ACC_PUBLIC)
  413. PHP_ME(FieldDescriptor, isMap, NULL, ZEND_ACC_PUBLIC)
  414. PHP_ME(FieldDescriptor, getEnumType, NULL, ZEND_ACC_PUBLIC)
  415. PHP_ME(FieldDescriptor, getMessageType, NULL, 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, NULL, ZEND_ACC_PUBLIC)
  595. PHP_ME(Descriptor, getFullName, NULL, ZEND_ACC_PUBLIC)
  596. PHP_ME(Descriptor, getField, NULL, ZEND_ACC_PUBLIC)
  597. PHP_ME(Descriptor, getFieldCount, NULL, ZEND_ACC_PUBLIC)
  598. PHP_ME(Descriptor, getOneofDecl, NULL, ZEND_ACC_PUBLIC)
  599. PHP_ME(Descriptor, getOneofDeclCount, NULL, ZEND_ACC_PUBLIC)
  600. PHP_ME(Descriptor, getPublicDescriptor, NULL, 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. /*
  769. * add_name_mappings()
  770. *
  771. * Adds the given descriptor data to this DescriptorPool.
  772. */
  773. static void add_descriptor(DescriptorPool *pool, const char *data,
  774. int data_len, upb_arena *arena) {
  775. size_t i, n;
  776. google_protobuf_FileDescriptorSet *set;
  777. const google_protobuf_FileDescriptorProto* const* files;
  778. set = google_protobuf_FileDescriptorSet_parse(data, data_len, arena);
  779. if (!set) {
  780. zend_error(E_ERROR, "Failed to parse binary descriptor\n");
  781. return;
  782. }
  783. files = google_protobuf_FileDescriptorSet_file(set, &n);
  784. for (i = 0; i < n; i++) {
  785. const google_protobuf_FileDescriptorProto* file = files[i];
  786. upb_strview name = google_protobuf_FileDescriptorProto_name(file);
  787. upb_status status;
  788. const upb_filedef *file_def;
  789. upb_status_clear(&status);
  790. if (upb_symtab_lookupfile2(pool->symtab, name.data, name.size)) {
  791. // Already added.
  792. continue;
  793. }
  794. // The PHP code generator currently special-cases descriptor.proto. It
  795. // doesn't add it as a dependency even if the proto file actually does
  796. // depend on it.
  797. if (depends_on_descriptor(file)) {
  798. google_protobuf_FileDescriptorProto_getmsgdef(pool->symtab);
  799. }
  800. file_def = upb_symtab_addfile(pool->symtab, file, &status);
  801. CheckUpbStatus(&status, "Unable to load descriptor");
  802. add_name_mappings(file_def);
  803. }
  804. }
  805. /*
  806. * DescriptorPool::internalAddGeneratedFile()
  807. *
  808. * Adds the given descriptor data to this DescriptorPool.
  809. */
  810. PHP_METHOD(DescriptorPool, internalAddGeneratedFile) {
  811. DescriptorPool *intern = GetPool(getThis());
  812. char *data = NULL;
  813. zend_long data_len;
  814. zend_bool use_nested_submsg = false;
  815. upb_arena *arena;
  816. if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|b", &data, &data_len,
  817. &use_nested_submsg) != SUCCESS) {
  818. return;
  819. }
  820. arena = upb_arena_new();
  821. add_descriptor(intern, data, data_len, arena);
  822. upb_arena_free(arena);
  823. }
  824. static zend_function_entry DescriptorPool_methods[] = {
  825. PHP_ME(DescriptorPool, getGeneratedPool, NULL,
  826. ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
  827. PHP_ME(DescriptorPool, getDescriptorByClassName, NULL, ZEND_ACC_PUBLIC)
  828. PHP_ME(DescriptorPool, getDescriptorByProtoName, NULL, ZEND_ACC_PUBLIC)
  829. PHP_ME(DescriptorPool, getEnumDescriptorByClassName, NULL, ZEND_ACC_PUBLIC)
  830. PHP_ME(DescriptorPool, internalAddGeneratedFile, NULL, ZEND_ACC_PUBLIC)
  831. ZEND_FE_END
  832. };
  833. // -----------------------------------------------------------------------------
  834. // GPBType
  835. // -----------------------------------------------------------------------------
  836. zend_class_entry* gpb_type_type;
  837. static zend_function_entry gpb_type_methods[] = {
  838. ZEND_FE_END
  839. };
  840. // -----------------------------------------------------------------------------
  841. // Module Init
  842. // -----------------------------------------------------------------------------
  843. void Def_ModuleInit() {
  844. zend_class_entry tmp_ce;
  845. zend_object_handlers *h;
  846. INIT_CLASS_ENTRY(tmp_ce, "Google\\Protobuf\\OneofDescriptor",
  847. OneofDescriptor_methods);
  848. OneofDescriptor_class_entry = zend_register_internal_class(&tmp_ce);
  849. OneofDescriptor_class_entry->ce_flags |= ZEND_ACC_FINAL;
  850. OneofDescriptor_class_entry->create_object = CreateHandler_ReturnNull;
  851. h = &OneofDescriptor_object_handlers;
  852. memcpy(h, &std_object_handlers, sizeof(zend_object_handlers));
  853. INIT_CLASS_ENTRY(tmp_ce, "Google\\Protobuf\\EnumValueDescriptor",
  854. EnumValueDescriptor_methods);
  855. EnumValueDescriptor_class_entry = zend_register_internal_class(&tmp_ce);
  856. EnumValueDescriptor_class_entry->ce_flags |= ZEND_ACC_FINAL;
  857. EnumValueDescriptor_class_entry->create_object = CreateHandler_ReturnNull;
  858. h = &EnumValueDescriptor_object_handlers;
  859. memcpy(h, &std_object_handlers, sizeof(zend_object_handlers));
  860. INIT_CLASS_ENTRY(tmp_ce, "Google\\Protobuf\\EnumDescriptor",
  861. EnumDescriptor_methods);
  862. EnumDescriptor_class_entry = zend_register_internal_class(&tmp_ce);
  863. EnumDescriptor_class_entry->ce_flags |= ZEND_ACC_FINAL;
  864. EnumDescriptor_class_entry->create_object = CreateHandler_ReturnNull;
  865. h = &EnumDescriptor_object_handlers;
  866. memcpy(h, &std_object_handlers, sizeof(zend_object_handlers));
  867. INIT_CLASS_ENTRY(tmp_ce, "Google\\Protobuf\\Descriptor",
  868. Descriptor_methods);
  869. Descriptor_class_entry = zend_register_internal_class(&tmp_ce);
  870. Descriptor_class_entry->ce_flags |= ZEND_ACC_FINAL;
  871. Descriptor_class_entry->create_object = CreateHandler_ReturnNull;
  872. h = &Descriptor_object_handlers;
  873. memcpy(h, &std_object_handlers, sizeof(zend_object_handlers));
  874. h->dtor_obj = Descriptor_destructor;
  875. INIT_CLASS_ENTRY(tmp_ce, "Google\\Protobuf\\FieldDescriptor",
  876. FieldDescriptor_methods);
  877. FieldDescriptor_class_entry = zend_register_internal_class(&tmp_ce);
  878. FieldDescriptor_class_entry->ce_flags |= ZEND_ACC_FINAL;
  879. FieldDescriptor_class_entry->create_object = CreateHandler_ReturnNull;
  880. h = &FieldDescriptor_object_handlers;
  881. memcpy(h, &std_object_handlers, sizeof(zend_object_handlers));
  882. INIT_CLASS_ENTRY(tmp_ce, "Google\\Protobuf\\Internal\\DescriptorPool",
  883. DescriptorPool_methods);
  884. DescriptorPool_class_entry = zend_register_internal_class(&tmp_ce);
  885. DescriptorPool_class_entry->ce_flags |= ZEND_ACC_FINAL;
  886. DescriptorPool_class_entry->create_object = DescriptorPool_create;
  887. h = &DescriptorPool_object_handlers;
  888. memcpy(h, &std_object_handlers, sizeof(zend_object_handlers));
  889. h->dtor_obj = DescriptorPool_destructor;
  890. // GPBType.
  891. #define STR(str) (str), strlen(str)
  892. zend_class_entry class_type;
  893. INIT_CLASS_ENTRY(class_type, "Google\\Protobuf\\Internal\\GPBType",
  894. gpb_type_methods);
  895. gpb_type_type = zend_register_internal_class(&class_type);
  896. zend_declare_class_constant_long(gpb_type_type, STR("DOUBLE"), 1);
  897. zend_declare_class_constant_long(gpb_type_type, STR("FLOAT"), 2);
  898. zend_declare_class_constant_long(gpb_type_type, STR("INT64"), 3);
  899. zend_declare_class_constant_long(gpb_type_type, STR("UINT64"), 4);
  900. zend_declare_class_constant_long(gpb_type_type, STR("INT32"), 5);
  901. zend_declare_class_constant_long(gpb_type_type, STR("FIXED64"), 6);
  902. zend_declare_class_constant_long(gpb_type_type, STR("FIXED32"), 7);
  903. zend_declare_class_constant_long(gpb_type_type, STR("BOOL"), 8);
  904. zend_declare_class_constant_long(gpb_type_type, STR("STRING"), 9);
  905. zend_declare_class_constant_long(gpb_type_type, STR("GROUP"), 10);
  906. zend_declare_class_constant_long(gpb_type_type, STR("MESSAGE"), 11);
  907. zend_declare_class_constant_long(gpb_type_type, STR("BYTES"), 12);
  908. zend_declare_class_constant_long(gpb_type_type, STR("UINT32"), 13);
  909. zend_declare_class_constant_long(gpb_type_type, STR("ENUM"), 14);
  910. zend_declare_class_constant_long(gpb_type_type, STR("SFIXED32"), 15);
  911. zend_declare_class_constant_long(gpb_type_type, STR("SFIXED64"), 16);
  912. zend_declare_class_constant_long(gpb_type_type, STR("SINT32"), 17);
  913. zend_declare_class_constant_long(gpb_type_type, STR("SINT64"), 18);
  914. #undef STR
  915. }