php-internal-docs 8.4.8
Unofficial docs for php/php-src
Loading...
Searching...
No Matches
transliterator_methods.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: Gustavo Lopes <cataphract@php.net> |
12 +----------------------------------------------------------------------+
13 */
14
15#ifdef HAVE_CONFIG_H
16#include <config.h>
17#endif
18
19#include "php_intl.h"
20#include "transliterator.h"
22#include "intl_data.h"
23#include "intl_convert.h"
24
25#include <zend_exceptions.h>
26
27static int create_transliterator( char *str_id, size_t str_id_len, zend_long direction, zval *object )
28{
30 UChar *ustr_id = NULL;
31 int32_t ustr_id_len = 0;
32 UTransliterator *utrans;
33 UParseError parse_error;
34
36
37 if( ( direction != TRANSLITERATOR_FORWARD ) && (direction != TRANSLITERATOR_REVERSE ) )
38 {
39 zend_argument_value_error(2, "must be either Transliterator::FORWARD or Transliterator::REVERSE");
40 return FAILURE;
41 }
42
44 TRANSLITERATOR_METHOD_FETCH_OBJECT_NO_CHECK; /* fetch zend object from zval "object" into "to" */
45
46 /* Convert transliterator id to UTF-16 */
47 intl_convert_utf8_to_utf16( &ustr_id, &ustr_id_len, str_id, str_id_len, TRANSLITERATOR_ERROR_CODE_P( to ) );
48 if( U_FAILURE( TRANSLITERATOR_ERROR_CODE( to ) ) )
49 {
51 intl_error_set_custom_msg( NULL, "String conversion of id to UTF-16 failed", 0 );
52 zval_ptr_dtor( object );
53 return FAILURE;
54 }
55
56 /* Open ICU Transliterator. */
57 utrans = utrans_openU( ustr_id, ustr_id_len, (UTransDirection ) direction,
58 NULL, -1, &parse_error, TRANSLITERATOR_ERROR_CODE_P( to ) );
59 if (ustr_id) {
60 efree( ustr_id );
61 }
62
63 if( U_FAILURE( TRANSLITERATOR_ERROR_CODE( to ) ) )
64 {
65 char *buf = NULL;
67 spprintf( &buf, 0, "transliterator_create: unable to open ICU transliterator"
68 " with id \"%s\"", str_id );
69 if( buf == NULL ) {
71 "transliterator_create: unable to open ICU transliterator", 0 );
72 }
73 else
74 {
75 intl_error_set_custom_msg( NULL, buf, /* copy message */ 1 );
76 efree( buf );
77 }
78 zval_ptr_dtor( object );
79 return FAILURE;
80 }
81
83 /* no need to close the transliterator manually on construction error */
84 if( U_FAILURE( TRANSLITERATOR_ERROR_CODE( to ) ) )
85 {
88 "transliterator_create: internal constructor call failed", 0 );
89 zval_ptr_dtor( object );
90 return FAILURE;
91 }
92
93 return SUCCESS;
94}
95
96/* {{{ Opens a transliterator by id. */
98{
99 char *str_id;
100 size_t str_id_len;
102 int res;
103
105
106 (void) to; /* unused */
107
109 Z_PARAM_STRING(str_id, str_id_len)
111 Z_PARAM_LONG(direction)
113
114 object = return_value;
115 res = create_transliterator( str_id, str_id_len, direction, object );
116 if( res == FAILURE )
117 RETURN_NULL();
118
119 /* success, leave return_value as it is (set by create_transliterator) */
120}
121/* }}} */
122
123/* {{{ Opens a transliterator by id. */
125{
126 char *str_rules;
127 size_t str_rules_len;
128 UChar *ustr_rules = NULL;
129 int32_t ustr_rules_len = 0;
131 UParseError parse_error;
132 UTransliterator *utrans;
133 UChar id[] = {0x52, 0x75, 0x6C, 0x65, 0x73, 0x54, 0x72,
134 0x61, 0x6E, 0x73, 0x50, 0x48, 0x50, 0}; /* RulesTransPHP */
136
138 Z_PARAM_STRING(str_rules, str_rules_len)
140 Z_PARAM_LONG(direction)
142
143 if( ( direction != TRANSLITERATOR_FORWARD ) && (direction != TRANSLITERATOR_REVERSE ) )
144 {
145 zend_argument_value_error(2, "must be either Transliterator::FORWARD or Transliterator::REVERSE");
147 }
148
149 object = return_value;
152
153 intl_convert_utf8_to_utf16( &ustr_rules, &ustr_rules_len,
154 str_rules, str_rules_len, TRANSLITERATOR_ERROR_CODE_P( to ) );
155 /* (I'm not a big fan of non-obvious flow control macros ).
156 * This one checks the error value, destroys object and returns false */
157 INTL_METHOD_CHECK_STATUS_OR_NULL( to, "String conversion of rules to UTF-16 failed" );
158
159 /* Open ICU Transliterator. */
160 utrans = utrans_openU( id, ( sizeof( id ) - 1 ) / ( sizeof( *id ) ), (UTransDirection ) direction,
161 ustr_rules, ustr_rules_len, &parse_error, TRANSLITERATOR_ERROR_CODE_P( to ) );
162 if (ustr_rules) {
163 efree( ustr_rules );
164 }
165
167 if( U_FAILURE( INTL_DATA_ERROR_CODE( to ) ) )
168 {
169 char *msg = NULL;
170 smart_str parse_error_str;
171 parse_error_str = intl_parse_error_to_string( &parse_error );
172 spprintf( &msg, 0, "transliterator_create_from_rules: unable to "
173 "create ICU transliterator from rules (%s)", parse_error_str.s? ZSTR_VAL(parse_error_str.s) : "" );
174 smart_str_free( &parse_error_str );
175 if( msg != NULL )
176 {
178 efree( msg );
179 }
181 RETURN_NULL();
182 }
184 /* no need to close the transliterator manually on construction error */
185 INTL_METHOD_CHECK_STATUS_OR_NULL( to, "transliterator_create_from_rules: internal constructor call failed" );
186}
187/* }}} */
188
189/* {{{ Opens the inverse transliterator transliterator. */
191{
192 Transliterator_object *to_orig;
193 UTransliterator *utrans;
195
197 &object, Transliterator_ce_ptr ) == FAILURE )
198 {
200 }
201
203 to_orig = to;
204
205 object = return_value;
207 TRANSLITERATOR_METHOD_FETCH_OBJECT_NO_CHECK; /* change "to" into new object (from "object" ) */
208
209 utrans = utrans_openInverse( to_orig->utrans, TRANSLITERATOR_ERROR_CODE_P( to ) );
210 INTL_METHOD_CHECK_STATUS_OR_NULL( to, "transliterator_create_inverse: could not create "
211 "inverse ICU transliterator" );
213 /* no need to close the transliterator manually on construction error */
214 INTL_METHOD_CHECK_STATUS_OR_NULL( to, "transliterator_create: internal constructor call failed" );
215}
216/* }}} */
217
218/* {{{ Return an array with the registered transliterator IDs. */
220{
221 UEnumeration *en;
222 const UChar *elem;
223 int32_t elem_len;
224 UErrorCode status = U_ZERO_ERROR;
225
227
229
230 en = utrans_openIDs( &status );
232 "transliterator_list_ids: Failed to obtain registered transliterators" );
233
235 while( (elem = uenum_unext( en, &elem_len, &status )) )
236 {
237 zend_string *el = intl_convert_utf16_to_utf8(elem, elem_len, &status );
238
239 if( !el )
240 {
241 break;
242 }
243 else
244 {
246 }
247 }
248 uenum_close( en );
249
251 if( U_FAILURE( status ) )
252 {
255 intl_error_set_custom_msg( NULL, "transliterator_list_ids: "
256 "Failed to build array of registered transliterators", 0 );
257 }
258}
259/* }}} */
260
261/* {{{ Transliterate a string. */
263{
264 char *str;
265 UChar *ustr = NULL,
266 *uresult = NULL;
267 size_t str_len;
268 int32_t ustr_len = 0,
269 capacity,
270 uresult_len;
271 zend_long start = 0,
272 limit = -1;
273 int success = 0;
274 zval tmp_object;
276
277 object = getThis();
278
279 ZVAL_UNDEF(&tmp_object);
280
281 if (object == NULL) {
282 /* in non-OOP version, accept both a transliterator and a string */
283 zend_string *arg1_str;
284 zend_object *arg1_obj;
285
288 Z_PARAM_STRING(str, str_len)
291 Z_PARAM_LONG(limit)
293
294 if (arg1_str) { /* not a transliterator object as first argument */
295 int res;
296 object = &tmp_object;
297 res = create_transliterator(ZSTR_VAL(arg1_str), ZSTR_LEN(arg1_str), TRANSLITERATOR_FORWARD, object);
298 if( res == FAILURE )
299 {
300 if (!EG(exception)) {
302 php_error_docref(NULL, E_WARNING, "Could not create transliterator with ID \"%s\" (%s)", ZSTR_VAL(arg1_str), ZSTR_VAL(message) );
303 zend_string_free( message );
304 }
305 ZVAL_UNDEF(&tmp_object);
306 /* don't set U_ILLEGAL_ARGUMENT_ERROR to allow fetching of inner error */
307 goto cleanup;
308 }
309 } else {
310 ZVAL_OBJ_COPY(&tmp_object, arg1_obj);
311 object = &tmp_object;
312 }
313 } else if(zend_parse_parameters( ZEND_NUM_ARGS(), "s|ll", &str, &str_len, &start, &limit) == FAILURE) {
315 }
316
317 if (limit < -1) {
318 zend_argument_value_error(object ? 3 : 4, "must be greater than or equal to -1");
319 goto cleanup_object;
320 }
321
322 if (start < 0) {
323 zend_argument_value_error(object ? 2 : 3, "must be greater than or equal to 0");
324 goto cleanup_object;
325 }
326
327 if (limit != -1 && start > limit) {
328 zend_argument_value_error(object ? 2 : 3, "must be less than or equal to argument #%d ($end)", object ? 3 : 4);
329 goto cleanup_object;
330 }
331
332 /* end argument parsing/validation */
333
335
336 intl_convert_utf8_to_utf16(&ustr, &ustr_len, str, str_len, TRANSLITERATOR_ERROR_CODE_P(to));
337 INTL_METHOD_CHECK_STATUS_OR_GOTO(to, "String conversion of string to UTF-16 failed", cleanup_object);
338
339 /* we've started allocating resources, goto from now on */
340
341 if( ( start > ustr_len ) || (( limit != -1 ) && (limit > ustr_len ) ) )
342 {
343 char *msg;
344 spprintf( &msg, 0,
345 "transliterator_transliterate: Neither \"start\" nor the \"end\" "
346 "arguments can exceed the number of UTF-16 code units "
347 "(in this case, %d)", (int) ustr_len );
348 if(msg != NULL )
349 {
351 msg, 1 );
352 efree( msg );
353 }
354 goto cleanup;
355 }
356
357 uresult = safe_emalloc( ustr_len, sizeof( UChar ), 1 * sizeof( UChar ) );
358 capacity = ustr_len + 1;
359
360 while( 1 )
361 {
362 int32_t temp_limit = ( limit == -1 ? ustr_len : (int32_t) limit );
363 memcpy( uresult, ustr, ustr_len * sizeof( UChar ) );
364 uresult_len = ustr_len;
365
366 utrans_transUChars( to->utrans, uresult, &uresult_len, capacity, (int32_t) start,
367 &temp_limit, TRANSLITERATOR_ERROR_CODE_P( to ) );
369 {
370 efree( uresult );
371
372 uresult = safe_emalloc( uresult_len, sizeof( UChar ), 1 * sizeof( UChar ) );
373 capacity = uresult_len + 1;
374
376 }
378 {
379 uresult = safe_erealloc( uresult, uresult_len, sizeof( UChar ), 1 * sizeof( UChar ) );
380
382 break;
383 }
384 else if( U_FAILURE( TRANSLITERATOR_ERROR_CODE( to ) ) )
385 {
388 "transliterator_transliterate: transliteration failed", 0 );
389 goto cleanup;
390 }
391 else
392 break;
393 }
394
395 uresult[uresult_len] = (UChar) 0;
396
397 success = 1;
398
399cleanup:
400 if( ustr )
401 efree( ustr );
402
403 if( success ) {
404 /* frees uresult even on error */
405 INTL_METHOD_RETVAL_UTF8( to, uresult, uresult_len, 1 );
406 }
407 else
408 {
409 if( uresult )
410 efree( uresult );
412 }
413
414cleanup_object:
415 zval_ptr_dtor( &tmp_object );
416}
417/* }}} */
418
420{
421 /* this constructor shouldn't be called as it's private */
423 "An object of this type cannot be created with the new operator.",
424 0 );
425}
426
427/* {{{ Get the last error code for this transliterator. */
429{
431
433 &object, Transliterator_ce_ptr ) == FAILURE )
434 {
436 }
437
438 /* Fetch the object (without resetting its last error code ). */
439 to = Z_INTL_TRANSLITERATOR_P( object );
440 if (to == NULL )
442
444}
445/* }}} */
446
447
448/* {{{ Get the last error message for this transliterator. */
450{
451 zend_string* message = NULL;
453
455 &object, Transliterator_ce_ptr ) == FAILURE )
456 {
458 }
459
460
461 /* Fetch the object (without resetting its last error code ). */
462 to = Z_INTL_TRANSLITERATOR_P( object );
463 if (to == NULL )
465
466 /* Return last error message. */
468 RETURN_STR( message );
469}
470/* }}} */
bool exception
Definition assert.c:30
const U_BUFFER_OVERFLOW_ERROR
const U_STRING_NOT_TERMINATED_WARNING
const U_ILLEGAL_ARGUMENT_ERROR
const U_ZERO_ERROR
DNS_STATUS status
Definition dns_win32.c:49
zend_string * res
Definition ffi.c:4692
memcpy(ptr1, ptr2, size)
buf start
Definition ffi.c:4687
zend_ffi_ctype_name_buf buf
Definition ffi.c:4685
#define NULL
Definition gdcache.h:45
#define SUCCESS
Definition hash_sha3.c:261
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_P(obj)
Definition intl_data.h:39
#define INTL_CHECK_STATUS(err, msg)
Definition intl_data.h:47
#define INTL_DATA_ERROR_CODE(obj)
Definition intl_data.h:40
#define INTL_METHOD_CHECK_STATUS_OR_GOTO(obj, msg, label)
Definition intl_data.h:75
#define INTL_METHOD_RETVAL_UTF8(obj, ustring, ulen, free_it)
Definition intl_data.h:103
#define INTL_METHOD_CHECK_STATUS_OR_NULL(obj, msg)
Definition intl_data.h:85
void intl_errors_set_custom_msg(intl_error *err, const char *msg, int copyMsg)
Definition intl_error.c:187
void intl_errors_set(intl_error *err, UErrorCode code, const char *msg, int copyMsg)
Definition intl_error.c:169
void intl_error_reset(intl_error *err)
Definition intl_error.c:78
void intl_error_set_code(intl_error *err, UErrorCode err_code)
Definition intl_error.c:141
void intl_error_set_custom_msg(intl_error *err, const char *msg, int copyMsg)
Definition intl_error.c:90
smart_str intl_parse_error_to_string(UParseError *pe)
Definition intl_error.c:206
zend_string * intl_error_get_message(intl_error *err)
Definition intl_error.c:116
PHPAPI ZEND_COLD void php_error_docref(const char *docref, int type, const char *format,...)
Definition main.c:1173
#define PHP_FUNCTION
Definition php.h:364
#define PHP_METHOD
Definition php.h:365
transliterator_get_error_code(Transliterator $transliterator)
transliterator_create_from_rules(string $rules, int $direction=Transliterator::FORWARD)
transliterator_transliterate(Transliterator|string $transliterator, string $string, int $start=0, int $end=-1)
transliterator_create(string $id, int $direction=Transliterator::FORWARD)
transliterator_list_ids()
transliterator_create_inverse(Transliterator $transliterator)
transliterator_get_error_message(Transliterator $transliterator)
char * msg
Definition phpdbg.h:289
#define spprintf
Definition spprintf.h:29
zend_string * s
zend_class_entry * Transliterator_ce_ptr
int transliterator_object_construct(zval *object, UTransliterator *utrans, UErrorCode *status)
#define TRANSLITERATOR_REVERSE
#define TRANSLITERATOR_ERROR_P(co)
#define TRANSLITERATOR_METHOD_FETCH_OBJECT
#define TRANSLITERATOR_FORWARD
#define TRANSLITERATOR_ERROR_CODE(co)
#define TRANSLITERATOR_METHOD_INIT_VARS
#define Z_INTL_TRANSLITERATOR_P(zv)
#define TRANSLITERATOR_ERROR_CODE_P(co)
#define TRANSLITERATOR_METHOD_FETCH_OBJECT_NO_CHECK
ZEND_API zend_result object_init_ex(zval *arg, zend_class_entry *class_type)
Definition zend_API.c:1849
ZEND_API zend_result zend_parse_parameters(uint32_t num_args, const char *type_spec,...)
Definition zend_API.c:1300
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
ZEND_API zend_result add_next_index_str(zval *arg, zend_string *str)
Definition zend_API.c:2177
#define ZEND_NUM_ARGS()
Definition zend_API.h:530
#define Z_PARAM_OBJ_OF_CLASS_OR_STR(destination_object, base_ce, destination_string)
Definition zend_API.h:1788
#define ZEND_PARSE_PARAMETERS_END()
Definition zend_API.h:1641
#define RETURN_FALSE
Definition zend_API.h:1058
#define ZEND_PARSE_PARAMETERS_NONE()
Definition zend_API.h:1623
#define RETURN_NULL()
Definition zend_API.h:1036
#define Z_PARAM_OPTIONAL
Definition zend_API.h:1667
#define Z_PARAM_STRING(dest, dest_len)
Definition zend_API.h:2071
#define ZEND_PARSE_PARAMETERS_START(min_num_args, max_num_args)
Definition zend_API.h:1620
#define Z_PARAM_LONG(dest)
Definition zend_API.h:1896
#define RETURN_LONG(l)
Definition zend_API.h:1037
#define RETURN_THROWS()
Definition zend_API.h:1060
#define RETURN_STR(s)
Definition zend_API.h:1039
#define getThis()
Definition zend_API.h:526
#define RETVAL_FALSE
Definition zend_API.h:1032
#define array_init(arg)
Definition zend_API.h:537
#define safe_erealloc(ptr, nmemb, size, offset)
Definition zend_alloc.h:161
#define efree(ptr)
Definition zend_alloc.h:155
#define safe_emalloc(nmemb, size, offset)
Definition zend_alloc.h:154
struct _zval_struct zval
#define E_WARNING
Definition zend_errors.h:24
ZEND_API ZEND_COLD zend_object * zend_throw_exception(zend_class_entry *exception_ce, const char *message, zend_long code)
ZEND_API void(ZEND_FASTCALL *zend_touch_vm_stack_data)(void *vm_stack_data)
#define EG(v)
ZEND_API void ZEND_FASTCALL zend_array_destroy(HashTable *ht)
Definition zend_hash.c:1808
int32_t zend_long
Definition zend_long.h:42
struct _zend_string zend_string
struct _zend_object zend_object
#define ZSTR_VAL(zstr)
Definition zend_string.h:68
#define ZSTR_LEN(zstr)
Definition zend_string.h:69
#define ZVAL_UNDEF(z)
@ FAILURE
Definition zend_types.h:61
#define ZVAL_OBJ_COPY(z, o)
#define Z_ARR_P(zval_p)
Definition zend_types.h:984
ZEND_API void zval_ptr_dtor(zval *zval_ptr)
zval * return_value