xref: /PHP-7.3/ext/standard/type.c (revision 902d39a3)
1 /*
2    +----------------------------------------------------------------------+
3    | PHP Version 7                                                        |
4    +----------------------------------------------------------------------+
5    | Copyright (c) 1997-2018 The PHP Group                                |
6    +----------------------------------------------------------------------+
7    | This source file is subject to version 3.01 of the PHP 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.php.net/license/3_01.txt                                  |
11    | If you did not receive a copy of the PHP license and are unable to   |
12    | obtain it through the world-wide-web, please send a note to          |
13    | license@php.net so we can mail you a copy immediately.               |
14    +----------------------------------------------------------------------+
15    | Author: Rasmus Lerdorf <rasmus@php.net>                              |
16    +----------------------------------------------------------------------+
17 */
18 
19 #include "php.h"
20 #include "php_incomplete_class.h"
21 
22 /* {{{ proto string gettype(mixed var)
23    Returns the type of the variable */
PHP_FUNCTION(gettype)24 PHP_FUNCTION(gettype)
25 {
26 	zval *arg;
27 	zend_string *type;
28 
29 	ZEND_PARSE_PARAMETERS_START(1, 1)
30 		Z_PARAM_ZVAL(arg)
31 	ZEND_PARSE_PARAMETERS_END();
32 
33 	type = zend_zval_get_type(arg);
34 	if (EXPECTED(type)) {
35 		RETURN_INTERNED_STR(type);
36 	} else {
37 		RETURN_STRING("unknown type");
38 	}
39 }
40 /* }}} */
41 
42 /* {{{ proto bool settype(mixed &var, string type)
43    Set the type of the variable */
PHP_FUNCTION(settype)44 PHP_FUNCTION(settype)
45 {
46 	zval *var;
47 	char *type;
48 	size_t type_len = 0;
49 
50 	ZEND_PARSE_PARAMETERS_START(2, 2)
51 		Z_PARAM_ZVAL_DEREF(var)
52 		Z_PARAM_STRING(type, type_len)
53 	ZEND_PARSE_PARAMETERS_END();
54 
55 	if (!strcasecmp(type, "integer")) {
56 		convert_to_long(var);
57 	} else if (!strcasecmp(type, "int")) {
58 		convert_to_long(var);
59 	} else if (!strcasecmp(type, "float")) {
60 		convert_to_double(var);
61 	} else if (!strcasecmp(type, "double")) { /* deprecated */
62 		convert_to_double(var);
63 	} else if (!strcasecmp(type, "string")) {
64 		convert_to_string(var);
65 	} else if (!strcasecmp(type, "array")) {
66 		convert_to_array(var);
67 	} else if (!strcasecmp(type, "object")) {
68 		convert_to_object(var);
69 	} else if (!strcasecmp(type, "bool")) {
70 		convert_to_boolean(var);
71 	} else if (!strcasecmp(type, "boolean")) {
72 		convert_to_boolean(var);
73 	} else if (!strcasecmp(type, "null")) {
74 		convert_to_null(var);
75 	} else if (!strcasecmp(type, "resource")) {
76 		php_error_docref(NULL, E_WARNING, "Cannot convert to resource type");
77 		RETURN_FALSE;
78 	} else {
79 		php_error_docref(NULL, E_WARNING, "Invalid type");
80 		RETURN_FALSE;
81 	}
82 	RETVAL_TRUE;
83 }
84 /* }}} */
85 
86 /* {{{ proto int intval(mixed var [, int base])
87    Get the integer value of a variable using the optional base for the conversion */
PHP_FUNCTION(intval)88 PHP_FUNCTION(intval)
89 {
90 	zval *num;
91 	zend_long base = 10;
92 
93 	ZEND_PARSE_PARAMETERS_START(1, 2)
94 		Z_PARAM_ZVAL(num)
95 		Z_PARAM_OPTIONAL
96 		Z_PARAM_LONG(base)
97 	ZEND_PARSE_PARAMETERS_END();
98 
99 	if (Z_TYPE_P(num) != IS_STRING || base == 10) {
100 		RETVAL_LONG(zval_get_long(num));
101 		return;
102 	}
103 
104 
105 	if (base == 0 || base == 2) {
106 		char *strval = Z_STRVAL_P(num);
107 		size_t strlen = Z_STRLEN_P(num);
108 
109 		while (isspace(*strval) && strlen) {
110 			strval++;
111 			strlen--;
112 		}
113 
114 		/* Length of 3+ covers "0b#" and "-0b" (which results in 0) */
115 		if (strlen > 2) {
116 			int offset = 0;
117 			if (strval[0] == '-' || strval[0] == '+') {
118 				offset = 1;
119 			}
120 
121 			if (strval[offset] == '0' && (strval[offset + 1] == 'b' || strval[offset + 1] == 'B')) {
122 				char *tmpval;
123 				strlen -= 2; /* Removing "0b" */
124 				tmpval = emalloc(strlen + 1);
125 
126 				/* Place the unary symbol at pos 0 if there was one */
127 				if (offset) {
128 					tmpval[0] = strval[0];
129 				}
130 
131 				/* Copy the data from after "0b" to the end of the buffer */
132 				memcpy(tmpval + offset, strval + offset + 2, strlen - offset);
133 				tmpval[strlen] = 0;
134 
135 				RETVAL_LONG(ZEND_STRTOL(tmpval, NULL, 2));
136 				efree(tmpval);
137 				return;
138 			}
139 		}
140 	}
141 
142 	RETVAL_LONG(ZEND_STRTOL(Z_STRVAL_P(num), NULL, base));
143 }
144 /* }}} */
145 
146 /* {{{ proto float floatval(mixed var)
147    Get the float value of a variable */
PHP_FUNCTION(floatval)148 PHP_FUNCTION(floatval)
149 {
150 	zval *num;
151 
152 	ZEND_PARSE_PARAMETERS_START(1, 1)
153 		Z_PARAM_ZVAL(num)
154 	ZEND_PARSE_PARAMETERS_END();
155 
156 	RETURN_DOUBLE(zval_get_double(num));
157 }
158 /* }}} */
159 
160 /* {{{ proto bool boolval(mixed var)
161    Get the boolean value of a variable */
PHP_FUNCTION(boolval)162 PHP_FUNCTION(boolval)
163 {
164 	zval *val;
165 
166 	ZEND_PARSE_PARAMETERS_START(1, 1)
167 		Z_PARAM_ZVAL(val)
168 	ZEND_PARSE_PARAMETERS_END();
169 
170 	RETURN_BOOL(zend_is_true(val));
171 }
172 /* }}} */
173 
174 /* {{{ proto string strval(mixed var)
175    Get the string value of a variable */
PHP_FUNCTION(strval)176 PHP_FUNCTION(strval)
177 {
178 	zval *num;
179 
180 	ZEND_PARSE_PARAMETERS_START(1, 1)
181 		Z_PARAM_ZVAL(num)
182 	ZEND_PARSE_PARAMETERS_END();
183 
184 	RETVAL_STR(zval_get_string(num));
185 }
186 /* }}} */
187 
php_is_type(INTERNAL_FUNCTION_PARAMETERS,int type)188 static inline void php_is_type(INTERNAL_FUNCTION_PARAMETERS, int type)
189 {
190 	zval *arg;
191 
192 	ZEND_PARSE_PARAMETERS_START(1, 1)
193 		Z_PARAM_ZVAL(arg)
194 	ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE);
195 
196 	if (Z_TYPE_P(arg) == type) {
197 		if (type == IS_RESOURCE) {
198 			const char *type_name = zend_rsrc_list_get_rsrc_type(Z_RES_P(arg));
199 			if (!type_name) {
200 				RETURN_FALSE;
201 			}
202 		}
203 		RETURN_TRUE;
204 	} else {
205 		RETURN_FALSE;
206 	}
207 }
208 
209 
210 /* {{{ proto bool is_null(mixed var)
211    Returns true if variable is null
212    Warning: This function is special-cased by zend_compile.c and so is usually bypassed */
PHP_FUNCTION(is_null)213 PHP_FUNCTION(is_null)
214 {
215 	php_is_type(INTERNAL_FUNCTION_PARAM_PASSTHRU, IS_NULL);
216 }
217 /* }}} */
218 
219 /* {{{ proto bool is_resource(mixed var)
220    Returns true if variable is a resource
221    Warning: This function is special-cased by zend_compile.c and so is usually bypassed */
PHP_FUNCTION(is_resource)222 PHP_FUNCTION(is_resource)
223 {
224 	php_is_type(INTERNAL_FUNCTION_PARAM_PASSTHRU, IS_RESOURCE);
225 }
226 /* }}} */
227 
228 /* {{{ proto bool is_bool(mixed var)
229    Returns true if variable is a boolean
230    Warning: This function is special-cased by zend_compile.c and so is usually bypassed */
PHP_FUNCTION(is_bool)231 PHP_FUNCTION(is_bool)
232 {
233 	zval *arg;
234 
235 	ZEND_PARSE_PARAMETERS_START(1, 1)
236 		Z_PARAM_ZVAL(arg)
237 	ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE);
238 
239 	RETURN_BOOL(Z_TYPE_P(arg) == IS_FALSE || Z_TYPE_P(arg) == IS_TRUE);
240 }
241 /* }}} */
242 
243 /* {{{ proto bool is_int(mixed var)
244    Returns true if variable is an integer
245    Warning: This function is special-cased by zend_compile.c and so is usually bypassed */
PHP_FUNCTION(is_int)246 PHP_FUNCTION(is_int)
247 {
248 	php_is_type(INTERNAL_FUNCTION_PARAM_PASSTHRU, IS_LONG);
249 }
250 /* }}} */
251 
252 /* {{{ proto bool is_float(mixed var)
253    Returns true if variable is float point
254    Warning: This function is special-cased by zend_compile.c and so is usually bypassed */
PHP_FUNCTION(is_float)255 PHP_FUNCTION(is_float)
256 {
257 	php_is_type(INTERNAL_FUNCTION_PARAM_PASSTHRU, IS_DOUBLE);
258 }
259 /* }}} */
260 
261 /* {{{ proto bool is_string(mixed var)
262    Returns true if variable is a string
263    Warning: This function is special-cased by zend_compile.c and so is usually bypassed */
PHP_FUNCTION(is_string)264 PHP_FUNCTION(is_string)
265 {
266 	php_is_type(INTERNAL_FUNCTION_PARAM_PASSTHRU, IS_STRING);
267 }
268 /* }}} */
269 
270 /* {{{ proto bool is_array(mixed var)
271    Returns true if variable is an array
272    Warning: This function is special-cased by zend_compile.c and so is usually bypassed */
PHP_FUNCTION(is_array)273 PHP_FUNCTION(is_array)
274 {
275 	php_is_type(INTERNAL_FUNCTION_PARAM_PASSTHRU, IS_ARRAY);
276 }
277 /* }}} */
278 
279 /* {{{ proto bool is_object(mixed var)
280    Returns true if variable is an object
281    Warning: This function is special-cased by zend_compile.c and so is usually bypassed */
PHP_FUNCTION(is_object)282 PHP_FUNCTION(is_object)
283 {
284 	php_is_type(INTERNAL_FUNCTION_PARAM_PASSTHRU, IS_OBJECT);
285 }
286 /* }}} */
287 
288 /* {{{ proto bool is_numeric(mixed value)
289    Returns true if value is a number or a numeric string */
PHP_FUNCTION(is_numeric)290 PHP_FUNCTION(is_numeric)
291 {
292 	zval *arg;
293 
294 	ZEND_PARSE_PARAMETERS_START(1, 1)
295 		Z_PARAM_ZVAL(arg)
296 	ZEND_PARSE_PARAMETERS_END();
297 
298 	switch (Z_TYPE_P(arg)) {
299 		case IS_LONG:
300 		case IS_DOUBLE:
301 			RETURN_TRUE;
302 			break;
303 
304 		case IS_STRING:
305 			if (is_numeric_string(Z_STRVAL_P(arg), Z_STRLEN_P(arg), NULL, NULL, 0)) {
306 				RETURN_TRUE;
307 			} else {
308 				RETURN_FALSE;
309 			}
310 			break;
311 
312 		default:
313 			RETURN_FALSE;
314 			break;
315 	}
316 }
317 /* }}} */
318 
319 /* {{{ proto bool is_scalar(mixed value)
320    Returns true if value is a scalar */
PHP_FUNCTION(is_scalar)321 PHP_FUNCTION(is_scalar)
322 {
323 	zval *arg;
324 
325 	ZEND_PARSE_PARAMETERS_START(1, 1)
326 		Z_PARAM_ZVAL(arg)
327 	ZEND_PARSE_PARAMETERS_END();
328 
329 	switch (Z_TYPE_P(arg)) {
330 		case IS_FALSE:
331 		case IS_TRUE:
332 		case IS_DOUBLE:
333 		case IS_LONG:
334 		case IS_STRING:
335 			RETURN_TRUE;
336 			break;
337 
338 		default:
339 			RETURN_FALSE;
340 			break;
341 	}
342 }
343 /* }}} */
344 
345 /* {{{ proto bool is_callable(mixed var [, bool syntax_only [, string &callable_name]])
346    Returns true if var is callable. */
PHP_FUNCTION(is_callable)347 PHP_FUNCTION(is_callable)
348 {
349 	zval *var, *callable_name = NULL;
350 	zend_string *name;
351 	char *error;
352 	zend_bool retval;
353 	zend_bool syntax_only = 0;
354 	int check_flags = 0;
355 
356 	ZEND_PARSE_PARAMETERS_START(1, 3)
357 		Z_PARAM_ZVAL(var)
358 		Z_PARAM_OPTIONAL
359 		Z_PARAM_BOOL(syntax_only)
360 		Z_PARAM_ZVAL_DEREF(callable_name)
361 	ZEND_PARSE_PARAMETERS_END();
362 
363 	if (syntax_only) {
364 		check_flags |= IS_CALLABLE_CHECK_SYNTAX_ONLY;
365 	}
366 	if (ZEND_NUM_ARGS() > 2) {
367 		retval = zend_is_callable_ex(var, NULL, check_flags, &name, NULL, &error);
368 		zval_ptr_dtor(callable_name);
369 		ZVAL_STR(callable_name, name);
370 	} else {
371 		retval = zend_is_callable_ex(var, NULL, check_flags, NULL, NULL, &error);
372 	}
373 	if (error) {
374 		/* ignore errors */
375 		efree(error);
376 	}
377 
378 	RETURN_BOOL(retval);
379 }
380 /* }}} */
381 
382 /* {{{ proto bool is_iterable(mixed var)
383    Returns true if var is iterable (array or instance of Traversable). */
PHP_FUNCTION(is_iterable)384 PHP_FUNCTION(is_iterable)
385 {
386 	zval *var;
387 
388 	ZEND_PARSE_PARAMETERS_START(1, 1)
389 		Z_PARAM_ZVAL(var)
390 	ZEND_PARSE_PARAMETERS_END();
391 
392 	RETURN_BOOL(zend_is_iterable(var));
393 }
394 /* }}} */
395 
396 /* {{{ proto bool is_countable(mixed var)
397    Returns true if var is countable (array or instance of Countable). */
PHP_FUNCTION(is_countable)398 PHP_FUNCTION(is_countable)
399 {
400 	zval *var;
401 
402 	ZEND_PARSE_PARAMETERS_START(1, 1)
403 		Z_PARAM_ZVAL(var)
404 	ZEND_PARSE_PARAMETERS_END();
405 
406 	RETURN_BOOL(zend_is_countable(var));
407 }
408 /* }}} */
409 
410 /*
411  * Local variables:
412  * tab-width: 4
413  * c-basic-offset: 4
414  * End:
415  * vim600: sw=4 ts=4 fdm=marker
416  * vim<600: sw=4 ts=4
417  */
418