16f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org/*
26f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*******************************************************************************
36f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*                                                                             *
46f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org* Copyright (C) 1999-2012, International Business Machines Corporation        *
56f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*               and others. All Rights Reserved.                              *
66f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*                                                                             *
76f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*******************************************************************************
86f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*   file name:  uresdata.c
96f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*   encoding:   US-ASCII
106f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*   tab size:   8 (not used)
116f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*   indentation:4
126f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*
136f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*   created on: 1999dec08
146f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*   created by: Markus W. Scherer
156f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org* Modification History:
166f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*
176f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*   Date        Name        Description
186f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*   06/20/2000  helena      OS/400 port changes; mostly typecast.
196f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*   06/24/02    weiv        Added support for resource sharing
206f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*/
216f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
226f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "unicode/utypes.h"
236f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "unicode/udata.h"
246f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "unicode/ustring.h"
256f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "unicode/utf16.h"
266f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "cmemory.h"
276f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "cstring.h"
286f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "uarrsort.h"
296f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "udataswp.h"
306f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "ucol_swp.h"
316f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "uinvchar.h"
326f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "uresdata.h"
336f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "uresimp.h"
346f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "uassert.h"
356f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
366f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#define LENGTHOF(array) (int32_t)(sizeof(array)/sizeof((array)[0]))
376f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
386f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org/*
396f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * Resource access helpers
406f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org */
416f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
426f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org/* get a const char* pointer to the key with the keyOffset byte offset from pRoot */
436f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#define RES_GET_KEY16(pResData, keyOffset) \
446f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    ((keyOffset)<(pResData)->localKeyLimit ? \
456f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        (const char *)(pResData)->pRoot+(keyOffset) : \
466f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        (pResData)->poolBundleKeys+(keyOffset)-(pResData)->localKeyLimit)
476f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
486f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#define RES_GET_KEY32(pResData, keyOffset) \
496f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    ((keyOffset)>=0 ? \
506f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        (const char *)(pResData)->pRoot+(keyOffset) : \
516f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        (pResData)->poolBundleKeys+((keyOffset)&0x7fffffff))
526f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
536f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#define URESDATA_ITEM_NOT_FOUND -1
546f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
556f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org/* empty resources, returned when the resource offset is 0 */
566f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstatic const uint16_t gEmpty16=0;
576f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
586f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstatic const struct {
596f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    int32_t length;
606f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    int32_t res;
616f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org} gEmpty32={ 0, 0 };
626f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
636f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstatic const struct {
646f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    int32_t length;
656f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    UChar nul;
666f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    UChar pad;
676f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org} gEmptyString={ 0, 0, 0 };
686f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
696f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org/*
706f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * All the type-access functions assume that
716f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * the resource is of the expected type.
726f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org */
736f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
746f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstatic int32_t
756f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org_res_findTableItem(const ResourceData *pResData, const uint16_t *keyOffsets, int32_t length,
766f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                   const char *key, const char **realKey) {
776f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    const char *tableKey;
786f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    int32_t mid, start, limit;
796f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    int result;
806f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
816f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /* do a binary search for the key */
826f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    start=0;
836f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    limit=length;
846f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    while(start<limit) {
856f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        mid = (start + limit) / 2;
866f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        tableKey = RES_GET_KEY16(pResData, keyOffsets[mid]);
876f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if (pResData->useNativeStrcmp) {
886f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            result = uprv_strcmp(key, tableKey);
896f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        } else {
906f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            result = uprv_compareInvCharsAsAscii(key, tableKey);
916f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
926f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if (result < 0) {
936f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            limit = mid;
946f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        } else if (result > 0) {
956f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            start = mid + 1;
966f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        } else {
976f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            /* We found it! */
986f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            *realKey=tableKey;
996f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            return mid;
1006f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
1016f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
1026f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return URESDATA_ITEM_NOT_FOUND;  /* not found or table is empty. */
1036f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
1046f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1056f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstatic int32_t
1066f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org_res_findTable32Item(const ResourceData *pResData, const int32_t *keyOffsets, int32_t length,
1076f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                     const char *key, const char **realKey) {
1086f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    const char *tableKey;
1096f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    int32_t mid, start, limit;
1106f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    int result;
1116f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1126f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /* do a binary search for the key */
1136f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    start=0;
1146f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    limit=length;
1156f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    while(start<limit) {
1166f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        mid = (start + limit) / 2;
1176f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        tableKey = RES_GET_KEY32(pResData, keyOffsets[mid]);
1186f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if (pResData->useNativeStrcmp) {
1196f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            result = uprv_strcmp(key, tableKey);
1206f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        } else {
1216f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            result = uprv_compareInvCharsAsAscii(key, tableKey);
1226f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
1236f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if (result < 0) {
1246f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            limit = mid;
1256f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        } else if (result > 0) {
1266f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            start = mid + 1;
1276f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        } else {
1286f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            /* We found it! */
1296f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            *realKey=tableKey;
1306f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            return mid;
1316f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
1326f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
1336f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return URESDATA_ITEM_NOT_FOUND;  /* not found or table is empty. */
1346f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
1356f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1366f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org/* helper for res_load() ---------------------------------------------------- */
1376f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1386f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstatic UBool U_CALLCONV
1396f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgisAcceptable(void *context,
1406f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org             const char *type, const char *name,
1416f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org             const UDataInfo *pInfo) {
1426f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    uprv_memcpy(context, pInfo->formatVersion, 4);
1436f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return (UBool)(
1446f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        pInfo->size>=20 &&
1456f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        pInfo->isBigEndian==U_IS_BIG_ENDIAN &&
1466f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        pInfo->charsetFamily==U_CHARSET_FAMILY &&
1476f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        pInfo->sizeofUChar==U_SIZEOF_UCHAR &&
1486f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        pInfo->dataFormat[0]==0x52 &&   /* dataFormat="ResB" */
1496f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        pInfo->dataFormat[1]==0x65 &&
1506f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        pInfo->dataFormat[2]==0x73 &&
1516f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        pInfo->dataFormat[3]==0x42 &&
1526f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        (pInfo->formatVersion[0]==1 || pInfo->formatVersion[0]==2));
1536f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
1546f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1556f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org/* semi-public functions ---------------------------------------------------- */
1566f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1576f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstatic void
1586f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgres_init(ResourceData *pResData,
1596f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         UVersionInfo formatVersion, const void *inBytes, int32_t length,
1606f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         UErrorCode *errorCode) {
1616f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    UResType rootType;
1626f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1636f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /* get the root resource */
1646f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    pResData->pRoot=(const int32_t *)inBytes;
1656f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    pResData->rootRes=(Resource)*pResData->pRoot;
1666f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    pResData->p16BitUnits=&gEmpty16;
1676f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1686f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /* formatVersion 1.1 must have a root item and at least 5 indexes */
1696f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(length>=0 && (length/4)<((formatVersion[0]==1 && formatVersion[1]==0) ? 1 : 1+5)) {
1706f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        *errorCode=U_INVALID_FORMAT_ERROR;
1716f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        res_unload(pResData);
1726f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return;
1736f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
1746f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1756f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /* currently, we accept only resources that have a Table as their roots */
1766f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    rootType=(UResType)RES_GET_TYPE(pResData->rootRes);
1776f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(!URES_IS_TABLE(rootType)) {
1786f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        *errorCode=U_INVALID_FORMAT_ERROR;
1796f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        res_unload(pResData);
1806f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return;
1816f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
1826f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1836f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(formatVersion[0]==1 && formatVersion[1]==0) {
1846f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        pResData->localKeyLimit=0x10000;  /* greater than any 16-bit key string offset */
1856f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    } else {
1866f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* bundles with formatVersion 1.1 and later contain an indexes[] array */
1876f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        const int32_t *indexes=pResData->pRoot+1;
1886f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        int32_t indexLength=indexes[URES_INDEX_LENGTH]&0xff;
1896f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(indexLength<=URES_INDEX_MAX_TABLE_LENGTH) {
1906f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            *errorCode=U_INVALID_FORMAT_ERROR;
1916f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            res_unload(pResData);
1926f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            return;
1936f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
1946f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if( length>=0 &&
1956f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            (length<((1+indexLength)<<2) ||
1966f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org             length<(indexes[URES_INDEX_BUNDLE_TOP]<<2))
1976f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        ) {
1986f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            *errorCode=U_INVALID_FORMAT_ERROR;
1996f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            res_unload(pResData);
2006f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            return;
2016f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
2026f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(indexes[URES_INDEX_KEYS_TOP]>(1+indexLength)) {
2036f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            pResData->localKeyLimit=indexes[URES_INDEX_KEYS_TOP]<<2;
2046f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
2056f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(indexLength>URES_INDEX_ATTRIBUTES) {
2066f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            int32_t att=indexes[URES_INDEX_ATTRIBUTES];
2076f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            pResData->noFallback=(UBool)(att&URES_ATT_NO_FALLBACK);
2086f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            pResData->isPoolBundle=(UBool)((att&URES_ATT_IS_POOL_BUNDLE)!=0);
2096f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            pResData->usesPoolBundle=(UBool)((att&URES_ATT_USES_POOL_BUNDLE)!=0);
2106f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
2116f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if((pResData->isPoolBundle || pResData->usesPoolBundle) && indexLength<=URES_INDEX_POOL_CHECKSUM) {
2126f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            *errorCode=U_INVALID_FORMAT_ERROR;
2136f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            res_unload(pResData);
2146f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            return;
2156f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
2166f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if( indexLength>URES_INDEX_16BIT_TOP &&
2176f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            indexes[URES_INDEX_16BIT_TOP]>indexes[URES_INDEX_KEYS_TOP]
2186f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        ) {
2196f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            pResData->p16BitUnits=(const uint16_t *)(pResData->pRoot+indexes[URES_INDEX_KEYS_TOP]);
2206f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
2216f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
2226f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
2236f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(formatVersion[0]==1 || U_CHARSET_FAMILY==U_ASCII_FAMILY) {
2246f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /*
2256f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         * formatVersion 1: compare key strings in native-charset order
2266f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         * formatVersion 2 and up: compare key strings in ASCII order
2276f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         */
2286f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        pResData->useNativeStrcmp=TRUE;
2296f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
2306f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
2316f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
2326f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgU_CAPI void U_EXPORT2
2336f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgres_read(ResourceData *pResData,
2346f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         const UDataInfo *pInfo, const void *inBytes, int32_t length,
2356f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         UErrorCode *errorCode) {
2366f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    UVersionInfo formatVersion;
2376f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
2386f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    uprv_memset(pResData, 0, sizeof(ResourceData));
2396f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(U_FAILURE(*errorCode)) {
2406f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return;
2416f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
2426f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(!isAcceptable(formatVersion, NULL, NULL, pInfo)) {
2436f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        *errorCode=U_INVALID_FORMAT_ERROR;
2446f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return;
2456f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
2466f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    res_init(pResData, formatVersion, inBytes, length, errorCode);
2476f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
2486f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
2496f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgU_CFUNC void
2506f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgres_load(ResourceData *pResData,
2516f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         const char *path, const char *name, UErrorCode *errorCode) {
2526f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    UVersionInfo formatVersion;
2536f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
2546f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    uprv_memset(pResData, 0, sizeof(ResourceData));
2556f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
2566f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /* load the ResourceBundle file */
2576f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    pResData->data=udata_openChoice(path, "res", name, isAcceptable, formatVersion, errorCode);
2586f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(U_FAILURE(*errorCode)) {
2596f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return;
2606f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
2616f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
2626f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /* get its memory and initialize *pResData */
2636f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    res_init(pResData, formatVersion, udata_getMemory(pResData->data), -1, errorCode);
2646f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
2656f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
2666f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgU_CFUNC void
2676f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgres_unload(ResourceData *pResData) {
2686f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(pResData->data!=NULL) {
2696f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        udata_close(pResData->data);
2706f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        pResData->data=NULL;
2716f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
2726f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
2736f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
2746f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstatic const int8_t gPublicTypes[URES_LIMIT] = {
2756f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    URES_STRING,
2766f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    URES_BINARY,
2776f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    URES_TABLE,
2786f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    URES_ALIAS,
2796f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
2806f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    URES_TABLE,     /* URES_TABLE32 */
2816f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    URES_TABLE,     /* URES_TABLE16 */
2826f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    URES_STRING,    /* URES_STRING_V2 */
2836f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    URES_INT,
2846f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
2856f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    URES_ARRAY,
2866f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    URES_ARRAY,     /* URES_ARRAY16 */
2876f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    URES_NONE,
2886f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    URES_NONE,
2896f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
2906f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    URES_NONE,
2916f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    URES_NONE,
2926f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    URES_INT_VECTOR,
2936f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    URES_NONE
2946f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org};
2956f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
2966f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgU_CAPI UResType U_EXPORT2
2976f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgres_getPublicType(Resource res) {
2986f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return (UResType)gPublicTypes[RES_GET_TYPE(res)];
2996f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
3006f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
3016f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgU_CAPI const UChar * U_EXPORT2
3026f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgres_getString(const ResourceData *pResData, Resource res, int32_t *pLength) {
3036f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    const UChar *p;
3046f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    uint32_t offset=RES_GET_OFFSET(res);
3056f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    int32_t length;
3066f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(RES_GET_TYPE(res)==URES_STRING_V2) {
3076f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        int32_t first;
3086f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        p=(const UChar *)(pResData->p16BitUnits+offset);
3096f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        first=*p;
3106f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(!U16_IS_TRAIL(first)) {
3116f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            length=u_strlen(p);
3126f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        } else if(first<0xdfef) {
3136f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            length=first&0x3ff;
3146f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            ++p;
3156f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        } else if(first<0xdfff) {
3166f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            length=((first-0xdfef)<<16)|p[1];
3176f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            p+=2;
3186f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        } else {
3196f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            length=((int32_t)p[1]<<16)|p[2];
3206f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            p+=3;
3216f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
3226f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    } else if(res==offset) /* RES_GET_TYPE(res)==URES_STRING */ {
3236f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        const int32_t *p32= res==0 ? &gEmptyString.length : pResData->pRoot+res;
3246f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        length=*p32++;
3256f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        p=(const UChar *)p32;
3266f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    } else {
3276f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        p=NULL;
3286f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        length=0;
3296f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
3306f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(pLength) {
3316f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        *pLength=length;
3326f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
3336f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return p;
3346f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
3356f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
3366f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgU_CAPI const UChar * U_EXPORT2
3376f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgres_getAlias(const ResourceData *pResData, Resource res, int32_t *pLength) {
3386f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    const UChar *p;
3396f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    uint32_t offset=RES_GET_OFFSET(res);
3406f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    int32_t length;
3416f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(RES_GET_TYPE(res)==URES_ALIAS) {
3426f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        const int32_t *p32= offset==0 ? &gEmptyString.length : pResData->pRoot+offset;
3436f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        length=*p32++;
3446f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        p=(const UChar *)p32;
3456f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    } else {
3466f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        p=NULL;
3476f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        length=0;
3486f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
3496f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(pLength) {
3506f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        *pLength=length;
3516f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
3526f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return p;
3536f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
3546f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
3556f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgU_CAPI const uint8_t * U_EXPORT2
3566f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgres_getBinary(const ResourceData *pResData, Resource res, int32_t *pLength) {
3576f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    const uint8_t *p;
3586f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    uint32_t offset=RES_GET_OFFSET(res);
3596f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    int32_t length;
3606f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(RES_GET_TYPE(res)==URES_BINARY) {
3616f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        const int32_t *p32= offset==0 ? (const int32_t*)&gEmpty32 : pResData->pRoot+offset;
3626f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        length=*p32++;
3636f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        p=(const uint8_t *)p32;
3646f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    } else {
3656f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        p=NULL;
3666f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        length=0;
3676f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
3686f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(pLength) {
3696f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        *pLength=length;
3706f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
3716f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return p;
3726f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
3736f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
3746f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
3756f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgU_CAPI const int32_t * U_EXPORT2
3766f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgres_getIntVector(const ResourceData *pResData, Resource res, int32_t *pLength) {
3776f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    const int32_t *p;
3786f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    uint32_t offset=RES_GET_OFFSET(res);
3796f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    int32_t length;
3806f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(RES_GET_TYPE(res)==URES_INT_VECTOR) {
3816f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        p= offset==0 ? (const int32_t *)&gEmpty32 : pResData->pRoot+offset;
3826f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        length=*p++;
3836f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    } else {
3846f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        p=NULL;
3856f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        length=0;
3866f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
3876f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(pLength) {
3886f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        *pLength=length;
3896f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
3906f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return p;
3916f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
3926f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
3936f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgU_CAPI int32_t U_EXPORT2
3946f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgres_countArrayItems(const ResourceData *pResData, Resource res) {
3956f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    uint32_t offset=RES_GET_OFFSET(res);
3966f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    switch(RES_GET_TYPE(res)) {
3976f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    case URES_STRING:
3986f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    case URES_STRING_V2:
3996f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    case URES_BINARY:
4006f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    case URES_ALIAS:
4016f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    case URES_INT:
4026f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    case URES_INT_VECTOR:
4036f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return 1;
4046f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    case URES_ARRAY:
4056f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    case URES_TABLE32:
4066f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return offset==0 ? 0 : *(pResData->pRoot+offset);
4076f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    case URES_TABLE:
4086f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return offset==0 ? 0 : *((const uint16_t *)(pResData->pRoot+offset));
4096f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    case URES_ARRAY16:
4106f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    case URES_TABLE16:
4116f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return pResData->p16BitUnits[offset];
4126f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    default:
4136f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return 0;
4146f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
4156f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
4166f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
4176f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgU_CAPI Resource U_EXPORT2
4186f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgres_getTableItemByKey(const ResourceData *pResData, Resource table,
4196f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                      int32_t *indexR, const char **key) {
4206f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    uint32_t offset=RES_GET_OFFSET(table);
4216f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    int32_t length;
4226f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    int32_t idx;
4236f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(key == NULL || *key == NULL) {
4246f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return RES_BOGUS;
4256f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
4266f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    switch(RES_GET_TYPE(table)) {
4276f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    case URES_TABLE: {
4286f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if (offset!=0) { /* empty if offset==0 */
4296f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            const uint16_t *p= (const uint16_t *)(pResData->pRoot+offset);
4306f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            length=*p++;
4316f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            *indexR=idx=_res_findTableItem(pResData, p, length, *key, key);
4326f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if(idx>=0) {
4336f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                const Resource *p32=(const Resource *)(p+length+(~length&1));
4346f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                return p32[idx];
4356f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
4366f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
4376f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        break;
4386f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
4396f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    case URES_TABLE16: {
4406f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        const uint16_t *p=pResData->p16BitUnits+offset;
4416f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        length=*p++;
4426f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        *indexR=idx=_res_findTableItem(pResData, p, length, *key, key);
4436f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(idx>=0) {
4446f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            return URES_MAKE_RESOURCE(URES_STRING_V2, p[length+idx]);
4456f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
4466f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        break;
4476f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
4486f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    case URES_TABLE32: {
4496f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if (offset!=0) { /* empty if offset==0 */
4506f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            const int32_t *p= pResData->pRoot+offset;
4516f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            length=*p++;
4526f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            *indexR=idx=_res_findTable32Item(pResData, p, length, *key, key);
4536f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if(idx>=0) {
4546f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                return (Resource)p[length+idx];
4556f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
4566f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
4576f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        break;
4586f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
4596f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    default:
4606f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        break;
4616f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
4626f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return RES_BOGUS;
4636f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
4646f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
4656f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgU_CAPI Resource U_EXPORT2
4666f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgres_getTableItemByIndex(const ResourceData *pResData, Resource table,
4676f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                        int32_t indexR, const char **key) {
4686f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    uint32_t offset=RES_GET_OFFSET(table);
4696f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    int32_t length;
4706f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    U_ASSERT(indexR>=0); /* to ensure the index is not negative */
4716f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    switch(RES_GET_TYPE(table)) {
4726f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    case URES_TABLE: {
4736f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if (offset != 0) { /* empty if offset==0 */
4746f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            const uint16_t *p= (const uint16_t *)(pResData->pRoot+offset);
4756f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            length=*p++;
4766f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if(indexR<length) {
4776f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                const Resource *p32=(const Resource *)(p+length+(~length&1));
4786f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                if(key!=NULL) {
4796f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    *key=RES_GET_KEY16(pResData, p[indexR]);
4806f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                }
4816f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                return p32[indexR];
4826f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
4836f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
4846f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        break;
4856f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
4866f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    case URES_TABLE16: {
4876f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        const uint16_t *p=pResData->p16BitUnits+offset;
4886f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        length=*p++;
4896f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(indexR<length) {
4906f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if(key!=NULL) {
4916f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                *key=RES_GET_KEY16(pResData, p[indexR]);
4926f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
4936f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            return URES_MAKE_RESOURCE(URES_STRING_V2, p[length+indexR]);
4946f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
4956f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        break;
4966f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
4976f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    case URES_TABLE32: {
4986f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if (offset != 0) { /* empty if offset==0 */
4996f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            const int32_t *p= pResData->pRoot+offset;
5006f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            length=*p++;
5016f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if(indexR<length) {
5026f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                if(key!=NULL) {
5036f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    *key=RES_GET_KEY32(pResData, p[indexR]);
5046f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                }
5056f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                return (Resource)p[length+indexR];
5066f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
5076f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
5086f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        break;
5096f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
5106f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    default:
5116f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        break;
5126f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
5136f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return RES_BOGUS;
5146f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
5156f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
5166f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgU_CAPI Resource U_EXPORT2
5176f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgres_getResource(const ResourceData *pResData, const char *key) {
5186f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    const char *realKey=key;
5196f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    int32_t idx;
5206f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return res_getTableItemByKey(pResData, pResData->rootRes, &idx, &realKey);
5216f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
5226f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
5236f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgU_CAPI Resource U_EXPORT2
5246f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgres_getArrayItem(const ResourceData *pResData, Resource array, int32_t indexR) {
5256f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    uint32_t offset=RES_GET_OFFSET(array);
5266f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    U_ASSERT(indexR>=0); /* to ensure the index is not negative */
5276f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    switch(RES_GET_TYPE(array)) {
5286f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    case URES_ARRAY: {
5296f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if (offset!=0) { /* empty if offset==0 */
5306f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            const int32_t *p= pResData->pRoot+offset;
5316f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if(indexR<*p) {
5326f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                return (Resource)p[1+indexR];
5336f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
5346f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
5356f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        break;
5366f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
5376f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    case URES_ARRAY16: {
5386f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        const uint16_t *p=pResData->p16BitUnits+offset;
5396f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(indexR<*p) {
5406f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            return URES_MAKE_RESOURCE(URES_STRING_V2, p[1+indexR]);
5416f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
5426f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        break;
5436f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
5446f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    default:
5456f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        break;
5466f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
5476f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return RES_BOGUS;
5486f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
5496f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
5506f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgU_CFUNC Resource
5516f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgres_findResource(const ResourceData *pResData, Resource r, char** path, const char** key) {
5526f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  /* we pass in a path. CollationElements/Sequence or zoneStrings/3/2 etc.
5536f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org   * iterates over a path and stops when a scalar resource is found. This
5546f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org   * CAN be an alias. Path gets set to the part that has not yet been processed.
5556f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org   */
5566f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
5576f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  char *pathP = *path, *nextSepP = *path;
5586f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  char *closeIndex = NULL;
5596f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  Resource t1 = r;
5606f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  Resource t2;
5616f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  int32_t indexR = 0;
5626f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  UResType type = (UResType)RES_GET_TYPE(t1);
5636f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
5646f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  /* if you come in with an empty path, you'll be getting back the same resource */
5656f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  if(!uprv_strlen(pathP)) {
5666f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org      return r;
5676f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  }
5686f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
5696f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  /* one needs to have an aggregate resource in order to search in it */
5706f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  if(!URES_IS_CONTAINER(type)) {
5716f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org      return RES_BOGUS;
5726f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  }
5736f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
5746f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  while(nextSepP && *pathP && t1 != RES_BOGUS && URES_IS_CONTAINER(type)) {
5756f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /* Iteration stops if: the path has been consumed, we found a non-existing
5766f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     * resource (t1 == RES_BOGUS) or we found a scalar resource (including alias)
5776f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     */
5786f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    nextSepP = uprv_strchr(pathP, RES_PATH_SEPARATOR);
5796f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /* if there are more separators, terminate string
5806f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     * and set path to the remaining part of the string
5816f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     */
5826f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(nextSepP != NULL) {
5836f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org      *nextSepP = 0; /* overwrite the separator with a NUL to terminate the key */
5846f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org      *path = nextSepP+1;
5856f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    } else {
5866f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org      *path = uprv_strchr(pathP, 0);
5876f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
5886f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
5896f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /* if the resource is a table */
5906f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /* try the key based access */
5916f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(URES_IS_TABLE(type)) {
5926f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org      *key = pathP;
5936f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org      t2 = res_getTableItemByKey(pResData, t1, &indexR, key);
5946f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org      if(t2 == RES_BOGUS) {
5956f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* if we fail to get the resource by key, maybe we got an index */
5966f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        indexR = uprv_strtol(pathP, &closeIndex, 10);
5976f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(closeIndex != pathP) {
5986f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org          /* if we indeed have an index, try to get the item by index */
5996f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org          t2 = res_getTableItemByIndex(pResData, t1, indexR, key);
6006f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
6016f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org      }
6026f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    } else if(URES_IS_ARRAY(type)) {
6036f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org      indexR = uprv_strtol(pathP, &closeIndex, 10);
6046f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org      if(closeIndex != pathP) {
6056f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        t2 = res_getArrayItem(pResData, t1, indexR);
6066f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org      } else {
6076f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        t2 = RES_BOGUS; /* have an array, but don't have a valid index */
6086f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org      }
6096f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org      *key = NULL;
6106f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    } else { /* can't do much here, except setting t2 to bogus */
6116f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org      t2 = RES_BOGUS;
6126f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
6136f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    t1 = t2;
6146f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    type = (UResType)RES_GET_TYPE(t1);
6156f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /* position pathP to next resource key/index */
6166f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    pathP = *path;
6176f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  }
6186f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
6196f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  return t1;
6206f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
6216f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
6226f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org/* resource bundle swapping ------------------------------------------------- */
6236f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
6246f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org/*
6256f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * Need to always enumerate the entire item tree,
6266f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * track the lowest address of any item to use as the limit for char keys[],
6276f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * track the highest address of any item to return the size of the data.
6286f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org *
6296f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * We should have thought of storing those in the data...
6306f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * It is possible to extend the data structure by putting additional values
6316f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * in places that are inaccessible by ordinary enumeration of the item tree.
6326f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * For example, additional integers could be stored at the beginning or
6336f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * end of the key strings; this could be indicated by a minor version number,
6346f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * and the data swapping would have to know about these values.
6356f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org *
6366f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * The data structure does not forbid keys to be shared, so we must swap
6376f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * all keys once instead of each key when it is referenced.
6386f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org *
6396f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * These swapping functions assume that a resource bundle always has a length
6406f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * that is a multiple of 4 bytes.
6416f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * Currently, this is trivially true because genrb writes bundle tree leaves
6426f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * physically first, before their branches, so that the root table with its
6436f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * array of resource items (uint32_t values) is always last.
6446f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org */
6456f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
6466f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org/* definitions for table sorting ------------------------ */
6476f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
6486f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org/*
6496f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * row of a temporary array
6506f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org *
6516f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * gets platform-endian key string indexes and sorting indexes;
6526f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * after sorting this array by keys, the actual key/value arrays are permutated
6536f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * according to the sorting indexes
6546f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org */
6556f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgtypedef struct Row {
6566f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    int32_t keyIndex, sortIndex;
6576f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org} Row;
6586f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
6596f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstatic int32_t
6606f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgures_compareRows(const void *context, const void *left, const void *right) {
6616f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    const char *keyChars=(const char *)context;
6626f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return (int32_t)uprv_strcmp(keyChars+((const Row *)left)->keyIndex,
6636f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                                keyChars+((const Row *)right)->keyIndex);
6646f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
6656f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
6666f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgtypedef struct TempTable {
6676f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    const char *keyChars;
6686f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    Row *rows;
6696f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    int32_t *resort;
6706f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    uint32_t *resFlags;
6716f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    int32_t localKeyLimit;
6726f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    uint8_t majorFormatVersion;
6736f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org} TempTable;
6746f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
6756f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgenum {
6766f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    STACK_ROW_CAPACITY=200
6776f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org};
6786f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
6796f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org/* The table item key string is not locally available. */
6806f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstatic const char *const gUnknownKey="";
6816f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
6826f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org/* resource table key for collation binaries: "%%CollationBin" */
6836f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstatic const UChar gCollationBinKey[]={
6846f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    0x25, 0x25,
6856f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    0x43, 0x6f, 0x6c, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e,
6866f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    0x42, 0x69, 0x6e,
6876f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    0
6886f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org};
6896f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
6906f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org/*
6916f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * swap one resource item
6926f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org */
6936f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstatic void
6946f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgures_swapResource(const UDataSwapper *ds,
6956f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                  const Resource *inBundle, Resource *outBundle,
6966f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                  Resource res, /* caller swaps res itself */
6976f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                  const char *key,
6986f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                  TempTable *pTempTable,
6996f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                  UErrorCode *pErrorCode) {
7006f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    const Resource *p;
7016f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    Resource *q;
7026f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    int32_t offset, count;
7036f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
7046f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    switch(RES_GET_TYPE(res)) {
7056f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    case URES_TABLE16:
7066f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    case URES_STRING_V2:
7076f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    case URES_INT:
7086f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    case URES_ARRAY16:
7096f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* integer, or points to 16-bit units, nothing to do here */
7106f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return;
7116f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    default:
7126f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        break;
7136f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
7146f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
7156f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /* all other types use an offset to point to their data */
7166f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    offset=(int32_t)RES_GET_OFFSET(res);
7176f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(offset==0) {
7186f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* special offset indicating an empty item */
7196f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return;
7206f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
7216f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(pTempTable->resFlags[offset>>5]&((uint32_t)1<<(offset&0x1f))) {
7226f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* we already swapped this resource item */
7236f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return;
7246f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    } else {
7256f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* mark it as swapped now */
7266f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        pTempTable->resFlags[offset>>5]|=((uint32_t)1<<(offset&0x1f));
7276f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
7286f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
7296f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    p=inBundle+offset;
7306f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    q=outBundle+offset;
7316f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
7326f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    switch(RES_GET_TYPE(res)) {
7336f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    case URES_ALIAS:
7346f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* physically same value layout as string, fall through */
7356f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    case URES_STRING:
7366f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        count=udata_readInt32(ds, (int32_t)*p);
7376f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* swap length */
7386f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        ds->swapArray32(ds, p, 4, q, pErrorCode);
7396f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* swap each UChar (the terminating NUL would not change) */
7406f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        ds->swapArray16(ds, p+1, 2*count, q+1, pErrorCode);
7416f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        break;
7426f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    case URES_BINARY:
7436f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        count=udata_readInt32(ds, (int32_t)*p);
7446f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* swap length */
7456f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        ds->swapArray32(ds, p, 4, q, pErrorCode);
7466f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* no need to swap or copy bytes - ures_swap() copied them all */
7476f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
7486f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* swap known formats */
7496f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#if !UCONFIG_NO_COLLATION
7506f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if( key!=NULL &&  /* the binary is in a table */
7516f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            (key!=gUnknownKey ?
7526f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                /* its table key string is "%%CollationBin" */
7536f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                0==ds->compareInvChars(ds, key, -1,
7546f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                                       gCollationBinKey, LENGTHOF(gCollationBinKey)-1) :
7556f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                /* its table key string is unknown but it looks like a collation binary */
7566f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                ucol_looksLikeCollationBinary(ds, p+1, count))
7576f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        ) {
7586f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            ucol_swapBinary(ds, p+1, count, q+1, pErrorCode);
7596f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
7606f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#endif
7616f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        break;
7626f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    case URES_TABLE:
7636f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    case URES_TABLE32:
7646f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        {
7656f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            const uint16_t *pKey16;
7666f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            uint16_t *qKey16;
7676f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
7686f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            const int32_t *pKey32;
7696f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            int32_t *qKey32;
7706f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
7716f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            Resource item;
7726f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            int32_t i, oldIndex;
7736f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
7746f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if(RES_GET_TYPE(res)==URES_TABLE) {
7756f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                /* get table item count */
7766f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                pKey16=(const uint16_t *)p;
7776f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                qKey16=(uint16_t *)q;
7786f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                count=ds->readUInt16(*pKey16);
7796f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
7806f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                pKey32=qKey32=NULL;
7816f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
7826f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                /* swap count */
7836f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                ds->swapArray16(ds, pKey16++, 2, qKey16++, pErrorCode);
7846f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
7856f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                offset+=((1+count)+1)/2;
7866f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            } else {
7876f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                /* get table item count */
7886f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                pKey32=(const int32_t *)p;
7896f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                qKey32=(int32_t *)q;
7906f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                count=udata_readInt32(ds, *pKey32);
7916f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
7926f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                pKey16=qKey16=NULL;
7936f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
7946f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                /* swap count */
7956f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                ds->swapArray32(ds, pKey32++, 4, qKey32++, pErrorCode);
7966f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
7976f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                offset+=1+count;
7986f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
7996f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
8006f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if(count==0) {
8016f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                break;
8026f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
8036f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
8046f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            p=inBundle+offset; /* pointer to table resources */
8056f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            q=outBundle+offset;
8066f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
8076f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            /* recurse */
8086f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            for(i=0; i<count; ++i) {
8096f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                const char *itemKey=gUnknownKey;
8106f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                if(pKey16!=NULL) {
8116f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    int32_t keyOffset=ds->readUInt16(pKey16[i]);
8126f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    if(keyOffset<pTempTable->localKeyLimit) {
8136f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                        itemKey=(const char *)outBundle+keyOffset;
8146f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    }
8156f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                } else {
8166f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    int32_t keyOffset=udata_readInt32(ds, pKey32[i]);
8176f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    if(keyOffset>=0) {
8186f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                        itemKey=(const char *)outBundle+keyOffset;
8196f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    }
8206f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                }
8216f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                item=ds->readUInt32(p[i]);
8226f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                ures_swapResource(ds, inBundle, outBundle, item, itemKey, pTempTable, pErrorCode);
8236f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                if(U_FAILURE(*pErrorCode)) {
8246f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    udata_printError(ds, "ures_swapResource(table res=%08x)[%d].recurse(%08x) failed\n",
8256f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                                     res, i, item);
8266f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    return;
8276f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                }
8286f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
8296f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
8306f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if(pTempTable->majorFormatVersion>1 || ds->inCharset==ds->outCharset) {
8316f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                /* no need to sort, just swap the offset/value arrays */
8326f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                if(pKey16!=NULL) {
8336f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    ds->swapArray16(ds, pKey16, count*2, qKey16, pErrorCode);
8346f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    ds->swapArray32(ds, p, count*4, q, pErrorCode);
8356f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                } else {
8366f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    /* swap key offsets and items as one array */
8376f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    ds->swapArray32(ds, pKey32, count*2*4, qKey32, pErrorCode);
8386f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                }
8396f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                break;
8406f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
8416f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
8426f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            /*
8436f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org             * We need to sort tables by outCharset key strings because they
8446f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org             * sort differently for different charset families.
8456f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org             * ures_swap() already set pTempTable->keyChars appropriately.
8466f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org             * First we set up a temporary table with the key indexes and
8476f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org             * sorting indexes and sort that.
8486f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org             * Then we permutate and copy/swap the actual values.
8496f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org             */
8506f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if(pKey16!=NULL) {
8516f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                for(i=0; i<count; ++i) {
8526f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    pTempTable->rows[i].keyIndex=ds->readUInt16(pKey16[i]);
8536f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    pTempTable->rows[i].sortIndex=i;
8546f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                }
8556f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            } else {
8566f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                for(i=0; i<count; ++i) {
8576f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    pTempTable->rows[i].keyIndex=udata_readInt32(ds, pKey32[i]);
8586f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    pTempTable->rows[i].sortIndex=i;
8596f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                }
8606f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
8616f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            uprv_sortArray(pTempTable->rows, count, sizeof(Row),
8626f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                           ures_compareRows, pTempTable->keyChars,
8636f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                           FALSE, pErrorCode);
8646f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if(U_FAILURE(*pErrorCode)) {
8656f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                udata_printError(ds, "ures_swapResource(table res=%08x).uprv_sortArray(%d items) failed\n",
8666f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                                 res, count);
8676f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                return;
8686f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
8696f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
8706f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            /*
8716f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org             * copy/swap/permutate items
8726f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org             *
8736f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org             * If we swap in-place, then the permutation must use another
8746f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org             * temporary array (pTempTable->resort)
8756f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org             * before the results are copied to the outBundle.
8766f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org             */
8776f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            /* keys */
8786f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if(pKey16!=NULL) {
8796f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                uint16_t *rKey16;
8806f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
8816f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                if(pKey16!=qKey16) {
8826f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    rKey16=qKey16;
8836f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                } else {
8846f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    rKey16=(uint16_t *)pTempTable->resort;
8856f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                }
8866f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                for(i=0; i<count; ++i) {
8876f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    oldIndex=pTempTable->rows[i].sortIndex;
8886f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    ds->swapArray16(ds, pKey16+oldIndex, 2, rKey16+i, pErrorCode);
8896f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                }
8906f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                if(qKey16!=rKey16) {
8916f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    uprv_memcpy(qKey16, rKey16, 2*count);
8926f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                }
8936f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            } else {
8946f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                int32_t *rKey32;
8956f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
8966f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                if(pKey32!=qKey32) {
8976f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    rKey32=qKey32;
8986f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                } else {
8996f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    rKey32=pTempTable->resort;
9006f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                }
9016f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                for(i=0; i<count; ++i) {
9026f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    oldIndex=pTempTable->rows[i].sortIndex;
9036f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    ds->swapArray32(ds, pKey32+oldIndex, 4, rKey32+i, pErrorCode);
9046f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                }
9056f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                if(qKey32!=rKey32) {
9066f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    uprv_memcpy(qKey32, rKey32, 4*count);
9076f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                }
9086f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
9096f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
9106f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            /* resources */
9116f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            {
9126f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                Resource *r;
9136f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
9146f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
9156f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                if(p!=q) {
9166f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    r=q;
9176f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                } else {
9186f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    r=(Resource *)pTempTable->resort;
9196f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                }
9206f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                for(i=0; i<count; ++i) {
9216f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    oldIndex=pTempTable->rows[i].sortIndex;
9226f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    ds->swapArray32(ds, p+oldIndex, 4, r+i, pErrorCode);
9236f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                }
9246f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                if(q!=r) {
9256f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    uprv_memcpy(q, r, 4*count);
9266f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                }
9276f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
9286f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
9296f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        break;
9306f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    case URES_ARRAY:
9316f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        {
9326f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            Resource item;
9336f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            int32_t i;
9346f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
9356f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            count=udata_readInt32(ds, (int32_t)*p);
9366f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            /* swap length */
9376f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            ds->swapArray32(ds, p++, 4, q++, pErrorCode);
9386f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
9396f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            /* recurse */
9406f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            for(i=0; i<count; ++i) {
9416f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                item=ds->readUInt32(p[i]);
9426f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                ures_swapResource(ds, inBundle, outBundle, item, NULL, pTempTable, pErrorCode);
9436f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                if(U_FAILURE(*pErrorCode)) {
9446f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    udata_printError(ds, "ures_swapResource(array res=%08x)[%d].recurse(%08x) failed\n",
9456f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                                     res, i, item);
9466f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    return;
9476f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                }
9486f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
9496f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
9506f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            /* swap items */
9516f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            ds->swapArray32(ds, p, 4*count, q, pErrorCode);
9526f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
9536f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        break;
9546f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    case URES_INT_VECTOR:
9556f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        count=udata_readInt32(ds, (int32_t)*p);
9566f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* swap length and each integer */
9576f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        ds->swapArray32(ds, p, 4*(1+count), q, pErrorCode);
9586f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        break;
9596f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    default:
9606f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* also catches RES_BOGUS */
9616f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        *pErrorCode=U_UNSUPPORTED_ERROR;
9626f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        break;
9636f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
9646f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
9656f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
9666f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgU_CAPI int32_t U_EXPORT2
9676f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgures_swap(const UDataSwapper *ds,
9686f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org          const void *inData, int32_t length, void *outData,
9696f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org          UErrorCode *pErrorCode) {
9706f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    const UDataInfo *pInfo;
9716f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    const Resource *inBundle;
9726f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    Resource rootRes;
9736f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    int32_t headerSize, maxTableLength;
9746f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
9756f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    Row rows[STACK_ROW_CAPACITY];
9766f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    int32_t resort[STACK_ROW_CAPACITY];
9776f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    TempTable tempTable;
9786f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
9796f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    const int32_t *inIndexes;
9806f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
9816f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /* the following integers count Resource item offsets (4 bytes each), not bytes */
9826f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    int32_t bundleLength, indexLength, keysBottom, keysTop, resBottom, top;
9836f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
9846f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /* udata_swapDataHeader checks the arguments */
9856f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    headerSize=udata_swapDataHeader(ds, inData, length, outData, pErrorCode);
9866f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(pErrorCode==NULL || U_FAILURE(*pErrorCode)) {
9876f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return 0;
9886f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
9896f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
9906f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /* check data format and format version */
9916f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    pInfo=(const UDataInfo *)((const char *)inData+4);
9926f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(!(
9936f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        pInfo->dataFormat[0]==0x52 &&   /* dataFormat="ResB" */
9946f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        pInfo->dataFormat[1]==0x65 &&
9956f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        pInfo->dataFormat[2]==0x73 &&
9966f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        pInfo->dataFormat[3]==0x42 &&
9976f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        ((pInfo->formatVersion[0]==1 && pInfo->formatVersion[1]>=1) ||  /* formatVersion 1.1+ or 2.x */
9986f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         pInfo->formatVersion[0]==2)
9996f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    )) {
10006f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        udata_printError(ds, "ures_swap(): data format %02x.%02x.%02x.%02x (format version %02x.%02x) is not a resource bundle\n",
10016f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                         pInfo->dataFormat[0], pInfo->dataFormat[1],
10026f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                         pInfo->dataFormat[2], pInfo->dataFormat[3],
10036f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                         pInfo->formatVersion[0], pInfo->formatVersion[1]);
10046f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        *pErrorCode=U_UNSUPPORTED_ERROR;
10056f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return 0;
10066f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
10076f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    tempTable.majorFormatVersion=pInfo->formatVersion[0];
10086f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
10096f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /* a resource bundle must contain at least one resource item */
10106f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(length<0) {
10116f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        bundleLength=-1;
10126f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    } else {
10136f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        bundleLength=(length-headerSize)/4;
10146f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
10156f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* formatVersion 1.1 must have a root item and at least 5 indexes */
10166f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(bundleLength<(1+5)) {
10176f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            udata_printError(ds, "ures_swap(): too few bytes (%d after header) for a resource bundle\n",
10186f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                             length-headerSize);
10196f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            *pErrorCode=U_INDEX_OUTOFBOUNDS_ERROR;
10206f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            return 0;
10216f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
10226f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
10236f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
10246f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    inBundle=(const Resource *)((const char *)inData+headerSize);
10256f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    rootRes=ds->readUInt32(*inBundle);
10266f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
10276f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /* formatVersion 1.1 adds the indexes[] array */
10286f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    inIndexes=(const int32_t *)(inBundle+1);
10296f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
10306f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    indexLength=udata_readInt32(ds, inIndexes[URES_INDEX_LENGTH])&0xff;
10316f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(indexLength<=URES_INDEX_MAX_TABLE_LENGTH) {
10326f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        udata_printError(ds, "ures_swap(): too few indexes for a 1.1+ resource bundle\n");
10336f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        *pErrorCode=U_INDEX_OUTOFBOUNDS_ERROR;
10346f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return 0;
10356f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
10366f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    keysBottom=1+indexLength;
10376f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    keysTop=udata_readInt32(ds, inIndexes[URES_INDEX_KEYS_TOP]);
10386f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(indexLength>URES_INDEX_16BIT_TOP) {
10396f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        resBottom=udata_readInt32(ds, inIndexes[URES_INDEX_16BIT_TOP]);
10406f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    } else {
10416f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        resBottom=keysTop;
10426f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
10436f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    top=udata_readInt32(ds, inIndexes[URES_INDEX_BUNDLE_TOP]);
10446f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    maxTableLength=udata_readInt32(ds, inIndexes[URES_INDEX_MAX_TABLE_LENGTH]);
10456f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
10466f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(0<=bundleLength && bundleLength<top) {
10476f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        udata_printError(ds, "ures_swap(): resource top %d exceeds bundle length %d\n",
10486f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                         top, bundleLength);
10496f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        *pErrorCode=U_INDEX_OUTOFBOUNDS_ERROR;
10506f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return 0;
10516f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
10526f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(keysTop>(1+indexLength)) {
10536f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        tempTable.localKeyLimit=keysTop<<2;
10546f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    } else {
10556f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        tempTable.localKeyLimit=0;
10566f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
10576f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
10586f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(length>=0) {
10596f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        Resource *outBundle=(Resource *)((char *)outData+headerSize);
10606f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
10616f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* track which resources we have already swapped */
10626f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        uint32_t stackResFlags[STACK_ROW_CAPACITY];
10636f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        int32_t resFlagsLength;
10646f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
10656f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /*
10666f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         * We need one bit per 4 resource bundle bytes so that we can track
10676f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         * every possible Resource for whether we have swapped it already.
10686f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         * Multiple Resource words can refer to the same bundle offsets
10696f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         * for sharing identical values.
10706f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         * We could optimize this by allocating only for locations above
10716f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         * where Resource values are stored (above keys & strings).
10726f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         */
10736f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        resFlagsLength=(length+31)>>5;          /* number of bytes needed */
10746f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        resFlagsLength=(resFlagsLength+3)&~3;   /* multiple of 4 bytes for uint32_t */
10756f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(resFlagsLength<=sizeof(stackResFlags)) {
10766f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            tempTable.resFlags=stackResFlags;
10776f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        } else {
10786f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            tempTable.resFlags=(uint32_t *)uprv_malloc(resFlagsLength);
10796f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if(tempTable.resFlags==NULL) {
10806f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                udata_printError(ds, "ures_swap(): unable to allocate memory for tracking resources\n");
10816f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                *pErrorCode=U_MEMORY_ALLOCATION_ERROR;
10826f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                return 0;
10836f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
10846f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
10856f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        uprv_memset(tempTable.resFlags, 0, resFlagsLength);
10866f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
10876f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* copy the bundle for binary and inaccessible data */
10886f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(inData!=outData) {
10896f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            uprv_memcpy(outBundle, inBundle, 4*top);
10906f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
10916f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
10926f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* swap the key strings, but not the padding bytes (0xaa) after the last string and its NUL */
10936f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        udata_swapInvStringBlock(ds, inBundle+keysBottom, 4*(keysTop-keysBottom),
10946f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                                    outBundle+keysBottom, pErrorCode);
10956f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(U_FAILURE(*pErrorCode)) {
10966f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            udata_printError(ds, "ures_swap().udata_swapInvStringBlock(keys[%d]) failed\n", 4*(keysTop-keysBottom));
10976f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            return 0;
10986f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
10996f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
11006f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* swap the 16-bit units (strings, table16, array16) */
11016f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(keysTop<resBottom) {
11026f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            ds->swapArray16(ds, inBundle+keysTop, (resBottom-keysTop)*4, outBundle+keysTop, pErrorCode);
11036f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if(U_FAILURE(*pErrorCode)) {
11046f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                udata_printError(ds, "ures_swap().swapArray16(16-bit units[%d]) failed\n", 2*(resBottom-keysTop));
11056f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                return 0;
11066f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
11076f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
11086f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
11096f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* allocate the temporary table for sorting resource tables */
11106f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        tempTable.keyChars=(const char *)outBundle; /* sort by outCharset */
11116f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(tempTable.majorFormatVersion>1 || maxTableLength<=STACK_ROW_CAPACITY) {
11126f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            tempTable.rows=rows;
11136f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            tempTable.resort=resort;
11146f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        } else {
11156f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            tempTable.rows=(Row *)uprv_malloc(maxTableLength*sizeof(Row)+maxTableLength*4);
11166f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if(tempTable.rows==NULL) {
11176f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                udata_printError(ds, "ures_swap(): unable to allocate memory for sorting tables (max length: %d)\n",
11186f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                                 maxTableLength);
11196f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                *pErrorCode=U_MEMORY_ALLOCATION_ERROR;
11206f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                if(tempTable.resFlags!=stackResFlags) {
11216f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    uprv_free(tempTable.resFlags);
11226f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                }
11236f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                return 0;
11246f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
11256f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            tempTable.resort=(int32_t *)(tempTable.rows+maxTableLength);
11266f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
11276f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
11286f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* swap the resources */
11296f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        ures_swapResource(ds, inBundle, outBundle, rootRes, NULL, &tempTable, pErrorCode);
11306f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(U_FAILURE(*pErrorCode)) {
11316f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            udata_printError(ds, "ures_swapResource(root res=%08x) failed\n",
11326f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                             rootRes);
11336f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
11346f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
11356f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(tempTable.rows!=rows) {
11366f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            uprv_free(tempTable.rows);
11376f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
11386f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(tempTable.resFlags!=stackResFlags) {
11396f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            uprv_free(tempTable.resFlags);
11406f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
11416f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
11426f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* swap the root resource and indexes */
11436f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        ds->swapArray32(ds, inBundle, keysBottom*4, outBundle, pErrorCode);
11446f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
11456f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
11466f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return headerSize+4*top;
11476f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
1148