00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "uresimp.h"
00022 #include <stdio.h>
00023
00024
00025 static void entryCloseInt(UResourceDataEntry *resB);
00026 void entryClose(UResourceDataEntry *resB);
00027
00028
00029
00030 static UHashtable *cache = NULL;
00031 static UBool isMutexInited = FALSE;
00032 static UMTX resbMutex = NULL;
00033
00034
00035 static int32_t hashEntry(const void *parm) {
00036 UResourceDataEntry *b = (UResourceDataEntry *)parm;
00037 return uhash_hashChars(b->fName)+37*uhash_hashChars(b->fPath);
00038 }
00039
00040
00041 static UBool compareEntries(const void *p1, const void *p2) {
00042 UResourceDataEntry *b1 = (UResourceDataEntry *)p1;
00043 UResourceDataEntry *b2 = (UResourceDataEntry *)p2;
00044
00045 return (UBool)(uhash_compareChars(b1->fName, b2->fName) &
00046 uhash_compareChars(b1->fPath, b2->fPath));
00047 }
00048
00049
00054 static UBool chopLocale(char *name) {
00055 char *i = uprv_strrchr(name, '_');
00056
00057 if(i != NULL) {
00058 *i = '\0';
00059 return TRUE;
00060 }
00061
00062 return FALSE;
00063 }
00064
00068 static void entryIncrease(UResourceDataEntry *entry) {
00069 umtx_lock(&resbMutex);
00070 entry->fCountExisting++;
00071 while(entry->fParent != NULL) {
00072 entry = entry->fParent;
00073 entry->fCountExisting++;
00074 }
00075 umtx_unlock(&resbMutex);
00076 }
00077
00082 const ResourceData *getFallbackData(const UResourceBundle* resBundle, const char* * resTag, UResourceDataEntry* *realData, Resource *res, UErrorCode *status) {
00083 UResourceDataEntry *resB = resBundle->fData;
00084 int32_t indexR = -1;
00085 int32_t i = 0;
00086 *res = RES_BOGUS;
00087 if(resB != NULL) {
00088 if(resB->fBogus == U_ZERO_ERROR) {
00089 *res = res_getTableItemByKey(&(resB->fData), resB->fData.rootRes, &indexR, resTag);
00090 i++;
00091 }
00092 if(resBundle->fHasFallback == TRUE) {
00093 while(*res == RES_BOGUS && resB->fParent != NULL) {
00094 resB = resB->fParent;
00095 if(resB->fBogus == U_ZERO_ERROR) {
00096 i++;
00097 *res = res_getTableItemByKey(&(resB->fData), resB->fData.rootRes, &indexR, resTag);
00098 }
00099 }
00100 }
00101
00102 if(*res != RES_BOGUS) {
00103 if(i>1) {
00104 if(uprv_strcmp(resB->fName, uloc_getDefault())==0 || uprv_strcmp(resB->fName, kRootLocaleName)==0) {
00105 *status = U_USING_DEFAULT_ERROR;
00106 } else {
00107 *status = U_USING_FALLBACK_ERROR;
00108 }
00109 }
00110 *realData = resB;
00111 return (&(resB->fData));
00112 } else {
00113 *status = U_MISSING_RESOURCE_ERROR;
00114 return NULL;
00115 }
00116 } else {
00117 *status = U_MISSING_RESOURCE_ERROR;
00118 return NULL;
00119 }
00120 }
00121
00123 static void initCache(UErrorCode *status) {
00124 if(isMutexInited == FALSE) {
00125 umtx_lock(NULL);
00126 if(isMutexInited == FALSE) {
00127 umtx_init(&resbMutex);
00128 isMutexInited = TRUE;
00129 }
00130 umtx_unlock(NULL);
00131 }
00132 if(cache == NULL) {
00133 UHashtable *newCache = uhash_open(hashEntry, compareEntries, status);
00134 if (U_FAILURE(*status)) {
00135 return;
00136 }
00137 umtx_lock(&resbMutex);
00138 if(cache == NULL) {
00139 cache = newCache;
00140 newCache = NULL;
00141 }
00142 umtx_unlock(&resbMutex);
00143 if(newCache != NULL) {
00144 uhash_close(newCache);
00145 }
00146 }
00147 }
00148
00151 static void setEntryName(UResourceDataEntry *res, char *name, UErrorCode *status) {
00152 if(res->fName != NULL) {
00153 uprv_free(res->fName);
00154 }
00155 res->fName = (char *)uprv_malloc(sizeof(char)*uprv_strlen(name)+1);
00156 if(res->fName == NULL) {
00157 *status = U_MEMORY_ALLOCATION_ERROR;
00158 } else {
00159 uprv_strcpy(res->fName, name);
00160 }
00161 }
00162
00166 static UResourceDataEntry *init_entry(const char *localeID, const char *path, UErrorCode *status) {
00167 UResourceDataEntry *r = NULL;
00168 UResourceDataEntry find;
00169 int32_t hashValue;
00170 char name[96];
00171 const char *myPath = NULL;
00172
00173 if(U_FAILURE(*status)) {
00174 return NULL;
00175 }
00176
00177
00178 if(localeID == NULL) {
00179 uprv_strcpy(name, uloc_getDefault());
00180 } else if(uprv_strlen(localeID) == 0) {
00181 uprv_strcpy(name, kRootLocaleName);
00182 } else {
00183 uprv_strcpy(name, localeID);
00184 }
00185
00186 if(path != NULL) {
00187 if(uprv_strcmp(path, u_getDataDirectory()) != 0) {
00188 myPath = path;
00189 }
00190 }
00191
00192 find.fName = name;
00193 find.fPath = (char *)myPath;
00194
00195
00196 hashValue = hashEntry((const void *)&find);
00197
00198
00199 r = (UResourceDataEntry *)uhash_get(cache, &find);
00200
00201 if(r != NULL) {
00202 r->fCountExisting++;
00203 *status = r->fBogus;
00204 } else {
00205 UBool result = FALSE;
00206
00207 r = (UResourceDataEntry *) uprv_malloc(sizeof(UResourceDataEntry));
00208
00209 if(r == NULL) {
00210 *status = U_MEMORY_ALLOCATION_ERROR;
00211 return NULL;
00212 }
00213 r->fCountExisting = 1;
00214
00215 r->fName = NULL;
00216 setEntryName(r, name, status);
00217
00218 r->fPath = NULL;
00219 if(myPath != NULL && !U_FAILURE(*status)) {
00220 r->fPath = (char *)uprv_malloc(sizeof(char)*uprv_strlen(myPath)+1);
00221 if(r->fPath == NULL) {
00222 *status = U_MEMORY_ALLOCATION_ERROR;
00223 } else {
00224 uprv_strcpy(r->fPath, myPath);
00225 }
00226 }
00227
00228 r->fHashKey = hashValue;
00229 r->fParent = NULL;
00230 r->fData.data = NULL;
00231 r->fData.pRoot = NULL;
00232 r->fData.rootRes = 0;
00233 r->fBogus = U_ZERO_ERROR;
00234
00235
00236 result = res_load(&(r->fData), r->fPath, r->fName, status);
00237
00238 if (result == FALSE || U_FAILURE(*status)) {
00239
00240 *status = U_USING_FALLBACK_ERROR;
00241 r->fBogus = U_USING_FALLBACK_ERROR;
00242 } else {
00243
00244 char aliasName[100];
00245 int32_t aliasLen;
00246
00247 Resource aliasres = res_getResource(&(r->fData), "%%ALIAS");
00248 const UChar *alias = res_getString(&(r->fData), aliasres, &aliasLen);
00249 if(alias != NULL && aliasLen > 0) {
00250 u_UCharsToChars(alias, aliasName, u_strlen(alias)+1);
00251 res_unload(&(r->fData));
00252 result = res_load(&(r->fData), r->fPath, aliasName, status);
00253 if (result == FALSE || U_FAILURE(*status)) {
00254
00255 *status = U_USING_FALLBACK_ERROR;
00256 r->fBogus = U_USING_FALLBACK_ERROR;
00257 }
00258 }
00259 }
00260
00261 {
00262 UResourceDataEntry *oldR = NULL;
00263 if((oldR = (UResourceDataEntry *)uhash_get(cache, r)) == NULL) {
00264
00265 uhash_put(cache, (void *)r, r, status);
00266 } else {
00267
00268
00269 uprv_free(r->fName);
00270 if(r->fPath != NULL) {
00271 uprv_free(r->fPath);
00272 }
00273 uprv_free(r);
00274 r = oldR;
00275 r->fCountExisting++;
00276 }
00277 }
00278 }
00279 return r;
00280 }
00281
00282
00283 static UResourceDataEntry *entryOpen(const char* path, const char* localeID, UErrorCode* status) {
00284 UErrorCode initstatus = U_ZERO_ERROR;
00285 UResourceDataEntry *r = NULL;
00286 UResourceDataEntry *t1 = NULL;
00287 UResourceDataEntry *t2 = NULL;
00288 UBool isDefault = FALSE;
00289 UBool isRoot = FALSE;
00290 UBool hasRealData = FALSE;
00291 UBool hasChopped = FALSE;
00292 char name[96];
00293
00294 if(U_FAILURE(*status)) {
00295 return NULL;
00296 }
00297
00298 initCache(status);
00299
00300 umtx_lock(&resbMutex);
00301 r = init_entry(localeID, path, &initstatus);
00302 uprv_strcpy(name, r->fName);
00303 isDefault = (UBool)(uprv_strncmp(name, uloc_getDefault(), uprv_strlen(name)) == 0);
00304 hasRealData = (UBool)(r->fBogus == U_ZERO_ERROR);
00305
00306 isRoot = (UBool)(uprv_strcmp(name, kRootLocaleName) == 0);
00307
00308
00309 hasChopped = chopLocale(name);
00310 t1 = r;
00311
00312 while (hasChopped && !isRoot && t1->fParent == NULL) {
00313
00314 t2 = init_entry(name, r->fPath, status);
00315 hasRealData = (UBool)((t2->fBogus == U_ZERO_ERROR) | hasRealData);
00316 t1->fParent = t2;
00317 t1 = t2;
00318 hasChopped = chopLocale(name);
00319 }
00320
00321 if(!hasRealData && !isDefault && !isRoot && t1->fParent == NULL) {
00322
00323 uprv_strcpy(name, uloc_getDefault());
00324 t2 = init_entry(name, r->fPath, status);
00325 hasRealData = (UBool)((t2->fBogus == U_ZERO_ERROR) | hasRealData);
00326 r->fBogus = U_USING_DEFAULT_ERROR;
00327 isDefault = TRUE;
00328 t1->fParent = t2;
00329 t1 = t2;
00330 hasChopped = chopLocale(name);
00331 while (hasChopped && t1->fParent == NULL) {
00332
00333 t2 = init_entry(name, r->fPath, status);
00334 hasRealData = (UBool)((t2->fBogus == U_ZERO_ERROR) | hasRealData);
00335 t1->fParent = t2;
00336 t1 = t2;
00337 hasChopped = chopLocale(name);
00338 }
00339 }
00340
00341 if(!isRoot && uprv_strcmp(t1->fName, kRootLocaleName) != 0 && t1->fParent == NULL) {
00342
00343 t2 = init_entry(kRootLocaleName, r->fPath, status);
00344 if(!hasRealData) {
00345 r->fBogus = U_USING_DEFAULT_ERROR;
00346 }
00347 hasRealData = (UBool)((t2->fBogus == U_ZERO_ERROR) | hasRealData);
00348 t1->fParent = t2;
00349 t1 = t2;
00350 }
00351
00352 while(!isRoot && t1->fParent != NULL) {
00353 t1->fParent->fCountExisting++;
00354 t1 = t1->fParent;
00355 hasRealData = (UBool)((t1->fBogus == U_ZERO_ERROR) | hasRealData);
00356 }
00357
00358 if(!hasRealData) {
00359 entryCloseInt(r);
00360 *status = U_MISSING_RESOURCE_ERROR;
00361 }
00362
00363 umtx_unlock(&resbMutex);
00364
00365 if(U_SUCCESS(*status)) {
00366 *status = r->fBogus;
00367 return r;
00368 } else {
00369 return NULL;
00370 }
00371 }
00372
00373
00383 U_CFUNC UResourceBundle* ures_openNoFallback(const char* path, const char* localeID, UErrorCode* status) {
00384 UResourceBundle *r = (UResourceBundle *)uprv_malloc(sizeof(UResourceBundle));
00385 if(r == NULL) {
00386 *status = U_MEMORY_ALLOCATION_ERROR;
00387 return NULL;
00388 }
00389
00390 r->fHasFallback = FALSE;
00391 r->fIsTopLevel = TRUE;
00392 ures_setIsStackObject(r, FALSE);
00393 r->fIndex = -1;
00394 r->fData = entryOpen(path, localeID, status);
00395 if(U_FAILURE(*status)) {
00396 uprv_free(r);
00397 return NULL;
00398 }
00399 if(r->fData->fBogus != U_ZERO_ERROR) {
00400 entryClose(r->fData);
00401 uprv_free(r);
00402 *status = U_MISSING_RESOURCE_ERROR;
00403 return NULL;
00404 }
00405
00406 r->fKey = NULL;
00407 r->fVersion = NULL;
00408 r->fResData.data = r->fData->fData.data;
00409 r->fResData.pRoot = r->fData->fData.pRoot;
00410 r->fResData.rootRes = r->fData->fData.rootRes;
00411 r->fRes = r->fResData.rootRes;
00412 r->fSize = res_countArrayItems(&(r->fResData), r->fRes);
00413 return r;
00414 }
00415
00416
00417 static UResourceBundle *init_resb_result(const ResourceData *rdata, const Resource r, const char *key, UResourceDataEntry *realData, UResourceBundle *resB, UErrorCode *status) {
00418 if(status == NULL || U_FAILURE(*status)) {
00419 return resB;
00420 }
00421 if(resB == NULL) {
00422 resB = (UResourceBundle *)uprv_malloc(sizeof(UResourceBundle));
00423 ures_setIsStackObject(resB, FALSE);
00424 } else {
00425 if(ures_isStackObject(resB, status) != FALSE) {
00426 ures_setIsStackObject(resB, TRUE);
00427 }
00428 }
00429 resB->fData = realData;
00430 entryIncrease(resB->fData);
00431 resB->fHasFallback = FALSE;
00432 resB->fIsTopLevel = FALSE;
00433 resB->fIndex = -1;
00434 resB->fKey = key;
00435 resB->fVersion = NULL;
00436 resB->fRes = r;
00437 resB->fResData.data = rdata->data;
00438 resB->fResData.pRoot = rdata->pRoot;
00439 resB->fResData.rootRes = rdata->rootRes;
00440 resB->fSize = res_countArrayItems(&(resB->fResData), resB->fRes);
00441 return resB;
00442 }
00443
00444 UResourceBundle *copyResb(UResourceBundle *r, const UResourceBundle *original, UErrorCode *status) {
00445 UBool isStackObject;
00446 if(U_FAILURE(*status) || r == original) {
00447 return r;
00448 }
00449 if(original != NULL) {
00450 if(r == NULL) {
00451 isStackObject = FALSE;
00452 r = (UResourceBundle *)uprv_malloc(sizeof(UResourceBundle));
00453 } else {
00454 isStackObject = ures_isStackObject(r, status);
00455 if(U_FAILURE(*status)) {
00456 return r;
00457 }
00458 if(isStackObject == FALSE) {
00459 ures_close(r);
00460 r = (UResourceBundle *)uprv_malloc(sizeof(UResourceBundle));
00461 }
00462 }
00463 uprv_memcpy(r, original, sizeof(UResourceBundle));
00464 ures_setIsStackObject(r, isStackObject);
00465 if(r->fData != NULL) {
00466 entryIncrease(r->fData);
00467 }
00468 return r;
00469 } else {
00470 return r;
00471 }
00472 }
00473
00478 U_CAPI const UChar* U_EXPORT2 ures_getString(const UResourceBundle* resB, int32_t* len, UErrorCode* status) {
00479
00480 if (status==NULL || U_FAILURE(*status)) {
00481 return NULL;
00482 }
00483 if(resB == NULL) {
00484 *status = U_ILLEGAL_ARGUMENT_ERROR;
00485 return NULL;
00486 }
00487
00488 switch(RES_GET_TYPE(resB->fRes)) {
00489 case RES_STRING:
00490 return res_getString(&(resB->fResData), resB->fRes, len);
00491 case RES_INT:
00492 case RES_INT_VECTOR:
00493 case RES_BINARY:
00494 case RES_ARRAY:
00495 case RES_TABLE:
00496 default:
00497 *status = U_RESOURCE_TYPE_MISMATCH;
00498 }
00499
00500 return NULL;
00501 }
00502
00503 U_CAPI const uint8_t* U_EXPORT2 ures_getBinary(const UResourceBundle* resB, int32_t* len,
00504 UErrorCode* status) {
00505
00506 if (status==NULL || U_FAILURE(*status)) {
00507 return NULL;
00508 }
00509 if(resB == NULL) {
00510 *status = U_ILLEGAL_ARGUMENT_ERROR;
00511 return NULL;
00512 }
00513 switch(RES_GET_TYPE(resB->fRes)) {
00514 case RES_BINARY:
00515 return res_getBinary(&(resB->fResData), resB->fRes, len);
00516 case RES_INT:
00517 case RES_STRING:
00518 case RES_INT_VECTOR:
00519 case RES_ARRAY:
00520 case RES_TABLE:
00521 default:
00522 *status = U_RESOURCE_TYPE_MISMATCH;
00523 }
00524
00525 return NULL;
00526 }
00527
00528 U_CAPI uint32_t U_EXPORT2 ures_getInt(const UResourceBundle* resB, UErrorCode *status) {
00529
00530 if (status==NULL || U_FAILURE(*status)) {
00531 return 0xffffffff;
00532 }
00533 if(resB == NULL) {
00534 *status = U_ILLEGAL_ARGUMENT_ERROR;
00535 return 0xffffffff;
00536 }
00537 return RES_GET_UINT(resB->fRes);
00538 }
00539
00540
00541 U_CAPI UResType U_EXPORT2 ures_getType(UResourceBundle *resB) {
00542 if(resB == NULL) {
00543 return RES_NONE;
00544 }
00545 return (UResType) (RES_GET_TYPE(resB->fRes));
00546 }
00547
00548 U_CAPI const char * U_EXPORT2 ures_getKey(UResourceBundle *resB) {
00549 if(resB == NULL) {
00550 return NULL;
00551 }
00552
00553 return(resB->fKey);
00554 }
00555
00556 U_CAPI int32_t U_EXPORT2 ures_getSize(UResourceBundle *resB) {
00557 if(resB == NULL) {
00558 return 0;
00559 }
00560
00561 return resB->fSize;
00562 }
00563
00564 U_CAPI void U_EXPORT2 ures_resetIterator(UResourceBundle *resB){
00565 if(resB == NULL) {
00566 return;
00567 }
00568 resB->fIndex = -1;
00569 }
00570
00571 U_CAPI UBool U_EXPORT2 ures_hasNext(UResourceBundle *resB) {
00572 if(resB == NULL) {
00573 return FALSE;
00574 }
00575 return (UBool)(resB->fIndex < resB->fSize-1);
00576 }
00577
00578 U_CAPI const UChar* U_EXPORT2 ures_getNextString(UResourceBundle *resB, int32_t* len, const char ** key, UErrorCode *status) {
00579 Resource r = RES_BOGUS;
00580
00581 if (status==NULL || U_FAILURE(*status)) {
00582 return NULL;
00583 }
00584 if(resB == NULL) {
00585 *status = U_ILLEGAL_ARGUMENT_ERROR;
00586 return NULL;
00587 }
00588
00589 if(resB->fIndex == resB->fSize-1) {
00590 *status = U_INDEX_OUTOFBOUNDS_ERROR;
00591 } else {
00592 resB->fIndex++;
00593 switch(RES_GET_TYPE(resB->fRes)) {
00594 case RES_INT:
00595 case RES_BINARY:
00596 case RES_STRING:
00597 return res_getString(&(resB->fResData), resB->fRes, len);
00598 case RES_TABLE:
00599 r = res_getTableItemByIndex(&(resB->fResData), resB->fRes, resB->fIndex, key);
00600 if(r == RES_BOGUS && resB->fHasFallback) {
00601
00602 }
00603 return res_getString(&(resB->fResData), r, len);
00604 case RES_ARRAY:
00605 r = res_getArrayItem(&(resB->fResData), resB->fRes, resB->fIndex);
00606 if(r == RES_BOGUS && resB->fHasFallback) {
00607
00608 }
00609 return res_getString(&(resB->fResData), r, len);
00610 case RES_INT_VECTOR:
00611 default:
00612 return NULL;
00613 break;
00614 }
00615 }
00616
00617 return NULL;
00618 }
00619
00620 U_CAPI UResourceBundle* U_EXPORT2 ures_getNextResource(UResourceBundle *resB, UResourceBundle *fillIn, UErrorCode *status) {
00621 const char *key = NULL;
00622 Resource r = RES_BOGUS;
00623
00624 if (status==NULL || U_FAILURE(*status)) {
00625
00626 return fillIn;
00627 }
00628 if(resB == NULL) {
00629 *status = U_ILLEGAL_ARGUMENT_ERROR;
00630
00631 return fillIn;
00632 }
00633
00634 if(resB->fIndex == resB->fSize-1) {
00635 *status = U_INDEX_OUTOFBOUNDS_ERROR;
00636
00637 } else {
00638 resB->fIndex++;
00639 switch(RES_GET_TYPE(resB->fRes)) {
00640 case RES_INT:
00641 case RES_BINARY:
00642 case RES_STRING:
00643 return copyResb(fillIn, resB, status);
00644 case RES_TABLE:
00645 r = res_getTableItemByIndex(&(resB->fResData), resB->fRes, resB->fIndex, &key);
00646 if(r == RES_BOGUS && resB->fHasFallback) {
00647
00648 }
00649 return init_resb_result(&(resB->fResData), r, key, resB->fData, fillIn, status);
00650 case RES_ARRAY:
00651 r = res_getArrayItem(&(resB->fResData), resB->fRes, resB->fIndex);
00652 if(r == RES_BOGUS && resB->fHasFallback) {
00653
00654 }
00655 return init_resb_result(&(resB->fResData), r, key, resB->fData, fillIn, status);
00656 case RES_INT_VECTOR:
00657 default:
00658
00659 return fillIn;
00660 }
00661 }
00662
00663 return fillIn;
00664 }
00665
00666 U_CAPI UResourceBundle* U_EXPORT2 ures_getByIndex(const UResourceBundle *resB, int32_t indexR, UResourceBundle *fillIn, UErrorCode *status) {
00667 const char* key = NULL;
00668 Resource r = RES_BOGUS;
00669
00670 if (status==NULL || U_FAILURE(*status)) {
00671
00672 return fillIn;
00673 }
00674 if(resB == NULL) {
00675 *status = U_ILLEGAL_ARGUMENT_ERROR;
00676
00677 return fillIn;
00678 }
00679
00680 if(indexR >= 0 && resB->fSize > indexR) {
00681 switch(RES_GET_TYPE(resB->fRes)) {
00682 case RES_INT:
00683 case RES_BINARY:
00684 case RES_STRING:
00685 return copyResb(fillIn, resB, status);
00686 case RES_TABLE:
00687 r = res_getTableItemByIndex(&(resB->fResData), resB->fRes, indexR, &key);
00688 if(r == RES_BOGUS && resB->fHasFallback) {
00689
00690 }
00691 return init_resb_result(&(resB->fResData), r, key, resB->fData, fillIn, status);
00692 case RES_ARRAY:
00693 r = res_getArrayItem(&(resB->fResData), resB->fRes, indexR);
00694 if(r == RES_BOGUS && resB->fHasFallback) {
00695
00696 }
00697 return init_resb_result(&(resB->fResData), r, key, resB->fData, fillIn, status);
00698 case RES_INT_VECTOR:
00699 default:
00700
00701 return fillIn;
00702 }
00703 } else {
00704 *status = U_MISSING_RESOURCE_ERROR;
00705 }
00706
00707 return fillIn;
00708 }
00709
00710 U_CAPI const UChar* U_EXPORT2 ures_getStringByIndex(const UResourceBundle *resB, int32_t indexS, int32_t* len, UErrorCode *status) {
00711 const char* key = NULL;
00712 Resource r = RES_BOGUS;
00713
00714 if (status==NULL || U_FAILURE(*status)) {
00715 return NULL;
00716 }
00717 if(resB == NULL) {
00718 *status = U_ILLEGAL_ARGUMENT_ERROR;
00719 return NULL;
00720 }
00721
00722 if(indexS >= 0 && resB->fSize > indexS) {
00723 switch(RES_GET_TYPE(resB->fRes)) {
00724 case RES_INT:
00725 case RES_BINARY:
00726 case RES_STRING:
00727 return res_getString(&(resB->fResData), resB->fRes, len);
00728 case RES_TABLE:
00729 r = res_getTableItemByIndex(&(resB->fResData), resB->fRes, indexS, &key);
00730 if(r == RES_BOGUS && resB->fHasFallback) {
00731
00732 }
00733 return res_getString(&(resB->fResData), r, len);
00734 case RES_ARRAY:
00735 r = res_getArrayItem(&(resB->fResData), resB->fRes, indexS);
00736 if(r == RES_BOGUS && resB->fHasFallback) {
00737
00738 }
00739 return res_getString(&(resB->fResData), r, len);
00740 case RES_INT_VECTOR:
00741 default:
00742 return NULL;
00743 }
00744 } else {
00745 *status = U_MISSING_RESOURCE_ERROR;
00746 }
00747 return NULL;
00748 }
00749
00750 U_CAPI UResourceBundle* U_EXPORT2 ures_getByKey(const UResourceBundle *resB, const char* inKey, UResourceBundle *fillIn, UErrorCode *status) {
00751 Resource res = RES_BOGUS;
00752 UResourceDataEntry *realData = NULL;
00753 const char *key = inKey;
00754
00755 if (status==NULL || U_FAILURE(*status)) {
00756
00757 return fillIn;
00758 }
00759 if(resB == NULL) {
00760 *status = U_ILLEGAL_ARGUMENT_ERROR;
00761
00762 return fillIn;
00763 }
00764
00765 if(RES_GET_TYPE(resB->fRes) == RES_TABLE) {
00766 int32_t t;
00767 res = res_getTableItemByKey(&(resB->fResData), resB->fRes, &t, &key);
00768 if(res == RES_BOGUS) {
00769 key = inKey;
00770 if(resB->fHasFallback == TRUE) {
00771 const ResourceData *rd = getFallbackData(resB, &key, &realData, &res, status);
00772 if(U_SUCCESS(*status)) {
00773 return init_resb_result(rd, res, key, realData, fillIn, status);
00774 } else {
00775 *status = U_MISSING_RESOURCE_ERROR;
00776 }
00777 } else {
00778 *status = U_MISSING_RESOURCE_ERROR;
00779 }
00780 } else {
00781 return init_resb_result(&(resB->fResData), res, key, resB->fData, fillIn, status);
00782 }
00783 } else if(RES_GET_TYPE(resB->fRes) == RES_ARRAY && resB->fHasFallback == TRUE) {
00784
00785 const ResourceData *rd = getFallbackData(resB, &key, &realData, &res, status);
00786 if(U_SUCCESS(*status)) {
00787 return init_resb_result(rd, res, key, realData, fillIn, status);
00788 } else {
00789 *status = U_MISSING_RESOURCE_ERROR;
00790 }
00791 } else {
00792 *status = U_RESOURCE_TYPE_MISMATCH;
00793 }
00794
00795 return fillIn;
00796 }
00797
00798 U_CAPI const UChar* U_EXPORT2 ures_getStringByKey(const UResourceBundle *resB, const char* inKey, int32_t* len, UErrorCode *status) {
00799 Resource res = RES_BOGUS;
00800 UResourceDataEntry *realData = NULL;
00801 const char* key = inKey;
00802
00803 if (status==NULL || U_FAILURE(*status)) {
00804 return NULL;
00805 }
00806 if(resB == NULL) {
00807 *status = U_ILLEGAL_ARGUMENT_ERROR;
00808 return NULL;
00809 }
00810
00811 if(RES_GET_TYPE(resB->fRes) == RES_TABLE) {
00812 int32_t t=0;
00813 res = res_getTableItemByKey(&(resB->fResData), resB->fRes, &t, &key);
00814 if(res == RES_BOGUS) {
00815 key = inKey;
00816 if(resB->fHasFallback == TRUE) {
00817 const ResourceData *rd = getFallbackData(resB, &key, &realData, &res, status);
00818 if(U_SUCCESS(*status)) {
00819 return res_getString(rd, res, len);
00820 } else {
00821 *status = U_MISSING_RESOURCE_ERROR;
00822 }
00823 } else {
00824 *status = U_MISSING_RESOURCE_ERROR;
00825 }
00826 } else {
00827 return res_getString(&(resB->fResData), res, len);
00828 }
00829 } else if(RES_GET_TYPE(resB->fRes) == RES_ARRAY && resB->fHasFallback == TRUE) {
00830
00831 const ResourceData *rd = getFallbackData(resB, &key, &realData, &res, status);
00832 if(U_SUCCESS(*status)) {
00833 return res_getString(rd, res, len);
00834 } else {
00835 *status = U_MISSING_RESOURCE_ERROR;
00836 }
00837 } else {
00838 *status = U_RESOURCE_TYPE_MISMATCH;
00839 }
00840 return NULL;
00841 }
00842
00843
00844
00845
00850 U_CFUNC const char* ures_getRealLocale(const UResourceBundle* resourceBundle, UErrorCode* status)
00851 {
00852 const UResourceDataEntry *resB = resourceBundle->fData;
00853 if (status==NULL || U_FAILURE(*status)) {
00854 return NULL;
00855 }
00856 if (!resourceBundle) {
00857 *status = U_ILLEGAL_ARGUMENT_ERROR;
00858 return NULL;
00859 }
00860
00861 while(resB->fBogus != U_ZERO_ERROR && resB->fParent != NULL) {
00862 resB = resB->fParent;
00863 }
00864 if(resB->fBogus == U_ZERO_ERROR) {
00865 return resB->fName;
00866 } else {
00867 *status = U_INTERNAL_PROGRAM_ERROR;
00868 }
00869 return NULL;
00870 }
00871
00872 static void entryCloseInt(UResourceDataEntry *resB) {
00873 UResourceDataEntry *p = resB;
00874
00875 while(resB != NULL) {
00876 p = resB->fParent;
00877 resB->fCountExisting--;
00878
00879 if(resB->fCountExisting <= 0) {
00880
00881
00882
00883
00884
00885
00886
00887
00888
00889
00890
00891
00892
00893
00894
00895
00896 }
00897
00898 resB = p;
00899 }
00900 }
00901
00906 void entryClose(UResourceDataEntry *resB) {
00907 umtx_lock(&resbMutex);
00908 entryCloseInt(resB);
00909 umtx_unlock(&resbMutex);
00910 }
00911
00912
00913 U_CFUNC const char* ures_getName(const UResourceBundle* resB) {
00914 return resB->fData->fName;
00915 }
00916 U_CFUNC const char* ures_getPath(const UResourceBundle* resB) {
00917 return resB->fData->fPath;
00918 }
00919 U_CFUNC const char* ures_getTag(const UResourceBundle* resB) {
00920 return resB->fKey;
00921 }
00922 U_CFUNC const ResourceData * ures_getResData(const UResourceBundle* resB) {
00923 return &(resB->fData->fData);
00924 }
00925
00926
00927
00933 U_CAPI void ures_openFillIn(UResourceBundle *r, const char* path,
00934 const char* localeID, UErrorCode* status) {
00935 if(r == NULL) {
00936 *status = U_INTERNAL_PROGRAM_ERROR;
00937 } else {
00938 UResourceDataEntry *firstData;
00939 r->fHasFallback = TRUE;
00940 r->fIsTopLevel = TRUE;
00941 r->fKey = NULL;
00942 r->fVersion = NULL;
00943 r->fIndex = -1;
00944 r->fData = entryOpen(path, localeID, status);
00945
00946 firstData = r->fData;
00947 while(firstData->fBogus != U_ZERO_ERROR && firstData->fParent != NULL) {
00948 firstData = firstData->fParent;
00949 }
00950 r->fResData.data = firstData->fData.data;
00951 r->fResData.pRoot = firstData->fData.pRoot;
00952 r->fResData.rootRes = firstData->fData.rootRes;
00953 r->fRes = r->fResData.rootRes;
00954 r->fSize = res_countArrayItems(&(r->fResData), r->fRes);
00955 }
00956 }
00957 U_CAPI UResourceBundle* ures_open(const char* path,
00958 const char* localeID,
00959 UErrorCode* status)
00960 {
00961 UResourceDataEntry *hasData = NULL;
00962 UResourceBundle *r = (UResourceBundle *)uprv_malloc(sizeof(UResourceBundle));
00963 if(r == NULL) {
00964 *status = U_MEMORY_ALLOCATION_ERROR;
00965 return NULL;
00966 }
00967
00968 r->fHasFallback = TRUE;
00969 r->fIsTopLevel = TRUE;
00970 ures_setIsStackObject(r, FALSE);
00971 r->fKey = NULL;
00972 r->fVersion = NULL;
00973 r->fIndex = -1;
00974 r->fData = entryOpen(path, localeID, status);
00975 if(U_FAILURE(*status)) {
00976 uprv_free(r);
00977 return NULL;
00978 }
00979
00980 hasData = r->fData;
00981 while(hasData->fBogus != U_ZERO_ERROR) {
00982 hasData = hasData->fParent;
00983 if(hasData == NULL) {
00984 entryClose(r->fData);
00985 uprv_free(r);
00986 *status = U_MISSING_RESOURCE_ERROR;
00987 return NULL;
00988 }
00989 }
00990
00991 r->fResData.data = hasData->fData.data;
00992 r->fResData.pRoot = hasData->fData.pRoot;
00993 r->fResData.rootRes = hasData->fData.rootRes;
00994 r->fRes = r->fResData.rootRes;
00995 r->fSize = res_countArrayItems(&(r->fResData), r->fRes);
00996
00997 return r;
00998 }
00999
01000 U_CAPI UResourceBundle* ures_openW(const wchar_t* myPath,
01001 const char* localeID,
01002 UErrorCode* status)
01003 {
01004 char path[100];
01005 UResourceBundle *r;
01006 size_t tempSize = uprv_wcstombs(NULL, myPath, ((size_t)-1) >> 1);
01007
01008
01009 tempSize = uprv_wcstombs(path, myPath, tempSize);
01010 path[tempSize] = 0;
01011
01012
01013
01014 r = ures_open(path, localeID, status);
01015
01016 if (r == FALSE || U_FAILURE(*status)) {
01017 return NULL;
01018 }
01019
01020 return r;
01021 }
01022
01023
01024 U_CAPI UResourceBundle* U_EXPORT2 ures_openU(const UChar* myPath,
01025 const char* localeID,
01026 UErrorCode* status)
01027 {
01028 char path[100];
01029 UResourceBundle *r;
01030 int32_t pathlen = u_strlen(myPath);
01031
01032
01033 u_UCharsToChars(myPath, path, pathlen);
01034 path[pathlen] = 0;
01035
01036 r = ures_open(path, localeID, status);
01037
01038 if (r == FALSE || U_FAILURE(*status)) {
01039 return NULL;
01040 }
01041
01042 return r;
01043 }
01044
01045 U_CAPI void ures_setIsStackObject( UResourceBundle* resB, UBool state) {
01046 if(state == TRUE) {
01047 resB->fMagic1 = 0;
01048 resB->fMagic2 = 0;
01049 } else {
01050 resB->fMagic1 = MAGIC1;
01051 resB->fMagic2 = MAGIC2;
01052 }
01053 }
01054
01055 U_CAPI UBool ures_isStackObject( UResourceBundle* resB, UErrorCode *status) {
01056 if(status == NULL || U_FAILURE(*status)) {
01057 return FALSE;
01058 }
01059 if(resB == NULL) {
01060 *status = U_ILLEGAL_ARGUMENT_ERROR;
01061 return TRUE;
01062 }
01063 if(resB->fMagic1 == MAGIC1 && resB->fMagic2 == MAGIC2) {
01064 return FALSE;
01065 } else {
01066 return TRUE;
01067 }
01068 }
01069
01070
01071 U_CAPI const UChar* ures_get( const UResourceBundle* resB,
01072 const char* resourceTag,
01073 UErrorCode* status)
01074 {
01075 int32_t len = 0;
01076 if(resB == NULL || U_FAILURE(*status)) {
01077 *status = U_ILLEGAL_ARGUMENT_ERROR;
01078 return NULL;
01079 }
01080 return ures_getStringByKey(resB, resourceTag, &len, status);
01081 }
01082
01083 U_CAPI const UChar* ures_getArrayItem(const UResourceBundle* resB,
01084 const char* resourceTag,
01085 int32_t resourceIndex,
01086 UErrorCode* status)
01087 {
01088 UResourceBundle res;
01089 ures_setIsStackObject(&res, TRUE);
01090 if (status==NULL || U_FAILURE(*status)) {
01091 return NULL;
01092 }
01093 if(resB == NULL) {
01094 *status = U_ILLEGAL_ARGUMENT_ERROR;
01095 return NULL;
01096 }
01097 ures_getByKey(resB, resourceTag, &res, status);
01098 if(U_SUCCESS(*status)) {
01099 int32_t len = 0;
01100 const UChar *r = ures_getStringByIndex(&res, resourceIndex, &len, status);
01101 ures_close(&res);
01102 return r;
01103 } else {
01104 return NULL;
01105 }
01106 }
01107
01108 U_CAPI const UChar* ures_get2dArrayItem(const UResourceBundle* resB,
01109 const char* resourceTag,
01110 int32_t rowIndex,
01111 int32_t columnIndex,
01112 UErrorCode* status)
01113 {
01114 UResourceBundle res;
01115 ures_setIsStackObject(&res, TRUE);
01116 if (status==NULL || U_FAILURE(*status)) {
01117 return NULL;
01118 }
01119 if(resB == NULL) {
01120 *status = U_ILLEGAL_ARGUMENT_ERROR;
01121 return NULL;
01122 }
01123 ures_getByKey(resB, resourceTag, &res, status);
01124 if(U_SUCCESS(*status)) {
01125 UResourceBundle res2;
01126 ures_setIsStackObject(&res2, TRUE);
01127 ures_getByIndex(&res, rowIndex, &res2, status);
01128 ures_close(&res);
01129 if(U_SUCCESS(*status)) {
01130 int32_t len = 0;
01131 const UChar *r = ures_getStringByIndex(&res2, columnIndex, &len, status);
01132 ures_close(&res2);
01133 return r;
01134 } else {
01135 return NULL;
01136 }
01137 } else {
01138 return NULL;
01139 }
01140 }
01141
01142 U_CAPI const UChar* ures_getTaggedArrayItem(const UResourceBundle* resB,
01143 const char* resourceTag,
01144 const char* itemTag,
01145 UErrorCode* status)
01146 {
01147 UResourceBundle res;
01148 ures_setIsStackObject(&res, TRUE);
01149 if (status==NULL || U_FAILURE(*status)) {
01150 return NULL;
01151 }
01152 if(resB == NULL) {
01153 *status = U_ILLEGAL_ARGUMENT_ERROR;
01154 return NULL;
01155 }
01156 ures_getByKey(resB, resourceTag, &res, status);
01157 if(U_SUCCESS(*status)) {
01158 int32_t len = 0;
01159 const UChar *r = ures_getStringByKey(&res, itemTag, &len, status);
01160 ures_close(&res);
01161 return r;
01162 } else {
01163 return NULL;
01164 }
01165 }
01166
01171 U_CAPI int32_t ures_countArrayItems(const UResourceBundle* resourceBundle,
01172 const char* resourceKey,
01173 UErrorCode* status)
01174 {
01175 UResourceBundle resData;
01176 ures_setIsStackObject(&resData, TRUE);
01177 if (status==NULL || U_FAILURE(*status)) {
01178 return 0;
01179 }
01180 if(resourceBundle == NULL) {
01181 *status = U_ILLEGAL_ARGUMENT_ERROR;
01182 return 0;
01183 }
01184 ures_getByKey(resourceBundle, resourceKey, &resData, status);
01185
01186 if(resData.fResData.data != NULL) {
01187 int32_t result = res_countArrayItems(&resData.fResData, resData.fRes);
01188 ures_close(&resData);
01189 return result;
01190 } else {
01191 *status = U_MISSING_RESOURCE_ERROR;
01192 ures_close(&resData);
01193 return 0;
01194 }
01195 }
01196
01197 U_CAPI void ures_close(UResourceBundle* resB)
01198 {
01199 UErrorCode status = U_ZERO_ERROR;
01200 if(resB != NULL) {
01201 if(resB->fData != NULL) {
01202 entryClose(resB->fData);
01203 }
01204
01205
01206
01207
01208
01209 if(resB->fVersion != NULL) {
01210 uprv_free(resB->fVersion);
01211 }
01212
01213 if(ures_isStackObject(resB, &status) == FALSE) {
01214 uprv_free(resB);
01215 }
01216 }
01217 }
01218
01219 U_CAPI const char* ures_getVersionNumber(const UResourceBundle* resourceBundle)
01220 {
01221 if (!resourceBundle) return NULL;
01222
01223 if(resourceBundle->fVersion == NULL) {
01224
01225
01226
01227 UErrorCode status = U_ZERO_ERROR;
01228 int32_t minor_len = 0;
01229 int32_t len;
01230
01231 const UChar* minor_version = ures_getStringByKey(resourceBundle, kVersionTag, &minor_len, &status);
01232
01233
01234
01235
01236
01237
01238 len = (minor_len > 0) ? minor_len : 1;
01239
01240
01241
01242
01243
01244 ((UResourceBundle *)resourceBundle)->fVersion = (char *)uprv_malloc(1 + len);
01245
01246 if(minor_len > 0) {
01247 u_UCharsToChars(minor_version, resourceBundle->fVersion , minor_len);
01248 resourceBundle->fVersion[len] = '\0';
01249 }
01250 else {
01251 uprv_strcat(resourceBundle->fVersion, kDefaultMinorVersion);
01252 }
01253 }
01254
01255 return resourceBundle->fVersion;
01256 }
01257
01258 U_CAPI void U_EXPORT2 ures_getVersion(const UResourceBundle* resB, UVersionInfo versionInfo) {
01259 if (!resB) return;
01260
01261 u_versionFromString(versionInfo, ures_getVersionNumber(resB));
01262 }
01263
01269 U_CAPI const char* ures_getLocale(const UResourceBundle* resourceBundle, UErrorCode* status)
01270 {
01271 if (status==NULL || U_FAILURE(*status)) {
01272 return NULL;
01273 }
01274 if (!resourceBundle)
01275 {
01276 *status = U_ILLEGAL_ARGUMENT_ERROR;
01277 return NULL;
01278 }
01279 return ures_getName(resourceBundle);
01280 }
01281
01282
01283