Annotation of embedaddon/php/ext/intl/locale/locale_methods.c, revision 1.1.1.4

1.1       misho       1: /*
                      2:    +----------------------------------------------------------------------+
                      3:    | PHP Version 5                                                        |
                      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: Kirti Velankar <kirtig@yahoo-inc.com>                       |
                     14:    +----------------------------------------------------------------------+
                     15: */
                     16: 
1.1.1.2   misho      17: /* $Id$ */
1.1       misho      18: 
                     19: #ifdef HAVE_CONFIG_H
                     20: #include "config.h"
                     21: #endif
                     22: 
                     23: #include <unicode/ustring.h>
                     24: #include <unicode/udata.h>
                     25: #include <unicode/putil.h>
                     26: #include <unicode/ures.h>
                     27: 
                     28: #include "php_intl.h"
                     29: #include "locale.h"
                     30: #include "locale_class.h"
                     31: #include "locale_methods.h"
                     32: #include "intl_convert.h"
                     33: #include "intl_data.h"
                     34: 
                     35: #include <zend_API.h>
                     36: #include <zend.h>
                     37: #include <php.h>
                     38: #include "main/php_ini.h"
                     39: #include "ext/standard/php_smart_str.h"
                     40: 
                     41: ZEND_EXTERN_MODULE_GLOBALS( intl )
                     42: 
                     43: /* Sizes required for the strings "variant15" , "extlang11", "private12" etc. */
                     44: #define SEPARATOR "_"
                     45: #define SEPARATOR1 "-"
                     46: #define DELIMITER "-_"
                     47: #define EXTLANG_PREFIX "a"
                     48: #define PRIVATE_PREFIX "x"
                     49: #define DISP_NAME "name"
                     50: 
                     51: #define MAX_NO_VARIANT  15
                     52: #define MAX_NO_EXTLANG  3
                     53: #define MAX_NO_PRIVATE  15
                     54: #define MAX_NO_LOOKUP_LANG_TAG  100
                     55: 
                     56: #define LOC_NOT_FOUND 1
                     57: 
                     58: /* Sizes required for the strings "variant15" , "extlang3", "private12" etc. */
                     59: #define VARIANT_KEYNAME_LEN  11
                     60: #define EXTLANG_KEYNAME_LEN  10
                     61: #define PRIVATE_KEYNAME_LEN  11
                     62: 
                     63: /* Based on IANA registry at the time of writing this code
                     64: *
                     65: */
                     66: static const char * const LOC_GRANDFATHERED[] = {
                     67:        "art-lojban",           "i-klingon",            "i-lux",                        "i-navajo",             "no-bok",               "no-nyn",
                     68:        "cel-gaulish",          "en-GB-oed",            "i-ami",                
                     69:        "i-bnn",                "i-default",            "i-enochian",   
                     70:        "i-mingo",              "i-pwn",                "i-tao", 
                     71:        "i-tay",                "i-tsu",                "sgn-BE-fr",
                     72:        "sgn-BE-nl",            "sgn-CH-de",            "zh-cmn",
                     73:        "zh-cmn-Hans",          "zh-cmn-Hant",          "zh-gan" ,
                     74:        "zh-guoyu",             "zh-hakka",             "zh-min",
                     75:        "zh-min-nan",           "zh-wuu",               "zh-xiang",     
                     76:        "zh-yue",               NULL
                     77: };
                     78: 
                     79: /* Based on IANA registry at the time of writing this code
                     80: *  This array lists the preferred values for the grandfathered tags if applicable
                     81: *  This is in sync with the array LOC_GRANDFATHERED     
                     82: *  e.g. the offsets of the grandfathered tags match the offset of the preferred  value
                     83: */
                     84: static const int               LOC_PREFERRED_GRANDFATHERED_LEN = 6;
                     85: static const char * const      LOC_PREFERRED_GRANDFATHERED[]  = {
                     86:        "jbo",                  "tlh",                  "lb",
                     87:        "nv",                   "nb",                   "nn",                   
                     88:        NULL
                     89: };
                     90: 
                     91: /*returns TRUE if a is an ID separator FALSE otherwise*/
                     92: #define isIDSeparator(a) (a == '_' || a == '-')
                     93: #define isKeywordSeparator(a) (a == '@' )
                     94: #define isEndOfTag(a) (a == '\0' )
                     95: 
                     96: #define isPrefixLetter(a) ((a=='x')||(a=='X')||(a=='i')||(a=='I'))
                     97: 
                     98: /*returns TRUE if one of the special prefixes is here (s=string)
                     99:   'x-' or 'i-' */
                    100: #define isIDPrefix(s) (isPrefixLetter(s[0])&&isIDSeparator(s[1]))
                    101: #define isKeywordPrefix(s) ( isKeywordSeparator(s[0]) )
                    102: 
                    103: /* Dot terminates it because of POSIX form  where dot precedes the codepage
                    104:  * except for variant */
                    105: #define isTerminator(a)  ((a==0)||(a=='.')||(a=='@'))
                    106: 
                    107: /* {{{ return the offset of 'key' in the array 'list'.
                    108:  * returns -1 if not present */
                    109: static int16_t findOffset(const char* const* list, const char* key)
                    110: {
                    111:        const char* const* anchor = list;
                    112:        while (*list != NULL) {
                    113:                if (strcmp(key, *list) == 0) {
                    114:                        return (int16_t)(list - anchor);
                    115:                }
                    116:                list++;
                    117:        }
                    118: 
                    119:        return -1;
                    120: 
                    121: }
                    122: /*}}}*/
                    123: 
                    124: static char* getPreferredTag(char* gf_tag)
                    125: { 
                    126:        char* result = NULL;
                    127:        int grOffset = 0;
                    128: 
                    129:        grOffset = findOffset( LOC_GRANDFATHERED ,gf_tag);
1.1.1.4 ! misho     130:        if(grOffset < 0) {
        !           131:                return NULL;
        !           132:        }
1.1       misho     133:        if( grOffset < LOC_PREFERRED_GRANDFATHERED_LEN ){
                    134:                /* return preferred tag */
                    135:                result = estrdup( LOC_PREFERRED_GRANDFATHERED[grOffset] );
                    136:        } else {
                    137:                /* Return correct grandfathered language tag */
                    138:                result = estrdup( LOC_GRANDFATHERED[grOffset] );
                    139:        }
                    140:        return result;
                    141: }
                    142: 
                    143: /* {{{
                    144: * returns the position of next token for lookup 
                    145: * or -1 if no token
                    146: * strtokr equivalent search for token in reverse direction 
                    147: */
                    148: static int getStrrtokenPos(char* str, int savedPos)
                    149: {
                    150:        int result =-1;
                    151:        int i;
                    152:        
                    153:        for(i=savedPos-1; i>=0; i--) {
                    154:                if(isIDSeparator(*(str+i)) ){
                    155:                        /* delimiter found; check for singleton */
                    156:                        if(i>=2 && isIDSeparator(*(str+i-2)) ){
                    157:                                /* a singleton; so send the position of token before the singleton */
                    158:                                result = i-2;
                    159:                        } else {
                    160:                                result = i;
                    161:                        }
                    162:                        break;
                    163:                }
                    164:        }
                    165:        if(result < 1){
                    166:                /* Just in case inavlid locale e.g. '-x-xyz' or '-sl_Latn' */
                    167:                result =-1;
                    168:        }
                    169:        return result;
                    170: }
                    171: /* }}} */
                    172: 
                    173: /* {{{
                    174: * returns the position of a singleton if present 
                    175: * returns -1 if no singleton
                    176: * strtok equivalent search for singleton
                    177: */
                    178: static int getSingletonPos(char* str)
                    179: {
                    180:        int result =-1;
                    181:        int i=0;
                    182:        int len = 0;
                    183:        
                    184:        if( str && ((len=strlen(str))>0) ){
                    185:                for( i=0; i<len ; i++){
                    186:                        if( isIDSeparator(*(str+i)) ){
                    187:                                if( i==1){
                    188:                                        /* string is of the form x-avy or a-prv1 */
                    189:                                        result =0;
                    190:                                        break;
                    191:                                } else {
                    192:                                        /* delimiter found; check for singleton */
                    193:                                        if( isIDSeparator(*(str+i+2)) ){
                    194:                                                /* a singleton; so send the position of separator before singleton */
                    195:                                                result = i+1;
                    196:                                                break;
                    197:                                        }
                    198:                                }
                    199:                        }
                    200:                }/* end of for */
                    201:                
                    202:        }
                    203:        return result;
                    204: }
                    205: /* }}} */
                    206: 
                    207: /* {{{ proto static string Locale::getDefault(  )
                    208:    Get default locale */
                    209: /* }}} */
                    210: /* {{{ proto static string locale_get_default( )
                    211:    Get default locale */
                    212: PHP_NAMED_FUNCTION(zif_locale_get_default)
                    213: {
                    214:        if( INTL_G(default_locale) == NULL ) {
                    215:                INTL_G(default_locale) = pestrdup( uloc_getDefault(), 1);
                    216:        }
                    217:        RETURN_STRING( INTL_G(default_locale), TRUE );
                    218: }
                    219: 
                    220: /* }}} */
                    221: 
                    222: /* {{{ proto static string Locale::setDefault( string $locale )
                    223:    Set default locale */
                    224: /* }}} */
                    225: /* {{{ proto static string locale_set_default( string $locale )
                    226:    Set default locale */
                    227: PHP_NAMED_FUNCTION(zif_locale_set_default)
                    228: {
                    229:        char* locale_name = NULL;
                    230:        int   len=0;    
                    231: 
                    232:        if(zend_parse_parameters( ZEND_NUM_ARGS() TSRMLS_CC,  "s",
                    233:                &locale_name ,&len ) == FAILURE)
                    234:        {
                    235:                intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR,
                    236:                                "locale_set_default: unable to parse input params", 0 TSRMLS_CC );
                    237: 
                    238:                RETURN_FALSE;
                    239:        }
                    240: 
                    241:        if(len == 0) {
                    242:                locale_name =  (char *)uloc_getDefault() ;
                    243:                len = strlen(locale_name);
                    244:        }
                    245: 
                    246:        zend_alter_ini_entry(LOCALE_INI_NAME, sizeof(LOCALE_INI_NAME), locale_name, len, PHP_INI_USER, PHP_INI_STAGE_RUNTIME);  
                    247: 
                    248:        RETURN_TRUE;
                    249: }
                    250: /* }}} */
                    251: 
                    252: /* {{{
                    253: * Gets the value from ICU 
                    254: * common code shared by get_primary_language,get_script or get_region or get_variant
                    255: * result = 0 if error, 1 if successful , -1 if no value
                    256: */
                    257: static char* get_icu_value_internal( char* loc_name , char* tag_name, int* result , int fromParseLocale)
                    258: {
                    259:        char*           tag_value       = NULL;
                    260:        int32_t         tag_value_len   = 512;
                    261: 
                    262:        int             singletonPos    = 0;
                    263:        char*           mod_loc_name    = NULL;
                    264:        int             grOffset        = 0;
                    265: 
                    266:        int32_t         buflen          = 512;
                    267:        UErrorCode      status          = U_ZERO_ERROR;
                    268: 
                    269: 
                    270:        if( strcmp(tag_name, LOC_CANONICALIZE_TAG) != 0 ){
                    271:                /* Handle  grandfathered languages */
                    272:                grOffset =  findOffset( LOC_GRANDFATHERED , loc_name );
                    273:                if( grOffset >= 0 ){
                    274:                        if( strcmp(tag_name , LOC_LANG_TAG)==0 ){
                    275:                                tag_value = estrdup(loc_name);
                    276:                                return tag_value;
                    277:                        } else {
                    278:                                /* Since Grandfathered , no value , do nothing , retutn NULL */
                    279:                                return NULL;
                    280:                        }
                    281:                }
                    282: 
                    283:        if( fromParseLocale==1 ){
                    284:                /* Handle singletons */
                    285:                if( strcmp(tag_name , LOC_LANG_TAG)==0 ){
                    286:                        if( strlen(loc_name)>1 && (isIDPrefix(loc_name) ==1 ) ){
                    287:                                return loc_name;
                    288:                        }
                    289:                }
                    290: 
                    291:                singletonPos = getSingletonPos( loc_name );     
                    292:                if( singletonPos == 0){
                    293:                        /* singleton at start of script, region , variant etc.
                    294:                         * or invalid singleton at start of language */
                    295:                        return NULL;
                    296:                } else if( singletonPos > 0 ){
                    297:                        /* singleton at some position except at start
                    298:                         * strip off the singleton and rest of the loc_name */
                    299:                        mod_loc_name = estrndup ( loc_name , singletonPos-1);
                    300:                }
                    301:        } /* end of if fromParse */
                    302: 
                    303:        } /* end of if != LOC_CANONICAL_TAG */
                    304: 
                    305:        if( mod_loc_name == NULL){
                    306:                mod_loc_name = estrdup(loc_name );      
                    307:        }
                    308: 
                    309:        /* Proceed to ICU */
                    310:     do{
                    311:                tag_value = erealloc( tag_value , buflen  );
                    312:                tag_value_len = buflen;
                    313: 
                    314:                if( strcmp(tag_name , LOC_SCRIPT_TAG)==0 ){
                    315:                        buflen = uloc_getScript ( mod_loc_name ,tag_value , tag_value_len , &status);
                    316:                }
                    317:                if( strcmp(tag_name , LOC_LANG_TAG )==0 ){
                    318:                        buflen = uloc_getLanguage ( mod_loc_name ,tag_value , tag_value_len , &status);
                    319:                }
                    320:                if( strcmp(tag_name , LOC_REGION_TAG)==0 ){
                    321:                        buflen = uloc_getCountry ( mod_loc_name ,tag_value , tag_value_len , &status);
                    322:                }
                    323:                if( strcmp(tag_name , LOC_VARIANT_TAG)==0 ){
                    324:                        buflen = uloc_getVariant ( mod_loc_name ,tag_value , tag_value_len , &status);
                    325:                }
                    326:                if( strcmp(tag_name , LOC_CANONICALIZE_TAG)==0 ){
                    327:                        buflen = uloc_canonicalize ( mod_loc_name ,tag_value , tag_value_len , &status);
                    328:                }
                    329: 
                    330:                if( U_FAILURE( status ) ) {
                    331:                        if( status == U_BUFFER_OVERFLOW_ERROR ) {
                    332:                                status = U_ZERO_ERROR;
                    333:                                continue;
                    334:                        }
                    335: 
                    336:                        /* Error in retriving data */
                    337:                        *result = 0;
                    338:                        if( tag_value ){
                    339:                                efree( tag_value );
                    340:                        }
                    341:                        if( mod_loc_name ){
                    342:                                efree( mod_loc_name);
                    343:                        }
                    344:                        return NULL;
                    345:                }
                    346:        } while( buflen > tag_value_len );
                    347: 
                    348:        if(  buflen ==0 ){
                    349:                /* No value found */
                    350:                *result = -1;
                    351:                if( tag_value ){
                    352:                        efree( tag_value );
                    353:                }
                    354:                if( mod_loc_name ){
                    355:                        efree( mod_loc_name);
                    356:                }
                    357:                return NULL;
                    358:        } else {
                    359:                *result = 1;
                    360:        }
                    361: 
                    362:        if( mod_loc_name ){
                    363:                efree( mod_loc_name);
                    364:        }
                    365:        return tag_value;
                    366: }
                    367: /* }}} */
                    368: 
                    369: /* {{{
                    370: * Gets the value from ICU , called when PHP userspace function is called
                    371: * common code shared by get_primary_language,get_script or get_region or get_variant
                    372: */
                    373: static void get_icu_value_src_php( char* tag_name, INTERNAL_FUNCTION_PARAMETERS) 
                    374: {
                    375: 
                    376:        char*       loc_name            = NULL;
                    377:        int         loc_name_len        = 0;
                    378: 
                    379:        char*       tag_value           = NULL;
                    380:        char*       empty_result        = "";
                    381: 
                    382:        int         result              = 0;
                    383:        char*       msg                 = NULL;
                    384: 
                    385:        UErrorCode  status              = U_ZERO_ERROR;
                    386: 
                    387:        intl_error_reset( NULL TSRMLS_CC );
                    388: 
                    389:        if(zend_parse_parameters( ZEND_NUM_ARGS() TSRMLS_CC, "s",
                    390:        &loc_name ,&loc_name_len ) == FAILURE) {
                    391:                spprintf(&msg , 0, "locale_get_%s : unable to parse input params", tag_name );
                    392:                intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR,  msg , 1 TSRMLS_CC );
                    393:                efree(msg);
                    394: 
                    395:                RETURN_FALSE;
                    396:     }
                    397: 
                    398:        if(loc_name_len == 0) {
                    399:                loc_name = INTL_G(default_locale);
                    400:        }
                    401: 
                    402:        /* Call ICU get */
                    403:        tag_value = get_icu_value_internal( loc_name , tag_name , &result ,0);
                    404: 
                    405:        /* No value found */
                    406:        if( result == -1 ) {
                    407:                if( tag_value){
                    408:                        efree( tag_value);
                    409:                }
                    410:                RETURN_STRING( empty_result , TRUE);
                    411:        }
                    412: 
                    413:        /* value found */
                    414:        if( tag_value){
                    415:                RETURN_STRING( tag_value , FALSE);
                    416:        }
                    417: 
                    418:        /* Error encountered while fetching the value */
                    419:        if( result ==0) {
                    420:                spprintf(&msg , 0, "locale_get_%s : unable to get locale %s", tag_name , tag_name );
                    421:                intl_error_set( NULL, status, msg , 1 TSRMLS_CC );
                    422:                efree(msg);
                    423:                RETURN_NULL();
                    424:        }
                    425: 
                    426: }
                    427: /* }}} */
                    428: 
                    429: /* {{{ proto static string Locale::getScript($locale) 
                    430:  * gets the script for the $locale 
                    431:  }}} */
                    432: /* {{{ proto static string locale_get_script($locale) 
                    433:  * gets the script for the $locale 
                    434:  */
                    435: PHP_FUNCTION( locale_get_script ) 
                    436: {
                    437:        get_icu_value_src_php( LOC_SCRIPT_TAG , INTERNAL_FUNCTION_PARAM_PASSTHRU );
                    438: }
                    439: /* }}} */
                    440: 
                    441: /* {{{ proto static string Locale::getRegion($locale) 
                    442:  * gets the region for the $locale 
                    443:  }}} */
                    444: /* {{{ proto static string locale_get_region($locale) 
                    445:  * gets the region for the $locale 
                    446:  */
                    447: PHP_FUNCTION( locale_get_region ) 
                    448: {
                    449:        get_icu_value_src_php( LOC_REGION_TAG , INTERNAL_FUNCTION_PARAM_PASSTHRU );
                    450: }
                    451: /* }}} */
                    452: 
                    453: /* {{{ proto static string Locale::getPrimaryLanguage($locale) 
                    454:  * gets the primary language for the $locale 
                    455:  }}} */
                    456: /* {{{ proto static string locale_get_primary_language($locale) 
                    457:  * gets the primary language for the $locale 
                    458:  */
                    459: PHP_FUNCTION(locale_get_primary_language ) 
                    460: {
                    461:        get_icu_value_src_php( LOC_LANG_TAG , INTERNAL_FUNCTION_PARAM_PASSTHRU );
                    462: }
                    463: /* }}} */
                    464: 
                    465: 
                    466: /* {{{
                    467:  * common code shared by display_xyz functions to  get the value from ICU 
                    468:  }}} */
                    469: static void get_icu_disp_value_src_php( char* tag_name, INTERNAL_FUNCTION_PARAMETERS) 
                    470: {
                    471:        char*       loc_name            = NULL;
                    472:        int         loc_name_len        = 0;
                    473: 
                    474:        char*       disp_loc_name       = NULL;
                    475:        int         disp_loc_name_len   = 0;
                    476:        int         free_loc_name       = 0;
                    477: 
                    478:        UChar*      disp_name           = NULL;
                    479:        int32_t     disp_name_len       = 0;
                    480: 
                    481:        char*       mod_loc_name        = NULL;
                    482: 
                    483:        int32_t     buflen              = 512;
                    484:        UErrorCode  status              = U_ZERO_ERROR;
                    485: 
                    486:        char*       utf8value           = NULL;
                    487:        int         utf8value_len       = 0;
                    488: 
                    489:        char*       msg                 = NULL;
                    490:        int         grOffset            = 0;
                    491: 
                    492:        intl_error_reset( NULL TSRMLS_CC );
                    493: 
                    494:        if(zend_parse_parameters( ZEND_NUM_ARGS() TSRMLS_CC, "s|s",
                    495:                &loc_name, &loc_name_len , 
                    496:                &disp_loc_name ,&disp_loc_name_len ) == FAILURE)
                    497:        {
                    498:                spprintf(&msg , 0, "locale_get_display_%s : unable to parse input params", tag_name );
                    499:                intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR,  msg , 1 TSRMLS_CC );
                    500:                efree(msg);
                    501:                RETURN_FALSE;
                    502:        }
                    503: 
                    504:        if(loc_name_len == 0) {
                    505:        loc_name = INTL_G(default_locale);
                    506:        }
                    507: 
                    508:        if( strcmp(tag_name, DISP_NAME) != 0 ){
                    509:                /* Handle grandfathered languages */
                    510:                grOffset = findOffset( LOC_GRANDFATHERED , loc_name );
                    511:                if( grOffset >= 0 ){
                    512:                        if( strcmp(tag_name , LOC_LANG_TAG)==0 ){
                    513:                                mod_loc_name = getPreferredTag( loc_name );
                    514:                        } else {
                    515:                                /* Since Grandfathered, no value, do nothing, retutn NULL */
                    516:                                RETURN_FALSE;
                    517:                        }
                    518:                }
                    519:        } /* end of if != LOC_CANONICAL_TAG */
                    520: 
                    521:        if( mod_loc_name==NULL ){
                    522:                mod_loc_name = estrdup( loc_name );
                    523:        }
                    524:        
                    525:        /* Check if disp_loc_name passed , if not use default locale */
                    526:        if( !disp_loc_name){
                    527:                disp_loc_name = estrdup(INTL_G(default_locale));
                    528:                free_loc_name = 1;
                    529:        }
                    530: 
                    531:     /* Get the disp_value for the given locale */
                    532:     do{
1.1.1.3   misho     533:         disp_name = erealloc( disp_name , buflen * sizeof(UChar)  );
1.1       misho     534:         disp_name_len = buflen;
                    535: 
                    536:                if( strcmp(tag_name , LOC_LANG_TAG)==0 ){
                    537:                        buflen = uloc_getDisplayLanguage ( mod_loc_name , disp_loc_name , disp_name , disp_name_len , &status);
                    538:                } else if( strcmp(tag_name , LOC_SCRIPT_TAG)==0 ){
                    539:                        buflen = uloc_getDisplayScript ( mod_loc_name , disp_loc_name , disp_name , disp_name_len , &status);
                    540:                } else if( strcmp(tag_name , LOC_REGION_TAG)==0 ){
                    541:                        buflen = uloc_getDisplayCountry ( mod_loc_name , disp_loc_name , disp_name , disp_name_len , &status);
                    542:                } else if( strcmp(tag_name , LOC_VARIANT_TAG)==0 ){
                    543:                        buflen = uloc_getDisplayVariant ( mod_loc_name , disp_loc_name , disp_name , disp_name_len , &status);
                    544:                } else if( strcmp(tag_name , DISP_NAME)==0 ){
                    545:                        buflen = uloc_getDisplayName ( mod_loc_name , disp_loc_name , disp_name , disp_name_len , &status);
                    546:                }
                    547: 
1.1.1.3   misho     548:                /* U_STRING_NOT_TERMINATED_WARNING is admissible here; don't look for it */
1.1       misho     549:                if( U_FAILURE( status ) )
                    550:                {
                    551:                        if( status == U_BUFFER_OVERFLOW_ERROR )
                    552:                        {
                    553:                                status = U_ZERO_ERROR;
                    554:                                continue;
                    555:                        }
                    556: 
                    557:                        spprintf(&msg, 0, "locale_get_display_%s : unable to get locale %s", tag_name , tag_name );
                    558:                        intl_error_set( NULL, status, msg , 1 TSRMLS_CC );
                    559:                        efree(msg);
                    560:                        if( disp_name){
                    561:                                efree( disp_name );
                    562:                        }
                    563:                        if( mod_loc_name){
                    564:                                efree( mod_loc_name );
                    565:                        }
                    566:                        if (free_loc_name) {
                    567:                                efree(disp_loc_name);
                    568:                                disp_loc_name = NULL;
                    569:                        }
                    570:                        RETURN_FALSE;
                    571:                }
                    572:        } while( buflen > disp_name_len );
                    573: 
                    574:        if( mod_loc_name){
                    575:                efree( mod_loc_name );
                    576:        }
                    577:        if (free_loc_name) {
                    578:                efree(disp_loc_name);
                    579:                disp_loc_name = NULL;
                    580:        }
                    581:        /* Convert display locale name from UTF-16 to UTF-8. */
                    582:        intl_convert_utf16_to_utf8( &utf8value, &utf8value_len, disp_name, buflen, &status );
                    583:        efree( disp_name );
                    584:        if( U_FAILURE( status ) )
                    585:        {
                    586:                spprintf(&msg, 0, "locale_get_display_%s :error converting display name for %s to UTF-8", tag_name , tag_name );
                    587:                intl_error_set( NULL, status, msg , 1 TSRMLS_CC );
                    588:                efree(msg);
                    589:                RETURN_FALSE;
                    590:        }
                    591: 
                    592:        RETVAL_STRINGL( utf8value, utf8value_len , FALSE);
                    593: 
                    594: }
                    595: /* }}} */
                    596: 
                    597: /* {{{ proto static string Locale::getDisplayName($locale[, $in_locale = null])
                    598: * gets the name for the $locale in $in_locale or default_locale
                    599:  }}} */
                    600: /* {{{ proto static string get_display_name($locale[, $in_locale = null])
                    601: * gets the name for the $locale in $in_locale or default_locale
                    602: */
                    603: PHP_FUNCTION(locale_get_display_name) 
                    604: {
                    605:     get_icu_disp_value_src_php( DISP_NAME , INTERNAL_FUNCTION_PARAM_PASSTHRU );
                    606: }
                    607: /* }}} */
                    608: 
                    609: /* {{{ proto static string Locale::getDisplayLanguage($locale[, $in_locale = null])
                    610: * gets the language for the $locale in $in_locale or default_locale
                    611:  }}} */
                    612: /* {{{ proto static string get_display_language($locale[, $in_locale = null])
                    613: * gets the language for the $locale in $in_locale or default_locale
                    614: */
                    615: PHP_FUNCTION(locale_get_display_language) 
                    616: {
                    617:     get_icu_disp_value_src_php( LOC_LANG_TAG , INTERNAL_FUNCTION_PARAM_PASSTHRU );
                    618: }
                    619: /* }}} */
                    620: 
                    621: /* {{{ proto static string Locale::getDisplayScript($locale, $in_locale = null)
                    622: * gets the script for the $locale in $in_locale or default_locale
                    623:  }}} */
                    624: /* {{{ proto static string get_display_script($locale, $in_locale = null)
                    625: * gets the script for the $locale in $in_locale or default_locale
                    626: */
                    627: PHP_FUNCTION(locale_get_display_script) 
                    628: {
                    629:     get_icu_disp_value_src_php( LOC_SCRIPT_TAG , INTERNAL_FUNCTION_PARAM_PASSTHRU );
                    630: }
                    631: /* }}} */
                    632: 
                    633: /* {{{ proto static string Locale::getDisplayRegion($locale, $in_locale = null)
                    634: * gets the region for the $locale in $in_locale or default_locale
                    635:  }}} */
                    636: /* {{{ proto static string get_display_region($locale, $in_locale = null)
                    637: * gets the region for the $locale in $in_locale or default_locale
                    638: */
                    639: PHP_FUNCTION(locale_get_display_region) 
                    640: {
                    641:     get_icu_disp_value_src_php( LOC_REGION_TAG , INTERNAL_FUNCTION_PARAM_PASSTHRU );
                    642: }
                    643: /* }}} */
                    644: 
                    645: /* {{{
                    646: * proto static string Locale::getDisplayVariant($locale, $in_locale = null)
                    647: * gets the variant for the $locale in $in_locale or default_locale
                    648:  }}} */
                    649: /* {{{
                    650: * proto static string get_display_variant($locale, $in_locale = null)
                    651: * gets the variant for the $locale in $in_locale or default_locale
                    652: */
                    653: PHP_FUNCTION(locale_get_display_variant) 
                    654: {
                    655:     get_icu_disp_value_src_php( LOC_VARIANT_TAG , INTERNAL_FUNCTION_PARAM_PASSTHRU );
                    656: }
                    657: /* }}} */
                    658: 
                    659:  /* {{{ proto static array getKeywords(string $locale) {
                    660:  * return an associative array containing keyword-value
                    661:  * pairs for this locale. The keys are keys to the array (doh!)
                    662:  * }}}*/
                    663:  /* {{{ proto static array locale_get_keywords(string $locale) {
                    664:  * return an associative array containing keyword-value
                    665:  * pairs for this locale. The keys are keys to the array (doh!)
                    666:  */ 
                    667: PHP_FUNCTION( locale_get_keywords )
                    668: {
                    669:     UEnumeration*   e        = NULL;
                    670:     UErrorCode      status   = U_ZERO_ERROR;
                    671: 
                    672:        const char*             kw_key        = NULL;
                    673:     int32_t         kw_key_len    = 0;
                    674: 
                    675:     char*              loc_name        = NULL;
                    676:     int                        loc_name_len    = 0;
                    677: 
                    678: /* 
                    679:        ICU expects the buffer to be allocated  before calling the function 
                    680:        and so the buffer size has been explicitly specified 
                    681:        ICU uloc.h #define      ULOC_KEYWORD_AND_VALUES_CAPACITY   100 
                    682:        hence the kw_value buffer size is 100
                    683: */
                    684:        char*           kw_value        = NULL;
                    685:     int32_t     kw_value_len    = 100;
                    686: 
                    687:     intl_error_reset( NULL TSRMLS_CC );
                    688: 
                    689:     if(zend_parse_parameters( ZEND_NUM_ARGS() TSRMLS_CC, "s",
                    690:         &loc_name, &loc_name_len ) == FAILURE)
                    691:     {
                    692:         intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR,
                    693:              "locale_get_keywords: unable to parse input params", 0 TSRMLS_CC );
                    694: 
                    695:         RETURN_FALSE;
                    696:     }
                    697: 
                    698:     if(loc_name_len == 0) {
                    699:         loc_name = INTL_G(default_locale);
                    700:     }
                    701: 
                    702:        /* Get the keywords */
                    703:     e = uloc_openKeywords( loc_name, &status );
                    704:     if( e != NULL )
                    705:     {
                    706:                /* Traverse it, filling the return array. */
                    707:        array_init( return_value );
                    708: 
                    709:        while( ( kw_key = uenum_next( e, &kw_key_len, &status ) ) != NULL ){
                    710:                        kw_value = ecalloc( 1 , kw_value_len  );
                    711: 
                    712:                        /* Get the keyword value for each keyword */
                    713:                        kw_value_len=uloc_getKeywordValue( loc_name,kw_key, kw_value, kw_value_len ,  &status );
                    714:                        if (status == U_BUFFER_OVERFLOW_ERROR) {
                    715:                                status = U_ZERO_ERROR;
                    716:                                kw_value = erealloc( kw_value , kw_value_len+1);
                    717:                                kw_value_len=uloc_getKeywordValue( loc_name,kw_key, kw_value, kw_value_len+1 ,  &status );
                    718:                        } else if(!U_FAILURE(status)) {
                    719:                                kw_value = erealloc( kw_value , kw_value_len+1);
                    720:                        } 
                    721:                        if (U_FAILURE(status)) {
                    722:                        intl_error_set( NULL, FAILURE, "locale_get_keywords: Error encountered while getting the keyword  value for the  keyword", 0 TSRMLS_CC );
                    723:                                if( kw_value){
                    724:                                        efree( kw_value );
                    725:                                }
                    726:                                zval_dtor(return_value);
                    727:                        RETURN_FALSE;
                    728:                        }
                    729: 
                    730:                        add_assoc_stringl( return_value, (char *)kw_key, kw_value , kw_value_len, 0);
                    731:                } /* end of while */
                    732: 
                    733:        } /* end of if e!=NULL */
                    734: 
                    735:     uenum_close( e );
                    736: }
                    737: /* }}} */
                    738: 
                    739:  /* {{{ proto static string Locale::canonicalize($locale) 
                    740:  * @return string the canonicalized locale 
                    741:  * }}} */
                    742:  /* {{{ proto static string locale_canonicalize(Locale $loc, string $locale) 
                    743:  * @param string $locale       The locale string to canonicalize
                    744:  */
                    745: PHP_FUNCTION(locale_canonicalize)
                    746: {
                    747:        get_icu_value_src_php( LOC_CANONICALIZE_TAG , INTERNAL_FUNCTION_PARAM_PASSTHRU );
                    748: }
                    749: /* }}} */
                    750: 
                    751: /* {{{ append_key_value 
                    752: * Internal function which is called from locale_compose
                    753: * gets the value for the key_name and appends to the loc_name
                    754: * returns 1 if successful , -1 if not found , 
                    755: * 0 if array element is not a string , -2 if buffer-overflow
                    756: */
                    757: static int append_key_value(smart_str* loc_name, HashTable* hash_arr, char* key_name)
                    758: {
                    759:        zval**  ele_value       = NULL;
                    760: 
                    761:        if(zend_hash_find(hash_arr , key_name , strlen(key_name) + 1 ,(void **)&ele_value ) == SUCCESS ) {
                    762:                if(Z_TYPE_PP(ele_value)!= IS_STRING ){
                    763:                        /* element value is not a string */
                    764:                        return FAILURE;
                    765:                }
                    766:                if(strcmp(key_name, LOC_LANG_TAG) != 0 && 
                    767:                   strcmp(key_name, LOC_GRANDFATHERED_LANG_TAG)!=0 ) {
                    768:                        /* not lang or grandfathered tag */
                    769:                        smart_str_appendl(loc_name, SEPARATOR , sizeof(SEPARATOR)-1);
                    770:                }
                    771:                smart_str_appendl(loc_name, Z_STRVAL_PP(ele_value) , Z_STRLEN_PP(ele_value));
                    772:                return SUCCESS;
                    773:        }
                    774: 
                    775:        return LOC_NOT_FOUND;
                    776: }
                    777: /* }}} */
                    778: 
                    779: /* {{{ append_prefix , appends the prefix needed
                    780: * e.g. private adds 'x'
                    781: */
                    782: static void add_prefix(smart_str* loc_name, char* key_name)
                    783: {
                    784:        if( strncmp(key_name , LOC_PRIVATE_TAG , 7) == 0 ){
                    785:                smart_str_appendl(loc_name, SEPARATOR , sizeof(SEPARATOR)-1);
                    786:                smart_str_appendl(loc_name, PRIVATE_PREFIX , sizeof(PRIVATE_PREFIX)-1);
                    787:        }
                    788: }
                    789: /* }}} */
                    790: 
                    791: /* {{{ append_multiple_key_values 
                    792: * Internal function which is called from locale_compose
                    793: * gets the multiple values for the key_name and appends to the loc_name
                    794: * used for 'variant','extlang','private' 
                    795: * returns 1 if successful , -1 if not found , 
                    796: * 0 if array element is not a string , -2 if buffer-overflow
                    797: */
                    798: static int append_multiple_key_values(smart_str* loc_name, HashTable* hash_arr, char* key_name TSRMLS_DC)
                    799: {
                    800:        zval**  ele_value       = NULL;
                    801:        int     i               = 0;
                    802:        int     isFirstSubtag   = 0;
                    803:        int     max_value       = 0;
                    804: 
                    805:        /* Variant/ Extlang/Private etc. */
                    806:        if( zend_hash_find( hash_arr , key_name , strlen(key_name) + 1 ,(void **)&ele_value ) == SUCCESS ) {
                    807:                if( Z_TYPE_PP(ele_value) == IS_STRING ){
                    808:                        add_prefix( loc_name , key_name);
                    809: 
                    810:                        smart_str_appendl(loc_name, SEPARATOR , sizeof(SEPARATOR)-1);
                    811:                        smart_str_appendl(loc_name, Z_STRVAL_PP(ele_value) , Z_STRLEN_PP(ele_value));
                    812:                        return SUCCESS;
                    813:                } else if(Z_TYPE_PP(ele_value) == IS_ARRAY ) {
                    814:                        HashPosition pos;
                    815:                        HashTable *arr = HASH_OF(*ele_value);
                    816:                        zval **data = NULL;
                    817: 
                    818:                        zend_hash_internal_pointer_reset_ex(arr, &pos);
                    819:                        while(zend_hash_get_current_data_ex(arr, (void **)&data, &pos) != FAILURE) {
                    820:                                if(Z_TYPE_PP(data) != IS_STRING) {
                    821:                                        return FAILURE;
                    822:                                }
                    823:                                if (isFirstSubtag++ == 0){
                    824:                                        add_prefix(loc_name , key_name);
                    825:                                }
                    826:                                smart_str_appendl(loc_name, SEPARATOR , sizeof(SEPARATOR)-1);
                    827:                                smart_str_appendl(loc_name, Z_STRVAL_PP(data) , Z_STRLEN_PP(data));
                    828:                                zend_hash_move_forward_ex(arr, &pos);
                    829:                        }
                    830:                        return SUCCESS;
                    831:                } else {
                    832:                        return FAILURE;
                    833:                }
                    834:        } else {
                    835:                char cur_key_name[31];
                    836:                /* Decide the max_value: the max. no. of elements allowed */
                    837:                if( strcmp(key_name , LOC_VARIANT_TAG) ==0 ){
                    838:                        max_value  = MAX_NO_VARIANT;
                    839:                }
                    840:                if( strcmp(key_name , LOC_EXTLANG_TAG) ==0 ){
                    841:                        max_value  = MAX_NO_EXTLANG;
                    842:                }
                    843:                if( strcmp(key_name , LOC_PRIVATE_TAG) ==0 ){
                    844:                        max_value  = MAX_NO_PRIVATE;
                    845:                }
                    846: 
                    847:                /* Multiple variant values as variant0, variant1 ,variant2 */
                    848:                isFirstSubtag = 0;
                    849:                for( i=0 ; i< max_value; i++ ){  
                    850:                        snprintf( cur_key_name , 30, "%s%d", key_name , i);     
                    851:                        if( zend_hash_find( hash_arr , cur_key_name , strlen(cur_key_name) + 1,(void **)&ele_value ) == SUCCESS ){
                    852:                                if( Z_TYPE_PP(ele_value)!= IS_STRING ){
                    853:                                        /* variant is not a string */
                    854:                                        return FAILURE;
                    855:                                }
                    856:                                /* Add the contents */
                    857:                                if (isFirstSubtag++ == 0){
                    858:                                        add_prefix(loc_name , cur_key_name);
                    859:                                }
                    860:                                smart_str_appendl(loc_name, SEPARATOR , sizeof(SEPARATOR)-1);
                    861:                                smart_str_appendl(loc_name, Z_STRVAL_PP(ele_value) , Z_STRLEN_PP(ele_value));
                    862:                        }
                    863:                } /* end of for */
                    864:        } /* end of else */
                    865: 
                    866:        return SUCCESS;
                    867: }
                    868: /* }}} */
                    869: 
                    870: /*{{{
                    871: * If applicable sets error message and aborts locale_compose gracefully
                    872: * returns 0  if locale_compose needs to be aborted 
                    873: * otherwise returns 1
                    874: */
                    875: static int handleAppendResult( int result, smart_str* loc_name TSRMLS_DC)
                    876: {
                    877:        intl_error_reset( NULL TSRMLS_CC );
                    878:        if( result == FAILURE) {
                    879:                intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR,
                    880:                         "locale_compose: parameter array element is not a string", 0 TSRMLS_CC );
                    881:                smart_str_free(loc_name);
                    882:                return 0;
                    883:        }
                    884:        return 1;
                    885: }
                    886: /* }}} */
                    887: 
                    888: #define RETURN_SMART_STR(s) smart_str_0((s)); RETURN_STRINGL((s)->c, (s)->len, 0)
                    889: /* {{{ proto static string Locale::composeLocale($array) 
                    890: * Creates a locale by combining the parts of locale-ID passed  
                    891: * }}} */
                    892: /* {{{ proto static string compose_locale($array) 
                    893: * Creates a locale by combining the parts of locale-ID passed  
                    894: * }}} */
                    895: PHP_FUNCTION(locale_compose)
                    896: {
                    897:        smart_str       loc_name_s = {0};
                    898:        smart_str *loc_name = &loc_name_s;
                    899:        zval*                   arr     = NULL;
                    900:        HashTable*              hash_arr = NULL;
                    901:        int                     result = 0;
                    902: 
                    903:        intl_error_reset( NULL TSRMLS_CC );
                    904: 
                    905:        if(zend_parse_parameters( ZEND_NUM_ARGS() TSRMLS_CC, "a",
                    906:                &arr) == FAILURE)
                    907:        {
                    908:                intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR,
                    909:                         "locale_compose: unable to parse input params", 0 TSRMLS_CC );
                    910:                RETURN_FALSE;
                    911:        }
                    912: 
                    913:        hash_arr = HASH_OF( arr );
                    914: 
                    915:        if( !hash_arr || zend_hash_num_elements( hash_arr ) == 0 )
                    916:                RETURN_FALSE;
                    917: 
                    918:        /* Check for grandfathered first */
                    919:        result = append_key_value(loc_name, hash_arr,  LOC_GRANDFATHERED_LANG_TAG);     
                    920:        if( result == SUCCESS){
                    921:                RETURN_SMART_STR(loc_name);
                    922:        }
                    923:        if( !handleAppendResult( result, loc_name TSRMLS_CC)){
                    924:                RETURN_FALSE;
                    925:        }
                    926: 
                    927:        /* Not grandfathered */
                    928:        result = append_key_value(loc_name, hash_arr , LOC_LANG_TAG);   
                    929:        if( result == LOC_NOT_FOUND ){
                    930:                intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR,
                    931:                "locale_compose: parameter array does not contain 'language' tag.", 0 TSRMLS_CC );
                    932:                smart_str_free(loc_name);
                    933:                RETURN_FALSE;
                    934:        }
                    935:        if( !handleAppendResult( result, loc_name TSRMLS_CC)){
                    936:                RETURN_FALSE;
                    937:        }
                    938: 
                    939:        /* Extlang */
                    940:        result = append_multiple_key_values(loc_name, hash_arr , LOC_EXTLANG_TAG TSRMLS_CC);
                    941:        if( !handleAppendResult( result, loc_name TSRMLS_CC)){
                    942:                RETURN_FALSE;
                    943:        }
                    944: 
                    945:        /* Script */
                    946:        result = append_key_value(loc_name, hash_arr , LOC_SCRIPT_TAG); 
                    947:        if( !handleAppendResult( result, loc_name TSRMLS_CC)){
                    948:                RETURN_FALSE;
                    949:        }
                    950:        
                    951:        /* Region */
                    952:        result = append_key_value( loc_name, hash_arr , LOC_REGION_TAG);
                    953:        if( !handleAppendResult( result, loc_name TSRMLS_CC)){
                    954:                RETURN_FALSE;
                    955:        }
                    956: 
                    957:        /* Variant */
                    958:        result = append_multiple_key_values( loc_name, hash_arr , LOC_VARIANT_TAG TSRMLS_CC); 
                    959:        if( !handleAppendResult( result, loc_name TSRMLS_CC)){
                    960:                RETURN_FALSE;
                    961:        }
                    962: 
                    963:        /* Private */
                    964:        result = append_multiple_key_values( loc_name, hash_arr , LOC_PRIVATE_TAG TSRMLS_CC);
                    965:        if( !handleAppendResult( result, loc_name TSRMLS_CC)){
                    966:                RETURN_FALSE;
                    967:        }
                    968: 
                    969:        RETURN_SMART_STR(loc_name);
                    970: }
                    971: /* }}} */
                    972: 
                    973: 
                    974: /*{{{
                    975: * Parses the locale and returns private subtags  if existing
                    976: * else returns NULL
                    977: * e.g. for locale='en_US-x-prv1-prv2-prv3'
                    978: * returns a pointer to the string 'prv1-prv2-prv3'
                    979: */
                    980: static char* get_private_subtags(char* loc_name)
                    981: {
                    982:        char*   result =NULL;
                    983:        int     singletonPos = 0;
                    984:        int     len =0; 
                    985:        char*   mod_loc_name =NULL;
                    986: 
                    987:        if( loc_name && (len = strlen(loc_name)>0 ) ){
                    988:                mod_loc_name = loc_name ; 
                    989:                len   = strlen(mod_loc_name);
                    990:                while( (singletonPos = getSingletonPos(mod_loc_name))!= -1){
                    991: 
                    992:                        if( singletonPos!=-1){ 
                    993:                                if( (*(mod_loc_name+singletonPos)=='x') || (*(mod_loc_name+singletonPos)=='X') ){               
                    994:                                        /* private subtag start found */
                    995:                                        if( singletonPos + 2 ==  len){
                    996:                                                /* loc_name ends with '-x-' ; return  NULL */
                    997:                                        }
                    998:                                        else{
                    999:                                                /* result = mod_loc_name + singletonPos +2; */
                   1000:                                                result = estrndup(mod_loc_name + singletonPos+2  , (len -( singletonPos +2) ) );
                   1001:                                        }
                   1002:                                        break;
                   1003:                                }
                   1004:                                else{
                   1005:                                        if( singletonPos + 1 >=  len){
                   1006:                                                /* String end */
                   1007:                                                break;
                   1008:                                        } else {
                   1009:                                                /* singleton found but not a private subtag , hence check further in the string for the private subtag */
                   1010:                                                mod_loc_name = mod_loc_name + singletonPos +1;
                   1011:                                                len = strlen(mod_loc_name);
                   1012:                                        }
                   1013:                                }
                   1014:                        }
                   1015: 
                   1016:                } /* end of while */
                   1017:        }
                   1018:        
                   1019:        return result;
                   1020: }
                   1021: /* }}} */
                   1022: 
                   1023: /* {{{ code used by locale_parse
                   1024: */
                   1025: static int add_array_entry(char* loc_name, zval* hash_arr, char* key_name TSRMLS_DC)
                   1026: {
                   1027:        char*   key_value       = NULL;
                   1028:        char*   cur_key_name    = NULL;
                   1029:        char*   token           = NULL;
                   1030:        char*   last_ptr        = NULL;
                   1031: 
                   1032:        int     result          = 0;
                   1033:        int     cur_result      = 0;
                   1034:        int     cnt             = 0;
                   1035: 
                   1036: 
                   1037:        if( strcmp(key_name , LOC_PRIVATE_TAG)==0 ){
                   1038:                key_value = get_private_subtags( loc_name );
                   1039:                result = 1;
                   1040:        } else {
                   1041:                key_value = get_icu_value_internal( loc_name , key_name , &result,1 );
                   1042:        }
                   1043:        if( (strcmp(key_name , LOC_PRIVATE_TAG)==0) || 
                   1044:                ( strcmp(key_name , LOC_VARIANT_TAG)==0) ){
                   1045:                if( result > 0 && key_value){
                   1046:                        /* Tokenize on the "_" or "-"  */
                   1047:                        token = php_strtok_r( key_value , DELIMITER ,&last_ptr);        
                   1048:                        if( cur_key_name ){
                   1049:                                efree( cur_key_name);
                   1050:                        }
                   1051:                        cur_key_name = (char*)ecalloc( 25,  25);
                   1052:                        sprintf( cur_key_name , "%s%d", key_name , cnt++);      
                   1053:                        add_assoc_string( hash_arr, cur_key_name , token ,TRUE );
                   1054:                        /* tokenize on the "_" or "-" and stop  at singleton if any */
                   1055:                        while( (token = php_strtok_r(NULL , DELIMITER , &last_ptr)) && (strlen(token)>1) ){
                   1056:                                sprintf( cur_key_name , "%s%d", key_name , cnt++);      
                   1057:                                add_assoc_string( hash_arr, cur_key_name , token , TRUE );
                   1058:                        }
                   1059: /*
                   1060:                        if( strcmp(key_name, LOC_PRIVATE_TAG) == 0 ){
                   1061:                        }
                   1062: */
                   1063:                }
                   1064:        } else {
                   1065:                if( result == 1 ){
                   1066:                        add_assoc_string( hash_arr, key_name , key_value , TRUE );
                   1067:                        cur_result = 1;
                   1068:                }
                   1069:        }
                   1070: 
                   1071:        if( cur_key_name ){
                   1072:                efree( cur_key_name);
                   1073:        }
                   1074:        /*if( key_name != LOC_PRIVATE_TAG && key_value){*/
                   1075:        if( key_value){
                   1076:                efree(key_value);       
                   1077:        }
                   1078:        return cur_result;
                   1079: }
                   1080: /* }}} */
                   1081: 
                   1082: /* {{{ proto static array Locale::parseLocale($locale) 
                   1083: * parses a locale-id into an array the different parts of it
                   1084:  }}} */
                   1085: /* {{{ proto static array parse_locale($locale) 
                   1086: * parses a locale-id into an array the different parts of it
                   1087: */
                   1088: PHP_FUNCTION(locale_parse)
                   1089: {
                   1090:     char*       loc_name        = NULL;
                   1091:     int         loc_name_len    = 0;
                   1092:     int         grOffset       = 0;
                   1093: 
                   1094:     intl_error_reset( NULL TSRMLS_CC );
                   1095: 
                   1096:     if(zend_parse_parameters( ZEND_NUM_ARGS() TSRMLS_CC, "s",
                   1097:         &loc_name, &loc_name_len ) == FAILURE)
                   1098:     {
                   1099:         intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR,
                   1100:              "locale_parse: unable to parse input params", 0 TSRMLS_CC );
                   1101: 
                   1102:         RETURN_FALSE;
                   1103:     }
                   1104: 
                   1105:     if(loc_name_len == 0) {
                   1106:         loc_name = INTL_G(default_locale);
                   1107:     }
                   1108: 
                   1109:        array_init( return_value );
                   1110: 
                   1111:        grOffset =  findOffset( LOC_GRANDFATHERED , loc_name );
                   1112:        if( grOffset >= 0 ){
                   1113:                add_assoc_string( return_value , LOC_GRANDFATHERED_LANG_TAG , estrdup(loc_name) ,FALSE );
                   1114:        }
                   1115:        else{
                   1116:                /* Not grandfathered */
                   1117:                add_array_entry( loc_name , return_value , LOC_LANG_TAG TSRMLS_CC);
                   1118:                add_array_entry( loc_name , return_value , LOC_SCRIPT_TAG TSRMLS_CC);
                   1119:                add_array_entry( loc_name , return_value , LOC_REGION_TAG TSRMLS_CC);
                   1120:                add_array_entry( loc_name , return_value , LOC_VARIANT_TAG TSRMLS_CC);
                   1121:                add_array_entry( loc_name , return_value , LOC_PRIVATE_TAG TSRMLS_CC);
                   1122:        }
                   1123: }
                   1124: /* }}} */
                   1125: 
                   1126: /* {{{ proto static array Locale::getAllVariants($locale)
                   1127: * gets an array containing the list of variants, or null
                   1128:  }}} */
                   1129: /* {{{ proto static array locale_get_all_variants($locale)
                   1130: * gets an array containing the list of variants, or null
                   1131: */
                   1132: PHP_FUNCTION(locale_get_all_variants)
                   1133: {
                   1134:        char*   loc_name        = NULL;
                   1135:        int     loc_name_len    = 0;
                   1136: 
                   1137:        int     result          = 0;
                   1138:        char*   token           = NULL;
                   1139:        char*   variant         = NULL;
                   1140:        char*   saved_ptr       = NULL;
                   1141: 
                   1142:        intl_error_reset( NULL TSRMLS_CC );
                   1143:        
                   1144:        if(zend_parse_parameters( ZEND_NUM_ARGS() TSRMLS_CC, "s",
                   1145:        &loc_name, &loc_name_len ) == FAILURE)
                   1146:        {
                   1147:                intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR,
                   1148:             "locale_parse: unable to parse input params", 0 TSRMLS_CC );
                   1149: 
                   1150:                RETURN_FALSE;
                   1151:        }
                   1152: 
                   1153:        if(loc_name_len == 0) {
                   1154:                loc_name = INTL_G(default_locale);
                   1155:        }
                   1156: 
                   1157: 
                   1158:        array_init( return_value );
                   1159: 
                   1160:        /* If the locale is grandfathered, stop, no variants */
                   1161:        if( findOffset( LOC_GRANDFATHERED , loc_name ) >=  0 ){ 
                   1162:                /* ("Grandfathered Tag. No variants."); */
                   1163:        }
                   1164:        else {  
                   1165:        /* Call ICU variant */
                   1166:                variant = get_icu_value_internal( loc_name , LOC_VARIANT_TAG , &result ,0);
                   1167:                if( result > 0 && variant){
                   1168:                        /* Tokenize on the "_" or "-" */
                   1169:                        token = php_strtok_r( variant , DELIMITER , &saved_ptr);        
                   1170:                        add_next_index_stringl( return_value, token , strlen(token) ,TRUE );
                   1171:                        /* tokenize on the "_" or "-" and stop  at singleton if any     */
                   1172:                        while( (token = php_strtok_r(NULL , DELIMITER, &saved_ptr)) && (strlen(token)>1) ){
                   1173:                                add_next_index_stringl( return_value, token , strlen(token) ,TRUE );
                   1174:                        }
                   1175:                }
                   1176:                if( variant ){
                   1177:                        efree( variant );
                   1178:                }
                   1179:        }
                   1180:                        
                   1181: 
                   1182: }
                   1183: /* }}} */
                   1184: 
                   1185: /*{{{
                   1186: * Converts to lower case and also replaces all hyphens with the underscore
                   1187: */
                   1188: static int strToMatch(char* str ,char *retstr)
                   1189: {
                   1190:        char*   anchor  = NULL;
                   1191:        char*   anchor1 = NULL;
                   1192:        int     result  = 0;
                   1193:        int     len     = 0;
                   1194: 
                   1195:     if( (!str) || str[0] == '\0'){
                   1196:         return result;
                   1197:     } else {
                   1198:        anchor = retstr;
                   1199:        anchor1 = str;
                   1200:         len = strlen(str);
                   1201:         while( (*str)!='\0' ){
                   1202:                if( *str == '-' ){
                   1203:                        *retstr =  '_';
                   1204:                } else {
                   1205:                        *retstr = tolower(*str);
                   1206:                }
                   1207:             str++;
                   1208:             retstr++;
                   1209:        }
                   1210:        *retstr = '\0';
                   1211:        retstr=  anchor;
                   1212:        str=  anchor1;
                   1213:        result = 1;
                   1214:     }
                   1215: 
                   1216:     return(result);
                   1217: }
                   1218: /* }}} */
                   1219: 
                   1220: /* {{{ proto static boolean Locale::filterMatches(string $langtag, string $locale[, bool $canonicalize])
                   1221: * Checks if a $langtag filter matches with $locale according to RFC 4647's basic filtering algorithm 
                   1222: */
                   1223: /* }}} */
                   1224: /* {{{ proto boolean locale_filter_matches(string $langtag, string $locale[, bool $canonicalize])
                   1225: * Checks if a $langtag filter matches with $locale according to RFC 4647's basic filtering algorithm 
                   1226: */
                   1227: PHP_FUNCTION(locale_filter_matches)
                   1228: {
                   1229:        char*           lang_tag        = NULL;
                   1230:        int             lang_tag_len    = 0;
                   1231:        char*           loc_range       = NULL;
                   1232:        int             loc_range_len   = 0;
                   1233: 
                   1234:        int             result          = 0;
                   1235:        char*           token           = 0;
                   1236:        char*           chrcheck        = NULL;
                   1237: 
                   1238:        char*           can_lang_tag    = NULL;
                   1239:        char*           can_loc_range   = NULL;
                   1240: 
                   1241:        char*           cur_lang_tag    = NULL;
                   1242:        char*           cur_loc_range   = NULL;
                   1243: 
                   1244:        zend_bool       boolCanonical   = 0;    
                   1245:        UErrorCode      status          = U_ZERO_ERROR;
                   1246: 
                   1247:        intl_error_reset( NULL TSRMLS_CC );
                   1248:        
                   1249:        if(zend_parse_parameters( ZEND_NUM_ARGS() TSRMLS_CC, "ss|b",
                   1250:                &lang_tag, &lang_tag_len , &loc_range , &loc_range_len , 
                   1251:                &boolCanonical) == FAILURE)
                   1252:        {
                   1253:                intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR,
                   1254:                "locale_filter_matches: unable to parse input params", 0 TSRMLS_CC );
                   1255: 
                   1256:                RETURN_FALSE;
                   1257:        }
                   1258: 
                   1259:        if(loc_range_len == 0) {
                   1260:                loc_range = INTL_G(default_locale);
                   1261:        }
                   1262: 
                   1263:        if( strcmp(loc_range,"*")==0){
                   1264:                RETURN_TRUE;
                   1265:        }
                   1266: 
                   1267:        if( boolCanonical ){
                   1268:                /* canonicalize loc_range */
                   1269:                can_loc_range=get_icu_value_internal( loc_range , LOC_CANONICALIZE_TAG , &result , 0);
                   1270:                if( result ==0) {
                   1271:                        intl_error_set( NULL, status, 
                   1272:                                "locale_filter_matches : unable to canonicalize loc_range" , 0 TSRMLS_CC );
                   1273:                        RETURN_FALSE;
                   1274:                }
                   1275: 
                   1276:                /* canonicalize lang_tag */
                   1277:                can_lang_tag = get_icu_value_internal( lang_tag , LOC_CANONICALIZE_TAG , &result ,  0);
                   1278:                if( result ==0) {
                   1279:                        intl_error_set( NULL, status, 
                   1280:                                "locale_filter_matches : unable to canonicalize lang_tag" , 0 TSRMLS_CC );
                   1281:                        RETURN_FALSE;
                   1282:                }
                   1283: 
                   1284:                /* Convert to lower case for case-insensitive comparison */
                   1285:                cur_lang_tag = ecalloc( 1, strlen(can_lang_tag) + 1);
                   1286: 
                   1287:                /* Convert to lower case for case-insensitive comparison */
                   1288:                result = strToMatch( can_lang_tag , cur_lang_tag);
                   1289:                if( result == 0) {
                   1290:                        efree( cur_lang_tag );
                   1291:                        efree( can_lang_tag );
                   1292:                        RETURN_FALSE;
                   1293:                }
                   1294: 
                   1295:                cur_loc_range = ecalloc( 1, strlen(can_loc_range) + 1);
                   1296:                result = strToMatch( can_loc_range , cur_loc_range );
                   1297:                if( result == 0) {
                   1298:                        efree( cur_lang_tag );
                   1299:                        efree( can_lang_tag );
                   1300:                        efree( cur_loc_range );
                   1301:                        efree( can_loc_range );
                   1302:                        RETURN_FALSE;
                   1303:                }
                   1304: 
                   1305:                /* check if prefix */
                   1306:                token   = strstr( cur_lang_tag , cur_loc_range );
                   1307:        
                   1308:                if( token && (token==cur_lang_tag) ){
                   1309:                        /* check if the char. after match is SEPARATOR */
                   1310:                        chrcheck = token + (strlen(cur_loc_range));
                   1311:                        if( isIDSeparator(*chrcheck) || isEndOfTag(*chrcheck) ){ 
                   1312:                                if( cur_lang_tag){
                   1313:                                        efree( cur_lang_tag );
                   1314:                                }
                   1315:                                if( cur_loc_range){
                   1316:                                        efree( cur_loc_range );
                   1317:                                }
                   1318:                                if( can_lang_tag){
                   1319:                                        efree( can_lang_tag );
                   1320:                                }
                   1321:                                if( can_loc_range){
                   1322:                                        efree( can_loc_range );
                   1323:                                }
                   1324:                                RETURN_TRUE;
                   1325:                        }
                   1326:                }
                   1327: 
                   1328:                /* No prefix as loc_range */
                   1329:                if( cur_lang_tag){
                   1330:                        efree( cur_lang_tag );
                   1331:                }
                   1332:                if( cur_loc_range){
                   1333:                        efree( cur_loc_range );
                   1334:                }
                   1335:                if( can_lang_tag){
                   1336:                        efree( can_lang_tag );
                   1337:                }
                   1338:                if( can_loc_range){
                   1339:                        efree( can_loc_range );
                   1340:                }
                   1341:                RETURN_FALSE;
                   1342: 
                   1343:        } /* end of if isCanonical */
                   1344:        else{
                   1345:                /* Convert to lower case for case-insensitive comparison */
                   1346:                cur_lang_tag = ecalloc( 1, strlen(lang_tag ) + 1);
                   1347:                
                   1348:                result = strToMatch( lang_tag , cur_lang_tag);
                   1349:                if( result == 0) {
                   1350:                        efree( cur_lang_tag );
                   1351:                        RETURN_FALSE;
                   1352:                }
                   1353:                cur_loc_range = ecalloc( 1, strlen(loc_range ) + 1);
                   1354:                result = strToMatch( loc_range , cur_loc_range );
                   1355:                if( result == 0) {
                   1356:                        efree( cur_lang_tag );
                   1357:                        efree( cur_loc_range );
                   1358:                        RETURN_FALSE;
                   1359:                }
                   1360: 
                   1361:                /* check if prefix */
                   1362:                token   = strstr( cur_lang_tag , cur_loc_range );
                   1363:                
                   1364:                if( token && (token==cur_lang_tag) ){
                   1365:                        /* check if the char. after match is SEPARATOR */
                   1366:                        chrcheck = token + (strlen(cur_loc_range));
                   1367:                        if( isIDSeparator(*chrcheck) || isEndOfTag(*chrcheck) ){ 
                   1368:                                if( cur_lang_tag){
                   1369:                                        efree( cur_lang_tag );
                   1370:                                }
                   1371:                                if( cur_loc_range){
                   1372:                                        efree( cur_loc_range );
                   1373:                                }
                   1374:                                RETURN_TRUE;
                   1375:                        }
                   1376:                }
                   1377: 
                   1378:                /* No prefix as loc_range */
                   1379:                if( cur_lang_tag){
                   1380:                        efree( cur_lang_tag );
                   1381:                }
                   1382:                if( cur_loc_range){
                   1383:                        efree( cur_loc_range );
                   1384:                }
                   1385:                RETURN_FALSE;
                   1386: 
                   1387:        }
                   1388: }
                   1389: /* }}} */
                   1390: 
                   1391: static void array_cleanup( char* arr[] , int arr_size)
                   1392: {
                   1393:        int i=0;
                   1394:        for( i=0; i< arr_size; i++ ){ 
                   1395:                if( arr[i*2] ){
                   1396:                        efree( arr[i*2]);
                   1397:                }
                   1398:        }
                   1399:        efree(arr);
                   1400: }
                   1401: 
                   1402: #define LOOKUP_CLEAN_RETURN(value)     array_cleanup(cur_arr, cur_arr_len); return (value)
                   1403: /* {{{
                   1404: * returns the lookup result to lookup_loc_range_src_php 
                   1405: * internal function
                   1406: */
                   1407: static char* lookup_loc_range(char* loc_range, HashTable* hash_arr, int canonicalize  TSRMLS_DC)
                   1408: {
                   1409:        int     i = 0;
                   1410:        int     cur_arr_len = 0;
                   1411:        int result = 0;
                   1412: 
                   1413:        char* lang_tag = NULL;
                   1414:        zval** ele_value = NULL;
                   1415:        char** cur_arr = NULL;
                   1416: 
                   1417:        char* cur_loc_range     = NULL;
                   1418:        char* can_loc_range     = NULL;
                   1419:        int     saved_pos = 0;
                   1420: 
                   1421:        char* return_value = NULL;
                   1422: 
                   1423:        cur_arr = ecalloc(zend_hash_num_elements(hash_arr)*2, sizeof(char *));
                   1424:        /* convert the array to lowercase , also replace hyphens with the underscore and store it in cur_arr */
                   1425:        for(zend_hash_internal_pointer_reset(hash_arr);
                   1426:                zend_hash_has_more_elements(hash_arr) == SUCCESS;
                   1427:                zend_hash_move_forward(hash_arr)) {
                   1428:                
                   1429:                if (zend_hash_get_current_data(hash_arr, (void**)&ele_value) == FAILURE) {
                   1430:                        /* Should never actually fail since the key is known to exist.*/
                   1431:                        continue;
                   1432:                }
                   1433:                if(Z_TYPE_PP(ele_value)!= IS_STRING) {
                   1434:                        /* element value is not a string */
                   1435:                        intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, "lookup_loc_range: locale array element is not a string", 0 TSRMLS_CC);
                   1436:                        LOOKUP_CLEAN_RETURN(NULL);
                   1437:                } 
                   1438:                cur_arr[cur_arr_len*2] = estrndup(Z_STRVAL_PP(ele_value), Z_STRLEN_PP(ele_value));
                   1439:                result = strToMatch(Z_STRVAL_PP(ele_value), cur_arr[cur_arr_len*2]);
                   1440:                if(result == 0) {
                   1441:                        intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, "lookup_loc_range: unable to canonicalize lang_tag", 0 TSRMLS_CC);
                   1442:                        LOOKUP_CLEAN_RETURN(NULL);
                   1443:                }
                   1444:                cur_arr[cur_arr_len*2+1] = Z_STRVAL_PP(ele_value);
                   1445:                cur_arr_len++ ; 
                   1446:        } /* end of for */
                   1447: 
                   1448:        /* Canonicalize array elements */
                   1449:        if(canonicalize) {
                   1450:                for(i=0; i<cur_arr_len; i++) { 
                   1451:                        lang_tag = get_icu_value_internal(cur_arr[i*2], LOC_CANONICALIZE_TAG, &result, 0);
                   1452:                        if(result != 1 || lang_tag == NULL || !lang_tag[0]) {
                   1453:                                if(lang_tag) {
                   1454:                                        efree(lang_tag);
                   1455:                                }
                   1456:                                intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, "lookup_loc_range: unable to canonicalize lang_tag" , 0 TSRMLS_CC);
                   1457:                                LOOKUP_CLEAN_RETURN(NULL);
                   1458:                        }
                   1459:                        cur_arr[i*2] = erealloc(cur_arr[i*2], strlen(lang_tag)+1);
                   1460:                        result = strToMatch(lang_tag, cur_arr[i*2]);    
                   1461:                        efree(lang_tag);
                   1462:                        if(result == 0) {
                   1463:                                intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, "lookup_loc_range: unable to canonicalize lang_tag" , 0 TSRMLS_CC);
                   1464:                                LOOKUP_CLEAN_RETURN(NULL);
                   1465:                        }
                   1466:                }
                   1467: 
                   1468:        }
                   1469: 
                   1470:        if(canonicalize) {
                   1471:                /* Canonicalize the loc_range */
                   1472:                can_loc_range = get_icu_value_internal(loc_range, LOC_CANONICALIZE_TAG, &result , 0);
                   1473:                if( result != 1 || can_loc_range == NULL || !can_loc_range[0]) {
                   1474:                        /* Error */
                   1475:                        intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, "lookup_loc_range: unable to canonicalize loc_range" , 0 TSRMLS_CC );
                   1476:                        if(can_loc_range) {
                   1477:                                efree(can_loc_range);
                   1478:                        }
                   1479:                        LOOKUP_CLEAN_RETURN(NULL);
                   1480:                } else {
                   1481:                        loc_range = can_loc_range;
                   1482:                }
                   1483:        } 
                   1484: 
                   1485:        cur_loc_range = ecalloc(1, strlen(loc_range)+1);
                   1486:        /* convert to lower and replace hyphens */
                   1487:        result = strToMatch(loc_range, cur_loc_range);  
                   1488:        if(can_loc_range) {
                   1489:                efree(can_loc_range);
                   1490:        }
                   1491:        if(result == 0) {
                   1492:                intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, "lookup_loc_range: unable to canonicalize lang_tag" , 0 TSRMLS_CC);
                   1493:                LOOKUP_CLEAN_RETURN(NULL);
                   1494:        }
                   1495: 
                   1496:        /* Lookup for the lang_tag match */
                   1497:        saved_pos = strlen(cur_loc_range);
                   1498:        while(saved_pos > 0) {
                   1499:                for(i=0; i< cur_arr_len; i++){ 
                   1500:                        if(cur_arr[i*2] != NULL && strlen(cur_arr[i*2]) == saved_pos && strncmp(cur_loc_range, cur_arr[i*2], saved_pos) == 0) { 
                   1501:                                /* Match found */
                   1502:                                return_value = estrdup(canonicalize?cur_arr[i*2]:cur_arr[i*2+1]);
                   1503:                                efree(cur_loc_range);
                   1504:                                LOOKUP_CLEAN_RETURN(return_value);
                   1505:                        }
                   1506:                }
                   1507:                saved_pos = getStrrtokenPos(cur_loc_range, saved_pos);
                   1508:        }
                   1509: 
                   1510:        /* Match not found */
                   1511:        efree(cur_loc_range);
                   1512:        LOOKUP_CLEAN_RETURN(NULL);
                   1513: }
                   1514: /* }}} */
                   1515: 
                   1516: /* {{{ proto string Locale::lookup(array $langtag, string $locale[, bool $canonicalize[, string $default = null]]) 
                   1517: * Searchs the items in $langtag for the best match to the language
                   1518: * range 
                   1519: */
                   1520: /* }}} */
                   1521: /* {{{ proto string locale_lookup(array $langtag, string $locale[, bool $canonicalize[, string $default = null]])
                   1522: * Searchs the items in $langtag for the best match to the language
                   1523: * range 
                   1524: */
                   1525: PHP_FUNCTION(locale_lookup)
                   1526: {
                   1527:        char*           fallback_loc            = NULL;
                   1528:        int             fallback_loc_len        = 0;
                   1529:        char*           loc_range               = NULL;
                   1530:        int             loc_range_len           = 0;
                   1531: 
                   1532:        zval*           arr                             = NULL;
                   1533:        HashTable*      hash_arr                = NULL;
                   1534:        zend_bool       boolCanonical   = 0;
                   1535:        char*           result                  =NULL;
                   1536: 
                   1537:        intl_error_reset( NULL TSRMLS_CC );
                   1538: 
                   1539:        if(zend_parse_parameters( ZEND_NUM_ARGS() TSRMLS_CC, "as|bs", &arr, &loc_range, &loc_range_len,
                   1540:                &boolCanonical, &fallback_loc, &fallback_loc_len) == FAILURE) {
                   1541:                intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR, "locale_lookup: unable to parse input params", 0 TSRMLS_CC );
                   1542:                RETURN_FALSE;
                   1543:        }
                   1544: 
                   1545:        if(loc_range_len == 0) {
                   1546:                loc_range = INTL_G(default_locale);
                   1547:        }
                   1548: 
                   1549:        hash_arr = HASH_OF(arr);
                   1550: 
                   1551:        if( !hash_arr || zend_hash_num_elements( hash_arr ) == 0 ) {
                   1552:                RETURN_EMPTY_STRING();
                   1553:        } 
                   1554:        
                   1555:        result = lookup_loc_range(loc_range, hash_arr, boolCanonical TSRMLS_CC);
                   1556:        if(result == NULL || result[0] == '\0') {
                   1557:                if( fallback_loc ) {
                   1558:                        result = estrndup(fallback_loc, fallback_loc_len);
                   1559:                } else {
                   1560:                        RETURN_EMPTY_STRING();
                   1561:                }
                   1562:        }
                   1563: 
                   1564:        RETVAL_STRINGL(result, strlen(result), 0);
                   1565: }
                   1566: /* }}} */
                   1567: 
                   1568: /* {{{ proto string Locale::acceptFromHttp(string $http_accept)
1.1.1.3   misho    1569: * Tries to find out best available locale based on HTTP �Accept-Language� header
1.1       misho    1570: */
                   1571: /* }}} */
                   1572: /* {{{ proto string locale_accept_from_http(string $http_accept)
1.1.1.3   misho    1573: * Tries to find out best available locale based on HTTP �Accept-Language� header
1.1       misho    1574: */
                   1575: PHP_FUNCTION(locale_accept_from_http)
                   1576: {
                   1577:        UEnumeration *available;
                   1578:        char *http_accept = NULL;
                   1579:        int http_accept_len;
                   1580:        UErrorCode status = 0;
                   1581:        int len;
                   1582:        char resultLocale[INTL_MAX_LOCALE_LEN+1];
                   1583:        UAcceptResult outResult;
                   1584: 
                   1585:        if(zend_parse_parameters( ZEND_NUM_ARGS() TSRMLS_CC, "s", &http_accept, &http_accept_len) == FAILURE)
                   1586:        {
                   1587:                intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR,
                   1588:                "locale_accept_from_http: unable to parse input parameters", 0 TSRMLS_CC );
                   1589:                RETURN_FALSE;
                   1590:        }
                   1591:        
                   1592:        available = ures_openAvailableLocales(NULL, &status);
                   1593:        INTL_CHECK_STATUS(status, "locale_accept_from_http: failed to retrieve locale list");
                   1594:        len = uloc_acceptLanguageFromHTTP(resultLocale, INTL_MAX_LOCALE_LEN, 
                   1595:                                                &outResult, http_accept, available, &status);
                   1596:        uenum_close(available);
                   1597:        INTL_CHECK_STATUS(status, "locale_accept_from_http: failed to find acceptable locale");
                   1598:        if (len < 0 || outResult == ULOC_ACCEPT_FAILED) {
                   1599:                RETURN_FALSE;
                   1600:        }
                   1601:        RETURN_STRINGL(resultLocale, len, 1);
                   1602: }
                   1603: /* }}} */
                   1604: 
                   1605: /*
                   1606:  * Local variables:
                   1607:  * tab-width: 4
                   1608:  * c-basic-offset: 4
                   1609:  * End:
                   1610:  * vim600: noet sw=4 ts=4 fdm=marker
                   1611:  * vim<600: noet sw=4 ts=4
                   1612:  *can_loc_len
                   1613: */

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>