1 : /*
2 : +----------------------------------------------------------------------+
3 : | Zend Engine |
4 : +----------------------------------------------------------------------+
5 : | Copyright (c) 1998-2009 Zend Technologies Ltd. (http://www.zend.com) |
6 : +----------------------------------------------------------------------+
7 : | This source file is subject to version 2.00 of the Zend license, |
8 : | that is bundled with this package in the file LICENSE, and is |
9 : | available through the world-wide-web at the following url: |
10 : | http://www.zend.com/license/2_00.txt. |
11 : | If you did not receive a copy of the Zend license and are unable to |
12 : | obtain it through the world-wide-web, please send a note to |
13 : | license@zend.com so we can mail you a copy immediately. |
14 : +----------------------------------------------------------------------+
15 : | Authors: Andi Gutmans <andi@zend.com> |
16 : | Zeev Suraski <zeev@zend.com> |
17 : +----------------------------------------------------------------------+
18 : */
19 :
20 : /* $Id: zend_operators.c 281669 2009-06-04 18:18:47Z mattwil $ */
21 :
22 : #include <ctype.h>
23 :
24 : #include "zend.h"
25 : #include "zend_operators.h"
26 : #include "zend_variables.h"
27 : #include "zend_globals.h"
28 : #include "zend_list.h"
29 : #include "zend_API.h"
30 : #include "zend_multiply.h"
31 : #include "zend_strtod.h"
32 : #include "zend_exceptions.h"
33 :
34 : #include "unicode/uchar.h"
35 : #include "unicode/ucol.h"
36 :
37 : #define LONG_SIGN_MASK (1L << (8*sizeof(long)-1))
38 :
39 : #if ZEND_USE_TOLOWER_L
40 : #include <locale.h>
41 : static _locale_t current_locale = NULL;
42 : /* this is true global! may lead to strange effects on ZTS, but so may setlocale() */
43 : #define zend_tolower(c) _tolower_l(c, current_locale)
44 : #else
45 : #define zend_tolower(c) tolower(c)
46 : #endif
47 :
48 : #define TYPE_PAIR(t1,t2) (((t1) << 4) | (t2))
49 :
50 : ZEND_API int zend_atoi(const char *str, int str_len) /* {{{ */
51 51031 : {
52 : int retval;
53 :
54 51031 : if (!str_len) {
55 33819 : str_len = strlen(str);
56 : }
57 51031 : retval = strtol(str, NULL, 0);
58 51031 : if (str_len>0) {
59 34213 : switch (str[str_len-1]) {
60 : case 'g':
61 : case 'G':
62 0 : retval *= 1024;
63 : /* break intentionally missing */
64 : case 'm':
65 : case 'M':
66 0 : retval *= 1024;
67 : /* break intentionally missing */
68 : case 'k':
69 : case 'K':
70 0 : retval *= 1024;
71 : break;
72 : }
73 : }
74 51031 : return retval;
75 : }
76 : /* }}} */
77 :
78 : ZEND_API long zend_atol(const char *str, int str_len) /* {{{ */
79 1037672 : {
80 : long retval;
81 :
82 1037672 : if (!str_len) {
83 33711 : str_len = strlen(str);
84 : }
85 1037672 : retval = strtol(str, NULL, 0);
86 1037672 : if (str_len>0) {
87 1003961 : switch (str[str_len-1]) {
88 : case 'g':
89 : case 'G':
90 4 : retval *= 1024;
91 : /* break intentionally missing */
92 : case 'm':
93 : case 'M':
94 50986 : retval *= 1024;
95 : /* break intentionally missing */
96 : case 'k':
97 : case 'K':
98 67994 : retval *= 1024;
99 : break;
100 : }
101 : }
102 1037672 : return retval;
103 : }
104 : /* }}} */
105 :
106 : ZEND_API double zend_string_to_double(const char *number, zend_uint length) /* {{{ */
107 0 : {
108 0 : double divisor = 10.0;
109 0 : double result = 0.0;
110 : double exponent;
111 0 : const char *end = number+length;
112 0 : const char *digit = number;
113 :
114 0 : if (!length) {
115 0 : return result;
116 : }
117 :
118 0 : while (digit < end) {
119 0 : if ((*digit <= '9' && *digit >= '0')) {
120 0 : result *= 10;
121 0 : result += *digit - '0';
122 0 : } else if (*digit == '.') {
123 0 : digit++;
124 0 : break;
125 0 : } else if (toupper(*digit) == 'E') {
126 0 : exponent = (double) atoi(digit+1);
127 0 : result *= pow(10.0, exponent);
128 0 : return result;
129 : } else {
130 0 : return result;
131 : }
132 0 : digit++;
133 : }
134 :
135 0 : while (digit < end) {
136 0 : if ((*digit <= '9' && *digit >= '0')) {
137 0 : result += (*digit - '0') / divisor;
138 0 : divisor *= 10;
139 0 : } else if (toupper(*digit) == 'E') {
140 0 : exponent = (double) atoi(digit+1);
141 0 : result *= pow(10.0, exponent);
142 0 : return result;
143 : } else {
144 0 : return result;
145 : }
146 0 : digit++;
147 : }
148 0 : return result;
149 : }
150 : /* }}} */
151 :
152 : ZEND_API int convert_scalar_to_number(zval *op TSRMLS_DC) /* {{{ */
153 208102 : {
154 208102 : switch (Z_TYPE_P(op)) {
155 : case IS_STRING:
156 : {
157 : char *strval;
158 :
159 7 : strval = Z_STRVAL_P(op);
160 7 : switch ((Z_TYPE_P(op)=is_numeric_string(strval, Z_STRLEN_P(op), &Z_LVAL_P(op), &Z_DVAL_P(op), 1))) {
161 : case IS_DOUBLE:
162 : case IS_LONG:
163 7 : break;
164 : default:
165 0 : Z_LVAL_P(op) = strtol(Z_STRVAL_P(op), NULL, 10);
166 0 : Z_TYPE_P(op) = IS_LONG;
167 : break;
168 : }
169 7 : STR_FREE(strval);
170 7 : break;
171 : }
172 : case IS_UNICODE:
173 : {
174 : UChar *strval;
175 :
176 101159 : strval = Z_USTRVAL_P(op);
177 101159 : switch ((Z_TYPE_P(op)=is_numeric_unicode(strval, Z_USTRLEN_P(op), &Z_LVAL_P(op), &Z_DVAL_P(op), 1))) {
178 : case IS_DOUBLE:
179 : case IS_LONG:
180 101111 : break;
181 : default:
182 48 : Z_LVAL_P(op) = zend_u_strtol(Z_USTRVAL_P(op), NULL, 10);
183 48 : Z_TYPE_P(op) = IS_LONG;
184 : break;
185 : }
186 101159 : USTR_FREE(strval);
187 101159 : break;
188 : }
189 : break;
190 : case IS_BOOL:
191 39 : Z_TYPE_P(op) = IS_LONG;
192 39 : break;
193 : case IS_RESOURCE:
194 7 : zend_list_delete(Z_LVAL_P(op));
195 7 : Z_TYPE_P(op) = IS_LONG;
196 7 : break;
197 : case IS_OBJECT:
198 6 : convert_to_long_base(op, 10);
199 6 : break;
200 : case IS_NULL:
201 50 : ZVAL_LONG(op, 0);
202 : break;
203 : }
204 :
205 208102 : return SUCCESS;
206 : }
207 : /* }}} */
208 :
209 : /* {{{ zendi_convert_scalar_to_number */
210 : #define zendi_convert_scalar_to_number(op, holder, result) \
211 : if (op==result) { \
212 : if (Z_TYPE_P(op) != IS_LONG) { \
213 : convert_scalar_to_number(op TSRMLS_CC); \
214 : } \
215 : } else { \
216 : switch (Z_TYPE_P(op)) { \
217 : case IS_STRING: \
218 : { \
219 : switch ((Z_TYPE(holder)=is_numeric_string(Z_STRVAL_P(op), Z_STRLEN_P(op), &Z_LVAL(holder), &Z_DVAL(holder), 1))) { \
220 : case IS_DOUBLE: \
221 : case IS_LONG: \
222 : break; \
223 : default: \
224 : Z_LVAL(holder) = strtol(Z_STRVAL_P(op), NULL, 10); \
225 : Z_TYPE(holder) = IS_LONG; \
226 : break; \
227 : } \
228 : (op) = &(holder); \
229 : break; \
230 : } \
231 : case IS_UNICODE: \
232 : { \
233 : switch ((Z_TYPE(holder)=is_numeric_unicode(Z_USTRVAL_P(op), Z_USTRLEN_P(op), &Z_LVAL(holder), &Z_DVAL(holder), 1))) { \
234 : case IS_DOUBLE: \
235 : case IS_LONG: \
236 : break; \
237 : default: \
238 : Z_LVAL(holder) = zend_u_strtol(Z_USTRVAL_P(op), NULL, 10); \
239 : Z_TYPE(holder) = IS_LONG; \
240 : break; \
241 : } \
242 : (op) = &(holder); \
243 : break; \
244 : } \
245 : case IS_BOOL: \
246 : case IS_RESOURCE: \
247 : ZVAL_LONG(&(holder), Z_LVAL_P(op)); \
248 : (op) = &(holder); \
249 : break; \
250 : case IS_NULL: \
251 : ZVAL_LONG(&(holder), 0); \
252 : (op) = &(holder); \
253 : break; \
254 : case IS_OBJECT: \
255 : (holder) = (*(op)); \
256 : zval_copy_ctor(&(holder)); \
257 : convert_to_long_base(&(holder), 10); \
258 : if (Z_TYPE(holder) == IS_LONG) { \
259 : (op) = &(holder); \
260 : } \
261 : break; \
262 : } \
263 : }
264 :
265 : /* }}} */
266 :
267 : /* {{{ zendi_convert_to_long */
268 : #define zendi_convert_to_long(op, holder, result) \
269 : if (op == result) { \
270 : convert_to_long(op); \
271 : } else if (Z_TYPE_P(op) != IS_LONG) { \
272 : switch (Z_TYPE_P(op)) { \
273 : case IS_NULL: \
274 : Z_LVAL(holder) = 0; \
275 : break; \
276 : case IS_DOUBLE: \
277 : Z_LVAL(holder) = zend_dval_to_lval(Z_DVAL_P(op)); \
278 : break; \
279 : case IS_STRING: \
280 : Z_LVAL(holder) = strtol(Z_STRVAL_P(op), NULL, 10); \
281 : break; \
282 : case IS_UNICODE: \
283 : Z_LVAL(holder) = zend_u_strtol(Z_USTRVAL_P(op), NULL, 10); \
284 : break; \
285 : case IS_ARRAY: \
286 : Z_LVAL(holder) = (zend_hash_num_elements(Z_ARRVAL_P(op))?1:0); \
287 : break; \
288 : case IS_OBJECT: \
289 : (holder) = (*(op)); \
290 : zval_copy_ctor(&(holder)); \
291 : convert_to_long_base(&(holder), 10); \
292 : break; \
293 : case IS_BOOL: \
294 : case IS_RESOURCE: \
295 : Z_LVAL(holder) = Z_LVAL_P(op); \
296 : break; \
297 : default: \
298 : zend_error(E_WARNING, "Cannot convert to ordinal value"); \
299 : Z_LVAL(holder) = 0; \
300 : break; \
301 : } \
302 : Z_TYPE(holder) = IS_LONG; \
303 : (op) = &(holder); \
304 : }
305 :
306 : /* }}} */
307 :
308 : /* {{{ zendi_convert_to_boolean */
309 : #define zendi_convert_to_boolean(op, holder, result) \
310 : if (op==result) { \
311 : convert_to_boolean(op); \
312 : } else if (Z_TYPE_P(op) != IS_BOOL) { \
313 : switch (Z_TYPE_P(op)) { \
314 : case IS_NULL: \
315 : Z_LVAL(holder) = 0; \
316 : break; \
317 : case IS_RESOURCE: \
318 : case IS_LONG: \
319 : Z_LVAL(holder) = (Z_LVAL_P(op) ? 1 : 0); \
320 : break; \
321 : case IS_DOUBLE: \
322 : Z_LVAL(holder) = (Z_DVAL_P(op) ? 1 : 0); \
323 : break; \
324 : case IS_STRING: \
325 : if (Z_STRLEN_P(op) == 0 \
326 : || (Z_STRLEN_P(op)==1 && Z_STRVAL_P(op)[0]=='0')) { \
327 : Z_LVAL(holder) = 0; \
328 : } else { \
329 : Z_LVAL(holder) = 1; \
330 : } \
331 : break; \
332 : case IS_UNICODE: \
333 : if (Z_USTRLEN_P(op) == 0 \
334 : || (Z_USTRLEN_P(op)==1 && \
335 : (Z_USTRVAL_P(op)[0]=='0'))) { \
336 : Z_LVAL(holder) = 0; \
337 : } else { \
338 : Z_LVAL(holder) = 1; \
339 : } \
340 : break; \
341 : case IS_ARRAY: \
342 : Z_LVAL(holder) = (zend_hash_num_elements(Z_ARRVAL_P(op))?1:0); \
343 : break; \
344 : case IS_OBJECT: \
345 : (holder) = (*(op)); \
346 : zval_copy_ctor(&(holder)); \
347 : convert_to_boolean(&(holder)); \
348 : break; \
349 : default: \
350 : Z_LVAL(holder) = 0; \
351 : break; \
352 : } \
353 : Z_TYPE(holder) = IS_BOOL; \
354 : (op) = &(holder); \
355 : }
356 :
357 : /* }}} */
358 :
359 : /* {{{ convert_object_to_type */
360 : #define convert_object_to_type(op, ctype, conv_func) \
361 : if (Z_OBJ_HT_P(op)->cast_object) { \
362 : zval dst; \
363 : if (Z_OBJ_HT_P(op)->cast_object(op, &dst, ctype, NULL TSRMLS_CC) == FAILURE) { \
364 : zend_error(E_RECOVERABLE_ERROR, \
365 : "Object of class %v could not be converted to %s", Z_OBJCE_P(op)->name, \
366 : zend_get_type_by_const(ctype)); \
367 : } else { \
368 : zval_dtor(op); \
369 : Z_TYPE_P(op) = ctype; \
370 : op->value = dst.value; \
371 : retval = SUCCESS; \
372 : } \
373 : } else { \
374 : if (Z_OBJ_HT_P(op)->get) { \
375 : zval *newop = Z_OBJ_HT_P(op)->get(op TSRMLS_CC); \
376 : if (Z_TYPE_P(newop) != IS_OBJECT) { \
377 : /* for safety - avoid loop */ \
378 : zval_dtor(op); \
379 : *op = *newop; \
380 : FREE_ZVAL(newop); \
381 : retval = conv_func(op); \
382 : } \
383 : } \
384 : }
385 :
386 : /* }}} */
387 :
388 : ZEND_API int convert_to_long(zval *op) /* {{{ */
389 975593 : {
390 975593 : return convert_to_long_base(op, 10);
391 : }
392 : /* }}} */
393 :
394 : ZEND_API int convert_to_long_base(zval *op, int base) /* {{{ */
395 979421 : {
396 : long tmp;
397 :
398 979421 : switch (Z_TYPE_P(op)) {
399 : case IS_NULL:
400 1125 : Z_LVAL_P(op) = 0;
401 1125 : break;
402 : case IS_RESOURCE: {
403 : TSRMLS_FETCH();
404 :
405 116 : zend_list_delete(Z_LVAL_P(op));
406 : }
407 : /* break missing intentionally */
408 : case IS_BOOL:
409 : case IS_LONG:
410 930795 : break;
411 : case IS_DOUBLE:
412 9097 : Z_LVAL_P(op) = zend_dval_to_lval(Z_DVAL_P(op));
413 9097 : break;
414 : case IS_STRING:
415 : {
416 33898 : char *strval = Z_STRVAL_P(op);
417 :
418 33898 : Z_LVAL_P(op) = strtol(strval, NULL, base);
419 33898 : STR_FREE(strval);
420 : }
421 33898 : break;
422 : case IS_UNICODE:
423 : {
424 3590 : UChar *strval = Z_USTRVAL_P(op);
425 3590 : Z_LVAL_P(op) = zend_u_strtol(strval, NULL, base);
426 3590 : USTR_FREE(strval);
427 : }
428 3590 : break;
429 : case IS_ARRAY:
430 863 : tmp = (zend_hash_num_elements(Z_ARRVAL_P(op))?1:0);
431 863 : zval_dtor(op);
432 863 : Z_LVAL_P(op) = tmp;
433 863 : break;
434 : case IS_OBJECT:
435 : {
436 53 : int retval = 1;
437 : TSRMLS_FETCH();
438 :
439 53 : convert_object_to_type(op, IS_LONG, convert_to_long);
440 :
441 53 : if (Z_TYPE_P(op) == IS_LONG) {
442 53 : return SUCCESS;
443 : }
444 :
445 0 : zend_error(E_NOTICE, "Object of class %v could not be converted to int", Z_OBJCE_P(op)->name);
446 :
447 0 : zval_dtor(op);
448 0 : ZVAL_LONG(op, retval);
449 0 : return FAILURE;
450 : }
451 : default:
452 0 : zend_error(E_WARNING, "Cannot convert to ordinal value");
453 0 : zval_dtor(op);
454 0 : Z_LVAL_P(op) = 0;
455 0 : return FAILURE;
456 : }
457 :
458 979368 : Z_TYPE_P(op) = IS_LONG;
459 979368 : return SUCCESS;
460 : }
461 : /* }}} */
462 :
463 : ZEND_API int convert_to_double(zval *op) /* {{{ */
464 332312 : {
465 : double tmp;
466 :
467 332312 : switch (Z_TYPE_P(op)) {
468 : case IS_NULL:
469 319 : Z_DVAL_P(op) = 0.0;
470 319 : break;
471 : case IS_RESOURCE: {
472 : TSRMLS_FETCH();
473 :
474 48 : zend_list_delete(Z_LVAL_P(op));
475 : }
476 : /* break missing intentionally */
477 : case IS_BOOL:
478 : case IS_LONG:
479 258289 : Z_DVAL_P(op) = (double) Z_LVAL_P(op);
480 258289 : break;
481 : case IS_DOUBLE:
482 72547 : break;
483 : case IS_STRING:
484 : {
485 26 : char *strval = Z_STRVAL_P(op);
486 :
487 26 : Z_DVAL_P(op) = zend_strtod(strval, NULL);
488 26 : STR_FREE(strval);
489 : }
490 26 : break;
491 : case IS_UNICODE:
492 : {
493 742 : UChar *strval = Z_USTRVAL_P(op);
494 :
495 742 : Z_DVAL_P(op) = zend_u_strtod(strval, NULL);
496 742 : USTR_FREE(strval);
497 : }
498 742 : break;
499 : case IS_ARRAY:
500 369 : tmp = (zend_hash_num_elements(Z_ARRVAL_P(op))?1:0);
501 369 : zval_dtor(op);
502 369 : Z_DVAL_P(op) = tmp;
503 369 : break;
504 : case IS_OBJECT:
505 : {
506 20 : double retval = 1.0;
507 : TSRMLS_FETCH();
508 :
509 20 : convert_object_to_type(op, IS_DOUBLE, convert_to_double);
510 :
511 20 : if (Z_TYPE_P(op) == IS_DOUBLE) {
512 20 : return SUCCESS;
513 : }
514 :
515 0 : zend_error(E_NOTICE, "Object of class %v could not be converted to double", Z_OBJCE_P(op)->name);
516 :
517 0 : zval_dtor(op);
518 0 : ZVAL_DOUBLE(op, retval);
519 0 : return FAILURE;
520 : }
521 : default:
522 0 : zend_error(E_WARNING, "Cannot convert to real value (type=%d)", Z_TYPE_P(op));
523 0 : zval_dtor(op);
524 0 : Z_DVAL_P(op) = 0;
525 0 : return FAILURE;
526 : }
527 :
528 332292 : Z_TYPE_P(op) = IS_DOUBLE;
529 332292 : return SUCCESS;
530 : }
531 : /* }}} */
532 :
533 : ZEND_API int convert_to_null(zval *op) /* {{{ */
534 1106 : {
535 1106 : if (Z_TYPE_P(op) == IS_OBJECT) {
536 6 : if (Z_OBJ_HT_P(op)->cast_object) {
537 : zval *org;
538 : TSRMLS_FETCH();
539 :
540 6 : ALLOC_ZVAL(org);
541 6 : *org = *op;
542 6 : if (Z_OBJ_HT_P(op)->cast_object(org, op, IS_NULL, NULL TSRMLS_CC) == SUCCESS) {
543 0 : zval_dtor(org);
544 0 : return SUCCESS;
545 : }
546 6 : *op = *org;
547 6 : FREE_ZVAL(org);
548 : }
549 : }
550 :
551 1106 : zval_dtor(op);
552 1106 : Z_TYPE_P(op) = IS_NULL;
553 1106 : return SUCCESS;
554 : }
555 : /* }}} */
556 :
557 : ZEND_API int convert_to_boolean(zval *op) /* {{{ */
558 80535 : {
559 : int tmp;
560 :
561 80535 : switch (Z_TYPE_P(op)) {
562 : case IS_BOOL:
563 3478 : break;
564 : case IS_NULL:
565 101 : Z_LVAL_P(op) = 0;
566 101 : break;
567 : case IS_RESOURCE: {
568 : TSRMLS_FETCH();
569 :
570 8 : zend_list_delete(Z_LVAL_P(op));
571 : }
572 : /* break missing intentionally */
573 : case IS_LONG:
574 533 : Z_LVAL_P(op) = (Z_LVAL_P(op) ? 1 : 0);
575 533 : break;
576 : case IS_DOUBLE:
577 161 : Z_LVAL_P(op) = (Z_DVAL_P(op) ? 1 : 0);
578 161 : break;
579 : case IS_STRING:
580 : {
581 36 : char *strval = Z_STRVAL_P(op);
582 :
583 40 : if (Z_STRLEN_P(op) == 0
584 : || (Z_STRLEN_P(op)==1 && Z_STRVAL_P(op)[0]=='0')) {
585 4 : Z_LVAL_P(op) = 0;
586 : } else {
587 32 : Z_LVAL_P(op) = 1;
588 : }
589 36 : STR_FREE(strval);
590 : }
591 36 : break;
592 : case IS_UNICODE:
593 : {
594 213 : UChar *strval = Z_USTRVAL_P(op);
595 :
596 270 : if (Z_USTRLEN_P(op) == 0
597 : || (Z_USTRLEN_P(op)==1 && Z_USTRVAL_P(op)[0]=='0')) {
598 57 : Z_LVAL_P(op) = 0;
599 : } else {
600 156 : Z_LVAL_P(op) = 1;
601 : }
602 213 : USTR_FREE(strval);
603 : }
604 213 : break;
605 : case IS_ARRAY:
606 20 : tmp = (zend_hash_num_elements(Z_ARRVAL_P(op))?1:0);
607 20 : zval_dtor(op);
608 20 : Z_LVAL_P(op) = tmp;
609 20 : break;
610 : case IS_OBJECT:
611 : {
612 75993 : zend_bool retval = 1;
613 : TSRMLS_FETCH();
614 :
615 75993 : convert_object_to_type(op, IS_BOOL, convert_to_boolean);
616 :
617 75993 : if (Z_TYPE_P(op) == IS_BOOL) {
618 75993 : return SUCCESS;
619 : }
620 :
621 0 : zval_dtor(op);
622 0 : ZVAL_BOOL(op, retval);
623 0 : return FAILURE;
624 : }
625 : default:
626 0 : zval_dtor(op);
627 0 : Z_LVAL_P(op) = 0;
628 : break;
629 : }
630 :
631 4542 : Z_TYPE_P(op) = IS_BOOL;
632 4542 : return SUCCESS;
633 : }
634 : /* }}} */
635 :
636 : #define NUM_BUF_SIZE 512
637 :
638 : /* rewrite of ap_php_conv_10 for UChar support */
639 : static UChar* zend_u_format_long(long lnum, UChar *result_end, int *result_len) /* {{{ */
640 1557757 : {
641 1557757 : UChar *p = result_end;
642 : unsigned long magnitude;
643 :
644 1557757 : *--p = 0;
645 :
646 1557757 : if (lnum < 0) {
647 2015 : long t = lnum + 1;
648 2015 : magnitude = ((unsigned long) - t) + 1;
649 : } else {
650 1555742 : magnitude = (unsigned long) lnum;
651 : }
652 :
653 : do {
654 3931586 : unsigned long new_magnitude = magnitude / 10;
655 :
656 3931586 : *--p = (UChar)(magnitude - new_magnitude * 10 + 0x30 /*'0'*/);
657 3931586 : magnitude = new_magnitude;
658 : }
659 3931586 : while (magnitude);
660 :
661 1557757 : if (lnum < 0) {
662 2015 : *--p = (UChar) 0x2d /*'-'*/;
663 : }
664 :
665 1557757 : *result_len = result_end - p - 1;
666 1557757 : return p;
667 : }
668 : /* }}} */
669 :
670 : #define NDIG 320
671 :
672 : /* rewrite of ap_php_cvt for UChar support */
673 : static UChar* zend_u_format_double(double arg, int ndigits, int *decpt, int *sign, int eflag, UChar *buf) /* {{{ */
674 15490 : {
675 : register int r2;
676 : int mvl;
677 : double fi, fj;
678 : register UChar *p, *p1;
679 :
680 15490 : if (ndigits >= NDIG - 1)
681 0 : ndigits = NDIG - 2;
682 15490 : r2 = 0;
683 15490 : *sign = 0;
684 15490 : p = &buf[0];
685 15490 : if (arg < 0) {
686 729 : *sign = 1;
687 729 : arg = -arg;
688 : }
689 15490 : arg = modf(arg, &fi);
690 15490 : p1 = &buf[NDIG];
691 : /*
692 : * Do integer part
693 : */
694 15490 : if (fi != 0) {
695 54613 : while (fi != 0) {
696 28667 : fj = modf(fi / 10, &fi);
697 28667 : if (p1 <= &buf[0]) {
698 0 : mvl = NDIG - ndigits;
699 0 : if (ndigits > 0) {
700 0 : memmove(&buf[mvl], &buf[0], (NDIG-mvl-1) * sizeof(UChar));
701 : }
702 0 : p1 += mvl;
703 : }
704 28667 : *--p1 = (UChar) ((fj + .03) * 10) + 0x30 /*'0'*/;
705 28667 : r2++;
706 : }
707 54613 : while (p1 < &buf[NDIG]) {
708 28667 : *p++ = *p1++;
709 : }
710 2517 : } else if (arg > 0) {
711 8265 : while ((fj = arg * 10) < 1) {
712 3363 : if (!eflag && (r2 * -1) < ndigits) {
713 0 : break;
714 : }
715 3363 : arg = fj;
716 3363 : r2--;
717 : }
718 : }
719 15490 : p1 = &buf[ndigits];
720 15490 : if (eflag == 0)
721 0 : p1 += r2;
722 15490 : *decpt = r2;
723 15490 : if (p1 < &buf[0]) {
724 0 : buf[0] = 0;
725 0 : return (buf);
726 : }
727 15490 : if (p <= p1 && p < &buf[NDIG]) {
728 15456 : arg = modf(arg * 10, &fj);
729 15456 : if ((int)fj==10) {
730 0 : *p++ = (UChar) 0x31 /*'1'*/;
731 0 : fj = 0;
732 0 : *decpt = ++r2;
733 : }
734 235182 : while (p <= p1 && p < &buf[NDIG]) {
735 204270 : *p++ = (UChar) fj + 0x30 /*'0'*/;
736 204270 : arg = modf(arg * 10, &fj);
737 : }
738 : }
739 15490 : if (p1 >= &buf[NDIG]) {
740 0 : buf[NDIG - 1] = 0;
741 0 : return (buf);
742 : }
743 15490 : p = p1;
744 15490 : *p1 += 5;
745 46271 : while (*p1 > (UChar) 0x39 /*'9'*/) {
746 15291 : *p1 = (UChar) 0x30 /*'0'*/;
747 15291 : if (p1 > buf)
748 15286 : ++ * --p1;
749 : else {
750 5 : *p1 = (UChar) 0x31 /*'1'*/;
751 5 : (*decpt)++;
752 5 : if (eflag == 0) {
753 0 : if (p > buf)
754 0 : *p = (UChar) 0x30 /*'0'*/;
755 0 : p++;
756 : }
757 : }
758 : }
759 15490 : *p = 0;
760 15490 : return (buf);
761 : }
762 : /* }}} */
763 :
764 : /* rewrite of ap_php_gcvt for UChar support */
765 : static UChar* zend_u_format_gdouble(double dnum, int ndigit, UChar *result) /* {{{ */
766 18497 : {
767 : int sign, decpt;
768 : register UChar *p1, *p2;
769 : register int i;
770 : UChar buf1[NDIG];
771 : static zend_bool did_string_init = FALSE;
772 : U_STRING_DECL(u_nan, "NAN", 3);
773 : U_STRING_DECL(u_inf, "INF", 3);
774 : U_STRING_DECL(u_ninf, "-INF", 4);
775 :
776 18497 : if (!did_string_init) {
777 321 : U_STRING_INIT(u_nan, "NAN", 3);
778 321 : U_STRING_INIT(u_inf, "INF", 3);
779 321 : U_STRING_INIT(u_ninf, "-INF", 4);
780 321 : did_string_init = TRUE;
781 : }
782 :
783 : /* check for out-of-bounds numbers */
784 18497 : if (zend_isnan(dnum)) {
785 1498 : u_memcpy(result, u_nan, 3);
786 1498 : result[3] = 0;
787 1498 : return result;
788 16999 : } else if (zend_isinf(dnum)) {
789 1509 : if (dnum > 0) {
790 1509 : u_memcpy(result, u_inf, 3);
791 1509 : result[3] = 0;
792 : } else {
793 0 : u_memcpy(result, u_ninf, 3);
794 0 : result[4] = 0;
795 : }
796 1509 : return result;
797 : }
798 :
799 15490 : if (ndigit >= NDIG - 1) {
800 0 : ndigit = NDIG - 2;
801 : }
802 :
803 15490 : p1 = zend_u_format_double(dnum, ndigit, &decpt, &sign, 1, buf1);
804 15490 : p2 = result;
805 :
806 15490 : if (sign) {
807 729 : *p2++ = (UChar) 0x2d /*'-'*/;
808 : }
809 : /* if decimal point position is less than precision, cut zeros only in fractional part */
810 15490 : if (decpt <= ndigit) {
811 15456 : i = ndigit - 1;
812 80056 : while (i > 0 && i >= decpt && p1[i] == (UChar) 0x30 /*'0'*/) {
813 49144 : ndigit--;
814 49144 : i--;
815 : }
816 : } else {
817 : /* otherwise cut all trailing zeros */
818 212 : for (i = ndigit - 1; i > 0 && p1[i] == (UChar) 0x30 /*'0'*/; i--) {
819 178 : ndigit--;
820 : }
821 : }
822 :
823 15747 : if ((decpt >= 0 && decpt - ndigit > 4)
824 : || (decpt < 0 && decpt < -3)) { /* use E-style */
825 257 : decpt--;
826 257 : *p2++ = *p1++;
827 257 : *p2++ = (UChar) 0x2e /*'.'*/;
828 1912 : for (i = 1; i < ndigit; i++)
829 1655 : *p2++ = *p1++;
830 257 : if (*(p2 - 1) == (UChar) 0x2e /*'.'*/) {
831 31 : *p2++ = (UChar) 0x30 /*'0'*/;
832 : }
833 257 : *p2++ = (UChar) 0x45 /*'E'*/;
834 257 : if (decpt < 0) {
835 223 : decpt = -decpt;
836 223 : *p2++ = (UChar) 0x2d /*'-'*/;
837 : } else
838 34 : *p2++ = (UChar) 0x2b /*'+'*/;
839 257 : if (decpt / 100 > 0)
840 5 : *p2++ = (UChar) (decpt / 100 + 0x30 /*'0'*/);
841 257 : if (decpt / 10 > 0)
842 51 : *p2++ = (UChar) ((decpt % 100) / 10 + 0x30 /*'0'*/);
843 257 : *p2++ = (UChar) (decpt % 10 + 0x30 /*'0'*/);
844 : } else {
845 15233 : if (decpt <= 0) {
846 2294 : if (*p1 != (UChar) 0x30 /*'0'*/) {
847 2228 : *p2++ = (UChar) 0x30 /*'0'*/;
848 2228 : *p2++ = (UChar) 0x2e /*'.'*/;
849 : }
850 4666 : while (decpt < 0) {
851 78 : decpt++;
852 78 : *p2++ = (UChar) 0x30 /*'0'*/;
853 : }
854 : }
855 180771 : for (i = 1; i <= ndigit; i++) {
856 165538 : *p2++ = *p1++;
857 165538 : if (i == decpt)
858 12939 : *p2++ = (UChar) 0x2e /*'.'*/;
859 : }
860 15233 : if (ndigit < decpt) {
861 0 : while (ndigit++ < decpt)
862 0 : *p2++ = (UChar) 0x30 /*'0'*/;
863 0 : *p2++ = (UChar) 0x2e /*'.'*/;
864 : }
865 : }
866 15490 : if (p2[-1] == (UChar) 0x2e /*'.'*/)
867 1406 : p2--;
868 15490 : *p2 = 0;
869 15490 : return (result);
870 : }
871 : /* }}} */
872 :
873 : ZEND_API int _convert_to_unicode(zval *op TSRMLS_DC ZEND_FILE_LINE_DC) /* {{{ */
874 2217598 : {
875 2217598 : return _convert_to_unicode_with_converter(op, ZEND_U_CONVERTER(UG(runtime_encoding_conv)) TSRMLS_CC ZEND_FILE_LINE_CC);
876 : }
877 : /* }}} */
878 :
879 : ZEND_API int _convert_to_unicode_with_converter(zval *op, UConverter *conv TSRMLS_DC ZEND_FILE_LINE_DC) /* {{{ */
880 2419107 : {
881 2419107 : switch (Z_TYPE_P(op)) {
882 : case IS_NULL:
883 2781 : Z_USTRVAL_P(op) = USTR_MAKE_REL("");
884 2781 : Z_USTRLEN_P(op) = 0;
885 2781 : break;
886 : case IS_UNICODE:
887 528416 : break;
888 : case IS_STRING:
889 301258 : return zval_string_to_unicode_ex(op, conv TSRMLS_CC);
890 : case IS_BOOL:
891 9269 : if (Z_LVAL_P(op)) {
892 1415 : Z_USTRVAL_P(op) = USTR_MAKE_REL("1");
893 1415 : Z_USTRLEN_P(op) = 1;
894 : } else {
895 7854 : Z_USTRVAL_P(op) = USTR_MAKE_REL("");
896 7854 : Z_USTRLEN_P(op) = 0;
897 : }
898 9269 : break;
899 : case IS_RESOURCE: {
900 : UChar num_buf[NUM_BUF_SIZE], *result;
901 : int result_len, rstr_len;
902 5049 : long rval = Z_LVAL_P(op);
903 :
904 5049 : zend_list_delete(Z_LVAL_P(op));
905 5049 : result = zend_u_format_long(rval, &num_buf[NUM_BUF_SIZE], &result_len);
906 :
907 5049 : rstr_len = sizeof("Resource id #")-1;
908 5049 : Z_USTRLEN_P(op) = rstr_len + result_len;
909 5049 : Z_USTRVAL_P(op) = eumalloc_rel(Z_USTRLEN_P(op) + 1);
910 5049 : u_charsToUChars("Resource id #", Z_USTRVAL_P(op), rstr_len);
911 : /* result_len+1 takes care of terminating NULL */
912 5049 : u_memcpy(Z_USTRVAL_P(op) + rstr_len, result, result_len+1);
913 5049 : break;
914 : }
915 : case IS_LONG: {
916 : UChar num_buf[NUM_BUF_SIZE], *result;
917 : int result_len;
918 1552708 : long lval = Z_LVAL_P(op);
919 :
920 1552708 : result = zend_u_format_long(lval, &num_buf[NUM_BUF_SIZE], &result_len);
921 :
922 1552708 : Z_USTRVAL_P(op) = eustrndup(result, result_len);
923 1552708 : Z_USTRLEN_P(op) = result_len;
924 1552708 : break;
925 : }
926 : case IS_DOUBLE: {
927 : UChar num_buf[NUM_BUF_SIZE], *result;
928 18497 : double dval = Z_DVAL_P(op);
929 :
930 18497 : result = zend_u_format_gdouble(dval, (int) EG(precision), &num_buf[1]);
931 18497 : if (*result == (UChar) 0x2b /*'+'*/) {
932 0 : result++;
933 : }
934 18497 : Z_USTRLEN_P(op) = u_strlen(result);
935 18497 : Z_USTRVAL_P(op) = eustrndup(result, Z_USTRLEN_P(op));
936 18497 : break;
937 : }
938 : case IS_ARRAY:
939 1060 : zend_error(E_NOTICE, "Array to string conversion");
940 1060 : zval_dtor(op);
941 1060 : Z_USTRVAL_P(op) = USTR_MAKE_REL("Array");
942 1060 : Z_USTRLEN_P(op) = sizeof("Array")-1;
943 1060 : Z_TYPE_P(op) = IS_UNICODE;
944 1060 : return FAILURE;
945 : case IS_OBJECT: {
946 69 : int retval = FAILURE;
947 :
948 69 : convert_object_to_type(op, IS_UNICODE, convert_to_unicode);
949 :
950 68 : if (retval == SUCCESS && Z_TYPE_P(op) == IS_UNICODE) {
951 64 : return SUCCESS;
952 : }
953 :
954 4 : zend_error(E_NOTICE, "Object of class %v to string conversion", Z_OBJCE_P(op)->name);
955 4 : zval_dtor(op);
956 4 : Z_USTRVAL_P(op) = USTR_MAKE_REL("Object");
957 4 : Z_USTRLEN_P(op) = sizeof("Object")-1;
958 4 : Z_TYPE_P(op) = IS_UNICODE;
959 4 : return FAILURE;
960 : }
961 : default:
962 0 : zval_dtor(op);
963 0 : ZVAL_BOOL(op, 0);
964 0 : return FAILURE;
965 : }
966 :
967 2116720 : Z_TYPE_P(op) = IS_UNICODE;
968 2116720 : return SUCCESS;
969 : }
970 : /* }}} */
971 :
972 : ZEND_API int _convert_to_string(zval *op ZEND_FILE_LINE_DC) /* {{{ */
973 4410326 : {
974 : TSRMLS_FETCH();
975 4410326 : return _convert_to_string_with_converter(op, ZEND_U_CONVERTER(UG(runtime_encoding_conv)) TSRMLS_CC ZEND_FILE_LINE_CC);
976 : }
977 : /* }}} */
978 :
979 : ZEND_API int _convert_to_string_with_converter(zval *op, UConverter *conv TSRMLS_DC ZEND_FILE_LINE_DC) /* {{{ */
980 4941355 : {
981 : long lval;
982 : double dval;
983 :
984 4941355 : switch (Z_TYPE_P(op)) {
985 : case IS_NULL:
986 3328 : Z_STRVAL_P(op) = STR_EMPTY_ALLOC();
987 3328 : Z_STRLEN_P(op) = 0;
988 3328 : break;
989 : case IS_STRING:
990 178608 : break;
991 : case IS_UNICODE:
992 3570411 : return zval_unicode_to_string_ex(op, conv TSRMLS_CC);
993 : case IS_BOOL:
994 898 : if (Z_LVAL_P(op)) {
995 349 : Z_STRVAL_P(op) = estrndup_rel("1", 1);
996 349 : Z_STRLEN_P(op) = 1;
997 : } else {
998 549 : Z_STRVAL_P(op) = STR_EMPTY_ALLOC();
999 549 : Z_STRLEN_P(op) = 0;
1000 : }
1001 898 : break;
1002 : case IS_RESOURCE: {
1003 15 : long tmp = Z_LVAL_P(op);
1004 :
1005 15 : zend_list_delete(Z_LVAL_P(op));
1006 15 : Z_STRLEN_P(op) = zend_spprintf(&Z_STRVAL_P(op), 0, "Resource id #%ld", tmp);
1007 15 : break;
1008 : }
1009 : case IS_LONG:
1010 1187158 : lval = Z_LVAL_P(op);
1011 :
1012 1187158 : Z_STRLEN_P(op) = zend_spprintf(&Z_STRVAL_P(op), 0, "%ld", lval);
1013 1187158 : break;
1014 : case IS_DOUBLE: {
1015 810 : dval = Z_DVAL_P(op);
1016 810 : Z_STRLEN_P(op) = zend_spprintf(&Z_STRVAL_P(op), 0, "%.*G", (int) EG(precision), dval);
1017 : /* %G already handles removing trailing zeros from the fractional part, yay */
1018 810 : break;
1019 : }
1020 : case IS_ARRAY:
1021 90 : zend_error(E_NOTICE, "Array to string conversion");
1022 90 : zval_dtor(op);
1023 90 : Z_STRVAL_P(op) = estrndup_rel("Array", sizeof("Array")-1);
1024 90 : Z_STRLEN_P(op) = sizeof("Array")-1;
1025 90 : Z_TYPE_P(op) = IS_STRING;
1026 90 : return FAILURE;
1027 : case IS_OBJECT: {
1028 37 : int retval = FAILURE;
1029 :
1030 37 : convert_object_to_type(op, IS_STRING, convert_to_string);
1031 :
1032 30 : if (retval == SUCCESS && Z_TYPE_P(op) == IS_STRING) {
1033 18 : return SUCCESS;
1034 : }
1035 :
1036 12 : zend_error(E_NOTICE, "Object of class %v to string conversion", Z_OBJCE_P(op)->name);
1037 12 : zval_dtor(op);
1038 12 : Z_STRVAL_P(op) = estrndup_rel("Object", sizeof("Object")-1);
1039 12 : Z_STRLEN_P(op) = sizeof("Object")-1;
1040 12 : Z_TYPE_P(op) = IS_STRING;
1041 12 : return FAILURE;
1042 : }
1043 : default:
1044 0 : zval_dtor(op);
1045 0 : ZVAL_BOOL(op, 0);
1046 0 : return FAILURE;
1047 : }
1048 :
1049 1370817 : Z_TYPE_P(op) = IS_STRING;
1050 1370817 : return SUCCESS;
1051 : }
1052 : /* }}} */
1053 :
1054 : static int convert_scalar_to_array(zval *op, int type TSRMLS_DC) /* {{{ */
1055 348 : {
1056 : zval *entry;
1057 :
1058 348 : ALLOC_ZVAL(entry);
1059 348 : *entry = *op;
1060 348 : INIT_PZVAL(entry);
1061 :
1062 348 : switch (type) {
1063 : case IS_ARRAY:
1064 224 : ALLOC_HASHTABLE(Z_ARRVAL_P(op));
1065 224 : zend_u_hash_init(Z_ARRVAL_P(op), 0, NULL, ZVAL_PTR_DTOR, 0, 0);
1066 224 : zend_hash_index_update(Z_ARRVAL_P(op), 0, (void *) &entry, sizeof(zval *), NULL);
1067 224 : Z_TYPE_P(op) = IS_ARRAY;
1068 224 : break;
1069 : case IS_OBJECT:
1070 124 : object_init(op);
1071 124 : zend_hash_update(Z_OBJPROP_P(op), "scalar", sizeof("scalar"), (void *) &entry, sizeof(zval *), NULL);
1072 : break;
1073 : }
1074 :
1075 348 : return SUCCESS;
1076 : }
1077 : /* }}} */
1078 :
1079 : ZEND_API int convert_to_array(zval *op) /* {{{ */
1080 17219 : {
1081 : TSRMLS_FETCH();
1082 :
1083 17219 : switch (Z_TYPE_P(op)) {
1084 : case IS_ARRAY:
1085 16955 : break;
1086 : /* OBJECTS_OPTIMIZE */
1087 : case IS_OBJECT:
1088 : {
1089 : zval *tmp;
1090 : HashTable *ht;
1091 15 : int retval = FAILURE;
1092 :
1093 15 : ALLOC_HASHTABLE(ht);
1094 15 : zend_u_hash_init(ht, 0, NULL, ZVAL_PTR_DTOR, 0, 0);
1095 15 : if (Z_OBJ_HT_P(op)->get_properties) {
1096 15 : HashTable *obj_ht = Z_OBJ_HT_P(op)->get_properties(op TSRMLS_CC);
1097 15 : if (obj_ht) {
1098 15 : zend_hash_copy(ht, obj_ht, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *));
1099 15 : retval = SUCCESS;
1100 : }
1101 : } else {
1102 0 : convert_object_to_type(op, IS_ARRAY, convert_to_array);
1103 :
1104 0 : if (Z_TYPE_P(op) == IS_ARRAY) {
1105 0 : zend_hash_destroy(ht);
1106 0 : FREE_HASHTABLE(ht);
1107 0 : return SUCCESS;
1108 : }
1109 : }
1110 15 : zval_dtor(op);
1111 15 : Z_TYPE_P(op) = IS_ARRAY;
1112 15 : Z_ARRVAL_P(op) = ht;
1113 15 : return retval;
1114 : }
1115 : break;
1116 : case IS_NULL:
1117 25 : ALLOC_HASHTABLE(Z_ARRVAL_P(op));
1118 25 : zend_u_hash_init(Z_ARRVAL_P(op), 0, NULL, ZVAL_PTR_DTOR, 0, 0);
1119 25 : Z_TYPE_P(op) = IS_ARRAY;
1120 25 : break;
1121 : default:
1122 224 : return convert_scalar_to_array(op, IS_ARRAY TSRMLS_CC);
1123 : }
1124 :
1125 16980 : return SUCCESS;
1126 : }
1127 : /* }}} */
1128 :
1129 : ZEND_API int convert_to_object(zval *op) /* {{{ */
1130 208 : {
1131 : TSRMLS_FETCH();
1132 :
1133 208 : switch (Z_TYPE_P(op)) {
1134 : case IS_ARRAY:
1135 : {
1136 67 : object_and_properties_init(op, zend_standard_class_def, Z_ARRVAL_P(op));
1137 67 : break;
1138 : }
1139 : case IS_OBJECT:
1140 10 : break;
1141 : case IS_NULL:
1142 7 : object_init(op);
1143 7 : break;
1144 : default:
1145 124 : return convert_scalar_to_array(op, IS_OBJECT TSRMLS_CC);
1146 : }
1147 :
1148 84 : return SUCCESS;
1149 : }
1150 : /* }}} */
1151 :
1152 : ZEND_API void multi_convert_to_long_ex(int argc, ...) /* {{{ */
1153 0 : {
1154 : zval **arg;
1155 : va_list ap;
1156 :
1157 0 : va_start(ap, argc);
1158 :
1159 0 : while (argc--) {
1160 0 : arg = va_arg(ap, zval **);
1161 0 : convert_to_long_ex(arg);
1162 : }
1163 :
1164 0 : va_end(ap);
1165 0 : }
1166 : /* }}} */
1167 :
1168 : ZEND_API void multi_convert_to_double_ex(int argc, ...) /* {{{ */
1169 0 : {
1170 : zval **arg;
1171 : va_list ap;
1172 :
1173 0 : va_start(ap, argc);
1174 :
1175 0 : while (argc--) {
1176 0 : arg = va_arg(ap, zval **);
1177 0 : convert_to_double_ex(arg);
1178 : }
1179 :
1180 0 : va_end(ap);
1181 0 : }
1182 : /* }}} */
1183 :
1184 : ZEND_API void multi_convert_to_string_ex(int argc, ...) /* {{{ */
1185 0 : {
1186 : zval **arg;
1187 : va_list ap;
1188 :
1189 0 : va_start(ap, argc);
1190 :
1191 0 : while (argc--) {
1192 0 : arg = va_arg(ap, zval **);
1193 0 : convert_to_string_ex(arg);
1194 : }
1195 :
1196 0 : va_end(ap);
1197 0 : }
1198 : /* }}} */
1199 :
1200 : ZEND_API int add_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */
1201 4535335 : {
1202 : zval op1_copy, op2_copy;
1203 4535335 : int converted = 0;
1204 :
1205 : while (1) {
1206 4535795 : switch (TYPE_PAIR(Z_TYPE_P(op1), Z_TYPE_P(op2))) {
1207 : case TYPE_PAIR(IS_LONG, IS_LONG): {
1208 3732543 : long lval = Z_LVAL_P(op1) + Z_LVAL_P(op2);
1209 :
1210 : /* check for overflow by comparing sign bits */
1211 3732896 : if ((Z_LVAL_P(op1) & LONG_SIGN_MASK) == (Z_LVAL_P(op2) & LONG_SIGN_MASK)
1212 : && (Z_LVAL_P(op1) & LONG_SIGN_MASK) != (lval & LONG_SIGN_MASK)) {
1213 :
1214 353 : ZVAL_DOUBLE(result, (double) Z_LVAL_P(op1) + (double) Z_LVAL_P(op2));
1215 : } else {
1216 3732190 : ZVAL_LONG(result, lval);
1217 : }
1218 3732543 : return SUCCESS;
1219 : }
1220 :
1221 : case TYPE_PAIR(IS_LONG, IS_DOUBLE):
1222 237 : ZVAL_DOUBLE(result, ((double)Z_LVAL_P(op1)) + Z_DVAL_P(op2));
1223 237 : return SUCCESS;
1224 :
1225 : case TYPE_PAIR(IS_DOUBLE, IS_LONG):
1226 802316 : ZVAL_DOUBLE(result, Z_DVAL_P(op1) + ((double)Z_LVAL_P(op2)));
1227 802316 : return SUCCESS;
1228 :
1229 : case TYPE_PAIR(IS_DOUBLE, IS_DOUBLE):
1230 229 : ZVAL_DOUBLE(result, Z_DVAL_P(op1) + Z_DVAL_P(op2));
1231 229 : return SUCCESS;
1232 :
1233 : case TYPE_PAIR(IS_ARRAY, IS_ARRAY): {
1234 : zval *tmp;
1235 :
1236 6 : if ((result == op1) && (result == op2)) {
1237 : /* $a += $a */
1238 1 : return SUCCESS;
1239 : }
1240 5 : if (result != op1) {
1241 4 : *result = *op1;
1242 4 : zval_copy_ctor(result);
1243 : }
1244 5 : zend_hash_merge(Z_ARRVAL_P(result), Z_ARRVAL_P(op2), (void (*)(void *pData)) zval_add_ref, (void *) &tmp, sizeof(zval *), 0);
1245 5 : return SUCCESS;
1246 : }
1247 :
1248 : default:
1249 464 : if (!converted) {
1250 460 : zendi_convert_scalar_to_number(op1, op1_copy, result);
1251 460 : zendi_convert_scalar_to_number(op2, op2_copy, result);
1252 460 : converted = 1;
1253 : } else {
1254 4 : zend_error(E_ERROR, "Unsupported operand types");
1255 0 : return FAILURE; /* unknown datatype */
1256 : }
1257 : }
1258 460 : }
1259 : }
1260 : /* }}} */
1261 :
1262 : ZEND_API int sub_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */
1263 263205 : {
1264 : zval op1_copy, op2_copy;
1265 263205 : int converted = 0;
1266 :
1267 : while (1) {
1268 263438 : switch (TYPE_PAIR(Z_TYPE_P(op1), Z_TYPE_P(op2))) {
1269 : case TYPE_PAIR(IS_LONG, IS_LONG): {
1270 245182 : long lval = Z_LVAL_P(op1) - Z_LVAL_P(op2);
1271 :
1272 : /* check for overflow by comparing sign bits */
1273 245198 : if ((Z_LVAL_P(op1) & LONG_SIGN_MASK) != (Z_LVAL_P(op2) & LONG_SIGN_MASK)
1274 : && (Z_LVAL_P(op1) & LONG_SIGN_MASK) != (lval & LONG_SIGN_MASK)) {
1275 :
1276 16 : ZVAL_DOUBLE(result, (double) Z_LVAL_P(op1) - (double) Z_LVAL_P(op2));
1277 : } else {
1278 245166 : ZVAL_LONG(result, lval);
1279 : }
1280 245182 : return SUCCESS;
1281 :
1282 : }
1283 : case TYPE_PAIR(IS_LONG, IS_DOUBLE):
1284 2093 : ZVAL_DOUBLE(result, ((double)Z_LVAL_P(op1)) - Z_DVAL_P(op2));
1285 2093 : return SUCCESS;
1286 :
1287 : case TYPE_PAIR(IS_DOUBLE, IS_LONG):
1288 115 : ZVAL_DOUBLE(result, Z_DVAL_P(op1) - ((double)Z_LVAL_P(op2)));
1289 115 : return SUCCESS;
1290 :
1291 : case TYPE_PAIR(IS_DOUBLE, IS_DOUBLE):
1292 15814 : ZVAL_DOUBLE(result, Z_DVAL_P(op1) - Z_DVAL_P(op2));
1293 15814 : return SUCCESS;
1294 :
1295 : default:
1296 234 : if (!converted) {
1297 233 : zendi_convert_scalar_to_number(op1, op1_copy, result);
1298 233 : zendi_convert_scalar_to_number(op2, op2_copy, result);
1299 233 : converted = 1;
1300 : } else {
1301 1 : zend_error(E_ERROR, "Unsupported operand types");
1302 0 : return FAILURE; /* unknown datatype */
1303 : }
1304 : }
1305 233 : }
1306 : }
1307 : /* }}} */
1308 :
1309 : ZEND_API int mul_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */
1310 13247 : {
1311 : zval op1_copy, op2_copy;
1312 13247 : int converted = 0;
1313 :
1314 : while (1) {
1315 13456 : switch (TYPE_PAIR(Z_TYPE_P(op1), Z_TYPE_P(op2))) {
1316 : case TYPE_PAIR(IS_LONG, IS_LONG): {
1317 : long overflow;
1318 :
1319 12913 : ZEND_SIGNED_MULTIPLY_LONG(Z_LVAL_P(op1),Z_LVAL_P(op2), Z_LVAL_P(result),Z_DVAL_P(result),overflow);
1320 12913 : Z_TYPE_P(result) = overflow ? IS_DOUBLE : IS_LONG;
1321 12913 : return SUCCESS;
1322 :
1323 : }
1324 : case TYPE_PAIR(IS_LONG, IS_DOUBLE):
1325 56 : ZVAL_DOUBLE(result, ((double)Z_LVAL_P(op1)) * Z_DVAL_P(op2));
1326 56 : return SUCCESS;
1327 :
1328 : case TYPE_PAIR(IS_DOUBLE, IS_LONG):
1329 68 : ZVAL_DOUBLE(result, Z_DVAL_P(op1) * ((double)Z_LVAL_P(op2)));
1330 68 : return SUCCESS;
1331 :
1332 : case TYPE_PAIR(IS_DOUBLE, IS_DOUBLE):
1333 209 : ZVAL_DOUBLE(result, Z_DVAL_P(op1) * Z_DVAL_P(op2));
1334 209 : return SUCCESS;
1335 :
1336 : default:
1337 210 : if (!converted) {
1338 209 : zendi_convert_scalar_to_number(op1, op1_copy, result);
1339 209 : zendi_convert_scalar_to_number(op2, op2_copy, result);
1340 209 : converted = 1;
1341 : } else {
1342 1 : zend_error(E_ERROR, "Unsupported operand types");
1343 0 : return FAILURE; /* unknown datatype */
1344 : }
1345 : }
1346 209 : }
1347 : }
1348 : /* }}} */
1349 :
1350 : ZEND_API int div_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */
1351 1611765 : {
1352 : zval op1_copy, op2_copy;
1353 1611765 : int converted = 0;
1354 :
1355 : while (1) {
1356 1611964 : switch (TYPE_PAIR(Z_TYPE_P(op1), Z_TYPE_P(op2))) {
1357 : case TYPE_PAIR(IS_LONG, IS_LONG):
1358 1308836 : if (Z_LVAL_P(op2) == 0) {
1359 30 : zend_error(E_WARNING, "Division by zero");
1360 30 : ZVAL_BOOL(result, 0);
1361 30 : return FAILURE; /* division by zero */
1362 1308806 : } else if (Z_LVAL_P(op2) == -1 && Z_LVAL_P(op1) == LONG_MIN) {
1363 : /* Prevent overflow error/crash */
1364 0 : ZVAL_DOUBLE(result, (double) LONG_MIN / -1);
1365 0 : return SUCCESS;
1366 : }
1367 1308806 : if (Z_LVAL_P(op1) % Z_LVAL_P(op2) == 0) { /* integer */
1368 486814 : ZVAL_LONG(result, Z_LVAL_P(op1) / Z_LVAL_P(op2));
1369 : } else {
1370 821992 : ZVAL_DOUBLE(result, ((double) Z_LVAL_P(op1)) / Z_LVAL_P(op2));
1371 : }
1372 1308806 : return SUCCESS;
1373 :
1374 : case TYPE_PAIR(IS_DOUBLE, IS_LONG):
1375 284821 : if (Z_LVAL_P(op2) == 0) {
1376 15 : zend_error(E_WARNING, "Division by zero");
1377 15 : ZVAL_BOOL(result, 0);
1378 15 : return FAILURE; /* division by zero */
1379 : }
1380 284806 : ZVAL_DOUBLE(result, Z_DVAL_P(op1) / (double)Z_LVAL_P(op2));
1381 284806 : return SUCCESS;
1382 :
1383 : case TYPE_PAIR(IS_LONG, IS_DOUBLE):
1384 2037 : if (Z_DVAL_P(op2) == 0) {
1385 0 : zend_error(E_WARNING, "Division by zero");
1386 0 : ZVAL_BOOL(result, 0);
1387 0 : return FAILURE; /* division by zero */
1388 : }
1389 2037 : ZVAL_DOUBLE(result, (double)Z_LVAL_P(op1) / Z_DVAL_P(op2));
1390 2037 : return SUCCESS;
1391 :
1392 : case TYPE_PAIR(IS_DOUBLE, IS_DOUBLE):
1393 16070 : if (Z_DVAL_P(op2) == 0) {
1394 0 : zend_error(E_WARNING, "Division by zero");
1395 0 : ZVAL_BOOL(result, 0);
1396 0 : return FAILURE; /* division by zero */
1397 : }
1398 16070 : ZVAL_DOUBLE(result, Z_DVAL_P(op1) / Z_DVAL_P(op2));
1399 16070 : return SUCCESS;
1400 :
1401 : default:
1402 200 : if (!converted) {
1403 199 : zendi_convert_scalar_to_number(op1, op1_copy, result);
1404 199 : zendi_convert_scalar_to_number(op2, op2_copy, result);
1405 199 : converted = 1;
1406 : } else {
1407 1 : zend_error(E_ERROR, "Unsupported operand types");
1408 0 : return FAILURE; /* unknown datatype */
1409 : }
1410 : }
1411 199 : }
1412 : }
1413 : /* }}} */
1414 :
1415 : ZEND_API int mod_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */
1416 49529 : {
1417 : zval op1_copy, op2_copy;
1418 :
1419 49529 : zendi_convert_to_long(op1, op1_copy, result);
1420 49529 : zendi_convert_to_long(op2, op2_copy, result);
1421 :
1422 49529 : if (Z_LVAL_P(op2) == 0) {
1423 43 : zend_error(E_WARNING, "Division by zero");
1424 43 : ZVAL_BOOL(result, 0);
1425 43 : return FAILURE; /* modulus by zero */
1426 : }
1427 :
1428 49486 : if (Z_LVAL_P(op2) == -1) {
1429 : /* Prevent overflow error/crash if op1==LONG_MIN */
1430 3 : ZVAL_LONG(result, 0);
1431 3 : return SUCCESS;
1432 : }
1433 :
1434 49483 : ZVAL_LONG(result, Z_LVAL_P(op1) % Z_LVAL_P(op2));
1435 49483 : return SUCCESS;
1436 : }
1437 : /* }}} */
1438 :
1439 : ZEND_API int boolean_xor_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */
1440 0 : {
1441 : zval op1_copy, op2_copy;
1442 :
1443 0 : zendi_convert_to_boolean(op1, op1_copy, result);
1444 0 : zendi_convert_to_boolean(op2, op2_copy, result);
1445 0 : ZVAL_BOOL(result, Z_LVAL_P(op1) ^ Z_LVAL_P(op2));
1446 0 : return SUCCESS;
1447 : }
1448 : /* }}} */
1449 :
1450 : ZEND_API int boolean_not_function(zval *result, zval *op1 TSRMLS_DC) /* {{{ */
1451 6845915 : {
1452 : zval op1_copy;
1453 :
1454 6845915 : zendi_convert_to_boolean(op1, op1_copy, result);
1455 6845915 : ZVAL_BOOL(result, !Z_LVAL_P(op1));
1456 6845915 : return SUCCESS;
1457 : }
1458 : /* }}} */
1459 :
1460 : ZEND_API int bitwise_not_function(zval *result, zval *op1 TSRMLS_DC) /* {{{ */
1461 101 : {
1462 101 : zval op1_copy = *op1;
1463 :
1464 101 : op1 = &op1_copy;
1465 :
1466 101 : if (Z_TYPE_P(op1) == IS_LONG) {
1467 84 : ZVAL_LONG(result, ~Z_LVAL_P(op1));
1468 84 : return SUCCESS;
1469 17 : } else if (Z_TYPE_P(op1) == IS_DOUBLE) {
1470 1 : ZVAL_LONG(result, ~zend_dval_to_lval(Z_DVAL_P(op1)));
1471 1 : return SUCCESS;
1472 16 : } else if (Z_TYPE_P(op1) == IS_STRING) {
1473 : int i;
1474 :
1475 15 : Z_TYPE_P(result) = IS_STRING;
1476 15 : Z_STRVAL_P(result) = estrndup(Z_STRVAL_P(op1), Z_STRLEN_P(op1));
1477 15 : Z_STRLEN_P(result) = Z_STRLEN_P(op1);
1478 83 : for (i = 0; i < Z_STRLEN_P(op1); i++) {
1479 68 : Z_STRVAL_P(result)[i] = ~Z_STRVAL_P(op1)[i];
1480 : }
1481 15 : return SUCCESS;
1482 : }
1483 1 : zend_error(E_ERROR, "Unsupported operand types");
1484 0 : return FAILURE; /* unknown datatype */
1485 : }
1486 : /* }}} */
1487 :
1488 : ZEND_API int bitwise_or_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */
1489 7768 : {
1490 : zval op1_copy, op2_copy;
1491 :
1492 7768 : if (Z_TYPE_P(op1) == IS_STRING && Z_TYPE_P(op2) == IS_STRING) {
1493 : zval *longer, *shorter;
1494 : char *result_str;
1495 : int i, result_len;
1496 :
1497 200 : if (Z_STRLEN_P(op1) >= Z_STRLEN_P(op2)) {
1498 117 : longer = op1;
1499 117 : shorter = op2;
1500 : } else {
1501 83 : longer = op2;
1502 83 : shorter = op1;
1503 : }
1504 :
1505 200 : Z_TYPE_P(result) = IS_STRING;
1506 200 : result_len = Z_STRLEN_P(longer);
1507 200 : result_str = estrndup(Z_STRVAL_P(longer), Z_STRLEN_P(longer));
1508 888 : for (i = 0; i < Z_STRLEN_P(shorter); i++) {
1509 688 : result_str[i] |= Z_STRVAL_P(shorter)[i];
1510 : }
1511 200 : if (result==op1) {
1512 1 : STR_FREE(Z_STRVAL_P(result));
1513 : }
1514 200 : Z_STRVAL_P(result) = result_str;
1515 200 : Z_STRLEN_P(result) = result_len;
1516 200 : return SUCCESS;
1517 : }
1518 :
1519 7568 : if (Z_TYPE_P(op1) == IS_UNICODE && Z_TYPE_P(op2) == IS_UNICODE) {
1520 0 : zend_error(E_ERROR, "Unsupported operand types");
1521 0 : return FAILURE;
1522 : }
1523 :
1524 7568 : zendi_convert_to_long(op1, op1_copy, result);
1525 7568 : zendi_convert_to_long(op2, op2_copy, result);
1526 :
1527 7568 : ZVAL_LONG(result, Z_LVAL_P(op1) | Z_LVAL_P(op2));
1528 7568 : return SUCCESS;
1529 : }
1530 : /* }}} */
1531 :
1532 : ZEND_API int bitwise_and_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */
1533 44234 : {
1534 : zval op1_copy, op2_copy;
1535 :
1536 44234 : if (Z_TYPE_P(op1) == IS_STRING && Z_TYPE_P(op2) == IS_STRING) {
1537 : zval *longer, *shorter;
1538 : char *result_str;
1539 : int i, result_len;
1540 :
1541 201 : if (Z_STRLEN_P(op1) >= Z_STRLEN_P(op2)) {
1542 117 : longer = op1;
1543 117 : shorter = op2;
1544 : } else {
1545 84 : longer = op2;
1546 84 : shorter = op1;
1547 : }
1548 :
1549 201 : Z_TYPE_P(result) = IS_STRING;
1550 201 : result_len = Z_STRLEN_P(shorter);
1551 201 : result_str = estrndup(Z_STRVAL_P(shorter), Z_STRLEN_P(shorter));
1552 888 : for (i = 0; i < Z_STRLEN_P(shorter); i++) {
1553 687 : result_str[i] &= Z_STRVAL_P(longer)[i];
1554 : }
1555 201 : if (result==op1) {
1556 1 : STR_FREE(Z_STRVAL_P(result));
1557 : }
1558 201 : Z_STRVAL_P(result) = result_str;
1559 201 : Z_STRLEN_P(result) = result_len;
1560 201 : return SUCCESS;
1561 : }
1562 :
1563 44033 : if (Z_TYPE_P(op1) == IS_UNICODE && Z_TYPE_P(op2) == IS_UNICODE) {
1564 0 : zend_error(E_ERROR, "Unsupported operand types");
1565 0 : return FAILURE;
1566 : }
1567 :
1568 44033 : zendi_convert_to_long(op1, op1_copy, result);
1569 44033 : zendi_convert_to_long(op2, op2_copy, result);
1570 :
1571 44033 : ZVAL_LONG(result, Z_LVAL_P(op1) & Z_LVAL_P(op2));
1572 44033 : return SUCCESS;
1573 : }
1574 : /* }}} */
1575 :
1576 : ZEND_API int bitwise_xor_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */
1577 214 : {
1578 : zval op1_copy, op2_copy;
1579 :
1580 214 : if (Z_TYPE_P(op1) == IS_STRING && Z_TYPE_P(op2) == IS_STRING) {
1581 : zval *longer, *shorter;
1582 : char *result_str;
1583 : int i, result_len;
1584 :
1585 202 : if (Z_STRLEN_P(op1) >= Z_STRLEN_P(op2)) {
1586 118 : longer = op1;
1587 118 : shorter = op2;
1588 : } else {
1589 84 : longer = op2;
1590 84 : shorter = op1;
1591 : }
1592 :
1593 202 : Z_TYPE_P(result) = IS_STRING;
1594 202 : result_len = Z_STRLEN_P(shorter);
1595 202 : result_str = estrndup(Z_STRVAL_P(shorter), Z_STRLEN_P(shorter));
1596 892 : for (i = 0; i < Z_STRLEN_P(shorter); i++) {
1597 690 : result_str[i] ^= Z_STRVAL_P(longer)[i];
1598 : }
1599 202 : if (result==op1) {
1600 1 : STR_FREE(Z_STRVAL_P(result));
1601 : }
1602 202 : Z_STRVAL_P(result) = result_str;
1603 202 : Z_STRLEN_P(result) = result_len;
1604 202 : return SUCCESS;
1605 : }
1606 :
1607 12 : if (Z_TYPE_P(op1) == IS_UNICODE && Z_TYPE_P(op2) == IS_UNICODE) {
1608 0 : zend_error(E_ERROR, "Unsupported operand types");
1609 0 : return FAILURE;
1610 : }
1611 :
1612 12 : zendi_convert_to_long(op1, op1_copy, result);
1613 12 : zendi_convert_to_long(op2, op2_copy, result);
1614 :
1615 12 : ZVAL_LONG(result, Z_LVAL_P(op1) ^ Z_LVAL_P(op2));
1616 12 : return SUCCESS;
1617 : }
1618 : /* }}} */
1619 :
1620 : ZEND_API int shift_left_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */
1621 3102 : {
1622 : zval op1_copy, op2_copy;
1623 :
1624 3102 : zendi_convert_to_long(op1, op1_copy, result);
1625 3102 : zendi_convert_to_long(op2, op2_copy, result);
1626 3102 : ZVAL_LONG(result, Z_LVAL_P(op1) << Z_LVAL_P(op2));
1627 3102 : return SUCCESS;
1628 : }
1629 : /* }}} */
1630 :
1631 : ZEND_API int shift_right_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */
1632 35053 : {
1633 : zval op1_copy, op2_copy;
1634 :
1635 35053 : zendi_convert_to_long(op1, op1_copy, result);
1636 35053 : zendi_convert_to_long(op2, op2_copy, result);
1637 35053 : ZVAL_LONG(result, Z_LVAL_P(op1) >> Z_LVAL_P(op2));
1638 35053 : return SUCCESS;
1639 : }
1640 : /* }}} */
1641 :
1642 : /* must support result==op1 */
1643 : ZEND_API int add_char_to_string(zval *result, const zval *op1, const zval *op2) /* {{{ */
1644 949572 : {
1645 949572 : if (Z_TYPE_P(op1) == IS_UNICODE) {
1646 949060 : UChar32 codepoint = (UChar32) Z_LVAL_P(op2);
1647 :
1648 949060 : if (U_IS_BMP(codepoint)) {
1649 949060 : Z_USTRLEN_P(result) = Z_USTRLEN_P(op1) + 1;
1650 949060 : Z_USTRVAL_P(result) = eurealloc(Z_USTRVAL_P(op1), Z_USTRLEN_P(result)+1);
1651 949060 : Z_USTRVAL_P(result)[Z_USTRLEN_P(result) - 1] = (UChar) Z_LVAL_P(op2);
1652 : } else {
1653 0 : Z_USTRLEN_P(result) = Z_USTRLEN_P(op1) + 2;
1654 0 : Z_USTRVAL_P(result) = eurealloc(Z_USTRVAL_P(op1), Z_USTRLEN_P(result)+1);
1655 0 : Z_USTRVAL_P(result)[Z_USTRLEN_P(result) - 2] = (UChar) U16_LEAD(codepoint);
1656 0 : Z_USTRVAL_P(result)[Z_USTRLEN_P(result) - 1] = (UChar) U16_TRAIL(codepoint);
1657 : }
1658 949060 : Z_USTRVAL_P(result)[Z_USTRLEN_P(result)] = 0;
1659 949060 : Z_TYPE_P(result) = IS_UNICODE;
1660 : } else {
1661 512 : Z_STRLEN_P(result) = Z_STRLEN_P(op1) + 1;
1662 512 : Z_STRVAL_P(result) = (char *) erealloc(Z_STRVAL_P(op1), Z_STRLEN_P(result)+1);
1663 512 : Z_STRVAL_P(result)[Z_STRLEN_P(result) - 1] = (char) Z_LVAL_P(op2);
1664 512 : Z_STRVAL_P(result)[Z_STRLEN_P(result)] = 0;
1665 512 : Z_TYPE_P(result) = Z_TYPE_P(op1);
1666 : }
1667 949572 : return SUCCESS;
1668 : }
1669 : /* }}} */
1670 :
1671 : /* must support result==op1 */
1672 : ZEND_API int add_string_to_string(zval *result, const zval *op1, const zval *op2) /* {{{ */
1673 12339147 : {
1674 12339147 : assert(Z_TYPE_P(op1) == Z_TYPE_P(op2));
1675 :
1676 12339147 : if (Z_TYPE_P(op1) == IS_UNICODE) {
1677 11422024 : int length = Z_USTRLEN_P(op1) + Z_USTRLEN_P(op2);
1678 :
1679 11422024 : Z_USTRVAL_P(result) = eurealloc(Z_USTRVAL_P(op1), length+1);
1680 11422024 : u_memcpy(Z_USTRVAL_P(result)+Z_USTRLEN_P(op1), Z_USTRVAL_P(op2), Z_USTRLEN_P(op2));
1681 11422024 : Z_USTRVAL_P(result)[length] = 0;
1682 11422024 : Z_USTRLEN_P(result) = length;
1683 11422024 : Z_TYPE_P(result) = IS_UNICODE;
1684 : } else {
1685 917123 : int length = Z_STRLEN_P(op1) + Z_STRLEN_P(op2);
1686 :
1687 917123 : Z_STRVAL_P(result) = (char *) erealloc(Z_STRVAL_P(op1), length+1);
1688 917123 : memcpy(Z_STRVAL_P(result)+Z_STRLEN_P(op1), Z_STRVAL_P(op2), Z_STRLEN_P(op2));
1689 917123 : Z_STRVAL_P(result)[length] = 0;
1690 917123 : Z_STRLEN_P(result) = length;
1691 917123 : Z_TYPE_P(result) = Z_TYPE_P(op1);
1692 : }
1693 12339147 : return SUCCESS;
1694 : }
1695 : /* }}} */
1696 :
1697 : ZEND_API int concat_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */
1698 3996640 : {
1699 : zval op1_copy, op2_copy;
1700 3996640 : int use_copy1 = 0, use_copy2 = 0;
1701 : zend_uchar result_type;
1702 :
1703 4964433 : if (Z_TYPE_P(op1) == IS_STRING && Z_TYPE_P(op2) == IS_STRING) {
1704 967793 : result_type = IS_STRING;
1705 : } else {
1706 3028847 : zend_make_unicode_zval(op1, &op1_copy, &use_copy1);
1707 3028847 : zend_make_unicode_zval(op2, &op2_copy, &use_copy2);
1708 3028847 : result_type = IS_UNICODE;
1709 : }
1710 :
1711 3996640 : if (use_copy1) {
1712 : /* We have created a converted copy of op1. Therefore, op1 won't become the result so
1713 : * we have to free it.
1714 : */
1715 40325 : if (result == op1) {
1716 20 : zval_dtor(op1);
1717 : }
1718 40325 : op1 = &op1_copy;
1719 : }
1720 3996640 : if (use_copy2) {
1721 61530 : op2 = &op2_copy;
1722 : }
1723 3996640 : if (result==op1) { /* special case, perform operations on result */
1724 3029386 : add_string_to_string(result, op1, op2);
1725 : } else {
1726 967254 : if (result_type == IS_UNICODE) {
1727 892512 : Z_USTRLEN_P(result) = Z_USTRLEN_P(op1) + Z_USTRLEN_P(op2);
1728 892512 : Z_USTRVAL_P(result) = eumalloc(Z_USTRLEN_P(result) + 1);
1729 892512 : u_memcpy(Z_USTRVAL_P(result), Z_USTRVAL_P(op1), Z_USTRLEN_P(op1));
1730 892512 : u_memcpy(Z_USTRVAL_P(result)+Z_USTRLEN_P(op1), Z_USTRVAL_P(op2), Z_USTRLEN_P(op2));
1731 892512 : Z_USTRVAL_P(result)[Z_USTRLEN_P(result)] = 0;
1732 892512 : Z_TYPE_P(result) = IS_UNICODE;
1733 : } else {
1734 74742 : Z_STRLEN_P(result) = Z_STRLEN_P(op1) + Z_STRLEN_P(op2);
1735 74742 : Z_STRVAL_P(result) = (char *) emalloc(Z_STRLEN_P(result) + 1);
1736 74742 : memcpy(Z_STRVAL_P(result), Z_STRVAL_P(op1), Z_STRLEN_P(op1));
1737 74742 : memcpy(Z_STRVAL_P(result)+Z_STRLEN_P(op1), Z_STRVAL_P(op2), Z_STRLEN_P(op2));
1738 74742 : Z_STRVAL_P(result)[Z_STRLEN_P(result)] = 0;
1739 74742 : Z_TYPE_P(result) = result_type;
1740 : }
1741 : }
1742 3996640 : if (use_copy1) {
1743 40325 : zval_dtor(op1);
1744 : }
1745 3996640 : if (use_copy2) {
1746 61530 : zval_dtor(op2);
1747 : }
1748 3996640 : return SUCCESS;
1749 : }
1750 : /* }}} */
1751 :
1752 : ZEND_API int string_compare_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */
1753 692579 : {
1754 : zval op1_copy, op2_copy;
1755 : int use_copy1, use_copy2;
1756 :
1757 692579 : zend_make_unicode_zval(op1, &op1_copy, &use_copy1);
1758 692579 : zend_make_unicode_zval(op2, &op2_copy, &use_copy2);
1759 :
1760 692579 : if (use_copy1) {
1761 425528 : op1 = &op1_copy;
1762 : }
1763 692579 : if (use_copy2) {
1764 501755 : op2 = &op2_copy;
1765 : }
1766 :
1767 692579 : ZVAL_LONG(result, zend_u_binary_zval_strcmp(op1, op2));
1768 :
1769 692579 : if (use_copy1) {
1770 425528 : zval_dtor(op1);
1771 : }
1772 692579 : if (use_copy2) {
1773 501755 : zval_dtor(op2);
1774 : }
1775 692579 : return SUCCESS;
1776 : }
1777 : /* }}} */
1778 :
1779 : ZEND_API int string_locale_compare_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */
1780 0 : {
1781 : zval op1_copy, op2_copy;
1782 : int use_copy1, use_copy2;
1783 :
1784 0 : zend_make_unicode_zval(op1, &op1_copy, &use_copy1);
1785 0 : zend_make_unicode_zval(op2, &op2_copy, &use_copy2);
1786 :
1787 0 : if (use_copy1) {
1788 0 : op1 = &op1_copy;
1789 : }
1790 0 : if (use_copy2) {
1791 0 : op2 = &op2_copy;
1792 : }
1793 :
1794 0 : Z_LVAL_P(result) = ucol_strcoll(UG(default_collator)->coll, Z_USTRVAL_P(op1), Z_USTRLEN_P(op1), Z_USTRVAL_P(op2), Z_USTRLEN_P(op2));
1795 0 : Z_TYPE_P(result) = IS_LONG;
1796 :
1797 0 : if (use_copy1) {
1798 0 : zval_dtor(op1);
1799 : }
1800 0 : if (use_copy2) {
1801 0 : zval_dtor(op2);
1802 : }
1803 0 : return SUCCESS;
1804 : }
1805 : /* }}} */
1806 :
1807 : ZEND_API int numeric_compare_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */
1808 926 : {
1809 : zval op1_copy, op2_copy;
1810 :
1811 926 : op1_copy = *op1;
1812 926 : zval_copy_ctor(&op1_copy);
1813 :
1814 926 : op2_copy = *op2;
1815 926 : zval_copy_ctor(&op2_copy);
1816 :
1817 926 : convert_to_double(&op1_copy);
1818 926 : convert_to_double(&op2_copy);
1819 :
1820 926 : ZVAL_LONG(result, ZEND_NORMALIZE_BOOL(Z_DVAL(op1_copy)-Z_DVAL(op2_copy)));
1821 :
1822 926 : return SUCCESS;
1823 : }
1824 : /* }}} */
1825 :
1826 : static inline void zend_free_obj_get_result(zval *op TSRMLS_DC) /* {{{ */
1827 413 : {
1828 413 : if (Z_REFCOUNT_P(op) == 0) {
1829 1 : GC_REMOVE_ZVAL_FROM_BUFFER(op);
1830 1 : zval_dtor(op);
1831 1 : FREE_ZVAL(op);
1832 : } else {
1833 412 : zval_ptr_dtor(&op);
1834 : }
1835 413 : }
1836 : /* }}} */
1837 :
1838 : ZEND_API int compare_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */
1839 52549372 : {
1840 : int ret;
1841 52549372 : int converted = 0;
1842 : zval op1_copy, op2_copy;
1843 : zval *op_free;
1844 :
1845 : while (1) {
1846 52569916 : switch (TYPE_PAIR(Z_TYPE_P(op1), Z_TYPE_P(op2))) {
1847 : case TYPE_PAIR(IS_LONG, IS_LONG):
1848 46143774 : ZVAL_LONG(result, Z_LVAL_P(op1)>Z_LVAL_P(op2)?1:(Z_LVAL_P(op1)<Z_LVAL_P(op2)?-1:0));
1849 46143774 : return SUCCESS;
1850 :
1851 : case TYPE_PAIR(IS_DOUBLE, IS_LONG):
1852 7888 : Z_DVAL_P(result) = Z_DVAL_P(op1) - (double)Z_LVAL_P(op2);
1853 7888 : ZVAL_LONG(result, ZEND_NORMALIZE_BOOL(Z_DVAL_P(result)));
1854 7888 : return SUCCESS;
1855 :
1856 : case TYPE_PAIR(IS_LONG, IS_DOUBLE):
1857 5424143 : Z_DVAL_P(result) = (double)Z_LVAL_P(op1) - Z_DVAL_P(op2);
1858 5424143 : ZVAL_LONG(result, ZEND_NORMALIZE_BOOL(Z_DVAL_P(result)));
1859 5424143 : return SUCCESS;
1860 :
1861 : case TYPE_PAIR(IS_DOUBLE, IS_DOUBLE):
1862 1449 : Z_DVAL_P(result) = Z_DVAL_P(op1) - Z_DVAL_P(op2);
1863 1449 : ZVAL_LONG(result, ZEND_NORMALIZE_BOOL(Z_DVAL_P(result)));
1864 1449 : return SUCCESS;
1865 :
1866 : case TYPE_PAIR(IS_ARRAY, IS_ARRAY):
1867 678 : zend_compare_arrays(result, op1, op2 TSRMLS_CC);
1868 678 : return SUCCESS;
1869 :
1870 : case TYPE_PAIR(IS_NULL, IS_NULL):
1871 255 : ZVAL_LONG(result, 0);
1872 255 : return SUCCESS;
1873 :
1874 : case TYPE_PAIR(IS_NULL, IS_BOOL):
1875 24 : ZVAL_LONG(result, Z_LVAL_P(op2) ? -1 : 0);
1876 24 : return SUCCESS;
1877 :
1878 : case TYPE_PAIR(IS_BOOL, IS_NULL):
1879 30 : ZVAL_LONG(result, Z_LVAL_P(op1) ? 1 : 0);
1880 30 : return SUCCESS;
1881 :
1882 : case TYPE_PAIR(IS_BOOL, IS_BOOL):
1883 4613 : ZVAL_LONG(result, ZEND_NORMALIZE_BOOL(Z_LVAL_P(op1) - Z_LVAL_P(op2)));
1884 4613 : return SUCCESS;
1885 :
1886 : case TYPE_PAIR(IS_STRING, IS_STRING):
1887 2552 : zendi_smart_strcmp(result, op1, op2);
1888 2552 : return SUCCESS;
1889 :
1890 : case TYPE_PAIR(IS_UNICODE, IS_UNICODE):
1891 945476 : zendi_u_smart_strcmp(result, op1, op2);
1892 945476 : return SUCCESS;
1893 :
1894 : case TYPE_PAIR(IS_STRING, IS_UNICODE):
1895 467 : zendi_u_smart_strcmp(result, op1, op2);
1896 467 : return SUCCESS;
1897 :
1898 : case TYPE_PAIR(IS_UNICODE, IS_STRING):
1899 541 : zendi_u_smart_strcmp(result, op1, op2);
1900 541 : return SUCCESS;
1901 :
1902 : case TYPE_PAIR(IS_NULL, IS_STRING):
1903 124 : ZVAL_LONG(result, zend_binary_strcmp("", 0, Z_STRVAL_P(op2), Z_STRLEN_P(op2)));
1904 124 : return SUCCESS;
1905 :
1906 : case TYPE_PAIR(IS_STRING, IS_NULL):
1907 8 : ZVAL_LONG(result, zend_binary_strcmp(Z_STRVAL_P(op1), Z_STRLEN_P(op1), "", 0));
1908 8 : return SUCCESS;
1909 :
1910 : case TYPE_PAIR(IS_NULL, IS_UNICODE):
1911 104 : ZVAL_LONG(result, zend_u_binary_strcmp(EMPTY_STR, 0, Z_USTRVAL_P(op2), Z_USTRLEN_P(op2)));
1912 104 : return SUCCESS;
1913 :
1914 : case TYPE_PAIR(IS_UNICODE, IS_NULL):
1915 318 : ZVAL_LONG(result, zend_u_binary_strcmp(Z_USTRVAL_P(op1), Z_USTRLEN_P(op1), EMPTY_STR, 0));
1916 318 : return SUCCESS;
1917 :
1918 : case TYPE_PAIR(IS_OBJECT, IS_NULL):
1919 48 : ZVAL_LONG(result, 1);
1920 48 : return SUCCESS;
1921 :
1922 : case TYPE_PAIR(IS_NULL, IS_OBJECT):
1923 15 : ZVAL_LONG(result, -1);
1924 15 : return SUCCESS;
1925 :
1926 : case TYPE_PAIR(IS_OBJECT, IS_OBJECT):
1927 : /* If both are objects sharing the same comparision handler then use is */
1928 550 : if (Z_OBJ_HANDLER_P(op1,compare_objects) == Z_OBJ_HANDLER_P(op2,compare_objects)) {
1929 549 : if (Z_OBJ_HANDLE_P(op1) == Z_OBJ_HANDLE_P(op2)) {
1930 : /* object handles are identical, apprently this is the same object */
1931 23 : ZVAL_LONG(result, 0);
1932 23 : return SUCCESS;
1933 : }
1934 526 : ZVAL_LONG(result, Z_OBJ_HT_P(op1)->compare_objects(op1, op2 TSRMLS_CC));
1935 526 : return SUCCESS;
1936 : }
1937 : /* break missing intentionally */
1938 :
1939 : default:
1940 36860 : if (Z_TYPE_P(op1) == IS_OBJECT) {
1941 217 : if (Z_OBJ_HT_P(op1)->get) {
1942 1 : op_free = Z_OBJ_HT_P(op1)->get(op1 TSRMLS_CC);
1943 1 : ret = compare_function(result, op_free, op2 TSRMLS_CC);
1944 1 : zend_free_obj_get_result(op_free TSRMLS_CC);
1945 1 : return ret;
1946 216 : } else if (Z_TYPE_P(op2) != IS_OBJECT && Z_OBJ_HT_P(op1)->cast_object) {
1947 215 : ALLOC_INIT_ZVAL(op_free);
1948 215 : if (Z_OBJ_HT_P(op1)->cast_object(op1, op_free, Z_TYPE_P(op2), NULL TSRMLS_CC) == FAILURE) {
1949 112 : ZVAL_LONG(result, 1);
1950 112 : zend_free_obj_get_result(op_free TSRMLS_CC);
1951 112 : return SUCCESS;
1952 : }
1953 103 : ret = compare_function(result, op_free, op2 TSRMLS_CC);
1954 103 : zend_free_obj_get_result(op_free TSRMLS_CC);
1955 103 : return ret;
1956 : }
1957 : }
1958 36644 : if (Z_TYPE_P(op2) == IS_OBJECT) {
1959 198 : if (Z_OBJ_HT_P(op2)->get) {
1960 0 : op_free = Z_OBJ_HT_P(op2)->get(op2 TSRMLS_CC);
1961 0 : ret = compare_function(result, op1, op_free TSRMLS_CC);
1962 0 : zend_free_obj_get_result(op_free TSRMLS_CC);
1963 0 : return ret;
1964 198 : } else if (Z_TYPE_P(op1) != IS_OBJECT && Z_OBJ_HT_P(op2)->cast_object) {
1965 197 : ALLOC_INIT_ZVAL(op_free);
1966 197 : if (Z_OBJ_HT_P(op2)->cast_object(op2, op_free, Z_TYPE_P(op1), NULL TSRMLS_CC) == FAILURE) {
1967 107 : ZVAL_LONG(result, -1);
1968 107 : zend_free_obj_get_result(op_free TSRMLS_CC);
1969 107 : return SUCCESS;
1970 : }
1971 90 : ret = compare_function(result, op1, op_free TSRMLS_CC);
1972 90 : zend_free_obj_get_result(op_free TSRMLS_CC);
1973 90 : return ret;
1974 : }
1975 : }
1976 36447 : if (!converted) {
1977 35896 : if (Z_TYPE_P(op1) == IS_NULL) {
1978 5426 : zendi_convert_to_boolean(op2, op2_copy, result);
1979 5426 : ZVAL_LONG(result, Z_LVAL_P(op2) ? -1 : 0);
1980 5426 : return SUCCESS;
1981 30470 : } else if (Z_TYPE_P(op2) == IS_NULL) {
1982 94 : zendi_convert_to_boolean(op1, op1_copy, result);
1983 94 : ZVAL_LONG(result, Z_LVAL_P(op1) ? 1 : 0);
1984 94 : return SUCCESS;
1985 30376 : } else if (Z_TYPE_P(op1) == IS_BOOL) {
1986 6494 : zendi_convert_to_boolean(op2, op2_copy, result);
1987 6494 : ZVAL_LONG(result, ZEND_NORMALIZE_BOOL(Z_LVAL_P(op1) - Z_LVAL_P(op2)));
1988 6494 : return SUCCESS;
1989 23882 : } else if (Z_TYPE_P(op2) == IS_BOOL) {
1990 3338 : zendi_convert_to_boolean(op1, op1_copy, result);
1991 3338 : ZVAL_LONG(result, ZEND_NORMALIZE_BOOL(Z_LVAL_P(op1) - Z_LVAL_P(op2)));
1992 3338 : return SUCCESS;
1993 : } else {
1994 20544 : zendi_convert_scalar_to_number(op1, op1_copy, result);
1995 20544 : zendi_convert_scalar_to_number(op2, op2_copy, result);
1996 20544 : converted = 1;
1997 : }
1998 551 : } else if (Z_TYPE_P(op1)==IS_ARRAY) {
1999 271 : ZVAL_LONG(result, 1);
2000 271 : return SUCCESS;
2001 280 : } else if (Z_TYPE_P(op2)==IS_ARRAY) {
2002 280 : ZVAL_LONG(result, -1);
2003 280 : return SUCCESS;
2004 0 : } else if (Z_TYPE_P(op1)==IS_OBJECT) {
2005 0 : ZVAL_LONG(result, 1);
2006 0 : return SUCCESS;
2007 0 : } else if (Z_TYPE_P(op2)==IS_OBJECT) {
2008 0 : ZVAL_LONG(result, -1);
2009 0 : return SUCCESS;
2010 : } else {
2011 0 : ZVAL_LONG(result, 0);
2012 0 : return FAILURE;
2013 : }
2014 : }
2015 20544 : }
2016 : }
2017 : /* }}} */
2018 :
2019 : static int hash_zval_identical_function(const zval **z1, const zval **z2) /* {{{ */
2020 1076 : {
2021 : zval result;
2022 : TSRMLS_FETCH();
2023 :
2024 : /* is_identical_function() returns 1 in case of identity and 0 in case
2025 : * of a difference;
2026 : * whereas this comparison function is expected to return 0 on identity,
2027 : * and non zero otherwise.
2028 : */
2029 1076 : if (is_identical_function(&result, (zval *) *z1, (zval *) *z2 TSRMLS_CC)==FAILURE) {
2030 0 : return 1;
2031 : }
2032 1076 : return !Z_LVAL(result);
2033 : }
2034 : /* }}} */
2035 :
2036 : ZEND_API int is_identical_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */
2037 2872404 : {
2038 2872404 : Z_TYPE_P(result) = IS_BOOL;
2039 2872404 : if (Z_TYPE_P(op1) != Z_TYPE_P(op2)) {
2040 1801542 : Z_LVAL_P(result) = 0;
2041 1801542 : return SUCCESS;
2042 : }
2043 1070862 : switch (Z_TYPE_P(op1)) {
2044 : case IS_NULL:
2045 9676 : Z_LVAL_P(result) = 1;
2046 9676 : break;
2047 : case IS_BOOL:
2048 : case IS_LONG:
2049 : case IS_RESOURCE:
2050 1044574 : Z_LVAL_P(result) = (Z_LVAL_P(op1) == Z_LVAL_P(op2));
2051 1044574 : break;
2052 : case IS_DOUBLE:
2053 184 : Z_LVAL_P(result) = (Z_DVAL_P(op1) == Z_DVAL_P(op2));
2054 184 : break;
2055 : case IS_STRING:
2056 88 : Z_LVAL_P(result) = (Z_STRLEN_P(op1) == Z_STRLEN_P(op2))
2057 : && (!memcmp(Z_STRVAL_P(op1), Z_STRVAL_P(op2), Z_STRLEN_P(op1)));
2058 88 : break;
2059 : case IS_UNICODE:
2060 16244 : Z_LVAL_P(result) = (Z_USTRLEN_P(op1) == Z_USTRLEN_P(op2))
2061 : && (!memcmp(Z_USTRVAL_P(op1), Z_USTRVAL_P(op2), UBYTES(Z_USTRLEN_P(op1))));
2062 16244 : break;
2063 : case IS_ARRAY:
2064 63 : Z_LVAL_P(result) = zend_hash_compare(Z_ARRVAL_P(op1), Z_ARRVAL_P(op2), (compare_func_t) hash_zval_identical_function, 1 TSRMLS_CC)==0;
2065 63 : break;
2066 : case IS_OBJECT:
2067 33 : if (Z_OBJ_HT_P(op1) == Z_OBJ_HT_P(op2)) {
2068 33 : Z_LVAL_P(result) = (Z_OBJ_HANDLE_P(op1) == Z_OBJ_HANDLE_P(op2));
2069 : } else {
2070 0 : Z_LVAL_P(result) = 0;
2071 : }
2072 33 : break;
2073 : default:
2074 0 : Z_LVAL_P(result) = 0;
2075 0 : return FAILURE;
2076 : }
2077 1070862 : return SUCCESS;
2078 : }
2079 : /* }}} */
2080 :
2081 : ZEND_API int is_not_identical_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */
2082 0 : {
2083 0 : if (is_identical_function(result, op1, op2 TSRMLS_CC) == FAILURE) {
2084 0 : return FAILURE;
2085 : }
2086 0 : Z_LVAL_P(result) = !Z_LVAL_P(result);
2087 0 : return SUCCESS;
2088 : }
2089 : /* }}} */
2090 :
2091 : ZEND_API int is_equal_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */
2092 345618 : {
2093 345618 : if (compare_function(result, op1, op2 TSRMLS_CC) == FAILURE) {
2094 0 : return FAILURE;
2095 : }
2096 345618 : ZVAL_BOOL(result, (Z_LVAL_P(result) == 0));
2097 345618 : return SUCCESS;
2098 : }
2099 : /* }}} */
2100 :
2101 : ZEND_API int is_not_equal_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */
2102 0 : {
2103 0 : if (compare_function(result, op1, op2 TSRMLS_CC) == FAILURE) {
2104 0 : return FAILURE;
2105 : }
2106 0 : ZVAL_BOOL(result, (Z_LVAL_P(result) != 0));
2107 0 : return SUCCESS;
2108 : }
2109 : /* }}} */
2110 :
2111 : ZEND_API int is_smaller_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */
2112 1898 : {
2113 1898 : if (compare_function(result, op1, op2 TSRMLS_CC) == FAILURE) {
2114 0 : return FAILURE;
2115 : }
2116 1898 : ZVAL_BOOL(result, (Z_LVAL_P(result) < 0));
2117 1898 : return SUCCESS;
2118 : }
2119 : /* }}} */
2120 :
2121 : ZEND_API int is_smaller_or_equal_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */
2122 1277 : {
2123 1277 : if (compare_function(result, op1, op2 TSRMLS_CC) == FAILURE) {
2124 0 : return FAILURE;
2125 : }
2126 1277 : ZVAL_BOOL(result, (Z_LVAL_P(result) <= 0));
2127 1277 : return SUCCESS;
2128 : }
2129 : /* }}} */
2130 :
2131 : ZEND_API zend_bool instanceof_function_ex(const zend_class_entry *instance_ce, const zend_class_entry *ce, zend_bool interfaces_only TSRMLS_DC) /* {{{ */
2132 346380 : {
2133 : zend_uint i;
2134 :
2135 521917 : for (i=0; i<instance_ce->num_interfaces; i++) {
2136 195588 : if (instanceof_function(instance_ce->interfaces[i], ce TSRMLS_CC)) {
2137 20051 : return 1;
2138 : }
2139 : }
2140 326329 : if (!interfaces_only) {
2141 855035 : while (instance_ce) {
2142 335810 : if (instance_ce == ce) {
2143 133427 : return 1;
2144 : }
2145 202383 : instance_ce = instance_ce->parent;
2146 : }
2147 : }
2148 :
2149 192902 : return 0;
2150 : }
2151 : /* }}} */
2152 :
2153 : ZEND_API zend_bool instanceof_function(const zend_class_entry *instance_ce, const zend_class_entry *ce TSRMLS_DC) /* {{{ */
2154 328404 : {
2155 328404 : return instanceof_function_ex(instance_ce, ce, 0 TSRMLS_CC);
2156 : }
2157 : /* }}} */
2158 :
2159 : #define LOWER_CASE 1
2160 : #define UPPER_CASE 2
2161 : #define NUMERIC 3
2162 :
2163 : static void increment_string(zval *str) /* {{{ */
2164 0 : {
2165 0 : int carry=0;
2166 0 : int pos=Z_STRLEN_P(str)-1;
2167 0 : char *s=Z_STRVAL_P(str);
2168 : char *t;
2169 0 : int last=0; /* Shut up the compiler warning */
2170 : int ch;
2171 :
2172 0 : if (Z_STRLEN_P(str) == 0) {
2173 0 : STR_FREE(Z_STRVAL_P(str));
2174 0 : Z_STRVAL_P(str) = estrndup("1", sizeof("1")-1);
2175 0 : Z_STRLEN_P(str) = 1;
2176 0 : return;
2177 : }
2178 :
2179 0 : while (pos >= 0) {
2180 0 : ch = s[pos];
2181 0 : if (ch >= 'a' && ch <= 'z') {
2182 0 : if (ch == 'z') {
2183 0 : s[pos] = 'a';
2184 0 : carry=1;
2185 : } else {
2186 0 : s[pos]++;
2187 0 : carry=0;
2188 : }
2189 0 : last=LOWER_CASE;
2190 0 : } else if (ch >= 'A' && ch <= 'Z') {
2191 0 : if (ch == 'Z') {
2192 0 : s[pos] = 'A';
2193 0 : carry=1;
2194 : } else {
2195 0 : s[pos]++;
2196 0 : carry=0;
2197 : }
2198 0 : last=UPPER_CASE;
2199 0 : } else if (ch >= '0' && ch <= '9') {
2200 0 : if (ch == '9') {
2201 0 : s[pos] = '0';
2202 0 : carry=1;
2203 : } else {
2204 0 : s[pos]++;
2205 0 : carry=0;
2206 : }
2207 0 : last = NUMERIC;
2208 : } else {
2209 0 : carry=0;
2210 0 : break;
2211 : }
2212 0 : if (carry == 0) {
2213 0 : break;
2214 : }
2215 0 : pos--;
2216 : }
2217 :
2218 0 : if (carry) {
2219 0 : t = (char *) emalloc(Z_STRLEN_P(str)+1+1);
2220 0 : memcpy(t+1, Z_STRVAL_P(str), Z_STRLEN_P(str));
2221 0 : Z_STRLEN_P(str)++;
2222 0 : t[Z_STRLEN_P(str)] = '\0';
2223 0 : switch (last) {
2224 : case NUMERIC:
2225 0 : t[0] = '1';
2226 0 : break;
2227 : case UPPER_CASE:
2228 0 : t[0] = 'A';
2229 0 : break;
2230 : case LOWER_CASE:
2231 0 : t[0] = 'a';
2232 : break;
2233 : }
2234 0 : STR_FREE(Z_STRVAL_P(str));
2235 0 : Z_STRVAL_P(str) = t;
2236 : }
2237 : }
2238 : /* }}} */
2239 :
2240 : static void increment_unicode(zval *str) /* {{{ */
2241 41 : {
2242 41 : int carry=0;
2243 41 : int pos=Z_USTRLEN_P(str)-1;
2244 41 : UChar *s=Z_USTRVAL_P(str);
2245 : UChar *t;
2246 41 : int last=0; /* Shut up the compiler warning */
2247 : int ch;
2248 :
2249 41 : if (Z_USTRLEN_P(str) == 0) {
2250 1 : USTR_FREE(Z_USTRVAL_P(str));
2251 1 : ZVAL_ASCII_STRINGL(str, "1", sizeof("1")-1, 1);
2252 1 : return;
2253 : }
2254 :
2255 84 : while (pos >= 0) {
2256 44 : ch = s[pos];
2257 76 : if (ch >= 'a' && ch <= 'z') {
2258 32 : if (ch == 'z') {
2259 2 : s[pos] = 'a';
2260 2 : carry=1;
2261 : } else {
2262 30 : s[pos]++;
2263 30 : carry=0;
2264 : }
2265 32 : last=LOWER_CASE;
2266 18 : } else if (ch >= 'A' && ch <= 'Z') {
2267 6 : if (ch == 'Z') {
2268 0 : s[pos] = 'A';
2269 0 : carry=1;
2270 : } else {
2271 6 : s[pos]++;
2272 6 : carry=0;
2273 : }
2274 6 : last=UPPER_CASE;
2275 8 : } else if (ch >= '0' && ch <= '9') {
2276 2 : if (ch == '9') {
2277 2 : s[pos] = '0';
2278 2 : carry=1;
2279 : } else {
2280 0 : s[pos]++;
2281 0 : carry=0;
2282 : }
2283 2 : last = NUMERIC;
2284 : } else {
2285 4 : carry=0;
2286 4 : break;
2287 : }
2288 40 : if (carry == 0) {
2289 36 : break;
2290 : }
2291 4 : pos--;
2292 : }
2293 :
2294 40 : if (carry) {
2295 0 : t = (UChar *) eumalloc(Z_USTRLEN_P(str)+1+1);
2296 0 : memcpy(t+1, Z_USTRVAL_P(str), UBYTES(Z_USTRLEN_P(str)));
2297 0 : Z_USTRLEN_P(str)++;
2298 0 : t[Z_USTRLEN_P(str)] = 0;
2299 0 : switch (last) {
2300 : case NUMERIC:
2301 0 : t[0] = '1';
2302 0 : break;
2303 : case UPPER_CASE:
2304 0 : t[0] = 'A';
2305 0 : break;
2306 : case LOWER_CASE:
2307 0 : t[0] = 'a';
2308 : break;
2309 : }
2310 0 : USTR_FREE(Z_USTRVAL_P(str));
2311 0 : Z_USTRVAL_P(str) = t;
2312 : }
2313 : }
2314 : /* }}} */
2315 :
2316 : ZEND_API int increment_function(zval *op1) /* {{{ */
2317 11944380 : {
2318 11944380 : switch (Z_TYPE_P(op1)) {
2319 : case IS_LONG:
2320 11944187 : if (Z_LVAL_P(op1) == LONG_MAX) {
2321 : /* switch to double */
2322 2 : double d = (double)Z_LVAL_P(op1);
2323 2 : ZVAL_DOUBLE(op1, d+1);
2324 : } else {
2325 11944185 : Z_LVAL_P(op1)++;
2326 : }
2327 11944187 : break;
2328 : case IS_DOUBLE:
2329 1 : Z_DVAL_P(op1) = Z_DVAL_P(op1) + 1;
2330 1 : break;
2331 : case IS_NULL:
2332 24 : ZVAL_LONG(op1, 1);
2333 24 : break;
2334 : case IS_STRING: {
2335 : long lval;
2336 : double dval;
2337 :
2338 7 : switch (is_numeric_string(Z_STRVAL_P(op1), Z_STRLEN_P(op1), &lval, &dval, 0)) {
2339 : case IS_LONG:
2340 7 : efree(Z_STRVAL_P(op1));
2341 7 : if (lval == LONG_MAX) {
2342 : /* switch to double */
2343 0 : double d = (double)lval;
2344 0 : ZVAL_DOUBLE(op1, d+1);
2345 : } else {
2346 7 : ZVAL_LONG(op1, lval+1);
2347 : }
2348 7 : break;
2349 : case IS_DOUBLE:
2350 0 : efree(Z_STRVAL_P(op1));
2351 0 : ZVAL_DOUBLE(op1, dval+1);
2352 0 : break;
2353 : default:
2354 : /* Perl style string increment */
2355 0 : increment_string(op1);
2356 : break;
2357 : }
2358 : }
2359 7 : break;
2360 : case IS_UNICODE: {
2361 : long lval;
2362 : double dval;
2363 :
2364 156 : switch (is_numeric_unicode(Z_USTRVAL_P(op1), Z_USTRLEN_P(op1), &lval, &dval, 0)) {
2365 : case IS_LONG:
2366 108 : efree(Z_USTRVAL_P(op1));
2367 108 : if (lval == LONG_MAX) {
2368 : /* switch to double */
2369 1 : double d = (double)lval;
2370 1 : ZVAL_DOUBLE(op1, d+1);
2371 : } else {
2372 107 : ZVAL_LONG(op1, lval+1);
2373 : }
2374 108 : break;
2375 : case IS_DOUBLE:
2376 7 : efree(Z_USTRVAL_P(op1));
2377 7 : ZVAL_DOUBLE(op1, dval+1);
2378 7 : break;
2379 : default:
2380 : /* Perl style string increment */
2381 41 : increment_unicode(op1);
2382 : break;
2383 : }
2384 : }
2385 156 : break;
2386 : default:
2387 5 : return FAILURE;
2388 : }
2389 11944375 : return SUCCESS;
2390 : }
2391 : /* }}} */
2392 :
2393 : ZEND_API int decrement_function(zval *op1) /* {{{ */
2394 15360550 : {
2395 : long lval;
2396 : double dval;
2397 :
2398 15360550 : switch (Z_TYPE_P(op1)) {
2399 : case IS_LONG:
2400 9524562 : if (Z_LVAL_P(op1) == LONG_MIN) {
2401 1 : double d = (double)Z_LVAL_P(op1);
2402 1 : ZVAL_DOUBLE(op1, d-1);
2403 : } else {
2404 9524561 : Z_LVAL_P(op1)--;
2405 : }
2406 9524562 : break;
2407 : case IS_DOUBLE:
2408 5835949 : Z_DVAL_P(op1) = Z_DVAL_P(op1) - 1;
2409 5835949 : break;
2410 : case IS_STRING: /* Like perl we only support string increment */
2411 0 : if (Z_STRLEN_P(op1) == 0) { /* consider as 0 */
2412 0 : STR_FREE(Z_STRVAL_P(op1));
2413 0 : ZVAL_LONG(op1, -1);
2414 0 : break;
2415 : }
2416 0 : switch (is_numeric_string(Z_STRVAL_P(op1), Z_STRLEN_P(op1), &lval, &dval, 0)) {
2417 : case IS_LONG:
2418 0 : STR_FREE(Z_STRVAL_P(op1));
2419 0 : if (lval == LONG_MIN) {
2420 0 : double d = (double)lval;
2421 0 : ZVAL_DOUBLE(op1, d-1);
2422 : } else {
2423 0 : ZVAL_LONG(op1, lval-1);
2424 : }
2425 0 : break;
2426 : case IS_DOUBLE:
2427 0 : STR_FREE(Z_STRVAL_P(op1));
2428 0 : ZVAL_DOUBLE(op1, dval - 1);
2429 : break;
2430 : }
2431 0 : break;
2432 : case IS_UNICODE:
2433 33 : if (Z_USTRLEN_P(op1) == 0) { /* consider as 0 */
2434 1 : USTR_FREE(Z_USTRVAL_P(op1));
2435 1 : ZVAL_LONG(op1, -1);
2436 1 : break;
2437 : }
2438 32 : switch (is_numeric_unicode(Z_USTRVAL_P(op1), Z_USTRLEN_P(op1), &lval, &dval, 0)) {
2439 : case IS_LONG:
2440 8 : USTR_FREE(Z_USTRVAL_P(op1));
2441 8 : if (lval == LONG_MIN) {
2442 1 : double d = (double)lval;
2443 1 : ZVAL_DOUBLE(op1, d-1);
2444 : } else {
2445 7 : ZVAL_LONG(op1, lval-1);
2446 : }
2447 8 : break;
2448 : case IS_DOUBLE:
2449 7 : USTR_FREE(Z_USTRVAL_P(op1));
2450 7 : ZVAL_DOUBLE(op1, dval - 1);
2451 : break;
2452 : }
2453 32 : break;
2454 : default:
2455 6 : return FAILURE;
2456 : }
2457 :
2458 15360544 : return SUCCESS;
2459 : }
2460 : /* }}} */
2461 :
2462 : ZEND_API int zval_is_true(zval *op) /* {{{ */
2463 3431 : {
2464 3431 : convert_to_boolean(op);
2465 3431 : return (Z_LVAL_P(op) ? 1 : 0);
2466 : }
2467 : /* }}} */
2468 :
2469 : #ifdef ZEND_USE_TOLOWER_L
2470 : ZEND_API void zend_update_current_locale(void) /* {{{ */
2471 : {
2472 : current_locale = _get_current_locale();
2473 : }
2474 : /* }}} */
2475 : #endif
2476 :
2477 : ZEND_API char *zend_str_tolower_copy(char *dest, const char *source, unsigned int length) /* {{{ */
2478 57309660 : {
2479 57309660 : register unsigned char *str = (unsigned char*)source;
2480 57309660 : register unsigned char *result = (unsigned char*)dest;
2481 57309660 : register unsigned char *end = str + length;
2482 :
2483 815912359 : while (str < end) {
2484 701293039 : *result++ = zend_tolower((int)*str++);
2485 : }
2486 57309660 : *result = '\0';
2487 :
2488 57309660 : return dest;
2489 : }
2490 : /* }}} */
2491 :
2492 : ZEND_API char *zend_str_tolower_dup(const char *source, unsigned int length) /* {{{ */
2493 57309630 : {
2494 57309630 : return zend_str_tolower_copy((char *)emalloc(length+1), source, length);
2495 : }
2496 : /* }}} */
2497 :
2498 : ZEND_API zstr zend_u_str_tolower_copy(zend_uchar type, zstr dest, zstr source, unsigned int length) /* {{{ */
2499 14489 : {
2500 14489 : if (type == IS_UNICODE) {
2501 14489 : register UChar *str = source.u;
2502 14489 : register UChar *result = dest.u;
2503 14489 : register UChar *end = str + length;
2504 :
2505 138739 : while (str < end) {
2506 109761 : *result++ = u_tolower((int)*str++);
2507 : }
2508 14489 : *result = '\0';
2509 :
2510 14489 : return dest;
2511 : } else {
2512 : zstr ret;
2513 :
2514 0 : ret.s = zend_str_tolower_copy(dest.s, source.s, length);
2515 0 : return ret;
2516 : }
2517 : }
2518 : /* }}} */
2519 :
2520 : ZEND_API zstr zend_u_str_tolower_dup(zend_uchar type, zstr source, unsigned int length) /* {{{ */
2521 14489 : {
2522 : zstr ret;
2523 :
2524 14489 : if (type == IS_UNICODE) {
2525 14489 : ret.u = eumalloc(length+1);
2526 14489 : ret = zend_u_str_tolower_copy(IS_UNICODE, ret, source, length);
2527 : } else {
2528 0 : ret.s = zend_str_tolower_copy((char*)emalloc(length+1), source.s, length);
2529 : }
2530 14489 : return ret;
2531 : }
2532 : /* }}} */
2533 :
2534 : ZEND_API void zend_str_tolower(char *str, unsigned int length) /* {{{ */
2535 775246 : {
2536 775246 : register unsigned char *p = (unsigned char*)str;
2537 775246 : register unsigned char *end = p + length;
2538 :
2539 7806627 : while (p < end) {
2540 6256135 : *p = zend_tolower((int)*p);
2541 6256135 : p++;
2542 : }
2543 775246 : }
2544 : /* }}} */
2545 :
2546 : ZEND_API void zend_u_str_tolower(zend_uchar type, zstr str, unsigned int length) /* {{{ */
2547 51 : {
2548 51 : if (type == IS_UNICODE) {
2549 51 : register UChar *p = str.u;
2550 51 : register UChar *end = p + length;
2551 :
2552 936 : while (p < end) {
2553 834 : *p = u_tolower((int)*p);
2554 834 : p++;
2555 : }
2556 : } else {
2557 0 : zend_str_tolower(str.s, length);
2558 : }
2559 51 : }
2560 : /* }}} */
2561 :
2562 : ZEND_API zstr zend_u_str_case_fold(zend_uchar type, zstr source, unsigned int length, zend_bool normalize, unsigned int *new_len) /* {{{ */
2563 29740342 : {
2564 : zstr ret;
2565 :
2566 29740342 : if (type == IS_UNICODE) {
2567 29732649 : int ret_len = length;
2568 :
2569 29732649 : if (normalize) {
2570 1470375 : if (zend_normalize_identifier(&ret.u, &ret_len, source.u, length, 1) == FAILURE) {
2571 0 : zend_error(E_NOTICE, "Could not normalize identifier");
2572 0 : ret.u = eustrndup(source.u, length);
2573 : }
2574 : } else {
2575 28262274 : UErrorCode status = U_ZERO_ERROR;
2576 :
2577 28262274 : zend_case_fold_string(&ret.u, &ret_len, source.u, length, U_FOLD_CASE_DEFAULT, &status);
2578 28262274 : if (U_FAILURE(status)) {
2579 0 : zend_error(E_NOTICE, "Could not case-fold string");
2580 0 : ret.u = eustrndup(source.u, length);
2581 : }
2582 : }
2583 :
2584 29732649 : *new_len = ret_len;
2585 : } else {
2586 7693 : *new_len = length;
2587 7693 : ret.s = zend_str_tolower_dup(source.s, length);
2588 : }
2589 29740342 : return ret;
2590 : }
2591 : /* }}} */
2592 :
2593 : ZEND_API int zend_binary_strcmp(const char *s1, uint len1, const char *s2, uint len2) /* {{{ */
2594 4492365 : {
2595 : int retval;
2596 :
2597 4492365 : retval = memcmp(s1, s2, MIN(len1, len2));
2598 4492365 : if (!retval) {
2599 1392260 : return (len1 - len2);
2600 : } else {
2601 3100105 : return retval;
2602 : }
2603 : }
2604 : /* }}} */
2605 :
2606 : ZEND_API int zend_u_binary_strcmp(UChar *s1, int len1, UChar *s2, int len2) /* {{{ */
2607 1558537 : {
2608 1558537 : int result = u_strCompare(s1, len1, s2, len2, 1);
2609 1558537 : return ZEND_NORMALIZE_BOOL(result);
2610 : }
2611 : /* }}} */
2612 :
2613 : ZEND_API int zend_binary_strncmp(const char *s1, uint len1, const char *s2, uint len2, uint length) /* {{{ */
2614 1 : {
2615 : int retval;
2616 :
2617 1 : retval = memcmp(s1, s2, MIN(length, MIN(len1, len2)));
2618 1 : if (!retval) {
2619 1 : return (MIN(length, len1) - MIN(length, len2));
2620 : } else {
2621 0 : return retval;
2622 : }
2623 : }
2624 : /* }}} */
2625 :
2626 : ZEND_API int zend_u_binary_strncmp(UChar *s1, int len1, UChar *s2, int len2, uint length) /* {{{ */
2627 11841 : {
2628 11841 : int32_t off1 = 0, off2 = 0;
2629 : UChar32 c1, c2;
2630 11841 : int result = 0;
2631 :
2632 102957 : for( ; length > 0; --length) {
2633 91532 : if (off1 >= len1 || off2 >= len2) {
2634 181 : result = len1 - len2;
2635 181 : return ZEND_NORMALIZE_BOOL(result);
2636 : }
2637 91351 : U16_NEXT(s1, off1, len1, c1);
2638 91351 : U16_NEXT(s2, off2, len2, c2);
2639 91351 : if (c1 != c2) {
2640 235 : result = (int32_t)c1-(int32_t)c2;
2641 235 : return ZEND_NORMALIZE_BOOL(result);
2642 : }
2643 : }
2644 :
2645 11425 : return 0;
2646 : }
2647 : /* }}} */
2648 :
2649 : ZEND_API int zend_binary_strcasecmp(const char *s1, uint len1, const char *s2, uint len2) /* {{{ */
2650 97689 : {
2651 : int len;
2652 : int c1, c2;
2653 :
2654 97689 : len = MIN(len1, len2);
2655 :
2656 415591 : while (len--) {
2657 317902 : c1 = zend_tolower((int)*(unsigned char *)s1++);
2658 317902 : c2 = zend_tolower((int)*(unsigned char *)s2++);
2659 317902 : if (c1 != c2) {
2660 97689 : return c1 - c2;
2661 : }
2662 : }
2663 :
2664 0 : return len1 - len2;
2665 : }
2666 : /* }}} */
2667 :
2668 : ZEND_API int zend_u_binary_strcasecmp(UChar *s1, int len1, UChar *s2, int len2) /* {{{ */
2669 1001 : {
2670 1001 : UErrorCode status = U_ZERO_ERROR;
2671 1001 : int result = u_strCaseCompare(s1, len1, s2, len2, U_COMPARE_CODE_POINT_ORDER, &status);
2672 1001 : return ZEND_NORMALIZE_BOOL(result);
2673 : }
2674 : /* }}} */
2675 :
2676 : ZEND_API int zend_binary_strncasecmp(const char *s1, uint len1, const char *s2, uint len2, uint length) /* {{{ */
2677 0 : {
2678 : int len;
2679 : int c1, c2;
2680 :
2681 0 : len = MIN(length, MIN(len1, len2));
2682 :
2683 0 : while (len--) {
2684 0 : c1 = zend_tolower((int)*(unsigned char *)s1++);
2685 0 : c2 = zend_tolower((int)*(unsigned char *)s2++);
2686 0 : if (c1 != c2) {
2687 0 : return c1 - c2;
2688 : }
2689 : }
2690 :
2691 0 : return MIN(length, len1) - MIN(length, len2);
2692 : }
2693 : /* }}} */
2694 :
2695 : /*
2696 : * Because we do not know UChar offsets for the passed-in limit of the number of
2697 : * codepoints to compare, we take a hit upfront by iterating over both strings
2698 : * until we find them. Then we can simply use u_strCaseCompare().
2699 : */
2700 : ZEND_API int zend_u_binary_strncasecmp(UChar *s1, int len1, UChar *s2, int len2, uint length) /* {{{ */
2701 16526 : {
2702 16526 : UErrorCode status = U_ZERO_ERROR;
2703 16526 : int32_t off1 = 0, off2 = 0;
2704 : int result;
2705 :
2706 16526 : U16_FWD_N(s1, off1, len1, length);
2707 16526 : U16_FWD_N(s2, off2, len2, length);
2708 16526 : result = u_strCaseCompare(s1, off1, s2, off2, U_COMPARE_CODE_POINT_ORDER, &status);
2709 16526 : return ZEND_NORMALIZE_BOOL(result);
2710 : }
2711 : /* }}} */
2712 :
2713 : ZEND_API int zend_binary_zval_strcmp(zval *s1, zval *s2) /* {{{ */
2714 2467 : {
2715 2467 : return zend_binary_strcmp(Z_STRVAL_P(s1), Z_STRLEN_P(s1), Z_STRVAL_P(s2), Z_STRLEN_P(s2));
2716 : }
2717 : /* }}} */
2718 :
2719 : ZEND_API int zend_u_binary_zval_strcmp(zval *s1, zval *s2) /* {{{ */
2720 1331500 : {
2721 1331500 : return zend_u_binary_strcmp(Z_USTRVAL_P(s1), Z_USTRLEN_P(s1), Z_USTRVAL_P(s2), Z_USTRLEN_P(s2));
2722 : }
2723 : /* }}} */
2724 :
2725 : ZEND_API int zend_binary_zval_strncmp(zval *s1, zval *s2, zval *s3) /* {{{ */
2726 0 : {
2727 0 : return zend_binary_strncmp(Z_STRVAL_P(s1), Z_STRLEN_P(s1), Z_STRVAL_P(s2), Z_STRLEN_P(s2), Z_LVAL_P(s3));
2728 : }
2729 : /* }}} */
2730 :
2731 : ZEND_API int zend_binary_zval_strcasecmp(zval *s1, zval *s2) /* {{{ */
2732 0 : {
2733 0 : return zend_binary_strcasecmp(Z_STRVAL_P(s1), Z_STRLEN_P(s1), Z_STRVAL_P(s2), Z_STRLEN_P(s2));
2734 : }
2735 : /* }}} */
2736 :
2737 : ZEND_API int zend_binary_zval_strncasecmp(zval *s1, zval *s2, zval *s3) /* {{{ */
2738 0 : {
2739 0 : return zend_binary_strncasecmp(Z_STRVAL_P(s1), Z_STRLEN_P(s1), Z_STRVAL_P(s2), Z_STRLEN_P(s2), Z_LVAL_P(s3));
2740 : }
2741 : /* }}} */
2742 :
2743 : ZEND_API void zendi_smart_strcmp(zval *result, zval *s1, zval *s2) /* {{{ */
2744 2552 : {
2745 : int ret1, ret2;
2746 : long lval1, lval2;
2747 : double dval1, dval2;
2748 :
2749 2637 : if ((ret1=is_numeric_string(Z_STRVAL_P(s1), Z_STRLEN_P(s1), &lval1, &dval1, 0)) &&
2750 : (ret2=is_numeric_string(Z_STRVAL_P(s2), Z_STRLEN_P(s2), &lval2, &dval2, 0))) {
2751 87 : if ((ret1==IS_DOUBLE) || (ret2==IS_DOUBLE)) {
2752 2 : if (ret1!=IS_DOUBLE) {
2753 0 : dval1 = (double) lval1;
2754 2 : } else if (ret2!=IS_DOUBLE) {
2755 0 : dval2 = (double) lval2;
2756 2 : } else if (dval1 == dval2 && !zend_finite(dval1)) {
2757 : /* Both values overflowed and have the same sign,
2758 : * so a numeric comparison would be inaccurate */
2759 0 : goto string_cmp;
2760 : }
2761 2 : Z_DVAL_P(result) = dval1 - dval2;
2762 2 : ZVAL_LONG(result, ZEND_NORMALIZE_BOOL(Z_DVAL_P(result)));
2763 : } else { /* they both have to be long's */
2764 83 : ZVAL_LONG(result, lval1 > lval2 ? 1 : (lval1 < lval2 ? -1 : 0));
2765 : }
2766 : } else {
2767 2467 : string_cmp:
2768 2467 : Z_LVAL_P(result) = zend_binary_zval_strcmp(s1, s2);
2769 2467 : ZVAL_LONG(result, ZEND_NORMALIZE_BOOL(Z_LVAL_P(result)));
2770 : }
2771 2552 : }
2772 : /* }}} */
2773 :
2774 : ZEND_API void zendi_u_smart_strcmp(zval *result, zval *s1, zval *s2) /* {{{ */
2775 946484 : {
2776 : int ret1, ret2;
2777 : long lval1, lval2;
2778 : double dval1, dval2;
2779 : zval s1_copy, s2_copy;
2780 946484 : int use_copy1 = 0, use_copy2 = 0;
2781 :
2782 946484 : if (Z_TYPE_P(s1) != IS_UNICODE || Z_TYPE_P(s2) != IS_UNICODE) {
2783 1008 : zend_make_unicode_zval(s1, &s1_copy, &use_copy1);
2784 1008 : zend_make_unicode_zval(s2, &s2_copy, &use_copy2);
2785 1008 : if (use_copy1) {
2786 467 : s1 = &s1_copy;
2787 : }
2788 1008 : if (use_copy2) {
2789 541 : s2 = &s2_copy;
2790 : }
2791 : }
2792 :
2793 1254080 : if ((ret1=is_numeric_unicode(Z_USTRVAL_P(s1), Z_USTRLEN_P(s1), &lval1, &dval1, 0)) &&
2794 : (ret2=is_numeric_unicode(Z_USTRVAL_P(s2), Z_USTRLEN_P(s2), &lval2, &dval2, 0))) {
2795 408604 : if ((ret1==IS_DOUBLE) || (ret2==IS_DOUBLE)) {
2796 101008 : if (ret1!=IS_DOUBLE) {
2797 24 : dval1 = (double) lval1;
2798 100984 : } else if (ret2!=IS_DOUBLE) {
2799 20 : dval2 = (double) lval2;
2800 100964 : } else if (dval1 == dval2 && !zend_finite(dval1)) {
2801 : /* Both values overflowed and have the same sign,
2802 : * so a numeric comparison would be inaccurate */
2803 0 : goto string_cmp;
2804 : }
2805 101008 : Z_DVAL_P(result) = dval1 - dval2;
2806 101008 : ZVAL_LONG(result, ZEND_NORMALIZE_BOOL(Z_DVAL_P(result)));
2807 : } else { /* they both have to be long's */
2808 206588 : ZVAL_LONG(result, lval1 > lval2 ? 1 : (lval1 < lval2 ? -1 : 0));
2809 : }
2810 : } else {
2811 638888 : string_cmp:
2812 638888 : Z_LVAL_P(result) = zend_u_binary_zval_strcmp(s1, s2);
2813 638888 : ZVAL_LONG(result, ZEND_NORMALIZE_BOOL(Z_LVAL_P(result)));
2814 : }
2815 :
2816 946484 : if (use_copy1) {
2817 467 : zval_dtor(s1);
2818 : }
2819 946484 : if (use_copy2) {
2820 541 : zval_dtor(s2);
2821 : }
2822 946484 : }
2823 : /* }}} */
2824 :
2825 : static int hash_zval_compare_function(const zval **z1, const zval **z2 TSRMLS_DC) /* {{{ */
2826 2275 : {
2827 : zval result;
2828 :
2829 2275 : if (compare_function(&result, (zval *) *z1, (zval *) *z2 TSRMLS_CC)==FAILURE) {
2830 0 : return 1;
2831 : }
2832 2275 : return Z_LVAL(result);
2833 : }
2834 : /* }}} */
2835 :
2836 : ZEND_API int zend_compare_symbol_tables_i(HashTable *ht1, HashTable *ht2 TSRMLS_DC) /* {{{ */
2837 473 : {
2838 473 : return zend_hash_compare(ht1, ht2, (compare_func_t) hash_zval_compare_function, 0 TSRMLS_CC);
2839 : }
2840 : /* }}} */
2841 :
2842 : ZEND_API void zend_compare_symbol_tables(zval *result, HashTable *ht1, HashTable *ht2 TSRMLS_DC) /* {{{ */
2843 678 : {
2844 678 : ZVAL_LONG(result, zend_hash_compare(ht1, ht2, (compare_func_t) hash_zval_compare_function, 0 TSRMLS_CC));
2845 678 : }
2846 : /* }}} */
2847 :
2848 : ZEND_API void zend_compare_arrays(zval *result, zval *a1, zval *a2 TSRMLS_DC) /* {{{ */
2849 678 : {
2850 678 : zend_compare_symbol_tables(result, Z_ARRVAL_P(a1), Z_ARRVAL_P(a2) TSRMLS_CC);
2851 678 : }
2852 : /* }}} */
2853 :
2854 : ZEND_API void zend_compare_objects(zval *result, zval *o1, zval *o2 TSRMLS_DC) /* {{{ */
2855 0 : {
2856 0 : Z_TYPE_P(result) = IS_LONG;
2857 :
2858 0 : if (Z_OBJ_HANDLE_P(o1) == Z_OBJ_HANDLE_P(o2)) {
2859 0 : Z_LVAL_P(result) = 0;
2860 0 : return;
2861 : }
2862 :
2863 0 : if (Z_OBJ_HT_P(o1)->compare_objects == NULL) {
2864 0 : Z_LVAL_P(result) = 1;
2865 : } else {
2866 0 : Z_LVAL_P(result) = Z_OBJ_HT_P(o1)->compare_objects(o1, o2 TSRMLS_CC);
2867 : }
2868 : }
2869 : /* }}} */
2870 :
2871 : ZEND_API void zend_locale_sprintf_double(zval *op ZEND_FILE_LINE_DC) /* {{{ */
2872 667 : {
2873 : TSRMLS_FETCH();
2874 :
2875 667 : Z_STRLEN_P(op) = zend_spprintf(&Z_STRVAL_P(op), 0, "%.*G", (int) EG(precision), (double)Z_DVAL_P(op));
2876 667 : }
2877 : /* }}} */
2878 :
2879 : /*
2880 : * Local variables:
2881 : * tab-width: 4
2882 : * c-basic-offset: 4
2883 : * indent-tabs-mode: t
2884 : * End:
2885 : */
|