PageRenderTime 56ms CodeModel.GetById 28ms RepoModel.GetById 1ms app.codeStats 0ms

/ext/standard/type.c

https://github.com/php/php-src
C | 454 lines | 317 code | 69 blank | 68 comment | 73 complexity | 32186fb94275c36de47417f4b95eae12 MD5 | raw file
Possible License(s): BSD-2-Clause, BSD-3-Clause, MPL-2.0-no-copyleft-exception, LGPL-2.1
  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. #include "php.h"
  17. #include "php_incomplete_class.h"
  18. /* {{{ Returns the type of the variable */
  19. PHP_FUNCTION(gettype)
  20. {
  21. zval *arg;
  22. zend_string *type;
  23. ZEND_PARSE_PARAMETERS_START(1, 1)
  24. Z_PARAM_ZVAL(arg)
  25. ZEND_PARSE_PARAMETERS_END();
  26. type = zend_zval_get_legacy_type(arg);
  27. if (EXPECTED(type)) {
  28. RETURN_INTERNED_STR(type);
  29. } else {
  30. RETURN_STRING("unknown type");
  31. }
  32. }
  33. /* }}} */
  34. /* {{{ Returns the type of the variable resolving class names */
  35. PHP_FUNCTION(get_debug_type)
  36. {
  37. zval *arg;
  38. const char *name;
  39. ZEND_PARSE_PARAMETERS_START(1, 1)
  40. Z_PARAM_ZVAL(arg)
  41. ZEND_PARSE_PARAMETERS_END();
  42. switch (Z_TYPE_P(arg)) {
  43. case IS_NULL:
  44. RETURN_INTERNED_STR(ZSTR_KNOWN(ZEND_STR_NULL_LOWERCASE));
  45. case IS_FALSE:
  46. case IS_TRUE:
  47. RETURN_INTERNED_STR(ZSTR_KNOWN(ZEND_STR_BOOL));
  48. case IS_LONG:
  49. RETURN_INTERNED_STR(ZSTR_KNOWN(ZEND_STR_INT));
  50. case IS_DOUBLE:
  51. RETURN_INTERNED_STR(ZSTR_KNOWN(ZEND_STR_FLOAT));
  52. case IS_STRING:
  53. RETURN_INTERNED_STR(ZSTR_KNOWN(ZEND_STR_STRING));
  54. case IS_ARRAY:
  55. RETURN_INTERNED_STR(ZSTR_KNOWN(ZEND_STR_ARRAY));
  56. case IS_OBJECT:
  57. if (Z_OBJ_P(arg)->ce->ce_flags & ZEND_ACC_ANON_CLASS) {
  58. name = ZSTR_VAL(Z_OBJ_P(arg)->ce->name);
  59. RETURN_NEW_STR(zend_string_init(name, strlen(name), 0));
  60. } else {
  61. RETURN_STR_COPY(Z_OBJ_P(arg)->ce->name);
  62. }
  63. case IS_RESOURCE:
  64. name = zend_rsrc_list_get_rsrc_type(Z_RES_P(arg));
  65. if (name) {
  66. RETURN_NEW_STR(zend_strpprintf(0, "resource (%s)", name));
  67. } else {
  68. RETURN_INTERNED_STR(ZSTR_KNOWN(ZEND_STR_CLOSED_RESOURCE));
  69. }
  70. default:
  71. RETURN_INTERNED_STR(ZSTR_KNOWN(ZEND_STR_UNKNOWN));
  72. }
  73. }
  74. /* }}} */
  75. /* {{{ Set the type of the variable */
  76. PHP_FUNCTION(settype)
  77. {
  78. zval *var;
  79. zend_string *type;
  80. zval tmp, *ptr;
  81. ZEND_PARSE_PARAMETERS_START(2, 2)
  82. Z_PARAM_ZVAL(var)
  83. Z_PARAM_STR(type)
  84. ZEND_PARSE_PARAMETERS_END();
  85. ZEND_ASSERT(Z_ISREF_P(var));
  86. if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(Z_REF_P(var)))) {
  87. ZVAL_COPY(&tmp, Z_REFVAL_P(var));
  88. ptr = &tmp;
  89. } else {
  90. ptr = Z_REFVAL_P(var);
  91. }
  92. if (zend_string_equals_literal_ci(type, "integer")) {
  93. convert_to_long(ptr);
  94. } else if (zend_string_equals_literal_ci(type, "int")) {
  95. convert_to_long(ptr);
  96. } else if (zend_string_equals_literal_ci(type, "float")) {
  97. convert_to_double(ptr);
  98. } else if (zend_string_equals_literal_ci(type, "double")) { /* deprecated */
  99. convert_to_double(ptr);
  100. } else if (zend_string_equals_literal_ci(type, "string")) {
  101. convert_to_string(ptr);
  102. } else if (zend_string_equals_literal_ci(type, "array")) {
  103. convert_to_array(ptr);
  104. } else if (zend_string_equals_literal_ci(type, "object")) {
  105. convert_to_object(ptr);
  106. } else if (zend_string_equals_literal_ci(type, "bool")) {
  107. convert_to_boolean(ptr);
  108. } else if (zend_string_equals_literal_ci(type, "boolean")) {
  109. convert_to_boolean(ptr);
  110. } else if (zend_string_equals_literal_ci(type, "null")) {
  111. convert_to_null(ptr);
  112. } else {
  113. if (ptr == &tmp) {
  114. zval_ptr_dtor(&tmp);
  115. }
  116. if (zend_string_equals_literal_ci(type, "resource")) {
  117. zend_value_error("Cannot convert to resource type");
  118. } else {
  119. zend_argument_value_error(2, "must be a valid type");
  120. }
  121. RETURN_THROWS();
  122. }
  123. if (ptr == &tmp) {
  124. zend_try_assign_typed_ref(Z_REF_P(var), &tmp);
  125. }
  126. RETVAL_TRUE;
  127. }
  128. /* }}} */
  129. /* {{{ Get the integer value of a variable using the optional base for the conversion */
  130. PHP_FUNCTION(intval)
  131. {
  132. zval *num;
  133. zend_long base = 10;
  134. ZEND_PARSE_PARAMETERS_START(1, 2)
  135. Z_PARAM_ZVAL(num)
  136. Z_PARAM_OPTIONAL
  137. Z_PARAM_LONG(base)
  138. ZEND_PARSE_PARAMETERS_END();
  139. if (Z_TYPE_P(num) != IS_STRING || base == 10) {
  140. RETVAL_LONG(zval_get_long(num));
  141. return;
  142. }
  143. if (base == 0 || base == 2) {
  144. char *strval = Z_STRVAL_P(num);
  145. size_t strlen = Z_STRLEN_P(num);
  146. while (isspace(*strval) && strlen) {
  147. strval++;
  148. strlen--;
  149. }
  150. /* Length of 3+ covers "0b#" and "-0b" (which results in 0) */
  151. if (strlen > 2) {
  152. int offset = 0;
  153. if (strval[0] == '-' || strval[0] == '+') {
  154. offset = 1;
  155. }
  156. if (strval[offset] == '0' && (strval[offset + 1] == 'b' || strval[offset + 1] == 'B')) {
  157. char *tmpval;
  158. strlen -= 2; /* Removing "0b" */
  159. tmpval = emalloc(strlen + 1);
  160. /* Place the unary symbol at pos 0 if there was one */
  161. if (offset) {
  162. tmpval[0] = strval[0];
  163. }
  164. /* Copy the data from after "0b" to the end of the buffer */
  165. memcpy(tmpval + offset, strval + offset + 2, strlen - offset);
  166. tmpval[strlen] = 0;
  167. RETVAL_LONG(ZEND_STRTOL(tmpval, NULL, 2));
  168. efree(tmpval);
  169. return;
  170. }
  171. }
  172. }
  173. RETVAL_LONG(ZEND_STRTOL(Z_STRVAL_P(num), NULL, base));
  174. }
  175. /* }}} */
  176. /* {{{ Get the float value of a variable */
  177. PHP_FUNCTION(floatval)
  178. {
  179. zval *num;
  180. ZEND_PARSE_PARAMETERS_START(1, 1)
  181. Z_PARAM_ZVAL(num)
  182. ZEND_PARSE_PARAMETERS_END();
  183. RETURN_DOUBLE(zval_get_double(num));
  184. }
  185. /* }}} */
  186. /* {{{ Get the boolean value of a variable */
  187. PHP_FUNCTION(boolval)
  188. {
  189. zval *value;
  190. ZEND_PARSE_PARAMETERS_START(1, 1)
  191. Z_PARAM_ZVAL(value)
  192. ZEND_PARSE_PARAMETERS_END();
  193. RETURN_BOOL(zend_is_true(value));
  194. }
  195. /* }}} */
  196. /* {{{ Get the string value of a variable */
  197. PHP_FUNCTION(strval)
  198. {
  199. zval *value;
  200. ZEND_PARSE_PARAMETERS_START(1, 1)
  201. Z_PARAM_ZVAL(value)
  202. ZEND_PARSE_PARAMETERS_END();
  203. RETVAL_STR(zval_get_string(value));
  204. }
  205. /* }}} */
  206. static inline void php_is_type(INTERNAL_FUNCTION_PARAMETERS, int type)
  207. {
  208. zval *arg;
  209. ZEND_PARSE_PARAMETERS_START(1, 1)
  210. Z_PARAM_ZVAL(arg)
  211. ZEND_PARSE_PARAMETERS_END();
  212. if (Z_TYPE_P(arg) == type) {
  213. if (type == IS_RESOURCE) {
  214. const char *type_name = zend_rsrc_list_get_rsrc_type(Z_RES_P(arg));
  215. if (!type_name) {
  216. RETURN_FALSE;
  217. }
  218. }
  219. RETURN_TRUE;
  220. } else {
  221. RETURN_FALSE;
  222. }
  223. }
  224. /* {{{ Returns true if variable is null
  225. Warning: This function is special-cased by zend_compile.c and so is usually bypassed */
  226. PHP_FUNCTION(is_null)
  227. {
  228. php_is_type(INTERNAL_FUNCTION_PARAM_PASSTHRU, IS_NULL);
  229. }
  230. /* }}} */
  231. /* {{{ Returns true if variable is a resource
  232. Warning: This function is special-cased by zend_compile.c and so is usually bypassed */
  233. PHP_FUNCTION(is_resource)
  234. {
  235. php_is_type(INTERNAL_FUNCTION_PARAM_PASSTHRU, IS_RESOURCE);
  236. }
  237. /* }}} */
  238. /* {{{ Returns true if variable is a boolean
  239. Warning: This function is special-cased by zend_compile.c and so is usually bypassed */
  240. PHP_FUNCTION(is_bool)
  241. {
  242. zval *arg;
  243. ZEND_PARSE_PARAMETERS_START(1, 1)
  244. Z_PARAM_ZVAL(arg)
  245. ZEND_PARSE_PARAMETERS_END();
  246. RETURN_BOOL(Z_TYPE_P(arg) == IS_FALSE || Z_TYPE_P(arg) == IS_TRUE);
  247. }
  248. /* }}} */
  249. /* {{{ Returns true if variable is an integer
  250. Warning: This function is special-cased by zend_compile.c and so is usually bypassed */
  251. PHP_FUNCTION(is_int)
  252. {
  253. php_is_type(INTERNAL_FUNCTION_PARAM_PASSTHRU, IS_LONG);
  254. }
  255. /* }}} */
  256. /* {{{ Returns true if variable is float point
  257. Warning: This function is special-cased by zend_compile.c and so is usually bypassed */
  258. PHP_FUNCTION(is_float)
  259. {
  260. php_is_type(INTERNAL_FUNCTION_PARAM_PASSTHRU, IS_DOUBLE);
  261. }
  262. /* }}} */
  263. /* {{{ Returns true if variable is a string
  264. Warning: This function is special-cased by zend_compile.c and so is usually bypassed */
  265. PHP_FUNCTION(is_string)
  266. {
  267. php_is_type(INTERNAL_FUNCTION_PARAM_PASSTHRU, IS_STRING);
  268. }
  269. /* }}} */
  270. /* {{{ Returns true if variable is an array
  271. Warning: This function is special-cased by zend_compile.c and so is usually bypassed */
  272. PHP_FUNCTION(is_array)
  273. {
  274. php_is_type(INTERNAL_FUNCTION_PARAM_PASSTHRU, IS_ARRAY);
  275. }
  276. /* }}} */
  277. /* {{{ Returns true if $array is an array whose keys are all numeric, sequential, and start at 0 */
  278. PHP_FUNCTION(array_is_list)
  279. {
  280. HashTable *array;
  281. ZEND_PARSE_PARAMETERS_START(1, 1)
  282. Z_PARAM_ARRAY_HT(array)
  283. ZEND_PARSE_PARAMETERS_END();
  284. RETURN_BOOL(zend_array_is_list(array));
  285. }
  286. /* }}} */
  287. /* {{{ Returns true if variable is an object
  288. Warning: This function is special-cased by zend_compile.c and so is usually bypassed */
  289. PHP_FUNCTION(is_object)
  290. {
  291. php_is_type(INTERNAL_FUNCTION_PARAM_PASSTHRU, IS_OBJECT);
  292. }
  293. /* }}} */
  294. /* {{{ Returns true if value is a number or a numeric string */
  295. PHP_FUNCTION(is_numeric)
  296. {
  297. zval *arg;
  298. ZEND_PARSE_PARAMETERS_START(1, 1)
  299. Z_PARAM_ZVAL(arg)
  300. ZEND_PARSE_PARAMETERS_END();
  301. switch (Z_TYPE_P(arg)) {
  302. case IS_LONG:
  303. case IS_DOUBLE:
  304. RETURN_TRUE;
  305. break;
  306. case IS_STRING:
  307. if (is_numeric_string(Z_STRVAL_P(arg), Z_STRLEN_P(arg), NULL, NULL, 0)) {
  308. RETURN_TRUE;
  309. } else {
  310. RETURN_FALSE;
  311. }
  312. break;
  313. default:
  314. RETURN_FALSE;
  315. break;
  316. }
  317. }
  318. /* }}} */
  319. /* {{{ Returns true if value is a scalar */
  320. PHP_FUNCTION(is_scalar)
  321. {
  322. zval *arg;
  323. ZEND_PARSE_PARAMETERS_START(1, 1)
  324. Z_PARAM_ZVAL(arg)
  325. ZEND_PARSE_PARAMETERS_END();
  326. switch (Z_TYPE_P(arg)) {
  327. case IS_FALSE:
  328. case IS_TRUE:
  329. case IS_DOUBLE:
  330. case IS_LONG:
  331. case IS_STRING:
  332. RETURN_TRUE;
  333. break;
  334. default:
  335. RETURN_FALSE;
  336. break;
  337. }
  338. }
  339. /* }}} */
  340. /* {{{ Returns true if var is callable. */
  341. PHP_FUNCTION(is_callable)
  342. {
  343. zval *var, *callable_name = NULL;
  344. zend_string *name;
  345. bool retval;
  346. bool syntax_only = 0;
  347. int check_flags = 0;
  348. ZEND_PARSE_PARAMETERS_START(1, 3)
  349. Z_PARAM_ZVAL(var)
  350. Z_PARAM_OPTIONAL
  351. Z_PARAM_BOOL(syntax_only)
  352. Z_PARAM_ZVAL(callable_name)
  353. ZEND_PARSE_PARAMETERS_END();
  354. if (syntax_only) {
  355. check_flags |= IS_CALLABLE_CHECK_SYNTAX_ONLY;
  356. }
  357. if (ZEND_NUM_ARGS() > 2) {
  358. retval = zend_is_callable_ex(var, NULL, check_flags, &name, NULL, NULL);
  359. ZEND_TRY_ASSIGN_REF_STR(callable_name, name);
  360. } else {
  361. retval = zend_is_callable_ex(var, NULL, check_flags, NULL, NULL, NULL);
  362. }
  363. RETURN_BOOL(retval);
  364. }
  365. /* }}} */
  366. /* {{{ Returns true if var is iterable (array or instance of Traversable). */
  367. PHP_FUNCTION(is_iterable)
  368. {
  369. zval *var;
  370. ZEND_PARSE_PARAMETERS_START(1, 1)
  371. Z_PARAM_ZVAL(var)
  372. ZEND_PARSE_PARAMETERS_END();
  373. RETURN_BOOL(zend_is_iterable(var));
  374. }
  375. /* }}} */
  376. /* {{{ Returns true if var is countable (array or instance of Countable). */
  377. PHP_FUNCTION(is_countable)
  378. {
  379. zval *var;
  380. ZEND_PARSE_PARAMETERS_START(1, 1)
  381. Z_PARAM_ZVAL(var)
  382. ZEND_PARSE_PARAMETERS_END();
  383. RETURN_BOOL(zend_is_countable(var));
  384. }
  385. /* }}} */