Annotation of embedaddon/php/ext/intl/collator/collator_convert.c, revision 1.1.1.1
1.1 misho 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: Vadim Savchuk <vsavchuk@productengine.com> |
14: | Dmitry Lakhtyuk <dlakhtyuk@productengine.com> |
15: +----------------------------------------------------------------------+
16: */
17:
18: #ifdef HAVE_CONFIG_H
19: #include "config.h"
20: #endif
21:
22: #include "php_intl.h"
23: #include "collator_class.h"
24: #include "collator_is_numeric.h"
25: #include "collator_convert.h"
26: #include "intl_convert.h"
27:
28: #include <unicode/ustring.h>
29: #include <php.h>
30:
31: #if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION <= 1)
32: #define CAST_OBJECT_SHOULD_FREE ,0
33: #else
34: #define CAST_OBJECT_SHOULD_FREE
35: #endif
36:
37: #define COLLATOR_CONVERT_RETURN_FAILED(retval) { \
38: zval_add_ref( &retval ); \
39: return retval; \
40: }
41:
42: /* {{{ collator_convert_hash_item_from_utf8_to_utf16 */
43: static void collator_convert_hash_item_from_utf8_to_utf16(
44: HashTable* hash, int hashKeyType, char* hashKey, ulong hashIndex,
45: UErrorCode* status )
46: {
47: const char* old_val;
48: int old_val_len;
49: UChar* new_val = NULL;
50: int new_val_len = 0;
51: zval** hashData = NULL;
52: zval* znew_val = NULL;
53:
54: /* Get current hash item. */
55: zend_hash_get_current_data( hash, (void**) &hashData );
56:
57: /* Process string values only. */
58: if( Z_TYPE_P( *hashData ) != IS_STRING )
59: return;
60:
61: old_val = Z_STRVAL_P( *hashData );
62: old_val_len = Z_STRLEN_P( *hashData );
63:
64: /* Convert it from UTF-8 to UTF-16LE and save the result to new_val[_len]. */
65: intl_convert_utf8_to_utf16( &new_val, &new_val_len, old_val, old_val_len, status );
66: if( U_FAILURE( *status ) )
67: return;
68:
69: /* Update current hash item with the converted value. */
70: MAKE_STD_ZVAL( znew_val );
71: ZVAL_STRINGL( znew_val, (char*)new_val, UBYTES(new_val_len), FALSE );
72:
73: if( hashKeyType == HASH_KEY_IS_STRING )
74: {
75: zend_hash_update( hash, hashKey, strlen( hashKey ) + 1,
76: (void*) &znew_val, sizeof(zval*), NULL );
77: }
78: else /* hashKeyType == HASH_KEY_IS_LONG */
79: {
80: zend_hash_index_update( hash, hashIndex,
81: (void*) &znew_val, sizeof(zval*), NULL );
82: }
83: }
84: /* }}} */
85:
86: /* {{{ collator_convert_hash_item_from_utf16_to_utf8 */
87: static void collator_convert_hash_item_from_utf16_to_utf8(
88: HashTable* hash, int hashKeyType, char* hashKey, ulong hashIndex,
89: UErrorCode* status )
90: {
91: const char* old_val;
92: int old_val_len;
93: char* new_val = NULL;
94: int new_val_len = 0;
95: zval** hashData = NULL;
96: zval* znew_val = NULL;
97:
98: /* Get current hash item. */
99: zend_hash_get_current_data( hash, (void**) &hashData );
100:
101: /* Process string values only. */
102: if( Z_TYPE_P( *hashData ) != IS_STRING )
103: return;
104:
105: old_val = Z_STRVAL_P( *hashData );
106: old_val_len = Z_STRLEN_P( *hashData );
107:
108: /* Convert it from UTF-16LE to UTF-8 and save the result to new_val[_len]. */
109: intl_convert_utf16_to_utf8( &new_val, &new_val_len,
110: (UChar*)old_val, UCHARS(old_val_len), status );
111: if( U_FAILURE( *status ) )
112: return;
113:
114: /* Update current hash item with the converted value. */
115: MAKE_STD_ZVAL( znew_val );
116: ZVAL_STRINGL( znew_val, (char*)new_val, new_val_len, FALSE );
117:
118: if( hashKeyType == HASH_KEY_IS_STRING )
119: {
120: zend_hash_update( hash, hashKey, strlen( hashKey ) + 1,
121: (void*) &znew_val, sizeof(zval*), NULL );
122: }
123: else /* hashKeyType == HASH_KEY_IS_LONG */
124: {
125: zend_hash_index_update( hash, hashIndex,
126: (void*) &znew_val, sizeof(zval*), NULL );
127: }
128: }
129: /* }}} */
130:
131: /* {{{ collator_convert_hash_from_utf8_to_utf16
132: * Convert values of the given hash from UTF-8 encoding to UTF-16LE.
133: */
134: void collator_convert_hash_from_utf8_to_utf16( HashTable* hash, UErrorCode* status )
135: {
136: ulong hashIndex = 0;
137: char* hashKey = NULL;
138: int hashKeyType = 0;
139:
140: zend_hash_internal_pointer_reset( hash );
141: while( ( hashKeyType = zend_hash_get_current_key( hash, &hashKey, &hashIndex, 0 ) )
142: != HASH_KEY_NON_EXISTANT )
143: {
144: /* Convert current hash item from UTF-8 to UTF-16LE. */
145: collator_convert_hash_item_from_utf8_to_utf16(
146: hash, hashKeyType, hashKey, hashIndex, status );
147: if( U_FAILURE( *status ) )
148: return;
149:
150: /* Proceed to the next item. */
151: zend_hash_move_forward( hash );
152: }
153: }
154: /* }}} */
155:
156: /* {{{ collator_convert_hash_from_utf16_to_utf8
157: * Convert values of the given hash from UTF-16LE encoding to UTF-8.
158: */
159: void collator_convert_hash_from_utf16_to_utf8( HashTable* hash, UErrorCode* status )
160: {
161: ulong hashIndex = 0;
162: char* hashKey = NULL;
163: int hashKeyType = 0;
164:
165: zend_hash_internal_pointer_reset( hash );
166: while( ( hashKeyType = zend_hash_get_current_key( hash, &hashKey, &hashIndex, 0 ) )
167: != HASH_KEY_NON_EXISTANT )
168: {
169: /* Convert current hash item from UTF-16LE to UTF-8. */
170: collator_convert_hash_item_from_utf16_to_utf8(
171: hash, hashKeyType, hashKey, hashIndex, status );
172: if( U_FAILURE( *status ) ) {
173: return;
174: }
175:
176: /* Proceed to the next item. */
177: zend_hash_move_forward( hash );
178: }
179: }
180: /* }}} */
181:
182: /* {{{ collator_convert_zstr_utf16_to_utf8
183: *
184: * Convert string from utf16 to utf8.
185: *
186: * @param zval* utf16_zval String to convert.
187: *
188: * @return zval* Converted string.
189: */
190: zval* collator_convert_zstr_utf16_to_utf8( zval* utf16_zval )
191: {
192: zval* utf8_zval = NULL;
193: char* str = NULL;
194: int str_len = 0;
195: UErrorCode status = U_ZERO_ERROR;
196:
197: /* Convert to utf8 then. */
198: intl_convert_utf16_to_utf8( &str, &str_len,
199: (UChar*) Z_STRVAL_P(utf16_zval), UCHARS( Z_STRLEN_P(utf16_zval) ), &status );
200: if( U_FAILURE( status ) )
201: php_error( E_WARNING, "Error converting utf16 to utf8 in collator_convert_zval_utf16_to_utf8()" );
202:
203: ALLOC_INIT_ZVAL( utf8_zval );
204: ZVAL_STRINGL( utf8_zval, str, str_len, FALSE );
205:
206: return utf8_zval;
207: }
208: /* }}} */
209:
210: /* {{{ collator_convert_zstr_utf8_to_utf16
211: *
212: * Convert string from utf8 to utf16.
213: *
214: * @param zval* utf8_zval String to convert.
215: *
216: * @return zval* Converted string.
217: */
218: zval* collator_convert_zstr_utf8_to_utf16( zval* utf8_zval )
219: {
220: zval* zstr = NULL;
221: UChar* ustr = NULL;
222: int ustr_len = 0;
223: UErrorCode status = U_ZERO_ERROR;
224:
225: /* Convert the string to UTF-16. */
226: intl_convert_utf8_to_utf16(
227: &ustr, &ustr_len,
228: Z_STRVAL_P( utf8_zval ), Z_STRLEN_P( utf8_zval ),
229: &status );
230: if( U_FAILURE( status ) )
231: php_error( E_WARNING, "Error casting object to string in collator_convert_zstr_utf8_to_utf16()" );
232:
233: /* Set string. */
234: ALLOC_INIT_ZVAL( zstr );
235: ZVAL_STRINGL( zstr, (char*)ustr, UBYTES(ustr_len), FALSE );
236:
237: return zstr;
238: }
239: /* }}} */
240:
241: /* {{{ collator_convert_object_to_string
242: * Convert object to UTF16-encoded string.
243: */
244: zval* collator_convert_object_to_string( zval* obj TSRMLS_DC )
245: {
246: zval* zstr = NULL;
247: UErrorCode status = U_ZERO_ERROR;
248: UChar* ustr = NULL;
249: int ustr_len = 0;
250:
251: /* Bail out if it's not an object. */
252: if( Z_TYPE_P( obj ) != IS_OBJECT )
253: {
254: COLLATOR_CONVERT_RETURN_FAILED( obj );
255: }
256:
257: /* Try object's handlers. */
258: if( Z_OBJ_HT_P(obj)->get )
259: {
260: zstr = Z_OBJ_HT_P(obj)->get( obj TSRMLS_CC );
261:
262: switch( Z_TYPE_P( zstr ) )
263: {
264: case IS_OBJECT:
265: {
266: /* Bail out. */
267: zval_ptr_dtor( &zstr );
268: COLLATOR_CONVERT_RETURN_FAILED( obj );
269: } break;
270:
271: case IS_STRING:
272: break;
273:
274: default:
275: {
276: convert_to_string( zstr );
277: } break;
278: }
279: }
280: else if( Z_OBJ_HT_P(obj)->cast_object )
281: {
282: ALLOC_INIT_ZVAL( zstr );
283:
284: if( Z_OBJ_HT_P(obj)->cast_object( obj, zstr, IS_STRING CAST_OBJECT_SHOULD_FREE TSRMLS_CC ) == FAILURE )
285: {
286: /* cast_object failed => bail out. */
287: zval_ptr_dtor( &zstr );
288: COLLATOR_CONVERT_RETURN_FAILED( obj );
289: }
290: }
291:
292: /* Object wasn't successfuly converted => bail out. */
293: if( zstr == NULL )
294: {
295: COLLATOR_CONVERT_RETURN_FAILED( obj );
296: }
297:
298: /* Convert the string to UTF-16. */
299: intl_convert_utf8_to_utf16(
300: &ustr, &ustr_len,
301: Z_STRVAL_P( zstr ), Z_STRLEN_P( zstr ),
302: &status );
303: if( U_FAILURE( status ) )
304: php_error( E_WARNING, "Error casting object to string in collator_convert_object_to_string()" );
305:
306: /* Cleanup zstr to hold utf16 string. */
307: zval_dtor( zstr );
308:
309: /* Set string. */
310: ZVAL_STRINGL( zstr, (char*)ustr, UBYTES(ustr_len), FALSE );
311:
312: /* Don't free ustr cause it's set in zstr without copy.
313: * efree( ustr );
314: */
315:
316: return zstr;
317: }
318: /* }}} */
319:
320: /* {{{ collator_convert_string_to_number
321: *
322: * Convert string to number.
323: *
324: * @param zval* str String to convert.
325: *
326: * @return zval* Number. If str is not numeric string return number zero.
327: */
328: zval* collator_convert_string_to_number( zval* str )
329: {
330: zval* num = collator_convert_string_to_number_if_possible( str );
331: if( num == str )
332: {
333: /* String wasn't converted => return zero. */
334: zval_ptr_dtor( &num );
335:
336: ALLOC_INIT_ZVAL( num );
337: ZVAL_LONG( num, 0 );
338: }
339:
340: return num;
341: }
342: /* }}} */
343:
344: /* {{{ collator_convert_string_to_double
345: *
346: * Convert string to double.
347: *
348: * @param zval* str String to convert.
349: *
350: * @return zval* Number. If str is not numeric string return number zero.
351: */
352: zval* collator_convert_string_to_double( zval* str )
353: {
354: zval* num = collator_convert_string_to_number( str );
355: if( Z_TYPE_P(num) == IS_LONG )
356: {
357: ZVAL_DOUBLE( num, Z_LVAL_P( num ) );
358: }
359:
360: return num;
361: }
362: /* }}} */
363:
364: /* {{{ collator_convert_string_to_number_if_possible
365: *
366: * Convert string to numer.
367: *
368: * @param zval* str String to convert.
369: *
370: * @return zval* Number if str is numeric string. Otherwise
371: * original str param.
372: */
373: zval* collator_convert_string_to_number_if_possible( zval* str )
374: {
375: zval* num = NULL;
376: int is_numeric = 0;
377: long lval = 0;
378: double dval = 0;
379:
380: if( Z_TYPE_P( str ) != IS_STRING )
381: {
382: COLLATOR_CONVERT_RETURN_FAILED( str );
383: }
384:
385: if( ( is_numeric = collator_is_numeric( (UChar*) Z_STRVAL_P(str), UCHARS( Z_STRLEN_P(str) ), &lval, &dval, 1 ) ) )
386: {
387: ALLOC_INIT_ZVAL( num );
388:
389: if( is_numeric == IS_LONG )
390: Z_LVAL_P(num) = lval;
391: if( is_numeric == IS_DOUBLE )
392: Z_DVAL_P(num) = dval;
393:
394: Z_TYPE_P(num) = is_numeric;
395: }
396: else
397: {
398: COLLATOR_CONVERT_RETURN_FAILED( str );
399: }
400:
401: return num;
402: }
403: /* }}} */
404:
405: /* {{{ collator_make_printable_zval
406: *
407: * Returns string from input zval.
408: *
409: * @param zval* arg zval to get string from
410: *
411: * @return zval* UTF16 string.
412: */
413: zval* collator_make_printable_zval( zval* arg )
414: {
415: zval arg_copy;
416: int use_copy = 0;
417: zval* str = NULL;
418:
419: if( Z_TYPE_P(arg) != IS_STRING )
420: {
421: zend_make_printable_zval(arg, &arg_copy, &use_copy);
422:
423: if( use_copy )
424: {
425: str = collator_convert_zstr_utf8_to_utf16( &arg_copy );
426: zval_dtor( &arg_copy );
427: }
428: else
429: {
430: str = collator_convert_zstr_utf8_to_utf16( arg );
431: }
432: }
433: else
434: {
435: COLLATOR_CONVERT_RETURN_FAILED( arg );
436: }
437:
438: return str;
439: }
440: /* }}} */
441:
442: /* {{{ collator_normalize_sort_argument
443: *
444: * Normalize argument to use in sort's compare function.
445: *
446: * @param zval* arg Sort's argument to normalize.
447: *
448: * @return zval* Normalized copy of arg or unmodified arg
449: * if normalization is not needed.
450: */
451: zval* collator_normalize_sort_argument( zval* arg )
452: {
453: zval* n_arg = NULL;
454:
455: if( Z_TYPE_P( arg ) != IS_STRING )
456: {
457: /* If its not a string then nothing to do.
458: * Return original arg.
459: */
460: COLLATOR_CONVERT_RETURN_FAILED( arg );
461: }
462:
463: /* Try convert to number. */
464: n_arg = collator_convert_string_to_number_if_possible( arg );
465:
466: if( n_arg == arg )
467: {
468: /* Conversion to number failed. */
469: zval_ptr_dtor( &n_arg );
470:
471: /* Convert string to utf8. */
472: n_arg = collator_convert_zstr_utf16_to_utf8( arg );
473: }
474:
475: return n_arg;
476: }
477: /* }}} */
478: /*
479: * Local variables:
480: * tab-width: 4
481: * c-basic-offset: 4
482: * End:
483: * vim600: noet sw=4 ts=4 fdm=marker
484: * vim<600: noet sw=4 ts=4
485: */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>