19
19
#include "zend.h"
20
20
#include "zend_API.h"
21
21
#include "zend_compile.h"
22
- #include "zend_interfaces_arginfo .h"
22
+ #include "zend_enum_arginfo .h"
23
23
24
24
#define ZEND_ENUM_PROPERTY_ERROR () \
25
25
zend_throw_error(NULL, "Enum properties are immutable")
31
31
} \
32
32
} while (0);
33
33
34
+ ZEND_API zend_class_entry * zend_ce_unit_enum ;
35
+ ZEND_API zend_class_entry * zend_ce_scalar_enum ;
36
+
34
37
static zend_object_handlers enum_handlers ;
35
38
36
39
zend_object * zend_enum_new (zval * result , zend_class_entry * ce , zend_string * case_name , zval * scalar_zv )
37
40
<
10000
div class="diff-text-inner">{
38
- // Temporarily remove the ZEND_ACC_ENUM flag to allow instantiation
39
- ce -> ce_flags &= ~ZEND_ACC_ENUM ;
40
- object_init_ex (result , ce );
41
- ce -> ce_flags |= ZEND_ACC_ENUM ;
41
+ zend_object * zobj = zend_objects_new (ce );
42
+ ZVAL_OBJ (result , zobj );
42
43
43
- zend_object * zobj = Z_OBJ_P (result );
44
44
ZVAL_STR_COPY (OBJ_PROP_NUM (zobj , 0 ), case_name );
45
45
if (scalar_zv != NULL ) {
46
46
ZVAL_COPY (OBJ_PROP_NUM (zobj , 1 ), scalar_zv );
@@ -123,7 +123,7 @@ static zval *zend_enum_read_property(zend_object *zobj, zend_string *name, int t
123
123
return zend_std_read_property (zobj , name , type , cache_slot , rv );
124
124
}
125
125
126
- ZEND_COLD zval * zend_enum_write_property (zend_object * object , zend_string * member , zval * value , void * * cache_slot )
126
+ static ZEND_COLD zval * zend_enum_write_property (zend_object * object , zend_string * member , zval * value , void * * cache_slot )
127
127
{
128
128
ZEND_ENUM_PROPERTY_ERROR ();
129
129
return & EG (uninitialized_zval );
@@ -134,12 +134,12 @@ static ZEND_COLD void zend_enum_unset_property(zend_object *object, zend_string
134
134
ZEND_ENUM_PROPERTY_ERROR ();
135
135
}
136
136
137
- ZEND_API zval * zend_enum_get_property_ptr_ptr (zend_object * zobj , zend_string * name , int type , void * * cache_slot )
137
+ static zval * zend_enum_get_property_ptr_ptr (zend_object * zobj , zend_string * name , int type , void * * cache_slot )
138
138
{
139
139
return NULL ;
140
140
}
141
141
142
- int zend_enum_compare_objects (zval * o1 , zval * o2 )
142
+ static int zend_enum_compare_objects (zval * o1 , zval * o2 )
143
143
{
144
144
if (Z_TYPE_P (o1 ) != IS_OBJECT || Z_TYPE_P (o2 ) != IS_OBJECT ) {
145
145
return ZEND_UNCOMPARABLE ;
@@ -148,8 +148,46 @@ int zend_enum_compare_objects(zval *o1, zval *o2)
148
148
return Z_OBJ_P (o1 ) == Z_OBJ_P (o2 ) ? 0 : 1 ;
149
149
}
150
150
151
+ static int zend_implement_unit_enum (zend_class_entry * interface , zend_class_entry * class_type )
152
+ {
153
+ if (class_type -> ce_flags & ZEND_ACC_ENUM ) {
154
+ return SUCCESS ;
155
+ }
156
+
157
+ zend_error_noreturn (E_ERROR , "Non-enum class %s cannot implement interface %s" ,
158
+ ZSTR_VAL (class_type -> name ),
159
+ ZSTR_VAL (interface -> name ));
160
+
161
+ return FAILURE ;
162
+ }
163
+
164
+ static int zend_implement_scalar_enum (zend_class_entry * interface , zend_class_entry * class_type )
165
+ {
166
+ if (!(class_type -> ce_flags & ZEND_ACC_ENUM )) {
167
+ zend_error_noreturn (E_ERROR , "Non-enum class %s cannot implement interface %s" ,
168
+ ZSTR_VAL (class_type -> name ),
169
+ ZSTR_VAL (interface -> name ));
170
+ return FAILURE ;
171
+ }
172
+
173
+ if (class_type -> enum_scalar_type == IS_UNDEF ) {
174
+ zend_error_noreturn (E_ERROR , "Non-scalar enum %s cannot implement interface %s" ,
175
+ ZSTR_VAL (class_type -> name ),
176
+ ZSTR_VAL (interface -> name ));
177
+ return FAILURE ;
178
+ }
179
+
180
+ return SUCCESS ;
181
+ }
182
+
151
183
void zend_register_enum_ce (void )
152
184
{
185
+ zend_ce_unit_enum = register_class_UnitEnum ();
186
+ zend_ce_unit_enum -> interface_gets_implemented = zend_implement_unit_enum ;
187
+
188
+ zend_ce_scalar_enum = register_class_ScalarEnum (zend_ce_unit_enum );
189
+ zend_ce_scalar_enum -> interface_gets_implemented = zend_implement_scalar_enum ;
190
+
153
191
memcpy (& enum_handlers , & std_object_handlers , sizeof (zend_object_handlers ));
154
192
enum_handlers .read_property = zend_enum_read_property ;
155
193
enum_handlers .write_property = zend_enum_write_property ;
@@ -190,8 +228,8 @@ static ZEND_NAMED_FUNCTION(zend_enum_cases_func)
190
228
191
229
array_init (return_value );
192
230
193
- ZEND_HASH_FOREACH_PTR (& ce -> constants_table , c ) {
194
- if (!(c -> value . u2 . access_flags & ZEND_CLASS_CONST_IS_CASE )) {
231
+ ZEND_HASH_FOREACH_PTR (CE_CONSTANTS_TABLE ( ce ) , c ) {
232
+ if (!(Z_ACCESS_FLAGS ( c -> value ) & ZEND_CLASS_CONST_IS_CASE )) {
195
233
continue ;
196
234
}
197
235
zval * zv = & c -> value ;
@@ -243,9 +281,8 @@ static void zend_enum_from_base(INTERNAL_FUNCTION_PARAMETERS, bool try)
243
281
}
244
282
245
283
ZEND_ASSERT (Z_TYPE_P (case_name_zv ) == IS_STRING );
246
- zval * case_const_zv = zend_hash_find (& ce -> constants_table , Z_STR_P (case_name_zv ));
247
- ZEND_ASSERT (case_const_zv != NULL );
248
- zend_class_constant * c = Z_PTR_P (case_const_zv );
284
+ zend_class_constant * c = zend_hash_find_ptr (CE_CONSTANTS_TABLE (ce ), Z_STR_P (case_name_zv ));
285
+ ZEND_ASSERT (c != NULL );
249
286
zval * case_zv = & c -> value ;
250
287
if (Z_TYPE_P (case_zv ) == IS_CONSTANT_AST ) {
251
288
zval_update_constant_ex (case_zv , c -> ce );
@@ -269,45 +306,49 @@ static ZEND_NAMED_FUNCTION(zend_enum_try_from_func)
269
306
270
307
void zend_enum_register_funcs (zend_class_entry * ce )
271
308
{
272
- zend_string * cases_func_name = zend_string_init ("cases" , strlen ("cases" ), 1 );
273
- zend_internal_function * cases_function = malloc (sizeof (zend_internal_function ));
309
+ const uint32_t fn_flags =
310
+ ZEND_ACC_PUBLIC |ZEND_ACC_STATIC |ZEND_ACC_HAS_RETURN_TYPE |ZEND_ACC_ARENA_ALLOCATED ;
311
+ zend_internal_function * cases_function =
312
+ zend_arena_alloc (& CG (arena ), sizeof (zend_internal_function ));
274
313
memset (cases_function , 0 , sizeof (zend_internal_function ));
275
314
cases_function -> type = ZEND_INTERNAL_FUNCTION ;
276
315
cases_function -> module = EG (current_module );
277
316
cases_function -> handler = zend_enum_cases_func ;
278
- cases_function -> function_name = cases_func_name ;
317
+ cases_function -> function_name = ZSTR_KNOWN ( ZEND_STR_CASES ) ;
279
318
cases_function -> scope = ce ;
280
- cases_function -> fn_flags = ZEND_ACC_PUBLIC | ZEND_ACC_STATIC | ZEND_ACC_HAS_RETURN_TYPE ;
319
+ cases_function -> fn_flags = fn_flags ;
281
320
cases_function -> arg_info = (zend_internal_arg_info * ) (arginfo_class_UnitEnum_cases + 1 );
282
- zend_hash_add_ptr (& ce -> function_table , cases_func_name , cases_function );
321
+ zend_hash_add_ptr (& ce -> function_table , ZSTR_KNOWN ( ZEND_STR_CASES ) , cases_function );
283
322
284
323
if (ce -> enum_scalar_type != IS_UNDEF ) {
285
- zend_string * from_func_name = zend_string_init ( "from" , strlen ( "from" ), 1 );
286
- zend_internal_function * from_function = malloc ( sizeof (zend_internal_function ));
324
+ zend_internal_function * from_function =
325
+ zend_arena_alloc ( & CG ( arena ), sizeof (zend_internal_function ));
287
326
memset (from_function , 0 , sizeof (zend_internal_function ));
288
327
from_function -> type = ZEND_INTERNAL_FUNCTION ;
289
328
from_function -> module = EG (current_module );
290
329
from_function -> handler = zend_enum_from_func ;
291
- from_function -> function_name = from_func_name ;
330
+ from_function -> function_name = ZSTR_KNOWN ( ZEND_STR_FROM ) ;
292
331
from_function -> scope = ce ;
293
- from_function -> fn_flags = ZEND_ACC_PUBLIC | ZEND_ACC_STATIC | ZEND_ACC_HAS_RETURN_TYPE ;
332
+ from_function -> fn_flags = fn_flags ;
294
333
from_function -> num_args = 1 ;
295
334
from_function -> required_num_args = 1 ;
296
335
from_function -> arg_info = (zend_internal_arg_info * ) (arginfo_class_ScalarEnum_from + 1 );
297
- zend_hash_add_ptr (& ce -> function_table , from_func_name , from_function );
336
+ zend_hash_add_ptr (& ce -> function_table , ZSTR_KNOWN ( ZEND_STR_FROM ) , from_function );
298
337
299
- zend_internal_function * try_from_function = malloc (sizeof (zend_internal_function ));
338
+ zend_internal_function * try_from_function =
339
+ zend_arena_alloc (& CG (arena ), sizeof (zend_internal_function ));
300
340
memset (try_from_function , 0 , sizeof (zend_internal_function ));
301
341
try_from_function -> type = ZEND_INTERNAL_FUNCTION ;
302
342
try_from_function -> module = EG (current_module );
303
343
try_from_function -> handler = zend_enum_try_from_func ;
304
- try_from_function -> function_name = zend_string_init ( "tryFrom" , strlen ( "tryFrom" ), 1 );
344
+ try_from_function -> function_name = ZSTR_KNOWN ( ZEND_STR_TRYFROM );
305
345
try_from_function -> scope = ce ;
306
- try_from_function -> fn_flags = ZEND_ACC_PUBLIC | ZEND_ACC_STATIC | ZEND_ACC_HAS_RETURN_TYPE ;
346
+ try_from_function -> fn_flags = fn_flags ;
307
347
try_from_function -> num_args = 1 ;
308
348
try_from_function -> required_num_args = 1 ;
309
349
try_from_function -> arg_info = (zend_internal_arg_info * ) (arginfo_class_ScalarEnum_tryFrom + 1 );
310
- zend_hash_add_ptr (& ce -> function_table , zend_string_init ("tryfrom" , strlen ("tryfrom" ), 1 ), try_from_function );
350
+ zend_hash_add_ptr (
351
+ & ce -> function_table , ZSTR_KNOWN (ZEND_STR_TRYFROM_LOWERCASE ), try_from_function );
311
352
}
312
353
}
313
354
0 commit comments