X-Git-Url: https://git.saurik.com/apple/icu.git/blobdiff_plain/b331163bffd790ced0e88b73f44f86d49ccc48a5..ef6cf650f4a75c3f97de06b51fa104f2069b9ea2:/icuSources/common/uresbund.cpp diff --git a/icuSources/common/uresbund.cpp b/icuSources/common/uresbund.cpp index b80c2c25..62460f8e 100644 --- a/icuSources/common/uresbund.cpp +++ b/icuSources/common/uresbund.cpp @@ -1,10 +1,10 @@ /* ****************************************************************************** -* Copyright (C) 1997-2015, International Business Machines Corporation and +* Copyright (C) 1997-2016, International Business Machines Corporation and * others. All Rights Reserved. ****************************************************************************** * -* File URESBUND.C +* File uresbund.cpp * * Modification History: * @@ -377,6 +377,7 @@ static UResourceDataEntry *init_entry(const char *localeID, const char *path, UE const int32_t *poolIndexes = r->fPool->fData.pRoot + 1; if(r->fData.pRoot[1 + URES_INDEX_POOL_CHECKSUM] == poolIndexes[URES_INDEX_POOL_CHECKSUM]) { r->fData.poolBundleKeys = (const char *)(poolIndexes + (poolIndexes[URES_INDEX_LENGTH] & 0xff)); + r->fData.poolBundleStrings = r->fPool->fData.p16BitUnits; } else { r->fBogus = *status = U_INVALID_FORMAT_ERROR; } @@ -1484,7 +1485,8 @@ U_CAPI const UChar* U_EXPORT2 ures_getNextString(UResourceBundle *resB, int32_t* case URES_BINARY: case URES_INT_VECTOR: *status = U_RESOURCE_TYPE_MISMATCH; - default: /*fall through*/ + U_FALLTHROUGH; + default: return NULL; } } @@ -1881,6 +1883,121 @@ ures_getByKeyWithFallback(const UResourceBundle *resB, return fillIn; } +namespace { + +void getAllContainerItemsWithFallback( + const UResourceBundle *bundle, ResourceDataValue &value, + ResourceArraySink *arraySink, ResourceTableSink *tableSink, + UErrorCode &errorCode) { + if (U_FAILURE(errorCode)) { return; } + // We recursively enumerate child-first, + // only storing parent items in the absence of child items. + // We store a placeholder value for the no-fallback/no-inheritance marker + // to prevent a parent item from being stored. + // + // It would be possible to recursively enumerate parent-first, + // overriding parent items with child items. + // When we see the no-fallback/no-inheritance marker, + // then we would remove the parent's item. + // We would deserialize parent values even though they are overridden in a child bundle. + UResType expectedType = arraySink != NULL ? URES_ARRAY : URES_TABLE; + if (ures_getType(bundle) == expectedType) { + value.pResData = &bundle->fResData; + if (arraySink != NULL) { + ures_getAllArrayItems(&bundle->fResData, bundle->fRes, value, *arraySink, errorCode); + } else /* tableSink != NULL */ { + ures_getAllTableItems(&bundle->fResData, bundle->fRes, value, *tableSink, errorCode); + } + } + UResourceDataEntry *entry = bundle->fData->fParent; + if (entry != NULL && U_SUCCESS(entry->fBogus)) { + // We might try to query the sink whether + // any fallback from the parent bundle is still possible. + + // Turn the parent UResourceDataEntry into a UResourceBundle, + // much like in ures_openWithType(). + // TODO: See if we can refactor ures_getByKeyWithFallback() + // and pull out an inner function that takes and returns a UResourceDataEntry + // so that we need not create UResourceBundle objects. + UResourceBundle parentBundle; + ures_initStackObject(&parentBundle); + parentBundle.fTopLevelData = parentBundle.fData = entry; + // TODO: What is the difference between bundle fData and fTopLevelData? + uprv_memcpy(&parentBundle.fResData, &entry->fData, sizeof(ResourceData)); + // TODO: Try to replace bundle.fResData with just using bundle.fData->fData. + parentBundle.fHasFallback = !parentBundle.fResData.noFallback; + parentBundle.fIsTopLevel = TRUE; + parentBundle.fRes = parentBundle.fResData.rootRes; + parentBundle.fSize = res_countArrayItems(&(parentBundle.fResData), parentBundle.fRes); + parentBundle.fIndex = -1; + entryIncrease(entry); + + // Look up the container item in the parent bundle. + UResourceBundle containerBundle; + ures_initStackObject(&containerBundle); + const UResourceBundle *rb; + if (bundle->fResPath == NULL || *bundle->fResPath == 0) { + rb = &parentBundle; + } else { + rb = ures_getByKeyWithFallback(&parentBundle, bundle->fResPath, + &containerBundle, &errorCode); + } + if (U_SUCCESS(errorCode) && ures_getType(rb) == expectedType) { + getAllContainerItemsWithFallback(rb, value, + arraySink, tableSink, errorCode); + } + ures_close(&containerBundle); + ures_close(&parentBundle); + } +} + +void getAllContainerItemsWithFallback( + const UResourceBundle *bundle, const char *path, + ResourceArraySink *arraySink, ResourceTableSink *tableSink, + UErrorCode &errorCode) { + if (U_FAILURE(errorCode)) { return; } + if (path == NULL) { + errorCode = U_ILLEGAL_ARGUMENT_ERROR; + return; + } + UResourceBundle stackBundle; + ures_initStackObject(&stackBundle); + const UResourceBundle *rb; + if (*path == 0) { + // empty path + rb = bundle; + } else { + rb = ures_getByKeyWithFallback(bundle, path, &stackBundle, &errorCode); + if (U_FAILURE(errorCode)) { + ures_close(&stackBundle); + return; + } + } + UResType expectedType = arraySink != NULL ? URES_ARRAY : URES_TABLE; + if (ures_getType(rb) != expectedType) { + errorCode = U_RESOURCE_TYPE_MISMATCH; + ures_close(&stackBundle); + return; + } + // Get all table items with fallback. + ResourceDataValue value; + getAllContainerItemsWithFallback(rb, value, arraySink, tableSink, errorCode); + ures_close(&stackBundle); +} + +} // namespace + +U_CAPI void U_EXPORT2 +ures_getAllArrayItemsWithFallback(const UResourceBundle *bundle, const char *path, + ResourceArraySink &sink, UErrorCode &errorCode) { + getAllContainerItemsWithFallback(bundle, path, &sink, NULL, errorCode); +} + +U_CAPI void U_EXPORT2 +ures_getAllTableItemsWithFallback(const UResourceBundle *bundle, const char *path, + ResourceTableSink &sink, UErrorCode &errorCode) { + getAllContainerItemsWithFallback(bundle, path, NULL, &sink, errorCode); +} U_CAPI UResourceBundle* U_EXPORT2 ures_getByKey(const UResourceBundle *resB, const char* inKey, UResourceBundle *fillIn, UErrorCode *status) { Resource res = RES_BOGUS;