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