1 : /*
2 : +----------------------------------------------------------------------+
3 : | PHP Version 5 |
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 : | http://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 : | Authors: Stanislav Malyshev <stas@zend.com> |
14 : +----------------------------------------------------------------------+
15 : */
16 :
17 : #ifdef HAVE_CONFIG_H
18 : #include "config.h"
19 : #endif
20 :
21 : #include <unicode/ustring.h>
22 : #include <locale.h>
23 :
24 : #include "php_intl.h"
25 : #include "formatter_class.h"
26 : #include "formatter_format.h"
27 : #include "formatter_parse.h"
28 : #include "intl_convert.h"
29 :
30 : #define ICU_LOCALE_BUG 1
31 :
32 : /* {{{ proto mixed NumberFormatter::parse( string $str[, int $type, int &$position ])
33 : * Parse a number. }}} */
34 : /* {{{ proto mixed numfmt_parse( NumberFormatter $nf, string $str[, int $type, int &$position ])
35 : * Parse a number.
36 : */
37 : PHP_FUNCTION( numfmt_parse )
38 86 : {
39 86 : long type = FORMAT_TYPE_DOUBLE;
40 86 : UChar* sstr = NULL;
41 86 : int sstr_len = 0;
42 86 : char* str = NULL;
43 : int str_len;
44 86 : int32_t val32, position = 0;
45 : int64_t val64;
46 : double val_double;
47 86 : int32_t* position_p = NULL;
48 86 : zval *zposition = NULL;
49 : char *oldlocale;
50 86 : FORMATTER_METHOD_INIT_VARS;
51 :
52 : /* Parse parameters. */
53 86 : if( zend_parse_method_parameters( ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Os|lz!",
54 : &object, NumberFormatter_ce_ptr, &str, &str_len, &type, &zposition ) == FAILURE )
55 : {
56 0 : intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR,
57 : "number_parse: unable to parse input params", 0 TSRMLS_CC );
58 :
59 0 : RETURN_FALSE;
60 : }
61 :
62 : /* Fetch the object. */
63 86 : FORMATTER_METHOD_FETCH_OBJECT;
64 :
65 : /* Convert given string to UTF-16. */
66 86 : intl_convert_utf8_to_utf16(&sstr, &sstr_len, str, str_len, &INTL_DATA_ERROR_CODE(nfo));
67 86 : INTL_METHOD_CHECK_STATUS( nfo, "String conversion to UTF-16 failed" );
68 :
69 86 : if(zposition) {
70 2 : convert_to_long(zposition);
71 2 : position = (int32_t)Z_LVAL_P( zposition );
72 2 : position_p = &position;
73 : }
74 :
75 : #if ICU_LOCALE_BUG && defined(LC_NUMERIC)
76 86 : oldlocale = setlocale(LC_NUMERIC, "C");
77 : #endif
78 :
79 86 : switch(type) {
80 : case FORMAT_TYPE_INT32:
81 2 : val32 = unum_parse(FORMATTER_OBJECT(nfo), sstr, sstr_len, position_p, &INTL_DATA_ERROR_CODE(nfo));
82 2 : RETVAL_LONG(val32);
83 2 : break;
84 : case FORMAT_TYPE_INT64:
85 0 : val64 = unum_parseInt64(FORMATTER_OBJECT(nfo), sstr, sstr_len, position_p, &INTL_DATA_ERROR_CODE(nfo));
86 0 : if(val64 > LONG_MAX || val64 < -LONG_MAX) {
87 0 : RETVAL_DOUBLE(val64);
88 : } else {
89 0 : val32 = (int32_t)val64;
90 0 : RETVAL_LONG(val32);
91 : }
92 0 : break;
93 : case FORMAT_TYPE_DOUBLE:
94 84 : val_double = unum_parseDouble(FORMATTER_OBJECT(nfo), sstr, sstr_len, position_p, &INTL_DATA_ERROR_CODE(nfo));
95 84 : RETVAL_DOUBLE(val_double);
96 84 : break;
97 : default:
98 0 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unsupported format type %ld", type);
99 0 : RETVAL_FALSE;
100 : break;
101 : }
102 : #if ICU_LOCALE_BUG && defined(LC_NUMERIC)
103 86 : setlocale(LC_NUMERIC, oldlocale);
104 : #endif
105 86 : if(zposition) {
106 2 : zval_dtor(zposition);
107 2 : ZVAL_LONG(zposition, position);
108 : }
109 :
110 86 : efree(sstr);
111 :
112 86 : INTL_METHOD_CHECK_STATUS( nfo, "Number parsing failed" );
113 : }
114 : /* }}} */
115 :
116 : /* {{{ proto double NumberFormatter::parseCurrency( string $str, string $¤cy[, int $&position] )
117 : * Parse a number as currency. }}} */
118 : /* {{{ proto double numfmt_parse_currency( NumberFormatter $nf, string $str, string $¤cy[, int $&position] )
119 : * Parse a number as currency.
120 : */
121 : PHP_FUNCTION( numfmt_parse_currency )
122 6 : {
123 : double number;
124 6 : UChar currency[5] = {0};
125 6 : UChar* sstr = NULL;
126 6 : int sstr_len = 0;
127 6 : char *currency_str = NULL;
128 6 : int currency_len = 0;
129 : char *str;
130 : int str_len;
131 6 : int32_t* position_p = NULL;
132 6 : int32_t position = 0;
133 6 : zval *zcurrency, *zposition = NULL;
134 6 : FORMATTER_METHOD_INIT_VARS;
135 :
136 : /* Parse parameters. */
137 6 : if( zend_parse_method_parameters( ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Osz|z!",
138 : &object, NumberFormatter_ce_ptr, &str, &str_len, &zcurrency, &zposition ) == FAILURE )
139 : {
140 0 : intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR,
141 : "number_parse_currency: unable to parse input params", 0 TSRMLS_CC );
142 :
143 0 : RETURN_FALSE;
144 : }
145 :
146 : /* Fetch the object. */
147 6 : FORMATTER_METHOD_FETCH_OBJECT;
148 :
149 : /* Convert given string to UTF-16. */
150 6 : intl_convert_utf8_to_utf16(&sstr, &sstr_len, str, str_len, &INTL_DATA_ERROR_CODE(nfo));
151 6 : INTL_METHOD_CHECK_STATUS( nfo, "String conversion to UTF-16 failed" );
152 :
153 6 : if(zposition) {
154 6 : convert_to_long(zposition);
155 6 : position = (int32_t)Z_LVAL_P( zposition );
156 6 : position_p = &position;
157 : }
158 :
159 6 : number = unum_parseDoubleCurrency(FORMATTER_OBJECT(nfo), sstr, sstr_len, position_p, currency, &INTL_DATA_ERROR_CODE(nfo));
160 6 : if(zposition) {
161 6 : zval_dtor(zposition);
162 6 : ZVAL_LONG(zposition, position);
163 : }
164 6 : efree(sstr);
165 6 : INTL_METHOD_CHECK_STATUS( nfo, "Number parsing failed" );
166 :
167 : /* Convert parsed currency to UTF-8 and pass it back to caller. */
168 4 : intl_convert_utf16_to_utf8(¤cy_str, ¤cy_len, currency, u_strlen(currency), &INTL_DATA_ERROR_CODE(nfo));
169 4 : INTL_METHOD_CHECK_STATUS( nfo, "Currency conversion to UTF-8 failed" );
170 4 : zval_dtor( zcurrency );
171 4 : ZVAL_STRINGL(zcurrency, currency_str, currency_len, 0);
172 :
173 4 : RETVAL_DOUBLE( number );
174 : }
175 : /* }}} */
176 :
177 : /*
178 : * Local variables:
179 : * tab-width: 4
180 : * c-basic-offset: 4
181 : * End:
182 : * vim600: noet sw=4 ts=4 fdm=marker
183 : * vim<600: noet sw=4 ts=4
184 : */
|