def.c 32 KB

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