1 #ifndef __GOOGLE_PROTOBUF_PHP_PROTOBUF_H__ 2 #define __GOOGLE_PROTOBUF_PHP_PROTOBUF_H__ 3 4 #include <php.h> 5 6 #include "upb.h" 7 8 #define PHP_PROTOBUF_EXTNAME "protobuf" 9 #define PHP_PROTOBUF_VERSION "0.01" 10 11 // Forward decls. 12 struct DescriptorPool; 13 struct Descriptor; 14 struct FieldDescriptor; 15 struct EnumDescriptor; 16 struct MessageLayout; 17 struct MessageField; 18 struct MessageHeader; 19 struct MessageBuilderContext; 20 struct EnumBuilderContext; 21 22 typedef struct DescriptorPool DescriptorPool; 23 typedef struct Descriptor Descriptor; 24 typedef struct FieldDescriptor FieldDescriptor; 25 typedef struct OneofDescriptor OneofDescriptor; 26 typedef struct EnumDescriptor EnumDescriptor; 27 typedef struct MessageLayout MessageLayout; 28 typedef struct MessageField MessageField; 29 typedef struct MessageHeader MessageHeader; 30 typedef struct MessageBuilderContext MessageBuilderContext; 31 typedef struct OneofBuilderContext OneofBuilderContext; 32 typedef struct EnumBuilderContext EnumBuilderContext; 33 34 extern zend_class_entry* builder_type; 35 extern zend_class_entry* descriptor_type; 36 extern zend_class_entry* message_builder_context_type; 37 38 extern DescriptorPool* generated_pool; // The actual generated pool 39 40 ZEND_BEGIN_MODULE_GLOBALS(protobuf) 41 zval* generated_pool; 42 zend_object_handlers* message_handlers; 43 HashTable upb_def_to_php_obj_map; 44 ZEND_END_MODULE_GLOBALS(protobuf) 45 46 ZEND_DECLARE_MODULE_GLOBALS(protobuf) 47 48 #ifdef ZTS 49 #define PROTOBUF_G(v) TSRMG(protobuf_globals_id, zend_protobuf_globals*, v) 50 #else 51 #define PROTOBUF_G(v) (protobuf_globals.v) 52 #endif 53 54 // ----------------------------------------------------------------------------- 55 // PHP functions and global variables. 56 // ----------------------------------------------------------------------------- 57 58 PHP_MINIT_FUNCTION(protobuf); 59 60 // ----------------------------------------------------------------------------- 61 // PHP class structure. 62 // ----------------------------------------------------------------------------- 63 64 struct DescriptorPool { 65 zend_object std; 66 upb_symtab* symtab; 67 HashTable* pending_list; 68 }; 69 70 struct Descriptor { 71 zend_object std; 72 const upb_msgdef* msgdef; 73 MessageLayout* layout; 74 // zval* klass; // begins as NULL 75 // const upb_handlers* fill_handlers; 76 // const upb_pbdecodermethod* fill_method; 77 const upb_handlers* pb_serialize_handlers; 78 // const upb_handlers* json_serialize_handlers; 79 // Handlers hold type class references for sub-message fields directly in some 80 // cases. We need to keep these rooted because they might otherwise be 81 // collected. 82 // zval_array typeclass_references; 83 }; 84 85 struct FieldDescriptor { 86 zend_object std; 87 const upb_fielddef* fielddef; 88 }; 89 90 struct OneofDescriptor { 91 zend_object std; 92 const upb_oneofdef* oneofdef; 93 }; 94 95 struct EnumDescriptor { 96 zend_object std; 97 const upb_enumdef* enumdef; 98 // zval* module; // begins as NULL 99 }; 100 101 // ----------------------------------------------------------------------------- 102 // Native slot storage abstraction. 103 // ----------------------------------------------------------------------------- 104 105 #define NATIVE_SLOT_MAX_SIZE sizeof(uint64_t) 106 107 size_t native_slot_size(upb_fieldtype_t type); 108 109 #define MAP_KEY_FIELD 1 110 #define MAP_VALUE_FIELD 2 111 112 // Oneof case slot value to indicate that no oneof case is set. The value `0` is 113 // safe because field numbers are used as case identifiers, and no field can 114 // have a number of 0. 115 #define ONEOF_CASE_NONE 0 116 117 // These operate on a map field (i.e., a repeated field of submessages whose 118 // submessage type is a map-entry msgdef). 119 bool is_map_field(const upb_fielddef* field); 120 const upb_fielddef* map_field_key(const upb_fielddef* field); 121 const upb_fielddef* map_field_value(const upb_fielddef* field); 122 123 // These operate on a map-entry msgdef. 124 const upb_fielddef* map_entry_key(const upb_msgdef* msgdef); 125 const upb_fielddef* map_entry_value(const upb_msgdef* msgdef); 126 127 // ----------------------------------------------------------------------------- 128 // Message layout / storage. 129 // ----------------------------------------------------------------------------- 130 131 #define MESSAGE_FIELD_NO_CASE ((size_t)-1) 132 133 struct MessageField { 134 size_t offset; 135 size_t case_offset; // for oneofs, a uint32. Else, MESSAGE_FIELD_NO_CASE. 136 }; 137 138 struct MessageLayout { 139 const upb_msgdef* msgdef; 140 MessageField* fields; 141 size_t size; 142 }; 143 144 void layout_init(MessageLayout* layout, void* storage); 145 zval* layout_get(MessageLayout* layout, const void* storage, 146 const upb_fielddef* field TSRMLS_DC); 147 MessageLayout* create_layout(const upb_msgdef* msgdef); 148 void free_layout(MessageLayout* layout); 149 zval* native_slot_get(upb_fieldtype_t type, /*VALUE type_class,*/ 150 const void* memory TSRMLS_DC); 151 152 // ----------------------------------------------------------------------------- 153 // Message class creation. 154 // ----------------------------------------------------------------------------- 155 156 struct MessageHeader { 157 zend_object std; 158 Descriptor* descriptor; // kept alive by self.class.descriptor reference. 159 // Data comes after this. 160 }; 161 162 struct MessageBuilderContext { 163 zend_object std; 164 zval* descriptor; 165 zval* pool; 166 }; 167 168 struct OneofBuilderContext { 169 zend_object std; 170 // VALUE descriptor; 171 // VALUE builder; 172 }; 173 174 struct EnumBuilderContext { 175 zend_object std; 176 // VALUE enumdesc; 177 }; 178 179 // Forward-declare all of the PHP method implementations. 180 181 DescriptorPool* php_to_descriptor_pool(zval* value TSRMLS_DC); 182 zend_object_value descriptor_pool_create(zend_class_entry *ce TSRMLS_DC); 183 void descriptor_pool_free_c(DescriptorPool* object TSRMLS_DC); 184 void descriptor_pool_free(void* object TSRMLS_DC); 185 void descriptor_pool_init_c_instance(DescriptorPool* pool TSRMLS_DC); 186 PHP_METHOD(DescriptorPool, addMessage); 187 PHP_METHOD(DescriptorPool, finalize); 188 189 Descriptor* php_to_descriptor(zval* value TSRMLS_DC); 190 zend_object_value descriptor_create(zend_class_entry *ce TSRMLS_DC); 191 void descriptor_init_c_instance(Descriptor* intern TSRMLS_DC); 192 void descriptor_free_c(Descriptor* object TSRMLS_DC); 193 void descriptor_free(void* object TSRMLS_DC); 194 void descriptor_name_set(Descriptor *desc, const char *name); 195 196 MessageBuilderContext* php_to_message_builder_context(zval* value TSRMLS_DC); 197 zend_object_value message_builder_context_create( 198 zend_class_entry* ce TSRMLS_DC); 199 void message_builder_context_init_c_instance( 200 MessageBuilderContext* intern TSRMLS_DC); 201 void message_builder_context_free_c(MessageBuilderContext* object TSRMLS_DC); 202 void message_builder_context_free(void* object TSRMLS_DC); 203 PHP_METHOD(MessageBuilderContext, optional); 204 PHP_METHOD(MessageBuilderContext, finalizeToPool); 205 206 PHP_METHOD(Message, encode); 207 const zend_class_entry* build_class_from_descriptor( 208 zval* php_descriptor TSRMLS_DC); 209 210 PHP_FUNCTION(get_generated_pool); 211 212 // ----------------------------------------------------------------------------- 213 // Global map from upb {msg,enum}defs to wrapper Descriptor/EnumDescriptor 214 // instances. 215 // ---------------------------------------------------------------------------- 216 217 void add_def_obj(const void* def, zval* value); 218 zval* get_def_obj(const void* def); 219 220 // ----------------------------------------------------------------------------- 221 // Utilities. 222 // ----------------------------------------------------------------------------- 223 224 // PHP Array utils. 225 #define Z_ARRVAL_SIZE_P(zval_p) zend_hash_num_elements(Z_ARRVAL_P(zval_p)) 226 #define Z_ARRVAL_BEGIN_P(zval_p) Z_ARRVAL_P(zval_p)->pListHead 227 #define Z_BUCKET_NEXT_PP(bucket_pp) *bucket_pp = (*bucket_pp)->pListNext 228 229 #define DEFINE_PHP_OBJECT(class_name, class_name_lower, name) \ 230 do { \ 231 zval* name; \ 232 MAKE_STD_ZVAL(name); \ 233 object_init_ex(name, class_name_lower##_type); \ 234 } while (0) 235 236 #define DEFINE_PHP_WRAPPER(class_name, class_name_lower, name, intern) \ 237 zval* name; \ 238 MAKE_STD_ZVAL(name); \ 239 object_init_ex(name, class_name_lower##_type); \ 240 Z_OBJVAL_P(name) \ 241 .handle = zend_objects_store_put( \ 242 intern, (zend_objects_store_dtor_t)zend_objects_destroy_object, \ 243 class_name_lower##_free, NULL TSRMLS_CC); 244 245 #define DEFINE_PHP_ZVAL(name) \ 246 do { \ 247 zval* name; \ 248 MAKE_STD_ZVAL(name); \ 249 } while (0) 250 251 #define DEFINE_PHP_STRING(name, value) \ 252 do { \ 253 zval* name; \ 254 MAKE_STD_ZVAL(name); \ 255 ZVAL_STRING(name, value, 1); \ 256 } while (0) 257 258 // Upb Utilities 259 260 void check_upb_status(const upb_status* status, const char* msg); 261 262 #define CHECK_UPB(code, msg) \ 263 do { \ 264 upb_status status = UPB_STATUS_INIT; \ 265 code; \ 266 check_upb_status(&status, msg); \ 267 } while (0) 268 269 // Memory management 270 271 #define ALLOC(class_name) (class_name*) emalloc(sizeof(class_name)) 272 #define ALLOC_N(class_name, n) (class_name*) emalloc(sizeof(class_name) * n) 273 #define FREE(object) efree(object) 274 275 // Type Checking 276 #define CHECK_TYPE(field, type) \ 277 if (Z_TYPE_P(field) != type) { \ 278 zend_error(E_ERROR, "Unexpected type"); \ 279 } 280 281 #endif // __GOOGLE_PROTOBUF_PHP_PROTOBUF_H__ 282