Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(118)

Side by Side Diff: source/common/uresbund.cpp

Issue 1621843002: ICU 56 update step 1 (Closed) Base URL: https://chromium.googlesource.com/chromium/deps/icu.git@561
Patch Set: Created 4 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « source/common/uposixdefs.h ('k') | source/common/uresdata.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 ****************************************************************************** 2 ******************************************************************************
3 * Copyright (C) 1997-2014, International Business Machines Corporation and 3 * Copyright (C) 1997-2015, International Business Machines Corporation and
4 * others. All Rights Reserved. 4 * others. All Rights Reserved.
5 ****************************************************************************** 5 ******************************************************************************
6 * 6 *
7 * File URESBUND.C 7 * File uresbund.cpp
8 * 8 *
9 * Modification History: 9 * Modification History:
10 * 10 *
11 * Date Name Description 11 * Date Name Description
12 * 04/01/97 aliu Creation. 12 * 04/01/97 aliu Creation.
13 * 06/14/99 stephen Removed functions taking a filename suffix. 13 * 06/14/99 stephen Removed functions taking a filename suffix.
14 * 07/20/99 stephen Changed for UResourceBundle typedef'd to void* 14 * 07/20/99 stephen Changed for UResourceBundle typedef'd to void*
15 * 11/09/99 weiv Added ures_getLocale() 15 * 11/09/99 weiv Added ures_getLocale()
16 * March 2000 weiv Total overhaul - using data in DLLs 16 * March 2000 weiv Total overhaul - using data in DLLs
17 * 06/20/2000 helena OS/400 port changes; mostly typecast. 17 * 06/20/2000 helena OS/400 port changes; mostly typecast.
(...skipping 29 matching lines...) Expand all
47 static icu::UInitOnce gCacheInitOnce; 47 static icu::UInitOnce gCacheInitOnce;
48 48
49 static UMutex resbMutex = U_MUTEX_INITIALIZER; 49 static UMutex resbMutex = U_MUTEX_INITIALIZER;
50 50
51 /* INTERNAL: hashes an entry */ 51 /* INTERNAL: hashes an entry */
52 static int32_t U_CALLCONV hashEntry(const UHashTok parm) { 52 static int32_t U_CALLCONV hashEntry(const UHashTok parm) {
53 UResourceDataEntry *b = (UResourceDataEntry *)parm.pointer; 53 UResourceDataEntry *b = (UResourceDataEntry *)parm.pointer;
54 UHashTok namekey, pathkey; 54 UHashTok namekey, pathkey;
55 namekey.pointer = b->fName; 55 namekey.pointer = b->fName;
56 pathkey.pointer = b->fPath; 56 pathkey.pointer = b->fPath;
57 return uhash_hashChars(namekey)+37*uhash_hashChars(pathkey); 57 return uhash_hashChars(namekey)+37u*uhash_hashChars(pathkey);
58 } 58 }
59 59
60 /* INTERNAL: compares two entries */ 60 /* INTERNAL: compares two entries */
61 static UBool U_CALLCONV compareEntries(const UHashTok p1, const UHashTok p2) { 61 static UBool U_CALLCONV compareEntries(const UHashTok p1, const UHashTok p2) {
62 UResourceDataEntry *b1 = (UResourceDataEntry *)p1.pointer; 62 UResourceDataEntry *b1 = (UResourceDataEntry *)p1.pointer;
63 UResourceDataEntry *b2 = (UResourceDataEntry *)p2.pointer; 63 UResourceDataEntry *b2 = (UResourceDataEntry *)p2.pointer;
64 UHashTok name1, name2, path1, path2; 64 UHashTok name1, name2, path1, path2;
65 name1.pointer = b1->fName; 65 name1.pointer = b1->fName;
66 name2.pointer = b2->fName; 66 name2.pointer = b2->fName;
67 path1.pointer = b1->fPath; 67 path1.pointer = b1->fPath;
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after
180 */ 180 */
181 umtx_lock(&resbMutex); 181 umtx_lock(&resbMutex);
182 if (cache == NULL) { 182 if (cache == NULL) {
183 umtx_unlock(&resbMutex); 183 umtx_unlock(&resbMutex);
184 return 0; 184 return 0;
185 } 185 }
186 186
187 do { 187 do {
188 deletedMore = FALSE; 188 deletedMore = FALSE;
189 /*creates an enumeration to iterate through every element in the table * / 189 /*creates an enumeration to iterate through every element in the table * /
190 pos = -1; 190 pos = UHASH_FIRST;
191 while ((e = uhash_nextElement(cache, &pos)) != NULL) 191 while ((e = uhash_nextElement(cache, &pos)) != NULL)
192 { 192 {
193 resB = (UResourceDataEntry *) e->value.pointer; 193 resB = (UResourceDataEntry *) e->value.pointer;
194 /* Deletes only if reference counter == 0 194 /* Deletes only if reference counter == 0
195 * Don't worry about the children of this node. 195 * Don't worry about the children of this node.
196 * Those will eventually get deleted too, if not already. 196 * Those will eventually get deleted too, if not already.
197 * Don't worry about the parents of this node. 197 * Don't worry about the parents of this node.
198 * Those will eventually get deleted too, if not already. 198 * Those will eventually get deleted too, if not already.
199 */ 199 */
200 /* 04/05/2002 [weiv] fCountExisting should now be accurate. If it's not zero, that means that */ 200 /* 04/05/2002 [weiv] fCountExisting should now be accurate. If it's not zero, that means that */
(...skipping 14 matching lines...) Expand all
215 umtx_unlock(&resbMutex); 215 umtx_unlock(&resbMutex);
216 216
217 return rbDeletedNum; 217 return rbDeletedNum;
218 } 218 }
219 219
220 #ifdef URES_DEBUG 220 #ifdef URES_DEBUG
221 #include <stdio.h> 221 #include <stdio.h>
222 222
223 U_CAPI UBool U_EXPORT2 ures_dumpCacheContents(void) { 223 U_CAPI UBool U_EXPORT2 ures_dumpCacheContents(void) {
224 UBool cacheNotEmpty = FALSE; 224 UBool cacheNotEmpty = FALSE;
225 int32_t pos = -1; 225 int32_t pos = UHASH_FIRST;
226 const UHashElement *e; 226 const UHashElement *e;
227 UResourceDataEntry *resB; 227 UResourceDataEntry *resB;
228 228
229 umtx_lock(&resbMutex); 229 umtx_lock(&resbMutex);
230 if (cache == NULL) { 230 if (cache == NULL) {
231 umtx_unlock(&resbMutex); 231 umtx_unlock(&resbMutex);
232 fprintf(stderr,"%s:%d: RB Cache is NULL.\n", __FILE__, __LINE__); 232 fprintf(stderr,"%s:%d: RB Cache is NULL.\n", __FILE__, __LINE__);
233 return FALSE; 233 return FALSE;
234 } 234 }
235 235
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after
370 *status = U_USING_FALLBACK_WARNING; 370 *status = U_USING_FALLBACK_WARNING;
371 r->fBogus = U_USING_FALLBACK_WARNING; 371 r->fBogus = U_USING_FALLBACK_WARNING;
372 } else { /* if we have a regular entry */ 372 } else { /* if we have a regular entry */
373 Resource aliasres; 373 Resource aliasres;
374 if (r->fData.usesPoolBundle) { 374 if (r->fData.usesPoolBundle) {
375 r->fPool = getPoolEntry(r->fPath, status); 375 r->fPool = getPoolEntry(r->fPath, status);
376 if (U_SUCCESS(*status)) { 376 if (U_SUCCESS(*status)) {
377 const int32_t *poolIndexes = r->fPool->fData.pRoot + 1; 377 const int32_t *poolIndexes = r->fPool->fData.pRoot + 1;
378 if(r->fData.pRoot[1 + URES_INDEX_POOL_CHECKSUM] == poolIndex es[URES_INDEX_POOL_CHECKSUM]) { 378 if(r->fData.pRoot[1 + URES_INDEX_POOL_CHECKSUM] == poolIndex es[URES_INDEX_POOL_CHECKSUM]) {
379 r->fData.poolBundleKeys = (const char *)(poolIndexes + ( poolIndexes[URES_INDEX_LENGTH] & 0xff)); 379 r->fData.poolBundleKeys = (const char *)(poolIndexes + ( poolIndexes[URES_INDEX_LENGTH] & 0xff));
380 r->fData.poolBundleStrings = r->fPool->fData.p16BitUnits ;
380 } else { 381 } else {
381 r->fBogus = *status = U_INVALID_FORMAT_ERROR; 382 r->fBogus = *status = U_INVALID_FORMAT_ERROR;
382 } 383 }
383 } else { 384 } else {
384 r->fBogus = *status; 385 r->fBogus = *status;
385 } 386 }
386 } 387 }
387 if (U_SUCCESS(*status)) { 388 if (U_SUCCESS(*status)) {
388 /* handle the alias by trying to get out the %%Alias tag.*/ 389 /* handle the alias by trying to get out the %%Alias tag.*/
389 /* We'll try to get alias string from the bundle */ 390 /* We'll try to get alias string from the bundle */
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
439 if( U_SUCCESS(*status) && 440 if( U_SUCCESS(*status) &&
440 (poolBundle == NULL || poolBundle->fBogus != U_ZERO_ERROR || !poolBundle ->fData.isPoolBundle) 441 (poolBundle == NULL || poolBundle->fBogus != U_ZERO_ERROR || !poolBundle ->fData.isPoolBundle)
441 ) { 442 ) {
442 *status = U_INVALID_FORMAT_ERROR; 443 *status = U_INVALID_FORMAT_ERROR;
443 } 444 }
444 return poolBundle; 445 return poolBundle;
445 } 446 }
446 447
447 /* INTERNAL: */ 448 /* INTERNAL: */
448 /* CAUTION: resbMutex must be locked when calling this function! */ 449 /* CAUTION: resbMutex must be locked when calling this function! */
449 static UResourceDataEntry *findFirstExisting(const char* path, char* name, UBool *isRoot, UBool *hasChopped, UBool *isDefault, UErrorCode* status) { 450 static UResourceDataEntry *
451 findFirstExisting(const char* path, char* name,
452 UBool *isRoot, UBool *hasChopped, UBool *isDefault, UErrorCode * status) {
450 UResourceDataEntry *r = NULL; 453 UResourceDataEntry *r = NULL;
451 UBool hasRealData = FALSE; 454 UBool hasRealData = FALSE;
452 const char *defaultLoc = uloc_getDefault(); 455 const char *defaultLoc = uloc_getDefault();
453 *hasChopped = TRUE; /* we're starting with a fresh name */ 456 *hasChopped = TRUE; /* we're starting with a fresh name */
454 457
455 while(*hasChopped && !hasRealData) { 458 while(*hasChopped && !hasRealData) {
456 r = init_entry(name, path, status); 459 r = init_entry(name, path, status);
457 /* Null pointer test */ 460 /* Null pointer test */
458 if (U_FAILURE(*status)) { 461 if (U_FAILURE(*status)) {
459 return NULL; 462 return NULL;
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
495 static UBool ures_isStackObject(const UResourceBundle* resB) { 498 static UBool ures_isStackObject(const UResourceBundle* resB) {
496 return((resB->fMagic1 == MAGIC1 && resB->fMagic2 == MAGIC2)?FALSE:TRUE); 499 return((resB->fMagic1 == MAGIC1 && resB->fMagic2 == MAGIC2)?FALSE:TRUE);
497 } 500 }
498 501
499 502
500 U_CFUNC void ures_initStackObject(UResourceBundle* resB) { 503 U_CFUNC void ures_initStackObject(UResourceBundle* resB) {
501 uprv_memset(resB, 0, sizeof(UResourceBundle)); 504 uprv_memset(resB, 0, sizeof(UResourceBundle));
502 ures_setIsStackObject(resB, TRUE); 505 ures_setIsStackObject(resB, TRUE);
503 } 506 }
504 507
505 static UResourceDataEntry *entryOpen(const char* path, const char* localeID, UEr rorCode* status) { 508 static UBool // returns U_SUCCESS(*status)
509 loadParentsExceptRoot(UResourceDataEntry *&t1,
510 char name[], int32_t nameCapacity,
511 UBool usingUSRData, char usrDataPath[], UErrorCode *status ) {
512 if (U_FAILURE(*status)) { return FALSE; }
513 UBool hasChopped = TRUE;
514 while (hasChopped && t1->fParent == NULL && !t1->fData.noFallback &&
515 res_getResource(&t1->fData,"%%ParentIsRoot") == RES_BOGUS) {
516 Resource parentRes = res_getResource(&t1->fData, "%%Parent");
517 if (parentRes != RES_BOGUS) { // An explicit parent was found.
518 int32_t parentLocaleLen = 0;
519 const UChar *parentLocaleName = res_getString(&(t1->fData), parentRe s, &parentLocaleLen);
520 if(parentLocaleName != NULL && 0 < parentLocaleLen && parentLocaleLe n < nameCapacity) {
521 u_UCharsToChars(parentLocaleName, name, parentLocaleLen + 1);
522 if (uprv_strcmp(name, kRootLocaleName) == 0) {
523 return TRUE;
524 }
525 }
526 }
527 // Insert regular parents.
528 UErrorCode parentStatus = U_ZERO_ERROR;
529 UResourceDataEntry *t2 = init_entry(name, t1->fPath, &parentStatus);
530 if (U_FAILURE(parentStatus)) {
531 *status = parentStatus;
532 return FALSE;
533 }
534 UResourceDataEntry *u2 = NULL;
535 UErrorCode usrStatus = U_ZERO_ERROR;
536 if (usingUSRData) { // This code inserts user override data into the in heritance chain.
537 u2 = init_entry(name, usrDataPath, &usrStatus);
538 }
539
540 if (usingUSRData && U_SUCCESS(usrStatus) && u2->fBogus == U_ZERO_ERROR) {
541 t1->fParent = u2;
542 u2->fParent = t2;
543 } else {
544 t1->fParent = t2;
545 if (usingUSRData) {
546 // The USR override data wasn't found, set it to be deleted.
547 u2->fCountExisting = 0;
548 }
549 }
550 t1 = t2;
551 hasChopped = chopLocale(name);
552 }
553 return TRUE;
554 }
555
556 static UBool // returns U_SUCCESS(*status)
557 insertRootBundle(UResourceDataEntry *&t1, UErrorCode *status) {
558 if (U_FAILURE(*status)) { return FALSE; }
559 UErrorCode parentStatus = U_ZERO_ERROR;
560 UResourceDataEntry *t2 = init_entry(kRootLocaleName, t1->fPath, &parentStatu s);
561 if (U_FAILURE(parentStatus)) {
562 *status = parentStatus;
563 return FALSE;
564 }
565 t1->fParent = t2;
566 t1 = t2;
567 return TRUE;
568 }
569
570 enum UResOpenType {
571 /**
572 * Open a resource bundle for the locale;
573 * if there is not even a base language bundle, then fall back to the defaul t locale;
574 * if there is no bundle for that either, then load the root bundle.
575 *
576 * This is the default bundle loading behavior.
577 */
578 URES_OPEN_LOCALE_DEFAULT_ROOT,
579 // TODO: ICU ticket #11271 "consistent default locale across locale trees"
580 // Add an option to look at the main locale tree for whether to
581 // fall back to root directly (if the locale has main data) or
582 // fall back to the default locale first (if the locale does not even have m ain data).
583 /**
584 * Open a resource bundle for the locale;
585 * if there is not even a base language bundle, then load the root bundle;
586 * never fall back to the default locale.
587 *
588 * This is used for algorithms that have good pan-Unicode default behavior,
589 * such as case mappings, collation, and segmentation (BreakIterator).
590 */
591 URES_OPEN_LOCALE_ROOT,
592 /**
593 * Open a resource bundle for the exact bundle name as requested;
594 * no fallbacks, do not load parent bundles.
595 *
596 * This is used for supplemental (non-locale) data.
597 */
598 URES_OPEN_DIRECT
599 };
600 typedef enum UResOpenType UResOpenType;
601
602 static UResourceDataEntry *entryOpen(const char* path, const char* localeID,
603 UResOpenType openType, UErrorCode* status) {
604 U_ASSERT(openType != URES_OPEN_DIRECT);
506 UErrorCode intStatus = U_ZERO_ERROR; 605 UErrorCode intStatus = U_ZERO_ERROR;
507 UErrorCode parentStatus = U_ZERO_ERROR;
508 UErrorCode usrStatus = U_ZERO_ERROR;
509 UResourceDataEntry *r = NULL; 606 UResourceDataEntry *r = NULL;
510 UResourceDataEntry *t1 = NULL; 607 UResourceDataEntry *t1 = NULL;
511 UResourceDataEntry *t2 = NULL;
512 UResourceDataEntry *u1 = NULL;
513 UResourceDataEntry *u2 = NULL;
514 UBool isDefault = FALSE; 608 UBool isDefault = FALSE;
515 UBool isRoot = FALSE; 609 UBool isRoot = FALSE;
516 UBool hasRealData = FALSE; 610 UBool hasRealData = FALSE;
517 UBool hasChopped = TRUE; 611 UBool hasChopped = TRUE;
518 UBool usingUSRData = U_USE_USRDATA && ( path == NULL || uprv_strncmp(path,U_ ICUDATA_NAME,8) == 0); 612 UBool usingUSRData = U_USE_USRDATA && ( path == NULL || uprv_strncmp(path,U_ ICUDATA_NAME,8) == 0);
519 613
520 char name[ULOC_FULLNAME_CAPACITY]; 614 char name[ULOC_FULLNAME_CAPACITY];
521 char usrDataPath[96]; 615 char usrDataPath[96];
522 616
523 initCache(status); 617 initCache(status);
(...skipping 19 matching lines...) Expand all
543 637
544 umtx_lock(&resbMutex); 638 umtx_lock(&resbMutex);
545 { /* umtx_lock */ 639 { /* umtx_lock */
546 /* We're going to skip all the locales that do not have any data */ 640 /* We're going to skip all the locales that do not have any data */
547 r = findFirstExisting(path, name, &isRoot, &hasChopped, &isDefault, &int Status); 641 r = findFirstExisting(path, name, &isRoot, &hasChopped, &isDefault, &int Status);
548 642
549 if(r != NULL) { /* if there is one real locale, we can look for parents. */ 643 if(r != NULL) { /* if there is one real locale, we can look for parents. */
550 t1 = r; 644 t1 = r;
551 hasRealData = TRUE; 645 hasRealData = TRUE;
552 if ( usingUSRData ) { /* This code inserts user override data into the inheritance chain */ 646 if ( usingUSRData ) { /* This code inserts user override data into the inheritance chain */
553 u1 = init_entry(t1->fName, usrDataPath, &usrStatus); 647 UErrorCode usrStatus = U_ZERO_ERROR;
648 UResourceDataEntry *u1 = init_entry(t1->fName, usrDataPath, &usr Status);
554 if ( u1 != NULL ) { 649 if ( u1 != NULL ) {
555 if(u1->fBogus == U_ZERO_ERROR) { 650 if(u1->fBogus == U_ZERO_ERROR) {
556 u1->fParent = t1; 651 u1->fParent = t1;
557 r = u1; 652 r = u1;
558 } else { 653 } else {
559 /* the USR override data wasn't found, set it to be deleted * / 654 /* the USR override data wasn't found, set it to be deleted * /
560 u1->fCountExisting = 0; 655 u1->fCountExisting = 0;
561 } 656 }
562 } 657 }
563 } 658 }
564 while (hasChopped && !isRoot && t1->fParent == NULL && !t1->fData.no Fallback) { 659 if (hasChopped && !isRoot) {
565 if ( res_getResource(&t1->fData,"%%Parent") != RES_BOGUS) { /* A n explicit parent was found */ 660 if (!loadParentsExceptRoot(t1, name, UPRV_LENGTHOF(name), usingU SRData, usrDataPath, status)) {
566 int32_t parentLocaleLen = 0;
567 const UChar *parentLocaleName = res_getString(&(t1->fData), res_getResource(&t1->fData,"%%Parent") , &parentLocaleLen);
568 if(parentLocaleName != NULL && parentLocaleLen > 0) {
569 u_UCharsToChars(parentLocaleName, name, parentLocaleLen+ 1);
570 if ( !uprv_strcmp(name,"root") ) { /* If parent is root, we just terminate the loop */
571 hasChopped = FALSE;
572 continue;
573 }
574 }
575 }
576 /* insert regular parents */
577 t2 = init_entry(name, t1->fPath, &parentStatus);
578 if ( usingUSRData ) { /* This code inserts user override data i nto the inheritance chain */
579 usrStatus = U_ZERO_ERROR;
580 u2 = init_entry(name, usrDataPath, &usrStatus);
581 }
582 /* Check for null pointer. */
583 if (t2 == NULL || ( usingUSRData && u2 == NULL)) {
584 *status = U_MEMORY_ALLOCATION_ERROR;
585 goto finishUnlock; 661 goto finishUnlock;
586 } 662 }
587
588 if ( usingUSRData && u2->fBogus == U_ZERO_ERROR ) {
589 t1->fParent = u2;
590 u2->fParent = t2;
591 } else {
592 t1->fParent = t2;
593 if(usingUSRData) {
594 /* the USR override data wasn't found, set it to be dele ted */
595 u2->fCountExisting = 0;
596 }
597 }
598 t1 = t2;
599 hasChopped = chopLocale(name);
600 } 663 }
601 } 664 }
602 665
603 /* we could have reached this point without having any real data */ 666 /* we could have reached this point without having any real data */
604 /* if that is the case, we need to chain in the default locale */ 667 /* if that is the case, we need to chain in the default locale */
605 if(r==NULL && !isDefault && !isRoot /*&& t1->fParent == NULL*/) { 668 if(r==NULL && openType == URES_OPEN_LOCALE_DEFAULT_ROOT && !isDefault && !isRoot) {
606 /* insert default locale */ 669 /* insert default locale */
607 uprv_strcpy(name, uloc_getDefault()); 670 uprv_strcpy(name, uloc_getDefault());
608 r = findFirstExisting(path, name, &isRoot, &hasChopped, &isDefault, &intStatus); 671 r = findFirstExisting(path, name, &isRoot, &hasChopped, &isDefault, &intStatus);
609 intStatus = U_USING_DEFAULT_WARNING; 672 intStatus = U_USING_DEFAULT_WARNING;
610 if(r != NULL) { /* the default locale exists */ 673 if(r != NULL) { /* the default locale exists */
611 t1 = r; 674 t1 = r;
612 hasRealData = TRUE; 675 hasRealData = TRUE;
613 isDefault = TRUE; 676 isDefault = TRUE;
614 while (hasChopped && t1->fParent == NULL) { 677 // TODO: Why not if (usingUSRData) { ... } like in the non-defau lt-locale code path?
615 if ( res_getResource(&t1->fData,"%%Parent") != RES_BOGUS) { /* An explicit parent was found */ 678 if (hasChopped && !isRoot) {
616 int32_t parentLocaleLen = 0; 679 if (!loadParentsExceptRoot(t1, name, UPRV_LENGTHOF(name), us ingUSRData, usrDataPath, status)) {
617 const UChar *parentLocaleName = res_getString(&(t1->fDat a), res_getResource(&t1->fData,"%%Parent") , &parentLocaleLen);
618 if(parentLocaleName != NULL && parentLocaleLen > 0) {
619 u_UCharsToChars(parentLocaleName, name, parentLocale Len+1);
620 if ( !uprv_strcmp(name,"root") ) { /* If parent is r oot, we just terminate the loop */
621 hasChopped = FALSE;
622 continue;
623 }
624 }
625 }
626 /* insert chopped defaults */
627 t2 = init_entry(name, t1->fPath, &parentStatus);
628 /* Check for null pointer. */
629 if (t2 == NULL) {
630 *status = U_MEMORY_ALLOCATION_ERROR;
631 goto finishUnlock; 680 goto finishUnlock;
632 } 681 }
633
634 if ( res_getResource(&t1->fData,"%%ParentIsRoot") == RES_BOG US) {
635 t1->fParent = t2;
636 t1 = t2;
637 }
638 hasChopped = chopLocale(name);
639 } 682 }
640 } 683 }
641 } 684 }
642 685
643 /* we could still have r == NULL at this point - maybe even default loca le is not */ 686 /* we could still have r == NULL at this point - maybe even default loca le is not */
644 /* present */ 687 /* present */
645 if(r == NULL) { 688 if(r == NULL) {
646 uprv_strcpy(name, kRootLocaleName); 689 uprv_strcpy(name, kRootLocaleName);
647 r = findFirstExisting(path, name, &isRoot, &hasChopped, &isDefault, &intStatus); 690 r = findFirstExisting(path, name, &isRoot, &hasChopped, &isDefault, &intStatus);
648 if(r != NULL) { 691 if(r != NULL) {
649 t1 = r; 692 t1 = r;
650 intStatus = U_USING_DEFAULT_WARNING; 693 intStatus = U_USING_DEFAULT_WARNING;
651 hasRealData = TRUE; 694 hasRealData = TRUE;
652 } else { /* we don't even have the root locale */ 695 } else { /* we don't even have the root locale */
653 *status = U_MISSING_RESOURCE_ERROR; 696 *status = U_MISSING_RESOURCE_ERROR;
654 goto finishUnlock; 697 goto finishUnlock;
655 } 698 }
656 } else if(!isRoot && uprv_strcmp(t1->fName, kRootLocaleName) != 0 && t1- >fParent == NULL && !r->fData.noFallback) { 699 } else if(!isRoot && uprv_strcmp(t1->fName, kRootLocaleName) != 0 &&
657 /* insert root locale */ 700 t1->fParent == NULL && !r->fData.noFallback) {
658 t2 = init_entry(kRootLocaleName, t1->fPath, &parentStatus); 701 if (!insertRootBundle(t1, status)) {
659 /* Check for null pointer. */
660 if (t2 == NULL) {
661 *status = U_MEMORY_ALLOCATION_ERROR;
662 goto finishUnlock; 702 goto finishUnlock;
663 } 703 }
664 if(!hasRealData) { 704 if(!hasRealData) {
665 r->fBogus = U_USING_DEFAULT_WARNING; 705 r->fBogus = U_USING_DEFAULT_WARNING;
666 } 706 }
667 hasRealData = (UBool)((t2->fBogus == U_ZERO_ERROR) || hasRealData);
668 t1->fParent = t2;
669 t1 = t2;
670 } 707 }
671 708
709 // TODO: Does this ever loop?
672 while(r != NULL && !isRoot && t1->fParent != NULL) { 710 while(r != NULL && !isRoot && t1->fParent != NULL) {
673 t1->fParent->fCountExisting++; 711 t1->fParent->fCountExisting++;
674 t1 = t1->fParent; 712 t1 = t1->fParent;
675 hasRealData = (UBool)((t1->fBogus == U_ZERO_ERROR) || hasRealData);
676 } 713 }
677 } /* umtx_lock */ 714 } /* umtx_lock */
678 finishUnlock: 715 finishUnlock:
679 umtx_unlock(&resbMutex); 716 umtx_unlock(&resbMutex);
680 717
681 if(U_SUCCESS(*status)) { 718 if(U_SUCCESS(*status)) {
682 if(U_SUCCESS(parentStatus)) { 719 if(intStatus != U_ZERO_ERROR) {
683 if(intStatus != U_ZERO_ERROR) { 720 *status = intStatus;
684 *status = intStatus;
685 }
686 return r;
687 } else {
688 *status = parentStatus;
689 return NULL;
690 } 721 }
722 return r;
691 } else { 723 } else {
692 return NULL; 724 return NULL;
693 } 725 }
694 } 726 }
695 727
728 /**
729 * Version of entryOpen() and findFirstExisting() for ures_openDirect(),
730 * with no fallbacks.
731 * Parent and root locale bundles are loaded if
732 * the requested bundle does not have the "nofallback" flag.
733 */
734 static UResourceDataEntry *
735 entryOpenDirect(const char* path, const char* localeID, UErrorCode* status) {
736 initCache(status);
737 if(U_FAILURE(*status)) {
738 return NULL;
739 }
740
741 umtx_lock(&resbMutex);
742 // findFirstExisting() without fallbacks.
743 UResourceDataEntry *r = init_entry(localeID, path, status);
744 if(U_SUCCESS(*status)) {
745 if(r->fBogus != U_ZERO_ERROR) {
746 r->fCountExisting--;
747 r = NULL;
748 }
749 } else {
750 r = NULL;
751 }
752
753 // Some code depends on the ures_openDirect() bundle to have a parent bundle chain,
754 // unless it is marked with "nofallback".
755 UResourceDataEntry *t1 = r;
756 if(r != NULL && uprv_strcmp(localeID, kRootLocaleName) != 0 && // not root
757 r->fParent == NULL && !r->fData.noFallback &&
758 uprv_strlen(localeID) < ULOC_FULLNAME_CAPACITY) {
759 char name[ULOC_FULLNAME_CAPACITY];
760 uprv_strcpy(name, localeID);
761 if(!chopLocale(name) || uprv_strcmp(name, kRootLocaleName) == 0 ||
762 loadParentsExceptRoot(t1, name, UPRV_LENGTHOF(name), FALSE, NULL , status)) {
763 if(uprv_strcmp(t1->fName, kRootLocaleName) != 0 && t1->fParent == NU LL) {
764 insertRootBundle(t1, status);
765 }
766 }
767 if(U_FAILURE(*status)) {
768 r = NULL;
769 }
770 }
771
772 if(r != NULL) {
773 // TODO: Does this ever loop?
774 while(t1->fParent != NULL) {
775 t1->fParent->fCountExisting++;
776 t1 = t1->fParent;
777 }
778 }
779 umtx_unlock(&resbMutex);
780 return r;
781 }
696 782
697 /** 783 /**
698 * Functions to create and destroy resource bundles. 784 * Functions to create and destroy resource bundles.
699 * CAUTION: resbMutex must be locked when calling this function. 785 * CAUTION: resbMutex must be locked when calling this function.
700 */ 786 */
701 /* INTERNAL: */ 787 /* INTERNAL: */
702 static void entryCloseInt(UResourceDataEntry *resB) { 788 static void entryCloseInt(UResourceDataEntry *resB) {
703 UResourceDataEntry *p = resB; 789 UResourceDataEntry *p = resB;
704 790
705 while(resB != NULL) { 791 while(resB != NULL) {
(...skipping 1300 matching lines...) Expand 10 before | Expand all | Expand 10 after
2006 #ifdef URES_DEBUG 2092 #ifdef URES_DEBUG
2007 U_CFUNC const char* ures_getPath(const UResourceBundle* resB) { 2093 U_CFUNC const char* ures_getPath(const UResourceBundle* resB) {
2008 if(resB == NULL) { 2094 if(resB == NULL) {
2009 return NULL; 2095 return NULL;
2010 } 2096 }
2011 2097
2012 return resB->fData->fPath; 2098 return resB->fData->fPath;
2013 } 2099 }
2014 #endif 2100 #endif
2015 2101
2016 /* OLD API implementation */ 2102 static UResourceBundle*
2017 2103 ures_openWithType(UResourceBundle *r, const char* path, const char* localeID,
2018 /** 2104 UResOpenType openType, UErrorCode* status) {
2019 * API: This function is used to open a resource bundle 2105 if(U_FAILURE(*status)) {
2020 * proper fallback chaining is executed while initialization.
2021 * The result is stored in cache for later fallback search.
2022 */
2023 U_CAPI void U_EXPORT2
2024 ures_openFillIn(UResourceBundle *r, const char* path,
2025 const char* localeID, UErrorCode* status) {
2026 if(r == NULL) {
2027 *status = U_ILLEGAL_ARGUMENT_ERROR;
2028 } else {
2029 UResourceDataEntry *firstData;
2030 UBool isStackObject = ures_isStackObject(r);
2031 char canonLocaleID[ULOC_FULLNAME_CAPACITY];
2032
2033 uloc_getBaseName(localeID, canonLocaleID, sizeof(canonLocaleID), status) ;
2034 if(U_FAILURE(*status) || *status == U_STRING_NOT_TERMINATED_WARNING) {
2035 *status = U_ILLEGAL_ARGUMENT_ERROR;
2036 return;
2037 }
2038
2039 ures_closeBundle(r, FALSE);
2040 uprv_memset(r, 0, sizeof(UResourceBundle));
2041 ures_setIsStackObject(r, isStackObject);
2042 r->fHasFallback = TRUE;
2043 r->fIsTopLevel = TRUE;
2044 r->fIndex = -1;
2045 r->fData = entryOpen(path, canonLocaleID, status);
2046 if(U_FAILURE(*status)) {
2047 return;
2048 }
2049 /* this is a quick fix to get regular data in bundle - until constructio n is cleaned up */
2050 firstData = r->fData;
2051 while(firstData->fBogus != U_ZERO_ERROR && firstData->fParent != NULL) {
2052 firstData = firstData->fParent;
2053 }
2054 uprv_memcpy(&r->fResData, &firstData->fData, sizeof(ResourceData));
2055 r->fHasFallback=(UBool)!r->fResData.noFallback;
2056 r->fRes = r->fResData.rootRes;
2057 r->fSize = res_countArrayItems(&(r->fResData), r->fRes);
2058 r->fTopLevelData = r->fData;
2059 }
2060 }
2061
2062 U_CAPI UResourceBundle* U_EXPORT2
2063 ures_open(const char* path,
2064 const char* localeID,
2065 UErrorCode* status)
2066 {
2067 char canonLocaleID[ULOC_FULLNAME_CAPACITY];
2068 UResourceDataEntry *hasData = NULL;
2069 UResourceBundle *r;
2070
2071 if(status == NULL || U_FAILURE(*status)) {
2072 return NULL; 2106 return NULL;
2073 } 2107 }
2074 2108
2075 /* first "canonicalize" the locale ID */ 2109 UResourceDataEntry *entry;
2076 uloc_getBaseName(localeID, canonLocaleID, sizeof(canonLocaleID), status); 2110 if(openType != URES_OPEN_DIRECT) {
2077 if(U_FAILURE(*status) || *status == U_STRING_NOT_TERMINATED_WARNING) { 2111 /* first "canonicalize" the locale ID */
2078 *status = U_ILLEGAL_ARGUMENT_ERROR; 2112 char canonLocaleID[ULOC_FULLNAME_CAPACITY];
2113 uloc_getBaseName(localeID, canonLocaleID, UPRV_LENGTHOF(canonLocaleID), status);
2114 if(U_FAILURE(*status) || *status == U_STRING_NOT_TERMINATED_WARNING) {
2115 *status = U_ILLEGAL_ARGUMENT_ERROR;
2116 return NULL;
2117 }
2118 entry = entryOpen(path, canonLocaleID, openType, status);
2119 } else {
2120 entry = entryOpenDirect(path, localeID, status);
2121 }
2122 if(U_FAILURE(*status)) {
2123 return NULL;
2124 }
2125 if(entry == NULL) {
2126 *status = U_MISSING_RESOURCE_ERROR;
2079 return NULL; 2127 return NULL;
2080 } 2128 }
2081 2129
2082 r = (UResourceBundle *)uprv_malloc(sizeof(UResourceBundle)); 2130 UBool isStackObject;
2083 if(r == NULL) { 2131 if(r == NULL) {
2084 *status = U_MEMORY_ALLOCATION_ERROR; 2132 r = (UResourceBundle *)uprv_malloc(sizeof(UResourceBundle));
2085 return NULL; 2133 if(r == NULL) {
2086 } 2134 entryClose(entry);
2087 2135 *status = U_MEMORY_ALLOCATION_ERROR;
2088 uprv_memset(r, 0, sizeof(UResourceBundle));
2089 r->fHasFallback = TRUE;
2090 r->fIsTopLevel = TRUE;
2091 ures_setIsStackObject(r, FALSE);
2092 r->fIndex = -1;
2093 r->fData = entryOpen(path, canonLocaleID, status);
2094 if(U_FAILURE(*status)) {
2095 uprv_free(r);
2096 return NULL;
2097 }
2098 r->fTopLevelData = r->fData;
2099
2100 hasData = r->fData;
2101 while(hasData->fBogus != U_ZERO_ERROR) {
2102 hasData = hasData->fParent;
2103 if(hasData == NULL) {
2104 /* This can happen only if fallback chain gets broken by an act of God */
2105 /* TODO: this unlikely to happen, consider removing it */
2106 entryClose(r->fData);
2107 uprv_free(r);
2108 *status = U_MISSING_RESOURCE_ERROR;
2109 return NULL; 2136 return NULL;
2110 } 2137 }
2138 isStackObject = FALSE;
2139 } else { // fill-in
2140 isStackObject = ures_isStackObject(r);
2141 ures_closeBundle(r, FALSE);
2111 } 2142 }
2143 uprv_memset(r, 0, sizeof(UResourceBundle));
2144 ures_setIsStackObject(r, isStackObject);
2112 2145
2113 uprv_memcpy(&r->fResData, &hasData->fData, sizeof(ResourceData)); 2146 r->fTopLevelData = r->fData = entry;
2114 r->fHasFallback=(UBool)!r->fResData.noFallback; 2147 uprv_memcpy(&r->fResData, &entry->fData, sizeof(ResourceData));
2148 r->fHasFallback = openType != URES_OPEN_DIRECT && !r->fResData.noFallback;
2149 r->fIsTopLevel = TRUE;
2115 r->fRes = r->fResData.rootRes; 2150 r->fRes = r->fResData.rootRes;
2116 r->fSize = res_countArrayItems(&(r->fResData), r->fRes); 2151 r->fSize = res_countArrayItems(&(r->fResData), r->fRes);
2117 /* 2152 r->fIndex = -1;
2118 if(r->fData->fPath != NULL) {
2119 ures_setResPath(r, r->fData->fPath);
2120 ures_appendResPath(r, RES_PATH_PACKAGE_S);
2121 ures_appendResPath(r, r->fData->fName);
2122 } else {
2123 ures_setResPath(r, r->fData->fName);
2124 }
2125 */
2126
2127 2153
2128 return r; 2154 return r;
2129 } 2155 }
2130 2156
2157 U_CAPI UResourceBundle* U_EXPORT2
2158 ures_open(const char* path, const char* localeID, UErrorCode* status) {
2159 return ures_openWithType(NULL, path, localeID, URES_OPEN_LOCALE_DEFAULT_ROOT , status);
2160 }
2161
2162 U_CAPI UResourceBundle* U_EXPORT2
2163 ures_openNoDefault(const char* path, const char* localeID, UErrorCode* status) {
2164 return ures_openWithType(NULL, path, localeID, URES_OPEN_LOCALE_ROOT, status );
2165 }
2166
2131 /** 2167 /**
2132 * Opens a resource bundle without "canonicalizing" the locale name. No fallbac k will be performed 2168 * Opens a resource bundle without "canonicalizing" the locale name. No fallbac k will be performed
2133 * or sought. However, alias substitution will happen! 2169 * or sought. However, alias substitution will happen!
2134 */ 2170 */
2135 U_CAPI UResourceBundle* U_EXPORT2 2171 U_CAPI UResourceBundle* U_EXPORT2
2136 ures_openDirect(const char* path, const char* localeID, UErrorCode* status) { 2172 ures_openDirect(const char* path, const char* localeID, UErrorCode* status) {
2137 UResourceBundle *r; 2173 return ures_openWithType(NULL, path, localeID, URES_OPEN_DIRECT, status);
2138 UErrorCode subStatus = U_ZERO_ERROR;
2139
2140 if(status == NULL || U_FAILURE(*status)) {
2141 return NULL;
2142 }
2143
2144 r = (UResourceBundle *)uprv_malloc(sizeof(UResourceBundle));
2145 if(r == NULL) {
2146 *status = U_MEMORY_ALLOCATION_ERROR;
2147 return NULL;
2148 }
2149
2150 r->fHasFallback = FALSE;
2151 r->fIsTopLevel = TRUE;
2152 ures_setIsStackObject(r, FALSE);
2153 r->fIndex = -1;
2154 r->fData = entryOpen(path, localeID, &subStatus);
2155 if(U_FAILURE(subStatus)) {
2156 *status = subStatus;
2157 uprv_free(r);
2158 return NULL;
2159 }
2160 if(subStatus != U_ZERO_ERROR /*r->fData->fBogus != U_ZERO_ERROR*/) {
2161 /* we didn't find one we were looking for - so openDirect */
2162 /* should fail */
2163 entryClose(r->fData);
2164 uprv_free(r);
2165 *status = U_MISSING_RESOURCE_ERROR;
2166 return NULL;
2167 }
2168
2169 r->fKey = NULL;
2170 r->fVersion = NULL;
2171 uprv_memcpy(&r->fResData, &r->fData->fData, sizeof(ResourceData));
2172 /* r->fHasFallback remains FALSE here in ures_openDirect() */
2173 r->fRes = r->fResData.rootRes;
2174 /*r->fParent = RES_BOGUS;*/
2175 r->fSize = res_countArrayItems(&(r->fResData), r->fRes);
2176 r->fResPath = NULL;
2177 r->fResPathLen = 0;
2178 /*r->fParentRes = NULL;*/
2179 r->fTopLevelData = r->fData;
2180
2181 return r;
2182 } 2174 }
2183 2175
2184 /** 2176 /**
2177 * API: This function is used to open a resource bundle
2178 * proper fallback chaining is executed while initialization.
2179 * The result is stored in cache for later fallback search.
2180 */
2181 U_CAPI void U_EXPORT2
2182 ures_openFillIn(UResourceBundle *r, const char* path,
2183 const char* localeID, UErrorCode* status) {
2184 if(U_SUCCESS(*status) && r == NULL) {
2185 *status = U_ILLEGAL_ARGUMENT_ERROR;
2186 return;
2187 }
2188 ures_openWithType(r, path, localeID, URES_OPEN_LOCALE_DEFAULT_ROOT, status);
2189 }
2190
2191 /**
2185 * API: Counts members. For arrays and tables, returns number of resources. 2192 * API: Counts members. For arrays and tables, returns number of resources.
2186 * For strings, returns 1. 2193 * For strings, returns 1.
2187 */ 2194 */
2188 U_CAPI int32_t U_EXPORT2 2195 U_CAPI int32_t U_EXPORT2
2189 ures_countArrayItems(const UResourceBundle* resourceBundle, 2196 ures_countArrayItems(const UResourceBundle* resourceBundle,
2190 const char* resourceKey, 2197 const char* resourceKey,
2191 UErrorCode* status) 2198 UErrorCode* status)
2192 { 2199 {
2193 UResourceBundle resData; 2200 UResourceBundle resData;
2194 ures_initStackObject(&resData); 2201 ures_initStackObject(&resData);
(...skipping 684 matching lines...) Expand 10 before | Expand all | Expand 10 after
2879 ures_getVersionByKey(const UResourceBundle* res, const char *key, UVersionInfo v er, UErrorCode *status) { 2886 ures_getVersionByKey(const UResourceBundle* res, const char *key, UVersionInfo v er, UErrorCode *status) {
2880 const UChar *str; 2887 const UChar *str;
2881 int32_t len; 2888 int32_t len;
2882 str = ures_getStringByKey(res, key, &len, status); 2889 str = ures_getStringByKey(res, key, &len, status);
2883 if(U_SUCCESS(*status)) { 2890 if(U_SUCCESS(*status)) {
2884 u_versionFromUString(ver, str); 2891 u_versionFromUString(ver, str);
2885 } 2892 }
2886 } 2893 }
2887 2894
2888 /* eof */ 2895 /* eof */
OLDNEW
« no previous file with comments | « source/common/uposixdefs.h ('k') | source/common/uresdata.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698