protobuf.h 18 KB

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