protobuf.h 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489
  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. #ifndef __GOOGLE_PROTOBUF_PHP_PROTOBUF_H__
  31. #define __GOOGLE_PROTOBUF_PHP_PROTOBUF_H__
  32. #include <php.h>
  33. // ubp.h has to be placed after php.h. Othwise, php.h will introduce NDEBUG.
  34. #include "upb.h"
  35. #define PHP_PROTOBUF_EXTNAME "protobuf"
  36. #define PHP_PROTOBUF_VERSION "3.2.0a1"
  37. #define MAX_LENGTH_OF_INT64 20
  38. #define SIZEOF_INT64 8
  39. // -----------------------------------------------------------------------------
  40. // Forward Declaration
  41. // ----------------------------------------------------------------------------
  42. struct DescriptorPool;
  43. struct Descriptor;
  44. struct EnumDescriptor;
  45. struct FieldDescriptor;
  46. struct MessageField;
  47. struct MessageHeader;
  48. struct MessageLayout;
  49. struct RepeatedField;
  50. struct RepeatedFieldIter;
  51. struct MapField;
  52. typedef struct DescriptorPool DescriptorPool;
  53. typedef struct Descriptor Descriptor;
  54. typedef struct EnumDescriptor EnumDescriptor;
  55. typedef struct FieldDescriptor FieldDescriptor;
  56. typedef struct MessageField MessageField;
  57. typedef struct MessageHeader MessageHeader;
  58. typedef struct MessageLayout MessageLayout;
  59. typedef struct RepeatedField RepeatedField;
  60. typedef struct RepeatedFieldIter RepeatedFieldIter;
  61. typedef struct MapField MapField;
  62. // -----------------------------------------------------------------------------
  63. // Globals.
  64. // -----------------------------------------------------------------------------
  65. ZEND_BEGIN_MODULE_GLOBALS(protobuf)
  66. ZEND_END_MODULE_GLOBALS(protobuf)
  67. // Init module and PHP classes.
  68. void descriptor_init(TSRMLS_D);
  69. void enum_descriptor_init(TSRMLS_D);
  70. void descriptor_pool_init(TSRMLS_D);
  71. void gpb_type_init(TSRMLS_D);
  72. void map_field_init(TSRMLS_D);
  73. void repeated_field_init(TSRMLS_D);
  74. void repeated_field_iter_init(TSRMLS_D);
  75. void util_init(TSRMLS_D);
  76. void message_init(TSRMLS_D);
  77. // Global map from upb {msg,enum}defs to wrapper Descriptor/EnumDescriptor
  78. // instances.
  79. void add_def_obj(const void* def, zval* value);
  80. zval* get_def_obj(const void* def);
  81. // Global map from PHP class entries to wrapper Descriptor/EnumDescriptor
  82. // instances.
  83. void add_ce_obj(const void* ce, zval* value);
  84. zval* get_ce_obj(const void* ce);
  85. extern zend_class_entry* map_field_type;
  86. extern zend_class_entry* repeated_field_type;
  87. // -----------------------------------------------------------------------------
  88. // Descriptor.
  89. // -----------------------------------------------------------------------------
  90. struct DescriptorPool {
  91. zend_object std;
  92. upb_symtab* symtab;
  93. HashTable* pending_list;
  94. };
  95. PHP_METHOD(DescriptorPool, getGeneratedPool);
  96. PHP_METHOD(DescriptorPool, internalAddGeneratedFile);
  97. extern zval* generated_pool_php; // wrapper of generated pool
  98. extern DescriptorPool* generated_pool; // The actual generated pool
  99. struct Descriptor {
  100. zend_object std;
  101. const upb_msgdef* msgdef;
  102. MessageLayout* layout;
  103. zend_class_entry* klass; // begins as NULL
  104. const upb_handlers* fill_handlers;
  105. const upb_pbdecodermethod* fill_method;
  106. const upb_json_parsermethod* json_fill_method;
  107. const upb_handlers* pb_serialize_handlers;
  108. const upb_handlers* json_serialize_handlers;
  109. const upb_handlers* json_serialize_handlers_preserve;
  110. };
  111. extern zend_class_entry* descriptor_type;
  112. void descriptor_name_set(Descriptor *desc, const char *name);
  113. struct FieldDescriptor {
  114. zend_object std;
  115. const upb_fielddef* fielddef;
  116. };
  117. struct EnumDescriptor {
  118. zend_object std;
  119. const upb_enumdef* enumdef;
  120. zend_class_entry* klass; // begins as NULL
  121. // VALUE module; // begins as nil
  122. };
  123. extern zend_class_entry* enum_descriptor_type;
  124. // -----------------------------------------------------------------------------
  125. // Message class creation.
  126. // -----------------------------------------------------------------------------
  127. void* message_data(void* msg);
  128. void message_create_with_type(zend_class_entry* ce, zval** message TSRMLS_DC);
  129. // Build PHP class for given descriptor. Instead of building from scratch, this
  130. // function modifies existing class which has been partially defined in PHP
  131. // code.
  132. void build_class_from_descriptor(zval* php_descriptor TSRMLS_DC);
  133. extern zend_object_handlers* message_handlers;
  134. // -----------------------------------------------------------------------------
  135. // Message layout / storage.
  136. // -----------------------------------------------------------------------------
  137. /*
  138. * In c extension, each protobuf message is a zval instance. The zval instance
  139. * is like union, which can be used to store int, string, zend_object_value and
  140. * etc. For protobuf message, the zval instance is used to store the
  141. * zend_object_value.
  142. *
  143. * The zend_object_value is composed of handlers and a handle to look up the
  144. * actual stored data. The handlers are pointers to functions, e.g., read,
  145. * write, and etc, to access properties.
  146. *
  147. * The actual data of protobuf messages is stored as MessageHeader in zend
  148. * engine's central repository. Each MessageHeader instance is composed of a
  149. * zend_object, a Descriptor instance and the real message data.
  150. *
  151. * For the reason that PHP's native types may not be large enough to store
  152. * protobuf message's field (e.g., int64), all message's data is stored in
  153. * custom memory layout and is indexed by the Descriptor instance.
  154. *
  155. * The zend_object contains the zend class entry and the properties table. The
  156. * zend class entry contains all information about protobuf message's
  157. * corresponding PHP class. The most useful information is the offset table of
  158. * properties. Because read access to properties requires returning zval
  159. * instance, we need to convert data from the custom layout to zval instance.
  160. * Instead of creating zval instance for every read access, we use the zval
  161. * instances in the properties table in the zend_object as cache. When
  162. * accessing properties, the offset is needed to find the zval property in
  163. * zend_object's properties table. These properties will be updated using the
  164. * data from custom memory layout only when reading these properties.
  165. *
  166. * zval
  167. * |-zend_object_value obj
  168. * |-zend_object_handlers* handlers -> |-read_property_handler
  169. * | |-write_property_handler
  170. * | ++++++++++++++++++++++
  171. * |-zend_object_handle handle -> + central repository +
  172. * ++++++++++++++++++++++
  173. * MessageHeader <-----------------|
  174. * |-zend_object std
  175. * | |-class_entry* ce -> class_entry
  176. * | | |-HashTable properties_table (name->offset)
  177. * | |-zval** properties_table <------------------------------|
  178. * | |------> zval* property(cache)
  179. * |-Descriptor* desc (name->offset)
  180. * |-void** data <-----------|
  181. * |-----------------------> void* property(data)
  182. *
  183. */
  184. #define MESSAGE_FIELD_NO_CASE ((size_t)-1)
  185. struct MessageField {
  186. size_t offset;
  187. int cache_index; // Each field except oneof field has a zval cache to avoid
  188. // multiple creation when being accessed.
  189. size_t case_offset; // for oneofs, a uint32. Else, MESSAGE_FIELD_NO_CASE.
  190. };
  191. struct MessageLayout {
  192. const upb_msgdef* msgdef;
  193. MessageField* fields;
  194. size_t size;
  195. };
  196. struct MessageHeader {
  197. zend_object std; // Stores properties table and class info of PHP instance.
  198. // This is needed for MessageHeader to be accessed via PHP.
  199. Descriptor* descriptor; // Kept alive by self.class.descriptor reference.
  200. // The real message data is appended after MessageHeader.
  201. };
  202. MessageLayout* create_layout(const upb_msgdef* msgdef);
  203. void layout_init(MessageLayout* layout, void* storage,
  204. zval** properties_table TSRMLS_DC);
  205. zval* layout_get(MessageLayout* layout, const void* storage,
  206. const upb_fielddef* field, zval** cache TSRMLS_DC);
  207. void layout_set(MessageLayout* layout, MessageHeader* header,
  208. const upb_fielddef* field, zval* val TSRMLS_DC);
  209. void layout_merge(MessageLayout* layout, MessageHeader* from,
  210. MessageHeader* to TSRMLS_DC);
  211. const char* layout_get_oneof_case(MessageLayout* layout, const void* storage,
  212. const upb_oneofdef* oneof TSRMLS_DC);
  213. void free_layout(MessageLayout* layout);
  214. PHP_METHOD(Message, clear);
  215. PHP_METHOD(Message, mergeFrom);
  216. PHP_METHOD(Message, readOneof);
  217. PHP_METHOD(Message, writeOneof);
  218. PHP_METHOD(Message, whichOneof);
  219. PHP_METHOD(Message, __construct);
  220. // -----------------------------------------------------------------------------
  221. // Encode / Decode.
  222. // -----------------------------------------------------------------------------
  223. // Maximum depth allowed during encoding, to avoid stack overflows due to
  224. // cycles.
  225. #define ENCODE_MAX_NESTING 63
  226. // Constructs the upb decoder method for parsing messages of this type.
  227. // This is called from the message class creation code.
  228. const upb_pbdecodermethod *new_fillmsg_decodermethod(Descriptor *desc,
  229. const void *owner);
  230. PHP_METHOD(Message, serializeToString);
  231. PHP_METHOD(Message, mergeFromString);
  232. PHP_METHOD(Message, jsonEncode);
  233. PHP_METHOD(Message, jsonDecode);
  234. // -----------------------------------------------------------------------------
  235. // Type check / conversion.
  236. // -----------------------------------------------------------------------------
  237. bool protobuf_convert_to_int32(zval* from, int32_t* to);
  238. bool protobuf_convert_to_uint32(zval* from, uint32_t* to);
  239. bool protobuf_convert_to_int64(zval* from, int64_t* to);
  240. bool protobuf_convert_to_uint64(zval* from, uint64_t* to);
  241. bool protobuf_convert_to_float(zval* from, float* to);
  242. bool protobuf_convert_to_double(zval* from, double* to);
  243. bool protobuf_convert_to_bool(zval* from, int8_t* to);
  244. bool protobuf_convert_to_string(zval* from);
  245. PHP_METHOD(Util, checkInt32);
  246. PHP_METHOD(Util, checkUint32);
  247. PHP_METHOD(Util, checkInt64);
  248. PHP_METHOD(Util, checkUint64);
  249. PHP_METHOD(Util, checkEnum);
  250. PHP_METHOD(Util, checkFloat);
  251. PHP_METHOD(Util, checkDouble);
  252. PHP_METHOD(Util, checkBool);
  253. PHP_METHOD(Util, checkString);
  254. PHP_METHOD(Util, checkBytes);
  255. PHP_METHOD(Util, checkMessage);
  256. PHP_METHOD(Util, checkMapField);
  257. PHP_METHOD(Util, checkRepeatedField);
  258. // -----------------------------------------------------------------------------
  259. // Native slot storage abstraction.
  260. // -----------------------------------------------------------------------------
  261. #define NATIVE_SLOT_MAX_SIZE sizeof(uint64_t)
  262. size_t native_slot_size(upb_fieldtype_t type);
  263. bool native_slot_set(upb_fieldtype_t type, const zend_class_entry* klass,
  264. void* memory, zval* value TSRMLS_DC);
  265. void native_slot_init(upb_fieldtype_t type, void* memory, zval** cache);
  266. // For each property, in order to avoid conversion between the zval object and
  267. // the actual data type during parsing/serialization, the containing message
  268. // object use the custom memory layout to store the actual data type for each
  269. // property inside of it. To access a property from php code, the property
  270. // needs to be converted to a zval object. The message object is not responsible
  271. // for providing such a zval object. Instead the caller needs to provide one
  272. // (cache) and update it with the actual data (memory).
  273. void native_slot_get(upb_fieldtype_t type, const void* memory,
  274. zval** cache TSRMLS_DC);
  275. void native_slot_get_default(upb_fieldtype_t type, zval** cache TSRMLS_DC);
  276. // -----------------------------------------------------------------------------
  277. // Map Field.
  278. // -----------------------------------------------------------------------------
  279. extern zend_object_handlers* map_field_handlers;
  280. typedef struct {
  281. zend_object std;
  282. upb_fieldtype_t key_type;
  283. upb_fieldtype_t value_type;
  284. const zend_class_entry* msg_ce; // class entry for value message
  285. upb_strtable table;
  286. } Map;
  287. typedef struct {
  288. Map* self;
  289. upb_strtable_iter it;
  290. } MapIter;
  291. void map_begin(zval* self, MapIter* iter TSRMLS_DC);
  292. void map_next(MapIter* iter);
  293. bool map_done(MapIter* iter);
  294. const char* map_iter_key(MapIter* iter, int* len);
  295. upb_value map_iter_value(MapIter* iter, int* len);
  296. // These operate on a map-entry msgdef.
  297. const upb_fielddef* map_entry_key(const upb_msgdef* msgdef);
  298. const upb_fielddef* map_entry_value(const upb_msgdef* msgdef);
  299. zend_object_value map_field_create(zend_class_entry *ce TSRMLS_DC);
  300. void map_field_create_with_field(zend_class_entry *ce, const upb_fielddef *field,
  301. zval **map_field TSRMLS_DC);
  302. void map_field_create_with_type(zend_class_entry *ce, upb_fieldtype_t key_type,
  303. upb_fieldtype_t value_type,
  304. const zend_class_entry *msg_ce,
  305. zval **map_field TSRMLS_DC);
  306. void map_field_free(void* object TSRMLS_DC);
  307. void* upb_value_memory(upb_value* v);
  308. #define MAP_KEY_FIELD 1
  309. #define MAP_VALUE_FIELD 2
  310. // These operate on a map field (i.e., a repeated field of submessages whose
  311. // submessage type is a map-entry msgdef).
  312. bool is_map_field(const upb_fielddef* field);
  313. const upb_fielddef* map_field_key(const upb_fielddef* field);
  314. const upb_fielddef* map_field_value(const upb_fielddef* field);
  315. bool map_index_set(Map *intern, const char* keyval, int length, upb_value v);
  316. PHP_METHOD(MapField, __construct);
  317. PHP_METHOD(MapField, offsetExists);
  318. PHP_METHOD(MapField, offsetGet);
  319. PHP_METHOD(MapField, offsetSet);
  320. PHP_METHOD(MapField, offsetUnset);
  321. PHP_METHOD(MapField, count);
  322. // -----------------------------------------------------------------------------
  323. // Repeated Field.
  324. // -----------------------------------------------------------------------------
  325. extern zend_object_handlers* repeated_field_handlers;
  326. struct RepeatedField {
  327. zend_object std;
  328. zval* array;
  329. upb_fieldtype_t type;
  330. const zend_class_entry* msg_ce; // class entry for containing message
  331. // (for message field only).
  332. };
  333. struct RepeatedFieldIter {
  334. zend_object std;
  335. RepeatedField* repeated_field;
  336. long position;
  337. };
  338. void repeated_field_create_with_field(zend_class_entry* ce,
  339. const upb_fielddef* field,
  340. zval** repeated_field TSRMLS_DC);
  341. void repeated_field_create_with_type(zend_class_entry* ce, upb_fieldtype_t type,
  342. const zend_class_entry* msg_ce,
  343. zval** repeated_field TSRMLS_DC);
  344. // Return the element at the index position from the repeated field. There is
  345. // not restriction on the type of stored elements.
  346. void *repeated_field_index_native(RepeatedField *intern, int index TSRMLS_DC);
  347. // Add the element to the end of the repeated field. There is not restriction on
  348. // the type of stored elements.
  349. void repeated_field_push_native(RepeatedField *intern, void *value TSRMLS_DC);
  350. PHP_METHOD(RepeatedField, __construct);
  351. PHP_METHOD(RepeatedField, append);
  352. PHP_METHOD(RepeatedField, offsetExists);
  353. PHP_METHOD(RepeatedField, offsetGet);
  354. PHP_METHOD(RepeatedField, offsetSet);
  355. PHP_METHOD(RepeatedField, offsetUnset);
  356. PHP_METHOD(RepeatedField, count);
  357. PHP_METHOD(RepeatedField, getIterator);
  358. PHP_METHOD(RepeatedFieldIter, rewind);
  359. PHP_METHOD(RepeatedFieldIter, current);
  360. PHP_METHOD(RepeatedFieldIter, key);
  361. PHP_METHOD(RepeatedFieldIter, next);
  362. PHP_METHOD(RepeatedFieldIter, valid);
  363. // -----------------------------------------------------------------------------
  364. // Oneof Field.
  365. // -----------------------------------------------------------------------------
  366. typedef struct {
  367. zend_object std;
  368. upb_oneofdef* oneofdef;
  369. int index; // Index of field in oneof. -1 if not set.
  370. char value[NATIVE_SLOT_MAX_SIZE];
  371. } Oneof;
  372. // Oneof case slot value to indicate that no oneof case is set. The value `0` is
  373. // safe because field numbers are used as case identifiers, and no field can
  374. // have a number of 0.
  375. #define ONEOF_CASE_NONE 0
  376. // -----------------------------------------------------------------------------
  377. // Upb.
  378. // -----------------------------------------------------------------------------
  379. upb_fieldtype_t to_fieldtype(upb_descriptortype_t type);
  380. const zend_class_entry *field_type_class(const upb_fielddef *field TSRMLS_DC);
  381. // -----------------------------------------------------------------------------
  382. // Utilities.
  383. // -----------------------------------------------------------------------------
  384. // PHP <-> C conversion.
  385. #define UNBOX(class_name, val) \
  386. (class_name*)zend_object_store_get_object(val TSRMLS_CC);
  387. #define BOX(class_name, wrapper, intern, free_func) \
  388. MAKE_STD_ZVAL(wrapper); \
  389. Z_TYPE_P(wrapper) = IS_OBJECT; \
  390. Z_OBJVAL_P(wrapper) \
  391. .handle = \
  392. zend_objects_store_put(intern, NULL, free_func, NULL TSRMLS_CC); \
  393. Z_OBJVAL_P(wrapper).handlers = zend_get_std_object_handlers();
  394. // Memory management
  395. #define ALLOC(class_name) (class_name*) emalloc(sizeof(class_name))
  396. #define PEMALLOC(class_name) (class_name*) pemalloc(sizeof(class_name), 1)
  397. #define ALLOC_N(class_name, n) (class_name*) emalloc(sizeof(class_name) * n)
  398. #define FREE(object) efree(object)
  399. #define PEFREE(object) pefree(object, 1)
  400. // Create PHP internal instance.
  401. #define CREATE(class_name, intern, init_func) \
  402. intern = ALLOC(class_name); \
  403. memset(intern, 0, sizeof(class_name)); \
  404. init_func(intern TSRMLS_CC);
  405. // String argument.
  406. #define STR(str) (str), strlen(str)
  407. // Zend Value
  408. #define Z_OBJ_P(zval_p) \
  409. ((zend_object*)(EG(objects_store) \
  410. .object_buckets[Z_OBJ_HANDLE_P(zval_p)] \
  411. .bucket.obj.object))
  412. #endif // __GOOGLE_PROTOBUF_PHP_PROTOBUF_H__