]> git.saurik.com Git - apple/icu.git/blobdiff - icuSources/common/uresbund.cpp
ICU-57131.0.1.tar.gz
[apple/icu.git] / icuSources / common / uresbund.cpp
index b80c2c252c0d1ba814f848a363711f5eb5ad564d..62460f8e20da03ea990c553c60da5b3b53ebd489 100644 (file)
@@ -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;