stas            Wed Jul 23 19:44:51 2008 UTC

  Modified files:              (Branch: PHP_5_3)
    /php-src/ext/intl/locale    locale_methods.c 
    /php-src/ext/intl/tests     locale_compose_locale.phpt 
  Log:
  add compose syntax as per request #14266
  
  
http://cvs.php.net/viewvc.cgi/php-src/ext/intl/locale/locale_methods.c?r1=1.1.2.2&r2=1.1.2.3&diff_format=u
Index: php-src/ext/intl/locale/locale_methods.c
diff -u php-src/ext/intl/locale/locale_methods.c:1.1.2.2 
php-src/ext/intl/locale/locale_methods.c:1.1.2.3
--- php-src/ext/intl/locale/locale_methods.c:1.1.2.2    Wed Jul 23 01:15:33 2008
+++ php-src/ext/intl/locale/locale_methods.c    Wed Jul 23 19:44:51 2008
@@ -34,6 +34,7 @@
 #include <zend.h>
 #include <php.h>
 #include "main/php_ini.h"
+#include "ext/standard/php_smart_str.h"
 
 ZEND_EXTERN_MODULE_GLOBALS( intl )
 
@@ -50,6 +51,8 @@
 #define MAX_NO_PRIVATE  15
 #define MAX_NO_LOOKUP_LANG_TAG  100
 
+#define LOC_NOT_FOUND 1
+
 //Sizes required for the strings "variant15" , "extlang3", "private12" etc.
 #define VARIANT_KEYNAME_LEN  11
 #define EXTLANG_KEYNAME_LEN  10
@@ -758,66 +761,42 @@
 }
 /* }}} */
 
-
 /* {{{ append_key_value 
 * Internal function which is called from locale_compose
 * gets the value for the key_name and appends to the loc_name
 * returns 1 if successful , -1 if not found , 
 * 0 if array element is not a string , -2 if buffer-overflow
 */
-static int append_key_value(char* loc_name, int loc_name_capacity , HashTable* 
hash_arr, char* key_name TSRMLS_DC)
+static int append_key_value(smart_str* loc_name, HashTable* hash_arr, char* 
key_name)
 {
-       int     needed_size     = -1;
        zval**  ele_value       = NULL;
 
-       intl_error_reset( NULL TSRMLS_CC );
-
-       if( zend_hash_find( hash_arr , key_name , strlen(key_name) + 1 ,(void 
**)&ele_value ) == SUCCESS ){
-               if( Z_TYPE_PP(ele_value)!= IS_STRING ){
+       if(zend_hash_find(hash_arr , key_name , strlen(key_name) + 1 ,(void 
**)&ele_value ) == SUCCESS ) {
+               if(Z_TYPE_PP(ele_value)!= IS_STRING ){
                        //element value is not a string 
-                       return 0;
+                       return FAILURE;
                }
-               if( strcmp(key_name , LOC_LANG_TAG) != 0 && 
-                   strcmp(key_name , LOC_GRANDFATHERED_LANG_TAG)!=0 ){
-
-                       needed_size = Z_STRLEN_PP(ele_value)+1 ;                
-                       if( needed_size > loc_name_capacity ){
-                               //Will cause Buffer_overflow
-                               return -2;
-                               
-                       } else {
-                               strcat( loc_name , SEPARATOR);
-                               strncat( loc_name , 
-                                        Z_STRVAL_PP(ele_value) , 
-                                        Z_STRLEN_PP(ele_value) );      
-                       }
-               } else {
-                       //lang or grandfathered  tag   
-                       needed_size = Z_STRLEN_PP(ele_value) ;          
-                       if( needed_size > loc_name_capacity ){
-                               //Will cause Buffer_overflow
-                               return -2;
-                               
-                       } else {
-                               strncat( loc_name , Z_STRVAL_PP(ele_value) , 
Z_STRLEN_PP(ele_value) );  
-                       }
+               if(strcmp(key_name, LOC_LANG_TAG) != 0 && 
+                  strcmp(key_name, LOC_GRANDFATHERED_LANG_TAG)!=0 ) {
+                       // not lang or grandfathered  tag   
+                       smart_str_appendl(loc_name, SEPARATOR , 
sizeof(SEPARATOR)-1);
                }
-       
-               return 1;
+               smart_str_appendl(loc_name, Z_STRVAL_PP(ele_value) , 
Z_STRLEN_PP(ele_value));
+               return SUCCESS;
        }
 
-       return -1;
+       return LOC_NOT_FOUND;
 }
 /* }}} */
 
 /* {{{ append_prefix , appends the prefix needed
 * e.g. private adds 'x'
 */
-static void add_prefix(char* loc_name , char* key_name)
+static void add_prefix(smart_str* loc_name, char* key_name)
 {
        if( strncmp(key_name , LOC_PRIVATE_TAG , 7) == 0 ){
-               strcat( loc_name , SEPARATOR);
-               strcat( loc_name , PRIVATE_PREFIX);
+               smart_str_appendl(loc_name, SEPARATOR , sizeof(SEPARATOR)-1);
+               smart_str_appendl(loc_name, PRIVATE_PREFIX , 
sizeof(PRIVATE_PREFIX)-1);
        }
 }
 /* }}} */
@@ -829,44 +808,45 @@
 * returns 1 if successful , -1 if not found , 
 * 0 if array element is not a string , -2 if buffer-overflow
 */
-static int append_multiple_key_values(char* loc_name, int loc_name_capacity  , 
HashTable* hash_arr, char* key_name TSRMLS_DC)
+static int append_multiple_key_values(smart_str* loc_name, HashTable* 
hash_arr, char* key_name)
 {
-       int     result          = -1;
        zval**  ele_value       = NULL;
-       char*   cur_key_name    = NULL;
-
        int     i               = 0;
        int     isFirstSubtag   = 0;
        int     max_value       = 0;
-       int     needed_size     = 0;
 
        //Variant/ Extlang/Private etc.
-       if( zend_hash_find( hash_arr , key_name , strlen(key_name) + 1 ,(void 
**)&ele_value ) == SUCCESS ){
-               if( Z_TYPE_PP(ele_value)!= IS_STRING ){
-                       //key_name is not a string 
-                       return 0;
-               }
-
-               //Determine the needed_size and check it against available
-               if( strcmp(key_name , LOC_PRIVATE_TAG) ==0 ){
-                       //for the string "-x-" and the size of array element
-                       needed_size = Z_STRLEN_PP(ele_value) + 3; 
+       if( zend_hash_find( hash_arr , key_name , strlen(key_name) + 1 ,(void 
**)&ele_value ) == SUCCESS ) {
+               if( Z_TYPE_PP(ele_value) == IS_STRING ){
+                       add_prefix( loc_name , key_name);
+
+                       smart_str_appendl(loc_name, SEPARATOR , 
sizeof(SEPARATOR)-1);
+                       smart_str_appendl(loc_name, Z_STRVAL_PP(ele_value) , 
Z_STRLEN_PP(ele_value));
+                       return SUCCESS;
+               } else if(Z_TYPE_PP(ele_value) == IS_ARRAY ) {
+                       HashPosition pos;
+                       HashTable *arr = HASH_OF(*ele_value);
+                       zval **data = NULL;
+
+                       zend_hash_internal_pointer_reset_ex(arr, &pos);
+                       while(zend_hash_get_current_data_ex(arr, (void 
**)&data, &pos) != FAILURE) {
+                               if(Z_TYPE_PP(data) != IS_STRING) {
+                                       return FAILURE;
+                               }
+                               if (isFirstSubtag++ == 0){
+                                       add_prefix(loc_name , key_name);
+                               }
+                               smart_str_appendl(loc_name, SEPARATOR , 
sizeof(SEPARATOR)-1);
+                               smart_str_appendl(loc_name, Z_STRVAL_PP(data) , 
Z_STRLEN_PP(data));
+                               zend_hash_move_forward_ex(arr, &pos);
+                       }
+                       return SUCCESS;
                } else {
-                       //for the SEPARATOR and the size of array element
-                       needed_size = Z_STRLEN_PP(ele_value) + 1; 
-               }
-               if( needed_size > loc_name_capacity){
-                       //Will cause buffer_overflow
-                       return -2;
+                       return FAILURE;
                }
-
-               add_prefix( loc_name , key_name);
-
-               strcat( loc_name , SEPARATOR);
-               strncat( loc_name , Z_STRVAL_PP(ele_value) , 
Z_STRLEN_PP(ele_value) );  
-               return 1;
        } else {
-               //Decide the max_value : the max. no. of elements allowed
+               char cur_key_name[31];
+               //Decide the max_value: the max. no. of elements allowed
                if( strcmp(key_name , LOC_VARIANT_TAG) ==0 ){
                        max_value  = MAX_NO_VARIANT;
                }
@@ -878,48 +858,25 @@
                }
 
                //Multiple variant values as variant0, variant1 ,variant2
-               cur_key_name = (char*)ecalloc( 25,  25);
                isFirstSubtag = 0;
                for( i=0 ; i< max_value; i++ ){  
-                       sprintf( cur_key_name , "%s%d", key_name , i);  
+                       snprintf( cur_key_name , 30, "%s%d", key_name , i);     
                        if( zend_hash_find( hash_arr , cur_key_name , 
strlen(cur_key_name) + 1,(void **)&ele_value ) == SUCCESS ){
                                if( Z_TYPE_PP(ele_value)!= IS_STRING ){
                                        //variant is not a string 
-                                       if( cur_key_name){
-                                               efree(cur_key_name);
-                                       }
-                                       return 0;
-                               }
-
-                               //Determine the needed_size and check it 
against available
-                               if( strcmp(key_name , LOC_PRIVATE_TAG) ==0 && 
isFirstSubtag ==0 ){
-                                       //for the string "-x-" and the size of 
array element
-                                       needed_size = Z_STRLEN_PP(ele_value) + 
3; 
-                               } else {
-                                       //for the SEPARATOR and the size of 
array element
-                                       needed_size = Z_STRLEN_PP(ele_value) + 
1; 
-                               }
-                               if( needed_size > loc_name_capacity){
-                                       //Will cause buffer_overflow
-                                       if( cur_key_name){
-                                               efree(cur_key_name);
-                                       }
-                                       return -2;
+                                       return FAILURE;
                                }
-                       
                                //Add the contents
                                if (isFirstSubtag++ == 0){
-                                       add_prefix( loc_name , cur_key_name);
+                                       add_prefix(loc_name , cur_key_name);
                                }
-                               strcat( loc_name , SEPARATOR);
-                               strncat( loc_name , Z_STRVAL_PP(ele_value) , 
Z_STRLEN_PP(ele_value) );  
+                               smart_str_appendl(loc_name, SEPARATOR , 
sizeof(SEPARATOR)-1);
+                               smart_str_appendl(loc_name, 
Z_STRVAL_PP(ele_value) , Z_STRLEN_PP(ele_value));
                        }
-                       result = 1;
                }//end of for 
-               efree(cur_key_name);
        }//end of else
 
-       return result;
+       return SUCCESS;
 }
 /* }}} */
 
@@ -928,31 +885,20 @@
 * returns 0  if locale_compose needs to be aborted 
 * otherwise returns 1
 */
-static int handleAppendResult( int result,char* loc_name TSRMLS_DC)
+static int handleAppendResult( int result, smart_str* loc_name TSRMLS_DC)
 {
        intl_error_reset( NULL TSRMLS_CC );
-       if( result == 0 ){
+       if( result == FAILURE) {
                intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR,
-                        "Aborting locale_compose: parameter array element is 
not a string ", 0 TSRMLS_CC );
-       
-               if( loc_name){
-                       efree(loc_name);
-               }
-               return 0;
-       }
-       if( result == -2 ){
-               intl_error_set( NULL, U_BUFFER_OVERFLOW_ERROR,
-                "Aborting locale_compose: array element will cause the buffer 
overflow. Maximum size allowed for locale_compose parameters is 512 bytes 
including separator character and prefixes. ", 0 TSRMLS_CC );
-
-               if( loc_name){
-                       efree(loc_name);
-               }
+                        "locale_compose: parameter array element is not a 
string", 0 TSRMLS_CC );
+               smart_str_free(loc_name);
                return 0;
        }
        return 1;
 }
 /* }}} */
 
+#define RETURN_SMART_STR(s) smart_str_0((s)); RETURN_STRINGL((s)->c, (s)->len, 
0)
 /* {{{ proto static string Locale::composeLocale($array) 
 * Creates a locale by combining the parts of locale-ID passed  
 * }}} */
@@ -961,26 +907,20 @@
 * }}} */
 PHP_FUNCTION(locale_compose)
 {
-       char*           loc_name        = NULL;
-       int             loc_name_len    = 0;
-
-       int32_t         buflen          = 512;
-
-       zval*           arr             = NULL;
-       HashTable*      hash_arr        = NULL;
-
-       int             result          = 0;
+       smart_str       loc_name_s = {0};
+       smart_str *loc_name = &loc_name_s;
+       zval*                   arr     = NULL;
+       HashTable*              hash_arr = NULL;
+       int                     result = 0;
 
        intl_error_reset( NULL TSRMLS_CC );
-
        // Parse parameters.
        if(zend_parse_parameters( ZEND_NUM_ARGS() TSRMLS_CC, "a",
                &arr) == FAILURE)
        {
-       intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR,
-            "locale_compose: unable to parse input params", 0 TSRMLS_CC );
-
-       RETURN_FALSE;
+               intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR,
+                        "locale_compose: unable to parse input params", 0 
TSRMLS_CC );
+               RETURN_FALSE;
        }
 
        hash_arr = HASH_OF( arr );
@@ -988,27 +928,21 @@
        if( !hash_arr || zend_hash_num_elements( hash_arr ) == 0 )
                RETURN_FALSE;
 
-       //Allocate memory
-       loc_name = (char*)ecalloc( 512,  sizeof(char));
-       loc_name_len = buflen;
-
        //Check for grandfathered first
-       result = append_key_value( loc_name , loc_name_len , hash_arr ,  
LOC_GRANDFATHERED_LANG_TAG TSRMLS_CC );        
-       if( result == 1 ){
-               RETURN_STRING( loc_name ,FALSE);
+       result = append_key_value(loc_name, hash_arr,  
LOC_GRANDFATHERED_LANG_TAG);     
+       if( result == SUCCESS){
+               RETURN_SMART_STR(loc_name);
        }
        if( !handleAppendResult( result, loc_name TSRMLS_CC)){
                RETURN_FALSE;
        }
 
        //Not grandfathered
-       result = append_key_value( loc_name , loc_name_len , hash_arr , 
LOC_LANG_TAG TSRMLS_CC );       
-       if( result == -1 ){
+       result = append_key_value(loc_name, hash_arr , LOC_LANG_TAG);   
+       if( result == LOC_NOT_FOUND ){
                intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR,
                "locale_compose: parameter array does not contain 'language' 
tag.", 0 TSRMLS_CC );
-               if( loc_name){
-                       efree(loc_name);
-               }
+               smart_str_free(loc_name);
                RETURN_FALSE;
        }
        if( !handleAppendResult( result, loc_name TSRMLS_CC)){
@@ -1016,36 +950,36 @@
        }
 
        //Extlang
-       result = append_multiple_key_values( loc_name , loc_name_len , hash_arr 
, LOC_EXTLANG_TAG TSRMLS_CC );
+       result = append_multiple_key_values(loc_name, hash_arr , 
LOC_EXTLANG_TAG);
        if( !handleAppendResult( result, loc_name TSRMLS_CC)){
                RETURN_FALSE;
        }
 
        //Script
-       result = append_key_value( loc_name , loc_name_len , hash_arr , 
LOC_SCRIPT_TAG TSRMLS_CC ); 
+       result = append_key_value(loc_name, hash_arr , LOC_SCRIPT_TAG); 
        if( !handleAppendResult( result, loc_name TSRMLS_CC)){
                RETURN_FALSE;
        }
        
        //Region
-       result = append_key_value( loc_name , loc_name_len , hash_arr , 
LOC_REGION_TAG TSRMLS_CC );
+       result = append_key_value( loc_name, hash_arr , LOC_REGION_TAG);
        if( !handleAppendResult( result, loc_name TSRMLS_CC)){
                RETURN_FALSE;
        }
 
        //Variant
-       result = append_multiple_key_values( loc_name , loc_name_len , hash_arr 
, LOC_VARIANT_TAG TSRMLS_CC ); 
+       result = append_multiple_key_values( loc_name, hash_arr , 
LOC_VARIANT_TAG); 
        if( !handleAppendResult( result, loc_name TSRMLS_CC)){
                RETURN_FALSE;
        }
 
        //Private
-       result = append_multiple_key_values( loc_name , loc_name_len , hash_arr 
, LOC_PRIVATE_TAG TSRMLS_CC );
+       result = append_multiple_key_values( loc_name, hash_arr , 
LOC_PRIVATE_TAG);
        if( !handleAppendResult( result, loc_name TSRMLS_CC)){
                RETURN_FALSE;
        }
 
-       RETURN_STRING( loc_name , FALSE);
+       RETURN_SMART_STR(loc_name);
 }
 /* }}} */
 
http://cvs.php.net/viewvc.cgi/php-src/ext/intl/tests/locale_compose_locale.phpt?r1=1.1.2.1&r2=1.1.2.2&diff_format=u
Index: php-src/ext/intl/tests/locale_compose_locale.phpt
diff -u php-src/ext/intl/tests/locale_compose_locale.phpt:1.1.2.1 
php-src/ext/intl/tests/locale_compose_locale.phpt:1.1.2.2
--- php-src/ext/intl/tests/locale_compose_locale.phpt:1.1.2.1   Mon Jul  7 
22:51:04 2008
+++ php-src/ext/intl/tests/locale_compose_locale.phpt   Wed Jul 23 19:44:51 2008
@@ -12,12 +12,10 @@
 
 function ut_main()
 {
-       $longstr = str_repeat("blah", 500);
        $loc_parts_arr1 = array( 
                Locale::LANG_TAG =>'sl' ,
                Locale::SCRIPT_TAG =>'Latn' ,
-               Locale::REGION_TAG =>'IT' ,
-               Locale::VARIANT_TAG => $longstr
+               Locale::REGION_TAG =>'IT' 
        );
        $loc_parts_arr2 = array( 
                Locale::LANG_TAG =>'de' ,
@@ -66,25 +64,27 @@
        $loc_parts_arr9 = array( 
                Locale::REGION_TAG =>'DE'
        );
-       $loc_parts_arr10 = array(
-               Locale::LANG_TAG => $longstr
-       );      
-       $loc_parts_arr11 = array(
-               Locale::LANG_TAG =>'en' ,
-               'private0' => $longstr
-       );
-       $loc_parts_arr12 = array( 
+       $loc_parts_arr10 = array( 
                Locale::LANG_TAG => 45,
                Locale::REGION_TAG => false,
                Locale::SCRIPT_TAG => 15
        );
-       $loc_parts_arr13 = array(
+       $loc_parts_arr11 = array(
                Locale::LANG_TAG =>'de'  , 
                Locale::REGION_TAG =>'DE', 
                'private0' => 13,
                'variant1' => array(),
                'extlang2' => false
        );      
+        $loc_parts_arr12 = array(
+                Locale::LANG_TAG =>'en' ,
+                Locale::SCRIPT_TAG =>'Hans' ,
+                Locale::REGION_TAG =>'CN',
+                Locale::VARIANT_TAG => array('nedis', 'rozaj'),
+               Locale::PRIVATE_TAG => array('prv1', 'prv2'),
+               Locale::EXTLANG_TAG => array('lng', 'ing')
+        );
+
 
        $loc_parts_arr = array(
                'loc1' => $loc_parts_arr1       ,
@@ -98,8 +98,7 @@
                'loc9' => $loc_parts_arr9       ,
                'loc10' => $loc_parts_arr10     ,
                'loc11' => $loc_parts_arr11     ,
-               'loc12' => $loc_parts_arr12     ,
-               'loc13' => $loc_parts_arr13
+               'loc12' => $loc_parts_arr12
        );
 
     error_reporting( E_ERROR );
@@ -139,8 +138,7 @@
 ------------
 Input Array name is : loc1
 
-Composed Locale: No values found from Locale compose due to the following 
error:
-Aborting locale_compose: array element will cause the buffer overflow. Maximum 
size allowed for locale_compose parameters is 512 bytes including separator 
character and prefixes. : U_BUFFER_OVERFLOW_ERROR
+Composed Locale: sl_Latn_IT
 ------------
 Input Array name is : loc2
 
@@ -178,20 +176,14 @@
 Input Array name is : loc10
 
 Composed Locale: No values found from Locale compose due to the following 
error:
-Aborting locale_compose: array element will cause the buffer overflow. Maximum 
size allowed for locale_compose parameters is 512 bytes including separator 
character and prefixes. : U_BUFFER_OVERFLOW_ERROR
+locale_compose: parameter array element is not a string: 
U_ILLEGAL_ARGUMENT_ERROR
 ------------
 Input Array name is : loc11
 
 Composed Locale: No values found from Locale compose due to the following 
error:
-Aborting locale_compose: array element will cause the buffer overflow. Maximum 
size allowed for locale_compose parameters is 512 bytes including separator 
character and prefixes. : U_BUFFER_OVERFLOW_ERROR
+locale_compose: parameter array element is not a string: 
U_ILLEGAL_ARGUMENT_ERROR
 ------------
 Input Array name is : loc12
 
-Composed Locale: No values found from Locale compose due to the following 
error:
-Aborting locale_compose: parameter array element is not a string : 
U_ILLEGAL_ARGUMENT_ERROR
+Composed Locale: en_lng_ing_Hans_CN_nedis_rozaj_x_prv1_prv2
 ------------
-Input Array name is : loc13
-
-Composed Locale: No values found from Locale compose due to the following 
error:
-Aborting locale_compose: parameter array element is not a string : 
U_ILLEGAL_ARGUMENT_ERROR
-------------
\ No newline at end of file

-- 
PHP CVS Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to