@@ -265,11 +265,23 @@ static zend_object* php_phongo_int64_clone_object(phongo_compat_object_handler_t
265
265
return new_object ;
266
266
}
267
267
268
- static int php_phongo_int64_compare_objects (zval * o1 , zval * o2 )
268
+ static bool php_phongo_int64_is_int64_object (zval * object )
269
269
{
270
- php_phongo_int64_t * intern1 , * intern2 ;
270
+ if (Z_TYPE_P (object ) != IS_OBJECT ) {
271
+ return false;
272
+ }
271
273
272
- ZEND_COMPARE_OBJECTS_FALLBACK (o1 , o2 );
274
+ return Z_OBJ_P (object )-> ce == php_phongo_int64_ce ;
275
+ }
276
+
277
+ static bool php_phongo_int64_is_long_or_double (zval * value )
278
+ {
279
+ return Z_TYPE_P (value ) == IS_LONG || Z_TYPE_P (value ) == IS_DOUBLE ;
280
+ }
281
+
282
+ static int php_phongo_int64_compare_int64_objects (zval * o1 , zval * o2 )
283
+ {
284
+ php_phongo_int64_t * intern1 , * intern2 ;
273
285
274
286
intern1 = Z_INT64_OBJ_P (o1 );
275
287
intern2 = Z_INT64_OBJ_P (o2 );
@@ -281,6 +293,105 @@ static int php_phongo_int64_compare_objects(zval* o1, zval* o2)
281
293
return 0 ;
282
294
}
283
295
296
+ static int php_phongo_int64_compare_with_long_or_float (zval * object , zval * value )
297
+ {
298
+ php_phongo_int64_t * intern ;
299
+ int64_t long_value ;
300
+ double double_value ;
301
+
302
+ intern = Z_INT64_OBJ_P (object );
303
+
304
+ assert (php_phongo_int64_is_long_or_double (value ));
305
+
306
+ switch (Z_TYPE_P (value )) {
307
+ case IS_LONG :
308
+ long_value = Z_LVAL_P (value );
309
+ if (intern -> integer != long_value ) {
310
+ return intern -> integer < long_value ? -1 : 1 ;
311
+ }
312
+ break ;
313
+
314
+ case IS_DOUBLE :
315
+ double_value = Z_DVAL_P (value );
316
+ if (intern -> integer != double_value ) {
317
+ return intern -> integer < double_value ? -1 : 1 ;
318
+ }
319
+ break ;
320
+
321
+ default :
322
+ return 0 ;
323
+ }
324
+
325
+ return 0 ;
326
+ }
327
+
328
+ static int php_phongo_int64_compare_objects (zval * o1 , zval * o2 )
329
+ {
330
+ if (php_phongo_int64_is_int64_object (o1 ) && php_phongo_int64_is_int64_object (o2 )) {
331
+ return php_phongo_int64_compare_int64_objects (o1 , o2 );
332
+ }
333
+
334
+ if (php_phongo_int64_is_int64_object (o1 ) && php_phongo_int64_is_long_or_double (o2 )) {
335
+ return php_phongo_int64_compare_with_long_or_float (o1 , o2 );
336
+ }
337
+
338
+ if (php_phongo_int64_is_long_or_double (o1 ) && php_phongo_int64_is_int64_object (o2 )) {
339
+ // Invert the result as we're flipping the values used for comparison
340
+ return -1 * php_phongo_int64_compare_with_long_or_float (o2 , o1 );
341
+ }
342
+
343
+ ZEND_COMPARE_OBJECTS_FALLBACK (o1 , o2 );
344
+
345
+ return 0 ;
346
+ }
347
+
348
+ #if PHP_VERSION_ID < 80000
349
+ static int php_phongo_int64_compare_with_other_type (zval * object , zval * value )
350
+ {
351
+ zval tmp_value ;
352
+ zval result ;
353
+ int ret ;
354
+
355
+ if (Z_OBJ_HT_P (object )-> cast_object (object , & tmp_value , ((Z_TYPE_P (value ) == IS_FALSE || Z_TYPE_P (value ) == IS_TRUE ) ? _IS_BOOL : Z_TYPE_P (value ))) == FAILURE ) {
356
+ zval_ptr_dtor (& tmp_value );
357
+ return 1 ;
358
+ }
359
+
360
+ compare_function (& result , & tmp_value , value );
361
+
362
+ ret = Z_LVAL (result );
363
+ zval_ptr_dtor (& tmp_value );
364
+ zval_ptr_dtor (& result );
365
+
366
+ return ret ;
367
+ }
368
+
369
+ static int php_phongo_int64_compare_zvals (zval * result , zval * op1 , zval * op2 )
370
+ {
371
+ /* Happy case: compare an int64 object with another object, long, or double */
372
+ if ((php_phongo_int64_is_int64_object (op1 ) || php_phongo_int64_is_long_or_double (op1 )) && (php_phongo_int64_is_int64_object (op2 ) || php_phongo_int64_is_long_or_double (op2 ))) {
373
+ ZVAL_LONG (result , php_phongo_int64_compare_objects (op1 , op2 ));
374
+ return SUCCESS ;
375
+ }
376
+
377
+ /* When comparing an int64 object with any other type, cast the int64 object to the desired type.
378
+ * We know that if op1 is an object, op2 has to be the other type and vice versa. For op2 being
379
+ * the object, we can again flip the values used for comparison and multiply the result with -1. */
380
+
381
+ if (php_phongo_int64_is_int64_object (op1 )) {
382
+ ZVAL_LONG (result , php_phongo_int64_compare_with_other_type (op1 , op2 ));
383
+ return SUCCESS ;
384
+ }
385
+
386
+ if (php_phongo_int64_is_int64_object (op2 )) {
387
+ ZVAL_LONG (result , -1 * php_phongo_int64_compare_with_other_type (op2 , op1 ));
388
+ return SUCCESS ;
389
+ }
390
+
391
+ return FAILURE ;
392
+ }
393
+ #endif
394
+
284
395
static zend_result php_phongo_int64_cast_object (phongo_compat_object_handler_type * readobj , zval * retval , int type )
285
396
{
286
397
php_phongo_int64_t * intern ;
@@ -563,6 +674,12 @@ void php_phongo_int64_init_ce(INIT_FUNC_ARGS)
563
674
php_phongo_handler_int64 .offset = XtOffsetOf (php_phongo_int64_t , std );
564
675
php_phongo_handler_int64 .cast_object = php_phongo_int64_cast_object ;
565
676
php_phongo_handler_int64 .do_operation = php_phongo_int64_do_operation ;
677
+
678
+ /* On PHP 7.4, compare_objects is only used when comparing two objects.
679
+ * Use the compare handler to compare an object with any other zval */
680
+ #if PHP_VERSION_ID < 80000
681
+ php_phongo_handler_int64 .compare = php_phongo_int64_compare_zvals ;
682
+ #endif
566
683
}
567
684
568
685
bool phongo_int64_new (zval * object , int64_t integer )
0 commit comments