PHP  
 PHP: Test and Code Coverage Analysis
downloads | QA | documentation | faq | getting help | mailing lists | reporting bugs | php.net sites | links | my php.net 
 

LTP GCOV extension - code coverage report
Current view: directory - intl/collator - collator_sort.c
Test: PHP Code Coverage
Date: 2009-11-21 Instrumented lines: 228
Code covered: 75.4 % Executed lines: 172
Legend: not executed executed

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

Generated by: LTP GCOV extension version 1.5

Generated at Sat, 21 Nov 2009 12:27:01 +0000 (3 days ago)

Copyright © 2005-2009 The PHP Group
All rights reserved.