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