root/ext/intl/collator/collator_sort.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. collator_regular_compare_function
  2. collator_numeric_compare_function
  3. collator_icu_compare_function
  4. collator_compare_func
  5. collator_cmp_sort_keys
  6. collator_get_compare_function
  7. collator_sort_internal
  8. PHP_FUNCTION
  9. PHP_FUNCTION
  10. PHP_FUNCTION
  11. PHP_FUNCTION

   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.h"
  24 #include "collator_class.h"
  25 #include "collator_sort.h"
  26 #include "collator_convert.h"
  27 #include "intl_convert.h"
  28 
  29 #if !defined(HAVE_PTRDIFF_T) && !defined(_PTRDIFF_T_DEFINED)
  30 typedef long ptrdiff_t;
  31 #endif
  32 
  33 /**
  34  * Declare 'index' which will point to sort key in sort key
  35  * buffer.
  36  */
  37 typedef struct _collator_sort_key_index {
  38         char* key;       /* pointer to sort key */
  39         zval** zstr;     /* pointer to original string(hash-item) */
  40 } collator_sort_key_index_t;
  41 
  42 ZEND_EXTERN_MODULE_GLOBALS( intl )
  43 
  44 static const size_t DEF_SORT_KEYS_BUF_SIZE = 1048576;
  45 static const size_t DEF_SORT_KEYS_BUF_INCREMENT = 1048576;
  46 
  47 static const size_t DEF_SORT_KEYS_INDX_BUF_SIZE = 1048576;
  48 static const size_t DEF_SORT_KEYS_INDX_BUF_INCREMENT = 1048576;
  49 
  50 static const size_t DEF_UTF16_BUF_SIZE = 1024;
  51 
  52 /* {{{ collator_regular_compare_function */
  53 static int collator_regular_compare_function(zval *result, zval *op1, zval *op2 TSRMLS_DC)
  54 {
  55         Collator_object* co = NULL;
  56 
  57         int rc      = SUCCESS;
  58 
  59         zval* str1  = collator_convert_object_to_string( op1 TSRMLS_CC );
  60         zval* str2  = collator_convert_object_to_string( op2 TSRMLS_CC );
  61 
  62         zval* num1  = NULL;
  63         zval* num2  = NULL;
  64         zval* norm1 = NULL;
  65         zval* norm2 = NULL;
  66 
  67         /* If both args are strings AND either of args is not numeric string
  68          * then use ICU-compare. Otherwise PHP-compare. */
  69         if( Z_TYPE_P(str1) == IS_STRING && Z_TYPE_P(str2) == IS_STRING &&
  70                 ( str1 == ( num1 = collator_convert_string_to_number_if_possible( str1 ) ) ||
  71                   str2 == ( num2 = collator_convert_string_to_number_if_possible( str2 ) ) ) )
  72         {
  73                 /* Fetch collator object. */
  74                 co = (Collator_object *) zend_object_store_get_object( INTL_G(current_collator) TSRMLS_CC );
  75 
  76                 if (!co || !co->ucoll) {
  77                         intl_error_set_code( NULL, COLLATOR_ERROR_CODE( co ) TSRMLS_CC );
  78                         intl_errors_set_custom_msg( COLLATOR_ERROR_P( co ),
  79                                 "Object not initialized", 0 TSRMLS_CC );
  80                         php_error_docref(NULL TSRMLS_CC, E_RECOVERABLE_ERROR, "Object not initialized");
  81 
  82                 }
  83 
  84                 /* Compare the strings using ICU. */
  85                 result->value.lval = ucol_strcoll(
  86                                 co->ucoll,
  87                                 INTL_Z_STRVAL_P(str1), INTL_Z_STRLEN_P(str1),
  88                                 INTL_Z_STRVAL_P(str2), INTL_Z_STRLEN_P(str2) );
  89                 result->type = IS_LONG;
  90         }
  91         else
  92         {
  93                 /* num1 is set if str1 and str2 are strings. */
  94                 if( num1 )
  95                 {
  96                         if( num1 == str1 )
  97                         {
  98                                 /* str1 is string but not numeric string
  99                                  * just convert it to utf8. 
 100                                  */
 101                                 norm1 = collator_convert_zstr_utf16_to_utf8( str1 );
 102 
 103                                 /* num2 is not set but str2 is string => do normalization. */
 104                                 norm2 = collator_normalize_sort_argument( str2 );
 105                         }
 106                         else
 107                         {
 108                                 /* str1 is numeric strings => passthru to PHP-compare. */
 109                                 zval_add_ref( &num1 );
 110                                 norm1 = num1;
 111 
 112                                 /* str2 is numeric strings => passthru to PHP-compare. */
 113                                 zval_add_ref( &num2 );
 114                                 norm2 = num2;
 115                         }
 116                 }
 117                 else
 118                 {
 119                         /* num1 is not set if str1 or str2 is not a string => do normalization. */
 120                         norm1 = collator_normalize_sort_argument( str1 );
 121 
 122                         /* if num1 is not set then num2 is not set as well => do normalization. */
 123                         norm2 = collator_normalize_sort_argument( str2 );
 124                 }
 125 
 126                 rc = compare_function( result, norm1, norm2 TSRMLS_CC );
 127 
 128                 zval_ptr_dtor( &norm1 );
 129                 zval_ptr_dtor( &norm2 );
 130         }
 131 
 132         if( num1 )
 133                 zval_ptr_dtor( &num1 );
 134 
 135         if( num2 )
 136                 zval_ptr_dtor( &num2 );
 137 
 138         zval_ptr_dtor( &str1 );
 139         zval_ptr_dtor( &str2 );
 140 
 141         return rc;
 142 }
 143 /* }}} */
 144 
 145 /* {{{ collator_numeric_compare_function
 146  * Convert input args to double and compare it.
 147  */
 148 static int collator_numeric_compare_function(zval *result, zval *op1, zval *op2 TSRMLS_DC)
 149 {
 150         int rc     = SUCCESS;
 151         zval* num1 = NULL;
 152         zval* num2 = NULL;
 153 
 154         if( Z_TYPE_P(op1) == IS_STRING )
 155         {
 156                 num1 = collator_convert_string_to_double( op1 );
 157                 op1 = num1;
 158         }
 159 
 160         if( Z_TYPE_P(op2) == IS_STRING )
 161         {
 162                 num2 = collator_convert_string_to_double( op2 );
 163                 op2 = num2;
 164         }
 165 
 166         rc = numeric_compare_function( result, op1, op2 TSRMLS_CC);
 167 
 168         if( num1 )
 169                 zval_ptr_dtor( &num1 );
 170         if( num2 )
 171                 zval_ptr_dtor( &num2 );
 172 
 173         return rc;
 174 }
 175 /* }}} */
 176 
 177 /* {{{ collator_icu_compare_function
 178  * Direct use of ucol_strcoll.
 179 */
 180 static int collator_icu_compare_function(zval *result, zval *op1, zval *op2 TSRMLS_DC)
 181 {
 182         int rc              = SUCCESS;
 183         Collator_object* co = NULL;
 184         zval* str1          = NULL;
 185         zval* str2          = NULL;
 186 
 187         str1 = collator_make_printable_zval( op1 );
 188         str2 = collator_make_printable_zval( op2 );
 189 
 190         /* Fetch collator object. */
 191         co = (Collator_object *) zend_object_store_get_object( INTL_G(current_collator) TSRMLS_CC );
 192 
 193         /* Compare the strings using ICU. */
 194         result->value.lval = ucol_strcoll(
 195                         co->ucoll,
 196                         INTL_Z_STRVAL_P(str1), INTL_Z_STRLEN_P(str1),
 197                         INTL_Z_STRVAL_P(str2), INTL_Z_STRLEN_P(str2) );
 198         result->type = IS_LONG;
 199 
 200         zval_ptr_dtor( &str1 );
 201         zval_ptr_dtor( &str2 );
 202 
 203         return rc;
 204 }
 205 /* }}} */
 206 
 207 /* {{{ collator_compare_func
 208  * Taken from PHP5 source (array_data_compare).
 209  */
 210 static int collator_compare_func( const void* a, const void* b TSRMLS_DC )
 211 {
 212         Bucket *f;
 213         Bucket *s;
 214         zval result;
 215         zval *first;
 216         zval *second;
 217 
 218         f = *((Bucket **) a);
 219         s = *((Bucket **) b);
 220 
 221         first = *((zval **) f->pData);
 222         second = *((zval **) s->pData);
 223 
 224         if( INTL_G(compare_func)( &result, first, second TSRMLS_CC) == FAILURE )
 225                 return 0;
 226 
 227         if( Z_TYPE(result) == IS_DOUBLE )
 228         {
 229                 if( Z_DVAL(result) < 0 )
 230                         return -1;
 231                 else if( Z_DVAL(result) > 0 )
 232                         return 1;
 233                 else
 234                         return 0;
 235         }
 236 
 237         convert_to_long(&result);
 238 
 239         if( Z_LVAL(result) < 0 )
 240                 return -1;
 241         else if( Z_LVAL(result) > 0 )
 242                 return 1;
 243 
 244         return 0;
 245 }
 246 /* }}} */
 247 
 248 /* {{{ collator_cmp_sort_keys
 249  * Compare sort keys
 250  */
 251 static int collator_cmp_sort_keys( const void *p1, const void *p2 TSRMLS_DC )
 252 {
 253         char* key1 = ((collator_sort_key_index_t*)p1)->key;
 254         char* key2 = ((collator_sort_key_index_t*)p2)->key;
 255 
 256         return strcmp( key1, key2 );
 257 }
 258 /* }}} */
 259 
 260 /* {{{ collator_get_compare_function
 261  * Choose compare function according to sort flags.
 262  */
 263 static collator_compare_func_t collator_get_compare_function( const long sort_flags )
 264 {
 265         collator_compare_func_t func;
 266 
 267         switch( sort_flags )
 268         {
 269                 case COLLATOR_SORT_NUMERIC:
 270                         func = collator_numeric_compare_function;
 271                         break;
 272 
 273                 case COLLATOR_SORT_STRING:
 274                         func = collator_icu_compare_function;
 275                         break;
 276 
 277                 case COLLATOR_SORT_REGULAR:
 278                 default:
 279                         func = collator_regular_compare_function;
 280                         break;
 281         }
 282 
 283         return func;
 284 }
 285 /* }}} */
 286 
 287 /* {{{ collator_sort_internal
 288  * Common code shared by collator_sort() and collator_asort() API functions.
 289  */
 290 static void collator_sort_internal( int renumber, INTERNAL_FUNCTION_PARAMETERS )
 291 {
 292         zval*          array            = NULL;
 293         HashTable*     hash             = NULL;
 294         zval*          saved_collator   = NULL;
 295         long           sort_flags       = COLLATOR_SORT_REGULAR;
 296 
 297         COLLATOR_METHOD_INIT_VARS
 298 
 299         /* Parse parameters. */
 300         if( zend_parse_method_parameters( ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Oa|l",
 301                 &object, Collator_ce_ptr, &array, &sort_flags ) == FAILURE )
 302         {
 303                 intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR,
 304                         "collator_sort_internal: unable to parse input params", 0 TSRMLS_CC );
 305 
 306                 RETURN_FALSE;
 307         }
 308 
 309         /* Fetch the object. */
 310         COLLATOR_METHOD_FETCH_OBJECT;
 311 
 312         /* Set 'compare function' according to sort flags. */
 313         INTL_G(compare_func) = collator_get_compare_function( sort_flags );
 314 
 315         hash = HASH_OF( array );
 316 
 317         /* Convert strings in the specified array from UTF-8 to UTF-16. */
 318         collator_convert_hash_from_utf8_to_utf16( hash, COLLATOR_ERROR_CODE_P( co ) );
 319         COLLATOR_CHECK_STATUS( co, "Error converting hash from UTF-8 to UTF-16" );
 320 
 321         /* Save specified collator in the request-global (?) variable. */
 322         saved_collator = INTL_G( current_collator );
 323         INTL_G( current_collator ) = object;
 324 
 325         /* Sort specified array. */
 326         zend_hash_sort( hash, zend_qsort, collator_compare_func, renumber TSRMLS_CC );
 327 
 328         /* Restore saved collator. */
 329         INTL_G( current_collator ) = saved_collator;
 330 
 331         /* Convert strings in the specified array back to UTF-8. */
 332         collator_convert_hash_from_utf16_to_utf8( hash, COLLATOR_ERROR_CODE_P( co ) );
 333         COLLATOR_CHECK_STATUS( co, "Error converting hash from UTF-16 to UTF-8" );
 334 
 335         RETURN_TRUE;
 336 }
 337 /* }}} */
 338 
 339 /* {{{ proto bool Collator::sort( Collator $coll, array(string) $arr [, int $sort_flags] )
 340  * Sort array using specified collator. }}} */
 341 /* {{{ proto bool collator_sort(  Collator $coll, array(string) $arr [, int $sort_flags] )
 342  * Sort array using specified collator.
 343  */
 344 PHP_FUNCTION( collator_sort )
 345 {
 346         collator_sort_internal( TRUE, INTERNAL_FUNCTION_PARAM_PASSTHRU );
 347 }
 348 /* }}} */
 349 
 350 /* {{{ proto bool Collator::sortWithSortKeys( Collator $coll, array(string) $arr )
 351  * Equivalent to standard PHP sort using Collator.
 352  * Uses ICU ucol_getSortKey for performance. }}} */
 353 /* {{{ proto bool collator_sort_with_sort_keys( Collator $coll, array(string) $arr )
 354  * Equivalent to standard PHP sort using Collator.
 355  * Uses ICU ucol_getSortKey for performance.
 356  */
 357 PHP_FUNCTION( collator_sort_with_sort_keys )
 358 {
 359         zval*       array                = NULL;
 360         HashTable*  hash                 = NULL;
 361         zval**      hashData             = NULL;                     /* currently processed item of input hash */
 362 
 363         char*       sortKeyBuf           = NULL;                     /* buffer to store sort keys */
 364         uint32_t    sortKeyBufSize       = DEF_SORT_KEYS_BUF_SIZE;   /* buffer size */
 365         ptrdiff_t   sortKeyBufOffset     = 0;                        /* pos in buffer to store sort key */
 366         int32_t     sortKeyLen           = 0;                        /* the length of currently processing key */
 367         uint32_t    bufLeft              = 0;
 368         uint32_t    bufIncrement         = 0;
 369 
 370         collator_sort_key_index_t* sortKeyIndxBuf = NULL;            /* buffer to store 'indexes' which will be passed to 'qsort' */
 371         uint32_t    sortKeyIndxBufSize   = DEF_SORT_KEYS_INDX_BUF_SIZE;
 372         uint32_t    sortKeyIndxSize      = sizeof( collator_sort_key_index_t );
 373 
 374         uint32_t    sortKeyCount         = 0;
 375         uint32_t    j                    = 0;
 376 
 377         UChar*      utf16_buf            = NULL;                     /* tmp buffer to hold current processing string in utf-16 */
 378         int         utf16_buf_size       = DEF_UTF16_BUF_SIZE;       /* the length of utf16_buf */
 379         int         utf16_len            = 0;                        /* length of converted string */
 380 
 381         HashTable* sortedHash            = NULL;
 382 
 383         COLLATOR_METHOD_INIT_VARS
 384 
 385         /* Parse parameters. */
 386         if( zend_parse_method_parameters( ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Oa",
 387                 &object, Collator_ce_ptr, &array ) == FAILURE )
 388         {
 389                 intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR,
 390                         "collator_sort_with_sort_keys: unable to parse input params", 0 TSRMLS_CC );
 391 
 392                 RETURN_FALSE;
 393         }
 394 
 395         /* Fetch the object. */
 396         COLLATOR_METHOD_FETCH_OBJECT;
 397 
 398         if (!co || !co->ucoll) {
 399                 intl_error_set_code( NULL, COLLATOR_ERROR_CODE( co ) TSRMLS_CC );
 400                 intl_errors_set_custom_msg( COLLATOR_ERROR_P( co ),
 401                         "Object not initialized", 0 TSRMLS_CC );
 402                 php_error_docref(NULL TSRMLS_CC, E_RECOVERABLE_ERROR, "Object not initialized");
 403 
 404                 RETURN_FALSE;
 405         }
 406 
 407         /*
 408          * Sort specified array.
 409          */
 410         hash = HASH_OF( array );
 411 
 412         if( !hash || zend_hash_num_elements( hash ) == 0 )
 413                 RETURN_TRUE;
 414 
 415         /* Create bufers */
 416         sortKeyBuf     = ecalloc( sortKeyBufSize,     sizeof( char    ) );
 417         sortKeyIndxBuf = ecalloc( sortKeyIndxBufSize, sizeof( uint8_t ) );
 418         utf16_buf      = eumalloc( utf16_buf_size );
 419 
 420         /* Iterate through input hash and create a sort key for each value. */
 421         zend_hash_internal_pointer_reset( hash );
 422         while( zend_hash_get_current_data( hash, (void**) &hashData ) == SUCCESS )
 423         {
 424                 /* Convert current hash item from UTF-8 to UTF-16LE and save the result to utf16_buf. */
 425 
 426                 utf16_len = utf16_buf_size;
 427 
 428                 /* Process string values only. */
 429                 if( Z_TYPE_PP( hashData ) == IS_STRING )
 430                 {
 431                         intl_convert_utf8_to_utf16( &utf16_buf, &utf16_len, Z_STRVAL_PP( hashData ), Z_STRLEN_PP( hashData ), COLLATOR_ERROR_CODE_P( co ) );
 432 
 433                         if( U_FAILURE( COLLATOR_ERROR_CODE( co ) ) )
 434                         {
 435                                 intl_error_set_code( NULL, COLLATOR_ERROR_CODE( co ) TSRMLS_CC );
 436                                 intl_errors_set_custom_msg( COLLATOR_ERROR_P( co ), "Sort with sort keys failed", 0 TSRMLS_CC );
 437 
 438                                 if( utf16_buf )
 439                                         efree( utf16_buf );
 440 
 441                                 efree( sortKeyIndxBuf );
 442                                 efree( sortKeyBuf );
 443 
 444                                 RETURN_FALSE;
 445                         }
 446                 }
 447                 else
 448                 {
 449                         /* Set empty string */
 450                         utf16_len = 0;
 451                         utf16_buf[utf16_len] = 0;
 452                 }
 453 
 454                 if( (utf16_len + 1) > utf16_buf_size )
 455                         utf16_buf_size = utf16_len + 1;
 456 
 457                 /* Get sort key, reallocating the buffer if needed. */
 458                 bufLeft = sortKeyBufSize - sortKeyBufOffset;
 459 
 460                 sortKeyLen = ucol_getSortKey( co->ucoll,
 461                                                                           utf16_buf,
 462                                                                           utf16_len,
 463                                                                           (uint8_t*)sortKeyBuf + sortKeyBufOffset,
 464                                                                           bufLeft );
 465 
 466                 /* check for sortKeyBuf overflow, increasing its size of the buffer if needed */
 467                 if( sortKeyLen > bufLeft )
 468                 {
 469                         bufIncrement = ( sortKeyLen > DEF_SORT_KEYS_BUF_INCREMENT ) ? sortKeyLen : DEF_SORT_KEYS_BUF_INCREMENT;
 470 
 471                         sortKeyBufSize += bufIncrement;
 472                         bufLeft += bufIncrement;
 473 
 474                         sortKeyBuf = erealloc( sortKeyBuf, sortKeyBufSize );
 475 
 476                         sortKeyLen = ucol_getSortKey( co->ucoll, utf16_buf, utf16_len, (uint8_t*)sortKeyBuf + sortKeyBufOffset, bufLeft );
 477                 }
 478 
 479                 /*  check sortKeyIndxBuf overflow, increasing its size of the buffer if needed */
 480                 if( ( sortKeyCount + 1 ) * sortKeyIndxSize > sortKeyIndxBufSize )
 481                 {
 482                         bufIncrement = ( sortKeyIndxSize > DEF_SORT_KEYS_INDX_BUF_INCREMENT ) ? sortKeyIndxSize : DEF_SORT_KEYS_INDX_BUF_INCREMENT;
 483 
 484                         sortKeyIndxBufSize += bufIncrement;
 485 
 486                         sortKeyIndxBuf = erealloc( sortKeyIndxBuf, sortKeyIndxBufSize );
 487                 }
 488 
 489                 sortKeyIndxBuf[sortKeyCount].key = (char*)sortKeyBufOffset;    /* remeber just offset, cause address */
 490                                                                                /* of 'sortKeyBuf' may be changed due to realloc. */
 491                 sortKeyIndxBuf[sortKeyCount].zstr = hashData;
 492 
 493                 sortKeyBufOffset += sortKeyLen;
 494                 ++sortKeyCount;
 495 
 496                 zend_hash_move_forward( hash );
 497         }
 498 
 499         /* update ptrs to point to valid keys. */
 500         for( j = 0; j < sortKeyCount; j++ )
 501                 sortKeyIndxBuf[j].key = sortKeyBuf + (ptrdiff_t)sortKeyIndxBuf[j].key;
 502 
 503         /* sort it */
 504         zend_qsort( sortKeyIndxBuf, sortKeyCount, sortKeyIndxSize, collator_cmp_sort_keys TSRMLS_CC );
 505 
 506         /* for resulting hash we'll assign new hash keys rather then reordering */
 507         ALLOC_HASHTABLE( sortedHash );
 508         zend_hash_init( sortedHash, 0, NULL, ZVAL_PTR_DTOR, 0 );
 509 
 510         for( j = 0; j < sortKeyCount; j++ )
 511         {
 512                 zval_add_ref( sortKeyIndxBuf[j].zstr );
 513                 zend_hash_next_index_insert( sortedHash, sortKeyIndxBuf[j].zstr, sizeof(zval **), NULL );
 514         }
 515 
 516         /* Save sorted hash into return variable. */
 517         zval_dtor( array );
 518         (array)->value.ht = sortedHash;
 519         (array)->type = IS_ARRAY;
 520 
 521         if( utf16_buf )
 522                 efree( utf16_buf );
 523 
 524         efree( sortKeyIndxBuf );
 525         efree( sortKeyBuf );
 526 
 527         RETURN_TRUE;
 528 }
 529 /* }}} */
 530 
 531 /* {{{ proto bool Collator::asort( Collator $coll, array(string) $arr )
 532  * Sort array using specified collator, maintaining index association. }}} */
 533 /* {{{ proto bool collator_asort( Collator $coll, array(string) $arr )
 534  * Sort array using specified collator, maintaining index association.
 535  */
 536 PHP_FUNCTION( collator_asort )
 537 {
 538         collator_sort_internal( FALSE, INTERNAL_FUNCTION_PARAM_PASSTHRU );
 539 }
 540 /* }}} */
 541 
 542 /* {{{ proto bool Collator::getSortKey( Collator $coll, string $str )
 543  * Get a sort key for a string from a Collator. }}} */
 544 /* {{{ proto bool collator_get_sort_key( Collator $coll, string $str )
 545  * Get a sort key for a string from a Collator. }}} */
 546 PHP_FUNCTION( collator_get_sort_key )
 547 {
 548         char*            str      = NULL;
 549         int              str_len  = 0;
 550         UChar*           ustr     = NULL;
 551         int              ustr_len = 0;
 552         uint8_t*         key     = NULL;
 553         int              key_len = 0;
 554 
 555         COLLATOR_METHOD_INIT_VARS
 556 
 557         /* Parse parameters. */
 558         if( zend_parse_method_parameters( ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Os",
 559                 &object, Collator_ce_ptr, &str, &str_len ) == FAILURE )
 560         {
 561                 intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR,
 562                          "collator_get_sort_key: unable to parse input params", 0 TSRMLS_CC );
 563 
 564                 RETURN_FALSE;
 565         }
 566 
 567         /* Fetch the object. */
 568         COLLATOR_METHOD_FETCH_OBJECT;
 569 
 570         if (!co || !co->ucoll) {
 571                 intl_error_set_code( NULL, COLLATOR_ERROR_CODE( co ) TSRMLS_CC );
 572                 intl_errors_set_custom_msg( COLLATOR_ERROR_P( co ),
 573                         "Object not initialized", 0 TSRMLS_CC );
 574                 php_error_docref(NULL TSRMLS_CC, E_RECOVERABLE_ERROR, "Object not initialized");
 575 
 576                 RETURN_FALSE;
 577         }
 578 
 579         /*
 580          * Compare given strings (converting them to UTF-16 first).
 581          */
 582 
 583         /* First convert the strings to UTF-16. */
 584         intl_convert_utf8_to_utf16(
 585                 &ustr, &ustr_len, str, str_len, COLLATOR_ERROR_CODE_P( co ) );
 586         if( U_FAILURE( COLLATOR_ERROR_CODE( co ) ) )
 587         {
 588                 /* Set global error code. */
 589                 intl_error_set_code( NULL, COLLATOR_ERROR_CODE( co ) TSRMLS_CC );
 590 
 591                 /* Set error messages. */
 592                 intl_errors_set_custom_msg( COLLATOR_ERROR_P( co ),
 593                         "Error converting first argument to UTF-16", 0 TSRMLS_CC );
 594                 efree( ustr );
 595                 RETURN_FALSE;
 596         }
 597 
 598         /* ucol_getSortKey is exception in that the key length includes the 
 599          * NUL terminator*/
 600         key_len = ucol_getSortKey(co->ucoll, ustr, ustr_len, key, 0);
 601         if(!key_len) {
 602                 efree( ustr );
 603                 RETURN_FALSE;
 604         }
 605         key = emalloc(key_len);
 606         key_len = ucol_getSortKey(co->ucoll, ustr, ustr_len, key, key_len);
 607         efree( ustr );
 608         if(!key_len) {
 609                 RETURN_FALSE;
 610         }
 611         RETURN_STRINGL((char *)key, key_len - 1, 0);
 612 }
 613 /* }}} */
 614 
 615 /*
 616  * Local variables:
 617  * tab-width: 4
 618  * c-basic-offset: 4
 619  * End:
 620  * vim600: noet sw=4 ts=4 fdm=marker
 621  * vim<600: noet sw=4 ts=4
 622  */

/* [<][>][^][v][top][bottom][index][help] */