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

Generated by: LCOV version 1.10

Generated at Mon, 10 Nov 2014 22:46:40 +0000 (11 days ago)

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