@@ -77,11 +77,105 @@ zend_object_handlers* phongo_get_std_object_handlers(void);
7777#define PHONGO_GET_PROPERTY_HASH_FREE_PROPS (is_temp , props ) \
7878 do { \
7979 if (is_temp) { \
80- zend_hash_destroy((props)); \
81- FREE_HASHTABLE(props); \
80+ zend_hash_release((props)); \
8281 } \
8382 } while (0)
8483
84+ #define PHONGO_ASSIGN_PROPERTY_HANDLERS (_name ) \
85+ do { \
86+ phongo_handler_##_name.read_property = phongo_##_name##_read_property; \
87+ phongo_handler_##_name.write_property = phongo_##_name##_write_property; \
88+ phongo_handler_##_name.has_property = phongo_##_name##_has_property; \
89+ phongo_handler_##_name.unset_property = phongo_##_name##_unset_property; \
90+ phongo_handler_##_name.get_property_ptr_ptr = phongo_##_name##_get_property_ptr_ptr; \
91+ phongo_handler_##_name.get_gc = phongo_##_name##_get_gc; \
92+ } while (0)
93+
94+ #define PHONGO_DEFINE_PROPERTY_HANDLERS (_name , _intern_extractor ) \
95+ static zval* phongo_##_name##_read_property(zend_object* zobj, zend_string* member, int type, void** cache_slot, zval* rv) \
96+ { \
97+ HashTable* props = _intern_extractor(zobj)->php_properties; \
98+ if (!props) { \
99+ ALLOC_HASHTABLE(props); \
100+ zend_hash_init(props, 0, NULL, ZVAL_PTR_DTOR, 0); \
101+ _intern_extractor(zobj)->php_properties = props; \
102+ } \
103+ zval* ret = zend_hash_find(props, member); \
104+ if (ret) { \
105+ return ret; \
106+ } \
107+ return &EG(uninitialized_zval); \
108+ } \
109+ \
110+ static zval* phongo_##_name##_write_property(zend_object* zobj, zend_string* name, zval* value, void** cache_slot) \
111+ { \
112+ Z_TRY_ADDREF_P(value); \
113+ HashTable* props = _intern_extractor(zobj)->php_properties; \
114+ if (!props) { \
115+ ALLOC_HASHTABLE(props); \
116+ zend_hash_init(props, 0, NULL, ZVAL_PTR_DTOR, 0); \
117+ _intern_extractor(zobj)->php_properties = props; \
118+ } \
119+ return zend_hash_add_new(props, name, value); \
120+ } \
121+ \
122+ static int phongo_##_name##_has_property(zend_object* zobj, zend_string* name, int has_set_exists, void** cache_slot) \
123+ { \
124+ HashTable* props = _intern_extractor(zobj)->php_properties; \
125+ if (!props) { \
126+ ALLOC_HASHTABLE(props); \
127+ zend_hash_init(props, 0, NULL, ZVAL_PTR_DTOR, 0); \
128+ _intern_extractor(zobj)->php_properties = props; \
129+ } \
130+ zval* value = zend_hash_find(props, name); \
131+ if (value) { \
132+ if (has_set_exists == ZEND_PROPERTY_NOT_EMPTY) { \
133+ return zend_is_true(value); \
134+ } \
135+ if (has_set_exists < ZEND_PROPERTY_NOT_EMPTY) { \
136+ ZEND_ASSERT(has_set_exists == ZEND_PROPERTY_ISSET); \
137+ ZVAL_DEREF(value); \
138+ return (Z_TYPE_P(value) != IS_NULL); \
139+ } \
140+ ZEND_ASSERT(has_set_exists == ZEND_PROPERTY_EXISTS); \
141+ return true; \
142+ } \
143+ return false; \
144+ } \
145+ \
146+ static void phongo_##_name##_unset_property(zend_object* zobj, zend_string* name, void** cache_slot) \
147+ { \
148+ HashTable* props = _intern_extractor(zobj)->php_properties; \
149+ if (!props) { \
150+ ALLOC_HASHTABLE(props); \
151+ zend_hash_init(props, 0, NULL, ZVAL_PTR_DTOR, 0); \
152+ _intern_extractor(zobj)->php_properties = props; \
153+ } \
154+ zend_hash_del(props, name); \
155+ } \
156+ \
157+ static zval* phongo_##_name##_get_property_ptr_ptr(zend_object* zobj, zend_string* name, int type, void** cache_slot) \
158+ { \
159+ HashTable* props = _intern_extractor(zobj)->php_properties; \
160+ if (!props) { \
161+ ALLOC_HASHTABLE(props); \
162+ zend_hash_init(props, 0, NULL, ZVAL_PTR_DTOR, 0); \
163+ _intern_extractor(zobj)->php_properties = props; \
164+ } \
165+ zval* value = zend_hash_find(props, name); \
166+ if (value) { \
167+ return value; \
168+ } \
169+ return zend_hash_add(props, name, &EG(uninitialized_zval)); \
170+ } \
171+ \
172+ static HashTable* phongo_##_name##_get_gc(zend_object* zobj, zval** table, int* n) \
173+ { \
174+ *table = NULL; \
175+ *n = 0; \
176+ return _intern_extractor(zobj)->php_properties; \
177+ }
178+
85179#define PHONGO_ZVAL_EXCEPTION_NAME (e ) (ZSTR_VAL(e->ce->name))
86180
87181#define PHONGO_SET_CREATED_BY_PID (intern ) \
0 commit comments