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