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

Generated by: LCOV version 1.10

Generated at Wed, 02 Sep 2015 17:19:10 +0000 (45 hours ago)

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