1
2 /*
3 +------------------------------------------------------------------------+
4 | Zephir Language |
5 +------------------------------------------------------------------------+
6 | Copyright (c) 2011-2017 Phalcon Team (http://www.zephir-lang.com) |
7 +------------------------------------------------------------------------+
8 | This source file is subject to the New BSD License that is bundled |
9 | with this package in the file docs/LICENSE.txt. |
10 | |
11 | If you did not receive a copy of the license and are unable to |
12 | obtain it through the world-wide-web, please send an email |
13 | to license@zephir-lang.com so we can send you a copy immediately. |
14 +------------------------------------------------------------------------+
15 | Authors: Andres Gutierrez <andres@zephir-lang.com> |
16 | Eduar Carvajal <eduar@zephir-lang.com> |
17 | Vladimir Kolesnikov <vladimir@extrememember.com> |
18 +------------------------------------------------------------------------+
19 */
20
21 #ifdef HAVE_CONFIG_H
22 #include "config.h"
23 #endif
24
25 #include <php.h>
26 #include <ext/standard/php_string.h>
27 #include <ext/standard/php_math.h>
28
29 #include "php_ext.h"
30 #include "kernel/main.h"
31 #include "kernel/memory.h"
32 #include "kernel/string.h"
33 #include "kernel/operators.h"
34
35 #include "Zend/zend_operators.h"
36
37 /**
38 * Appends the content of the right operator to the left operator
39 */
zephir_concat_self(zval * left,zval * right)40 void zephir_concat_self(zval *left, zval *right)
41 {
42 zval left_copy, right_copy;
43 size_t length, left_length, right_length;
44 int use_copy_left = 0, use_copy_right = 0;
45 zend_string *target;
46
47 if (Z_TYPE_P(right) != IS_STRING) {
48 use_copy_right = zephir_make_printable_zval(right, &right_copy);
49 if (use_copy_right) {
50 right = &right_copy;
51 }
52 }
53
54 if (Z_TYPE_P(left) == IS_NULL) {
55 ZVAL_STRINGL(left, Z_STRVAL_P(right), Z_STRLEN_P(right));
56
57 if (use_copy_right) {
58 zval_dtor(&right_copy);
59 }
60
61 return;
62 }
63
64 if (Z_TYPE_P(left) != IS_STRING) {
65 use_copy_left = zephir_make_printable_zval(left, &left_copy);
66 if (use_copy_left) {
67 ZEPHIR_CPY_WRT_CTOR(left, (&left_copy));
68 }
69 }
70
71 SEPARATE_ZVAL_IF_NOT_REF(left);
72
73 left_length = Z_STRLEN_P(left);
74 right_length = Z_STRLEN_P(right);
75 length = left_length + right_length;
76 target = zend_string_extend(Z_STR_P(left), length, 0);
77 ZVAL_NEW_STR(left, target);
78 memcpy(ZSTR_VAL(target) + left_length, Z_STRVAL_P(right), right_length);
79
80 ZSTR_VAL(target)[length] = '\0';
81
82 if (use_copy_left) {
83 zval_dtor(&left_copy);
84 }
85
86 if (use_copy_right) {
87 zval_dtor(&right_copy);
88 }
89 }
90
91 /**
92 * Appends the content of the right operator to the left operator
93 */
zephir_concat_self_char(zval * left,unsigned char right)94 void zephir_concat_self_char(zval *left, unsigned char right)
95 {
96 zval left_copy;
97 int use_copy = 0, length;
98 zend_string *target;
99
100 if (Z_TYPE_P(left) == IS_NULL) {
101 target = zend_string_alloc(1, 0);
102 ZSTR_VAL(target)[0] = right;
103 ZSTR_VAL(target)[1] = 0;
104 ZVAL_STR(left, target);;
105 return;
106 }
107
108 if (Z_TYPE_P(left) != IS_STRING) {
109 use_copy = zephir_make_printable_zval(left, &left_copy);
110 if (use_copy) {
111 ZEPHIR_CPY_WRT_CTOR(left, (&left_copy));
112 }
113 }
114
115 SEPARATE_ZVAL_IF_NOT_REF(left);
116
117 length = Z_STRLEN_P(left) + 1;
118 target = zend_string_extend(Z_STR_P(left), length, 0);
119 ZVAL_NEW_STR(left, target);
120 ZSTR_VAL(target)[length - 1] = right;
121 ZSTR_VAL(target)[length] = 0;
122
123 if (use_copy) {
124 zval_dtor(&left_copy);
125 }
126 }
127
128 /**
129 * Appends the content of the right operator to the left operator
130 */
zephir_concat_self_str(zval * left,const char * right,int right_length)131 void zephir_concat_self_str(zval *left, const char *right, int right_length)
132 {
133 zval left_copy;
134 size_t length, left_length;
135 int use_copy = 0;
136 zend_string *target;
137
138 if (Z_TYPE_P(left) == IS_NULL) {
139 ZVAL_STRINGL(left, right, right_length);
140 return;
141 }
142
143 if (Z_TYPE_P(left) != IS_STRING) {
144 use_copy = zephir_make_printable_zval(left, &left_copy);
145 if (use_copy) {
146 ZEPHIR_CPY_WRT_CTOR(left, (&left_copy));
147 }
148 }
149
150 SEPARATE_ZVAL_IF_NOT_REF(left);
151 left_length = Z_STRLEN_P(left);
152 length = left_length + right_length;
153 target = zend_string_extend(Z_STR_P(left), length, 0);
154 ZVAL_NEW_STR(left, target);
155 memcpy(ZSTR_VAL(target) + left_length, right, right_length);
156 ZSTR_VAL(target)[length] = '\0';
157
158 if (use_copy) {
159 zval_dtor(&left_copy);
160 }
161 }
162
163 /**
164 * Natural compare with long operandus on right
165 */
zephir_compare_strict_long(zval * op1,long op2)166 int zephir_compare_strict_long(zval *op1, long op2)
167 {
168 switch (Z_TYPE_P(op1)) {
169 case IS_LONG:
170 return Z_LVAL_P(op1) == op2;
171 case IS_DOUBLE:
172 return Z_DVAL_P(op1) == (double) op2;
173 case IS_NULL:
174 return 0 == op2;
175 case IS_TRUE:
176 case IS_FALSE:
177 if (Z_TYPE_P(op1) == IS_TRUE) {
178 return 1 == op2;
179 } else {
180 return 0 == op2;
181 }
182 default:
183 {
184 zval result, op2_tmp;
185 ZVAL_LONG(&op2_tmp, op2);
186 is_equal_function(&result, op1, &op2_tmp);
187 return Z_TYPE(result) == IS_TRUE ? 1 : 0;
188 }
189 }
190
191 return 0;
192 }
193
194 /**
195 * Natural compare with bool operandus on right
196 */
zephir_compare_strict_bool(zval * op1,zend_bool op2)197 int zephir_compare_strict_bool(zval *op1, zend_bool op2)
198 {
199 switch (Z_TYPE_P(op1)) {
200 case IS_LONG:
201 return (Z_LVAL_P(op1) ? 1 : 0) == op2;
202 case IS_DOUBLE:
203 return (Z_DVAL_P(op1) ? 1 : 0) == op2;
204 case IS_NULL:
205 return 0 == op2;
206 case IS_TRUE:
207 return 1 == op2;
208 case IS_FALSE:
209 return 0 == op2;
210 default:
211 {
212 zval result, op2_tmp;
213 ZVAL_BOOL(&op2_tmp, op2);
214 is_equal_function(&result, op1, &op2_tmp);
215 return Z_TYPE(result) == IS_TRUE;
216 }
217 }
218
219 return 0;
220 }
221
222 /**
223 * Natural compare with string operandus on right
224 */
zephir_compare_strict_string(zval * op1,const char * op2,int op2_length)225 int zephir_compare_strict_string(zval *op1, const char *op2, int op2_length)
226 {
227 switch (Z_TYPE_P(op1)) {
228
229 case IS_STRING:
230 if (!Z_STRLEN_P(op1) && !op2_length) {
231 return 1;
232 }
233 if (Z_STRLEN_P(op1) != op2_length) {
234 return 0;
235 }
236 return !zend_binary_strcmp(Z_STRVAL_P(op1), Z_STRLEN_P(op1), op2, op2_length);
237
238 case IS_NULL:
239 return !zend_binary_strcmp("", 0, op2, op2_length);
240
241 case IS_TRUE:
242 return !zend_binary_strcmp("1", strlen("1"), op2, op2_length);
243
244 case IS_FALSE:
245 return !zend_binary_strcmp("0", strlen("0"), op2, op2_length);
246 }
247
248 return 0;
249 }
250
zephir_negate(zval * z)251 void zephir_negate(zval *z)
252 {
253 while (1) {
254 switch (Z_TYPE_P(z)) {
255 case IS_LONG:
256 ZVAL_LONG(z, -Z_LVAL_P(z));
257 return;
258
259 case IS_TRUE:
260 ZVAL_LONG(z, -1);
261 return;
262
263 case IS_DOUBLE:
264 ZVAL_DOUBLE(z, -Z_DVAL_P(z));
265 return;
266
267 case IS_NULL:
268 case IS_FALSE:
269 ZVAL_LONG(z, 0);
270 return;
271
272 default:
273 convert_scalar_to_number(z);
274 assert(Z_TYPE_P(z) == IS_LONG || Z_TYPE_P(z) == IS_DOUBLE);
275 }
276 }
277 }
278
zephir_convert_to_object(zval * op)279 void zephir_convert_to_object(zval *op)
280 {
281 convert_to_object(op);
282 }
283
284 /**
285 * Returns the long value of a zval
286 */
zephir_get_intval_ex(const zval * op)287 long zephir_get_intval_ex(const zval *op)
288 {
289 switch (Z_TYPE_P(op)) {
290 case IS_ARRAY:
291 return zend_hash_num_elements(Z_ARRVAL_P(op)) ? 1 : 0;
292
293 case IS_RESOURCE:
294 return (zend_long)Z_RES_HANDLE_P(op);
295
296 case IS_CALLABLE:
297 case IS_OBJECT:
298 return 1;
299
300 case IS_LONG:
301 return Z_LVAL_P(op);
302
303 case IS_TRUE:
304 return 1;
305
306 case IS_FALSE:
307 return 0;
308
309 case IS_DOUBLE:
310 return (long) Z_DVAL_P(op);
311
312 case IS_STRING: {
313 zend_uchar type;
314 double double_value = 0;
315 zend_long long_value = 0;
316
317 ASSUME(Z_STRVAL_P(op) != NULL);
318 type = is_numeric_string(Z_STRVAL_P(op), Z_STRLEN_P(op), &long_value, &double_value, 0);
319 if (type == IS_LONG) {
320 return long_value;
321 }
322 if (type == IS_DOUBLE) {
323 return (long) double_value;
324 }
325 return 0;
326 }
327 }
328
329 return 0;
330 }
331
zephir_get_charval_ex(const zval * op)332 long zephir_get_charval_ex(const zval *op)
333 {
334 switch (Z_TYPE_P(op)) {
335 case IS_ARRAY:
336 case IS_CALLABLE:
337 case IS_RESOURCE:
338 case IS_OBJECT:
339 return 0;
340
341 case IS_LONG:
342 return Z_LVAL_P(op);
343
344 case IS_TRUE:
345 return 1;
346
347 case IS_FALSE:
348 return 0;
349
350 case IS_DOUBLE:
351 return (long) Z_DVAL_P(op);
352
353 case IS_STRING: {
354 if (Z_STRLEN_P(op) > 0) {
355 return Z_STRVAL_P(op)[0];
356 }
357 return 0;
358 }
359 }
360
361 return 0;
362 }
363
364 /**
365 * Returns the long value of a zval
366 */
zephir_get_doubleval_ex(const zval * op)367 double zephir_get_doubleval_ex(const zval *op)
368 {
369 int type;
370 zend_long long_value = 0;
371 double double_value = 0;
372
373 switch (Z_TYPE_P(op)) {
374
375 case IS_ARRAY:
376 return zend_hash_num_elements(Z_ARRVAL_P(op)) ? (double) 1 : 0;
377
378 case IS_CALLABLE:
379 case IS_RESOURCE:
380 case IS_OBJECT:
381 return (double) 1;
382
383 case IS_LONG:
384 return (double) Z_LVAL_P(op);
385
386 case IS_TRUE:
387 return (double) 1;
388
389 case IS_FALSE:
390 return (double) 0;
391
392 case IS_DOUBLE:
393 return Z_DVAL_P(op);
394
395 case IS_STRING:
396 if ((type = is_numeric_string(Z_STRVAL_P(op), Z_STRLEN_P(op), &long_value, &double_value, 0))) {
397 if (type == IS_LONG) {
398 return (double) long_value;
399 } else {
400 if (type == IS_DOUBLE) {
401 return double_value;
402 } else {
403 return 0;
404 }
405 }
406 }
407 }
408
409 return 0;
410 }
411
412 /**
413 * Returns the long value of a zval
414 */
zephir_get_boolval_ex(zval * op)415 zend_bool zephir_get_boolval_ex(zval *op)
416 {
417 return (zend_bool) zend_is_true(op);
418 }
419
420 /**
421 * Returns the long value of a zval
422 */
zephir_is_numeric_ex(const zval * op)423 int zephir_is_numeric_ex(const zval *op)
424 {
425 int type;
426
427 switch (Z_TYPE_P(op)) {
428
429 case IS_LONG:
430 return 1;
431
432 case IS_TRUE:
433 case IS_FALSE:
434 return 0;
435
436 case IS_DOUBLE:
437 return 1;
438
439 case IS_STRING:
440 if ((type = is_numeric_string(Z_STRVAL_P(op), Z_STRLEN_P(op), NULL, NULL, 0))) {
441 if (type == IS_LONG || type == IS_DOUBLE) {
442 return 1;
443 }
444 }
445 }
446
447 return 0;
448 }
449
450 /**
451 * Check if two zvals are equal
452 */
zephir_is_equal(zval * op1,zval * op2)453 int zephir_is_equal(zval *op1, zval *op2)
454 {
455 zval result;
456
457 is_equal_function(&result, op1, op2);
458 return Z_TYPE(result) == IS_TRUE;
459 }
460
461 /**
462 * Check if a zval is less than other
463 */
zephir_less(zval * op1,zval * op2)464 int zephir_less(zval *op1, zval *op2)
465 {
466 zval result;
467 is_smaller_function(&result, op1, op2);
468 return Z_TYPE(result) == IS_TRUE;
469 }
470
471 /**
472 * Check if a zval is greater than other
473 */
zephir_greater(zval * op1,zval * op2)474 int zephir_greater(zval *op1, zval *op2)
475 {
476 zval result;
477 is_smaller_or_equal_function(&result, op1, op2);
478 return Z_TYPE(result) == IS_FALSE;
479 }
480
481 /**
482 * Check if two zvals are identical
483 */
zephir_is_identical(zval * op1,zval * op2)484 int zephir_is_identical(zval *op1, zval *op2)
485 {
486 zval result;
487 is_identical_function(&result, op1, op2);
488 return Z_TYPE(result) == IS_TRUE;
489 }
490
491 /**
492 * Do bitwise_and function
493 */
zephir_bitwise_and_function(zval * result,zval * op1,zval * op2)494 int zephir_bitwise_and_function(zval *result, zval *op1, zval *op2)
495 {
496 int status;
497 status = bitwise_and_function(result, op1, op2);
498 return status;
499 }
500
501 /**
502 * Do bitwise_or function
503 */
zephir_bitwise_or_function(zval * result,zval * op1,zval * op2)504 int zephir_bitwise_or_function(zval *result, zval *op1, zval *op2)
505 {
506 int status;
507 status = bitwise_or_function(result, op1, op2);
508 return status;
509 }
510
511 /**
512 * Do bitwise_xor function
513 */
zephir_bitwise_xor_function(zval * result,zval * op1,zval * op2)514 int zephir_bitwise_xor_function(zval *result, zval *op1, zval *op2)
515 {
516 int status;
517 status = bitwise_xor_function(result, op1, op2);
518 return status;
519 }
520
521 /**
522 * Check if a zval is less/equal than other
523 */
zephir_less_equal(zval * op1,zval * op2)524 int zephir_less_equal(zval *op1, zval *op2)
525 {
526 zval result;
527 is_smaller_or_equal_function(&result, op1, op2);
528 return Z_TYPE(result) == IS_TRUE;
529 }
530
531 /**
532 * Check if a zval is less than a long value
533 */
zephir_less_long(zval * op1,long op2)534 int zephir_less_long(zval *op1, long op2)
535 {
536 zval result, op2_zval;
537 ZVAL_LONG(&op2_zval, op2);
538
539 is_smaller_function(&result, op1, &op2_zval);
540 return Z_TYPE(result) == IS_TRUE;
541 }
542
zephir_less_double(zval * op1,double op2)543 int zephir_less_double(zval *op1, double op2)
544 {
545 zval result, op2_zval;
546 ZVAL_DOUBLE(&op2_zval, op2);
547
548 is_smaller_function(&result, op1, &op2_zval);
549 return Z_TYPE(result) == IS_TRUE;
550 }
551
zephir_less_equal_long(zval * op1,long op2)552 int zephir_less_equal_long(zval *op1, long op2)
553 {
554 zval result, op2_zval;
555 ZVAL_LONG(&op2_zval, op2);
556
557 is_smaller_or_equal_function(&result, op1, &op2_zval);
558 return Z_TYPE(result) == IS_TRUE;
559 }
560
561 /**
562 * Check if a zval is greater than a long value
563 */
zephir_greater_long(zval * op1,long op2)564 int zephir_greater_long(zval *op1, long op2)
565 {
566 zval result, op2_zval;
567 ZVAL_LONG(&op2_zval, op2);
568
569 is_smaller_or_equal_function(&result, op1, &op2_zval);
570 return Z_TYPE(result) == IS_FALSE;
571 }
572
zephir_greater_double(zval * op1,double op2)573 int zephir_greater_double(zval *op1, double op2)
574 {
575 zval result, op2_zval;
576 ZVAL_DOUBLE(&op2_zval, op2);
577
578 is_smaller_or_equal_function(&result, op1, &op2_zval);
579 return Z_TYPE(result) == IS_FALSE;
580 }
581
582 /**
583 * Check if a zval is greater/equal than other
584 */
zephir_greater_equal(zval * op1,zval * op2)585 int zephir_greater_equal(zval *op1, zval *op2)
586 {
587 zval result;
588 is_smaller_function(&result, op1, op2);
589 return Z_TYPE(result) == IS_FALSE;
590 }
591
592 /**
593 * Check for greater/equal
594 */
zephir_greater_equal_long(zval * op1,long op2)595 int zephir_greater_equal_long(zval *op1, long op2)
596 {
597 zval result, op2_zval;
598 ZVAL_LONG(&op2_zval, op2);
599 is_smaller_function(&result, op1, &op2_zval);
600 return Z_TYPE(result) == IS_FALSE;
601 }
602
603 /**
604 * Do safe divisions between two longs
605 */
zephir_safe_div_long_long(long op1,long op2)606 double zephir_safe_div_long_long(long op1, long op2)
607 {
608 if (!op2) {
609 zend_error(E_WARNING, "Division by zero");
610 return 0;
611 }
612 return (double) op1 / (double) op2;
613 }
614
615 /**
616 * Do safe divisions between two long/double
617 */
zephir_safe_div_long_double(long op1,double op2)618 double zephir_safe_div_long_double(long op1, double op2)
619 {
620 if (!op2) {
621 zend_error(E_WARNING, "Division by zero");
622 return 0;
623 }
624 return (double) op1 / op2;
625 }
626
627 /**
628 * Do safe divisions between two double/zval
629 */
zephir_safe_div_double_zval(double op1,zval * op2)630 double zephir_safe_div_double_zval(double op1, zval *op2)
631 {
632 if (!zephir_get_numberval(op2)) {
633 zend_error(E_WARNING, "Division by zero");
634 return 0;
635 }
636 switch (Z_TYPE_P(op2)) {
637 case IS_ARRAY:
638 case IS_OBJECT:
639 case IS_RESOURCE:
640 zend_error(E_WARNING, "Unsupported operand types");
641 break;
642 }
643 return op1 / ((double) zephir_get_numberval(op2));
644 }
645
646 /**
647 * Do safe divisions between two double/long
648 */
zephir_safe_div_double_long(double op1,long op2)649 double zephir_safe_div_double_long(double op1, long op2)
650 {
651 if (!op2) {
652 zend_error(E_WARNING, "Division by zero");
653 return 0;
654 }
655 return op1 / (double) op2;
656 }
657
658 /**
659 * Do safe divisions between two doubles
660 */
zephir_safe_div_double_double(double op1,double op2)661 double zephir_safe_div_double_double(double op1, double op2)
662 {
663 if (!op2) {
664 zend_error(E_WARNING, "Division by zero");
665 return 0;
666 }
667 return op1 / op2;
668 }
669
670 /**
671 * Do safe divisions between two zval/long
672 */
zephir_safe_div_zval_long(zval * op1,long op2)673 double zephir_safe_div_zval_long(zval *op1, long op2)
674 {
675 if (!op2) {
676 zend_error(E_WARNING, "Division by zero");
677 return 0;
678 }
679 switch (Z_TYPE_P(op1)) {
680 case IS_ARRAY:
681 case IS_OBJECT:
682 case IS_RESOURCE:
683 zend_error(E_WARNING, "Unsupported operand types");
684 break;
685 }
686 return ((double) zephir_get_numberval(op1)) / (double) op2;
687 }
688
689 /**
690 * Do safe divisions between two long/zval
691 */
zephir_safe_div_long_zval(long op1,zval * op2)692 double zephir_safe_div_long_zval(long op1, zval *op2)
693 {
694 if (!zephir_get_numberval(op2)) {
695 zend_error(E_WARNING, "Division by zero");
696 return 0;
697 }
698 switch (Z_TYPE_P(op2)) {
699 case IS_ARRAY:
700 case IS_OBJECT:
701 case IS_RESOURCE:
702 zend_error(E_WARNING, "Unsupported operand types");
703 break;
704 }
705 return (double) op1 / ((double) zephir_get_numberval(op2));
706 }
707
708 /**
709 * Do safe divisions between two zval/double
710 */
zephir_safe_div_zval_double(zval * op1,double op2)711 double zephir_safe_div_zval_double(zval *op1, double op2)
712 {
713 if (!op2) {
714 zend_error(E_WARNING, "Division by zero");
715 return 0;
716 }
717 switch (Z_TYPE_P(op1)) {
718 case IS_ARRAY:
719 case IS_OBJECT:
720 case IS_RESOURCE:
721 zend_error(E_WARNING, "Unsupported operand types");
722 break;
723 }
724 return ((double) zephir_get_numberval(op1)) / op2;
725 }
726
727 /**
728 * Do safe divisions between two longs
729 */
zephir_safe_mod_long_long(long op1,long op2)730 long zephir_safe_mod_long_long(long op1, long op2)
731 {
732 if (!op2) {
733 zend_error(E_WARNING, "Division by zero");
734 return 0;
735 }
736 return op1 % op2;
737 }
738
739 /**
740 * Do safe divisions between two zval/long
741 */
zephir_safe_mod_zval_long(zval * op1,long op2)742 long zephir_safe_mod_zval_long(zval *op1, long op2)
743 {
744 if (!op2) {
745 zend_error(E_WARNING, "Division by zero");
746 return 0;
747 }
748 switch (Z_TYPE_P(op1)) {
749 case IS_ARRAY:
750 case IS_OBJECT:
751 case IS_RESOURCE:
752 zend_error(E_WARNING, "Unsupported operand types");
753 break;
754 }
755 return ((long) zephir_get_numberval(op1)) % (long) op2;
756 }
757