summaryrefslogtreecommitdiff
path: root/deps/icu-small/source/common/uresbund.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'deps/icu-small/source/common/uresbund.cpp')
-rw-r--r--deps/icu-small/source/common/uresbund.cpp278
1 files changed, 155 insertions, 123 deletions
diff --git a/deps/icu-small/source/common/uresbund.cpp b/deps/icu-small/source/common/uresbund.cpp
index c9f2c860da..3a9b4340bb 100644
--- a/deps/icu-small/source/common/uresbund.cpp
+++ b/deps/icu-small/source/common/uresbund.cpp
@@ -31,6 +31,7 @@
#include "ucln_cmn.h"
#include "cmemory.h"
#include "cstring.h"
+#include "mutex.h"
#include "uhash.h"
#include "unicode/uenum.h"
#include "uenumimp.h"
@@ -38,6 +39,7 @@
#include "umutex.h"
#include "putilimp.h"
#include "uassert.h"
+#include "uresdata.h"
using namespace icu;
@@ -47,12 +49,9 @@ TODO: This cache should probably be removed when the deprecated code is
completely removed.
*/
static UHashtable *cache = NULL;
-static icu::UInitOnce gCacheInitOnce;
+static icu::UInitOnce gCacheInitOnce = U_INITONCE_INITIALIZER;
-static UMutex *resbMutex() {
- static UMutex m = U_MUTEX_INITIALIZER;
- return &m;
-}
+static UMutex resbMutex;
/* INTERNAL: hashes an entry */
static int32_t U_CALLCONV hashEntry(const UHashTok parm) {
@@ -96,13 +95,12 @@ static UBool chopLocale(char *name) {
* Internal function
*/
static void entryIncrease(UResourceDataEntry *entry) {
- umtx_lock(resbMutex());
+ Mutex lock(&resbMutex);
entry->fCountExisting++;
while(entry->fParent != NULL) {
entry = entry->fParent;
entry->fCountExisting++;
}
- umtx_unlock(resbMutex());
}
/**
@@ -184,9 +182,8 @@ static int32_t ures_flushCache()
/*if shared data hasn't even been lazy evaluated yet
* return 0
*/
- umtx_lock(resbMutex());
+ Mutex lock(&resbMutex);
if (cache == NULL) {
- umtx_unlock(resbMutex());
return 0;
}
@@ -218,7 +215,6 @@ static int32_t ures_flushCache()
* got decremented by free_entry().
*/
} while(deletedMore);
- umtx_unlock(resbMutex());
return rbDeletedNum;
}
@@ -232,9 +228,8 @@ U_CAPI UBool U_EXPORT2 ures_dumpCacheContents(void) {
const UHashElement *e;
UResourceDataEntry *resB;
- umtx_lock(resbMutex());
+ Mutex lock(&resbMutex);
if (cache == NULL) {
- umtx_unlock(resbMutex());
fprintf(stderr,"%s:%d: RB Cache is NULL.\n", __FILE__, __LINE__);
return FALSE;
}
@@ -253,9 +248,6 @@ U_CAPI UBool U_EXPORT2 ures_dumpCacheContents(void) {
}
fprintf(stderr,"%s:%d: RB Cache still contains %d items.\n", __FILE__, __LINE__, uhash_count(cache));
-
- umtx_unlock(resbMutex());
-
return cacheNotEmpty;
}
@@ -401,7 +393,8 @@ static UResourceDataEntry *init_entry(const char *localeID, const char *path, UE
/* We'll try to get alias string from the bundle */
aliasres = res_getResource(&(r->fData), "%%ALIAS");
if (aliasres != RES_BOGUS) {
- const UChar *alias = res_getString(&(r->fData), aliasres, &aliasLen);
+ // No tracing: called during initial data loading
+ const UChar *alias = res_getStringNoTrace(&(r->fData), aliasres, &aliasLen);
if(alias != NULL && aliasLen > 0) { /* if there is actual alias - unload and load new data */
u_UCharsToChars(alias, aliasName, aliasLen+1);
r->fAlias = init_entry(aliasName, path, status);
@@ -542,7 +535,8 @@ loadParentsExceptRoot(UResourceDataEntry *&t1,
Resource parentRes = res_getResource(&t1->fData, "%%Parent");
if (parentRes != RES_BOGUS) { // An explicit parent was found.
int32_t parentLocaleLen = 0;
- const UChar *parentLocaleName = res_getString(&(t1->fData), parentRes, &parentLocaleLen);
+ // No tracing: called during initial data loading
+ const UChar *parentLocaleName = res_getStringNoTrace(&(t1->fData), parentRes, &parentLocaleLen);
if(parentLocaleName != NULL && 0 < parentLocaleLen && parentLocaleLen < nameCapacity) {
u_UCharsToChars(parentLocaleName, name, parentLocaleLen + 1);
if (uprv_strcmp(name, kRootLocaleName) == 0) {
@@ -666,107 +660,105 @@ static UResourceDataEntry *entryOpen(const char* path, const char* localeID,
}
}
- umtx_lock(resbMutex());
- { /* umtx_lock */
- /* We're going to skip all the locales that do not have any data */
- r = findFirstExisting(path, name, &isRoot, &hasChopped, &isDefault, &intStatus);
+ Mutex lock(&resbMutex); // Lock resbMutex until the end of this function.
+
+ /* We're going to skip all the locales that do not have any data */
+ r = findFirstExisting(path, name, &isRoot, &hasChopped, &isDefault, &intStatus);
+
+ // If we failed due to out-of-memory, report the failure and exit early.
+ if (intStatus == U_MEMORY_ALLOCATION_ERROR) {
+ *status = intStatus;
+ goto finish;
+ }
+
+ if(r != NULL) { /* if there is one real locale, we can look for parents. */
+ t1 = r;
+ hasRealData = TRUE;
+ if ( usingUSRData ) { /* This code inserts user override data into the inheritance chain */
+ UErrorCode usrStatus = U_ZERO_ERROR;
+ UResourceDataEntry *u1 = init_entry(t1->fName, usrDataPath, &usrStatus);
+ // If we failed due to out-of-memory, report the failure and exit early.
+ if (intStatus == U_MEMORY_ALLOCATION_ERROR) {
+ *status = intStatus;
+ goto finish;
+ }
+ if ( u1 != NULL ) {
+ if(u1->fBogus == U_ZERO_ERROR) {
+ u1->fParent = t1;
+ r = u1;
+ } else {
+ /* the USR override data wasn't found, set it to be deleted */
+ u1->fCountExisting = 0;
+ }
+ }
+ }
+ if (hasChopped && !isRoot) {
+ if (!loadParentsExceptRoot(t1, name, UPRV_LENGTHOF(name), usingUSRData, usrDataPath, status)) {
+ goto finish;
+ }
+ }
+ }
+ /* we could have reached this point without having any real data */
+ /* if that is the case, we need to chain in the default locale */
+ if(r==NULL && openType == URES_OPEN_LOCALE_DEFAULT_ROOT && !isDefault && !isRoot) {
+ /* insert default locale */
+ uprv_strcpy(name, uloc_getDefault());
+ r = findFirstExisting(path, name, &isRoot, &hasChopped, &isDefault, &intStatus);
// If we failed due to out-of-memory, report the failure and exit early.
if (intStatus == U_MEMORY_ALLOCATION_ERROR) {
*status = intStatus;
- goto finishUnlock;
+ goto finish;
}
-
- if(r != NULL) { /* if there is one real locale, we can look for parents. */
+ intStatus = U_USING_DEFAULT_WARNING;
+ if(r != NULL) { /* the default locale exists */
t1 = r;
hasRealData = TRUE;
- if ( usingUSRData ) { /* This code inserts user override data into the inheritance chain */
- UErrorCode usrStatus = U_ZERO_ERROR;
- UResourceDataEntry *u1 = init_entry(t1->fName, usrDataPath, &usrStatus);
- // If we failed due to out-of-memory, report the failure and exit early.
- if (intStatus == U_MEMORY_ALLOCATION_ERROR) {
- *status = intStatus;
- goto finishUnlock;
- }
- if ( u1 != NULL ) {
- if(u1->fBogus == U_ZERO_ERROR) {
- u1->fParent = t1;
- r = u1;
- } else {
- /* the USR override data wasn't found, set it to be deleted */
- u1->fCountExisting = 0;
- }
- }
- }
+ isDefault = TRUE;
+ // TODO: Why not if (usingUSRData) { ... } like in the non-default-locale code path?
if (hasChopped && !isRoot) {
if (!loadParentsExceptRoot(t1, name, UPRV_LENGTHOF(name), usingUSRData, usrDataPath, status)) {
- goto finishUnlock;
+ goto finish;
}
}
}
+ }
- /* we could have reached this point without having any real data */
- /* if that is the case, we need to chain in the default locale */
- if(r==NULL && openType == URES_OPEN_LOCALE_DEFAULT_ROOT && !isDefault && !isRoot) {
- /* insert default locale */
- uprv_strcpy(name, uloc_getDefault());
- r = findFirstExisting(path, name, &isRoot, &hasChopped, &isDefault, &intStatus);
- // If we failed due to out-of-memory, report the failure and exit early.
- if (intStatus == U_MEMORY_ALLOCATION_ERROR) {
- *status = intStatus;
- goto finishUnlock;
- }
+ /* we could still have r == NULL at this point - maybe even default locale is not */
+ /* present */
+ if(r == NULL) {
+ uprv_strcpy(name, kRootLocaleName);
+ r = findFirstExisting(path, name, &isRoot, &hasChopped, &isDefault, &intStatus);
+ // If we failed due to out-of-memory, report the failure and exit early.
+ if (intStatus == U_MEMORY_ALLOCATION_ERROR) {
+ *status = intStatus;
+ goto finish;
+ }
+ if(r != NULL) {
+ t1 = r;
intStatus = U_USING_DEFAULT_WARNING;
- if(r != NULL) { /* the default locale exists */
- t1 = r;
- hasRealData = TRUE;
- isDefault = TRUE;
- // TODO: Why not if (usingUSRData) { ... } like in the non-default-locale code path?
- if (hasChopped && !isRoot) {
- if (!loadParentsExceptRoot(t1, name, UPRV_LENGTHOF(name), usingUSRData, usrDataPath, status)) {
- goto finishUnlock;
- }
- }
- }
+ hasRealData = TRUE;
+ } else { /* we don't even have the root locale */
+ *status = U_MISSING_RESOURCE_ERROR;
+ goto finish;
}
-
- /* we could still have r == NULL at this point - maybe even default locale is not */
- /* present */
- if(r == NULL) {
- uprv_strcpy(name, kRootLocaleName);
- r = findFirstExisting(path, name, &isRoot, &hasChopped, &isDefault, &intStatus);
- // If we failed due to out-of-memory, report the failure and exit early.
- if (intStatus == U_MEMORY_ALLOCATION_ERROR) {
- *status = intStatus;
- goto finishUnlock;
- }
- if(r != NULL) {
- t1 = r;
- intStatus = U_USING_DEFAULT_WARNING;
- hasRealData = TRUE;
- } else { /* we don't even have the root locale */
- *status = U_MISSING_RESOURCE_ERROR;
- goto finishUnlock;
- }
- } else if(!isRoot && uprv_strcmp(t1->fName, kRootLocaleName) != 0 &&
- t1->fParent == NULL && !r->fData.noFallback) {
- if (!insertRootBundle(t1, status)) {
- goto finishUnlock;
- }
- if(!hasRealData) {
- r->fBogus = U_USING_DEFAULT_WARNING;
- }
+ } else if(!isRoot && uprv_strcmp(t1->fName, kRootLocaleName) != 0 &&
+ t1->fParent == NULL && !r->fData.noFallback) {
+ if (!insertRootBundle(t1, status)) {
+ goto finish;
}
-
- // TODO: Does this ever loop?
- while(r != NULL && !isRoot && t1->fParent != NULL) {
- t1->fParent->fCountExisting++;
- t1 = t1->fParent;
+ if(!hasRealData) {
+ r->fBogus = U_USING_DEFAULT_WARNING;
}
- } /* umtx_lock */
-finishUnlock:
- umtx_unlock(resbMutex());
+ }
+ // TODO: Does this ever loop?
+ while(r != NULL && !isRoot && t1->fParent != NULL) {
+ t1->fParent->fCountExisting++;
+ t1 = t1->fParent;
+ }
+
+finish:
if(U_SUCCESS(*status)) {
if(intStatus != U_ZERO_ERROR) {
*status = intStatus;
@@ -790,7 +782,7 @@ entryOpenDirect(const char* path, const char* localeID, UErrorCode* status) {
return NULL;
}
- umtx_lock(resbMutex());
+ Mutex lock(&resbMutex);
// findFirstExisting() without fallbacks.
UResourceDataEntry *r = init_entry(localeID, path, status);
if(U_SUCCESS(*status)) {
@@ -828,7 +820,6 @@ entryOpenDirect(const char* path, const char* localeID, UErrorCode* status) {
t1 = t1->fParent;
}
}
- umtx_unlock(resbMutex());
return r;
}
@@ -871,9 +862,8 @@ static void entryCloseInt(UResourceDataEntry *resB) {
*/
static void entryClose(UResourceDataEntry *resB) {
- umtx_lock(resbMutex());
+ Mutex lock(&resbMutex);
entryCloseInt(resB);
- umtx_unlock(resbMutex());
}
/*
@@ -1177,6 +1167,7 @@ static UResourceBundle *init_resb_result(const ResourceData *rdata, Resource r,
if(mainRes != result) {
ures_close(mainRes);
}
+ ResourceTracer(resB).maybeTrace("getalias");
return result;
}
} else {
@@ -1256,6 +1247,7 @@ static UResourceBundle *init_resb_result(const ResourceData *rdata, Resource r,
/*resB->fParent = parent->fRes;*/
uprv_memmove(&resB->fResData, rdata, sizeof(ResourceData));
resB->fSize = res_countArrayItems(&(resB->fResData), resB->fRes);
+ ResourceTracer(resB).trace("get");
return resB;
}
@@ -1304,7 +1296,7 @@ U_CAPI const UChar* U_EXPORT2 ures_getString(const UResourceBundle* resB, int32_
*status = U_ILLEGAL_ARGUMENT_ERROR;
return NULL;
}
- s = res_getString(&(resB->fResData), resB->fRes, len);
+ s = res_getString({resB}, &(resB->fResData), resB->fRes, len);
if (s == NULL) {
*status = U_RESOURCE_TYPE_MISMATCH;
}
@@ -1393,7 +1385,7 @@ U_CAPI const uint8_t* U_EXPORT2 ures_getBinary(const UResourceBundle* resB, int3
*status = U_ILLEGAL_ARGUMENT_ERROR;
return NULL;
}
- p = res_getBinary(&(resB->fResData), resB->fRes, len);
+ p = res_getBinary({resB}, &(resB->fResData), resB->fRes, len);
if (p == NULL) {
*status = U_RESOURCE_TYPE_MISMATCH;
}
@@ -1410,7 +1402,7 @@ U_CAPI const int32_t* U_EXPORT2 ures_getIntVector(const UResourceBundle* resB, i
*status = U_ILLEGAL_ARGUMENT_ERROR;
return NULL;
}
- p = res_getIntVector(&(resB->fResData), resB->fRes, len);
+ p = res_getIntVector({resB}, &(resB->fResData), resB->fRes, len);
if (p == NULL) {
*status = U_RESOURCE_TYPE_MISMATCH;
}
@@ -1431,7 +1423,7 @@ U_CAPI int32_t U_EXPORT2 ures_getInt(const UResourceBundle* resB, UErrorCode *st
*status = U_RESOURCE_TYPE_MISMATCH;
return 0xffffffff;
}
- return RES_GET_INT(resB->fRes);
+ return res_getInt({resB}, resB->fRes);
}
U_CAPI uint32_t U_EXPORT2 ures_getUInt(const UResourceBundle* resB, UErrorCode *status) {
@@ -1446,7 +1438,7 @@ U_CAPI uint32_t U_EXPORT2 ures_getUInt(const UResourceBundle* resB, UErrorCode *
*status = U_RESOURCE_TYPE_MISMATCH;
return 0xffffffff;
}
- return RES_GET_UINT(resB->fRes);
+ return res_getUInt({resB}, resB->fRes);
}
U_CAPI UResType U_EXPORT2 ures_getType(const UResourceBundle *resB) {
@@ -1457,10 +1449,18 @@ U_CAPI UResType U_EXPORT2 ures_getType(const UResourceBundle *resB) {
}
U_CAPI const char * U_EXPORT2 ures_getKey(const UResourceBundle *resB) {
+ //
+ // TODO: Trace ures_getKey? I guess not usually.
+ //
+ // We usually get the key string to decide whether we want the value, or to
+ // make a key-value pair. Tracing the value should suffice.
+ //
+ // However, I believe we have some data (e.g., in res_index) where the key
+ // strings are the data. Tracing the enclosing table should suffice.
+ //
if(resB == NULL) {
return NULL;
}
-
return(resB->fKey);
}
@@ -1480,7 +1480,7 @@ static const UChar* ures_getStringWithAlias(const UResourceBundle *resB, Resourc
ures_close(tempRes);
return result;
} else {
- return res_getString(&(resB->fResData), r, len);
+ return res_getString({resB, sIndex}, &(resB->fResData), r, len);
}
}
@@ -1516,7 +1516,7 @@ U_CAPI const UChar* U_EXPORT2 ures_getNextString(UResourceBundle *resB, int32_t*
switch(RES_GET_TYPE(resB->fRes)) {
case URES_STRING:
case URES_STRING_V2:
- return res_getString(&(resB->fResData), resB->fRes, len);
+ return res_getString({resB}, &(resB->fResData), resB->fRes, len);
case URES_TABLE:
case URES_TABLE16:
case URES_TABLE32:
@@ -1661,7 +1661,7 @@ U_CAPI const UChar* U_EXPORT2 ures_getStringByIndex(const UResourceBundle *resB,
switch(RES_GET_TYPE(resB->fRes)) {
case URES_STRING:
case URES_STRING_V2:
- return res_getString(&(resB->fResData), resB->fRes, len);
+ return res_getString({resB}, &(resB->fResData), resB->fRes, len);
case URES_TABLE:
case URES_TABLE16:
case URES_TABLE32:
@@ -1953,10 +1953,10 @@ void getAllItemsWithFallback(
// When the sink sees the no-fallback/no-inheritance marker,
// then it would remove the parent's item.
// We would deserialize parent values even though they are overridden in a child bundle.
- value.pResData = &bundle->fResData;
+ value.setData(&bundle->fResData);
UResourceDataEntry *parentEntry = bundle->fData->fParent;
UBool hasParent = parentEntry != NULL && U_SUCCESS(parentEntry->fBogus);
- value.setResource(bundle->fRes);
+ value.setResource(bundle->fRes, ResourceTracer(bundle));
sink.put(bundle->fKey, value, !hasParent, errorCode);
if (hasParent) {
// We might try to query the sink whether
@@ -2001,31 +2001,60 @@ void getAllItemsWithFallback(
} // namespace
+// Requires a ResourceDataValue fill-in, so that we need not cast from a ResourceValue.
+// Unfortunately, the caller must know which subclass to make and pass in.
+// Alternatively, we could make it as polymorphic as in Java by
+// returning a ResourceValue pointer (possibly wrapped into a LocalPointer)
+// that the caller then owns.
+//
+// Also requires a UResourceBundle fill-in, so that the value's ResourceTracer
+// can point to a non-local bundle.
+// Without tracing, the child bundle could be a function-local object.
+U_CAPI void U_EXPORT2
+ures_getValueWithFallback(const UResourceBundle *bundle, const char *path,
+ UResourceBundle *tempFillIn,
+ ResourceDataValue &value, UErrorCode &errorCode) {
+ if (U_FAILURE(errorCode)) { return; }
+ if (path == nullptr) {
+ errorCode = U_ILLEGAL_ARGUMENT_ERROR;
+ return;
+ }
+ const UResourceBundle *rb;
+ if (*path == 0) {
+ // empty path
+ rb = bundle;
+ } else {
+ rb = ures_getByKeyWithFallback(bundle, path, tempFillIn, &errorCode);
+ if (U_FAILURE(errorCode)) {
+ return;
+ }
+ }
+ value.setData(&rb->fResData);
+ value.setResource(rb->fRes, ResourceTracer(rb));
+}
+
U_CAPI void U_EXPORT2
ures_getAllItemsWithFallback(const UResourceBundle *bundle, const char *path,
icu::ResourceSink &sink, UErrorCode &errorCode) {
if (U_FAILURE(errorCode)) { return; }
- if (path == NULL) {
+ if (path == nullptr) {
errorCode = U_ILLEGAL_ARGUMENT_ERROR;
return;
}
- UResourceBundle stackBundle;
- ures_initStackObject(&stackBundle);
+ StackUResourceBundle stackBundle;
const UResourceBundle *rb;
if (*path == 0) {
// empty path
rb = bundle;
} else {
- rb = ures_getByKeyWithFallback(bundle, path, &stackBundle, &errorCode);
+ rb = ures_getByKeyWithFallback(bundle, path, stackBundle.getAlias(), &errorCode);
if (U_FAILURE(errorCode)) {
- ures_close(&stackBundle);
return;
}
}
// Get all table items with fallback.
ResourceDataValue value;
getAllItemsWithFallback(rb, value, sink, errorCode);
- ures_close(&stackBundle);
}
U_CAPI UResourceBundle* U_EXPORT2 ures_getByKey(const UResourceBundle *resB, const char* inKey, UResourceBundle *fillIn, UErrorCode *status) {
@@ -2108,7 +2137,7 @@ U_CAPI const UChar* U_EXPORT2 ures_getStringByKey(const UResourceBundle *resB, c
switch (RES_GET_TYPE(res)) {
case URES_STRING:
case URES_STRING_V2:
- return res_getString(rd, res, len);
+ return res_getString({resB, key}, rd, res, len);
case URES_ALIAS:
{
const UChar* result = 0;
@@ -2130,7 +2159,7 @@ U_CAPI const UChar* U_EXPORT2 ures_getStringByKey(const UResourceBundle *resB, c
switch (RES_GET_TYPE(res)) {
case URES_STRING:
case URES_STRING_V2:
- return res_getString(&(resB->fResData), res, len);
+ return res_getString({resB, key}, &(resB->fResData), res, len);
case URES_ALIAS:
{
const UChar* result = 0;
@@ -2151,6 +2180,7 @@ U_CAPI const UChar* U_EXPORT2 ures_getStringByKey(const UResourceBundle *resB, c
/* here should go a first attempt to locate the key using index table */
const ResourceData *rd = getFallbackData(resB, &key, &realData, &res, status);
if(U_SUCCESS(*status)) {
+ // TODO: Tracing
return res_getString(rd, res, len);
} else {
*status = U_MISSING_RESOURCE_ERROR;
@@ -2296,6 +2326,8 @@ ures_openWithType(UResourceBundle *r, const char* path, const char* localeID,
r->fSize = res_countArrayItems(&(r->fResData), r->fRes);
r->fIndex = -1;
+ ResourceTracer(r).traceOpen();
+
return r;
}