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

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{
                    530:         disp_name = erealloc( disp_name , buflen  );
                    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: 
                    545:                if( U_FAILURE( status ) )
                    546:                {
                    547:                        if( status == U_BUFFER_OVERFLOW_ERROR )
                    548:                        {
                    549:                                status = U_ZERO_ERROR;
                    550:                                continue;
                    551:                        }
                    552: 
                    553:                        spprintf(&msg, 0, "locale_get_display_%s : unable to get locale %s", tag_name , tag_name );
                    554:                        intl_error_set( NULL, status, msg , 1 TSRMLS_CC );
                    555:                        efree(msg);
                    556:                        if( disp_name){
                    557:                                efree( disp_name );
                    558:                        }
                    559:                        if( mod_loc_name){
                    560:                                efree( mod_loc_name );
                    561:                        }
                    562:                        if (free_loc_name) {
                    563:                                efree(disp_loc_name);
                    564:                                disp_loc_name = NULL;
                    565:                        }
                    566:                        RETURN_FALSE;
                    567:                }
                    568:        } while( buflen > disp_name_len );
                    569: 
                    570:        if( mod_loc_name){
                    571:                efree( mod_loc_name );
                    572:        }
                    573:        if (free_loc_name) {
                    574:                efree(disp_loc_name);
                    575:                disp_loc_name = NULL;
                    576:        }
                    577:        /* Convert display locale name from UTF-16 to UTF-8. */
                    578:        intl_convert_utf16_to_utf8( &utf8value, &utf8value_len, disp_name, buflen, &status );
                    579:        efree( disp_name );
                    580:        if( U_FAILURE( status ) )
                    581:        {
                    582:                spprintf(&msg, 0, "locale_get_display_%s :error converting display name for %s to UTF-8", tag_name , tag_name );
                    583:                intl_error_set( NULL, status, msg , 1 TSRMLS_CC );
                    584:                efree(msg);
                    585:                RETURN_FALSE;
                    586:        }
                    587: 
                    588:        RETVAL_STRINGL( utf8value, utf8value_len , FALSE);
                    589: 
                    590: }
                    591: /* }}} */
                    592: 
                    593: /* {{{ proto static string Locale::getDisplayName($locale[, $in_locale = null])
                    594: * gets the name for the $locale in $in_locale or default_locale
                    595:  }}} */
                    596: /* {{{ proto static string get_display_name($locale[, $in_locale = null])
                    597: * gets the name for the $locale in $in_locale or default_locale
                    598: */
                    599: PHP_FUNCTION(locale_get_display_name) 
                    600: {
                    601:     get_icu_disp_value_src_php( DISP_NAME , INTERNAL_FUNCTION_PARAM_PASSTHRU );
                    602: }
                    603: /* }}} */
                    604: 
                    605: /* {{{ proto static string Locale::getDisplayLanguage($locale[, $in_locale = null])
                    606: * gets the language for the $locale in $in_locale or default_locale
                    607:  }}} */
                    608: /* {{{ proto static string get_display_language($locale[, $in_locale = null])
                    609: * gets the language for the $locale in $in_locale or default_locale
                    610: */
                    611: PHP_FUNCTION(locale_get_display_language) 
                    612: {
                    613:     get_icu_disp_value_src_php( LOC_LANG_TAG , INTERNAL_FUNCTION_PARAM_PASSTHRU );
                    614: }
                    615: /* }}} */
                    616: 
                    617: /* {{{ proto static string Locale::getDisplayScript($locale, $in_locale = null)
                    618: * gets the script for the $locale in $in_locale or default_locale
                    619:  }}} */
                    620: /* {{{ proto static string get_display_script($locale, $in_locale = null)
                    621: * gets the script for the $locale in $in_locale or default_locale
                    622: */
                    623: PHP_FUNCTION(locale_get_display_script) 
                    624: {
                    625:     get_icu_disp_value_src_php( LOC_SCRIPT_TAG , INTERNAL_FUNCTION_PARAM_PASSTHRU );
                    626: }
                    627: /* }}} */
                    628: 
                    629: /* {{{ proto static string Locale::getDisplayRegion($locale, $in_locale = null)
                    630: * gets the region for the $locale in $in_locale or default_locale
                    631:  }}} */
                    632: /* {{{ proto static string get_display_region($locale, $in_locale = null)
                    633: * gets the region for the $locale in $in_locale or default_locale
                    634: */
                    635: PHP_FUNCTION(locale_get_display_region) 
                    636: {
                    637:     get_icu_disp_value_src_php( LOC_REGION_TAG , INTERNAL_FUNCTION_PARAM_PASSTHRU );
                    638: }
                    639: /* }}} */
                    640: 
                    641: /* {{{
                    642: * proto static string Locale::getDisplayVariant($locale, $in_locale = null)
                    643: * gets the variant for the $locale in $in_locale or default_locale
                    644:  }}} */
                    645: /* {{{
                    646: * proto static string get_display_variant($locale, $in_locale = null)
                    647: * gets the variant for the $locale in $in_locale or default_locale
                    648: */
                    649: PHP_FUNCTION(locale_get_display_variant) 
                    650: {
                    651:     get_icu_disp_value_src_php( LOC_VARIANT_TAG , INTERNAL_FUNCTION_PARAM_PASSTHRU );
                    652: }
                    653: /* }}} */
                    654: 
                    655:  /* {{{ proto static array getKeywords(string $locale) {
                    656:  * return an associative array containing keyword-value
                    657:  * pairs for this locale. The keys are keys to the array (doh!)
                    658:  * }}}*/
                    659:  /* {{{ proto static array locale_get_keywords(string $locale) {
                    660:  * return an associative array containing keyword-value
                    661:  * pairs for this locale. The keys are keys to the array (doh!)
                    662:  */ 
                    663: PHP_FUNCTION( locale_get_keywords )
                    664: {
                    665:     UEnumeration*   e        = NULL;
                    666:     UErrorCode      status   = U_ZERO_ERROR;
                    667: 
                    668:        const char*             kw_key        = NULL;
                    669:     int32_t         kw_key_len    = 0;
                    670: 
                    671:     char*              loc_name        = NULL;
                    672:     int                        loc_name_len    = 0;
                    673: 
                    674: /* 
                    675:        ICU expects the buffer to be allocated  before calling the function 
                    676:        and so the buffer size has been explicitly specified 
                    677:        ICU uloc.h #define      ULOC_KEYWORD_AND_VALUES_CAPACITY   100 
                    678:        hence the kw_value buffer size is 100
                    679: */
                    680:        char*           kw_value        = NULL;
                    681:     int32_t     kw_value_len    = 100;
                    682: 
                    683:     intl_error_reset( NULL TSRMLS_CC );
                    684: 
                    685:     if(zend_parse_parameters( ZEND_NUM_ARGS() TSRMLS_CC, "s",
                    686:         &loc_name, &loc_name_len ) == FAILURE)
                    687:     {
                    688:         intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR,
                    689:              "locale_get_keywords: unable to parse input params", 0 TSRMLS_CC );
                    690: 
                    691:         RETURN_FALSE;
                    692:     }
                    693: 
                    694:     if(loc_name_len == 0) {
                    695:         loc_name = INTL_G(default_locale);
                    696:     }
                    697: 
                    698:        /* Get the keywords */
                    699:     e = uloc_openKeywords( loc_name, &status );
                    700:     if( e != NULL )
                    701:     {
                    702:                /* Traverse it, filling the return array. */
                    703:        array_init( return_value );
                    704: 
                    705:        while( ( kw_key = uenum_next( e, &kw_key_len, &status ) ) != NULL ){
                    706:                        kw_value = ecalloc( 1 , kw_value_len  );
                    707: 
                    708:                        /* Get the keyword value for each keyword */
                    709:                        kw_value_len=uloc_getKeywordValue( loc_name,kw_key, kw_value, kw_value_len ,  &status );
                    710:                        if (status == U_BUFFER_OVERFLOW_ERROR) {
                    711:                                status = U_ZERO_ERROR;
                    712:                                kw_value = erealloc( kw_value , kw_value_len+1);
                    713:                                kw_value_len=uloc_getKeywordValue( loc_name,kw_key, kw_value, kw_value_len+1 ,  &status );
                    714:                        } else if(!U_FAILURE(status)) {
                    715:                                kw_value = erealloc( kw_value , kw_value_len+1);
                    716:                        } 
                    717:                        if (U_FAILURE(status)) {
                    718:                        intl_error_set( NULL, FAILURE, "locale_get_keywords: Error encountered while getting the keyword  value for the  keyword", 0 TSRMLS_CC );
                    719:                                if( kw_value){
                    720:                                        efree( kw_value );
                    721:                                }
                    722:                                zval_dtor(return_value);
                    723:                        RETURN_FALSE;
                    724:                        }
                    725: 
                    726:                        add_assoc_stringl( return_value, (char *)kw_key, kw_value , kw_value_len, 0);
                    727:                } /* end of while */
                    728: 
                    729:        } /* end of if e!=NULL */
                    730: 
                    731:     uenum_close( e );
                    732: }
                    733: /* }}} */
                    734: 
                    735:  /* {{{ proto static string Locale::canonicalize($locale) 
                    736:  * @return string the canonicalized locale 
                    737:  * }}} */
                    738:  /* {{{ proto static string locale_canonicalize(Locale $loc, string $locale) 
                    739:  * @param string $locale       The locale string to canonicalize
                    740:  */
                    741: PHP_FUNCTION(locale_canonicalize)
                    742: {
                    743:        get_icu_value_src_php( LOC_CANONICALIZE_TAG , INTERNAL_FUNCTION_PARAM_PASSTHRU );
                    744: }
                    745: /* }}} */
                    746: 
                    747: /* {{{ append_key_value 
                    748: * Internal function which is called from locale_compose
                    749: * gets the value for the key_name and appends to the loc_name
                    750: * returns 1 if successful , -1 if not found , 
                    751: * 0 if array element is not a string , -2 if buffer-overflow
                    752: */
                    753: static int append_key_value(smart_str* loc_name, HashTable* hash_arr, char* key_name)
                    754: {
                    755:        zval**  ele_value       = NULL;
                    756: 
                    757:        if(zend_hash_find(hash_arr , key_name , strlen(key_name) + 1 ,(void **)&ele_value ) == SUCCESS ) {
                    758:                if(Z_TYPE_PP(ele_value)!= IS_STRING ){
                    759:                        /* element value is not a string */
                    760:                        return FAILURE;
                    761:                }
                    762:                if(strcmp(key_name, LOC_LANG_TAG) != 0 && 
                    763:                   strcmp(key_name, LOC_GRANDFATHERED_LANG_TAG)!=0 ) {
                    764:                        /* not lang or grandfathered tag */
                    765:                        smart_str_appendl(loc_name, SEPARATOR , sizeof(SEPARATOR)-1);
                    766:                }
                    767:                smart_str_appendl(loc_name, Z_STRVAL_PP(ele_value) , Z_STRLEN_PP(ele_value));
                    768:                return SUCCESS;
                    769:        }
                    770: 
                    771:        return LOC_NOT_FOUND;
                    772: }
                    773: /* }}} */
                    774: 
                    775: /* {{{ append_prefix , appends the prefix needed
                    776: * e.g. private adds 'x'
                    777: */
                    778: static void add_prefix(smart_str* loc_name, char* key_name)
                    779: {
                    780:        if( strncmp(key_name , LOC_PRIVATE_TAG , 7) == 0 ){
                    781:                smart_str_appendl(loc_name, SEPARATOR , sizeof(SEPARATOR)-1);
                    782:                smart_str_appendl(loc_name, PRIVATE_PREFIX , sizeof(PRIVATE_PREFIX)-1);
                    783:        }
                    784: }
                    785: /* }}} */
                    786: 
                    787: /* {{{ append_multiple_key_values 
                    788: * Internal function which is called from locale_compose
                    789: * gets the multiple values for the key_name and appends to the loc_name
                    790: * used for 'variant','extlang','private' 
                    791: * returns 1 if successful , -1 if not found , 
                    792: * 0 if array element is not a string , -2 if buffer-overflow
                    793: */
                    794: static int append_multiple_key_values(smart_str* loc_name, HashTable* hash_arr, char* key_name TSRMLS_DC)
                    795: {
                    796:        zval**  ele_value       = NULL;
                    797:        int     i               = 0;
                    798:        int     isFirstSubtag   = 0;
                    799:        int     max_value       = 0;
                    800: 
                    801:        /* Variant/ Extlang/Private etc. */
                    802:        if( zend_hash_find( hash_arr , key_name , strlen(key_name) + 1 ,(void **)&ele_value ) == SUCCESS ) {
                    803:                if( Z_TYPE_PP(ele_value) == IS_STRING ){
                    804:                        add_prefix( loc_name , key_name);
                    805: 
                    806:                        smart_str_appendl(loc_name, SEPARATOR , sizeof(SEPARATOR)-1);
                    807:                        smart_str_appendl(loc_name, Z_STRVAL_PP(ele_value) , Z_STRLEN_PP(ele_value));
                    808:                        return SUCCESS;
                    809:                } else if(Z_TYPE_PP(ele_value) == IS_ARRAY ) {
                    810:                        HashPosition pos;
                    811:                        HashTable *arr = HASH_OF(*ele_value);
                    812:                        zval **data = NULL;
                    813: 
                    814:                        zend_hash_internal_pointer_reset_ex(arr, &pos);
                    815:                        while(zend_hash_get_current_data_ex(arr, (void **)&data, &pos) != FAILURE) {
                    816:                                if(Z_TYPE_PP(data) != IS_STRING) {
                    817:                                        return FAILURE;
                    818:                                }
                    819:                                if (isFirstSubtag++ == 0){
                    820:                                        add_prefix(loc_name , key_name);
                    821:                                }
                    822:                                smart_str_appendl(loc_name, SEPARATOR , sizeof(SEPARATOR)-1);
                    823:                                smart_str_appendl(loc_name, Z_STRVAL_PP(data) , Z_STRLEN_PP(data));
                    824:                                zend_hash_move_forward_ex(arr, &pos);
                    825:                        }
                    826:                        return SUCCESS;
                    827:                } else {
                    828:                        return FAILURE;
                    829:                }
                    830:        } else {
                    831:                char cur_key_name[31];
                    832:                /* Decide the max_value: the max. no. of elements allowed */
                    833:                if( strcmp(key_name , LOC_VARIANT_TAG) ==0 ){
                    834:                        max_value  = MAX_NO_VARIANT;
                    835:                }
                    836:                if( strcmp(key_name , LOC_EXTLANG_TAG) ==0 ){
                    837:                        max_value  = MAX_NO_EXTLANG;
                    838:                }
                    839:                if( strcmp(key_name , LOC_PRIVATE_TAG) ==0 ){
                    840:                        max_value  = MAX_NO_PRIVATE;
                    841:                }
                    842: 
                    843:                /* Multiple variant values as variant0, variant1 ,variant2 */
                    844:                isFirstSubtag = 0;
                    845:                for( i=0 ; i< max_value; i++ ){  
                    846:                        snprintf( cur_key_name , 30, "%s%d", key_name , i);     
                    847:                        if( zend_hash_find( hash_arr , cur_key_name , strlen(cur_key_name) + 1,(void **)&ele_value ) == SUCCESS ){
                    848:                                if( Z_TYPE_PP(ele_value)!= IS_STRING ){
                    849:                                        /* variant is not a string */
                    850:                                        return FAILURE;
                    851:                                }
                    852:                                /* Add the contents */
                    853:                                if (isFirstSubtag++ == 0){
                    854:                                        add_prefix(loc_name , cur_key_name);
                    855:                                }
                    856:                                smart_str_appendl(loc_name, SEPARATOR , sizeof(SEPARATOR)-1);
                    857:                                smart_str_appendl(loc_name, Z_STRVAL_PP(ele_value) , Z_STRLEN_PP(ele_value));
                    858:                        }
                    859:                } /* end of for */
                    860:        } /* end of else */
                    861: 
                    862:        return SUCCESS;
                    863: }
                    864: /* }}} */
                    865: 
                    866: /*{{{
                    867: * If applicable sets error message and aborts locale_compose gracefully
                    868: * returns 0  if locale_compose needs to be aborted 
                    869: * otherwise returns 1
                    870: */
                    871: static int handleAppendResult( int result, smart_str* loc_name TSRMLS_DC)
                    872: {
                    873:        intl_error_reset( NULL TSRMLS_CC );
                    874:        if( result == FAILURE) {
                    875:                intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR,
                    876:                         "locale_compose: parameter array element is not a string", 0 TSRMLS_CC );
                    877:                smart_str_free(loc_name);
                    878:                return 0;
                    879:        }
                    880:        return 1;
                    881: }
                    882: /* }}} */
                    883: 
                    884: #define RETURN_SMART_STR(s) smart_str_0((s)); RETURN_STRINGL((s)->c, (s)->len, 0)
                    885: /* {{{ proto static string Locale::composeLocale($array) 
                    886: * Creates a locale by combining the parts of locale-ID passed  
                    887: * }}} */
                    888: /* {{{ proto static string compose_locale($array) 
                    889: * Creates a locale by combining the parts of locale-ID passed  
                    890: * }}} */
                    891: PHP_FUNCTION(locale_compose)
                    892: {
                    893:        smart_str       loc_name_s = {0};
                    894:        smart_str *loc_name = &loc_name_s;
                    895:        zval*                   arr     = NULL;
                    896:        HashTable*              hash_arr = NULL;
                    897:        int                     result = 0;
                    898: 
                    899:        intl_error_reset( NULL TSRMLS_CC );
                    900: 
                    901:        if(zend_parse_parameters( ZEND_NUM_ARGS() TSRMLS_CC, "a",
                    902:                &arr) == FAILURE)
                    903:        {
                    904:                intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR,
                    905:                         "locale_compose: unable to parse input params", 0 TSRMLS_CC );
                    906:                RETURN_FALSE;
                    907:        }
                    908: 
                    909:        hash_arr = HASH_OF( arr );
                    910: 
                    911:        if( !hash_arr || zend_hash_num_elements( hash_arr ) == 0 )
                    912:                RETURN_FALSE;
                    913: 
                    914:        /* Check for grandfathered first */
                    915:        result = append_key_value(loc_name, hash_arr,  LOC_GRANDFATHERED_LANG_TAG);     
                    916:        if( result == SUCCESS){
                    917:                RETURN_SMART_STR(loc_name);
                    918:        }
                    919:        if( !handleAppendResult( result, loc_name TSRMLS_CC)){
                    920:                RETURN_FALSE;
                    921:        }
                    922: 
                    923:        /* Not grandfathered */
                    924:        result = append_key_value(loc_name, hash_arr , LOC_LANG_TAG);   
                    925:        if( result == LOC_NOT_FOUND ){
                    926:                intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR,
                    927:                "locale_compose: parameter array does not contain 'language' tag.", 0 TSRMLS_CC );
                    928:                smart_str_free(loc_name);
                    929:                RETURN_FALSE;
                    930:        }
                    931:        if( !handleAppendResult( result, loc_name TSRMLS_CC)){
                    932:                RETURN_FALSE;
                    933:        }
                    934: 
                    935:        /* Extlang */
                    936:        result = append_multiple_key_values(loc_name, hash_arr , LOC_EXTLANG_TAG TSRMLS_CC);
                    937:        if( !handleAppendResult( result, loc_name TSRMLS_CC)){
                    938:                RETURN_FALSE;
                    939:        }
                    940: 
                    941:        /* Script */
                    942:        result = append_key_value(loc_name, hash_arr , LOC_SCRIPT_TAG); 
                    943:        if( !handleAppendResult( result, loc_name TSRMLS_CC)){
                    944:                RETURN_FALSE;
                    945:        }
                    946:        
                    947:        /* Region */
                    948:        result = append_key_value( loc_name, hash_arr , LOC_REGION_TAG);
                    949:        if( !handleAppendResult( result, loc_name TSRMLS_CC)){
                    950:                RETURN_FALSE;
                    951:        }
                    952: 
                    953:        /* Variant */
                    954:        result = append_multiple_key_values( loc_name, hash_arr , LOC_VARIANT_TAG TSRMLS_CC); 
                    955:        if( !handleAppendResult( result, loc_name TSRMLS_CC)){
                    956:                RETURN_FALSE;
                    957:        }
                    958: 
                    959:        /* Private */
                    960:        result = append_multiple_key_values( loc_name, hash_arr , LOC_PRIVATE_TAG TSRMLS_CC);
                    961:        if( !handleAppendResult( result, loc_name TSRMLS_CC)){
                    962:                RETURN_FALSE;
                    963:        }
                    964: 
                    965:        RETURN_SMART_STR(loc_name);
                    966: }
                    967: /* }}} */
                    968: 
                    969: 
                    970: /*{{{
                    971: * Parses the locale and returns private subtags  if existing
                    972: * else returns NULL
                    973: * e.g. for locale='en_US-x-prv1-prv2-prv3'
                    974: * returns a pointer to the string 'prv1-prv2-prv3'
                    975: */
                    976: static char* get_private_subtags(char* loc_name)
                    977: {
                    978:        char*   result =NULL;
                    979:        int     singletonPos = 0;
                    980:        int     len =0; 
                    981:        char*   mod_loc_name =NULL;
                    982: 
                    983:        if( loc_name && (len = strlen(loc_name)>0 ) ){
                    984:                mod_loc_name = loc_name ; 
                    985:                len   = strlen(mod_loc_name);
                    986:                while( (singletonPos = getSingletonPos(mod_loc_name))!= -1){
                    987: 
                    988:                        if( singletonPos!=-1){ 
                    989:                                if( (*(mod_loc_name+singletonPos)=='x') || (*(mod_loc_name+singletonPos)=='X') ){               
                    990:                                        /* private subtag start found */
                    991:                                        if( singletonPos + 2 ==  len){
                    992:                                                /* loc_name ends with '-x-' ; return  NULL */
                    993:                                        }
                    994:                                        else{
                    995:                                                /* result = mod_loc_name + singletonPos +2; */
                    996:                                                result = estrndup(mod_loc_name + singletonPos+2  , (len -( singletonPos +2) ) );
                    997:                                        }
                    998:                                        break;
                    999:                                }
                   1000:                                else{
                   1001:                                        if( singletonPos + 1 >=  len){
                   1002:                                                /* String end */
                   1003:                                                break;
                   1004:                                        } else {
                   1005:                                                /* singleton found but not a private subtag , hence check further in the string for the private subtag */
                   1006:                                                mod_loc_name = mod_loc_name + singletonPos +1;
                   1007:                                                len = strlen(mod_loc_name);
                   1008:                                        }
                   1009:                                }
                   1010:                        }
                   1011: 
                   1012:                } /* end of while */
                   1013:        }
                   1014:        
                   1015:        return result;
                   1016: }
                   1017: /* }}} */
                   1018: 
                   1019: /* {{{ code used by locale_parse
                   1020: */
                   1021: static int add_array_entry(char* loc_name, zval* hash_arr, char* key_name TSRMLS_DC)
                   1022: {
                   1023:        char*   key_value       = NULL;
                   1024:        char*   cur_key_name    = NULL;
                   1025:        char*   token           = NULL;
                   1026:        char*   last_ptr        = NULL;
                   1027: 
                   1028:        int     result          = 0;
                   1029:        int     cur_result      = 0;
                   1030:        int     cnt             = 0;
                   1031: 
                   1032: 
                   1033:        if( strcmp(key_name , LOC_PRIVATE_TAG)==0 ){
                   1034:                key_value = get_private_subtags( loc_name );
                   1035:                result = 1;
                   1036:        } else {
                   1037:                key_value = get_icu_value_internal( loc_name , key_name , &result,1 );
                   1038:        }
                   1039:        if( (strcmp(key_name , LOC_PRIVATE_TAG)==0) || 
                   1040:                ( strcmp(key_name , LOC_VARIANT_TAG)==0) ){
                   1041:                if( result > 0 && key_value){
                   1042:                        /* Tokenize on the "_" or "-"  */
                   1043:                        token = php_strtok_r( key_value , DELIMITER ,&last_ptr);        
                   1044:                        if( cur_key_name ){
                   1045:                                efree( cur_key_name);
                   1046:                        }
                   1047:                        cur_key_name = (char*)ecalloc( 25,  25);
                   1048:                        sprintf( cur_key_name , "%s%d", key_name , cnt++);      
                   1049:                        add_assoc_string( hash_arr, cur_key_name , token ,TRUE );
                   1050:                        /* tokenize on the "_" or "-" and stop  at singleton if any */
                   1051:                        while( (token = php_strtok_r(NULL , DELIMITER , &last_ptr)) && (strlen(token)>1) ){
                   1052:                                sprintf( cur_key_name , "%s%d", key_name , cnt++);      
                   1053:                                add_assoc_string( hash_arr, cur_key_name , token , TRUE );
                   1054:                        }
                   1055: /*
                   1056:                        if( strcmp(key_name, LOC_PRIVATE_TAG) == 0 ){
                   1057:                        }
                   1058: */
                   1059:                }
                   1060:        } else {
                   1061:                if( result == 1 ){
                   1062:                        add_assoc_string( hash_arr, key_name , key_value , TRUE );
                   1063:                        cur_result = 1;
                   1064:                }
                   1065:        }
                   1066: 
                   1067:        if( cur_key_name ){
                   1068:                efree( cur_key_name);
                   1069:        }
                   1070:        /*if( key_name != LOC_PRIVATE_TAG && key_value){*/
                   1071:        if( key_value){
                   1072:                efree(key_value);       
                   1073:        }
                   1074:        return cur_result;
                   1075: }
                   1076: /* }}} */
                   1077: 
                   1078: /* {{{ proto static array Locale::parseLocale($locale) 
                   1079: * parses a locale-id into an array the different parts of it
                   1080:  }}} */
                   1081: /* {{{ proto static array parse_locale($locale) 
                   1082: * parses a locale-id into an array the different parts of it
                   1083: */
                   1084: PHP_FUNCTION(locale_parse)
                   1085: {
                   1086:     char*       loc_name        = NULL;
                   1087:     int         loc_name_len    = 0;
                   1088:     int         grOffset       = 0;
                   1089: 
                   1090:     intl_error_reset( NULL TSRMLS_CC );
                   1091: 
                   1092:     if(zend_parse_parameters( ZEND_NUM_ARGS() TSRMLS_CC, "s",
                   1093:         &loc_name, &loc_name_len ) == FAILURE)
                   1094:     {
                   1095:         intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR,
                   1096:              "locale_parse: unable to parse input params", 0 TSRMLS_CC );
                   1097: 
                   1098:         RETURN_FALSE;
                   1099:     }
                   1100: 
                   1101:     if(loc_name_len == 0) {
                   1102:         loc_name = INTL_G(default_locale);
                   1103:     }
                   1104: 
                   1105:        array_init( return_value );
                   1106: 
                   1107:        grOffset =  findOffset( LOC_GRANDFATHERED , loc_name );
                   1108:        if( grOffset >= 0 ){
                   1109:                add_assoc_string( return_value , LOC_GRANDFATHERED_LANG_TAG , estrdup(loc_name) ,FALSE );
                   1110:        }
                   1111:        else{
                   1112:                /* Not grandfathered */
                   1113:                add_array_entry( loc_name , return_value , LOC_LANG_TAG TSRMLS_CC);
                   1114:                add_array_entry( loc_name , return_value , LOC_SCRIPT_TAG TSRMLS_CC);
                   1115:                add_array_entry( loc_name , return_value , LOC_REGION_TAG TSRMLS_CC);
                   1116:                add_array_entry( loc_name , return_value , LOC_VARIANT_TAG TSRMLS_CC);
                   1117:                add_array_entry( loc_name , return_value , LOC_PRIVATE_TAG TSRMLS_CC);
                   1118:        }
                   1119: }
                   1120: /* }}} */
                   1121: 
                   1122: /* {{{ proto static array Locale::getAllVariants($locale)
                   1123: * gets an array containing the list of variants, or null
                   1124:  }}} */
                   1125: /* {{{ proto static array locale_get_all_variants($locale)
                   1126: * gets an array containing the list of variants, or null
                   1127: */
                   1128: PHP_FUNCTION(locale_get_all_variants)
                   1129: {
                   1130:        char*   loc_name        = NULL;
                   1131:        int     loc_name_len    = 0;
                   1132: 
                   1133:        int     result          = 0;
                   1134:        char*   token           = NULL;
                   1135:        char*   variant         = NULL;
                   1136:        char*   saved_ptr       = NULL;
                   1137: 
                   1138:        intl_error_reset( NULL TSRMLS_CC );
                   1139:        
                   1140:        if(zend_parse_parameters( ZEND_NUM_ARGS() TSRMLS_CC, "s",
                   1141:        &loc_name, &loc_name_len ) == FAILURE)
                   1142:        {
                   1143:                intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR,
                   1144:             "locale_parse: unable to parse input params", 0 TSRMLS_CC );
                   1145: 
                   1146:                RETURN_FALSE;
                   1147:        }
                   1148: 
                   1149:        if(loc_name_len == 0) {
                   1150:                loc_name = INTL_G(default_locale);
                   1151:        }
                   1152: 
                   1153: 
                   1154:        array_init( return_value );
                   1155: 
                   1156:        /* If the locale is grandfathered, stop, no variants */
                   1157:        if( findOffset( LOC_GRANDFATHERED , loc_name ) >=  0 ){ 
                   1158:                /* ("Grandfathered Tag. No variants."); */
                   1159:        }
                   1160:        else {  
                   1161:        /* Call ICU variant */
                   1162:                variant = get_icu_value_internal( loc_name , LOC_VARIANT_TAG , &result ,0);
                   1163:                if( result > 0 && variant){
                   1164:                        /* Tokenize on the "_" or "-" */
                   1165:                        token = php_strtok_r( variant , DELIMITER , &saved_ptr);        
                   1166:                        add_next_index_stringl( return_value, token , strlen(token) ,TRUE );
                   1167:                        /* tokenize on the "_" or "-" and stop  at singleton if any     */
                   1168:                        while( (token = php_strtok_r(NULL , DELIMITER, &saved_ptr)) && (strlen(token)>1) ){
                   1169:                                add_next_index_stringl( return_value, token , strlen(token) ,TRUE );
                   1170:                        }
                   1171:                }
                   1172:                if( variant ){
                   1173:                        efree( variant );
                   1174:                }
                   1175:        }
                   1176:                        
                   1177: 
                   1178: }
                   1179: /* }}} */
                   1180: 
                   1181: /*{{{
                   1182: * Converts to lower case and also replaces all hyphens with the underscore
                   1183: */
                   1184: static int strToMatch(char* str ,char *retstr)
                   1185: {
                   1186:        char*   anchor  = NULL;
                   1187:        char*   anchor1 = NULL;
                   1188:        int     result  = 0;
                   1189:        int     len     = 0;
                   1190: 
                   1191:     if( (!str) || str[0] == '\0'){
                   1192:         return result;
                   1193:     } else {
                   1194:        anchor = retstr;
                   1195:        anchor1 = str;
                   1196:         len = strlen(str);
                   1197:         while( (*str)!='\0' ){
                   1198:                if( *str == '-' ){
                   1199:                        *retstr =  '_';
                   1200:                } else {
                   1201:                        *retstr = tolower(*str);
                   1202:                }
                   1203:             str++;
                   1204:             retstr++;
                   1205:        }
                   1206:        *retstr = '\0';
                   1207:        retstr=  anchor;
                   1208:        str=  anchor1;
                   1209:        result = 1;
                   1210:     }
                   1211: 
                   1212:     return(result);
                   1213: }
                   1214: /* }}} */
                   1215: 
                   1216: /* {{{ proto static boolean Locale::filterMatches(string $langtag, string $locale[, bool $canonicalize])
                   1217: * Checks if a $langtag filter matches with $locale according to RFC 4647's basic filtering algorithm 
                   1218: */
                   1219: /* }}} */
                   1220: /* {{{ proto boolean locale_filter_matches(string $langtag, string $locale[, bool $canonicalize])
                   1221: * Checks if a $langtag filter matches with $locale according to RFC 4647's basic filtering algorithm 
                   1222: */
                   1223: PHP_FUNCTION(locale_filter_matches)
                   1224: {
                   1225:        char*           lang_tag        = NULL;
                   1226:        int             lang_tag_len    = 0;
                   1227:        char*           loc_range       = NULL;
                   1228:        int             loc_range_len   = 0;
                   1229: 
                   1230:        int             result          = 0;
                   1231:        char*           token           = 0;
                   1232:        char*           chrcheck        = NULL;
                   1233: 
                   1234:        char*           can_lang_tag    = NULL;
                   1235:        char*           can_loc_range   = NULL;
                   1236: 
                   1237:        char*           cur_lang_tag    = NULL;
                   1238:        char*           cur_loc_range   = NULL;
                   1239: 
                   1240:        zend_bool       boolCanonical   = 0;    
                   1241:        UErrorCode      status          = U_ZERO_ERROR;
                   1242: 
                   1243:        intl_error_reset( NULL TSRMLS_CC );
                   1244:        
                   1245:        if(zend_parse_parameters( ZEND_NUM_ARGS() TSRMLS_CC, "ss|b",
                   1246:                &lang_tag, &lang_tag_len , &loc_range , &loc_range_len , 
                   1247:                &boolCanonical) == FAILURE)
                   1248:        {
                   1249:                intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR,
                   1250:                "locale_filter_matches: unable to parse input params", 0 TSRMLS_CC );
                   1251: 
                   1252:                RETURN_FALSE;
                   1253:        }
                   1254: 
                   1255:        if(loc_range_len == 0) {
                   1256:                loc_range = INTL_G(default_locale);
                   1257:        }
                   1258: 
                   1259:        if( strcmp(loc_range,"*")==0){
                   1260:                RETURN_TRUE;
                   1261:        }
                   1262: 
                   1263:        if( boolCanonical ){
                   1264:                /* canonicalize loc_range */
                   1265:                can_loc_range=get_icu_value_internal( loc_range , LOC_CANONICALIZE_TAG , &result , 0);
                   1266:                if( result ==0) {
                   1267:                        intl_error_set( NULL, status, 
                   1268:                                "locale_filter_matches : unable to canonicalize loc_range" , 0 TSRMLS_CC );
                   1269:                        RETURN_FALSE;
                   1270:                }
                   1271: 
                   1272:                /* canonicalize lang_tag */
                   1273:                can_lang_tag = get_icu_value_internal( lang_tag , LOC_CANONICALIZE_TAG , &result ,  0);
                   1274:                if( result ==0) {
                   1275:                        intl_error_set( NULL, status, 
                   1276:                                "locale_filter_matches : unable to canonicalize lang_tag" , 0 TSRMLS_CC );
                   1277:                        RETURN_FALSE;
                   1278:                }
                   1279: 
                   1280:                /* Convert to lower case for case-insensitive comparison */
                   1281:                cur_lang_tag = ecalloc( 1, strlen(can_lang_tag) + 1);
                   1282: 
                   1283:                /* Convert to lower case for case-insensitive comparison */
                   1284:                result = strToMatch( can_lang_tag , cur_lang_tag);
                   1285:                if( result == 0) {
                   1286:                        efree( cur_lang_tag );
                   1287:                        efree( can_lang_tag );
                   1288:                        RETURN_FALSE;
                   1289:                }
                   1290: 
                   1291:                cur_loc_range = ecalloc( 1, strlen(can_loc_range) + 1);
                   1292:                result = strToMatch( can_loc_range , cur_loc_range );
                   1293:                if( result == 0) {
                   1294:                        efree( cur_lang_tag );
                   1295:                        efree( can_lang_tag );
                   1296:                        efree( cur_loc_range );
                   1297:                        efree( can_loc_range );
                   1298:                        RETURN_FALSE;
                   1299:                }
                   1300: 
                   1301:                /* check if prefix */
                   1302:                token   = strstr( cur_lang_tag , cur_loc_range );
                   1303:        
                   1304:                if( token && (token==cur_lang_tag) ){
                   1305:                        /* check if the char. after match is SEPARATOR */
                   1306:                        chrcheck = token + (strlen(cur_loc_range));
                   1307:                        if( isIDSeparator(*chrcheck) || isEndOfTag(*chrcheck) ){ 
                   1308:                                if( cur_lang_tag){
                   1309:                                        efree( cur_lang_tag );
                   1310:                                }
                   1311:                                if( cur_loc_range){
                   1312:                                        efree( cur_loc_range );
                   1313:                                }
                   1314:                                if( can_lang_tag){
                   1315:                                        efree( can_lang_tag );
                   1316:                                }
                   1317:                                if( can_loc_range){
                   1318:                                        efree( can_loc_range );
                   1319:                                }
                   1320:                                RETURN_TRUE;
                   1321:                        }
                   1322:                }
                   1323: 
                   1324:                /* No prefix as loc_range */
                   1325:                if( cur_lang_tag){
                   1326:                        efree( cur_lang_tag );
                   1327:                }
                   1328:                if( cur_loc_range){
                   1329:                        efree( cur_loc_range );
                   1330:                }
                   1331:                if( can_lang_tag){
                   1332:                        efree( can_lang_tag );
                   1333:                }
                   1334:                if( can_loc_range){
                   1335:                        efree( can_loc_range );
                   1336:                }
                   1337:                RETURN_FALSE;
                   1338: 
                   1339:        } /* end of if isCanonical */
                   1340:        else{
                   1341:                /* Convert to lower case for case-insensitive comparison */
                   1342:                cur_lang_tag = ecalloc( 1, strlen(lang_tag ) + 1);
                   1343:                
                   1344:                result = strToMatch( lang_tag , cur_lang_tag);
                   1345:                if( result == 0) {
                   1346:                        efree( cur_lang_tag );
                   1347:                        RETURN_FALSE;
                   1348:                }
                   1349:                cur_loc_range = ecalloc( 1, strlen(loc_range ) + 1);
                   1350:                result = strToMatch( loc_range , cur_loc_range );
                   1351:                if( result == 0) {
                   1352:                        efree( cur_lang_tag );
                   1353:                        efree( cur_loc_range );
                   1354:                        RETURN_FALSE;
                   1355:                }
                   1356: 
                   1357:                /* check if prefix */
                   1358:                token   = strstr( cur_lang_tag , cur_loc_range );
                   1359:                
                   1360:                if( token && (token==cur_lang_tag) ){
                   1361:                        /* check if the char. after match is SEPARATOR */
                   1362:                        chrcheck = token + (strlen(cur_loc_range));
                   1363:                        if( isIDSeparator(*chrcheck) || isEndOfTag(*chrcheck) ){ 
                   1364:                                if( cur_lang_tag){
                   1365:                                        efree( cur_lang_tag );
                   1366:                                }
                   1367:                                if( cur_loc_range){
                   1368:                                        efree( cur_loc_range );
                   1369:                                }
                   1370:                                RETURN_TRUE;
                   1371:                        }
                   1372:                }
                   1373: 
                   1374:                /* No prefix as loc_range */
                   1375:                if( cur_lang_tag){
                   1376:                        efree( cur_lang_tag );
                   1377:                }
                   1378:                if( cur_loc_range){
                   1379:                        efree( cur_loc_range );
                   1380:                }
                   1381:                RETURN_FALSE;
                   1382: 
                   1383:        }
                   1384: }
                   1385: /* }}} */
                   1386: 
                   1387: static void array_cleanup( char* arr[] , int arr_size)
                   1388: {
                   1389:        int i=0;
                   1390:        for( i=0; i< arr_size; i++ ){ 
                   1391:                if( arr[i*2] ){
                   1392:                        efree( arr[i*2]);
                   1393:                }
                   1394:        }
                   1395:        efree(arr);
                   1396: }
                   1397: 
                   1398: #define LOOKUP_CLEAN_RETURN(value)     array_cleanup(cur_arr, cur_arr_len); return (value)
                   1399: /* {{{
                   1400: * returns the lookup result to lookup_loc_range_src_php 
                   1401: * internal function
                   1402: */
                   1403: static char* lookup_loc_range(char* loc_range, HashTable* hash_arr, int canonicalize  TSRMLS_DC)
                   1404: {
                   1405:        int     i = 0;
                   1406:        int     cur_arr_len = 0;
                   1407:        int result = 0;
                   1408: 
                   1409:        char* lang_tag = NULL;
                   1410:        zval** ele_value = NULL;
                   1411:        char** cur_arr = NULL;
                   1412: 
                   1413:        char* cur_loc_range     = NULL;
                   1414:        char* can_loc_range     = NULL;
                   1415:        int     saved_pos = 0;
                   1416: 
                   1417:        char* return_value = NULL;
                   1418: 
                   1419:        cur_arr = ecalloc(zend_hash_num_elements(hash_arr)*2, sizeof(char *));
                   1420:        /* convert the array to lowercase , also replace hyphens with the underscore and store it in cur_arr */
                   1421:        for(zend_hash_internal_pointer_reset(hash_arr);
                   1422:                zend_hash_has_more_elements(hash_arr) == SUCCESS;
                   1423:                zend_hash_move_forward(hash_arr)) {
                   1424:                
                   1425:                if (zend_hash_get_current_data(hash_arr, (void**)&ele_value) == FAILURE) {
                   1426:                        /* Should never actually fail since the key is known to exist.*/
                   1427:                        continue;
                   1428:                }
                   1429:                if(Z_TYPE_PP(ele_value)!= IS_STRING) {
                   1430:                        /* element value is not a string */
                   1431:                        intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, "lookup_loc_range: locale array element is not a string", 0 TSRMLS_CC);
                   1432:                        LOOKUP_CLEAN_RETURN(NULL);
                   1433:                } 
                   1434:                cur_arr[cur_arr_len*2] = estrndup(Z_STRVAL_PP(ele_value), Z_STRLEN_PP(ele_value));
                   1435:                result = strToMatch(Z_STRVAL_PP(ele_value), cur_arr[cur_arr_len*2]);
                   1436:                if(result == 0) {
                   1437:                        intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, "lookup_loc_range: unable to canonicalize lang_tag", 0 TSRMLS_CC);
                   1438:                        LOOKUP_CLEAN_RETURN(NULL);
                   1439:                }
                   1440:                cur_arr[cur_arr_len*2+1] = Z_STRVAL_PP(ele_value);
                   1441:                cur_arr_len++ ; 
                   1442:        } /* end of for */
                   1443: 
                   1444:        /* Canonicalize array elements */
                   1445:        if(canonicalize) {
                   1446:                for(i=0; i<cur_arr_len; i++) { 
                   1447:                        lang_tag = get_icu_value_internal(cur_arr[i*2], LOC_CANONICALIZE_TAG, &result, 0);
                   1448:                        if(result != 1 || lang_tag == NULL || !lang_tag[0]) {
                   1449:                                if(lang_tag) {
                   1450:                                        efree(lang_tag);
                   1451:                                }
                   1452:                                intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, "lookup_loc_range: unable to canonicalize lang_tag" , 0 TSRMLS_CC);
                   1453:                                LOOKUP_CLEAN_RETURN(NULL);
                   1454:                        }
                   1455:                        cur_arr[i*2] = erealloc(cur_arr[i*2], strlen(lang_tag)+1);
                   1456:                        result = strToMatch(lang_tag, cur_arr[i*2]);    
                   1457:                        efree(lang_tag);
                   1458:                        if(result == 0) {
                   1459:                                intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, "lookup_loc_range: unable to canonicalize lang_tag" , 0 TSRMLS_CC);
                   1460:                                LOOKUP_CLEAN_RETURN(NULL);
                   1461:                        }
                   1462:                }
                   1463: 
                   1464:        }
                   1465: 
                   1466:        if(canonicalize) {
                   1467:                /* Canonicalize the loc_range */
                   1468:                can_loc_range = get_icu_value_internal(loc_range, LOC_CANONICALIZE_TAG, &result , 0);
                   1469:                if( result != 1 || can_loc_range == NULL || !can_loc_range[0]) {
                   1470:                        /* Error */
                   1471:                        intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, "lookup_loc_range: unable to canonicalize loc_range" , 0 TSRMLS_CC );
                   1472:                        if(can_loc_range) {
                   1473:                                efree(can_loc_range);
                   1474:                        }
                   1475:                        LOOKUP_CLEAN_RETURN(NULL);
                   1476:                } else {
                   1477:                        loc_range = can_loc_range;
                   1478:                }
                   1479:        } 
                   1480: 
                   1481:        cur_loc_range = ecalloc(1, strlen(loc_range)+1);
                   1482:        /* convert to lower and replace hyphens */
                   1483:        result = strToMatch(loc_range, cur_loc_range);  
                   1484:        if(can_loc_range) {
                   1485:                efree(can_loc_range);
                   1486:        }
                   1487:        if(result == 0) {
                   1488:                intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, "lookup_loc_range: unable to canonicalize lang_tag" , 0 TSRMLS_CC);
                   1489:                LOOKUP_CLEAN_RETURN(NULL);
                   1490:        }
                   1491: 
                   1492:        /* Lookup for the lang_tag match */
                   1493:        saved_pos = strlen(cur_loc_range);
                   1494:        while(saved_pos > 0) {
                   1495:                for(i=0; i< cur_arr_len; i++){ 
                   1496:                        if(cur_arr[i*2] != NULL && strlen(cur_arr[i*2]) == saved_pos && strncmp(cur_loc_range, cur_arr[i*2], saved_pos) == 0) { 
                   1497:                                /* Match found */
                   1498:                                return_value = estrdup(canonicalize?cur_arr[i*2]:cur_arr[i*2+1]);
                   1499:                                efree(cur_loc_range);
                   1500:                                LOOKUP_CLEAN_RETURN(return_value);
                   1501:                        }
                   1502:                }
                   1503:                saved_pos = getStrrtokenPos(cur_loc_range, saved_pos);
                   1504:        }
                   1505: 
                   1506:        /* Match not found */
                   1507:        efree(cur_loc_range);
                   1508:        LOOKUP_CLEAN_RETURN(NULL);
                   1509: }
                   1510: /* }}} */
                   1511: 
                   1512: /* {{{ proto string Locale::lookup(array $langtag, string $locale[, bool $canonicalize[, string $default = null]]) 
                   1513: * Searchs the items in $langtag for the best match to the language
                   1514: * range 
                   1515: */
                   1516: /* }}} */
                   1517: /* {{{ proto string locale_lookup(array $langtag, string $locale[, bool $canonicalize[, string $default = null]])
                   1518: * Searchs the items in $langtag for the best match to the language
                   1519: * range 
                   1520: */
                   1521: PHP_FUNCTION(locale_lookup)
                   1522: {
                   1523:        char*           fallback_loc            = NULL;
                   1524:        int             fallback_loc_len        = 0;
                   1525:        char*           loc_range               = NULL;
                   1526:        int             loc_range_len           = 0;
                   1527: 
                   1528:        zval*           arr                             = NULL;
                   1529:        HashTable*      hash_arr                = NULL;
                   1530:        zend_bool       boolCanonical   = 0;
                   1531:        char*           result                  =NULL;
                   1532: 
                   1533:        intl_error_reset( NULL TSRMLS_CC );
                   1534: 
                   1535:        if(zend_parse_parameters( ZEND_NUM_ARGS() TSRMLS_CC, "as|bs", &arr, &loc_range, &loc_range_len,
                   1536:                &boolCanonical, &fallback_loc, &fallback_loc_len) == FAILURE) {
                   1537:                intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR, "locale_lookup: unable to parse input params", 0 TSRMLS_CC );
                   1538:                RETURN_FALSE;
                   1539:        }
                   1540: 
                   1541:        if(loc_range_len == 0) {
                   1542:                loc_range = INTL_G(default_locale);
                   1543:        }
                   1544: 
                   1545:        hash_arr = HASH_OF(arr);
                   1546: 
                   1547:        if( !hash_arr || zend_hash_num_elements( hash_arr ) == 0 ) {
                   1548:                RETURN_EMPTY_STRING();
                   1549:        } 
                   1550:        
                   1551:        result = lookup_loc_range(loc_range, hash_arr, boolCanonical TSRMLS_CC);
                   1552:        if(result == NULL || result[0] == '\0') {
                   1553:                if( fallback_loc ) {
                   1554:                        result = estrndup(fallback_loc, fallback_loc_len);
                   1555:                } else {
                   1556:                        RETURN_EMPTY_STRING();
                   1557:                }
                   1558:        }
                   1559: 
                   1560:        RETVAL_STRINGL(result, strlen(result), 0);
                   1561: }
                   1562: /* }}} */
                   1563: 
                   1564: /* {{{ proto string Locale::acceptFromHttp(string $http_accept)
                   1565: * Tries to find out best available locale based on HTTP “Accept-Language” header
                   1566: */
                   1567: /* }}} */
                   1568: /* {{{ proto string locale_accept_from_http(string $http_accept)
                   1569: * Tries to find out best available locale based on HTTP “Accept-Language” header
                   1570: */
                   1571: PHP_FUNCTION(locale_accept_from_http)
                   1572: {
                   1573:        UEnumeration *available;
                   1574:        char *http_accept = NULL;
                   1575:        int http_accept_len;
                   1576:        UErrorCode status = 0;
                   1577:        int len;
                   1578:        char resultLocale[INTL_MAX_LOCALE_LEN+1];
                   1579:        UAcceptResult outResult;
                   1580: 
                   1581:        if(zend_parse_parameters( ZEND_NUM_ARGS() TSRMLS_CC, "s", &http_accept, &http_accept_len) == FAILURE)
                   1582:        {
                   1583:                intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR,
                   1584:                "locale_accept_from_http: unable to parse input parameters", 0 TSRMLS_CC );
                   1585:                RETURN_FALSE;
                   1586:        }
                   1587:        
                   1588:        available = ures_openAvailableLocales(NULL, &status);
                   1589:        INTL_CHECK_STATUS(status, "locale_accept_from_http: failed to retrieve locale list");
                   1590:        len = uloc_acceptLanguageFromHTTP(resultLocale, INTL_MAX_LOCALE_LEN, 
                   1591:                                                &outResult, http_accept, available, &status);
                   1592:        uenum_close(available);
                   1593:        INTL_CHECK_STATUS(status, "locale_accept_from_http: failed to find acceptable locale");
                   1594:        if (len < 0 || outResult == ULOC_ACCEPT_FAILED) {
                   1595:                RETURN_FALSE;
                   1596:        }
                   1597:        RETURN_STRINGL(resultLocale, len, 1);
                   1598: }
                   1599: /* }}} */
                   1600: 
                   1601: /*
                   1602:  * Local variables:
                   1603:  * tab-width: 4
                   1604:  * c-basic-offset: 4
                   1605:  * End:
                   1606:  * vim600: noet sw=4 ts=4 fdm=marker
                   1607:  * vim<600: noet sw=4 ts=4
                   1608:  *can_loc_len
                   1609: */

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