]> git.saurik.com Git - apple/icu.git/blobdiff - icuSources/common/uresbund.c
ICU-461.18.tar.gz
[apple/icu.git] / icuSources / common / uresbund.c
index c3a7f0cf73eecfdad9a8f99cd86cc963402b1c13..40c32861fc776d61c02c478b8403c23534c88eac 100644 (file)
@@ -1,6 +1,6 @@
 /*
 ******************************************************************************
-* Copyright (C) 1997-2004, International Business Machines Corporation and   *
+* Copyright (C) 1997-2010, International Business Machines Corporation and   *
 * others. All Rights Reserved.                                               *
 ******************************************************************************
 *
@@ -45,7 +45,7 @@ static UHashtable *cache = NULL;
 static UMTX resbMutex = NULL;
 
 /* INTERNAL: hashes an entry  */
-static int32_t U_EXPORT2 U_CALLCONV hashEntry(const UHashTok parm) {
+static int32_t U_CALLCONV hashEntry(const UHashTok parm) {
     UResourceDataEntry *b = (UResourceDataEntry *)parm.pointer;
     UHashTok namekey, pathkey;
     namekey.pointer = b->fName;
@@ -54,7 +54,7 @@ static int32_t U_EXPORT2 U_CALLCONV hashEntry(const UHashTok parm) {
 }
 
 /* INTERNAL: compares two entries */
-static UBool U_EXPORT2 U_CALLCONV compareEntries(const UHashTok p1, const UHashTok p2) {
+static UBool U_CALLCONV compareEntries(const UHashTok p1, const UHashTok p2) {
     UResourceDataEntry *b1 = (UResourceDataEntry *)p1.pointer;
     UResourceDataEntry *b2 = (UResourceDataEntry *)p2.pointer;
     UHashTok name1, name2, path1, path2;
@@ -62,7 +62,7 @@ static UBool U_EXPORT2 U_CALLCONV compareEntries(const UHashTok p1, const UHashT
     name2.pointer = b2->fName;
     path1.pointer = b1->fPath;
     path2.pointer = b2->fPath;
-    return (UBool)(uhash_compareChars(name1, name2) & 
+    return (UBool)(uhash_compareChars(name1, name2) &&
         uhash_compareChars(path1, path2));
 }
 
@@ -139,14 +139,37 @@ static const ResourceData *getFallbackData(const UResourceBundle* resBundle, con
     }
 }
 
+static void
+free_entry(UResourceDataEntry *entry) {
+    UResourceDataEntry *alias;
+    res_unload(&(entry->fData));
+    if(entry->fName != NULL && entry->fName != entry->fNameBuffer) {
+        uprv_free(entry->fName);
+    }
+    if(entry->fPath != NULL) {
+        uprv_free(entry->fPath);
+    }
+    if(entry->fPool != NULL) {
+        --entry->fPool->fCountExisting;
+    }
+    alias = entry->fAlias;
+    if(alias != NULL) {
+        while(alias->fAlias != NULL) {
+            alias = alias->fAlias;
+        }
+        --alias->fCountExisting;
+    }
+    uprv_free(entry);
+}
+
 /* Works just like ucnv_flushCache() */
-/* TODO: figure out why fCountExisting may not go to zero. Do not make this function public yet. */
 static int32_t ures_flushCache()
 {
-    UResourceDataEntry *resB = NULL;
-    int32_t pos = -1;
+    UResourceDataEntry *resB;
+    int32_t pos;
     int32_t rbDeletedNum = 0;
     const UHashElement *e;
+    UBool deletedMore;
 
     /*if shared data hasn't even been lazy evaluated yet
     * return 0
@@ -157,41 +180,77 @@ static int32_t ures_flushCache()
         return 0;
     }
 
-    /*creates an enumeration to iterate through every element in the table */
-    while ((e = uhash_nextElement(cache, &pos)) != NULL)
-    {
-        resB = (UResourceDataEntry *) e->value.pointer;
-        /* Deletes only if reference counter == 0
-         * Don't worry about the children of this node.
-         * Those will eventually get deleted too, if not already.
-         * Don't worry about the parents of this node.
-         * Those will eventually get deleted too, if not already.
-         */
-        /* DONE: figure out why fCountExisting may not go to zero. Do not make this function public yet. */
-        /* 04/05/2002 [weiv] fCountExisting should now be accurate. If it's not zero, that means that    */
-        /* some resource bundles are still open somewhere. */
-
-        /*U_ASSERT(resB->fCountExisting == 0);*/
-        if (resB->fCountExisting == 0) {
-            rbDeletedNum++;
-            uhash_removeElement(cache, e);
-            if(resB->fBogus == U_ZERO_ERROR) {
-                res_unload(&(resB->fData));
-            }
-            if(resB->fName != NULL) {
-                uprv_free(resB->fName);
-            }
-            if(resB->fPath != NULL) {
-                uprv_free(resB->fPath);
+    do {
+        deletedMore = FALSE;
+        /*creates an enumeration to iterate through every element in the table */
+        pos = -1;
+        while ((e = uhash_nextElement(cache, &pos)) != NULL)
+        {
+            resB = (UResourceDataEntry *) e->value.pointer;
+            /* Deletes only if reference counter == 0
+             * Don't worry about the children of this node.
+             * Those will eventually get deleted too, if not already.
+             * Don't worry about the parents of this node.
+             * Those will eventually get deleted too, if not already.
+             */
+            /* 04/05/2002 [weiv] fCountExisting should now be accurate. If it's not zero, that means that    */
+            /* some resource bundles are still open somewhere. */
+
+            if (resB->fCountExisting == 0) {
+                rbDeletedNum++;
+                deletedMore = TRUE;
+                uhash_removeElement(cache, e);
+                free_entry(resB);
             }
-            uprv_free(resB);
         }
-    }
+        /*
+         * Do it again to catch bundles (aliases, pool bundle) whose fCountExisting
+         * got decremented by free_entry().
+         */
+    } while(deletedMore);
     umtx_unlock(&resbMutex);
 
     return rbDeletedNum;
 }
 
+#ifdef URES_DEBUG
+#include <stdio.h>
+
+U_CAPI UBool U_EXPORT2 ures_dumpCacheContents(void) {
+  UBool cacheNotEmpty = FALSE;
+  int32_t pos = -1;
+  const UHashElement *e;
+  UResourceDataEntry *resB;
+  
+    umtx_lock(&resbMutex);
+    if (cache == NULL) {
+      umtx_unlock(&resbMutex);
+      fprintf(stderr,"%s:%d: RB Cache is NULL.\n", __FILE__, __LINE__);
+      return FALSE;
+    }
+
+    while ((e = uhash_nextElement(cache, &pos)) != NULL) {
+      cacheNotEmpty=TRUE;
+      resB = (UResourceDataEntry *) e->value.pointer;
+      fprintf(stderr,"%s:%d: RB Cache: Entry @0x%p, refcount %d, name %s:%s.  Pool 0x%p, alias 0x%p, parent 0x%p\n",
+              __FILE__, __LINE__,
+              (void*)resB, resB->fCountExisting,
+              resB->fName?resB->fName:"NULL",
+              resB->fPath?resB->fPath:"NULL",
+              (void*)resB->fPool,
+              (void*)resB->fAlias,
+              (void*)resB->fParent);       
+    }
+    
+    fprintf(stderr,"%s:%d: RB Cache still contains %d items.\n", __FILE__, __LINE__, uhash_count(cache));
+
+    umtx_unlock(&resbMutex);
+    
+    return cacheNotEmpty;
+}
+
+#endif
+
 static UBool U_CALLCONV ures_cleanup(void)
 {
     if (cache != NULL) {
@@ -210,11 +269,9 @@ static UBool U_CALLCONV ures_cleanup(void)
 /** INTERNAL: Initializes the cache for resources */
 static void initCache(UErrorCode *status) {
     UBool makeCache = FALSE;
-    umtx_lock(&resbMutex);
-    makeCache = (cache ==  NULL);
-    umtx_unlock(&resbMutex);
+    UMTX_CHECK(&resbMutex, (cache ==  NULL), makeCache);
     if(makeCache) {
-        UHashtable *newCache = uhash_open(hashEntry, compareEntries, status);
+        UHashtable *newCache = uhash_open(hashEntry, compareEntries, NULL, status);
         if (U_FAILURE(*status)) {
             return;
         }
@@ -234,10 +291,16 @@ static void initCache(UErrorCode *status) {
 /** INTERNAL: sets the name (locale) of the resource bundle to given name */
 
 static void setEntryName(UResourceDataEntry *res, char *name, UErrorCode *status) {
-    if(res->fName != NULL) {
+    int32_t len = (int32_t)uprv_strlen(name);
+    if(res->fName != NULL && res->fName != res->fNameBuffer) {
         uprv_free(res->fName);
     }
-    res->fName = (char *)uprv_malloc(sizeof(char)*uprv_strlen(name)+1);
+    if (len < (int32_t)sizeof(res->fNameBuffer)) {
+        res->fName = res->fNameBuffer;
+    }
+    else {
+        res->fName = (char *)uprv_malloc(len+1);
+    }
     if(res->fName == NULL) {
         *status = U_MEMORY_ALLOCATION_ERROR;
     } else {
@@ -245,6 +308,9 @@ static void setEntryName(UResourceDataEntry *res, char *name, UErrorCode *status
     }
 }
 
+static UResourceDataEntry *
+getPoolEntry(const char *path, UErrorCode *status);
+
 /**
  *  INTERNAL: Inits and opens an entry from a data DLL.
  *    CAUTION:  resbMutex must be locked when calling this function.
@@ -252,12 +318,11 @@ static void setEntryName(UResourceDataEntry *res, char *name, UErrorCode *status
 static UResourceDataEntry *init_entry(const char *localeID, const char *path, UErrorCode *status) {
     UResourceDataEntry *r = NULL;
     UResourceDataEntry find;
-    int32_t hashValue;
+    /*int32_t hashValue;*/
     char name[96];
-    const char *myPath = NULL;
     char aliasName[100] = { 0 };
     int32_t aliasLen = 0;
-    UBool isAlias = FALSE;
+    /*UBool isAlias = FALSE;*/
     UHashTok hashkey;
 
     if(U_FAILURE(*status)) {
@@ -267,148 +332,165 @@ static UResourceDataEntry *init_entry(const char *localeID, const char *path, UE
     /* here we try to deduce the right locale name */
     if(localeID == NULL) { /* if localeID is NULL, we're trying to open default locale */
         uprv_strcpy(name, uloc_getDefault());
-    } else if(uprv_strlen(localeID) == 0) { /* if localeID is "" then we try to open root locale */
+    } else if(*localeID == 0) { /* if localeID is "" then we try to open root locale */
         uprv_strcpy(name, kRootLocaleName);
     } else { /* otherwise, we'll open what we're given */
         uprv_strcpy(name, localeID);
     }
 
-    if(path != NULL) { /* if we actually have path, we'll use it */
-      myPath = path;
-    }
-
     find.fName = name;
-    find.fPath = (char *)myPath;
+    find.fPath = (char *)path;
 
     /* calculate the hash value of the entry */
     hashkey.pointer = (void *)&find;
-    hashValue = hashEntry(hashkey);
+    /*hashValue = hashEntry(hashkey);*/
 
     /* check to see if we already have this entry */
     r = (UResourceDataEntry *)uhash_get(cache, &find);
-
-    if(r != NULL) { /* if the entry is already in the hash table */
-        r->fCountExisting++; /* we just increase it's reference count */
-        /* if the resource has a warning */
-        /* we don't want to overwrite a status with no error */
-        if(r->fBogus != U_ZERO_ERROR) {
-          *status = r->fBogus; /* set the returning status */
-        } 
-    } else { /* otherwise, we'll try to construct a new entry */
-        UBool result = FALSE;
-
+    if(r == NULL) {
+        /* if the entry is not yet in the hash table, we'll try to construct a new one */
         r = (UResourceDataEntry *) uprv_malloc(sizeof(UResourceDataEntry));
-
         if(r == NULL) {
             *status = U_MEMORY_ALLOCATION_ERROR;
             return NULL;
         }
-        r->fCountExisting = 1;
 
-        r->fName = NULL;
+        uprv_memset(r, 0, sizeof(UResourceDataEntry));
+        /*r->fHashKey = hashValue;*/
+
         setEntryName(r, name, status);
+        if (U_FAILURE(*status)) {
+            uprv_free(r);
+            return NULL;
+        }
 
-        r->fPath = NULL;
-        if(myPath != NULL && !U_FAILURE(*status)) {
-            r->fPath = (char *)uprv_malloc(sizeof(char)*uprv_strlen(myPath)+1);
+        if(path != NULL) {
+            r->fPath = (char *)uprv_strdup(path);
             if(r->fPath == NULL) {
                 *status = U_MEMORY_ALLOCATION_ERROR;
-            } else {
-                uprv_strcpy(r->fPath, myPath);
+                uprv_free(r);
+                return NULL;
             }
         }
 
-        r->fHashKey = hashValue;
-        r->fParent = NULL;
-        r->fData.data = NULL;
-        r->fData.pRoot = NULL;
-        r->fData.rootRes = 0;
-        r->fBogus = U_ZERO_ERROR;
-        
-        /* this is the acutal loading - returns bool true/false */
-        result = res_load(&(r->fData), r->fPath, r->fName, status);
+        /* this is the actual loading */
+        res_load(&(r->fData), r->fPath, r->fName, status);
 
-        if (result == FALSE || U_FAILURE(*status)) { 
+        if (U_FAILURE(*status)) { 
             /* we have no such entry in dll, so it will always use fallback */
             *status = U_USING_FALLBACK_WARNING;
             r->fBogus = U_USING_FALLBACK_WARNING;
         } else { /* if we have a regular entry */
-            /* We might be able to do this a wee bit more efficiently (we could check whether the aliased data) */
-            /* is already in the cache), but it's good the way it is */
-            /* handle the alias by trying to get out the %%Alias tag.*/
-            /* We'll try to get alias string from the bundle */
-            Resource aliasres = res_getResource(&(r->fData), "%%ALIAS");
-            const UChar *alias = res_getString(&(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);
-                isAlias = TRUE;
-                res_unload(&(r->fData));
-                result = res_load(&(r->fData), r->fPath, aliasName, status);
-                if (result == FALSE || U_FAILURE(*status)) { 
-                    /* we couldn't load aliased data - so we have no data */
-                    *status = U_USING_FALLBACK_WARNING;
-                    r->fBogus = U_USING_FALLBACK_WARNING;
+            Resource aliasres;
+            if (r->fData.usesPoolBundle) {
+                r->fPool = getPoolEntry(r->fPath, status);
+                if (U_SUCCESS(*status)) {
+                    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));
+                    } else {
+                        r->fBogus = *status = U_INVALID_FORMAT_ERROR;
+                    }
+                } else {
+                    r->fBogus = *status;
+                }
+            }
+            if (U_SUCCESS(*status)) {
+                /* handle the alias by trying to get out the %%Alias tag.*/
+                /* 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);
+                    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);
+                    }
                 }
-                setEntryName(r, aliasName, status);
             }
         }
 
         {
             UResourceDataEntry *oldR = NULL;
             if((oldR = (UResourceDataEntry *)uhash_get(cache, r)) == NULL) { /* if the data is not cached */
-              /* just insert it in the cache */
-                uhash_put(cache, (void *)r, r, status);
-            } else {
-              /* somebody have already inserted it while we were working, discard newly opened data */
-              /* Also, we could get here IF we opened an alias */
-                uprv_free(r->fName);
-                if(r->fPath != NULL) {
-                    uprv_free(r->fPath);
+                /* just insert it in the cache */
+                UErrorCode cacheStatus = U_ZERO_ERROR;
+                uhash_put(cache, (void *)r, r, &cacheStatus);
+                if (U_FAILURE(cacheStatus)) {
+                    *status = cacheStatus;
+                    free_entry(r);
+                    r = NULL;
                 }
-                res_unload(&(r->fData));
-                uprv_free(r);
+            } else {
+                /* somebody have already inserted it while we were working, discard newly opened data */
+                /* Also, we could get here IF we opened an alias */
+                free_entry(r);
                 r = oldR;
-                r->fCountExisting++;
             }
         }
 
     }
+    if(r != NULL) {
+        /* return the real bundle */
+        while(r->fAlias != NULL) {
+            r = r->fAlias;
+        }
+        r->fCountExisting++; /* we increase its reference count */
+        /* if the resource has a warning */
+        /* we don't want to overwrite a status with no error */
+        if(r->fBogus != U_ZERO_ERROR && U_SUCCESS(*status)) {
+             *status = r->fBogus; /* set the returning status */
+        }
+    }
     return r;
 }
 
+static UResourceDataEntry *
+getPoolEntry(const char *path, UErrorCode *status) {
+    UResourceDataEntry *poolBundle = init_entry(kPoolBundleName, path, status);
+    if( U_SUCCESS(*status) &&
+        (poolBundle == NULL || poolBundle->fBogus != U_ZERO_ERROR || !poolBundle->fData.isPoolBundle)
+    ) {
+        *status = U_INVALID_FORMAT_ERROR;
+    }
+    return poolBundle;
+}
+
 /* INTERNAL: */
 /*   CAUTION:  resbMutex must be locked when calling this function! */
 static UResourceDataEntry *findFirstExisting(const char* path, char* name, UBool *isRoot, UBool *hasChopped, UBool *isDefault, UErrorCode* status) {
-  UResourceDataEntry *r = NULL;
-  UBool hasRealData = FALSE;
-  const char *defaultLoc = uloc_getDefault();
-  UErrorCode intStatus = U_ZERO_ERROR;
-  *hasChopped = TRUE; /* we're starting with a fresh name */
-
-  while(*hasChopped && !hasRealData) {
-    r = init_entry(name, path, &intStatus);
-    *isDefault = (UBool)(uprv_strncmp(name, defaultLoc, uprv_strlen(name)) == 0);
-    hasRealData = (UBool)(r->fBogus == U_ZERO_ERROR);
-    if(!hasRealData) {
-      /* this entry is not real. We will discard it. */
-      /* However, the parent line for this entry is  */
-      /* not to be used - as there might be parent   */
-      /* lines in cache from previous openings that  */
-      /* are not updated yet. */
-      r->fCountExisting--;
-      /*entryCloseInt(r);*/
-      r = NULL;
-      *status = U_USING_FALLBACK_WARNING;
-    } else {
-      uprv_strcpy(name, r->fName); /* this is needed for supporting aliases */
-    }
+    UResourceDataEntry *r = NULL;
+    UBool hasRealData = FALSE;
+    const char *defaultLoc = uloc_getDefault();
+    *hasChopped = TRUE; /* we're starting with a fresh name */
 
-    *isRoot = (UBool)(uprv_strcmp(name, kRootLocaleName) == 0);
+    while(*hasChopped && !hasRealData) {
+        r = init_entry(name, path, status);
+        /* Null pointer test */
+        if (U_FAILURE(*status)) {
+            return NULL;
+        }
+        *isDefault = (UBool)(uprv_strncmp(name, defaultLoc, uprv_strlen(name)) == 0);
+        hasRealData = (UBool)(r->fBogus == U_ZERO_ERROR);
+        if(!hasRealData) {
+            /* this entry is not real. We will discard it. */
+            /* However, the parent line for this entry is  */
+            /* not to be used - as there might be parent   */
+            /* lines in cache from previous openings that  */
+            /* are not updated yet. */
+            r->fCountExisting--;
+            /*entryCloseInt(r);*/
+            r = NULL;
+            *status = U_USING_FALLBACK_WARNING;
+        } else {
+            uprv_strcpy(name, r->fName); /* this is needed for supporting aliases */
+        }
 
-    /*Fallback data stuff*/
-    *hasChopped = chopLocale(name);
-  }
-  return r;
+        *isRoot = (UBool)(uprv_strcmp(name, kRootLocaleName) == 0);
+
+        /*Fallback data stuff*/
+        *hasChopped = chopLocale(name);
+    }
+    return r;
 }
 
 static void ures_setIsStackObject( UResourceBundle* resB, UBool state) {
@@ -434,104 +516,178 @@ U_CFUNC void ures_initStackObject(UResourceBundle* resB) {
 static UResourceDataEntry *entryOpen(const char* path, const char* localeID, UErrorCode* status) {
     UErrorCode intStatus = U_ZERO_ERROR;
     UErrorCode parentStatus = U_ZERO_ERROR;
+    UErrorCode usrStatus = U_ZERO_ERROR;
     UResourceDataEntry *r = NULL;
     UResourceDataEntry *t1 = NULL;
     UResourceDataEntry *t2 = NULL;
+    UResourceDataEntry *u1 = NULL;
+    UResourceDataEntry *u2 = NULL;
     UBool isDefault = FALSE;
     UBool isRoot = FALSE;
     UBool hasRealData = FALSE;
     UBool hasChopped = TRUE;
+    UBool usingUSRData = U_USE_USRDATA && ( path == NULL || uprv_strncmp(path,U_ICUDATA_NAME,8) == 0);
+
     char name[96];
+    char usrDataPath[96];
+
+    initCache(status);
 
     if(U_FAILURE(*status)) {
-      return NULL;
+        return NULL;
     }
 
-    initCache(status);
-
     uprv_strcpy(name, localeID);
 
+    if ( usingUSRData ) {
+        if ( path == NULL ) {
+           uprv_strcpy(usrDataPath,U_USRDATA_NAME);
+        } else {
+           uprv_strcpy(usrDataPath,path);
+           usrDataPath[0] = 'u';
+           usrDataPath[1] = 's';
+           usrDataPath[2] = 'r';
+        }
+    }
     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);
-
-      if(r != NULL) { /* if there is one real locale, we can look for parents. */
-        t1 = r;
-        hasRealData = TRUE;
-        while (hasChopped && !isRoot && t1->fParent == NULL) {
-            /* insert regular parents */
-            t2 = init_entry(name, r->fPath, &parentStatus);
-            t1->fParent = t2;
-            t1 = t2;
-            hasChopped = chopLocale(name);
-        }
-      }
+        /* We're going to skip all the locales that do not have any data */
+        r = findFirstExisting(path, name, &isRoot, &hasChopped, &isDefault, &intStatus);
 
-      /* 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 && !isDefault && !isRoot /*&& t1->fParent == NULL*/) {
-          /* insert default locale */
-          uprv_strcpy(name, uloc_getDefault());
-          r = findFirstExisting(path, name, &isRoot, &hasChopped, &isDefault, &intStatus);
-          intStatus = U_USING_DEFAULT_WARNING;
-          if(r != NULL) { /* the default locale exists */
+        if(r != NULL) { /* if there is one real locale, we can look for parents. */
             t1 = r;
             hasRealData = TRUE;
-            isDefault = TRUE;
-            while (hasChopped && t1->fParent == NULL) {
-                /* insert chopped defaults */
-                t2 = init_entry(name, r->fPath, &parentStatus);
-                t1->fParent = t2;
-                t1 = t2;
+            if ( usingUSRData ) {  /* This code inserts user override data into the inheritance chain */
+               u1 = init_entry(t1->fName, usrDataPath, &usrStatus);
+               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;
+                 }
+               }
+            }
+            while (hasChopped && !isRoot && t1->fParent == NULL && !t1->fData.noFallback) {
+                /* insert regular parents */
+                t2 = init_entry(name, t1->fPath, &parentStatus);
+                if ( usingUSRData ) {  /* This code inserts user override data into the inheritance chain */
+                    usrStatus = U_ZERO_ERROR;
+                    u2 = init_entry(name, usrDataPath, &usrStatus);
+                }
+                /* Check for null pointer. */
+                if (t2 == NULL || ( usingUSRData && u2 == NULL)) {
+                    *status = U_MEMORY_ALLOCATION_ERROR;
+                    goto finishUnlock;
+                }
+                
+                if ( res_getResource(&t1->fData,"%%ParentIsRoot") == RES_BOGUS) {
+                    if ( usingUSRData && u2->fBogus == U_ZERO_ERROR ) {
+                        t1->fParent = u2;
+                        u2->fParent = t2;
+                    } else {
+                        t1->fParent = t2;
+                        if(usingUSRData) {
+                            /* the USR override data wasn't found, set it to be deleted */
+                            u2->fCountExisting = 0;
+                        }
+                    }
+                    t1 = t2;
+                } else {
+                    if (usingUSRData) {
+                        /* the USR override data wasn't found, set it to be deleted */
+                        u2->fCountExisting = 0;
+                    }
+                    /* t2->fCountExisting have to be decremented since the call to init_entry increments
+                     * it and if we hit this code, that means it is not set as the parent.
+                     */
+                    t2->fCountExisting--;
+                }
                 hasChopped = chopLocale(name);
             }
-          } 
-      }
+        }
 
-      /* 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(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;
+        /* 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 && !isDefault && !isRoot /*&& t1->fParent == NULL*/) {
+            /* insert default locale */
+            uprv_strcpy(name, uloc_getDefault());
+            r = findFirstExisting(path, name, &isRoot, &hasChopped, &isDefault, &intStatus);
+            intStatus = U_USING_DEFAULT_WARNING;
+            if(r != NULL) { /* the default locale exists */
+                t1 = r;
+                hasRealData = TRUE;
+                isDefault = TRUE;
+                while (hasChopped && t1->fParent == NULL) {
+                    /* insert chopped defaults */
+                    t2 = init_entry(name, t1->fPath, &parentStatus);
+                    /* Check for null pointer. */
+                    if (t2 == NULL) {
+                        *status = U_MEMORY_ALLOCATION_ERROR;
+                        goto finishUnlock;
+                    }
+
+                    if ( res_getResource(&t1->fData,"%%ParentIsRoot") == RES_BOGUS) {
+                        t1->fParent = t2;
+                        t1 = t2;
+                    }
+                    hasChopped = chopLocale(name);
+                }
+            } 
         }
-      } else if(!isRoot && uprv_strcmp(t1->fName, kRootLocaleName) != 0 && t1->fParent == NULL) {
-          /* insert root locale */
-          t2 = init_entry(kRootLocaleName, r->fPath, &parentStatus);
-          if(!hasRealData) {
-            r->fBogus = U_USING_DEFAULT_WARNING;
-          }
-          hasRealData = (UBool)((t2->fBogus == U_ZERO_ERROR) | hasRealData);
-          t1->fParent = t2;
-          t1 = t2;
-      }
 
-      while(r != NULL && !isRoot && t1->fParent != NULL) {
-          t1->fParent->fCountExisting++;
-          t1 = t1->fParent;
-          hasRealData = (UBool)((t1->fBogus == U_ZERO_ERROR) | hasRealData);
-      }
+        /* 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(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) {
+            /* insert root locale */
+            t2 = init_entry(kRootLocaleName, t1->fPath, &parentStatus);
+            /* Check for null pointer. */
+            if (t2 == NULL) {
+                *status = U_MEMORY_ALLOCATION_ERROR;
+                goto finishUnlock;
+            }
+            if(!hasRealData) {
+                r->fBogus = U_USING_DEFAULT_WARNING;
+            }
+            hasRealData = (UBool)((t2->fBogus == U_ZERO_ERROR) || hasRealData);
+            t1->fParent = t2;
+            t1 = t2;
+        }
+
+        while(r != NULL && !isRoot && t1->fParent != NULL) {
+            t1->fParent->fCountExisting++;
+            t1 = t1->fParent;
+            hasRealData = (UBool)((t1->fBogus == U_ZERO_ERROR) || hasRealData);
+        }
     } /* umtx_lock */
+finishUnlock:
     umtx_unlock(&resbMutex);
 
     if(U_SUCCESS(*status)) {
-      if(U_SUCCESS(parentStatus)) {
-        if(intStatus != U_ZERO_ERROR) {
-          *status = intStatus;  
+        if(U_SUCCESS(parentStatus)) {
+            if(intStatus != U_ZERO_ERROR) {
+                *status = intStatus;  
+            }
+            return r;
+        } else {
+            *status = parentStatus;
+            return NULL;
         }
-        return r;
-      } else {
-        *status = parentStatus;
-        return NULL;
-      }
     } else {
-      return NULL;
+        return NULL;
     }
 }
 
@@ -548,7 +704,7 @@ static void entryCloseInt(UResourceDataEntry *resB) {
         p = resB->fParent;
         resB->fCountExisting--;
 
-        /* Entries are left in the cache. TODO: add ures_cacheFlush() to force a flush
+        /* Entries are left in the cache. TODO: add ures_flushCache() to force a flush
          of the cache. */
 /*
         if(resB->fCountExisting <= 0) {
@@ -580,182 +736,317 @@ static void entryClose(UResourceDataEntry *resB) {
   umtx_unlock(&resbMutex);
 }
 
+/*
+U_CFUNC void ures_setResPath(UResourceBundle *resB, const char* toAdd) {
+  if(resB->fResPath == NULL) {
+    resB->fResPath = resB->fResBuf;
+    *(resB->fResPath) = 0;
+  } 
+  resB->fResPathLen = uprv_strlen(toAdd);
+  if(RES_BUFSIZE <= resB->fResPathLen+1) {
+    if(resB->fResPath == resB->fResBuf) {
+      resB->fResPath = (char *)uprv_malloc((resB->fResPathLen+1)*sizeof(char));
+    } else {
+      resB->fResPath = (char *)uprv_realloc(resB->fResPath, (resB->fResPathLen+1)*sizeof(char));
+    }
+  }
+  uprv_strcpy(resB->fResPath, toAdd);
+}
+*/
+static void ures_appendResPath(UResourceBundle *resB, const char* toAdd, int32_t lenToAdd, UErrorCode *status) {
+    int32_t resPathLenOrig = resB->fResPathLen;
+    if(resB->fResPath == NULL) {
+        resB->fResPath = resB->fResBuf;
+        *(resB->fResPath) = 0;
+        resB->fResPathLen = 0;
+    } 
+    resB->fResPathLen += lenToAdd;
+    if(RES_BUFSIZE <= resB->fResPathLen+1) {
+        if(resB->fResPath == resB->fResBuf) {
+            resB->fResPath = (char *)uprv_malloc((resB->fResPathLen+1)*sizeof(char));
+            /* Check that memory was allocated correctly. */
+            if (resB->fResPath == NULL) {
+                *status = U_MEMORY_ALLOCATION_ERROR;
+                return;
+            }
+            uprv_strcpy(resB->fResPath, resB->fResBuf);
+        } else {
+            char *temp = (char *)uprv_realloc(resB->fResPath, (resB->fResPathLen+1)*sizeof(char));
+            /* Check that memory was reallocated correctly. */
+            if (temp == NULL) {
+                *status = U_MEMORY_ALLOCATION_ERROR;
+                return;
+            }
+            resB->fResPath = temp;
+        }
+    }
+    uprv_strcpy(resB->fResPath + resPathLenOrig, toAdd);
+}
+
+static void ures_freeResPath(UResourceBundle *resB) {
+    if (resB->fResPath && resB->fResPath != resB->fResBuf) {
+        uprv_free(resB->fResPath);
+    }
+    resB->fResPath = NULL;
+    resB->fResPathLen = 0;
+}
+
+static void
+ures_closeBundle(UResourceBundle* resB, UBool freeBundleObj)
+{
+    if(resB != NULL) {
+        if(resB->fData != NULL) {
+            entryClose(resB->fData);
+        }
+        if(resB->fVersion != NULL) {
+            uprv_free(resB->fVersion);
+        }
+        ures_freeResPath(resB);
+
+        if(ures_isStackObject(resB) == FALSE && freeBundleObj) {
+            uprv_free(resB);
+        }
+#if 0 /*U_DEBUG*/
+        else {
+            /* poison the data */
+            uprv_memset(resB, -1, sizeof(UResourceBundle));
+        }
+#endif
+    }
+}
+
+U_CAPI void  U_EXPORT2
+ures_close(UResourceBundle* resB)
+{
+    ures_closeBundle(resB, TRUE);
+}
+
 static UResourceBundle *init_resb_result(const ResourceData *rdata, Resource r, 
-                                         const char *key, int32_t index, UResourceDataEntry *realData, 
+                                         const char *key, int32_t idx, UResourceDataEntry *realData, 
                                          const UResourceBundle *parent, int32_t noAlias,
                                          UResourceBundle *resB, UErrorCode *status) 
 {
     if(status == NULL || U_FAILURE(*status)) {
         return resB;
     }
+    if (parent == NULL) {
+        *status = U_ILLEGAL_ARGUMENT_ERROR;
+        return NULL;
+    }
     if(RES_GET_TYPE(r) == URES_ALIAS) { /* This is an alias, need to exchange with real data */
-      if(noAlias < URES_MAX_ALIAS_LEVEL) { 
-        int32_t len = 0;
-        const UChar *alias = res_getAlias(rdata, r, &len);   
-        if(len > 0) {
-          /* we have an alias, now let's cut it up */
-          char stackAlias[200];
-          char *chAlias = NULL, *path = NULL, *locale = NULL, *keyPath = NULL;
-          int32_t capacity;
-
-          /*
-           * Allocate enough space for both the char * version
-           * of the alias and parent->fResPath.
-           *
-           * We do this so that res_findResource() can modify the path,
-           * which allows us to remove redundant _res_findResource() variants
-           * in uresdata.c.
-           * res_findResource() now NUL-terminates each segment so that table keys
-           * can always be compared with strcmp() instead of strncmp().
-           * Saves code there and simplifies testing and code coverage.
-           *
-           * markus 2003oct17
-           */
-          ++len; /* count the terminating NUL */
-          if(parent != NULL && parent->fResPath != NULL) {
-            capacity = uprv_strlen(parent->fResPath) + 1;
-          } else {
-            capacity = 0;
-          }
-          if(capacity < len) {
-            capacity = len;
-          }
-          if(capacity <= sizeof(stackAlias)) {
-            capacity = sizeof(stackAlias);
-            chAlias = stackAlias;
-          } else {
-            chAlias = (char *)uprv_malloc(capacity);
-            /* test for NULL */
-            if(chAlias == NULL) {
-              *status = U_MEMORY_ALLOCATION_ERROR;
-              return NULL;
-            }
-          }
-          u_UCharsToChars(alias, chAlias, len);
-
-          if(*chAlias == RES_PATH_SEPARATOR) {
-            /* there is a path included */
-            locale = uprv_strchr(chAlias+1, RES_PATH_SEPARATOR);
-            if(locale == NULL) {
-                locale = uprv_strchr(chAlias, 0); /* avoid locale == NULL to make code below work */
-            } else {
-                *locale = 0;
-                locale++;
-            }
-            path = chAlias+1;
-            if(uprv_strcmp(path, "ICUDATA") == 0) { /* want ICU data */
-              path = NULL;
-            }
-          } else {
-            /* no path, start with a locale */
-            locale = chAlias;
-            path = realData->fPath;
-          }
-          keyPath = uprv_strchr(locale, RES_PATH_SEPARATOR);
-          if(keyPath) {
-            *keyPath = 0;
-            keyPath++;
-          }
-          {
-            /* got almost everything, let's try to open */
-            /* first, open the bundle with real data */
-            UResourceBundle *result = resB;
-            const char* temp = NULL;
-            UErrorCode intStatus = U_ZERO_ERROR;
-            UResourceBundle *mainRes = ures_openDirect(path, locale, &intStatus); 
-            if(U_SUCCESS(intStatus)) {
-              if(keyPath == NULL) {
-                /* no key path. This means that we are going to 
-                 * to use the corresponding resource from
-                 * another bundle
-                 */
-                /* first, we are going to get a corresponding parent 
-                 * resource to the one we are searching.
-                 */
-                char *aKey = parent->fResPath;
-                if(aKey) {
-                  uprv_strcpy(chAlias, aKey); /* allocated large enough above */
-                  aKey = chAlias;
-                  r = res_findResource(&(mainRes->fResData), mainRes->fRes, &aKey, &temp);
+        if(noAlias < URES_MAX_ALIAS_LEVEL) { 
+            int32_t len = 0;
+            const UChar *alias = res_getAlias(rdata, r, &len); 
+            if(len > 0) {
+                /* we have an alias, now let's cut it up */
+                char stackAlias[200];
+                char *chAlias = NULL, *path = NULL, *locale = NULL, *keyPath = NULL;
+                int32_t capacity;
+
+                /*
+                * Allocate enough space for both the char * version
+                * of the alias and parent->fResPath.
+                *
+                * We do this so that res_findResource() can modify the path,
+                * which allows us to remove redundant _res_findResource() variants
+                * in uresdata.c.
+                * res_findResource() now NUL-terminates each segment so that table keys
+                * can always be compared with strcmp() instead of strncmp().
+                * Saves code there and simplifies testing and code coverage.
+                *
+                * markus 2003oct17
+                */
+                ++len; /* count the terminating NUL */
+                if(parent->fResPath != NULL) {
+                    capacity = (int32_t)uprv_strlen(parent->fResPath) + 1;
                 } else {
-                  r = mainRes->fRes;
+                    capacity = 0;
                 }
-                if(key) {
-                  /* we need to make keyPath from parent's fResPath and
-                   * current key, if there is a key associated
-                   */
-                  len = uprv_strlen(key) + 1;
-                  if(len > capacity) {
+                if(capacity < len) {
                     capacity = len;
-                    if(chAlias == stackAlias) {
-                      chAlias = (char *)uprv_malloc(capacity);
-                    } else {
-                      chAlias = (char *)uprv_realloc(chAlias, capacity);
-                    }
+                }
+                if(capacity <= sizeof(stackAlias)) {
+                    capacity = sizeof(stackAlias);
+                    chAlias = stackAlias;
+                } else {
+                    chAlias = (char *)uprv_malloc(capacity);
+                    /* test for NULL */
                     if(chAlias == NULL) {
-                      ures_close(mainRes);
-                      *status = U_MEMORY_ALLOCATION_ERROR;
-                      return NULL;
+                        *status = U_MEMORY_ALLOCATION_ERROR;
+                        return NULL;
                     }
-                  }
-                  uprv_memcpy(chAlias, key, len);
-                  aKey = chAlias;
-                  r = res_findResource(&(mainRes->fResData), r, &aKey, &temp);
-                } else if(index != -1) {
-                /* if there is no key, but there is an index, try to get by the index */
-                /* here we have either a table or an array, so get the element */
-                  if(RES_GET_TYPE(r) == URES_TABLE || RES_GET_TYPE(r) == URES_TABLE32) {
-                    r = res_getTableItemByIndex(&(mainRes->fResData), r, index, (const char **)&aKey);
-                  } else { /* array */
-                    r = res_getArrayItem(&(mainRes->fResData), r, index);
-                  }
                 }
-                if(r != RES_BOGUS) {
-                  result = init_resb_result(&(mainRes->fResData), r, key, -1, mainRes->fData, parent, noAlias+1, resB, status);
+                u_UCharsToChars(alias, chAlias, len);
+
+                if(*chAlias == RES_PATH_SEPARATOR) {
+                    /* there is a path included */
+                    locale = uprv_strchr(chAlias+1, RES_PATH_SEPARATOR);
+                    if(locale == NULL) {
+                        locale = uprv_strchr(chAlias, 0); /* avoid locale == NULL to make code below work */
+                    } else {
+                        *locale = 0;
+                        locale++;
+                    }
+                    path = chAlias+1;
+                    if(uprv_strcmp(path, "LOCALE") == 0) {
+                        /* this is an XPath alias, starting with "/LOCALE/" */
+                        /* it contains the path to a resource which should be looked up */
+                        /* starting in the requested locale */
+                        keyPath = locale; 
+                        locale = parent->fTopLevelData->fName; /* this is the requested locale's name */
+                        path = realData->fPath; /* we will be looking in the same package */
+                    } else {
+                        if(uprv_strcmp(path, "ICUDATA") == 0) { /* want ICU data */
+                            path = NULL;
+                        }
+                        keyPath = uprv_strchr(locale, RES_PATH_SEPARATOR);
+                        if(keyPath) {
+                            *keyPath = 0;
+                            keyPath++;
+                        }
+                    }
                 } else {
-                  *status = U_MISSING_RESOURCE_ERROR;
-                  result = resB;
+                    /* no path, start with a locale */
+                    locale = chAlias;
+                    keyPath = uprv_strchr(locale, RES_PATH_SEPARATOR);
+                    if(keyPath) {
+                        *keyPath = 0;
+                        keyPath++;
+                    }
+                    path = realData->fPath;
                 }
-              } else {
-                /* this one is a bit trickier. 
-                 * we start finding keys, but after we resolve one alias, the path might continue.
-                 * Consider: 
-                 *     aliastest:alias { "testtypes/anotheralias/Sequence" }
-                 *     anotheralias:alias { "/ICUDATA/sh/CollationElements" }
-                 * aliastest resource should finally have the sequence, not collation elements.
-                 */
-                result = mainRes;
-                while(*keyPath && U_SUCCESS(*status)) {
-                  r = res_findResource(&(result->fResData), result->fRes, &keyPath, &temp);
-                  if(r == RES_BOGUS) {
-                    *status = U_MISSING_RESOURCE_ERROR;
-                    result = resB;
-                    break;
-                  }
-                  resB = init_resb_result(&(result->fResData), r, key, -1, result->fData, parent, noAlias+1, resB, status);
-                  result = resB;
+
+
+                {
+                    /* got almost everything, let's try to open */
+                    /* first, open the bundle with real data */
+                    UResourceBundle *result = resB;
+                    const char* temp = NULL;
+                    UErrorCode intStatus = U_ZERO_ERROR;
+                    UResourceBundle *mainRes = ures_openDirect(path, locale, &intStatus); 
+                    if(U_SUCCESS(intStatus)) {
+                        if(keyPath == NULL) {
+                            /* no key path. This means that we are going to 
+                            * to use the corresponding resource from
+                            * another bundle
+                            */
+                            /* first, we are going to get a corresponding parent 
+                            * resource to the one we are searching.
+                            */
+                            char *aKey = parent->fResPath;
+                            if(aKey) {
+                                uprv_strcpy(chAlias, aKey); /* allocated large enough above */
+                                aKey = chAlias;
+                                r = res_findResource(&(mainRes->fResData), mainRes->fRes, &aKey, &temp);
+                            } else {
+                                r = mainRes->fRes;
+                            }
+                            if(key) {
+                                /* we need to make keyPath from parent's fResPath and
+                                * current key, if there is a key associated
+                                */
+                                len = (int32_t)(uprv_strlen(key) + 1);
+                                if(len > capacity) {
+                                    capacity = len;
+                                    if(chAlias == stackAlias) {
+                                        chAlias = (char *)uprv_malloc(capacity);
+                                    } else {
+                                        chAlias = (char *)uprv_realloc(chAlias, capacity);
+                                    }
+                                    if(chAlias == NULL) {
+                                        ures_close(mainRes);
+                                        *status = U_MEMORY_ALLOCATION_ERROR;
+                                        return NULL;
+                                    }
+                                }
+                                uprv_memcpy(chAlias, key, len);
+                                aKey = chAlias;
+                                r = res_findResource(&(mainRes->fResData), r, &aKey, &temp);
+                            } else if(idx != -1) {
+                                /* if there is no key, but there is an index, try to get by the index */
+                                /* here we have either a table or an array, so get the element */
+                                UResType type = RES_GET_TYPE(r);
+                                if(URES_IS_TABLE(type)) {
+                                    r = res_getTableItemByIndex(&(mainRes->fResData), r, idx, (const char **)&aKey);
+                                } else { /* array */
+                                    r = res_getArrayItem(&(mainRes->fResData), r, idx);
+                                }
+                            }
+                            if(r != RES_BOGUS) {
+                                result = init_resb_result(&(mainRes->fResData), r, temp, -1, mainRes->fData, mainRes, noAlias+1, resB, status);
+                            } else {
+                                *status = U_MISSING_RESOURCE_ERROR;
+                                result = resB;
+                            }
+                        } else {
+                            /* this one is a bit trickier. 
+                            * we start finding keys, but after we resolve one alias, the path might continue.
+                            * Consider: 
+                            *     aliastest:alias { "testtypes/anotheralias/Sequence" }
+                            *     anotheralias:alias { "/ICUDATA/sh/CollationElements" }
+                            * aliastest resource should finally have the sequence, not collation elements.
+                            */
+                            UResourceDataEntry *dataEntry = mainRes->fData;
+                            char stackPath[URES_MAX_BUFFER_SIZE];
+                            char *pathBuf = stackPath, *myPath = pathBuf;
+                            if(uprv_strlen(keyPath) > URES_MAX_BUFFER_SIZE) {
+                                pathBuf = (char *)uprv_malloc((uprv_strlen(keyPath)+1)*sizeof(char));
+                                if(pathBuf == NULL) {
+                                    *status = U_MEMORY_ALLOCATION_ERROR;
+                                    return NULL;
+                                }
+                            }
+                            uprv_strcpy(pathBuf, keyPath);
+                            result = mainRes;
+                            /* now we have fallback following here */
+                            do {
+                                r = dataEntry->fData.rootRes;     
+                                /* this loop handles 'found' resources over several levels */
+                                while(*myPath && U_SUCCESS(*status)) {
+                                    r = res_findResource(&(dataEntry->fData), r, &myPath, &temp);
+                                    if(r != RES_BOGUS) { /* found a resource, but it might be an indirection */
+                                        resB = init_resb_result(&(dataEntry->fData), r, temp, -1, dataEntry, result, noAlias+1, resB, status);
+                                        result = resB;
+                                        if(result) {
+                                            r = result->fRes; /* switch to a new resource, possibly a new tree */
+                                            dataEntry = result->fData;
+                                        }
+                                    } else { /* no resource found, we don't really want to look anymore on this level */
+                                        break;
+                                    }
+                                }
+                                dataEntry = dataEntry->fParent;
+                                uprv_strcpy(pathBuf, keyPath);
+                                myPath = pathBuf;
+                            } while(r == RES_BOGUS && dataEntry != NULL);
+                            if(r == RES_BOGUS) {
+                                *status = U_MISSING_RESOURCE_ERROR;
+                                result = resB;
+                            }
+                            if(pathBuf != stackPath) {
+                                uprv_free(pathBuf);
+                            }
+                        }
+                    } else { /* we failed to open the resource we're aliasing to */
+                        *status = intStatus;
+                    }
+                    if(chAlias != stackAlias) {
+                        uprv_free(chAlias);
+                    }
+                    if(mainRes != result) {
+                        ures_close(mainRes);
+                    }
+                    return result;
                 }
-              }
-            } else { /* we failed to open the resource we're aliasing to */
-              *status = intStatus;
-            }
-            if(chAlias != stackAlias) {
-              uprv_free(chAlias);
-            }
-            if(mainRes != result) {
-              ures_close(mainRes);
+            } else {
+                /* bad alias, should be an error */ 
+                *status = U_ILLEGAL_ARGUMENT_ERROR;
+                return resB;
             }
-            return result;
-          }
         } else {
-          /* bad alias, should be an error */ 
-          *status = U_ILLEGAL_ARGUMENT_ERROR;
-          return resB;
+            *status = U_TOO_MANY_ALIASES_ERROR;
+            return resB;
         }
-      } else {
-        *status = U_TOO_MANY_ALIASES_ERROR;
-        return resB;
-      }
     }
     if(resB == NULL) {
         resB = (UResourceBundle *)uprv_malloc(sizeof(UResourceBundle));
@@ -774,9 +1065,17 @@ static UResourceBundle *init_resb_result(const ResourceData *rdata, Resource r,
         if(resB->fVersion != NULL) {
             uprv_free(resB->fVersion);
         }
+        /* 
+        weiv: if stack object was passed in, it doesn't really need to be reinited,
+        since the purpose of initing is to remove stack junk. However, at this point 
+        we would not do anything to an allocated object, so stack object should be
+        treated the same
+        */
+        /*
         if(ures_isStackObject(resB) != FALSE) {
-            ures_initStackObject(resB);
+        ures_initStackObject(resB);
         }
+        */
         if(parent != resB) {
             ures_freeResPath(resB);
         }
@@ -786,28 +1085,35 @@ static UResourceBundle *init_resb_result(const ResourceData *rdata, Resource r,
     resB->fHasFallback = FALSE;
     resB->fIsTopLevel = FALSE;
     resB->fIndex = -1;
-    resB->fKey = key;
-    resB->fParentRes = parent;
+    resB->fKey = key; 
+    /*resB->fParentRes = parent;*/
     resB->fTopLevelData = parent->fTopLevelData;
     if(parent->fResPath && parent != resB) {
-      ures_appendResPath(resB, parent->fResPath, parent->fResPathLen);
+        ures_appendResPath(resB, parent->fResPath, parent->fResPathLen, status);
     }
     if(key != NULL) {
-      ures_appendResPath(resB, key, uprv_strlen(key));
-      ures_appendResPath(resB, RES_PATH_SEPARATOR_S, 1);
-    } else {
-      char buf[256];
-      int32_t len = T_CString_integerToString(buf, index, 10);
-      ures_appendResPath(resB, buf, len);
-      ures_appendResPath(resB, RES_PATH_SEPARATOR_S, 1);
+        ures_appendResPath(resB, key, (int32_t)uprv_strlen(key), status);
+        if(resB->fResPath[resB->fResPathLen-1] != RES_PATH_SEPARATOR) {
+            ures_appendResPath(resB, RES_PATH_SEPARATOR_S, 1, status);
+        }
+    } else if(idx >= 0) {
+        char buf[256];
+        int32_t len = T_CString_integerToString(buf, idx, 10);
+        ures_appendResPath(resB, buf, len, status);
+        if(resB->fResPath[resB->fResPathLen-1] != RES_PATH_SEPARATOR) {
+            ures_appendResPath(resB, RES_PATH_SEPARATOR_S, 1, status);
+        }
+    }
+    /* Make sure that Purify doesn't complain about uninitialized memory copies. */
+    {
+        int32_t usedLen = ((resB->fResBuf == resB->fResPath) ? resB->fResPathLen : 0);
+        uprv_memset(resB->fResBuf + usedLen, 0, sizeof(resB->fResBuf) - usedLen);
     }
 
     resB->fVersion = NULL;
     resB->fRes = r;
     /*resB->fParent = parent->fRes;*/
-    resB->fResData.data = rdata->data;
-    resB->fResData.pRoot = rdata->pRoot;
-    resB->fResData.rootRes = rdata->rootRes;
+    uprv_memmove(&resB->fResData, rdata, sizeof(ResourceData));
     resB->fSize = res_countArrayItems(&(resB->fResData), resB->fRes);
     return resB;
 }
@@ -828,33 +1134,20 @@ UResourceBundle *ures_copyResb(UResourceBundle *r, const UResourceBundle *origin
             }
         } else {
             isStackObject = ures_isStackObject(r);
-            if(U_FAILURE(*status)) {
-                return r;
-            }
-            ures_close(r);
-            if(isStackObject == FALSE) {
-                r = (UResourceBundle *)uprv_malloc(sizeof(UResourceBundle));
-                /* test for NULL */
-                if (r == NULL) {
-                    *status = U_MEMORY_ALLOCATION_ERROR;
-                    return NULL;
-                }
-            }
+            ures_closeBundle(r, FALSE);
         }
         uprv_memcpy(r, original, sizeof(UResourceBundle));
         r->fResPath = NULL;
         r->fResPathLen = 0;
         if(original->fResPath) {
-          ures_appendResPath(r, original->fResPath, original->fResPathLen);
+            ures_appendResPath(r, original->fResPath, original->fResPathLen, status);
         }
         ures_setIsStackObject(r, isStackObject);
         if(r->fData != NULL) {
-          entryIncrease(r->fData);
+            entryIncrease(r->fData);
         }
-        return r;
-    } else {
-        return r;
     }
+    return r;
 }
 
 /**
@@ -862,7 +1155,7 @@ UResourceBundle *ures_copyResb(UResourceBundle *r, const UResourceBundle *origin
  */
 
 U_CAPI const UChar* U_EXPORT2 ures_getString(const UResourceBundle* resB, int32_t* len, UErrorCode* status) {
-
+    const UChar *s;
     if (status==NULL || U_FAILURE(*status)) {
         return NULL;
     }
@@ -870,25 +1163,88 @@ 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);
+    if (s == NULL) {
+        *status = U_RESOURCE_TYPE_MISMATCH;
+    }
+    return s;
+}
 
-    switch(RES_GET_TYPE(resB->fRes)) {
-        case URES_STRING:
-            return res_getString(&(resB->fResData), resB->fRes, len);
-        case URES_INT:
-        case URES_INT_VECTOR:
-        case URES_BINARY:
-        case URES_ARRAY:
-        case URES_TABLE:
-        case URES_TABLE32:
-        default:
-            *status = U_RESOURCE_TYPE_MISMATCH;
+static const char *
+ures_toUTF8String(const UChar *s16, int32_t length16,
+                  char *dest, int32_t *pLength,
+                  UBool forceCopy,
+                  UErrorCode *status) {
+    int32_t capacity;
+
+    if (U_FAILURE(*status)) {
+        return NULL;
+    }
+    if (pLength != NULL) {
+        capacity = *pLength;
+    } else {
+        capacity = 0;
+    }
+    if (capacity < 0 || (capacity > 0 && dest == NULL)) {
+        *status = U_ILLEGAL_ARGUMENT_ERROR;
+        return NULL;
     }
 
-    return NULL;
+    if (length16 == 0) {
+        /* empty string, return as read-only pointer */
+        if (pLength != NULL) {
+            *pLength = 0;
+        }
+        if (forceCopy) {
+            u_terminateChars(dest, capacity, 0, status);
+            return dest;
+        } else {
+            return "";
+        }
+    } else {
+        /* We need to transform the string to the destination buffer. */
+        if (capacity < length16) {
+            /* No chance for the string to fit. Pure preflighting. */
+            return u_strToUTF8(NULL, 0, pLength, s16, length16, status);
+        }
+        if (!forceCopy && (length16 <= 0x2aaaaaaa)) {
+            /*
+             * We know the string will fit into dest because each UChar turns
+             * into at most three UTF-8 bytes. Fill the latter part of dest
+             * so that callers do not expect to use dest as a string pointer,
+             * hopefully leading to more robust code for when resource bundles
+             * may store UTF-8 natively.
+             * (In which case dest would not be used at all.)
+             *
+             * We do not do this if forceCopy=TRUE because then the caller
+             * expects the string to start exactly at dest.
+             *
+             * The test above for <= 0x2aaaaaaa prevents overflows.
+             * The +1 is for the NUL terminator.
+             */
+            int32_t maxLength = 3 * length16 + 1;
+            if (capacity > maxLength) {
+                dest += capacity - maxLength;
+                capacity = maxLength;
+            }
+        }
+        return u_strToUTF8(dest, capacity, pLength, s16, length16, status);
+    }
+}
+
+U_CAPI const char * U_EXPORT2
+ures_getUTF8String(const UResourceBundle *resB,
+                   char *dest, int32_t *pLength,
+                   UBool forceCopy,
+                   UErrorCode *status) {
+    int32_t length16;
+    const UChar *s16 = ures_getString(resB, &length16, status);
+    return ures_toUTF8String(s16, length16, dest, pLength, forceCopy, status);
 }
 
 U_CAPI const uint8_t* U_EXPORT2 ures_getBinary(const UResourceBundle* resB, int32_t* len, 
                                                UErrorCode*               status) {
+  const uint8_t *p;
   if (status==NULL || U_FAILURE(*status)) {
     return NULL;
   }
@@ -896,24 +1252,16 @@ U_CAPI const uint8_t* U_EXPORT2 ures_getBinary(const UResourceBundle* resB, int3
     *status = U_ILLEGAL_ARGUMENT_ERROR;
     return NULL;
   }
-  switch(RES_GET_TYPE(resB->fRes)) {
-  case URES_BINARY:
-    return res_getBinary(&(resB->fResData), resB->fRes, len);
-  case URES_INT:
-  case URES_STRING:
-  case URES_INT_VECTOR:
-  case URES_ARRAY:
-  case URES_TABLE:
-  case URES_TABLE32:
-  default:
+  p = res_getBinary(&(resB->fResData), resB->fRes, len);
+  if (p == NULL) {
     *status = U_RESOURCE_TYPE_MISMATCH;
   }
-
-  return NULL;
+  return p;
 }
 
 U_CAPI const int32_t* U_EXPORT2 ures_getIntVector(const UResourceBundle* resB, int32_t* len, 
                                                    UErrorCode*               status) {
+  const int32_t *p;
   if (status==NULL || U_FAILURE(*status)) {
     return NULL;
   }
@@ -921,20 +1269,11 @@ U_CAPI const int32_t* U_EXPORT2 ures_getIntVector(const UResourceBundle* resB, i
     *status = U_ILLEGAL_ARGUMENT_ERROR;
     return NULL;
   }
-  switch(RES_GET_TYPE(resB->fRes)) {
-  case URES_INT_VECTOR:
-    return res_getIntVector(&(resB->fResData), resB->fRes, len);
-  case URES_INT:
-  case URES_STRING:
-  case URES_ARRAY:
-  case URES_BINARY:
-  case URES_TABLE:
-  case URES_TABLE32:
-  default:
+  p = res_getIntVector(&(resB->fResData), resB->fRes, len);
+  if (p == NULL) {
     *status = U_RESOURCE_TYPE_MISMATCH;
   }
-
-  return NULL;
+  return p;
 }
 
 /* this function returns a signed integer */ 
@@ -969,15 +1308,11 @@ U_CAPI uint32_t U_EXPORT2 ures_getUInt(const UResourceBundle* resB, UErrorCode *
   return RES_GET_UINT(resB->fRes);
 }
 
-
 U_CAPI UResType U_EXPORT2 ures_getType(const UResourceBundle *resB) {
-  UResType type;
-
   if(resB == NULL) {
     return URES_NONE;
   }
-  type = (UResType) RES_GET_TYPE(resB->fRes);
-  return type == URES_TABLE32 ? URES_TABLE : type;
+  return res_getPublicType(resB->fRes);
 }
 
 U_CAPI const char * U_EXPORT2 ures_getKey(const UResourceBundle *resB) {
@@ -1038,11 +1373,11 @@ U_CAPI const UChar* U_EXPORT2 ures_getNextString(UResourceBundle *resB, int32_t*
   } else {
     resB->fIndex++;
     switch(RES_GET_TYPE(resB->fRes)) {
-    case URES_INT:
-    case URES_BINARY:
     case URES_STRING:
+    case URES_STRING_V2:
       return res_getString(&(resB->fResData), resB->fRes, len); 
     case URES_TABLE:
+    case URES_TABLE16:
     case URES_TABLE32:
       r = res_getTableItemByIndex(&(resB->fResData), resB->fRes, resB->fIndex, key);
       if(r == RES_BOGUS && resB->fHasFallback) {
@@ -1050,6 +1385,7 @@ U_CAPI const UChar* U_EXPORT2 ures_getNextString(UResourceBundle *resB, int32_t*
       }
       return ures_getStringWithAlias(resB, r, resB->fIndex, len, status);
     case URES_ARRAY:
+    case URES_ARRAY16:
       r = res_getArrayItem(&(resB->fResData), resB->fRes, resB->fIndex);
       if(r == RES_BOGUS && resB->fHasFallback) {
         /* TODO: do the fallback */
@@ -1057,10 +1393,12 @@ U_CAPI const UChar* U_EXPORT2 ures_getNextString(UResourceBundle *resB, int32_t*
       return ures_getStringWithAlias(resB, r, resB->fIndex, len, status);
     case URES_ALIAS:
       return ures_getStringWithAlias(resB, resB->fRes, resB->fIndex, len, status);
+    case URES_INT:
+    case URES_BINARY:
     case URES_INT_VECTOR:
+        *status = U_RESOURCE_TYPE_MISMATCH;
     default:
       return NULL;
-      break;
     }
   }
 
@@ -1090,8 +1428,11 @@ U_CAPI UResourceBundle* U_EXPORT2 ures_getNextResource(UResourceBundle *resB, UR
         case URES_INT:
         case URES_BINARY:
         case URES_STRING:
+        case URES_STRING_V2:
+        case URES_INT_VECTOR:
             return ures_copyResb(fillIn, resB, status);
         case URES_TABLE:
+        case URES_TABLE16:
         case URES_TABLE32:
             r = res_getTableItemByIndex(&(resB->fResData), resB->fRes, resB->fIndex, &key);
             if(r == RES_BOGUS && resB->fHasFallback) {
@@ -1099,12 +1440,12 @@ U_CAPI UResourceBundle* U_EXPORT2 ures_getNextResource(UResourceBundle *resB, UR
             }
             return init_resb_result(&(resB->fResData), r, key, resB->fIndex, resB->fData, resB, 0, fillIn, status);
         case URES_ARRAY:
+        case URES_ARRAY16:
             r = res_getArrayItem(&(resB->fResData), resB->fRes, resB->fIndex);
             if(r == RES_BOGUS && resB->fHasFallback) {
                 /* TODO: do the fallback */
             }
             return init_resb_result(&(resB->fResData), r, key, resB->fIndex, resB->fData, resB, 0, fillIn, status);
-        case URES_INT_VECTOR:
         default:
             /*return NULL;*/
             return fillIn;
@@ -1133,8 +1474,11 @@ U_CAPI UResourceBundle* U_EXPORT2 ures_getByIndex(const UResourceBundle *resB, i
         case URES_INT:
         case URES_BINARY:
         case URES_STRING:
+        case URES_STRING_V2:
+        case URES_INT_VECTOR:
             return ures_copyResb(fillIn, resB, status);
         case URES_TABLE:
+        case URES_TABLE16:
         case URES_TABLE32:
             r = res_getTableItemByIndex(&(resB->fResData), resB->fRes, indexR, &key);
             if(r == RES_BOGUS && resB->fHasFallback) {
@@ -1142,12 +1486,12 @@ U_CAPI UResourceBundle* U_EXPORT2 ures_getByIndex(const UResourceBundle *resB, i
             }
             return init_resb_result(&(resB->fResData), r, key, indexR, resB->fData, resB, 0, fillIn, status);
         case URES_ARRAY:
+        case URES_ARRAY16:
             r = res_getArrayItem(&(resB->fResData), resB->fRes, indexR);
             if(r == RES_BOGUS && resB->fHasFallback) {
                 /* TODO: do the fallback */
             }
             return init_resb_result(&(resB->fResData), r, key, indexR, resB->fData, resB, 0, fillIn, status);
-        case URES_INT_VECTOR:
         default:
             /*return NULL;*/
             return fillIn;
@@ -1173,11 +1517,11 @@ U_CAPI const UChar* U_EXPORT2 ures_getStringByIndex(const UResourceBundle *resB,
 
     if(indexS >= 0 && resB->fSize > indexS) {
         switch(RES_GET_TYPE(resB->fRes)) {
-        case URES_INT:
-        case URES_BINARY:
         case URES_STRING:
+        case URES_STRING_V2:
             return res_getString(&(resB->fResData), resB->fRes, len);
         case URES_TABLE:
+        case URES_TABLE16:
         case URES_TABLE32:
             r = res_getTableItemByIndex(&(resB->fResData), resB->fRes, indexS, &key);
             if(r == RES_BOGUS && resB->fHasFallback) {
@@ -1185,17 +1529,23 @@ U_CAPI const UChar* U_EXPORT2 ures_getStringByIndex(const UResourceBundle *resB,
             }
             return ures_getStringWithAlias(resB, r, indexS, len, status);
         case URES_ARRAY:
+        case URES_ARRAY16:
             r = res_getArrayItem(&(resB->fResData), resB->fRes, indexS);
             if(r == RES_BOGUS && resB->fHasFallback) {
                 /* TODO: do the fallback */
             }
             return ures_getStringWithAlias(resB, r, indexS, len, status);
         case URES_ALIAS:
-          return ures_getStringWithAlias(resB, resB->fRes, indexS, len, status);
-
-        /*case URES_INT_VECTOR:*/
-        /*default:*/
-          /*return;*/
+            return ures_getStringWithAlias(resB, resB->fRes, indexS, len, status);
+        case URES_INT:
+        case URES_BINARY:
+        case URES_INT_VECTOR:
+            *status = U_RESOURCE_TYPE_MISMATCH;
+            break;
+        default:
+          /* must not occur */
+          *status = U_INTERNAL_PROGRAM_ERROR;
+          break;
         }
     } else {
         *status = U_MISSING_RESOURCE_ERROR;
@@ -1203,6 +1553,17 @@ U_CAPI const UChar* U_EXPORT2 ures_getStringByIndex(const UResourceBundle *resB,
     return NULL;
 }
 
+U_CAPI const char * U_EXPORT2
+ures_getUTF8StringByIndex(const UResourceBundle *resB,
+                          int32_t idx,
+                          char *dest, int32_t *pLength,
+                          UBool forceCopy,
+                          UErrorCode *status) {
+    int32_t length16;
+    const UChar *s16 = ures_getStringByIndex(resB, idx, &length16, status);
+    return ures_toUTF8String(s16, length16, dest, pLength, forceCopy, status);
+}
+
 /*U_CAPI const char *ures_getResPath(UResourceBundle *resB) {
   return resB->fResPath;
 }*/
@@ -1213,7 +1574,7 @@ ures_findResource(const char* path, UResourceBundle *fillIn, UErrorCode *status)
   UResourceBundle *first = NULL; 
   UResourceBundle *result = fillIn;
   char *packageName = NULL;
-  char *pathToResource = NULL;
+  char *pathToResource = NULL, *save = NULL;
   char *locale = NULL, *localeEnd = NULL;
   int32_t length;
 
@@ -1221,8 +1582,8 @@ ures_findResource(const char* path, UResourceBundle *fillIn, UErrorCode *status)
     return result;
   }
 
-  length = uprv_strlen(path)+1;
-  pathToResource = (char *)uprv_malloc(length*sizeof(char));
+  length = (int32_t)(uprv_strlen(path)+1);
+  save = pathToResource = (char *)uprv_malloc(length*sizeof(char));
   /* test for NULL */
   if(pathToResource == NULL) {
     *status = U_MEMORY_ALLOCATION_ERROR;
@@ -1258,7 +1619,7 @@ ures_findResource(const char* path, UResourceBundle *fillIn, UErrorCode *status)
     }
     ures_close(first);
   }
-  uprv_free(pathToResource);
+  uprv_free(save);
   return result;
 }
 
@@ -1285,20 +1646,35 @@ ures_findSubResource(const UResourceBundle *resB, char* path, UResourceBundle *f
         *status = U_MISSING_RESOURCE_ERROR;
         break;
     }
-  } while(uprv_strlen(path)); /* there is more stuff in the path */
+  } while(*path); /* there is more stuff in the path */
 
   return result;
 }
+U_INTERNAL const UChar* U_EXPORT2 
+ures_getStringByKeyWithFallback(const UResourceBundle *resB, 
+                                const char* inKey, 
+                                int32_t* len,
+                                UErrorCode *status) {
+
+    UResourceBundle stack;
+    const UChar* retVal = NULL;
+    ures_initStackObject(&stack);
+    ures_getByKeyWithFallback(resB, inKey, &stack, status);
+    retVal = ures_getString(&stack, len, status);
+    ures_close(&stack);
+    return retVal;
+}
 
 U_CAPI UResourceBundle* U_EXPORT2 
 ures_getByKeyWithFallback(const UResourceBundle *resB, 
                           const char* inKey, 
                           UResourceBundle *fillIn, 
                           UErrorCode *status) {
-    Resource res = RES_BOGUS;
+    Resource res = RES_BOGUS, rootRes = RES_BOGUS;
     /*UResourceDataEntry *realData = NULL;*/
     const char *key = inKey;
     UResourceBundle *helper = NULL;
+    UResType type;
 
     if (status==NULL || U_FAILURE(*status)) {
         return fillIn;
@@ -1308,34 +1684,54 @@ ures_getByKeyWithFallback(const UResourceBundle *resB,
         return fillIn;
     }
 
-    if(RES_GET_TYPE(resB->fRes) == URES_TABLE || RES_GET_TYPE(resB->fRes) == URES_TABLE32) {
+    type = RES_GET_TYPE(resB->fRes);
+    if(URES_IS_TABLE(type)) {
         int32_t t;
         res = res_getTableItemByKey(&(resB->fResData), resB->fRes, &t, &key);
         if(res == RES_BOGUS) {
             UResourceDataEntry *dataEntry = resB->fData;
             char path[256];
             char* myPath = path;
+            const char* resPath = resB->fResPath;
+            int32_t len = resB->fResPathLen;
 
             while(res == RES_BOGUS && dataEntry->fParent != NULL) { /* Otherwise, we'll look in parents */
                 dataEntry = dataEntry->fParent;
+                rootRes = dataEntry->fData.rootRes;
+
                 if(dataEntry->fBogus == U_ZERO_ERROR) {
-                    uprv_strncpy(path, resB->fResPath, resB->fResPathLen);
-                    uprv_strcpy(path+resB->fResPathLen, inKey);
+                    uprv_strncpy(path, resPath, len);
+                    uprv_strcpy(path+len, inKey);
                     myPath = path;
                     key = inKey;
                     do {
-                        res = res_findResource(&(dataEntry->fData), dataEntry->fData.rootRes, &myPath, &key);
+                        res = res_findResource(&(dataEntry->fData), rootRes, &myPath, &key);
                         if (RES_GET_TYPE(res) == URES_ALIAS && *myPath) {
                             /* We hit an alias, but we didn't finish following the path. */
-                            helper = init_resb_result(&(dataEntry->fData), res, inKey, -1, dataEntry, resB, 0, helper, status);
-                            dataEntry = helper->fData;
+                            helper = init_resb_result(&(dataEntry->fData), res, NULL, -1, dataEntry, resB, 0, helper, status); 
+                            /*helper = init_resb_result(&(dataEntry->fData), res, inKey, -1, dataEntry, resB, 0, helper, status);*/
+                            if(helper) {
+                              dataEntry = helper->fData;
+                              rootRes = helper->fRes;
+                              resPath = helper->fResPath;
+                              len = helper->fResPathLen;
+
+                            } else {
+                              break;
+                            }
                         }
-                    } while(uprv_strlen(myPath));
+                    } while(*myPath); /* Continue until the whole path is consumed */
                 }
             }
             /*const ResourceData *rd = getFallbackData(resB, &key, &realData, &res, status);*/
             if(res != RES_BOGUS) {
               /* check if resB->fResPath gives the right name here */
+                if(uprv_strcmp(dataEntry->fName, uloc_getDefault())==0 || uprv_strcmp(dataEntry->fName, kRootLocaleName)==0) {
+                    *status = U_USING_DEFAULT_WARNING;
+                } else {
+                    *status = U_USING_FALLBACK_WARNING;
+                }
+
                 fillIn = init_resb_result(&(dataEntry->fData), res, inKey, -1, dataEntry, resB, 0, fillIn, status);
             } else {
                 *status = U_MISSING_RESOURCE_ERROR;
@@ -1356,6 +1752,7 @@ U_CAPI UResourceBundle* U_EXPORT2 ures_getByKey(const UResourceBundle *resB, con
     Resource res = RES_BOGUS;
     UResourceDataEntry *realData = NULL;
     const char *key = inKey;
+    UResType type;
 
     if (status==NULL || U_FAILURE(*status)) {
         return fillIn;
@@ -1365,7 +1762,8 @@ U_CAPI UResourceBundle* U_EXPORT2 ures_getByKey(const UResourceBundle *resB, con
         return fillIn;
     }
 
-    if(RES_GET_TYPE(resB->fRes) == URES_TABLE || RES_GET_TYPE(resB->fRes) == URES_TABLE32) {
+    type = RES_GET_TYPE(resB->fRes);
+    if(URES_IS_TABLE(type)) {
         int32_t t;
         res = res_getTableItemByKey(&(resB->fResData), resB->fRes, &t, &key);
         if(res == RES_BOGUS) {
@@ -1408,6 +1806,7 @@ U_CAPI const UChar* U_EXPORT2 ures_getStringByKey(const UResourceBundle *resB, c
     Resource res = RES_BOGUS;
     UResourceDataEntry *realData = NULL;
     const char* key = inKey;
+    UResType type;
 
     if (status==NULL || U_FAILURE(*status)) {
         return NULL;
@@ -1417,7 +1816,8 @@ U_CAPI const UChar* U_EXPORT2 ures_getStringByKey(const UResourceBundle *resB, c
         return NULL;
     }
 
-    if(RES_GET_TYPE(resB->fRes) == URES_TABLE || RES_GET_TYPE(resB->fRes) == URES_TABLE32) {
+    type = RES_GET_TYPE(resB->fRes);
+    if(URES_IS_TABLE(type)) {
         int32_t t=0;
 
         res = res_getTableItemByKey(&(resB->fResData), resB->fRes, &t, &key);
@@ -1429,9 +1829,7 @@ U_CAPI const UChar* U_EXPORT2 ures_getStringByKey(const UResourceBundle *resB, c
                 if(U_SUCCESS(*status)) {
                     switch (RES_GET_TYPE(res)) {
                     case URES_STRING:
-                    case URES_TABLE:
-                    case URES_TABLE32:
-                    case URES_ARRAY:
+                    case URES_STRING_V2:
                         return res_getString(rd, res, len);
                     case URES_ALIAS:
                       {
@@ -1453,9 +1851,7 @@ U_CAPI const UChar* U_EXPORT2 ures_getStringByKey(const UResourceBundle *resB, c
         } else {
             switch (RES_GET_TYPE(res)) {
             case URES_STRING:
-            case URES_TABLE:
-            case URES_TABLE32:
-            case URES_ARRAY:
+            case URES_STRING_V2:
                 return res_getString(&(resB->fResData), res, len);
             case URES_ALIAS:
               {
@@ -1489,6 +1885,16 @@ U_CAPI const UChar* U_EXPORT2 ures_getStringByKey(const UResourceBundle *resB, c
     return NULL;
 }
 
+U_CAPI const char * U_EXPORT2
+ures_getUTF8StringByKey(const UResourceBundle *resB,
+                        const char *key,
+                        char *dest, int32_t *pLength,
+                        UBool forceCopy,
+                        UErrorCode *status) {
+    int32_t length16;
+    const UChar *s16 = ures_getStringByKey(resB, key, &length16, status);
+    return ures_toUTF8String(s16, length16, dest, pLength, forceCopy, status);
+}
 
 /* TODO: clean from here down */
 
@@ -1496,8 +1902,8 @@ U_CAPI const UChar* U_EXPORT2 ures_getStringByKey(const UResourceBundle *resB, c
  *  INTERNAL: Get the name of the first real locale (not placeholder) 
  *  that has resource bundle data.
  */
-U_CAPI const char*  U_EXPORT2
-ures_getLocale(const UResourceBundle* resourceBundle, UErrorCode* status)
+U_INTERNAL const char*  U_EXPORT2
+ures_getLocaleInternal(const UResourceBundle* resourceBundle, UErrorCode* status)
 {
     if (status==NULL || U_FAILURE(*status)) {
         return NULL;
@@ -1510,6 +1916,14 @@ ures_getLocale(const UResourceBundle* resourceBundle, UErrorCode* status)
     }
 }
 
+U_CAPI const char* U_EXPORT2 
+ures_getLocale(const UResourceBundle* resourceBundle, 
+               UErrorCode* status)
+{
+  return ures_getLocaleInternal(resourceBundle, status);
+}
+
+
 U_CAPI const char* U_EXPORT2 
 ures_getLocaleByType(const UResourceBundle* resourceBundle, 
                      ULocDataLocaleType type, 
@@ -1524,13 +1938,10 @@ ures_getLocaleByType(const UResourceBundle* resourceBundle,
         switch(type) {
         case ULOC_ACTUAL_LOCALE:
             return resourceBundle->fData->fName;
-            break;
         case ULOC_VALID_LOCALE:
             return resourceBundle->fTopLevelData->fName;
-            break;
         case ULOC_REQUESTED_LOCALE:
             return NULL;
-            break;
         default:
             *status = U_ILLEGAL_ARGUMENT_ERROR;
             return NULL;
@@ -1538,52 +1949,6 @@ ures_getLocaleByType(const UResourceBundle* resourceBundle,
     }
 }
 
-
-/*
-U_CFUNC void ures_setResPath(UResourceBundle *resB, const char* toAdd) {
-  if(resB->fResPath == NULL) {
-    resB->fResPath = resB->fResBuf;
-    *(resB->fResPath) = 0;
-  } 
-  resB->fResPathLen = uprv_strlen(toAdd);
-  if(RES_BUFSIZE <= resB->fResPathLen+1) {
-    if(resB->fResPath == resB->fResBuf) {
-      resB->fResPath = (char *)uprv_malloc((resB->fResPathLen+1)*sizeof(char));
-    } else {
-      resB->fResPath = (char *)uprv_realloc(resB->fResPath, (resB->fResPathLen+1)*sizeof(char));
-    }
-  }
-  uprv_strcpy(resB->fResPath, toAdd);
-}
-*/
-U_CFUNC void ures_appendResPath(UResourceBundle *resB, const char* toAdd, int32_t lenToAdd) {
-  int32_t resPathLenOrig = resB->fResPathLen;
-  if(resB->fResPath == NULL) {
-    resB->fResPath = resB->fResBuf;
-    *(resB->fResPath) = 0;
-    resB->fResPathLen = 0;
-  } 
-  resB->fResPathLen += lenToAdd;
-  if(RES_BUFSIZE <= resB->fResPathLen+1) {
-    if(resB->fResPath == resB->fResBuf) {
-      resB->fResPath = (char *)uprv_malloc((resB->fResPathLen+1)*sizeof(char));
-      uprv_strcpy(resB->fResPath, resB->fResBuf);
-    } else {
-      resB->fResPath = (char *)uprv_realloc(resB->fResPath, (resB->fResPathLen+1)*sizeof(char));
-    }
-  }
-  uprv_strcpy(resB->fResPath + resPathLenOrig, toAdd);
-}
-
-U_CFUNC void ures_freeResPath(UResourceBundle *resB) {
-  if (resB->fResPath && resB->fResPath != resB->fResBuf) {
-    uprv_free(resB->fResPath);
-  }
-  resB->fResPath = NULL;
-  resB->fResPathLen = 0;
-}
-
-
 U_CFUNC const char* ures_getName(const UResourceBundle* resB) {
   if(resB == NULL) {
     return NULL;
@@ -1592,6 +1957,7 @@ U_CFUNC const char* ures_getName(const UResourceBundle* resB) {
   return resB->fData->fName;
 }
 
+#ifdef URES_DEBUG
 U_CFUNC const char* ures_getPath(const UResourceBundle* resB) {
   if(resB == NULL) {
     return NULL;
@@ -1599,6 +1965,7 @@ U_CFUNC const char* ures_getPath(const UResourceBundle* resB) {
 
   return resB->fData->fPath;
 }
+#endif
 
 /* OLD API implementation */
 
@@ -1611,37 +1978,31 @@ U_CAPI void  U_EXPORT2
 ures_openFillIn(UResourceBundle *r, const char* path,
                     const char* localeID, UErrorCode* status) {
     if(r == NULL) {
-        *status = U_INTERNAL_PROGRAM_ERROR;
+        *status = U_ILLEGAL_ARGUMENT_ERROR;
     } else {
         UResourceDataEntry *firstData;
+        UBool isStackObject = ures_isStackObject(r);
+
+        ures_closeBundle(r, FALSE);
+        uprv_memset(r, 0, sizeof(UResourceBundle));
+        ures_setIsStackObject(r, isStackObject);
         r->fHasFallback = TRUE;
         r->fIsTopLevel = TRUE;
-        r->fKey = NULL;
-        r->fVersion = NULL;
         r->fIndex = -1;
-        if(r->fData != NULL) {
-            entryClose(r->fData);
-        }
-        if(r->fVersion != NULL) {
-            uprv_free(r->fVersion);
-        }
         r->fData = entryOpen(path, localeID, status);
+        if(U_FAILURE(*status)) {
+            return;
+        }
         /* this is a quick fix to get regular data in bundle - until construction is cleaned up */
         firstData = r->fData;
         while(firstData->fBogus != U_ZERO_ERROR && firstData->fParent != NULL) {
             firstData = firstData->fParent;
         }
-        r->fResData.data = firstData->fData.data;
-        r->fResData.pRoot = firstData->fData.pRoot;
-        r->fResData.rootRes = firstData->fData.rootRes;
+        uprv_memcpy(&r->fResData, &firstData->fData, sizeof(ResourceData));
+        r->fHasFallback=(UBool)!r->fResData.noFallback;
         r->fRes = r->fResData.rootRes;
         r->fSize = res_countArrayItems(&(r->fResData), r->fRes);
-        /*r->fParent = RES_BOGUS;*/
-        /*r->fResPath = NULL;*/
-        r->fParentRes = NULL;
         r->fTopLevelData = r->fData;
-
-        ures_freeResPath(r);
     }
 }
 
@@ -1653,14 +2014,13 @@ ures_open(const char* path,
     char canonLocaleID[100];
     UResourceDataEntry *hasData = NULL;
     UResourceBundle *r;
-    int32_t length;
 
     if(status == NULL || U_FAILURE(*status)) {
         return NULL;
     }
 
     /* first "canonicalize" the locale ID */
-    length = uloc_getBaseName(localeID, canonLocaleID, sizeof(canonLocaleID), status);
+    uloc_getBaseName(localeID, canonLocaleID, sizeof(canonLocaleID), status);
     if(U_FAILURE(*status) || *status == U_STRING_NOT_TERMINATED_WARNING) {
         *status = U_ILLEGAL_ARGUMENT_ERROR;
         return NULL;
@@ -1672,18 +2032,16 @@ ures_open(const char* path,
         return NULL;
     }
 
+    uprv_memset(r, 0, sizeof(UResourceBundle));
     r->fHasFallback = TRUE;
     r->fIsTopLevel = TRUE;
     ures_setIsStackObject(r, FALSE);
-    r->fKey = NULL;
-    r->fVersion = NULL;
     r->fIndex = -1;
     r->fData = entryOpen(path, canonLocaleID, status);
     if(U_FAILURE(*status)) {
         uprv_free(r);
         return NULL;
     }
-    r->fParentRes = NULL;
     r->fTopLevelData = r->fData;
 
     hasData = r->fData;
@@ -1699,14 +2057,10 @@ ures_open(const char* path,
         }
     }
 
-    r->fResData.data = hasData->fData.data;
-    r->fResData.pRoot = hasData->fData.pRoot;
-    r->fResData.rootRes = hasData->fData.rootRes;
+    uprv_memcpy(&r->fResData, &hasData->fData, sizeof(ResourceData));
+    r->fHasFallback=(UBool)!r->fResData.noFallback;
     r->fRes = r->fResData.rootRes;
-    /*r->fParent = RES_BOGUS;*/
     r->fSize = res_countArrayItems(&(r->fResData), r->fRes);
-    r->fResPath = NULL;
-    r->fResPathLen = 0;
     /*
     if(r->fData->fPath != NULL) {
       ures_setResPath(r, r->fData->fPath);
@@ -1761,15 +2115,14 @@ ures_openDirect(const char* path, const char* localeID, UErrorCode* status) {
 
     r->fKey = NULL;
     r->fVersion = NULL;
-    r->fResData.data = r->fData->fData.data;
-    r->fResData.pRoot = r->fData->fData.pRoot;
-    r->fResData.rootRes = r->fData->fData.rootRes;
+    uprv_memcpy(&r->fResData, &r->fData->fData, sizeof(ResourceData));
+    /* r->fHasFallback remains FALSE here in ures_openDirect() */
     r->fRes = r->fResData.rootRes;
     /*r->fParent = RES_BOGUS;*/
     r->fSize = res_countArrayItems(&(r->fResData), r->fRes);
     r->fResPath = NULL;
     r->fResPathLen = 0;
-    r->fParentRes = NULL;
+    /*r->fParentRes = NULL;*/
     r->fTopLevelData = r->fData;
 
     return r;
@@ -1806,32 +2159,18 @@ ures_countArrayItems(const UResourceBundle* resourceBundle,
     }
 }
 
-U_CAPI void  U_EXPORT2
-ures_close(UResourceBundle*    resB)
-{
-    if(resB != NULL) {
-        if(resB->fData != NULL) {
-            entryClose(resB->fData);
-        }
-        if(resB->fVersion != NULL) {
-            uprv_free(resB->fVersion);
-        }
-        ures_freeResPath(resB);
-
-        if(ures_isStackObject(resB) == FALSE) {
-            uprv_free(resB);
-        }
-        else {
-#if 0 /*U_DEBUG*/
-            /* poison the data */
-            uprv_memset(resB, -1, sizeof(UResourceBundle));
-#endif
-        }
-    }
-}
-
-U_CAPI const char*  U_EXPORT2
-ures_getVersionNumber(const UResourceBundle*   resourceBundle)
+/**
+ * Internal function.
+ * Return the version number associated with this ResourceBundle as a string.
+ *
+ * @param resourceBundle The resource bundle for which the version is checked.
+ * @return  A version number string as specified in the resource bundle or its parent.
+ *          The caller does not own this string.
+ * @see ures_getVersion
+ * @internal
+ */
+U_INTERNAL const char* U_EXPORT2 
+ures_getVersionNumberInternal(const UResourceBundle *resourceBundle)
 {
     if (!resourceBundle) return NULL;
 
@@ -1857,23 +2196,33 @@ ures_getVersionNumber(const UResourceBundle*   resourceBundle)
 
 
         ((UResourceBundle *)resourceBundle)->fVersion = (char *)uprv_malloc(1 + len); 
+        /* Check for null pointer. */
+        if (((UResourceBundle *)resourceBundle)->fVersion == NULL) {
+            return NULL;
+        }
        
         if(minor_len > 0) {
             u_UCharsToChars(minor_version, resourceBundle->fVersion , minor_len);
             resourceBundle->fVersion[len] =  '\0';
         }
         else {
-          uprv_strcpy(resourceBundle->fVersion, kDefaultMinorVersion);
+            uprv_strcpy(resourceBundle->fVersion, kDefaultMinorVersion);
         }
     }
 
     return resourceBundle->fVersion;
 }
 
+U_CAPI const char*  U_EXPORT2
+ures_getVersionNumber(const UResourceBundle*   resourceBundle)
+{
+    return ures_getVersionNumberInternal(resourceBundle);
+}
+
 U_CAPI void U_EXPORT2 ures_getVersion(const UResourceBundle* resB, UVersionInfo versionInfo) {
     if (!resB) return;
 
-    u_versionFromString(versionInfo, ures_getVersionNumber(resB));
+    u_versionFromString(versionInfo, ures_getVersionNumberInternal(resB));
 }
 
 /** Tree support functions *******************************/
@@ -1916,7 +2265,7 @@ ures_loc_nextLocale(UEnumeration* en,
     int32_t len = 0;
     if(ures_hasNext(res) && (k = ures_getNextResource(res, &ctx->curr, status))) {
         result = ures_getKey(k);
-        len = uprv_strlen(result);
+        len = (int32_t)uprv_strlen(result);
     }
     if (resultLength) {
         *resultLength = len;
@@ -1946,7 +2295,7 @@ static const UEnumeration gLocalesEnum = {
 U_CAPI UEnumeration* U_EXPORT2
 ures_openAvailableLocales(const char *path, UErrorCode *status)
 {
-    UResourceBundle *index = NULL;
+    UResourceBundle *idx = NULL;
     UEnumeration *en = NULL;
     ULocalesContext *myContext = NULL;
     
@@ -1965,8 +2314,8 @@ ures_openAvailableLocales(const char *path, UErrorCode *status)
     
     ures_initStackObject(&myContext->installed);
     ures_initStackObject(&myContext->curr);
-    index = ures_openDirect(path, INDEX_LOCALE_NAME, status);
-    ures_getByKey(index, INDEX_TAG, &myContext->installed, status);
+    idx = ures_openDirect(path, INDEX_LOCALE_NAME, status);
+    ures_getByKey(idx, INDEX_TAG, &myContext->installed, status);
     if(U_SUCCESS(*status)) {
 #if defined(URES_TREE_DEBUG)
         fprintf(stderr, "Got %s::%s::[%s] : %s\n", 
@@ -1983,11 +2332,21 @@ ures_openAvailableLocales(const char *path, UErrorCode *status)
         en = NULL;
     }
     
-    ures_close(index);
+    ures_close(idx);
     
     return en;
 }
 
+static UBool isLocaleInList(UEnumeration *locEnum, const char *locToSearch, UErrorCode *status) {
+    const char *loc;
+    while ((loc = uenum_next(locEnum, NULL, status)) != NULL) {
+        if (uprv_strcmp(loc, locToSearch) == 0) {
+            return TRUE;
+        }
+    }
+    return FALSE;
+}
+
 U_CAPI int32_t U_EXPORT2
 ures_getFunctionalEquivalent(char *result, int32_t resultCapacity,
                              const char *path, const char *resName, const char *keyword, const char *locid,
@@ -2005,9 +2364,6 @@ ures_getFunctionalEquivalent(char *result, int32_t resultCapacity,
     UErrorCode subStatus = U_ZERO_ERROR;
     int32_t length = 0;
     if(U_FAILURE(*status)) return 0;
-    if(isAvailable) { 
-        *isAvailable = TRUE;
-    }
     uloc_getKeywordValue(locid, keyword, kwVal, 1024-1,&subStatus);
     if(!uprv_strcmp(kwVal, DEFAULT_TAG)) {
         kwVal[0]=0;
@@ -2023,7 +2379,16 @@ ures_getFunctionalEquivalent(char *result, int32_t resultCapacity,
     
     uprv_strcpy(parent, base);
     uprv_strcpy(found, base);
-    
+
+    if(isAvailable) { 
+        UEnumeration *locEnum = ures_openAvailableLocales(path, &subStatus);
+        *isAvailable = TRUE;
+        if (U_SUCCESS(subStatus)) {
+            *isAvailable = isLocaleInList(locEnum, parent, &subStatus);
+        }
+        uenum_close(locEnum);
+    }
+
     if(U_FAILURE(subStatus)) {
         *status = subStatus;
         return 0;
@@ -2033,7 +2398,8 @@ ures_getFunctionalEquivalent(char *result, int32_t resultCapacity,
         subStatus = U_ZERO_ERROR;
         res = ures_open(path, parent, &subStatus);
         if(((subStatus == U_USING_FALLBACK_WARNING) ||
-            (subStatus == U_USING_DEFAULT_WARNING)) && isAvailable) {
+            (subStatus == U_USING_DEFAULT_WARNING)) && isAvailable)
+        {
             *isAvailable = FALSE;
         }
         isAvailable = NULL; /* only want to set this the first time around */
@@ -2073,11 +2439,14 @@ ures_getFunctionalEquivalent(char *result, int32_t resultCapacity,
         }
         
         subStatus = U_ZERO_ERROR;
-        
-        uprv_strcpy(found, parent);
-        uloc_getParent(found,parent,1023,&subStatus);
+
+        if (res != NULL) {
+            uprv_strcpy(found, ures_getLocaleByType(res, ULOC_VALID_LOCALE, &subStatus));
+        }
+
+        uloc_getParent(found,parent,sizeof(parent),&subStatus);
         ures_close(res);
-    } while(!defVal[0] && *found && U_SUCCESS(*status));
+    } while(!defVal[0] && *found && uprv_strcmp(found, "root") != 0 && U_SUCCESS(*status));
     
     /* Now, see if we can find the kwVal collator.. start the search over.. */
     uprv_strcpy(parent, base);
@@ -2266,7 +2635,7 @@ ures_getFunctionalEquivalent(char *result, int32_t resultCapacity,
     ures_close(&bund1);
     ures_close(&bund2);
     
-    length = uprv_strlen(found);
+    length = (int32_t)uprv_strlen(found);
 
     if(U_SUCCESS(*status)) {
         int32_t copyLength = uprv_min(length, resultCapacity);
@@ -2307,8 +2676,8 @@ ures_getKeywordValues(const char *path, const char *keyword, UErrorCode *status)
     locs = ures_openAvailableLocales(path, status);
     
     if(U_FAILURE(*status)) {
-      ures_close(&item);
-      ures_close(&subItem);
+        ures_close(&item);
+        ures_close(&subItem);
         return NULL;
     }
     
@@ -2344,7 +2713,7 @@ ures_getKeywordValues(const char *path, const char *keyword, UErrorCode *status)
             && U_SUCCESS(subStatus)) {
             const char *k;
             int32_t i;
-            k = ures_getKey(&subItem);
+            k = ures_getKey(subPtr);
             
 #if defined(URES_TREE_DEBUG)
             /* fprintf(stderr, "%s | %s | %s | %s\n", path?path:"<ICUDATA>", keyword, locale, k); */
@@ -2355,7 +2724,7 @@ ures_getKeywordValues(const char *path, const char *keyword, UErrorCode *status)
                 }
             }
             if(k && *k) {
-                int32_t kLen = uprv_strlen(k);
+                int32_t kLen = (int32_t)uprv_strlen(k);
                 if(!uprv_strcmp(k,DEFAULT_TAG)) {
                     continue; /* don't need 'default'. */
                 }
@@ -2387,5 +2756,77 @@ ures_getKeywordValues(const char *path, const char *keyword, UErrorCode *status)
 #endif
     return uloc_openKeywordList(valuesBuf, valuesIndex, status);
 }
+#if 0
+/* This code isn't needed, and given the documentation warnings the implementation is suspect */
+U_INTERNAL UBool U_EXPORT2
+ures_equal(const UResourceBundle* res1, const UResourceBundle* res2){
+    if(res1==NULL || res2==NULL){
+        return res1==res2; /* pointer comparision */
+    }
+    if(res1->fKey==NULL||  res2->fKey==NULL){
+        return (res1->fKey==res2->fKey);
+    }else{
+        if(uprv_strcmp(res1->fKey, res2->fKey)!=0){
+            return FALSE;
+        }
+    }
+    if(uprv_strcmp(res1->fData->fName, res2->fData->fName)!=0){
+        return FALSE;
+    }
+    if(res1->fData->fPath == NULL||  res2->fData->fPath==NULL){
+        return (res1->fData->fPath == res2->fData->fPath);
+    }else{
+        if(uprv_strcmp(res1->fData->fPath, res2->fData->fPath)!=0){
+            return FALSE;
+        }
+    }
+    if(uprv_strcmp(res1->fData->fParent->fName, res2->fData->fParent->fName)!=0){
+        return FALSE;
+    }
+    if(uprv_strcmp(res1->fData->fParent->fPath, res2->fData->fParent->fPath)!=0){
+        return FALSE;
+    }
+    if(uprv_strncmp(res1->fResPath, res2->fResPath, res1->fResPathLen)!=0){
+        return FALSE;
+    }
+    if(res1->fRes != res2->fRes){
+        return FALSE;
+    }
+    return TRUE;
+}
+U_INTERNAL UResourceBundle* U_EXPORT2
+ures_clone(const UResourceBundle* res, UErrorCode* status){
+    UResourceBundle* bundle = NULL;
+    UResourceBundle* ret = NULL;
+    if(U_FAILURE(*status) || res == NULL){
+        return NULL;
+    }
+    bundle = ures_open(res->fData->fPath, res->fData->fName, status);
+    if(res->fResPath!=NULL){
+        ret = ures_findSubResource(bundle, res->fResPath, NULL, status);
+        ures_close(bundle);
+    }else{
+        ret = bundle;
+    }
+    return ret;
+}
+U_INTERNAL const UResourceBundle* U_EXPORT2
+ures_getParentBundle(const UResourceBundle* res){
+    if(res==NULL){
+        return NULL;
+    }
+    return res->fParentRes;
+}
+#endif
+
+U_INTERNAL void U_EXPORT2
+ures_getVersionByKey(const UResourceBundle* res, const char *key, UVersionInfo ver, UErrorCode *status) {
+  const UChar *str;
+  int32_t len;
+  str = ures_getStringByKey(res, key, &len, status);
+  if(U_SUCCESS(*status)) {
+    u_versionFromUString(ver, str);
+  } 
+}
 
 /* eof */