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

Generated by: LCOV version 1.10

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

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