| Index: source/common/uresbund.cpp
|
| diff --git a/source/common/uresbund.cpp b/source/common/uresbund.cpp
|
| index e74afb8a483db2ed251c39a82de835ca216901f4..b2d071a09f93835b9f5a3d0fd4ce69e738b53993 100644
|
| --- a/source/common/uresbund.cpp
|
| +++ b/source/common/uresbund.cpp
|
| @@ -1882,6 +1882,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;
|
|
|