php-internal-docs 8.4.8
Unofficial docs for php/php-src
Loading...
Searching...
No Matches
formatter_parse.c
Go to the documentation of this file.
1/*
2 +----------------------------------------------------------------------+
3 | This source file is subject to version 3.01 of the PHP license, |
4 | that is bundled with this package in the file LICENSE, and is |
5 | available through the world-wide-web at the following url: |
6 | https://www.php.net/license/3_01.txt |
7 | If you did not receive a copy of the PHP license and are unable to |
8 | obtain it through the world-wide-web, please send a note to |
9 | license@php.net so we can mail you a copy immediately. |
10 +----------------------------------------------------------------------+
11 | Authors: Stanislav Malyshev <stas@zend.com> |
12 +----------------------------------------------------------------------+
13 */
14
15#ifdef HAVE_CONFIG_H
16#include <config.h>
17#endif
18
19#include "php_intl.h"
20
21#include <unicode/ustring.h>
22#include <locale.h>
23
24#include "formatter_class.h"
25#include "formatter_format.h"
26#include "intl_convert.h"
27
28#define ICU_LOCALE_BUG 1
29
30/* {{{ Parse a number. */
32{
34 UChar* sstr = NULL;
35 int32_t sstr_len = 0;
36 char* str = NULL;
37 size_t str_len;
38 int32_t val32, position = 0;
39 int64_t val64;
40 double val_double;
41 int32_t* position_p = NULL;
42 zval *zposition = NULL;
43 char *oldlocale;
45
46 /* Parse parameters. */
48 &object, NumberFormatter_ce_ptr, &str, &str_len, &type, &zposition ) == FAILURE )
49 {
51 }
52
53 if (zposition) {
54 position = (int32_t) zval_get_long(zposition);
55 position_p = &position;
56 }
57
58 /* Fetch the object. */
60
61 /* Convert given string to UTF-16. */
62 intl_convert_utf8_to_utf16(&sstr, &sstr_len, str, str_len, &INTL_DATA_ERROR_CODE(nfo));
63 INTL_METHOD_CHECK_STATUS( nfo, "String conversion to UTF-16 failed" );
64
65#if ICU_LOCALE_BUG && defined(LC_NUMERIC)
66 /* need to copy here since setlocale may change it later */
67 oldlocale = estrdup(setlocale(LC_NUMERIC, NULL));
69#endif
70
71 switch(type) {
73 val32 = unum_parse(FORMATTER_OBJECT(nfo), sstr, sstr_len, position_p, &INTL_DATA_ERROR_CODE(nfo));
74 RETVAL_LONG(val32);
75 break;
77 val64 = unum_parseInt64(FORMATTER_OBJECT(nfo), sstr, sstr_len, position_p, &INTL_DATA_ERROR_CODE(nfo));
78 if(val64 > ZEND_LONG_MAX || val64 < ZEND_LONG_MIN) {
79 RETVAL_DOUBLE(val64);
80 } else {
81 RETVAL_LONG((zend_long)val64);
82 }
83 break;
85 val_double = unum_parseDouble(FORMATTER_OBJECT(nfo), sstr, sstr_len, position_p, &INTL_DATA_ERROR_CODE(nfo));
86 RETVAL_DOUBLE(val_double);
87 break;
89 if (getThis()) {
90 const char *space;
91 const char *class_name = get_active_class_name(&space);
92 zend_argument_value_error(2, "cannot be NumberFormatter::TYPE_CURRENCY constant, "
93 "use %s%sparseCurrency() method instead", class_name, space);
94 } else {
95 zend_argument_value_error(3, "cannot be NumberFormatter::TYPE_CURRENCY constant, use numfmt_parse_currency() function instead");
96 }
97 goto cleanup;
98 default:
99 zend_argument_value_error(hasThis() ? 2 : 3, "must be a NumberFormatter::TYPE_* constant");
100 goto cleanup;
101 }
102
103 if (zposition) {
104 ZEND_TRY_ASSIGN_REF_LONG(zposition, position);
105 }
106
107cleanup:
108
109#if ICU_LOCALE_BUG && defined(LC_NUMERIC)
110 setlocale(LC_NUMERIC, oldlocale);
111 efree(oldlocale);
112#endif
113
114 if (sstr) {
115 efree(sstr);
116 }
117
118 INTL_METHOD_CHECK_STATUS( nfo, "Number parsing failed" );
119}
120/* }}} */
121
122/* {{{ Parse a number as currency. */
124{
125 double number;
126 UChar currency[5] = {0};
127 UChar* sstr = NULL;
128 int32_t sstr_len = 0;
129 zend_string *u8str;
130 char *str;
131 size_t str_len;
132 int32_t* position_p = NULL;
133 int32_t position = 0;
134 zval *zcurrency, *zposition = NULL;
136
137 /* Parse parameters. */
139 &object, NumberFormatter_ce_ptr, &str, &str_len, &zcurrency, &zposition ) == FAILURE )
140 {
142 }
143
144 /* Fetch the object. */
146
147 /* Convert given string to UTF-16. */
148 intl_convert_utf8_to_utf16(&sstr, &sstr_len, str, str_len, &INTL_DATA_ERROR_CODE(nfo));
149 INTL_METHOD_CHECK_STATUS( nfo, "String conversion to UTF-16 failed" );
150
151 if(zposition) {
152 position = (int32_t) zval_get_long(zposition);
153 position_p = &position;
154 }
155
156 number = unum_parseDoubleCurrency(FORMATTER_OBJECT(nfo), sstr, sstr_len, position_p, currency, &INTL_DATA_ERROR_CODE(nfo));
157 if(zposition) {
158 ZEND_TRY_ASSIGN_REF_LONG(zposition, position);
159 }
160 if (sstr) {
161 efree(sstr);
162 }
163 INTL_METHOD_CHECK_STATUS( nfo, "Number parsing failed" );
164
165 /* Convert parsed currency to UTF-8 and pass it back to caller. */
166 u8str = intl_convert_utf16_to_utf8(currency, u_strlen(currency), &INTL_DATA_ERROR_CODE(nfo));
167 INTL_METHOD_CHECK_STATUS( nfo, "Currency conversion to UTF-8 failed" );
168 ZEND_TRY_ASSIGN_REF_NEW_STR(zcurrency, u8str);
169
170 RETVAL_DOUBLE( number );
171}
172/* }}} */
const LC_NUMERIC
setlocale(int $category, $locales,... $rest)
zend_ffi_type * type
Definition ffi.c:3812
zend_class_entry * NumberFormatter_ce_ptr
#define FORMATTER_METHOD_FETCH_OBJECT
#define FORMATTER_METHOD_INIT_VARS
#define FORMATTER_OBJECT(nfo)
#define FORMAT_TYPE_INT64
#define FORMAT_TYPE_CURRENCY
#define FORMAT_TYPE_DOUBLE
#define FORMAT_TYPE_INT32
#define NULL
Definition gdcache.h:45
void intl_convert_utf8_to_utf16(UChar **target, int32_t *target_len, const char *src, size_t src_len, UErrorCode *status)
zend_string * intl_convert_utf16_to_utf8(const UChar *src, int32_t src_len, UErrorCode *status)
#define INTL_DATA_ERROR_CODE(obj)
Definition intl_data.h:40
#define INTL_METHOD_CHECK_STATUS(obj, msg)
Definition intl_data.h:66
#define PHP_FUNCTION
Definition php.h:364
numfmt_parse(NumberFormatter $formatter, string $string, int $type=NumberFormatter::TYPE_DOUBLE, &$offset=null)
numfmt_parse_currency(NumberFormatter $formatter, string $string, &$currency, &$offset=null)
ZEND_API zend_result zend_parse_method_parameters(uint32_t num_args, zval *this_ptr, const char *type_spec,...)
Definition zend_API.c:1314
ZEND_API ZEND_COLD void zend_argument_value_error(uint32_t arg_num, const char *format,...)
Definition zend_API.c:433
#define ZEND_NUM_ARGS()
Definition zend_API.h:530
#define hasThis()
Definition zend_API.h:525
#define RETVAL_DOUBLE(d)
Definition zend_API.h:1012
#define ZEND_TRY_ASSIGN_REF_LONG(zv, lval)
Definition zend_API.h:1205
#define RETURN_THROWS()
Definition zend_API.h:1060
#define ZEND_TRY_ASSIGN_REF_NEW_STR(zv, str)
Definition zend_API.h:1293
#define RETVAL_LONG(l)
Definition zend_API.h:1011
#define getThis()
Definition zend_API.h:526
#define efree(ptr)
Definition zend_alloc.h:155
#define estrdup(s)
Definition zend_alloc.h:164
struct _zval_struct zval
ZEND_API const char * get_active_class_name(const char **space)
int32_t zend_long
Definition zend_long.h:42
#define ZEND_LONG_MIN
Definition zend_long.h:46
#define ZEND_LONG_MAX
Definition zend_long.h:45
struct _zend_string zend_string
@ FAILURE
Definition zend_types.h:61