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

LCOV - code coverage report
Current view: top level - ext/intl/collator - collator_sort.c (source / functions) Hit Total Coverage
Test: PHP Code Coverage Lines: 171 238 71.8 %
Date: 2016-06-25 Functions: 11 12 91.7 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10

Generated at Sat, 25 Jun 2016 07:08:56 +0000 (43 hours ago)

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