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

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

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