1 /*
2 +----------------------------------------------------------------------+
3 | Copyright (c) The PHP Group |
4 +----------------------------------------------------------------------+
5 | This source file is subject to version 3.01 of the PHP license, |
6 | that is bundled with this package in the file LICENSE, and is |
7 | available through the world-wide-web at the following url: |
8 | https://www.php.net/license/3_01.txt |
9 | If you did not receive a copy of the PHP license and are unable to |
10 | obtain it through the world-wide-web, please send a note to |
11 | license@php.net so we can mail you a copy immediately. |
12 +----------------------------------------------------------------------+
13 | Author: Rasmus Lerdorf <rasmus@php.net> |
14 +----------------------------------------------------------------------+
15 */
16
17 #include "php.h"
18
19 /* {{{ Returns the type of the variable */
PHP_FUNCTION(gettype)20 PHP_FUNCTION(gettype)
21 {
22 zval *arg;
23 zend_string *type;
24
25 ZEND_PARSE_PARAMETERS_START(1, 1)
26 Z_PARAM_ZVAL(arg)
27 ZEND_PARSE_PARAMETERS_END();
28
29 type = zend_zval_get_legacy_type(arg);
30 if (EXPECTED(type)) {
31 RETURN_INTERNED_STR(type);
32 } else {
33 RETURN_STRING("unknown type");
34 }
35 }
36 /* }}} */
37
38 /* {{{ Returns the type of the variable resolving class names */
PHP_FUNCTION(get_debug_type)39 PHP_FUNCTION(get_debug_type)
40 {
41 zval *arg;
42 const char *name;
43
44 ZEND_PARSE_PARAMETERS_START(1, 1)
45 Z_PARAM_ZVAL(arg)
46 ZEND_PARSE_PARAMETERS_END();
47
48 switch (Z_TYPE_P(arg)) {
49 case IS_NULL:
50 RETURN_INTERNED_STR(ZSTR_KNOWN(ZEND_STR_NULL_LOWERCASE));
51 case IS_FALSE:
52 case IS_TRUE:
53 RETURN_INTERNED_STR(ZSTR_KNOWN(ZEND_STR_BOOL));
54 case IS_LONG:
55 RETURN_INTERNED_STR(ZSTR_KNOWN(ZEND_STR_INT));
56 case IS_DOUBLE:
57 RETURN_INTERNED_STR(ZSTR_KNOWN(ZEND_STR_FLOAT));
58 case IS_STRING:
59 RETURN_INTERNED_STR(ZSTR_KNOWN(ZEND_STR_STRING));
60 case IS_ARRAY:
61 RETURN_INTERNED_STR(ZSTR_KNOWN(ZEND_STR_ARRAY));
62 case IS_OBJECT:
63 if (Z_OBJ_P(arg)->ce->ce_flags & ZEND_ACC_ANON_CLASS) {
64 name = ZSTR_VAL(Z_OBJ_P(arg)->ce->name);
65 RETURN_NEW_STR(zend_string_init(name, strlen(name), 0));
66 } else {
67 RETURN_STR_COPY(Z_OBJ_P(arg)->ce->name);
68 }
69 case IS_RESOURCE:
70 name = zend_rsrc_list_get_rsrc_type(Z_RES_P(arg));
71 if (name) {
72 RETURN_NEW_STR(zend_strpprintf(0, "resource (%s)", name));
73 } else {
74 RETURN_INTERNED_STR(ZSTR_KNOWN(ZEND_STR_CLOSED_RESOURCE));
75 }
76 default:
77 RETURN_INTERNED_STR(ZSTR_KNOWN(ZEND_STR_UNKNOWN));
78 }
79 }
80 /* }}} */
81
82
83 /* {{{ Set the type of the variable */
PHP_FUNCTION(settype)84 PHP_FUNCTION(settype)
85 {
86 zval *var;
87 zend_string *type;
88 zval tmp, *ptr;
89
90 ZEND_PARSE_PARAMETERS_START(2, 2)
91 Z_PARAM_ZVAL(var)
92 Z_PARAM_STR(type)
93 ZEND_PARSE_PARAMETERS_END();
94
95 ZEND_ASSERT(Z_ISREF_P(var));
96 if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(Z_REF_P(var)))) {
97 ZVAL_COPY(&tmp, Z_REFVAL_P(var));
98 ptr = &tmp;
99 } else {
100 ptr = Z_REFVAL_P(var);
101 }
102 if (zend_string_equals_ci(type, ZSTR_KNOWN(ZEND_STR_INTEGER))) {
103 convert_to_long(ptr);
104 } else if (zend_string_equals_ci(type, ZSTR_KNOWN(ZEND_STR_INT))) {
105 convert_to_long(ptr);
106 } else if (zend_string_equals_ci(type, ZSTR_KNOWN(ZEND_STR_FLOAT))) {
107 convert_to_double(ptr);
108 } else if (zend_string_equals_ci(type, ZSTR_KNOWN(ZEND_STR_DOUBLE))) { /* deprecated */
109 convert_to_double(ptr);
110 } else if (zend_string_equals_ci(type, ZSTR_KNOWN(ZEND_STR_STRING))) {
111 convert_to_string(ptr);
112 } else if (zend_string_equals_ci(type, ZSTR_KNOWN(ZEND_STR_ARRAY))) {
113 convert_to_array(ptr);
114 } else if (zend_string_equals_ci(type, ZSTR_KNOWN(ZEND_STR_OBJECT))) {
115 convert_to_object(ptr);
116 } else if (zend_string_equals_ci(type, ZSTR_KNOWN(ZEND_STR_BOOL))) {
117 convert_to_boolean(ptr);
118 } else if (zend_string_equals_ci(type, ZSTR_KNOWN(ZEND_STR_BOOLEAN))) {
119 convert_to_boolean(ptr);
120 } else if (zend_string_equals_ci(type, ZSTR_KNOWN(ZEND_STR_NULL_LOWERCASE))) {
121 convert_to_null(ptr);
122 } else {
123 if (ptr == &tmp) {
124 zval_ptr_dtor(&tmp);
125 }
126 if (zend_string_equals_ci(type, ZSTR_KNOWN(ZEND_STR_RESOURCE))) {
127 zend_value_error("Cannot convert to resource type");
128 } else {
129 zend_argument_value_error(2, "must be a valid type");
130 }
131 RETURN_THROWS();
132 }
133
134 if (ptr == &tmp) {
135 zend_try_assign_typed_ref(Z_REF_P(var), &tmp);
136 }
137 RETVAL_TRUE;
138 }
139 /* }}} */
140
141 /* {{{ Get the integer value of a variable using the optional base for the conversion */
PHP_FUNCTION(intval)142 PHP_FUNCTION(intval)
143 {
144 zval *num;
145 zend_long base = 10;
146
147 ZEND_PARSE_PARAMETERS_START(1, 2)
148 Z_PARAM_ZVAL(num)
149 Z_PARAM_OPTIONAL
150 Z_PARAM_LONG(base)
151 ZEND_PARSE_PARAMETERS_END();
152
153 if (Z_TYPE_P(num) != IS_STRING || base == 10) {
154 RETVAL_LONG(zval_get_long(num));
155 return;
156 }
157
158
159 if (base == 0 || base == 2) {
160 char *strval = Z_STRVAL_P(num);
161 size_t strlen = Z_STRLEN_P(num);
162
163 while (isspace(*strval) && strlen) {
164 strval++;
165 strlen--;
166 }
167
168 /* Length of 3+ covers "0b#" and "-0b" (which results in 0) */
169 if (strlen > 2) {
170 int offset = 0;
171 if (strval[0] == '-' || strval[0] == '+') {
172 offset = 1;
173 }
174
175 if (strval[offset] == '0' && (strval[offset + 1] == 'b' || strval[offset + 1] == 'B')) {
176 char *tmpval;
177 strlen -= 2; /* Removing "0b" */
178 tmpval = emalloc(strlen + 1);
179
180 /* Place the unary symbol at pos 0 if there was one */
181 if (offset) {
182 tmpval[0] = strval[0];
183 }
184
185 /* Copy the data from after "0b" to the end of the buffer */
186 memcpy(tmpval + offset, strval + offset + 2, strlen - offset);
187 tmpval[strlen] = 0;
188
189 RETVAL_LONG(ZEND_STRTOL(tmpval, NULL, 2));
190 efree(tmpval);
191 return;
192 }
193 }
194 }
195
196 RETVAL_LONG(ZEND_STRTOL(Z_STRVAL_P(num), NULL, base));
197 }
198 /* }}} */
199
200 /* {{{ Get the float value of a variable */
PHP_FUNCTION(floatval)201 PHP_FUNCTION(floatval)
202 {
203 zval *num;
204
205 ZEND_PARSE_PARAMETERS_START(1, 1)
206 Z_PARAM_ZVAL(num)
207 ZEND_PARSE_PARAMETERS_END();
208
209 RETURN_DOUBLE(zval_get_double(num));
210 }
211 /* }}} */
212
213 /* {{{ Get the boolean value of a variable */
PHP_FUNCTION(boolval)214 PHP_FUNCTION(boolval)
215 {
216 zval *value;
217
218 ZEND_PARSE_PARAMETERS_START(1, 1)
219 Z_PARAM_ZVAL(value)
220 ZEND_PARSE_PARAMETERS_END();
221
222 RETURN_BOOL(zend_is_true(value));
223 }
224 /* }}} */
225
226 /* {{{ Get the string value of a variable */
PHP_FUNCTION(strval)227 PHP_FUNCTION(strval)
228 {
229 zval *value;
230
231 ZEND_PARSE_PARAMETERS_START(1, 1)
232 Z_PARAM_ZVAL(value)
233 ZEND_PARSE_PARAMETERS_END();
234
235 RETVAL_STR(zval_get_string(value));
236 }
237 /* }}} */
238
php_is_type(INTERNAL_FUNCTION_PARAMETERS,int type)239 static inline void php_is_type(INTERNAL_FUNCTION_PARAMETERS, int type)
240 {
241 zval *arg;
242
243 ZEND_PARSE_PARAMETERS_START(1, 1)
244 Z_PARAM_ZVAL(arg)
245 ZEND_PARSE_PARAMETERS_END();
246
247 if (Z_TYPE_P(arg) == type) {
248 if (type == IS_RESOURCE) {
249 const char *type_name = zend_rsrc_list_get_rsrc_type(Z_RES_P(arg));
250 if (!type_name) {
251 RETURN_FALSE;
252 }
253 }
254 RETURN_TRUE;
255 } else {
256 RETURN_FALSE;
257 }
258 }
259
260
261 /* {{{ Returns true if variable is null
262 Warning: This function is special-cased by zend_compile.c and so is usually bypassed */
PHP_FUNCTION(is_null)263 PHP_FUNCTION(is_null)
264 {
265 php_is_type(INTERNAL_FUNCTION_PARAM_PASSTHRU, IS_NULL);
266 }
267 /* }}} */
268
269 /* {{{ Returns true if variable is a resource
270 Warning: This function is special-cased by zend_compile.c and so is usually bypassed */
PHP_FUNCTION(is_resource)271 PHP_FUNCTION(is_resource)
272 {
273 php_is_type(INTERNAL_FUNCTION_PARAM_PASSTHRU, IS_RESOURCE);
274 }
275 /* }}} */
276
277 /* {{{ Returns true if variable is a boolean
278 Warning: This function is special-cased by zend_compile.c and so is usually bypassed */
PHP_FUNCTION(is_bool)279 PHP_FUNCTION(is_bool)
280 {
281 zval *arg;
282
283 ZEND_PARSE_PARAMETERS_START(1, 1)
284 Z_PARAM_ZVAL(arg)
285 ZEND_PARSE_PARAMETERS_END();
286
287 RETURN_BOOL(Z_TYPE_P(arg) == IS_FALSE || Z_TYPE_P(arg) == IS_TRUE);
288 }
289 /* }}} */
290
291 /* {{{ Returns true if variable is an integer
292 Warning: This function is special-cased by zend_compile.c and so is usually bypassed */
PHP_FUNCTION(is_int)293 PHP_FUNCTION(is_int)
294 {
295 php_is_type(INTERNAL_FUNCTION_PARAM_PASSTHRU, IS_LONG);
296 }
297 /* }}} */
298
299 /* {{{ Returns true if variable is float point
300 Warning: This function is special-cased by zend_compile.c and so is usually bypassed */
PHP_FUNCTION(is_float)301 PHP_FUNCTION(is_float)
302 {
303 php_is_type(INTERNAL_FUNCTION_PARAM_PASSTHRU, IS_DOUBLE);
304 }
305 /* }}} */
306
307 /* {{{ Returns true if variable is a string
308 Warning: This function is special-cased by zend_compile.c and so is usually bypassed */
PHP_FUNCTION(is_string)309 PHP_FUNCTION(is_string)
310 {
311 php_is_type(INTERNAL_FUNCTION_PARAM_PASSTHRU, IS_STRING);
312 }
313 /* }}} */
314
315 /* {{{ Returns true if variable is an array
316 Warning: This function is special-cased by zend_compile.c and so is usually bypassed */
PHP_FUNCTION(is_array)317 PHP_FUNCTION(is_array)
318 {
319 php_is_type(INTERNAL_FUNCTION_PARAM_PASSTHRU, IS_ARRAY);
320 }
321 /* }}} */
322
323 /* {{{ Returns true if $array is an array whose keys are all numeric, sequential, and start at 0 */
PHP_FUNCTION(array_is_list)324 PHP_FUNCTION(array_is_list)
325 {
326 HashTable *array;
327
328 ZEND_PARSE_PARAMETERS_START(1, 1)
329 Z_PARAM_ARRAY_HT(array)
330 ZEND_PARSE_PARAMETERS_END();
331
332 RETURN_BOOL(zend_array_is_list(array));
333 }
334 /* }}} */
335
336 /* {{{ Returns true if variable is an object
337 Warning: This function is special-cased by zend_compile.c and so is usually bypassed */
PHP_FUNCTION(is_object)338 PHP_FUNCTION(is_object)
339 {
340 php_is_type(INTERNAL_FUNCTION_PARAM_PASSTHRU, IS_OBJECT);
341 }
342 /* }}} */
343
_zend_is_numeric(zval * return_value,zval * arg)344 static inline void _zend_is_numeric(zval *return_value, zval *arg)
345 {
346 switch (Z_TYPE_P(arg)) {
347 case IS_LONG:
348 case IS_DOUBLE:
349 RETURN_TRUE;
350 break;
351
352 case IS_STRING:
353 if (is_numeric_string(Z_STRVAL_P(arg), Z_STRLEN_P(arg), NULL, NULL, 0)) {
354 RETURN_TRUE;
355 } else {
356 RETURN_FALSE;
357 }
358 break;
359
360 default:
361 RETURN_FALSE;
362 break;
363 }
364 }
365
366 /* {{{ Returns true if value is a number or a numeric string */
PHP_FUNCTION(is_numeric)367 PHP_FUNCTION(is_numeric)
368 {
369 zval *arg;
370
371 ZEND_PARSE_PARAMETERS_START(1, 1)
372 Z_PARAM_ZVAL(arg)
373 ZEND_PARSE_PARAMETERS_END();
374
375 _zend_is_numeric(return_value, arg);
376 }
377 /* }}} */
378
379 ZEND_FRAMELESS_FUNCTION(is_numeric, 1)
380 {
381 zval *arg;
382
383 Z_FLF_PARAM_ZVAL(1, arg);
384
385 _zend_is_numeric(return_value, arg);
386 }
387
388 /* {{{ Returns true if value is a scalar */
PHP_FUNCTION(is_scalar)389 PHP_FUNCTION(is_scalar)
390 {
391 zval *arg;
392
393 ZEND_PARSE_PARAMETERS_START(1, 1)
394 Z_PARAM_ZVAL(arg)
395 ZEND_PARSE_PARAMETERS_END();
396
397 switch (Z_TYPE_P(arg)) {
398 case IS_FALSE:
399 case IS_TRUE:
400 case IS_DOUBLE:
401 case IS_LONG:
402 case IS_STRING:
403 RETURN_TRUE;
404 break;
405
406 default:
407 RETURN_FALSE;
408 break;
409 }
410 }
411 /* }}} */
412
413 /* {{{ Returns true if var is callable. */
PHP_FUNCTION(is_callable)414 PHP_FUNCTION(is_callable)
415 {
416 zval *var, *callable_name = NULL;
417 zend_string *name;
418 bool retval;
419 bool syntax_only = 0;
420 int check_flags = 0;
421
422 ZEND_PARSE_PARAMETERS_START(1, 3)
423 Z_PARAM_ZVAL(var)
424 Z_PARAM_OPTIONAL
425 Z_PARAM_BOOL(syntax_only)
426 Z_PARAM_ZVAL(callable_name)
427 ZEND_PARSE_PARAMETERS_END();
428
429 if (syntax_only) {
430 check_flags |= IS_CALLABLE_CHECK_SYNTAX_ONLY;
431 }
432 if (ZEND_NUM_ARGS() > 2) {
433 retval = zend_is_callable_ex(var, NULL, check_flags, &name, NULL, NULL);
434 ZEND_TRY_ASSIGN_REF_STR(callable_name, name);
435 } else {
436 retval = zend_is_callable_ex(var, NULL, check_flags, NULL, NULL, NULL);
437 }
438
439 RETURN_BOOL(retval);
440 }
441 /* }}} */
442
443 /* {{{ Returns true if var is iterable (array or instance of Traversable). */
PHP_FUNCTION(is_iterable)444 PHP_FUNCTION(is_iterable)
445 {
446 zval *var;
447
448 ZEND_PARSE_PARAMETERS_START(1, 1)
449 Z_PARAM_ZVAL(var)
450 ZEND_PARSE_PARAMETERS_END();
451
452 RETURN_BOOL(zend_is_iterable(var));
453 }
454 /* }}} */
455
456 /* {{{ Returns true if var is countable (array or instance of Countable). */
PHP_FUNCTION(is_countable)457 PHP_FUNCTION(is_countable)
458 {
459 zval *var;
460
461 ZEND_PARSE_PARAMETERS_START(1, 1)
462 Z_PARAM_ZVAL(var)
463 ZEND_PARSE_PARAMETERS_END();
464
465 RETURN_BOOL(zend_is_countable(var));
466 }
467 /* }}} */
468