1b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/*
2b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*******************************************************************************
3b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*                                                                             *
450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho* Copyright (C) 1999-2010, International Business Machines Corporation        *
5b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*               and others. All Rights Reserved.                              *
6b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*                                                                             *
7b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*******************************************************************************
8b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*   file name:  uresdata.c
9b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*   encoding:   US-ASCII
10b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*   tab size:   8 (not used)
11b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*   indentation:4
12b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*
13b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*   created on: 1999dec08
14b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*   created by: Markus W. Scherer
15b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* Modification History:
16b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*
17b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*   Date        Name        Description
18b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*   06/20/2000  helena      OS/400 port changes; mostly typecast.
19b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*   06/24/02    weiv        Added support for resource sharing
20b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*/
21b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
22b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "unicode/utypes.h"
23b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "unicode/udata.h"
2450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#include "unicode/ustring.h"
25b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "cmemory.h"
26b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "cstring.h"
27b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "uarrsort.h"
28b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "udataswp.h"
29b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "ucol_swp.h"
3050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#include "uinvchar.h"
31b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "uresdata.h"
32b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "uresimp.h"
33b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
34b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define LENGTHOF(array) (int32_t)(sizeof(array)/sizeof((array)[0]))
35b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
36b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/*
37b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * Resource access helpers
38b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru */
39b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
40b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/* get a const char* pointer to the key with the keyOffset byte offset from pRoot */
4150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#define RES_GET_KEY16(pResData, keyOffset) \
4250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    ((keyOffset)<(pResData)->localKeyLimit ? \
4350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        (const char *)(pResData)->pRoot+(keyOffset) : \
4450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        (pResData)->poolBundleKeys+(keyOffset)-(pResData)->localKeyLimit)
45b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
4650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#define RES_GET_KEY32(pResData, keyOffset) \
4750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    ((keyOffset)>=0 ? \
4850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        (const char *)(pResData)->pRoot+(keyOffset) : \
4950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        (pResData)->poolBundleKeys+((keyOffset)&0x7fffffff))
50b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
5150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#define URESDATA_ITEM_NOT_FOUND -1
52b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
5350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* empty resources, returned when the resource offset is 0 */
5450294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic const uint16_t gEmpty16=0;
5550294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic const int32_t gEmpty32=0;
5650294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic const struct {
5750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    int32_t length;
5850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    UChar nul;
5950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    UChar pad;
6050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho} gEmptyString={ 0, 0, 0 };
61b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
62b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/*
6350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho * All the type-access functions assume that
6450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho * the resource is of the expected type.
65b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru */
66b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
6750294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic int32_t
6850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho_res_findTableItem(const ResourceData *pResData, const uint16_t *keyOffsets, int32_t length,
6950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                   const char *key, const char **realKey) {
7050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    const char *tableKey;
7150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    int32_t mid, start, limit;
72b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int result;
73b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
7450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    /* do a binary search for the key */
7550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    start=0;
7650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    limit=length;
7750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    while(start<limit) {
7850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        mid = (start + limit) / 2;
7950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        tableKey = RES_GET_KEY16(pResData, keyOffsets[mid]);
8050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        if (pResData->useNativeStrcmp) {
8150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            result = uprv_strcmp(key, tableKey);
8250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        } else {
8350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            result = uprv_compareInvCharsAsAscii(key, tableKey);
8450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        }
8550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        if (result < 0) {
8650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            limit = mid;
8750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        } else if (result > 0) {
8850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            start = mid + 1;
8950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        } else {
9050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            /* We found it! */
9150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            *realKey=tableKey;
9250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            return mid;
93b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
94b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
9550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    return URESDATA_ITEM_NOT_FOUND;  /* not found or table is empty. */
96b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
97b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
9850294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic int32_t
9950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho_res_findTable32Item(const ResourceData *pResData, const int32_t *keyOffsets, int32_t length,
10050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                     const char *key, const char **realKey) {
10150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    const char *tableKey;
102b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t mid, start, limit;
103b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int result;
104b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
10550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    /* do a binary search for the key */
10650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    start=0;
10750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    limit=length;
10850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    while(start<limit) {
10950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        mid = (start + limit) / 2;
11050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        tableKey = RES_GET_KEY32(pResData, keyOffsets[mid]);
11150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        if (pResData->useNativeStrcmp) {
11250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            result = uprv_strcmp(key, tableKey);
11350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        } else {
11450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            result = uprv_compareInvCharsAsAscii(key, tableKey);
11550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        }
11650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        if (result < 0) {
11750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            limit = mid;
11850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        } else if (result > 0) {
11950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            start = mid + 1;
12050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        } else {
12150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            /* We found it! */
12250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            *realKey=tableKey;
12350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            return mid;
124b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
125b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
12650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    return URESDATA_ITEM_NOT_FOUND;  /* not found or table is empty. */
127b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
128b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
129b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/* helper for res_load() ---------------------------------------------------- */
130b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
131b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic UBool U_CALLCONV
132b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruisAcceptable(void *context,
133b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru             const char *type, const char *name,
134b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru             const UDataInfo *pInfo) {
135b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uprv_memcpy(context, pInfo->formatVersion, 4);
136b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return (UBool)(
137b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        pInfo->size>=20 &&
138b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        pInfo->isBigEndian==U_IS_BIG_ENDIAN &&
139b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        pInfo->charsetFamily==U_CHARSET_FAMILY &&
140b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        pInfo->sizeofUChar==U_SIZEOF_UCHAR &&
141b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        pInfo->dataFormat[0]==0x52 &&   /* dataFormat="ResB" */
142b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        pInfo->dataFormat[1]==0x65 &&
143b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        pInfo->dataFormat[2]==0x73 &&
144b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        pInfo->dataFormat[3]==0x42 &&
14550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        (pInfo->formatVersion[0]==1 || pInfo->formatVersion[0]==2));
146b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
147b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
148b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/* semi-public functions ---------------------------------------------------- */
149b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
15050294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic void
15150294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehores_init(ResourceData *pResData,
15250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho         UVersionInfo formatVersion, const void *inBytes, int32_t length,
15350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho         UErrorCode *errorCode) {
154b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UResType rootType;
155b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
15650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    /* get the root resource */
15750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    pResData->pRoot=(const int32_t *)inBytes;
15850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    pResData->rootRes=(Resource)*pResData->pRoot;
15950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    pResData->p16BitUnits=&gEmpty16;
160b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
16150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    /* formatVersion 1.1 must have a root item and at least 5 indexes */
16250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    if(length>=0 && (length/4)<((formatVersion[0]==1 && formatVersion[1]==0) ? 1 : 1+5)) {
16350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        *errorCode=U_INVALID_FORMAT_ERROR;
16450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        res_unload(pResData);
16550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        return;
16650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    }
167b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
168b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* currently, we accept only resources that have a Table as their roots */
169b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    rootType=RES_GET_TYPE(pResData->rootRes);
17050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    if(!URES_IS_TABLE(rootType)) {
171b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        *errorCode=U_INVALID_FORMAT_ERROR;
17250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        res_unload(pResData);
17350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        return;
174b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
175b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
17650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    if(formatVersion[0]==1 && formatVersion[1]==0) {
17750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        pResData->localKeyLimit=0x10000;  /* greater than any 16-bit key string offset */
17850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    } else {
179b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* bundles with formatVersion 1.1 and later contain an indexes[] array */
18050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        const int32_t *indexes=pResData->pRoot+1;
18150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        int32_t indexLength=indexes[URES_INDEX_LENGTH]&0xff;
18250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        if(indexLength<=URES_INDEX_MAX_TABLE_LENGTH) {
18350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            *errorCode=U_INVALID_FORMAT_ERROR;
18450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            res_unload(pResData);
18550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            return;
18650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        }
18750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        if( length>=0 &&
18850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            (length<((1+indexLength)<<2) ||
18950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho             length<(indexes[URES_INDEX_BUNDLE_TOP]<<2))
19050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        ) {
19150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            *errorCode=U_INVALID_FORMAT_ERROR;
19250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            res_unload(pResData);
19350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            return;
19450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        }
19550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        if(indexes[URES_INDEX_KEYS_TOP]>(1+indexLength)) {
19650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            pResData->localKeyLimit=indexes[URES_INDEX_KEYS_TOP]<<2;
197b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
19850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        if(indexLength>URES_INDEX_ATTRIBUTES) {
19950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            int32_t att=indexes[URES_INDEX_ATTRIBUTES];
20050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            pResData->noFallback=(UBool)(att&URES_ATT_NO_FALLBACK);
20150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            pResData->isPoolBundle=(UBool)((att&URES_ATT_IS_POOL_BUNDLE)!=0);
20250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            pResData->usesPoolBundle=(UBool)((att&URES_ATT_USES_POOL_BUNDLE)!=0);
20350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        }
20450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        if((pResData->isPoolBundle || pResData->usesPoolBundle) && indexLength<=URES_INDEX_POOL_CHECKSUM) {
20550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            *errorCode=U_INVALID_FORMAT_ERROR;
20650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            res_unload(pResData);
20750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            return;
20850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        }
20950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        if( indexLength>URES_INDEX_16BIT_TOP &&
21050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            indexes[URES_INDEX_16BIT_TOP]>indexes[URES_INDEX_KEYS_TOP]
21150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        ) {
21250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            pResData->p16BitUnits=(const uint16_t *)(pResData->pRoot+indexes[URES_INDEX_KEYS_TOP]);
21350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        }
21450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    }
21550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
21650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    if(formatVersion[0]==1 || U_CHARSET_FAMILY==U_ASCII_FAMILY) {
21750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        /*
21850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho         * formatVersion 1: compare key strings in native-charset order
21950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho         * formatVersion 2 and up: compare key strings in ASCII order
22050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho         */
22150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        pResData->useNativeStrcmp=TRUE;
22250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    }
22350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho}
22450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
22550294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoU_CAPI void U_EXPORT2
22650294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehores_read(ResourceData *pResData,
22750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho         const UDataInfo *pInfo, const void *inBytes, int32_t length,
22850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho         UErrorCode *errorCode) {
22950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    UVersionInfo formatVersion;
23050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
23150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    uprv_memset(pResData, 0, sizeof(ResourceData));
23250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    if(U_FAILURE(*errorCode)) {
23350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        return;
23450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    }
23550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    if(!isAcceptable(formatVersion, NULL, NULL, pInfo)) {
23650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        *errorCode=U_INVALID_FORMAT_ERROR;
23750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        return;
23850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    }
23950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    res_init(pResData, formatVersion, inBytes, length, errorCode);
24050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho}
24150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
24250294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoU_CFUNC void
24350294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehores_load(ResourceData *pResData,
24450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho         const char *path, const char *name, UErrorCode *errorCode) {
24550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    UVersionInfo formatVersion;
24650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
24750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    uprv_memset(pResData, 0, sizeof(ResourceData));
24850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
24950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    /* load the ResourceBundle file */
25050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    pResData->data=udata_openChoice(path, "res", name, isAcceptable, formatVersion, errorCode);
25150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    if(U_FAILURE(*errorCode)) {
25250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        return;
253b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
254b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
25550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    /* get its memory and initialize *pResData */
25650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    res_init(pResData, formatVersion, udata_getMemory(pResData->data), -1, errorCode);
257b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
258b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
259b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CFUNC void
260b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querures_unload(ResourceData *pResData) {
261b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(pResData->data!=NULL) {
262b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        udata_close(pResData->data);
263b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        pResData->data=NULL;
264b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
265b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
266b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
26750294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic const int8_t gPublicTypes[URES_LIMIT] = {
26850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    URES_STRING,
26950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    URES_BINARY,
27050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    URES_TABLE,
27150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    URES_ALIAS,
27250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
27350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    URES_TABLE,     /* URES_TABLE32 */
27450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    URES_TABLE,     /* URES_TABLE16 */
27550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    URES_STRING,    /* URES_STRING_V2 */
27650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    URES_INT,
27750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
27850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    URES_ARRAY,
27950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    URES_ARRAY,     /* URES_ARRAY16 */
28050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    URES_NONE,
28150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    URES_NONE,
28250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
28350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    URES_NONE,
28450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    URES_NONE,
28550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    URES_INT_VECTOR,
28650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    URES_NONE
28750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho};
28850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
28950294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoU_CAPI UResType U_EXPORT2
29050294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehores_getPublicType(Resource res) {
29150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    return (UResType)gPublicTypes[RES_GET_TYPE(res)];
29250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho}
29350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
29450294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoU_CAPI const UChar * U_EXPORT2
29550294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehores_getString(const ResourceData *pResData, Resource res, int32_t *pLength) {
29650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    const UChar *p;
29750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    uint32_t offset=RES_GET_OFFSET(res);
29850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    int32_t length;
29950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    if(RES_GET_TYPE(res)==URES_STRING_V2) {
30050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        int32_t first;
30150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        p=(const UChar *)(pResData->p16BitUnits+offset);
30250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        first=*p;
30350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        if(!U16_IS_TRAIL(first)) {
30450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            length=u_strlen(p);
30550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        } else if(first<0xdfef) {
30650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            length=first&0x3ff;
30750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            ++p;
30850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        } else if(first<0xdfff) {
30950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            length=((first-0xdfef)<<16)|p[1];
31050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            p+=2;
31150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        } else {
31250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            length=((int32_t)p[1]<<16)|p[2];
31350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            p+=3;
314b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
31550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    } else if(res==offset) /* RES_GET_TYPE(res)==URES_STRING */ {
31650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        const int32_t *p32= res==0 ? &gEmptyString.length : pResData->pRoot+res;
31750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        length=*p32++;
31850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        p=(const UChar *)p32;
319b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    } else {
32050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        p=NULL;
32150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        length=0;
32250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    }
32350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    if(pLength) {
32450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        *pLength=length;
325b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
32650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    return p;
327b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
328b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
32950294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoU_CAPI const UChar * U_EXPORT2
33050294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehores_getAlias(const ResourceData *pResData, Resource res, int32_t *pLength) {
33150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    const UChar *p;
33250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    uint32_t offset=RES_GET_OFFSET(res);
33350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    int32_t length;
33450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    if(RES_GET_TYPE(res)==URES_ALIAS) {
33550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        const int32_t *p32= offset==0 ? &gEmptyString.length : pResData->pRoot+offset;
33650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        length=*p32++;
33750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        p=(const UChar *)p32;
338b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    } else {
33950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        p=NULL;
34050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        length=0;
34150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    }
34250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    if(pLength) {
34350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        *pLength=length;
344b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
34550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    return p;
346b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
347b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
34850294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoU_CAPI const uint8_t * U_EXPORT2
34950294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehores_getBinary(const ResourceData *pResData, Resource res, int32_t *pLength) {
35050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    const uint8_t *p;
35150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    uint32_t offset=RES_GET_OFFSET(res);
35250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    int32_t length;
35350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    if(RES_GET_TYPE(res)==URES_BINARY) {
35450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        const int32_t *p32= offset==0 ? &gEmpty32 : pResData->pRoot+offset;
35550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        length=*p32++;
35650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        p=(const uint8_t *)p32;
357b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    } else {
35850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        p=NULL;
35950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        length=0;
36050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    }
36150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    if(pLength) {
36250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        *pLength=length;
363b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
36450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    return p;
365b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
366b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
367b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
36850294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoU_CAPI const int32_t * U_EXPORT2
36950294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehores_getIntVector(const ResourceData *pResData, Resource res, int32_t *pLength) {
37050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    const int32_t *p;
37150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    uint32_t offset=RES_GET_OFFSET(res);
37250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    int32_t length;
37350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    if(RES_GET_TYPE(res)==URES_INT_VECTOR) {
37450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        p= offset==0 ? &gEmpty32 : pResData->pRoot+offset;
37550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        length=*p++;
376b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    } else {
37750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        p=NULL;
37850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        length=0;
37950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    }
38050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    if(pLength) {
38150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        *pLength=length;
38250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    }
38350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    return p;
38450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho}
38550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
38650294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoU_CAPI int32_t U_EXPORT2
38750294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehores_countArrayItems(const ResourceData *pResData, Resource res) {
38850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    uint32_t offset=RES_GET_OFFSET(res);
38950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    switch(RES_GET_TYPE(res)) {
39050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    case URES_STRING:
39150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    case URES_STRING_V2:
39250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    case URES_BINARY:
39350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    case URES_ALIAS:
39450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    case URES_INT:
39550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    case URES_INT_VECTOR:
39650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        return 1;
39750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    case URES_ARRAY:
39850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    case URES_TABLE32:
39950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        return offset==0 ? 0 : *(pResData->pRoot+offset);
40050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    case URES_TABLE:
40150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        return offset==0 ? 0 : *((const uint16_t *)(pResData->pRoot+offset));
40250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    case URES_ARRAY16:
40350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    case URES_TABLE16:
40450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        return pResData->p16BitUnits[offset];
40550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    default:
40650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        return 0;
407b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
408b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
409b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
41050294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoU_CAPI Resource U_EXPORT2
41150294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehores_getTableItemByKey(const ResourceData *pResData, Resource table,
41250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                      int32_t *indexR, const char **key) {
41350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    uint32_t offset=RES_GET_OFFSET(table);
41450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    int32_t length;
41550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    int32_t idx;
41650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    if(key == NULL || *key == NULL) {
41750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        return RES_BOGUS;
41850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    }
41950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    switch(RES_GET_TYPE(table)) {
42050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    case URES_TABLE: {
42150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        const uint16_t *p= offset==0 ? &gEmpty16 : (const uint16_t *)(pResData->pRoot+offset);
42250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        length=*p++;
42350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        *indexR=idx=_res_findTableItem(pResData, p, length, *key, key);
42450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        if(idx>=0) {
42550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            const Resource *p32=(const Resource *)(p+length+(~length&1));
42650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            return p32[idx];
427b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
42850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        break;
42950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    }
43050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    case URES_TABLE16: {
43150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        const uint16_t *p=pResData->p16BitUnits+offset;
43250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        length=*p++;
43350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        *indexR=idx=_res_findTableItem(pResData, p, length, *key, key);
43450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        if(idx>=0) {
43550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            return URES_MAKE_RESOURCE(URES_STRING_V2, p[length+idx]);
436b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
43750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        break;
43850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    }
43950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    case URES_TABLE32: {
44050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        const int32_t *p= offset==0 ? &gEmpty32 : pResData->pRoot+offset;
44150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        length=*p++;
44250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        *indexR=idx=_res_findTable32Item(pResData, p, length, *key, key);
44350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        if(idx>=0) {
44450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            return (Resource)p[length+idx];
445b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
44650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        break;
44750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    }
44850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    default:
44950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        break;
45050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    }
45150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    return RES_BOGUS;
452b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
453b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
45450294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoU_CAPI Resource U_EXPORT2
45550294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehores_getTableItemByIndex(const ResourceData *pResData, Resource table,
45650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                        int32_t indexR, const char **key) {
45750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    uint32_t offset=RES_GET_OFFSET(table);
45850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    int32_t length;
45950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    switch(RES_GET_TYPE(table)) {
46050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    case URES_TABLE: {
46150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        const uint16_t *p= offset==0 ? &gEmpty16 : (const uint16_t *)(pResData->pRoot+offset);
46250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        length=*p++;
46350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        if(indexR<length) {
46450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            const Resource *p32=(const Resource *)(p+length+(~length&1));
46550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            if(key!=NULL) {
46650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                *key=RES_GET_KEY16(pResData, p[indexR]);
46750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            }
46850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            return p32[indexR];
46950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        }
47050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        break;
47150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    }
47250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    case URES_TABLE16: {
47350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        const uint16_t *p=pResData->p16BitUnits+offset;
47450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        length=*p++;
47550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        if(indexR<length) {
47650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            if(key!=NULL) {
47750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                *key=RES_GET_KEY16(pResData, p[indexR]);
47850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            }
47950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            return URES_MAKE_RESOURCE(URES_STRING_V2, p[length+indexR]);
48050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        }
48150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        break;
48250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    }
48350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    case URES_TABLE32: {
48450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        const int32_t *p= offset==0 ? &gEmpty32 : pResData->pRoot+offset;
48550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        length=*p++;
48650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        if(indexR<length) {
48750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            if(key!=NULL) {
48850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                *key=RES_GET_KEY32(pResData, p[indexR]);
48950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            }
49050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            return (Resource)p[length+indexR];
49150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        }
49250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        break;
49350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    }
49450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    default:
49550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        break;
49650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    }
49750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    return RES_BOGUS;
49850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho}
49950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
50050294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoU_CAPI Resource U_EXPORT2
501b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querures_getResource(const ResourceData *pResData, const char *key) {
50250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    const char *realKey=key;
503b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    int32_t idx;
50450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    return res_getTableItemByKey(pResData, pResData->rootRes, &idx, &realKey);
505b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
506b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
50750294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoU_CAPI Resource U_EXPORT2
50850294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehores_getArrayItem(const ResourceData *pResData, Resource array, int32_t indexR) {
50950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    uint32_t offset=RES_GET_OFFSET(array);
51050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    switch(RES_GET_TYPE(array)) {
51150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    case URES_ARRAY: {
51250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        const int32_t *p= offset==0 ? &gEmpty32 : pResData->pRoot+offset;
51350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        if(indexR<*p) {
51450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            return (Resource)p[1+indexR];
51550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        }
51650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        break;
51750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    }
51850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    case URES_ARRAY16: {
51950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        const uint16_t *p=pResData->p16BitUnits+offset;
52050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        if(indexR<*p) {
52150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            return URES_MAKE_RESOURCE(URES_STRING_V2, p[1+indexR]);
52250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        }
52350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        break;
52450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    }
52550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    default:
52650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        break;
52750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    }
52850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    return RES_BOGUS;
529b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
530b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
531b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CFUNC Resource
532b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querures_findResource(const ResourceData *pResData, Resource r, char** path, const char** key) {
533b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  /* we pass in a path. CollationElements/Sequence or zoneStrings/3/2 etc.
534b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru   * iterates over a path and stops when a scalar resource is found. This
535b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru   * CAN be an alias. Path gets set to the part that has not yet been processed.
536b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru   */
537b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
538b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  char *pathP = *path, *nextSepP = *path;
539b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  char *closeIndex = NULL;
540b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  Resource t1 = r;
541b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  Resource t2;
542b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  int32_t indexR = 0;
543b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  UResType type = RES_GET_TYPE(t1);
544b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
545b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  /* if you come in with an empty path, you'll be getting back the same resource */
546b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  if(!uprv_strlen(pathP)) {
547b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      return r;
548b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
549b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
550b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  /* one needs to have an aggregate resource in order to search in it */
55150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho  if(!URES_IS_CONTAINER(type)) {
552b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      return RES_BOGUS;
553b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
554b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
55550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho  while(nextSepP && *pathP && t1 != RES_BOGUS && URES_IS_CONTAINER(type)) {
556b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* Iteration stops if: the path has been consumed, we found a non-existing
557b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     * resource (t1 == RES_BOGUS) or we found a scalar resource (including alias)
558b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     */
559b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    nextSepP = uprv_strchr(pathP, RES_PATH_SEPARATOR);
560b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* if there are more separators, terminate string
561b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     * and set path to the remaining part of the string
562b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru     */
563b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(nextSepP != NULL) {
564b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      *nextSepP = 0; /* overwrite the separator with a NUL to terminate the key */
565b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      *path = nextSepP+1;
566b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    } else {
567b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      *path = uprv_strchr(pathP, 0);
568b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
569b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
570b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* if the resource is a table */
571b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* try the key based access */
57250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    if(URES_IS_TABLE(type)) {
57350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho      *key = pathP;
57450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho      t2 = res_getTableItemByKey(pResData, t1, &indexR, key);
575b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      if(t2 == RES_BOGUS) {
576b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* if we fail to get the resource by key, maybe we got an index */
577b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        indexR = uprv_strtol(pathP, &closeIndex, 10);
578b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if(closeIndex != pathP) {
579b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          /* if we indeed have an index, try to get the item by index */
580b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          t2 = res_getTableItemByIndex(pResData, t1, indexR, key);
581b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
582b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      }
58350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    } else if(URES_IS_ARRAY(type)) {
584b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      indexR = uprv_strtol(pathP, &closeIndex, 10);
585b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      if(closeIndex != pathP) {
58650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        t2 = res_getArrayItem(pResData, t1, indexR);
587b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      } else {
588b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        t2 = RES_BOGUS; /* have an array, but don't have a valid index */
589b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      }
590b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      *key = NULL;
591b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    } else { /* can't do much here, except setting t2 to bogus */
592b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      t2 = RES_BOGUS;
593b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
594b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    t1 = t2;
595b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    type = RES_GET_TYPE(t1);
596b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* position pathP to next resource key/index */
597b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    pathP = *path;
598b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  }
599b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
600b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  return t1;
601b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
602b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
603b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/* resource bundle swapping ------------------------------------------------- */
604b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
605b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/*
606b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * Need to always enumerate the entire item tree,
607b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * track the lowest address of any item to use as the limit for char keys[],
608b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * track the highest address of any item to return the size of the data.
609b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *
610b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * We should have thought of storing those in the data...
611b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * It is possible to extend the data structure by putting additional values
612b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * in places that are inaccessible by ordinary enumeration of the item tree.
613b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * For example, additional integers could be stored at the beginning or
614b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * end of the key strings; this could be indicated by a minor version number,
615b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * and the data swapping would have to know about these values.
616b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *
617b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * The data structure does not forbid keys to be shared, so we must swap
618b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * all keys once instead of each key when it is referenced.
619b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *
620b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * These swapping functions assume that a resource bundle always has a length
621b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * that is a multiple of 4 bytes.
622b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * Currently, this is trivially true because genrb writes bundle tree leaves
623b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * physically first, before their branches, so that the root table with its
624b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * array of resource items (uint32_t values) is always last.
625b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru */
626b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
627b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/* definitions for table sorting ------------------------ */
628b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
629b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/*
630b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * row of a temporary array
631b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *
632b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * gets platform-endian key string indexes and sorting indexes;
633b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * after sorting this array by keys, the actual key/value arrays are permutated
634b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * according to the sorting indexes
635b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru */
636b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querutypedef struct Row {
637b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t keyIndex, sortIndex;
638b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} Row;
639b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
640b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic int32_t
641b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruures_compareRows(const void *context, const void *left, const void *right) {
642b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    const char *keyChars=(const char *)context;
643b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return (int32_t)uprv_strcmp(keyChars+((const Row *)left)->keyIndex,
644b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                keyChars+((const Row *)right)->keyIndex);
645b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
646b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
647b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querutypedef struct TempTable {
648b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    const char *keyChars;
649b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    Row *rows;
650b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t *resort;
65150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    uint32_t *resFlags;
65250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    int32_t localKeyLimit;
65350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    uint8_t majorFormatVersion;
654b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} TempTable;
655b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
656b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruenum {
657b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    STACK_ROW_CAPACITY=200
658b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru};
659b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
66050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* The table item key string is not locally available. */
66150294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic const char *const gUnknownKey="";
662b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
663b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/* resource table key for collation binaries: "%%CollationBin" */
664b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic const UChar gCollationBinKey[]={
665b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    0x25, 0x25,
666b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    0x43, 0x6f, 0x6c, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e,
667b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    0x42, 0x69, 0x6e,
668b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    0
669b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru};
670b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
671b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/*
672b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * swap one resource item
673b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru */
674b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic void
675b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruures_swapResource(const UDataSwapper *ds,
676b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                  const Resource *inBundle, Resource *outBundle,
677b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                  Resource res, /* caller swaps res itself */
67850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                  const char *key,
679b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                  TempTable *pTempTable,
680b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                  UErrorCode *pErrorCode) {
681b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    const Resource *p;
682b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    Resource *q;
683b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t offset, count;
684b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
68550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    switch(RES_GET_TYPE(res)) {
68650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    case URES_TABLE16:
68750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    case URES_STRING_V2:
68850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    case URES_INT:
68950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    case URES_ARRAY16:
69050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        /* integer, or points to 16-bit units, nothing to do here */
691b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return;
69250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    default:
69350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        break;
694b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
695b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
696b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* all other types use an offset to point to their data */
697b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    offset=(int32_t)RES_GET_OFFSET(res);
69850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    if(offset==0) {
69950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        /* special offset indicating an empty item */
70050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        return;
70150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    }
70250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    if(pTempTable->resFlags[offset>>5]&((uint32_t)1<<(offset&0x1f))) {
70350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        /* we already swapped this resource item */
70450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        return;
70550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    } else {
70650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        /* mark it as swapped now */
70750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        pTempTable->resFlags[offset>>5]|=((uint32_t)1<<(offset&0x1f));
70850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    }
70950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
710b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    p=inBundle+offset;
711b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    q=outBundle+offset;
712b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
713b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    switch(RES_GET_TYPE(res)) {
714b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    case URES_ALIAS:
715b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* physically same value layout as string, fall through */
716b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    case URES_STRING:
717b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        count=udata_readInt32(ds, (int32_t)*p);
718b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* swap length */
719b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        ds->swapArray32(ds, p, 4, q, pErrorCode);
720b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* swap each UChar (the terminating NUL would not change) */
721b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        ds->swapArray16(ds, p+1, 2*count, q+1, pErrorCode);
722b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        break;
723b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    case URES_BINARY:
724b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        count=udata_readInt32(ds, (int32_t)*p);
725b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* swap length */
726b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        ds->swapArray32(ds, p, 4, q, pErrorCode);
727b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* no need to swap or copy bytes - ures_swap() copied them all */
728b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
729b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* swap known formats */
730b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#if !UCONFIG_NO_COLLATION
73150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        if( key!=NULL &&  /* the binary is in a table */
73250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            (key!=gUnknownKey ?
73350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                /* its table key string is "%%CollationBin" */
73450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                0==ds->compareInvChars(ds, key, -1,
73550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                                       gCollationBinKey, LENGTHOF(gCollationBinKey)-1) :
73650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                /* its table key string is unknown but it looks like a collation binary */
73750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                ucol_looksLikeCollationBinary(ds, p+1, count))
73850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        ) {
739b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            ucol_swapBinary(ds, p+1, count, q+1, pErrorCode);
740b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
74150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#endif
742b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        break;
743b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    case URES_TABLE:
744b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    case URES_TABLE32:
745b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        {
746b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            const uint16_t *pKey16;
747b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            uint16_t *qKey16;
748b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
749b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            const int32_t *pKey32;
750b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            int32_t *qKey32;
751b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
752b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            Resource item;
753b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            int32_t i, oldIndex;
754b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
755b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if(RES_GET_TYPE(res)==URES_TABLE) {
756b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                /* get table item count */
757b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                pKey16=(const uint16_t *)p;
758b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                qKey16=(uint16_t *)q;
759b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                count=ds->readUInt16(*pKey16);
760b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
761b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                pKey32=qKey32=NULL;
762b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
763b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                /* swap count */
764b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                ds->swapArray16(ds, pKey16++, 2, qKey16++, pErrorCode);
765b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
766b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                offset+=((1+count)+1)/2;
767b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            } else {
768b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                /* get table item count */
769b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                pKey32=(const int32_t *)p;
770b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                qKey32=(int32_t *)q;
771b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                count=udata_readInt32(ds, *pKey32);
772b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
773b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                pKey16=qKey16=NULL;
774b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
775b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                /* swap count */
776b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                ds->swapArray32(ds, pKey32++, 4, qKey32++, pErrorCode);
777b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
778b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                offset+=1+count;
779b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
780b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
781b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if(count==0) {
782b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                break;
783b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
784b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
785b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            p=inBundle+offset; /* pointer to table resources */
786b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            q=outBundle+offset;
787b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
788b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            /* recurse */
789b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            for(i=0; i<count; ++i) {
79050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                const char *itemKey=gUnknownKey;
79150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                if(pKey16!=NULL) {
79250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                    int32_t keyOffset=ds->readUInt16(pKey16[i]);
79350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                    if(keyOffset<pTempTable->localKeyLimit) {
79450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                        itemKey=(const char *)outBundle+keyOffset;
79550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                    }
796b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                } else {
79750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                    int32_t keyOffset=udata_readInt32(ds, pKey32[i]);
79850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                    if(keyOffset>=0) {
79950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                        itemKey=(const char *)outBundle+keyOffset;
80050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                    }
801b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
802b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                item=ds->readUInt32(p[i]);
80350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                ures_swapResource(ds, inBundle, outBundle, item, itemKey, pTempTable, pErrorCode);
804b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                if(U_FAILURE(*pErrorCode)) {
805b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    udata_printError(ds, "ures_swapResource(table res=%08x)[%d].recurse(%08x) failed\n",
806b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                     res, i, item);
807b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    return;
808b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
809b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
810b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
81150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            if(pTempTable->majorFormatVersion>1 || ds->inCharset==ds->outCharset) {
812b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                /* no need to sort, just swap the offset/value arrays */
813b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                if(pKey16!=NULL) {
814b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    ds->swapArray16(ds, pKey16, count*2, qKey16, pErrorCode);
815b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    ds->swapArray32(ds, p, count*4, q, pErrorCode);
816b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                } else {
817b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    /* swap key offsets and items as one array */
818b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    ds->swapArray32(ds, pKey32, count*2*4, qKey32, pErrorCode);
819b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
820b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                break;
821b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
822b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
823b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            /*
824b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru             * We need to sort tables by outCharset key strings because they
825b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru             * sort differently for different charset families.
826b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru             * ures_swap() already set pTempTable->keyChars appropriately.
827b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru             * First we set up a temporary table with the key indexes and
828b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru             * sorting indexes and sort that.
829b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru             * Then we permutate and copy/swap the actual values.
830b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru             */
831b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if(pKey16!=NULL) {
832b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                for(i=0; i<count; ++i) {
833b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    pTempTable->rows[i].keyIndex=ds->readUInt16(pKey16[i]);
834b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    pTempTable->rows[i].sortIndex=i;
835b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
836b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            } else {
837b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                for(i=0; i<count; ++i) {
838b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    pTempTable->rows[i].keyIndex=udata_readInt32(ds, pKey32[i]);
839b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    pTempTable->rows[i].sortIndex=i;
840b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
841b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
842b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            uprv_sortArray(pTempTable->rows, count, sizeof(Row),
843b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                           ures_compareRows, pTempTable->keyChars,
844b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                           FALSE, pErrorCode);
845b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if(U_FAILURE(*pErrorCode)) {
846b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                udata_printError(ds, "ures_swapResource(table res=%08x).uprv_sortArray(%d items) failed\n",
847b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                 res, count);
848b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                return;
849b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
850b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
851b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            /*
852b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru             * copy/swap/permutate items
853b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru             *
854b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru             * If we swap in-place, then the permutation must use another
855b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru             * temporary array (pTempTable->resort)
856b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru             * before the results are copied to the outBundle.
857b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru             */
858b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            /* keys */
859b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if(pKey16!=NULL) {
860b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                uint16_t *rKey16;
861b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
862b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                if(pKey16!=qKey16) {
863b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    rKey16=qKey16;
864b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                } else {
865b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    rKey16=(uint16_t *)pTempTable->resort;
866b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
867b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                for(i=0; i<count; ++i) {
868b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    oldIndex=pTempTable->rows[i].sortIndex;
869b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    ds->swapArray16(ds, pKey16+oldIndex, 2, rKey16+i, pErrorCode);
870b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
871b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                if(qKey16!=rKey16) {
872b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    uprv_memcpy(qKey16, rKey16, 2*count);
873b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
874b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            } else {
875b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                int32_t *rKey32;
876b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
877b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                if(pKey32!=qKey32) {
878b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    rKey32=qKey32;
879b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                } else {
880b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    rKey32=pTempTable->resort;
881b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
882b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                for(i=0; i<count; ++i) {
883b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    oldIndex=pTempTable->rows[i].sortIndex;
884b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    ds->swapArray32(ds, pKey32+oldIndex, 4, rKey32+i, pErrorCode);
885b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
886b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                if(qKey32!=rKey32) {
887b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    uprv_memcpy(qKey32, rKey32, 4*count);
888b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
889b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
890b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
891b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            /* resources */
892b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            {
893b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                Resource *r;
894b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
895b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
896b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                if(p!=q) {
897b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    r=q;
898b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                } else {
899b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    r=(Resource *)pTempTable->resort;
900b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
901b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                for(i=0; i<count; ++i) {
902b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    oldIndex=pTempTable->rows[i].sortIndex;
903b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    ds->swapArray32(ds, p+oldIndex, 4, r+i, pErrorCode);
904b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
905b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                if(q!=r) {
906b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    uprv_memcpy(q, r, 4*count);
907b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
908b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
909b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
910b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        break;
911b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    case URES_ARRAY:
912b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        {
913b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            Resource item;
914b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            int32_t i;
915b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
916b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            count=udata_readInt32(ds, (int32_t)*p);
917b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            /* swap length */
918b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            ds->swapArray32(ds, p++, 4, q++, pErrorCode);
919b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
920b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            /* recurse */
921b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            for(i=0; i<count; ++i) {
922b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                item=ds->readUInt32(p[i]);
92350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                ures_swapResource(ds, inBundle, outBundle, item, NULL, pTempTable, pErrorCode);
924b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                if(U_FAILURE(*pErrorCode)) {
925b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    udata_printError(ds, "ures_swapResource(array res=%08x)[%d].recurse(%08x) failed\n",
926b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                     res, i, item);
927b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    return;
928b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
929b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
930b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
931b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            /* swap items */
932b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            ds->swapArray32(ds, p, 4*count, q, pErrorCode);
933b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
934b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        break;
935b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    case URES_INT_VECTOR:
936b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        count=udata_readInt32(ds, (int32_t)*p);
937b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* swap length and each integer */
938b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        ds->swapArray32(ds, p, 4*(1+count), q, pErrorCode);
939b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        break;
940b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    default:
941b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* also catches RES_BOGUS */
942b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        *pErrorCode=U_UNSUPPORTED_ERROR;
943b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        break;
944b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
945b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
946b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
947b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CAPI int32_t U_EXPORT2
948b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruures_swap(const UDataSwapper *ds,
949b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          const void *inData, int32_t length, void *outData,
950b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          UErrorCode *pErrorCode) {
951b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    const UDataInfo *pInfo;
952b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    const Resource *inBundle;
953b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    Resource rootRes;
954b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t headerSize, maxTableLength;
955b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
956b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    Row rows[STACK_ROW_CAPACITY];
957b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t resort[STACK_ROW_CAPACITY];
958b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    TempTable tempTable;
959b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
96050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    const int32_t *inIndexes;
96150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
962b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* the following integers count Resource item offsets (4 bytes each), not bytes */
96350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    int32_t bundleLength, indexLength, keysBottom, keysTop, resBottom, top;
964b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
965b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* udata_swapDataHeader checks the arguments */
966b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    headerSize=udata_swapDataHeader(ds, inData, length, outData, pErrorCode);
967b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(pErrorCode==NULL || U_FAILURE(*pErrorCode)) {
968b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return 0;
969b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
970b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
971b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* check data format and format version */
972b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    pInfo=(const UDataInfo *)((const char *)inData+4);
973b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(!(
974b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        pInfo->dataFormat[0]==0x52 &&   /* dataFormat="ResB" */
975b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        pInfo->dataFormat[1]==0x65 &&
976b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        pInfo->dataFormat[2]==0x73 &&
977b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        pInfo->dataFormat[3]==0x42 &&
97850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        ((pInfo->formatVersion[0]==1 && pInfo->formatVersion[1]>=1) ||  /* formatVersion 1.1+ or 2.x */
97950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho         pInfo->formatVersion[0]==2)
980b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    )) {
98150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        udata_printError(ds, "ures_swap(): data format %02x.%02x.%02x.%02x (format version %02x.%02x) is not a resource bundle\n",
982b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                         pInfo->dataFormat[0], pInfo->dataFormat[1],
983b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                         pInfo->dataFormat[2], pInfo->dataFormat[3],
98450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                         pInfo->formatVersion[0], pInfo->formatVersion[1]);
985b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        *pErrorCode=U_UNSUPPORTED_ERROR;
986b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return 0;
987b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
98850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    tempTable.majorFormatVersion=pInfo->formatVersion[0];
989b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
990b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* a resource bundle must contain at least one resource item */
991b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(length<0) {
992b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        bundleLength=-1;
993b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    } else {
994b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        bundleLength=(length-headerSize)/4;
995b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
996b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* formatVersion 1.1 must have a root item and at least 5 indexes */
99750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        if(bundleLength<(1+5)) {
998b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            udata_printError(ds, "ures_swap(): too few bytes (%d after header) for a resource bundle\n",
999b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                             length-headerSize);
1000b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            *pErrorCode=U_INDEX_OUTOFBOUNDS_ERROR;
1001b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return 0;
1002b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1003b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1004b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1005b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    inBundle=(const Resource *)((const char *)inData+headerSize);
1006b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    rootRes=ds->readUInt32(*inBundle);
1007b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
100850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    /* formatVersion 1.1 adds the indexes[] array */
100950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    inIndexes=(const int32_t *)(inBundle+1);
1010b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
101150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    indexLength=udata_readInt32(ds, inIndexes[URES_INDEX_LENGTH])&0xff;
101250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    if(indexLength<=URES_INDEX_MAX_TABLE_LENGTH) {
101350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        udata_printError(ds, "ures_swap(): too few indexes for a 1.1+ resource bundle\n");
101450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        *pErrorCode=U_INDEX_OUTOFBOUNDS_ERROR;
101550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        return 0;
101650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    }
101750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    keysBottom=1+indexLength;
101850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    keysTop=udata_readInt32(ds, inIndexes[URES_INDEX_KEYS_TOP]);
101950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    if(indexLength>URES_INDEX_16BIT_TOP) {
102050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        resBottom=udata_readInt32(ds, inIndexes[URES_INDEX_16BIT_TOP]);
102150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    } else {
102250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        resBottom=keysTop;
102350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    }
102450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    top=udata_readInt32(ds, inIndexes[URES_INDEX_BUNDLE_TOP]);
102550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    maxTableLength=udata_readInt32(ds, inIndexes[URES_INDEX_MAX_TABLE_LENGTH]);
1026b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
102750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    if(0<=bundleLength && bundleLength<top) {
102850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        udata_printError(ds, "ures_swap(): resource top %d exceeds bundle length %d\n",
102950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                         top, bundleLength);
103050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        *pErrorCode=U_INDEX_OUTOFBOUNDS_ERROR;
103150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        return 0;
103250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    }
103350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    if(keysTop>(1+indexLength)) {
103450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        tempTable.localKeyLimit=keysTop<<2;
103550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    } else {
103650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        tempTable.localKeyLimit=0;
1037b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1038b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1039b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(length>=0) {
1040b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        Resource *outBundle=(Resource *)((char *)outData+headerSize);
1041b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
104250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        /* track which resources we have already swapped */
104350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        uint32_t stackResFlags[STACK_ROW_CAPACITY];
104450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        int32_t resFlagsLength;
104550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
104650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        /*
104750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho         * We need one bit per 4 resource bundle bytes so that we can track
104850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho         * every possible Resource for whether we have swapped it already.
104950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho         * Multiple Resource words can refer to the same bundle offsets
105050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho         * for sharing identical values.
105150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho         * We could optimize this by allocating only for locations above
105250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho         * where Resource values are stored (above keys & strings).
105350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho         */
105450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        resFlagsLength=(length+31)>>5;          /* number of bytes needed */
105550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        resFlagsLength=(resFlagsLength+3)&~3;   /* multiple of 4 bytes for uint32_t */
105650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        if(resFlagsLength<=sizeof(stackResFlags)) {
105750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            tempTable.resFlags=stackResFlags;
105850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        } else {
105950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            tempTable.resFlags=(uint32_t *)uprv_malloc(resFlagsLength);
106050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            if(tempTable.resFlags==NULL) {
106150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                udata_printError(ds, "ures_swap(): unable to allocate memory for tracking resources\n");
106250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                *pErrorCode=U_MEMORY_ALLOCATION_ERROR;
106350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                return 0;
106450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            }
106550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        }
106650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        uprv_memset(tempTable.resFlags, 0, resFlagsLength);
106750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
1068b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* copy the bundle for binary and inaccessible data */
1069b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if(inData!=outData) {
1070b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            uprv_memcpy(outBundle, inBundle, 4*top);
1071b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1072b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1073b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* swap the key strings, but not the padding bytes (0xaa) after the last string and its NUL */
107450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        udata_swapInvStringBlock(ds, inBundle+keysBottom, 4*(keysTop-keysBottom),
107550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                                    outBundle+keysBottom, pErrorCode);
1076b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if(U_FAILURE(*pErrorCode)) {
107750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            udata_printError(ds, "ures_swap().udata_swapInvStringBlock(keys[%d]) failed\n", 4*(keysTop-keysBottom));
1078b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return 0;
1079b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1080b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
108150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        /* swap the 16-bit units (strings, table16, array16) */
108250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        if(keysTop<resBottom) {
108350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            ds->swapArray16(ds, inBundle+keysTop, (resBottom-keysTop)*4, outBundle+keysTop, pErrorCode);
108450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            if(U_FAILURE(*pErrorCode)) {
108550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                udata_printError(ds, "ures_swap().swapArray16(16-bit units[%d]) failed\n", 2*(resBottom-keysTop));
108650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                return 0;
108750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            }
108850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        }
108950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
1090b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* allocate the temporary table for sorting resource tables */
1091b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        tempTable.keyChars=(const char *)outBundle; /* sort by outCharset */
109250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        if(tempTable.majorFormatVersion>1 || maxTableLength<=STACK_ROW_CAPACITY) {
1093b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            tempTable.rows=rows;
1094b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            tempTable.resort=resort;
1095b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        } else {
1096b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            tempTable.rows=(Row *)uprv_malloc(maxTableLength*sizeof(Row)+maxTableLength*4);
1097b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if(tempTable.rows==NULL) {
1098b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                udata_printError(ds, "ures_swap(): unable to allocate memory for sorting tables (max length: %d)\n",
1099b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                 maxTableLength);
1100b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                *pErrorCode=U_MEMORY_ALLOCATION_ERROR;
110150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                if(tempTable.resFlags!=stackResFlags) {
110250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                    uprv_free(tempTable.resFlags);
110350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                }
1104b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                return 0;
1105b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
1106b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            tempTable.resort=(int32_t *)(tempTable.rows+maxTableLength);
1107b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1108b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1109b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* swap the resources */
111050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        ures_swapResource(ds, inBundle, outBundle, rootRes, NULL, &tempTable, pErrorCode);
1111b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if(U_FAILURE(*pErrorCode)) {
1112b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            udata_printError(ds, "ures_swapResource(root res=%08x) failed\n",
1113b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                             rootRes);
1114b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1115b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1116b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if(tempTable.rows!=rows) {
1117b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            uprv_free(tempTable.rows);
1118b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
111950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        if(tempTable.resFlags!=stackResFlags) {
112050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            uprv_free(tempTable.resFlags);
112150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        }
1122b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1123b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        /* swap the root resource and indexes */
112450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        ds->swapArray32(ds, inBundle, keysBottom*4, outBundle, pErrorCode);
1125b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1126b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1127b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return headerSize+4*top;
1128b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1129