protobuf.h 36 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912
  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.3.2"
  37. #define MAX_LENGTH_OF_INT64 20
  38. #define SIZEOF_INT64 8
  39. // -----------------------------------------------------------------------------
  40. // PHP7 Wrappers
  41. // ----------------------------------------------------------------------------
  42. #if PHP_MAJOR_VERSION < 7
  43. #define php_proto_zend_literal const zend_literal*
  44. #define PHP_PROTO_CASE_IS_BOOL IS_BOOL
  45. #define PHP_PROTO_SIZE int
  46. #define PHP_PROTO_LONG long
  47. #define PHP_PROTO_TSRMLS_DC TSRMLS_DC
  48. #define PHP_PROTO_TSRMLS_CC TSRMLS_CC
  49. // PHP String
  50. #define PHP_PROTO_ZVAL_STRING(zval_ptr, s, copy) \
  51. ZVAL_STRING(zval_ptr, s, copy)
  52. #define PHP_PROTO_ZVAL_STRINGL(zval_ptr, s, len, copy) \
  53. ZVAL_STRINGL(zval_ptr, s, len, copy)
  54. #define PHP_PROTO_RETURN_STRING(s, copy) RETURN_STRING(s, copy)
  55. #define PHP_PROTO_RETURN_STRINGL(s, len, copy) RETURN_STRINGL(s, len, copy)
  56. #define PHP_PROTO_RETVAL_STRINGL(s, len, copy) RETVAL_STRINGL(s, len, copy)
  57. #define php_proto_zend_make_printable_zval(from, to) \
  58. { \
  59. int use_copy; \
  60. zend_make_printable_zval(from, to, &use_copy); \
  61. }
  62. // PHP Array
  63. #define PHP_PROTO_HASH_OF(array) Z_ARRVAL_P(array)
  64. #define php_proto_zend_hash_index_update_zval(ht, h, pData) \
  65. zend_hash_index_update(ht, h, &(pData), sizeof(void*), NULL)
  66. #define php_proto_zend_hash_index_update_mem(ht, h, pData, nDataSize, pDest) \
  67. zend_hash_index_update(ht, h, pData, nDataSize, pDest)
  68. #define php_proto_zend_hash_index_find_zval(ht, h, pDest) \
  69. zend_hash_index_find(ht, h, pDest)
  70. #define php_proto_zend_hash_index_find_mem(ht, h, pDest) \
  71. zend_hash_index_find(ht, h, pDest)
  72. #define php_proto_zend_hash_next_index_insert_zval(ht, pData) \
  73. zend_hash_next_index_insert(ht, pData, sizeof(void*), NULL)
  74. #define php_proto_zend_hash_next_index_insert_mem(ht, pData, nDataSize, pDest) \
  75. zend_hash_next_index_insert(ht, pData, nDataSize, pDest)
  76. #define php_proto_zend_hash_get_current_data_ex(ht, pDest, pos) \
  77. zend_hash_get_current_data_ex(ht, pDest, pos)
  78. // PHP Object
  79. #define PHP_PROTO_WRAP_OBJECT_START(name) \
  80. struct name { \
  81. zend_object std;
  82. #define PHP_PROTO_WRAP_OBJECT_END \
  83. };
  84. #define PHP_PROTO_INIT_CLASS_START(CLASSNAME, CAMELNAME, LOWWERNAME) \
  85. void LOWWERNAME##_init(TSRMLS_D) { \
  86. zend_class_entry class_type; \
  87. const char* class_name = CLASSNAME; \
  88. INIT_CLASS_ENTRY_EX(class_type, CLASSNAME, strlen(CLASSNAME), \
  89. LOWWERNAME##_methods); \
  90. LOWWERNAME##_type = zend_register_internal_class(&class_type TSRMLS_CC); \
  91. LOWWERNAME##_type->create_object = LOWWERNAME##_create; \
  92. LOWWERNAME##_handlers = PEMALLOC(zend_object_handlers); \
  93. memcpy(LOWWERNAME##_handlers, zend_get_std_object_handlers(), \
  94. sizeof(zend_object_handlers));
  95. #define PHP_PROTO_INIT_CLASS_END \
  96. }
  97. #define PHP_PROTO_OBJECT_CREATE_START(NAME, LOWWERNAME) \
  98. static zend_object_value LOWWERNAME##_create( \
  99. zend_class_entry* ce TSRMLS_DC) { \
  100. PHP_PROTO_ALLOC_CLASS_OBJECT(NAME, ce); \
  101. zend_object_std_init(&intern->std, ce TSRMLS_CC); \
  102. object_properties_init(&intern->std, ce);
  103. #define PHP_PROTO_OBJECT_CREATE_END(NAME, LOWWERNAME) \
  104. PHP_PROTO_FREE_CLASS_OBJECT(NAME, LOWWERNAME##_free, LOWWERNAME##_handlers); \
  105. }
  106. #define PHP_PROTO_OBJECT_FREE_START(classname, lowername) \
  107. void lowername##_free(void* object TSRMLS_DC) { \
  108. classname* intern = object;
  109. #define PHP_PROTO_OBJECT_FREE_END \
  110. zend_object_std_dtor(&intern->std TSRMLS_CC); \
  111. efree(intern); \
  112. }
  113. #define PHP_PROTO_OBJECT_DTOR_START(classname, lowername)
  114. #define PHP_PROTO_OBJECT_DTOR_END
  115. #define CACHED_VALUE zval*
  116. #define CACHED_TO_ZVAL_PTR(VALUE) (VALUE)
  117. #define CACHED_PTR_TO_ZVAL_PTR(VALUE) (*VALUE)
  118. #define ZVAL_PTR_TO_CACHED_PTR(VALUE) (&VALUE)
  119. #define CREATE_OBJ_ON_ALLOCATED_ZVAL_PTR(zval_ptr, class_type) \
  120. ZVAL_OBJ(zval_ptr, class_type->create_object(class_type TSRMLS_CC));
  121. #define PHP_PROTO_SEPARATE_ZVAL_IF_NOT_REF(value) \
  122. SEPARATE_ZVAL_IF_NOT_REF(value)
  123. #define PHP_PROTO_GLOBAL_UNINITIALIZED_ZVAL EG(uninitialized_zval_ptr)
  124. #define OBJ_PROP(PROPERTIES, OFFSET) (PROPERTIES)->properties_table[OFFSET]
  125. #define php_proto_zval_ptr_dtor(zval_ptr) \
  126. zval_ptr_dtor(&(zval_ptr))
  127. #define PHP_PROTO_ALLOC_CLASS_OBJECT(class_object, class_type) \
  128. class_object* intern; \
  129. intern = (class_object*)emalloc(sizeof(class_object)); \
  130. memset(intern, 0, sizeof(class_object));
  131. #define PHP_PROTO_FREE_CLASS_OBJECT(class_object, class_object_free, handler) \
  132. zend_object_value retval = {0}; \
  133. retval.handle = zend_objects_store_put( \
  134. intern, (zend_objects_store_dtor_t)zend_objects_destroy_object, \
  135. class_object_free, NULL TSRMLS_CC); \
  136. retval.handlers = handler; \
  137. return retval;
  138. #define PHP_PROTO_ALLOC_ARRAY(zval_ptr) \
  139. ALLOC_HASHTABLE(Z_ARRVAL_P(zval_ptr)); \
  140. Z_TYPE_P(zval_ptr) = IS_ARRAY;
  141. #define ZVAL_OBJ(zval_ptr, call_create) \
  142. Z_TYPE_P(zval_ptr) = IS_OBJECT; \
  143. Z_OBJVAL_P(zval_ptr) = call_create;
  144. #define UNBOX(class_name, val) \
  145. (class_name*)zend_object_store_get_object(val TSRMLS_CC);
  146. #define UNBOX_HASHTABLE_VALUE(class_name, val) UNBOX(class_name, val)
  147. #define HASHTABLE_VALUE_DTOR ZVAL_PTR_DTOR
  148. #define PHP_PROTO_HASHTABLE_VALUE zval*
  149. #define HASHTABLE_VALUE_CE(val) Z_OBJCE_P(val)
  150. #define CREATE_HASHTABLE_VALUE(OBJ, WRAPPED_OBJ, OBJ_TYPE, OBJ_CLASS_ENTRY) \
  151. OBJ_TYPE* OBJ; \
  152. PHP_PROTO_HASHTABLE_VALUE WRAPPED_OBJ; \
  153. MAKE_STD_ZVAL(WRAPPED_OBJ); \
  154. ZVAL_OBJ(WRAPPED_OBJ, \
  155. OBJ_CLASS_ENTRY->create_object(OBJ_CLASS_ENTRY TSRMLS_CC)); \
  156. OBJ = UNBOX_HASHTABLE_VALUE(OBJ_TYPE, WRAPPED_OBJ); \
  157. Z_DELREF_P(desc_php);
  158. #define PHP_PROTO_CE_DECLARE zend_class_entry**
  159. #define PHP_PROTO_CE_UNREF(ce) (*ce)
  160. #define php_proto_zend_lookup_class(name, name_length, ce) \
  161. zend_lookup_class(name, name_length, ce TSRMLS_CC)
  162. #else // PHP_MAJOR_VERSION >= 7
  163. #define php_proto_zend_literal void**
  164. #define PHP_PROTO_CASE_IS_BOOL IS_TRUE: case IS_FALSE
  165. #define PHP_PROTO_SIZE size_t
  166. #define PHP_PROTO_LONG zend_long
  167. #define PHP_PROTO_TSRMLS_DC
  168. #define PHP_PROTO_TSRMLS_CC
  169. // PHP String
  170. #define PHP_PROTO_ZVAL_STRING(zval_ptr, s, copy) \
  171. ZVAL_STRING(zval_ptr, s)
  172. #define PHP_PROTO_ZVAL_STRINGL(zval_ptr, s, len, copy) \
  173. ZVAL_STRINGL(zval_ptr, s, len)
  174. #define PHP_PROTO_RETURN_STRING(s, copy) RETURN_STRING(s)
  175. #define PHP_PROTO_RETURN_STRINGL(s, len, copy) RETURN_STRINGL(s, len)
  176. #define PHP_PROTO_RETVAL_STRINGL(s, len, copy) RETVAL_STRINGL(s, len)
  177. #define php_proto_zend_make_printable_zval(from, to) \
  178. zend_make_printable_zval(from, to)
  179. // PHP Array
  180. #define PHP_PROTO_HASH_OF(array) Z_ARRVAL_P(&array)
  181. static inline int php_proto_zend_hash_index_update_zval(HashTable* ht, ulong h,
  182. zval* pData) {
  183. void* result = NULL;
  184. result = zend_hash_index_update(ht, h, pData);
  185. return result != NULL ? SUCCESS : FAILURE;
  186. }
  187. static inline int php_proto_zend_hash_index_update_mem(HashTable* ht, ulong h,
  188. void* pData, uint nDataSize,
  189. void** pDest) {
  190. void* result = NULL;
  191. result = zend_hash_index_update_mem(ht, h, pData, nDataSize);
  192. if (pDest != NULL) *pDest = result;
  193. return result != NULL ? SUCCESS : FAILURE;
  194. }
  195. static inline int php_proto_zend_hash_index_find_zval(const HashTable* ht,
  196. ulong h, void** pDest) {
  197. zval* result = zend_hash_index_find(ht, h);
  198. if (pDest != NULL) *pDest = result;
  199. return result != NULL ? SUCCESS : FAILURE;
  200. }
  201. static inline int php_proto_zend_hash_index_find_mem(const HashTable* ht,
  202. ulong h, void** pDest) {
  203. void* result = NULL;
  204. result = zend_hash_index_find_ptr(ht, h);
  205. if (pDest != NULL) *pDest = result;
  206. return result != NULL ? SUCCESS : FAILURE;
  207. }
  208. static inline int php_proto_zend_hash_next_index_insert_zval(HashTable* ht,
  209. void* pData) {
  210. zval tmp;
  211. ZVAL_OBJ(&tmp, *(zend_object**)pData);
  212. zval* result = zend_hash_next_index_insert(ht, &tmp);
  213. return result != NULL ? SUCCESS : FAILURE;
  214. }
  215. static inline int php_proto_zend_hash_next_index_insert_mem(HashTable* ht,
  216. void* pData,
  217. uint nDataSize,
  218. void** pDest) {
  219. void* result = NULL;
  220. result = zend_hash_next_index_insert_mem(ht, pData, nDataSize);
  221. if (pDest != NULL) *pDest = result;
  222. return result != NULL ? SUCCESS : FAILURE;
  223. }
  224. static inline int php_proto_zend_hash_get_current_data_ex(HashTable* ht,
  225. void** pDest,
  226. HashPosition* pos) {
  227. void* result = NULL;
  228. result = zend_hash_get_current_data_ex(ht, pos);
  229. if (pDest != NULL) *pDest = result;
  230. return result != NULL ? SUCCESS : FAILURE;
  231. }
  232. // PHP Object
  233. #define PHP_PROTO_WRAP_OBJECT_START(name) struct name {
  234. #define PHP_PROTO_WRAP_OBJECT_END \
  235. zend_object std; \
  236. };
  237. #define PHP_PROTO_INIT_CLASS_START(CLASSNAME, CAMELNAME, LOWWERNAME) \
  238. void LOWWERNAME##_init(TSRMLS_D) { \
  239. zend_class_entry class_type; \
  240. const char* class_name = CLASSNAME; \
  241. INIT_CLASS_ENTRY_EX(class_type, CLASSNAME, strlen(CLASSNAME), \
  242. LOWWERNAME##_methods); \
  243. LOWWERNAME##_type = zend_register_internal_class(&class_type TSRMLS_CC); \
  244. LOWWERNAME##_type->create_object = LOWWERNAME##_create; \
  245. LOWWERNAME##_handlers = PEMALLOC(zend_object_handlers); \
  246. memcpy(LOWWERNAME##_handlers, zend_get_std_object_handlers(), \
  247. sizeof(zend_object_handlers)); \
  248. LOWWERNAME##_handlers->free_obj = LOWWERNAME##_free; \
  249. LOWWERNAME##_handlers->dtor_obj = LOWWERNAME##_dtor; \
  250. LOWWERNAME##_handlers->offset = XtOffsetOf(CAMELNAME, std);
  251. #define PHP_PROTO_INIT_CLASS_END \
  252. }
  253. #define PHP_PROTO_OBJECT_FREE_START(classname, lowername) \
  254. void lowername##_free(zend_object* object) { \
  255. classname* intern = \
  256. (classname*)((char*)object - XtOffsetOf(classname, std));
  257. #define PHP_PROTO_OBJECT_FREE_END \
  258. }
  259. #define PHP_PROTO_OBJECT_DTOR_START(classname, lowername) \
  260. void lowername##_dtor(zend_object* object) { \
  261. classname* intern = \
  262. (classname*)((char*)object - XtOffsetOf(classname, std));
  263. #define PHP_PROTO_OBJECT_DTOR_END \
  264. zend_object_std_dtor(object TSRMLS_CC); \
  265. }
  266. #define PHP_PROTO_OBJECT_CREATE_START(NAME, LOWWERNAME) \
  267. static zend_object* LOWWERNAME##_create(zend_class_entry* ce TSRMLS_DC) { \
  268. PHP_PROTO_ALLOC_CLASS_OBJECT(NAME, ce); \
  269. zend_object_std_init(&intern->std, ce TSRMLS_CC); \
  270. object_properties_init(&intern->std, ce);
  271. #define PHP_PROTO_OBJECT_CREATE_END(NAME, LOWWERNAME) \
  272. PHP_PROTO_FREE_CLASS_OBJECT(NAME, LOWWERNAME##_free, LOWWERNAME##_handlers); \
  273. }
  274. #define CACHED_VALUE zval
  275. #define CACHED_TO_ZVAL_PTR(VALUE) (&VALUE)
  276. #define CACHED_PTR_TO_ZVAL_PTR(VALUE) (VALUE)
  277. #define ZVAL_PTR_TO_CACHED_PTR(VALUE) (VALUE)
  278. #define CREATE_OBJ_ON_ALLOCATED_ZVAL_PTR(zval_ptr, class_type) \
  279. ZVAL_OBJ(zval_ptr, class_type->create_object(class_type));
  280. #define PHP_PROTO_SEPARATE_ZVAL_IF_NOT_REF(value) ;
  281. #define PHP_PROTO_GLOBAL_UNINITIALIZED_ZVAL &EG(uninitialized_zval)
  282. #define php_proto_zval_ptr_dtor(zval_ptr) \
  283. zval_ptr_dtor(zval_ptr)
  284. #define PHP_PROTO_ALLOC_CLASS_OBJECT(class_object, class_type) \
  285. class_object* intern; \
  286. int size = sizeof(class_object) + zend_object_properties_size(class_type); \
  287. intern = ecalloc(1, size); \
  288. memset(intern, 0, size);
  289. #define PHP_PROTO_FREE_CLASS_OBJECT(class_object, class_object_free, handler) \
  290. intern->std.handlers = handler; \
  291. return &intern->std;
  292. #define PHP_PROTO_ALLOC_ARRAY(zval_ptr) \
  293. ZVAL_NEW_ARR(zval_ptr)
  294. #define UNBOX(class_name, val) \
  295. (class_name*)((char*)Z_OBJ_P(val) - XtOffsetOf(class_name, std));
  296. #define UNBOX_HASHTABLE_VALUE(class_name, val) \
  297. (class_name*)((char*)val - XtOffsetOf(class_name, std))
  298. #define HASHTABLE_VALUE_DTOR php_proto_hashtable_descriptor_release
  299. #define PHP_PROTO_HASHTABLE_VALUE zend_object*
  300. #define HASHTABLE_VALUE_CE(val) val->ce
  301. #define CREATE_HASHTABLE_VALUE(OBJ, WRAPPED_OBJ, OBJ_TYPE, OBJ_CLASS_ENTRY) \
  302. OBJ_TYPE* OBJ; \
  303. PHP_PROTO_HASHTABLE_VALUE WRAPPED_OBJ; \
  304. WRAPPED_OBJ = OBJ_CLASS_ENTRY->create_object(OBJ_CLASS_ENTRY); \
  305. OBJ = UNBOX_HASHTABLE_VALUE(OBJ_TYPE, WRAPPED_OBJ); \
  306. --GC_REFCOUNT(WRAPPED_OBJ);
  307. #define PHP_PROTO_CE_DECLARE zend_class_entry*
  308. #define PHP_PROTO_CE_UNREF(ce) (ce)
  309. static inline int php_proto_zend_lookup_class(
  310. const char* name, int name_length, zend_class_entry** ce TSRMLS_DC) {
  311. zend_string *zstr_name = zend_string_init(name, name_length, 0);
  312. *ce = zend_lookup_class(zstr_name);
  313. zend_string_release(zstr_name);
  314. return *ce != NULL ? SUCCESS : FAILURE;
  315. }
  316. #endif // PHP_MAJOR_VERSION >= 7
  317. // -----------------------------------------------------------------------------
  318. // Forward Declaration
  319. // ----------------------------------------------------------------------------
  320. struct DescriptorPool;
  321. struct Descriptor;
  322. struct EnumDescriptor;
  323. struct EnumValueDescriptor;
  324. struct FieldDescriptor;
  325. struct InternalDescriptorPool;
  326. struct MessageField;
  327. struct MessageHeader;
  328. struct MessageLayout;
  329. struct RepeatedField;
  330. struct RepeatedFieldIter;
  331. struct Map;
  332. struct MapIter;
  333. struct Oneof;
  334. typedef struct DescriptorPool DescriptorPool;
  335. typedef struct Descriptor Descriptor;
  336. typedef struct EnumDescriptor EnumDescriptor;
  337. typedef struct EnumValueDescriptor EnumValueDescriptor;
  338. typedef struct FieldDescriptor FieldDescriptor;
  339. typedef struct InternalDescriptorPool InternalDescriptorPool;
  340. typedef struct MessageField MessageField;
  341. typedef struct MessageHeader MessageHeader;
  342. typedef struct MessageLayout MessageLayout;
  343. typedef struct RepeatedField RepeatedField;
  344. typedef struct RepeatedFieldIter RepeatedFieldIter;
  345. typedef struct Map Map;
  346. typedef struct MapIter MapIter;
  347. typedef struct Oneof Oneof;
  348. // -----------------------------------------------------------------------------
  349. // Globals.
  350. // -----------------------------------------------------------------------------
  351. ZEND_BEGIN_MODULE_GLOBALS(protobuf)
  352. ZEND_END_MODULE_GLOBALS(protobuf)
  353. // Init module and PHP classes.
  354. void descriptor_init(TSRMLS_D);
  355. void enum_descriptor_init(TSRMLS_D);
  356. void descriptor_pool_init(TSRMLS_D);
  357. void internal_descriptor_pool_init(TSRMLS_D);
  358. void field_descriptor_init(TSRMLS_D);
  359. void gpb_type_init(TSRMLS_D);
  360. void map_field_init(TSRMLS_D);
  361. void map_field_iter_init(TSRMLS_D);
  362. void oneof_descriptor_init(TSRMLS_D);
  363. void repeated_field_init(TSRMLS_D);
  364. void repeated_field_iter_init(TSRMLS_D);
  365. void util_init(TSRMLS_D);
  366. void message_init(TSRMLS_D);
  367. // Global map from upb {msg,enum}defs to wrapper Descriptor/EnumDescriptor
  368. // instances.
  369. void add_def_obj(const void* def, PHP_PROTO_HASHTABLE_VALUE value);
  370. PHP_PROTO_HASHTABLE_VALUE get_def_obj(const void* def);
  371. // Global map from PHP class entries to wrapper Descriptor/EnumDescriptor
  372. // instances.
  373. void add_ce_obj(const void* ce, PHP_PROTO_HASHTABLE_VALUE value);
  374. PHP_PROTO_HASHTABLE_VALUE get_ce_obj(const void* ce);
  375. bool class_added(const void* ce);
  376. extern zend_class_entry* map_field_type;
  377. extern zend_class_entry* repeated_field_type;
  378. // -----------------------------------------------------------------------------
  379. // Descriptor.
  380. // -----------------------------------------------------------------------------
  381. PHP_PROTO_WRAP_OBJECT_START(DescriptorPool)
  382. InternalDescriptorPool* intern;
  383. PHP_PROTO_WRAP_OBJECT_END
  384. PHP_METHOD(DescriptorPool, getGeneratedPool);
  385. PHP_METHOD(DescriptorPool, getDescriptorByClassName);
  386. PHP_METHOD(DescriptorPool, getEnumDescriptorByClassName);
  387. PHP_PROTO_WRAP_OBJECT_START(InternalDescriptorPool)
  388. upb_symtab* symtab;
  389. HashTable* pending_list;
  390. PHP_PROTO_WRAP_OBJECT_END
  391. PHP_METHOD(InternalDescriptorPool, getGeneratedPool);
  392. PHP_METHOD(InternalDescriptorPool, internalAddGeneratedFile);
  393. // wrapper of generated pool
  394. #if PHP_MAJOR_VERSION < 7
  395. extern zval* generated_pool_php;
  396. extern zval* internal_generated_pool_php;
  397. void descriptor_pool_free(void* object TSRMLS_DC);
  398. void internal_descriptor_pool_free(void* object TSRMLS_DC);
  399. #else
  400. extern zend_object *generated_pool_php;
  401. extern zend_object *internal_generated_pool_php;
  402. void descriptor_pool_free(zend_object* object);
  403. void internal_descriptor_pool_free(zend_object* object);
  404. #endif
  405. extern InternalDescriptorPool* generated_pool; // The actual generated pool
  406. PHP_PROTO_WRAP_OBJECT_START(Descriptor)
  407. const upb_msgdef* msgdef;
  408. MessageLayout* layout;
  409. zend_class_entry* klass; // begins as NULL
  410. const upb_handlers* fill_handlers;
  411. const upb_pbdecodermethod* fill_method;
  412. const upb_json_parsermethod* json_fill_method;
  413. const upb_handlers* pb_serialize_handlers;
  414. const upb_handlers* json_serialize_handlers;
  415. const upb_handlers* json_serialize_handlers_preserve;
  416. PHP_PROTO_WRAP_OBJECT_END
  417. PHP_METHOD(Descriptor, getFullName);
  418. PHP_METHOD(Descriptor, getField);
  419. PHP_METHOD(Descriptor, getFieldCount);
  420. PHP_METHOD(Descriptor, getOneofDecl);
  421. PHP_METHOD(Descriptor, getOneofDeclCount);
  422. extern zend_class_entry* descriptor_type;
  423. void descriptor_name_set(Descriptor *desc, const char *name);
  424. PHP_PROTO_WRAP_OBJECT_START(FieldDescriptor)
  425. const upb_fielddef* fielddef;
  426. PHP_PROTO_WRAP_OBJECT_END
  427. PHP_METHOD(FieldDescriptor, getName);
  428. PHP_METHOD(FieldDescriptor, getNumber);
  429. PHP_METHOD(FieldDescriptor, getLabel);
  430. PHP_METHOD(FieldDescriptor, getType);
  431. PHP_METHOD(FieldDescriptor, isMap);
  432. PHP_METHOD(FieldDescriptor, getEnumType);
  433. PHP_METHOD(FieldDescriptor, getMessageType);
  434. extern zend_class_entry* field_descriptor_type;
  435. PHP_PROTO_WRAP_OBJECT_START(EnumDescriptor)
  436. const upb_enumdef* enumdef;
  437. zend_class_entry* klass; // begins as NULL
  438. PHP_PROTO_WRAP_OBJECT_END
  439. PHP_METHOD(EnumDescriptor, getValue);
  440. PHP_METHOD(EnumDescriptor, getValueCount);
  441. extern zend_class_entry* enum_descriptor_type;
  442. PHP_PROTO_WRAP_OBJECT_START(EnumValueDescriptor)
  443. const char* name;
  444. int32_t number;
  445. PHP_PROTO_WRAP_OBJECT_END
  446. PHP_METHOD(EnumValueDescriptor, getName);
  447. PHP_METHOD(EnumValueDescriptor, getNumber);
  448. extern zend_class_entry* enum_value_descriptor_type;
  449. // -----------------------------------------------------------------------------
  450. // Message class creation.
  451. // -----------------------------------------------------------------------------
  452. void* message_data(MessageHeader* msg);
  453. void custom_data_init(const zend_class_entry* ce,
  454. MessageHeader* msg PHP_PROTO_TSRMLS_DC);
  455. // Build PHP class for given descriptor. Instead of building from scratch, this
  456. // function modifies existing class which has been partially defined in PHP
  457. // code.
  458. void build_class_from_descriptor(
  459. PHP_PROTO_HASHTABLE_VALUE php_descriptor TSRMLS_DC);
  460. extern zend_object_handlers* message_handlers;
  461. // -----------------------------------------------------------------------------
  462. // Message layout / storage.
  463. // -----------------------------------------------------------------------------
  464. /*
  465. * In c extension, each protobuf message is a zval instance. The zval instance
  466. * is like union, which can be used to store int, string, zend_object_value and
  467. * etc. For protobuf message, the zval instance is used to store the
  468. * zend_object_value.
  469. *
  470. * The zend_object_value is composed of handlers and a handle to look up the
  471. * actual stored data. The handlers are pointers to functions, e.g., read,
  472. * write, and etc, to access properties.
  473. *
  474. * The actual data of protobuf messages is stored as MessageHeader in zend
  475. * engine's central repository. Each MessageHeader instance is composed of a
  476. * zend_object, a Descriptor instance and the real message data.
  477. *
  478. * For the reason that PHP's native types may not be large enough to store
  479. * protobuf message's field (e.g., int64), all message's data is stored in
  480. * custom memory layout and is indexed by the Descriptor instance.
  481. *
  482. * The zend_object contains the zend class entry and the properties table. The
  483. * zend class entry contains all information about protobuf message's
  484. * corresponding PHP class. The most useful information is the offset table of
  485. * properties. Because read access to properties requires returning zval
  486. * instance, we need to convert data from the custom layout to zval instance.
  487. * Instead of creating zval instance for every read access, we use the zval
  488. * instances in the properties table in the zend_object as cache. When
  489. * accessing properties, the offset is needed to find the zval property in
  490. * zend_object's properties table. These properties will be updated using the
  491. * data from custom memory layout only when reading these properties.
  492. *
  493. * zval
  494. * |-zend_object_value obj
  495. * |-zend_object_handlers* handlers -> |-read_property_handler
  496. * | |-write_property_handler
  497. * | ++++++++++++++++++++++
  498. * |-zend_object_handle handle -> + central repository +
  499. * ++++++++++++++++++++++
  500. * MessageHeader <-----------------|
  501. * |-zend_object std
  502. * | |-class_entry* ce -> class_entry
  503. * | | |-HashTable properties_table (name->offset)
  504. * | |-zval** properties_table <------------------------------|
  505. * | |------> zval* property(cache)
  506. * |-Descriptor* desc (name->offset)
  507. * |-void** data <-----------|
  508. * |-----------------------> void* property(data)
  509. *
  510. */
  511. #define MESSAGE_FIELD_NO_CASE ((size_t)-1)
  512. struct MessageField {
  513. size_t offset;
  514. int cache_index; // Each field except oneof field has a zval cache to avoid
  515. // multiple creation when being accessed.
  516. size_t case_offset; // for oneofs, a uint32. Else, MESSAGE_FIELD_NO_CASE.
  517. };
  518. struct MessageLayout {
  519. const upb_msgdef* msgdef;
  520. MessageField* fields;
  521. size_t size;
  522. };
  523. PHP_PROTO_WRAP_OBJECT_START(MessageHeader)
  524. void* data; // Point to the real message data.
  525. // Place needs to be consistent with map_parse_frame_data_t.
  526. Descriptor* descriptor; // Kept alive by self.class.descriptor reference.
  527. PHP_PROTO_WRAP_OBJECT_END
  528. MessageLayout* create_layout(const upb_msgdef* msgdef);
  529. void layout_init(MessageLayout* layout, void* storage,
  530. CACHED_VALUE* properties_table PHP_PROTO_TSRMLS_DC);
  531. zval* layout_get(MessageLayout* layout, const void* storage,
  532. const upb_fielddef* field, CACHED_VALUE* cache TSRMLS_DC);
  533. void layout_set(MessageLayout* layout, MessageHeader* header,
  534. const upb_fielddef* field, zval* val TSRMLS_DC);
  535. void layout_merge(MessageLayout* layout, MessageHeader* from,
  536. MessageHeader* to TSRMLS_DC);
  537. const char* layout_get_oneof_case(MessageLayout* layout, const void* storage,
  538. const upb_oneofdef* oneof TSRMLS_DC);
  539. void free_layout(MessageLayout* layout);
  540. PHP_METHOD(Message, clear);
  541. PHP_METHOD(Message, mergeFrom);
  542. PHP_METHOD(Message, readOneof);
  543. PHP_METHOD(Message, writeOneof);
  544. PHP_METHOD(Message, whichOneof);
  545. PHP_METHOD(Message, __construct);
  546. // -----------------------------------------------------------------------------
  547. // Encode / Decode.
  548. // -----------------------------------------------------------------------------
  549. // Maximum depth allowed during encoding, to avoid stack overflows due to
  550. // cycles.
  551. #define ENCODE_MAX_NESTING 63
  552. // Constructs the upb decoder method for parsing messages of this type.
  553. // This is called from the message class creation code.
  554. const upb_pbdecodermethod *new_fillmsg_decodermethod(Descriptor *desc,
  555. const void *owner);
  556. PHP_METHOD(Message, serializeToString);
  557. PHP_METHOD(Message, mergeFromString);
  558. PHP_METHOD(Message, serializeToJsonString);
  559. PHP_METHOD(Message, mergeFromJsonString);
  560. // -----------------------------------------------------------------------------
  561. // Type check / conversion.
  562. // -----------------------------------------------------------------------------
  563. bool protobuf_convert_to_int32(zval* from, int32_t* to);
  564. bool protobuf_convert_to_uint32(zval* from, uint32_t* to);
  565. bool protobuf_convert_to_int64(zval* from, int64_t* to);
  566. bool protobuf_convert_to_uint64(zval* from, uint64_t* to);
  567. bool protobuf_convert_to_float(zval* from, float* to);
  568. bool protobuf_convert_to_double(zval* from, double* to);
  569. bool protobuf_convert_to_bool(zval* from, int8_t* to);
  570. bool protobuf_convert_to_string(zval* from);
  571. PHP_METHOD(Util, checkInt32);
  572. PHP_METHOD(Util, checkUint32);
  573. PHP_METHOD(Util, checkInt64);
  574. PHP_METHOD(Util, checkUint64);
  575. PHP_METHOD(Util, checkEnum);
  576. PHP_METHOD(Util, checkFloat);
  577. PHP_METHOD(Util, checkDouble);
  578. PHP_METHOD(Util, checkBool);
  579. PHP_METHOD(Util, checkString);
  580. PHP_METHOD(Util, checkBytes);
  581. PHP_METHOD(Util, checkMessage);
  582. PHP_METHOD(Util, checkMapField);
  583. PHP_METHOD(Util, checkRepeatedField);
  584. // -----------------------------------------------------------------------------
  585. // Native slot storage abstraction.
  586. // -----------------------------------------------------------------------------
  587. #define NATIVE_SLOT_MAX_SIZE sizeof(uint64_t)
  588. size_t native_slot_size(upb_fieldtype_t type);
  589. bool native_slot_set(upb_fieldtype_t type, const zend_class_entry* klass,
  590. void* memory, zval* value TSRMLS_DC);
  591. // String/Message is stored differently in array/map from normal message fields.
  592. // So we need to make a special method to handle that.
  593. bool native_slot_set_by_array(upb_fieldtype_t type,
  594. const zend_class_entry* klass, void* memory,
  595. zval* value TSRMLS_DC);
  596. bool native_slot_set_by_map(upb_fieldtype_t type, const zend_class_entry* klass,
  597. void* memory, zval* value TSRMLS_DC);
  598. void native_slot_init(upb_fieldtype_t type, void* memory, CACHED_VALUE* cache);
  599. // For each property, in order to avoid conversion between the zval object and
  600. // the actual data type during parsing/serialization, the containing message
  601. // object use the custom memory layout to store the actual data type for each
  602. // property inside of it. To access a property from php code, the property
  603. // needs to be converted to a zval object. The message object is not responsible
  604. // for providing such a zval object. Instead the caller needs to provide one
  605. // (cache) and update it with the actual data (memory).
  606. void native_slot_get(upb_fieldtype_t type, const void* memory,
  607. CACHED_VALUE* cache TSRMLS_DC);
  608. // String/Message is stored differently in array/map from normal message fields.
  609. // So we need to make a special method to handle that.
  610. void native_slot_get_by_array(upb_fieldtype_t type, const void* memory,
  611. CACHED_VALUE* cache TSRMLS_DC);
  612. void native_slot_get_by_map_key(upb_fieldtype_t type, const void* memory,
  613. int length, CACHED_VALUE* cache TSRMLS_DC);
  614. void native_slot_get_by_map_value(upb_fieldtype_t type, const void* memory,
  615. CACHED_VALUE* cache TSRMLS_DC);
  616. void native_slot_get_default(upb_fieldtype_t type,
  617. CACHED_VALUE* cache TSRMLS_DC);
  618. // -----------------------------------------------------------------------------
  619. // Map Field.
  620. // -----------------------------------------------------------------------------
  621. extern zend_object_handlers* map_field_handlers;
  622. extern zend_object_handlers* map_field_iter_handlers;
  623. PHP_PROTO_WRAP_OBJECT_START(Map)
  624. upb_fieldtype_t key_type;
  625. upb_fieldtype_t value_type;
  626. const zend_class_entry* msg_ce; // class entry for value message
  627. upb_strtable table;
  628. PHP_PROTO_WRAP_OBJECT_END
  629. PHP_PROTO_WRAP_OBJECT_START(MapIter)
  630. Map* self;
  631. upb_strtable_iter it;
  632. PHP_PROTO_WRAP_OBJECT_END
  633. void map_begin(zval* self, MapIter* iter TSRMLS_DC);
  634. void map_next(MapIter* iter);
  635. bool map_done(MapIter* iter);
  636. const char* map_iter_key(MapIter* iter, int* len);
  637. upb_value map_iter_value(MapIter* iter, int* len);
  638. // These operate on a map-entry msgdef.
  639. const upb_fielddef* map_entry_key(const upb_msgdef* msgdef);
  640. const upb_fielddef* map_entry_value(const upb_msgdef* msgdef);
  641. void map_field_create_with_field(const zend_class_entry* ce,
  642. const upb_fielddef* field,
  643. CACHED_VALUE* map_field PHP_PROTO_TSRMLS_DC);
  644. void map_field_create_with_type(const zend_class_entry* ce,
  645. upb_fieldtype_t key_type,
  646. upb_fieldtype_t value_type,
  647. const zend_class_entry* msg_ce,
  648. CACHED_VALUE* map_field PHP_PROTO_TSRMLS_DC);
  649. void* upb_value_memory(upb_value* v);
  650. #define MAP_KEY_FIELD 1
  651. #define MAP_VALUE_FIELD 2
  652. // These operate on a map field (i.e., a repeated field of submessages whose
  653. // submessage type is a map-entry msgdef).
  654. bool is_map_field(const upb_fielddef* field);
  655. const upb_fielddef* map_field_key(const upb_fielddef* field);
  656. const upb_fielddef* map_field_value(const upb_fielddef* field);
  657. bool map_index_set(Map *intern, const char* keyval, int length, upb_value v);
  658. PHP_METHOD(MapField, __construct);
  659. PHP_METHOD(MapField, offsetExists);
  660. PHP_METHOD(MapField, offsetGet);
  661. PHP_METHOD(MapField, offsetSet);
  662. PHP_METHOD(MapField, offsetUnset);
  663. PHP_METHOD(MapField, count);
  664. PHP_METHOD(MapField, getIterator);
  665. PHP_METHOD(MapFieldIter, rewind);
  666. PHP_METHOD(MapFieldIter, current);
  667. PHP_METHOD(MapFieldIter, key);
  668. PHP_METHOD(MapFieldIter, next);
  669. PHP_METHOD(MapFieldIter, valid);
  670. // -----------------------------------------------------------------------------
  671. // Repeated Field.
  672. // -----------------------------------------------------------------------------
  673. extern zend_object_handlers* repeated_field_handlers;
  674. extern zend_object_handlers* repeated_field_iter_handlers;
  675. PHP_PROTO_WRAP_OBJECT_START(RepeatedField)
  676. #if PHP_MAJOR_VERSION < 7
  677. zval* array;
  678. #else
  679. zval array;
  680. #endif
  681. upb_fieldtype_t type;
  682. const zend_class_entry* msg_ce; // class entry for containing message
  683. // (for message field only).
  684. PHP_PROTO_WRAP_OBJECT_END
  685. PHP_PROTO_WRAP_OBJECT_START(RepeatedFieldIter)
  686. RepeatedField* repeated_field;
  687. long position;
  688. PHP_PROTO_WRAP_OBJECT_END
  689. void repeated_field_create_with_field(
  690. zend_class_entry* ce, const upb_fielddef* field,
  691. CACHED_VALUE* repeated_field PHP_PROTO_TSRMLS_DC);
  692. void repeated_field_create_with_type(
  693. zend_class_entry* ce, upb_fieldtype_t type, const zend_class_entry* msg_ce,
  694. CACHED_VALUE* repeated_field PHP_PROTO_TSRMLS_DC);
  695. // Return the element at the index position from the repeated field. There is
  696. // not restriction on the type of stored elements.
  697. void *repeated_field_index_native(RepeatedField *intern, int index TSRMLS_DC);
  698. // Add the element to the end of the repeated field. There is not restriction on
  699. // the type of stored elements.
  700. void repeated_field_push_native(RepeatedField *intern, void *value);
  701. PHP_METHOD(RepeatedField, __construct);
  702. PHP_METHOD(RepeatedField, append);
  703. PHP_METHOD(RepeatedField, offsetExists);
  704. PHP_METHOD(RepeatedField, offsetGet);
  705. PHP_METHOD(RepeatedField, offsetSet);
  706. PHP_METHOD(RepeatedField, offsetUnset);
  707. PHP_METHOD(RepeatedField, count);
  708. PHP_METHOD(RepeatedField, getIterator);
  709. PHP_METHOD(RepeatedFieldIter, rewind);
  710. PHP_METHOD(RepeatedFieldIter, current);
  711. PHP_METHOD(RepeatedFieldIter, key);
  712. PHP_METHOD(RepeatedFieldIter, next);
  713. PHP_METHOD(RepeatedFieldIter, valid);
  714. // -----------------------------------------------------------------------------
  715. // Oneof Field.
  716. // -----------------------------------------------------------------------------
  717. PHP_PROTO_WRAP_OBJECT_START(Oneof)
  718. upb_oneofdef* oneofdef;
  719. int index; // Index of field in oneof. -1 if not set.
  720. char value[NATIVE_SLOT_MAX_SIZE];
  721. PHP_PROTO_WRAP_OBJECT_END
  722. PHP_METHOD(Oneof, getName);
  723. PHP_METHOD(Oneof, getField);
  724. PHP_METHOD(Oneof, getFieldCount);
  725. extern zend_class_entry* oneof_descriptor_type;
  726. // Oneof case slot value to indicate that no oneof case is set. The value `0` is
  727. // safe because field numbers are used as case identifiers, and no field can
  728. // have a number of 0.
  729. #define ONEOF_CASE_NONE 0
  730. // -----------------------------------------------------------------------------
  731. // Upb.
  732. // -----------------------------------------------------------------------------
  733. upb_fieldtype_t to_fieldtype(upb_descriptortype_t type);
  734. const zend_class_entry* field_type_class(
  735. const upb_fielddef* field PHP_PROTO_TSRMLS_DC);
  736. // -----------------------------------------------------------------------------
  737. // Utilities.
  738. // -----------------------------------------------------------------------------
  739. // Memory management
  740. #define ALLOC(class_name) (class_name*) emalloc(sizeof(class_name))
  741. #define PEMALLOC(class_name) (class_name*) pemalloc(sizeof(class_name), 1)
  742. #define ALLOC_N(class_name, n) (class_name*) emalloc(sizeof(class_name) * n)
  743. #define FREE(object) efree(object)
  744. #define PEFREE(object) pefree(object, 1)
  745. // String argument.
  746. #define STR(str) (str), strlen(str)
  747. // Zend Value
  748. #if PHP_MAJOR_VERSION < 7
  749. #define Z_OBJ_P(zval_p) \
  750. ((zend_object*)(EG(objects_store) \
  751. .object_buckets[Z_OBJ_HANDLE_P(zval_p)] \
  752. .bucket.obj.object))
  753. #endif
  754. #endif // __GOOGLE_PROTOBUF_PHP_PROTOBUF_H__