1b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/* 2b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru******************************************************************************* 3b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* 454dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius* Copyright (C) 2000-2012, International Business Machines 5b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* Corporation and others. All Rights Reserved. 6b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* 7b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru******************************************************************************* 8b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* 9b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* File reslist.c 10b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* 11b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* Modification History: 12b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* 13b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* Date Name Description 14b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* 02/21/00 weiv Creation. 15b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru******************************************************************************* 16b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*/ 17b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 18b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include <assert.h> 19b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include <stdio.h> 20b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "reslist.h" 21b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "unewdata.h" 22b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "unicode/ures.h" 23b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "unicode/putil.h" 24b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "errmsg.h" 25b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 2650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#include "uarrsort.h" 27103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius#include "uelement.h" 2850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#include "uinvchar.h" 29103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius#include "ustr_imp.h" 3054dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius#include "unicode/utf16.h" 3150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* 3250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho * Align binary data at a 16-byte offset from the start of the resource bundle, 3350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho * to be safe for any data type it may contain. 3450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho */ 35b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define BIN_ALIGNMENT 16 36b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 37b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic UBool gIncludeCopyright = FALSE; 3850294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic UBool gUsePoolBundle = FALSE; 3950294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic int32_t gFormatVersion = 2; 4050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 4150294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic UChar gEmptyString = 0; 4250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 4350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* How do we store string values? */ 4450294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoenum { 4550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho STRINGS_UTF16_V1, /* formatVersion 1: int length + UChars + NUL + padding to 4 bytes */ 4650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho STRINGS_UTF16_V2 /* formatVersion 2: optional length in 1..3 UChars + UChars + NUL */ 4750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho}; 4850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 4950294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoenum { 5050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho MAX_IMPLICIT_STRING_LENGTH = 40 /* do not store the length explicitly for such strings */ 5150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho}; 52b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 53c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru/* 54c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru * res_none() returns the address of kNoResource, 55c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru * for use in non-error cases when no resource is to be added to the bundle. 56c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru * (NULL is used in error cases.) 57c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru */ 5850294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic const struct SResource kNoResource = { URES_NONE }; 59b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 6050294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic UDataInfo dataInfo= { 61b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru sizeof(UDataInfo), 62b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 0, 63b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 64b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru U_IS_BIG_ENDIAN, 65b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru U_CHARSET_FAMILY, 66b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru sizeof(UChar), 67b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 0, 68b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 6950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho {0x52, 0x65, 0x73, 0x42}, /* dataFormat="ResB" */ 7050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho {1, 3, 0, 0}, /* formatVersion */ 71b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru {1, 4, 0, 0} /* dataVersion take a look at version inside parsed resb*/ 72b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}; 73b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 7450294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic const UVersionInfo gFormatVersions[3] = { /* indexed by a major-formatVersion integer */ 7550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho { 0, 0, 0, 0 }, 7650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho { 1, 3, 0, 0 }, 7750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho { 2, 0, 0, 0 } 7850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho}; 7950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 80b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic uint8_t calcPadding(uint32_t size) { 81b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru /* returns space we need to pad */ 82b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return (uint8_t) ((size % sizeof(uint32_t)) ? (sizeof(uint32_t) - (size % sizeof(uint32_t))) : 0); 83b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 84b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 85b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 86b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid setIncludeCopyright(UBool val){ 87b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru gIncludeCopyright=val; 88b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 89b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 90b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUBool getIncludeCopyright(void){ 91b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return gIncludeCopyright; 92b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 93b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 9450294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehovoid setFormatVersion(int32_t formatVersion) { 9550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho gFormatVersion = formatVersion; 9650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho} 97b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 9850294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehovoid setUsePoolBundle(UBool use) { 9950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho gUsePoolBundle = use; 100b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 101b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 10250294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic void 10350294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehobundle_compactStrings(struct SRBRoot *bundle, UErrorCode *status); 10450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 105b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/* Writing Functions */ 106b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 10750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* 10850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho * type_write16() functions write resource values into f16BitUnits 10950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho * and determine the resource item word, if possible. 11050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho */ 11150294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic void 11250294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehores_write16(struct SRBRoot *bundle, struct SResource *res, 11350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho UErrorCode *status); 114b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 11550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* 11650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho * type_preWrite() functions calculate ("preflight") and advance the *byteOffset 11750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho * by the size of their data in the binary file and 11850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho * determine the resource item word. 11950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho * Most type_preWrite() functions may add any number of bytes, but res_preWrite() 12050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho * will always pad it to a multiple of 4. 12150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho * The resource item type may be a related subtype of the fType. 12250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho * 12350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho * The type_preWrite() and type_write() functions start and end at the same 12450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho * byteOffset values. 12550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho * Prewriting allows bundle_write() to determine the root resource item word, 12650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho * before actually writing the bundle contents to the file, 12750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho * which is necessary because the root item is stored at the beginning. 12850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho */ 12950294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic void 13050294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehores_preWrite(uint32_t *byteOffset, 13150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho struct SRBRoot *bundle, struct SResource *res, 13250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho UErrorCode *status); 133b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 13450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* 13550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho * type_write() functions write their data to mem and update the byteOffset 13650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho * in parallel. 13750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho * (A kingdom for C++ and polymorphism...) 13850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho */ 13950294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic void 14050294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehores_write(UNewDataMemory *mem, uint32_t *byteOffset, 14150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho struct SRBRoot *bundle, struct SResource *res, 14250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho UErrorCode *status); 143b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 14450294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic uint16_t * 14550294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoreserve16BitUnits(struct SRBRoot *bundle, int32_t length, UErrorCode *status) { 146b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (U_FAILURE(*status)) { 14750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return NULL; 14850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 14950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if ((bundle->f16BitUnitsLength + length) > bundle->f16BitUnitsCapacity) { 15050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uint16_t *newUnits; 15150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho int32_t capacity = 2 * bundle->f16BitUnitsCapacity + length + 1024; 15250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho capacity &= ~1; /* ensures padding fits if f16BitUnitsLength needs it */ 15350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho newUnits = (uint16_t *)uprv_malloc(capacity * 2); 15450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (newUnits == NULL) { 15550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *status = U_MEMORY_ALLOCATION_ERROR; 15650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return NULL; 15750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 15850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (bundle->f16BitUnitsLength > 0) { 15950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_memcpy(newUnits, bundle->f16BitUnits, bundle->f16BitUnitsLength * 2); 16050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } else { 16150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho newUnits[0] = 0; 16250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho bundle->f16BitUnitsLength = 1; 16350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 16450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_free(bundle->f16BitUnits); 16550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho bundle->f16BitUnits = newUnits; 16650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho bundle->f16BitUnitsCapacity = capacity; 167b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 16850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return bundle->f16BitUnits + bundle->f16BitUnitsLength; 16950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho} 170b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 17150294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic int32_t 17250294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehomakeRes16(uint32_t resWord) { 17350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uint32_t type, offset; 17450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (resWord == 0) { 17550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return 0; /* empty string */ 17650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 17750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho type = RES_GET_TYPE(resWord); 17850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho offset = RES_GET_OFFSET(resWord); 17950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (type == URES_STRING_V2 && offset <= 0xffff) { 18050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return (int32_t)offset; 18150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 18250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return -1; 18350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho} 184b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 18550294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic int32_t 18650294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehomapKey(struct SRBRoot *bundle, int32_t oldpos) { 18750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const KeyMapEntry *map = bundle->fKeyMap; 18850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho int32_t i, start, limit; 18950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 19050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* do a binary search for the old, pre-bundle_compactKeys() key offset */ 19150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho start = bundle->fPoolBundleKeysCount; 19250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho limit = start + bundle->fKeysCount; 19350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho while (start < limit - 1) { 19450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho i = (start + limit) / 2; 19550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (oldpos < map[i].oldpos) { 19650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho limit = i; 19750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } else { 19850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho start = i; 199b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 20050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 20150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho assert(oldpos == map[start].oldpos); 20250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return map[start].newpos; 20350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho} 204b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 20550294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic uint16_t 20650294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehomakeKey16(struct SRBRoot *bundle, int32_t key) { 20750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (key >= 0) { 20850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return (uint16_t)key; 20950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } else { 21050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return (uint16_t)(key + bundle->fLocalKeyLimit); /* offset in the pool bundle */ 21150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 21250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho} 213b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 21450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* 21550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho * Only called for UTF-16 v1 strings and duplicate UTF-16 v2 strings. 21650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho * For unique UTF-16 v2 strings, res_write16() sees fRes != RES_BOGUS 21750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho * and exits early. 21850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho */ 21950294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic void 22050294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostring_write16(struct SRBRoot *bundle, struct SResource *res, UErrorCode *status) { 22150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho struct SResource *same; 22250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if ((same = res->u.fString.fSame) != NULL) { 22350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* This is a duplicate. */ 22450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (same->fRes == RES_BOGUS) { 22550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* The original has not been visited yet. */ 22650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho string_write16(bundle, same, status); 22750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 22850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->fRes = same->fRes; 22950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->fWritten = same->fWritten; 23050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 23150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho} 232b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 23350294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic void 23450294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoarray_write16(struct SRBRoot *bundle, struct SResource *res, 23550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho UErrorCode *status) { 23650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho struct SResource *current; 23750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho int32_t res16 = 0; 238b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 23950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (U_FAILURE(*status)) { 24050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return; 24150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 24250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (res->u.fArray.fCount == 0 && gFormatVersion > 1) { 24350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->fRes = URES_MAKE_EMPTY_RESOURCE(URES_ARRAY); 24450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->fWritten = TRUE; 24550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return; 24650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 24750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (current = res->u.fArray.fFirst; current != NULL; current = current->fNext) { 24850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res_write16(bundle, current, status); 24950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res16 |= makeRes16(current->fRes); 25050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 25150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (U_SUCCESS(*status) && res->u.fArray.fCount <= 0xffff && res16 >= 0 && gFormatVersion > 1) { 25250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uint16_t *p16 = reserve16BitUnits(bundle, 1 + res->u.fArray.fCount, status); 25350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (U_SUCCESS(*status)) { 25450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->fRes = URES_MAKE_RESOURCE(URES_ARRAY16, bundle->f16BitUnitsLength); 25550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *p16++ = (uint16_t)res->u.fArray.fCount; 25650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (current = res->u.fArray.fFirst; current != NULL; current = current->fNext) { 25750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *p16++ = (uint16_t)makeRes16(current->fRes); 25850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 25950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho bundle->f16BitUnitsLength += 1 + res->u.fArray.fCount; 26050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->fWritten = TRUE; 261b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 26250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 26350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho} 264b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 26550294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic void 26650294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehotable_write16(struct SRBRoot *bundle, struct SResource *res, 26750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho UErrorCode *status) { 26850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho struct SResource *current; 26950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho int32_t maxKey = 0, maxPoolKey = 0x80000000; 27050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho int32_t res16 = 0; 27150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho UBool hasLocalKeys = FALSE, hasPoolKeys = FALSE; 272b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 27350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (U_FAILURE(*status)) { 27450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return; 27550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 27650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (res->u.fTable.fCount == 0 && gFormatVersion > 1) { 27750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->fRes = URES_MAKE_EMPTY_RESOURCE(URES_TABLE); 27850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->fWritten = TRUE; 27950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return; 28050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 28150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Find the smallest table type that fits the data. */ 28250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (current = res->u.fTable.fFirst; current != NULL; current = current->fNext) { 28350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho int32_t key; 28450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res_write16(bundle, current, status); 28550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (bundle->fKeyMap == NULL) { 28650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho key = current->fKey; 28750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } else { 28850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho key = current->fKey = mapKey(bundle, current->fKey); 28950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 29050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (key >= 0) { 29150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho hasLocalKeys = TRUE; 29250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (key > maxKey) { 29350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho maxKey = key; 29450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 29550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } else { 29650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho hasPoolKeys = TRUE; 29750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (key > maxPoolKey) { 29850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho maxPoolKey = key; 29950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 30050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 30150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res16 |= makeRes16(current->fRes); 30250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 30350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (U_FAILURE(*status)) { 30450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return; 30550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 30650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if(res->u.fTable.fCount > (uint32_t)bundle->fMaxTableLength) { 30750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho bundle->fMaxTableLength = res->u.fTable.fCount; 30850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 30950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho maxPoolKey &= 0x7fffffff; 31050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (res->u.fTable.fCount <= 0xffff && 31150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho (!hasLocalKeys || maxKey < bundle->fLocalKeyLimit) && 31250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho (!hasPoolKeys || maxPoolKey < (0x10000 - bundle->fLocalKeyLimit)) 31350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho ) { 31450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (res16 >= 0 && gFormatVersion > 1) { 31550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uint16_t *p16 = reserve16BitUnits(bundle, 1 + res->u.fTable.fCount * 2, status); 31650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (U_SUCCESS(*status)) { 31750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* 16-bit count, key offsets and values */ 31850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->fRes = URES_MAKE_RESOURCE(URES_TABLE16, bundle->f16BitUnitsLength); 31950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *p16++ = (uint16_t)res->u.fTable.fCount; 32050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (current = res->u.fTable.fFirst; current != NULL; current = current->fNext) { 32150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *p16++ = makeKey16(bundle, current->fKey); 32250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 32350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (current = res->u.fTable.fFirst; current != NULL; current = current->fNext) { 32450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *p16++ = (uint16_t)makeRes16(current->fRes); 32550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 32650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho bundle->f16BitUnitsLength += 1 + res->u.fTable.fCount * 2; 32750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->fWritten = TRUE; 32850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 32950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } else { 33050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* 16-bit count, 16-bit key offsets, 32-bit values */ 33150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->u.fTable.fType = URES_TABLE; 33250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 333b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } else { 33450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* 32-bit count, key offsets and values */ 33550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->u.fTable.fType = URES_TABLE32; 336b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 337b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 338b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 33950294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic void 34050294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehores_write16(struct SRBRoot *bundle, struct SResource *res, 34150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho UErrorCode *status) { 34250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (U_FAILURE(*status) || res == NULL) { 34350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return; 34450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 34550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (res->fRes != RES_BOGUS) { 34650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* 34750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho * The resource item word was already precomputed, which means 34850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho * no further data needs to be written. 34950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho * This might be an integer, or an empty or UTF-16 v2 string, 35050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho * an empty binary, etc. 35150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho */ 35250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return; 353b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 35450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho switch (res->fType) { 35550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho case URES_STRING: 35650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho string_write16(bundle, res, status); 35750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break; 35850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho case URES_ARRAY: 35950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho array_write16(bundle, res, status); 36050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break; 36150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho case URES_TABLE: 36250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho table_write16(bundle, res, status); 36350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break; 36450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho default: 36550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Only a few resource types write 16-bit units. */ 36650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break; 36750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 36850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho} 369b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 37050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* 37150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho * Only called for UTF-16 v1 strings. 37250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho * For UTF-16 v2 strings, res_preWrite() sees fRes != RES_BOGUS 37350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho * and exits early. 37450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho */ 37550294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic void 37650294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostring_preWrite(uint32_t *byteOffset, 37750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho struct SRBRoot *bundle, struct SResource *res, 37850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho UErrorCode *status) { 37950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Write the UTF-16 v1 string. */ 38050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->fRes = URES_MAKE_RESOURCE(URES_STRING, *byteOffset >> 2); 38150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *byteOffset += 4 + (res->u.fString.fLength + 1) * U_SIZEOF_UCHAR; 382b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 383b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 38450294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic void 38550294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehobin_preWrite(uint32_t *byteOffset, 38650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho struct SRBRoot *bundle, struct SResource *res, 38750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho UErrorCode *status) { 388b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru uint32_t pad = 0; 38950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uint32_t dataStart = *byteOffset + sizeof(res->u.fBinaryValue.fLength); 390b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 391b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (dataStart % BIN_ALIGNMENT) { 392b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru pad = (BIN_ALIGNMENT - dataStart % BIN_ALIGNMENT); 39350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *byteOffset += pad; /* pad == 4 or 8 or 12 */ 394b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 39550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->fRes = URES_MAKE_RESOURCE(URES_BINARY, *byteOffset >> 2); 39650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *byteOffset += 4 + res->u.fBinaryValue.fLength; 397b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 398b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 39950294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic void 40050294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoarray_preWrite(uint32_t *byteOffset, 40150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho struct SRBRoot *bundle, struct SResource *res, 40250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho UErrorCode *status) { 40350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho struct SResource *current; 404b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 40550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (U_FAILURE(*status)) { 40650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return; 40750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 40850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (current = res->u.fArray.fFirst; current != NULL; current = current->fNext) { 40950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res_preWrite(byteOffset, bundle, current, status); 41050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 41150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->fRes = URES_MAKE_RESOURCE(URES_ARRAY, *byteOffset >> 2); 41250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *byteOffset += (1 + res->u.fArray.fCount) * 4; 41350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho} 414b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 41550294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic void 41650294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehotable_preWrite(uint32_t *byteOffset, 41750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho struct SRBRoot *bundle, struct SResource *res, 41850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho UErrorCode *status) { 41950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho struct SResource *current; 420b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 421b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (U_FAILURE(*status)) { 42250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return; 423b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 42450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (current = res->u.fTable.fFirst; current != NULL; current = current->fNext) { 42550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res_preWrite(byteOffset, bundle, current, status); 42650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 42750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (res->u.fTable.fType == URES_TABLE) { 42850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* 16-bit count, 16-bit key offsets, 32-bit values */ 42950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->fRes = URES_MAKE_RESOURCE(URES_TABLE, *byteOffset >> 2); 43050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *byteOffset += 2 + res->u.fTable.fCount * 6; 43150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } else { 43250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* 32-bit count, key offsets and values */ 43350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->fRes = URES_MAKE_RESOURCE(URES_TABLE32, *byteOffset >> 2); 43450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *byteOffset += 4 + res->u.fTable.fCount * 8; 43550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 43650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho} 437b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 43850294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic void 43950294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehores_preWrite(uint32_t *byteOffset, 44050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho struct SRBRoot *bundle, struct SResource *res, 44150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho UErrorCode *status) { 44250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (U_FAILURE(*status) || res == NULL) { 44350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return; 44450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 44550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (res->fRes != RES_BOGUS) { 44650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* 44750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho * The resource item word was already precomputed, which means 44850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho * no further data needs to be written. 44950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho * This might be an integer, or an empty or UTF-16 v2 string, 45050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho * an empty binary, etc. 45150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho */ 45250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return; 45350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 45450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho switch (res->fType) { 45550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho case URES_STRING: 45650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho string_preWrite(byteOffset, bundle, res, status); 45750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break; 45850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho case URES_ALIAS: 45950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->fRes = URES_MAKE_RESOURCE(URES_ALIAS, *byteOffset >> 2); 46050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *byteOffset += 4 + (res->u.fString.fLength + 1) * U_SIZEOF_UCHAR; 46150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break; 46250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho case URES_INT_VECTOR: 46350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (res->u.fIntVector.fCount == 0 && gFormatVersion > 1) { 46450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->fRes = URES_MAKE_EMPTY_RESOURCE(URES_INT_VECTOR); 46550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->fWritten = TRUE; 466b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } else { 46750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->fRes = URES_MAKE_RESOURCE(URES_INT_VECTOR, *byteOffset >> 2); 46850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *byteOffset += (1 + res->u.fIntVector.fCount) * 4; 469b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 47050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break; 47150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho case URES_BINARY: 47250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho bin_preWrite(byteOffset, bundle, res, status); 47350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break; 47450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho case URES_INT: 47550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break; 47650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho case URES_ARRAY: 47750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho array_preWrite(byteOffset, bundle, res, status); 47850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break; 47950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho case URES_TABLE: 48050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho table_preWrite(byteOffset, bundle, res, status); 48150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break; 48250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho default: 48350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *status = U_INTERNAL_PROGRAM_ERROR; 48450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break; 48550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 48650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *byteOffset += calcPadding(*byteOffset); 48750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho} 488b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 48950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* 49050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho * Only called for UTF-16 v1 strings. For UTF-16 v2 strings, 49150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho * res_write() sees fWritten and exits early. 49250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho */ 49350294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic void string_write(UNewDataMemory *mem, uint32_t *byteOffset, 49450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho struct SRBRoot *bundle, struct SResource *res, 49550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho UErrorCode *status) { 49650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Write the UTF-16 v1 string. */ 49750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho int32_t length = res->u.fString.fLength; 49850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho udata_write32(mem, length); 49950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho udata_writeUString(mem, res->u.fString.fChars, length + 1); 50050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *byteOffset += 4 + (length + 1) * U_SIZEOF_UCHAR; 50150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->fWritten = TRUE; 50250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho} 503b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 50450294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic void alias_write(UNewDataMemory *mem, uint32_t *byteOffset, 50550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho struct SRBRoot *bundle, struct SResource *res, 50650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho UErrorCode *status) { 50750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho int32_t length = res->u.fString.fLength; 50850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho udata_write32(mem, length); 50950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho udata_writeUString(mem, res->u.fString.fChars, length + 1); 51050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *byteOffset += 4 + (length + 1) * U_SIZEOF_UCHAR; 51150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho} 512b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 51350294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic void array_write(UNewDataMemory *mem, uint32_t *byteOffset, 51450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho struct SRBRoot *bundle, struct SResource *res, 51550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho UErrorCode *status) { 51650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uint32_t i; 517b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 51850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho struct SResource *current = NULL; 519b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 52050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (U_FAILURE(*status)) { 52150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return; 52250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 52350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (i = 0, current = res->u.fArray.fFirst; current != NULL; ++i, current = current->fNext) { 52450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res_write(mem, byteOffset, bundle, current, status); 52550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 52650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho assert(i == res->u.fArray.fCount); 527b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 52850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho udata_write32(mem, res->u.fArray.fCount); 52950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (current = res->u.fArray.fFirst; current != NULL; current = current->fNext) { 53050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho udata_write32(mem, current->fRes); 53150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 53250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *byteOffset += (1 + res->u.fArray.fCount) * 4; 53350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho} 534b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 53550294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic void intvector_write(UNewDataMemory *mem, uint32_t *byteOffset, 53650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho struct SRBRoot *bundle, struct SResource *res, 53750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho UErrorCode *status) { 53850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uint32_t i = 0; 53950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho udata_write32(mem, res->u.fIntVector.fCount); 54050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for(i = 0; i<res->u.fIntVector.fCount; i++) { 54150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho udata_write32(mem, res->u.fIntVector.fArray[i]); 54250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 54350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *byteOffset += (1 + res->u.fIntVector.fCount) * 4; 54450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho} 545b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 54650294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic void bin_write(UNewDataMemory *mem, uint32_t *byteOffset, 54750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho struct SRBRoot *bundle, struct SResource *res, 54850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho UErrorCode *status) { 54950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uint32_t pad = 0; 55050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uint32_t dataStart = *byteOffset + sizeof(res->u.fBinaryValue.fLength); 551b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 55250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (dataStart % BIN_ALIGNMENT) { 55350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho pad = (BIN_ALIGNMENT - dataStart % BIN_ALIGNMENT); 55450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho udata_writePadding(mem, pad); /* pad == 4 or 8 or 12 */ 55550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *byteOffset += pad; 556b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 557b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 55850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho udata_write32(mem, res->u.fBinaryValue.fLength); 55950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (res->u.fBinaryValue.fLength > 0) { 56050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho udata_writeBlock(mem, res->u.fBinaryValue.fData, res->u.fBinaryValue.fLength); 56150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 56250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *byteOffset += 4 + res->u.fBinaryValue.fLength; 563b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 564b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 56550294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic void table_write(UNewDataMemory *mem, uint32_t *byteOffset, 56650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho struct SRBRoot *bundle, struct SResource *res, 56750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho UErrorCode *status) { 56850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho struct SResource *current; 56950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uint32_t i; 57050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 571b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (U_FAILURE(*status)) { 57250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return; 573b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 57450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (i = 0, current = res->u.fTable.fFirst; current != NULL; ++i, current = current->fNext) { 57550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho assert(i < res->u.fTable.fCount); 57650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res_write(mem, byteOffset, bundle, current, status); 57750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 57850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho assert(i == res->u.fTable.fCount); 579b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 58050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if(res->u.fTable.fType == URES_TABLE) { 58150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho udata_write16(mem, (uint16_t)res->u.fTable.fCount); 58250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (current = res->u.fTable.fFirst; current != NULL; current = current->fNext) { 58350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho udata_write16(mem, makeKey16(bundle, current->fKey)); 58450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 58550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *byteOffset += (1 + res->u.fTable.fCount)* 2; 58650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if ((res->u.fTable.fCount & 1) == 0) { 58750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* 16-bit count and even number of 16-bit key offsets need padding before 32-bit resource items */ 58850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho udata_writePadding(mem, 2); 58950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *byteOffset += 2; 590b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 59150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } else /* URES_TABLE32 */ { 59250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho udata_write32(mem, res->u.fTable.fCount); 59350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (current = res->u.fTable.fFirst; current != NULL; current = current->fNext) { 59450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho udata_write32(mem, (uint32_t)current->fKey); 59550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 59650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *byteOffset += (1 + res->u.fTable.fCount)* 4; 59750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 59850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (current = res->u.fTable.fFirst; current != NULL; current = current->fNext) { 59950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho udata_write32(mem, current->fRes); 600b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 60150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *byteOffset += res->u.fTable.fCount * 4; 60250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho} 603b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 60450294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehovoid res_write(UNewDataMemory *mem, uint32_t *byteOffset, 60550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho struct SRBRoot *bundle, struct SResource *res, 60650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho UErrorCode *status) { 60750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uint8_t paddingSize; 60850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 60950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (U_FAILURE(*status) || res == NULL) { 61050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return; 61150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 61250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (res->fWritten) { 61350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho assert(res->fRes != RES_BOGUS); 61450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return; 61550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 61650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho switch (res->fType) { 61750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho case URES_STRING: 61850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho string_write (mem, byteOffset, bundle, res, status); 61950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break; 62050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho case URES_ALIAS: 62150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho alias_write (mem, byteOffset, bundle, res, status); 62250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break; 62350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho case URES_INT_VECTOR: 62450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho intvector_write (mem, byteOffset, bundle, res, status); 62550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break; 62650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho case URES_BINARY: 62750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho bin_write (mem, byteOffset, bundle, res, status); 62850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break; 62950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho case URES_INT: 63050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break; /* fRes was set by int_open() */ 63150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho case URES_ARRAY: 63250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho array_write (mem, byteOffset, bundle, res, status); 63350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break; 63450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho case URES_TABLE: 63550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho table_write (mem, byteOffset, bundle, res, status); 63650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break; 63750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho default: 63850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *status = U_INTERNAL_PROGRAM_ERROR; 63950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break; 64050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 64150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho paddingSize = calcPadding(*byteOffset); 64250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (paddingSize > 0) { 64350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho udata_writePadding(mem, paddingSize); 64450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *byteOffset += paddingSize; 64550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 64650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->fWritten = TRUE; 647b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 648b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 64950294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehovoid bundle_write(struct SRBRoot *bundle, 65050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const char *outputDir, const char *outputPkg, 65150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho char *writtenFilename, int writtenFilenameLen, 65250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho UErrorCode *status) { 653b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UNewDataMemory *mem = NULL; 65450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uint32_t byteOffset = 0; 655b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru uint32_t top, size; 656b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru char dataName[1024]; 657b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t indexes[URES_INDEX_TOP]; 658b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 65950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho bundle_compactKeys(bundle, status); 66050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* 66150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho * Add padding bytes to fKeys so that fKeysTop is 4-aligned. 66250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho * Safe because the capacity is a multiple of 4. 66350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho */ 66450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho while (bundle->fKeysTop & 3) { 66550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho bundle->fKeys[bundle->fKeysTop++] = (char)0xaa; 66650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 66750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* 66850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho * In URES_TABLE, use all local key offsets that fit into 16 bits, 66950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho * and use the remaining 16-bit offsets for pool key offsets 67050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho * if there are any. 67150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho * If there are no local keys, then use the whole 16-bit space 67250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho * for pool key offsets. 67350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho * Note: This cannot be changed without changing the major formatVersion. 67450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho */ 67550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (bundle->fKeysBottom < bundle->fKeysTop) { 67650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (bundle->fKeysTop <= 0x10000) { 67750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho bundle->fLocalKeyLimit = bundle->fKeysTop; 67850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } else { 67950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho bundle->fLocalKeyLimit = 0x10000; 68050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 68150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } else { 68250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho bundle->fLocalKeyLimit = 0; 683b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 684b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 68550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho bundle_compactStrings(bundle, status); 68650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res_write16(bundle, bundle->fRoot, status); 68750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (bundle->f16BitUnitsLength & 1) { 68850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho bundle->f16BitUnits[bundle->f16BitUnitsLength++] = 0xaaaa; /* pad to multiple of 4 bytes */ 68950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 69050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* all keys have been mapped */ 69150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_free(bundle->fKeyMap); 69250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho bundle->fKeyMap = NULL; 69350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 69450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho byteOffset = bundle->fKeysTop + bundle->f16BitUnitsLength * 2; 69550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res_preWrite(&byteOffset, bundle, bundle->fRoot, status); 69650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 69750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* total size including the root item */ 69850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho top = byteOffset; 69950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 700b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (U_FAILURE(*status)) { 701b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return; 702b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 703b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 70450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (writtenFilename && writtenFilenameLen) { 70550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *writtenFilename = 0; 70650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 70750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 708b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (writtenFilename) { 709b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t off = 0, len = 0; 710b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (outputDir) { 711b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru len = (int32_t)uprv_strlen(outputDir); 712b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (len > writtenFilenameLen) { 713b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru len = writtenFilenameLen; 714b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 715b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru uprv_strncpy(writtenFilename, outputDir, len); 716b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 717b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (writtenFilenameLen -= len) { 718b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru off += len; 719b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru writtenFilename[off] = U_FILE_SEP_CHAR; 720b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (--writtenFilenameLen) { 721b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ++off; 722b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if(outputPkg != NULL) 723b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru { 724b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru uprv_strcpy(writtenFilename+off, outputPkg); 725b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru off += (int32_t)uprv_strlen(outputPkg); 726b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru writtenFilename[off] = '_'; 727b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ++off; 728b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 729b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 730b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru len = (int32_t)uprv_strlen(bundle->fLocale); 731b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (len > writtenFilenameLen) { 732b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru len = writtenFilenameLen; 733b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 734b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru uprv_strncpy(writtenFilename + off, bundle->fLocale, len); 735b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (writtenFilenameLen -= len) { 736b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru off += len; 737b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru len = 5; 738b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (len > writtenFilenameLen) { 739b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru len = writtenFilenameLen; 740b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 741b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru uprv_strncpy(writtenFilename + off, ".res", len); 742b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 743b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 744b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 745b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 746b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 747b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if(outputPkg) 748b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru { 749b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru uprv_strcpy(dataName, outputPkg); 750b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru uprv_strcat(dataName, "_"); 751b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru uprv_strcat(dataName, bundle->fLocale); 752b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 753b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru else 754b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru { 755b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru uprv_strcpy(dataName, bundle->fLocale); 756b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 757b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 75850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_memcpy(dataInfo.formatVersion, gFormatVersions + gFormatVersion, sizeof(UVersionInfo)); 75950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 760b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru mem = udata_create(outputDir, "res", dataName, &dataInfo, (gIncludeCopyright==TRUE)? U_COPYRIGHT_STRING:NULL, status); 761b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if(U_FAILURE(*status)){ 762b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return; 763b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 764b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 765b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru /* write the root item */ 76650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho udata_write32(mem, bundle->fRoot->fRes); 767b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 768b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru /* 769b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * formatVersion 1.1 (ICU 2.8): 770b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * write int32_t indexes[] after root and before the strings 771b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * to make it easier to parse resource bundles in icuswap or from Java etc. 772b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru */ 773b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru uprv_memset(indexes, 0, sizeof(indexes)); 77450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho indexes[URES_INDEX_LENGTH]= bundle->fIndexLength; 77550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho indexes[URES_INDEX_KEYS_TOP]= bundle->fKeysTop>>2; 776b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru indexes[URES_INDEX_RESOURCES_TOP]= (int32_t)(top>>2); 777b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru indexes[URES_INDEX_BUNDLE_TOP]= indexes[URES_INDEX_RESOURCES_TOP]; 778b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru indexes[URES_INDEX_MAX_TABLE_LENGTH]= bundle->fMaxTableLength; 779b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 780b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru /* 781b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * formatVersion 1.2 (ICU 3.6): 782b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * write indexes[URES_INDEX_ATTRIBUTES] with URES_ATT_NO_FALLBACK set or not set 783b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * the memset() above initialized all indexes[] to 0 784b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru */ 78550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (bundle->noFallback) { 786b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru indexes[URES_INDEX_ATTRIBUTES]=URES_ATT_NO_FALLBACK; 787b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 78850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* 78950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho * formatVersion 2.0 (ICU 4.4): 79050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho * more compact string value storage, optional pool bundle 79150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho */ 79250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (URES_INDEX_16BIT_TOP < bundle->fIndexLength) { 79350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho indexes[URES_INDEX_16BIT_TOP] = (bundle->fKeysTop>>2) + (bundle->f16BitUnitsLength>>1); 79450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 79550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (URES_INDEX_POOL_CHECKSUM < bundle->fIndexLength) { 79650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (bundle->fIsPoolBundle) { 79750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho indexes[URES_INDEX_ATTRIBUTES] |= URES_ATT_IS_POOL_BUNDLE | URES_ATT_NO_FALLBACK; 79850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho indexes[URES_INDEX_POOL_CHECKSUM] = 79950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho (int32_t)computeCRC((char *)(bundle->fKeys + bundle->fKeysBottom), 80050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho (uint32_t)(bundle->fKeysTop - bundle->fKeysBottom), 80150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 0); 80250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } else if (gUsePoolBundle) { 80350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho indexes[URES_INDEX_ATTRIBUTES] |= URES_ATT_USES_POOL_BUNDLE; 80450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho indexes[URES_INDEX_POOL_CHECKSUM] = bundle->fPoolChecksum; 80550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 80650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 807b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 808b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru /* write the indexes[] */ 80950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho udata_writeBlock(mem, indexes, bundle->fIndexLength*4); 810b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 811b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru /* write the table key strings */ 81250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho udata_writeBlock(mem, bundle->fKeys+bundle->fKeysBottom, 81350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho bundle->fKeysTop-bundle->fKeysBottom); 814b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 81550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* write the v2 UTF-16 strings, URES_TABLE16 and URES_ARRAY16 */ 81650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho udata_writeBlock(mem, bundle->f16BitUnits, bundle->f16BitUnitsLength*2); 817b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 818b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru /* write all of the bundle contents: the root item and its children */ 81950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho byteOffset = bundle->fKeysTop + bundle->f16BitUnitsLength * 2; 82050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res_write(mem, &byteOffset, bundle, bundle->fRoot, status); 82150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho assert(byteOffset == top); 822b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 823b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru size = udata_finish(mem, status); 824b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if(top != size) { 825b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru fprintf(stderr, "genrb error: wrote %u bytes but counted %u\n", 826b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru (int)size, (int)top); 827b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *status = U_INTERNAL_PROGRAM_ERROR; 828b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 829b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 830b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 831b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/* Opening Functions */ 832b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 83350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/* gcc 4.2 complained "no previous prototype for res_open" without this prototype... */ 83450294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostruct SResource* res_open(struct SRBRoot *bundle, const char *tag, 83550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const struct UString* comment, UErrorCode* status); 83650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 83750294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostruct SResource* res_open(struct SRBRoot *bundle, const char *tag, 83850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const struct UString* comment, UErrorCode* status){ 83950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho struct SResource *res; 84050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho int32_t key = bundle_addtag(bundle, tag, status); 841b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (U_FAILURE(*status)) { 842b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return NULL; 843b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 844b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 845b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru res = (struct SResource *) uprv_malloc(sizeof(struct SResource)); 846b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (res == NULL) { 847b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *status = U_MEMORY_ALLOCATION_ERROR; 848b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return NULL; 849b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 850b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru uprv_memset(res, 0, sizeof(struct SResource)); 85150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->fKey = key; 85250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->fRes = RES_BOGUS; 853b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 854c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru ustr_init(&res->fComment); 855b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if(comment != NULL){ 856c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru ustr_cpy(&res->fComment, comment, status); 85750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (U_FAILURE(*status)) { 85850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res_close(res); 85950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return NULL; 86050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 861b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 862b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return res; 863b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 864c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru 865c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Querustruct SResource* res_none() { 86650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return (struct SResource*)&kNoResource; 867c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru} 868c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru 86950294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostruct SResource* table_open(struct SRBRoot *bundle, const char *tag, const struct UString* comment, UErrorCode *status) { 87050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho struct SResource *res = res_open(bundle, tag, comment, status); 871b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (U_FAILURE(*status)) { 872b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return NULL; 873b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 874b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru res->fType = URES_TABLE; 87550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->u.fTable.fRoot = bundle; 876b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return res; 877b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 878b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 879b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustruct SResource* array_open(struct SRBRoot *bundle, const char *tag, const struct UString* comment, UErrorCode *status) { 88050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho struct SResource *res = res_open(bundle, tag, comment, status); 881b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (U_FAILURE(*status)) { 882b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return NULL; 883b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 884b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru res->fType = URES_ARRAY; 88550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return res; 88650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho} 887b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 88850294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic int32_t U_CALLCONV 889103e9ffba2cba345d0078eb8b8db33249f81840aCraig Corneliusstring_hash(const UElement key) { 89050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const struct SResource *res = (struct SResource *)key.pointer; 891103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius return ustr_hashUCharsN(res->u.fString.fChars, res->u.fString.fLength); 89250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho} 893b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 89450294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic UBool U_CALLCONV 895103e9ffba2cba345d0078eb8b8db33249f81840aCraig Corneliusstring_comp(const UElement key1, const UElement key2) { 89650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const struct SResource *res1 = (struct SResource *)key1.pointer; 89750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const struct SResource *res2 = (struct SResource *)key2.pointer; 89850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return 0 == u_strCompare(res1->u.fString.fChars, res1->u.fString.fLength, 89950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res2->u.fString.fChars, res2->u.fString.fLength, 90050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho FALSE); 901b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 902b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 903b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehostruct SResource *string_open(struct SRBRoot *bundle, const char *tag, const UChar *value, int32_t len, const struct UString* comment, UErrorCode *status) { 90450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho struct SResource *res = res_open(bundle, tag, comment, status); 905b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (U_FAILURE(*status)) { 906b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return NULL; 907b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 908b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru res->fType = URES_STRING; 909b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 91050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (len == 0 && gFormatVersion > 1) { 91150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->u.fString.fChars = &gEmptyString; 91250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->fRes = 0; 91350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->fWritten = TRUE; 91450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return res; 915b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 916b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 917b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru res->u.fString.fLength = len; 918b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 91950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (gFormatVersion > 1) { 92050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* check for duplicates */ 92150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->u.fString.fChars = (UChar *)value; 92250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (bundle->fStringSet == NULL) { 92350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho UErrorCode localStatus = U_ZERO_ERROR; /* if failure: just don't detect dups */ 92450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho bundle->fStringSet = uhash_open(string_hash, string_comp, string_comp, &localStatus); 92550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } else { 92650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->u.fString.fSame = uhash_get(bundle->fStringSet, res); 92750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 928b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 92950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (res->u.fString.fSame == NULL) { 93050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* this is a new string */ 93150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->u.fString.fChars = (UChar *) uprv_malloc(sizeof(UChar) * (len + 1)); 932b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 93350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (res->u.fString.fChars == NULL) { 93450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *status = U_MEMORY_ALLOCATION_ERROR; 93550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_free(res); 93650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return NULL; 93750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 938b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 93950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_memcpy(res->u.fString.fChars, value, sizeof(UChar) * len); 94050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->u.fString.fChars[len] = 0; 94150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (bundle->fStringSet != NULL) { 94250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* put it into the set for finding duplicates */ 94350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uhash_put(bundle->fStringSet, res, res, status); 94450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 94550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 94650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (bundle->fStringsForm != STRINGS_UTF16_V1) { 94750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (len <= MAX_IMPLICIT_STRING_LENGTH && !U16_IS_TRAIL(value[0]) && len == u_strlen(value)) { 94850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* 94950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho * This string will be stored without an explicit length. 95050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho * Runtime will detect !U16_IS_TRAIL(value[0]) and call u_strlen(). 95150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho */ 95250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->u.fString.fNumCharsForLength = 0; 95350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } else if (len <= 0x3ee) { 95450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->u.fString.fNumCharsForLength = 1; 95550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } else if (len <= 0xfffff) { 95650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->u.fString.fNumCharsForLength = 2; 95750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } else { 95850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->u.fString.fNumCharsForLength = 3; 95950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 96050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho bundle->f16BitUnitsLength += res->u.fString.fNumCharsForLength + len + 1; /* +1 for the NUL */ 96150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 96250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } else { 96350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* this is a duplicate of fSame */ 96450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho struct SResource *same = res->u.fString.fSame; 96550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->u.fString.fChars = same->u.fString.fChars; 96650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 967b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return res; 968b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 969b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 970b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/* TODO: make alias_open and string_open use the same code */ 971b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehostruct SResource *alias_open(struct SRBRoot *bundle, const char *tag, UChar *value, int32_t len, const struct UString* comment, UErrorCode *status) { 97250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho struct SResource *res = res_open(bundle, tag, comment, status); 973b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (U_FAILURE(*status)) { 974b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return NULL; 975b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 976b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru res->fType = URES_ALIAS; 97750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (len == 0 && gFormatVersion > 1) { 97850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->u.fString.fChars = &gEmptyString; 97950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->fRes = URES_MAKE_EMPTY_RESOURCE(URES_ALIAS); 98050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->fWritten = TRUE; 98150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return res; 982b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 983b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 984b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru res->u.fString.fLength = len; 985b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru res->u.fString.fChars = (UChar *) uprv_malloc(sizeof(UChar) * (len + 1)); 986b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (res->u.fString.fChars == NULL) { 987b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *status = U_MEMORY_ALLOCATION_ERROR; 988b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru uprv_free(res); 989b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return NULL; 990b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 991b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru uprv_memcpy(res->u.fString.fChars, value, sizeof(UChar) * (len + 1)); 992b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return res; 993b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 994b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 995b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 996b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehostruct SResource* intvector_open(struct SRBRoot *bundle, const char *tag, const struct UString* comment, UErrorCode *status) { 99750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho struct SResource *res = res_open(bundle, tag, comment, status); 998b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (U_FAILURE(*status)) { 999b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return NULL; 1000b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1001b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru res->fType = URES_INT_VECTOR; 1002b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1003b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru res->u.fIntVector.fCount = 0; 1004b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru res->u.fIntVector.fArray = (uint32_t *) uprv_malloc(sizeof(uint32_t) * RESLIST_MAX_INT_VECTOR); 1005b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (res->u.fIntVector.fArray == NULL) { 1006b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *status = U_MEMORY_ALLOCATION_ERROR; 1007b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru uprv_free(res); 1008b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return NULL; 1009b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1010b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return res; 1011b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 1012b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1013b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehostruct SResource *int_open(struct SRBRoot *bundle, const char *tag, int32_t value, const struct UString* comment, UErrorCode *status) { 101450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho struct SResource *res = res_open(bundle, tag, comment, status); 1015b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (U_FAILURE(*status)) { 1016b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return NULL; 1017b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1018b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru res->fType = URES_INT; 1019b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru res->u.fIntValue.fValue = value; 102050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->fRes = URES_MAKE_RESOURCE(URES_INT, value & 0x0FFFFFFF); 102150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->fWritten = TRUE; 1022b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return res; 1023b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 1024b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1025b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustruct SResource *bin_open(struct SRBRoot *bundle, const char *tag, uint32_t length, uint8_t *data, const char* fileName, const struct UString* comment, UErrorCode *status) { 102650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho struct SResource *res = res_open(bundle, tag, comment, status); 1027b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (U_FAILURE(*status)) { 1028b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return NULL; 1029b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1030b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru res->fType = URES_BINARY; 1031b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1032b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru res->u.fBinaryValue.fLength = length; 1033b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru res->u.fBinaryValue.fFileName = NULL; 1034b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if(fileName!=NULL && uprv_strcmp(fileName, "") !=0){ 1035b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru res->u.fBinaryValue.fFileName = (char*) uprv_malloc(sizeof(char) * (uprv_strlen(fileName)+1)); 1036b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru uprv_strcpy(res->u.fBinaryValue.fFileName,fileName); 1037b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1038b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (length > 0) { 1039b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru res->u.fBinaryValue.fData = (uint8_t *) uprv_malloc(sizeof(uint8_t) * length); 1040b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1041b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (res->u.fBinaryValue.fData == NULL) { 1042b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *status = U_MEMORY_ALLOCATION_ERROR; 1043b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru uprv_free(res); 1044b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return NULL; 1045b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1046b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1047b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru uprv_memcpy(res->u.fBinaryValue.fData, data, length); 1048b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1049b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru else { 1050b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru res->u.fBinaryValue.fData = NULL; 105150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (gFormatVersion > 1) { 105250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->fRes = URES_MAKE_EMPTY_RESOURCE(URES_BINARY); 105350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->fWritten = TRUE; 105450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 1055b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1056b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1057b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return res; 1058b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 1059b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 106050294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostruct SRBRoot *bundle_open(const struct UString* comment, UBool isPoolBundle, UErrorCode *status) { 106150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho struct SRBRoot *bundle; 1062b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1063b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (U_FAILURE(*status)) { 1064b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return NULL; 1065b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1066b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1067b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru bundle = (struct SRBRoot *) uprv_malloc(sizeof(struct SRBRoot)); 1068b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (bundle == NULL) { 1069b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *status = U_MEMORY_ALLOCATION_ERROR; 1070b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return 0; 1071b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1072b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru uprv_memset(bundle, 0, sizeof(struct SRBRoot)); 1073b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 107450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho bundle->fKeys = (char *) uprv_malloc(sizeof(char) * KEY_SPACE_SIZE); 107550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho bundle->fRoot = table_open(bundle, NULL, comment, status); 107650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (bundle->fKeys == NULL || bundle->fRoot == NULL || U_FAILURE(*status)) { 1077b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (U_SUCCESS(*status)) { 1078b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *status = U_MEMORY_ALLOCATION_ERROR; 1079b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 108050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho bundle_close(bundle, status); 1081b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return NULL; 1082b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1083b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 108450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho bundle->fLocale = NULL; 108550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho bundle->fKeysCapacity = KEY_SPACE_SIZE; 108650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* formatVersion 1.1: start fKeysTop after the root item and indexes[] */ 108750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho bundle->fIsPoolBundle = isPoolBundle; 108850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (gUsePoolBundle || isPoolBundle) { 108950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho bundle->fIndexLength = URES_INDEX_POOL_CHECKSUM + 1; 109050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } else if (gFormatVersion >= 2) { 109150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho bundle->fIndexLength = URES_INDEX_16BIT_TOP + 1; 109250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } else /* formatVersion 1 */ { 109350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho bundle->fIndexLength = URES_INDEX_ATTRIBUTES + 1; 109450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 109550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho bundle->fKeysBottom = (1 /* root */ + bundle->fIndexLength) * 4; 109650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_memset(bundle->fKeys, 0, bundle->fKeysBottom); 109750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho bundle->fKeysTop = bundle->fKeysBottom; 109850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 109950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (gFormatVersion == 1) { 110050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho bundle->fStringsForm = STRINGS_UTF16_V1; 110150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } else { 110250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho bundle->fStringsForm = STRINGS_UTF16_V2; 110350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 110450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 1105b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return bundle; 1106b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 1107b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1108b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/* Closing Functions */ 1109c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Querustatic void table_close(struct SResource *table) { 1110b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru struct SResource *current = NULL; 1111b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru struct SResource *prev = NULL; 1112b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1113b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru current = table->u.fTable.fFirst; 1114b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1115b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru while (current != NULL) { 1116b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru prev = current; 1117b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru current = current->fNext; 1118b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1119c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru res_close(prev); 1120b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1121b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1122b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru table->u.fTable.fFirst = NULL; 1123b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 1124b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1125c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Querustatic void array_close(struct SResource *array) { 1126b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru struct SResource *current = NULL; 1127b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru struct SResource *prev = NULL; 1128b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1129b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if(array==NULL){ 1130b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return; 1131b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1132b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru current = array->u.fArray.fFirst; 1133b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1134b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru while (current != NULL) { 1135b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru prev = current; 1136b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru current = current->fNext; 1137b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1138c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru res_close(prev); 1139b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1140b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru array->u.fArray.fFirst = NULL; 1141b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 1142b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1143c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Querustatic void string_close(struct SResource *string) { 114450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (string->u.fString.fChars != NULL && 114550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho string->u.fString.fChars != &gEmptyString && 114650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho string->u.fString.fSame == NULL 114750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho ) { 1148b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru uprv_free(string->u.fString.fChars); 1149b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru string->u.fString.fChars =NULL; 1150b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1151b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 1152b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1153c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Querustatic void alias_close(struct SResource *alias) { 1154b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (alias->u.fString.fChars != NULL) { 1155b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru uprv_free(alias->u.fString.fChars); 1156b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru alias->u.fString.fChars =NULL; 1157b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1158b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 1159b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1160c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Querustatic void intvector_close(struct SResource *intvector) { 1161b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (intvector->u.fIntVector.fArray != NULL) { 1162b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru uprv_free(intvector->u.fIntVector.fArray); 1163b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru intvector->u.fIntVector.fArray =NULL; 1164b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1165b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 1166b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1167c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Querustatic void int_close(struct SResource *intres) { 1168b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru /* Intentionally left blank */ 1169b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 1170b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1171c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Querustatic void bin_close(struct SResource *binres) { 1172b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (binres->u.fBinaryValue.fData != NULL) { 1173b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru uprv_free(binres->u.fBinaryValue.fData); 1174b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru binres->u.fBinaryValue.fData = NULL; 1175b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 117654dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius if (binres->u.fBinaryValue.fFileName != NULL) { 117754dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius uprv_free(binres->u.fBinaryValue.fFileName); 117854dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius binres->u.fBinaryValue.fFileName = NULL; 117954dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius } 1180b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 1181b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1182c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queruvoid res_close(struct SResource *res) { 1183b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (res != NULL) { 1184b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru switch(res->fType) { 1185b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru case URES_STRING: 1186c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru string_close(res); 1187b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru break; 1188b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru case URES_ALIAS: 1189c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru alias_close(res); 1190b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru break; 1191b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru case URES_INT_VECTOR: 1192c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru intvector_close(res); 1193b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru break; 1194b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru case URES_BINARY: 1195c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru bin_close(res); 1196b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru break; 1197b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru case URES_INT: 1198c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru int_close(res); 1199b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru break; 1200b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru case URES_ARRAY: 1201c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru array_close(res); 1202b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru break; 1203b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru case URES_TABLE: 1204c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru table_close(res); 1205b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru break; 1206b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru default: 1207b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru /* Shouldn't happen */ 1208b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru break; 1209b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1210b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1211c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru ustr_deinit(&res->fComment); 1212b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru uprv_free(res); 1213b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1214b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 1215b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1216b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid bundle_close(struct SRBRoot *bundle, UErrorCode *status) { 121750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res_close(bundle->fRoot); 121850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_free(bundle->fLocale); 121950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_free(bundle->fKeys); 122050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_free(bundle->fKeyMap); 122150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uhash_close(bundle->fStringSet); 122250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_free(bundle->f16BitUnits); 122350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_free(bundle); 122450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho} 1225b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 122650294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehovoid bundle_closeString(struct SRBRoot *bundle, struct SResource *string) { 122750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (bundle->fStringSet != NULL) { 122850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uhash_remove(bundle->fStringSet, string); 1229b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 123050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho string_close(string); 1231b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 1232b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1233b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/* Adding Functions */ 1234b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid table_add(struct SResource *table, struct SResource *res, int linenumber, UErrorCode *status) { 1235b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru struct SResource *current = NULL; 1236b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru struct SResource *prev = NULL; 1237b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru struct SResTable *list; 123850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const char *resKeyString; 1239b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1240b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (U_FAILURE(*status)) { 1241b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return; 1242b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1243c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru if (res == &kNoResource) { 1244c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru return; 1245c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru } 1246b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1247b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru /* remember this linenumber to report to the user if there is a duplicate key */ 1248b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru res->line = linenumber; 1249b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1250b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru /* here we need to traverse the list */ 1251b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru list = &(table->u.fTable); 1252b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ++(list->fCount); 1253b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1254b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru /* is list still empty? */ 1255b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (list->fFirst == NULL) { 1256b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru list->fFirst = res; 1257b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru res->fNext = NULL; 1258b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return; 1259b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1260b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 126150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho resKeyString = list->fRoot->fKeys + res->fKey; 126250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 1263b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru current = list->fFirst; 1264b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1265b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru while (current != NULL) { 126650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const char *currentKeyString = list->fRoot->fKeys + current->fKey; 126750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho int diff; 126850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* 126950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho * formatVersion 1: compare key strings in native-charset order 127050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho * formatVersion 2 and up: compare key strings in ASCII order 127150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho */ 127250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (gFormatVersion == 1 || U_CHARSET_FAMILY == U_ASCII_FAMILY) { 127350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho diff = uprv_strcmp(currentKeyString, resKeyString); 127450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } else { 127550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho diff = uprv_compareInvCharsAsAscii(currentKeyString, resKeyString); 127650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 127750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (diff < 0) { 1278b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru prev = current; 1279b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru current = current->fNext; 128050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } else if (diff > 0) { 1281b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru /* we're either in front of list, or in middle */ 1282b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (prev == NULL) { 1283b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru /* front of the list */ 1284b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru list->fFirst = res; 1285b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } else { 1286b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru /* middle of the list */ 1287b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru prev->fNext = res; 1288b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1289b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1290b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru res->fNext = current; 1291b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return; 1292b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } else { 1293b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru /* Key already exists! ERROR! */ 129450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho error(linenumber, "duplicate key '%s' in table, first appeared at line %d", currentKeyString, current->line); 1295b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *status = U_UNSUPPORTED_ERROR; 1296b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return; 1297b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1298b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1299b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1300b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru /* end of list */ 1301b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru prev->fNext = res; 1302b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru res->fNext = NULL; 1303b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 1304b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1305b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid array_add(struct SResource *array, struct SResource *res, UErrorCode *status) { 1306b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (U_FAILURE(*status)) { 1307b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return; 1308b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1309b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1310b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (array->u.fArray.fFirst == NULL) { 1311b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru array->u.fArray.fFirst = res; 1312b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru array->u.fArray.fLast = res; 1313b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } else { 1314b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru array->u.fArray.fLast->fNext = res; 1315b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru array->u.fArray.fLast = res; 1316b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1317b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1318b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru (array->u.fArray.fCount)++; 1319b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 1320b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1321b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid intvector_add(struct SResource *intvector, int32_t value, UErrorCode *status) { 1322b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (U_FAILURE(*status)) { 1323b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return; 1324b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1325b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1326b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *(intvector->u.fIntVector.fArray + intvector->u.fIntVector.fCount) = value; 1327b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru intvector->u.fIntVector.fCount++; 1328b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 1329b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1330b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/* Misc Functions */ 1331b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1332b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid bundle_setlocale(struct SRBRoot *bundle, UChar *locale, UErrorCode *status) { 1333b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1334b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if(U_FAILURE(*status)) { 1335b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return; 1336b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1337b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1338b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (bundle->fLocale!=NULL) { 1339b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru uprv_free(bundle->fLocale); 1340b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1341b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1342b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru bundle->fLocale= (char*) uprv_malloc(sizeof(char) * (u_strlen(locale)+1)); 1343b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1344b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if(bundle->fLocale == NULL) { 1345b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *status = U_MEMORY_ALLOCATION_ERROR; 1346b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return; 1347b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1348b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1349b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru /*u_strcpy(bundle->fLocale, locale);*/ 1350b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru u_UCharsToChars(locale, bundle->fLocale, u_strlen(locale)+1); 1351b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1352b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 1353b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 135450294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic const char * 135550294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehogetKeyString(const struct SRBRoot *bundle, int32_t key) { 135650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (key < 0) { 135750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return bundle->fPoolBundleKeys + (key & 0x7fffffff); 135850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } else { 135950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return bundle->fKeys + key; 136050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 136150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho} 136250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 136350294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoconst char * 136450294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehores_getKeyString(const struct SRBRoot *bundle, const struct SResource *res, char temp[8]) { 136550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (res->fKey == -1) { 136650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return NULL; 136750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 136850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return getKeyString(bundle, res->fKey); 136950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho} 137050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 137150294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoconst char * 137250294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehobundle_getKeyBytes(struct SRBRoot *bundle, int32_t *pLength) { 137350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *pLength = bundle->fKeysTop - bundle->fKeysBottom; 137450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return bundle->fKeys + bundle->fKeysBottom; 137550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho} 1376b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1377b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruint32_t 137850294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehobundle_addKeyBytes(struct SRBRoot *bundle, const char *keyBytes, int32_t length, UErrorCode *status) { 137950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho int32_t keypos; 1380b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1381b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (U_FAILURE(*status)) { 1382b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return -1; 1383b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 138450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (length < 0 || (keyBytes == NULL && length != 0)) { 138550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *status = U_ILLEGAL_ARGUMENT_ERROR; 1386b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return -1; 1387b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 138850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (length == 0) { 138950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return bundle->fKeysTop; 139050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 1391b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 139250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho keypos = bundle->fKeysTop; 139350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho bundle->fKeysTop += length; 139450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (bundle->fKeysTop >= bundle->fKeysCapacity) { 1395b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru /* overflow - resize the keys buffer */ 1396b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru bundle->fKeysCapacity += KEY_SPACE_SIZE; 1397b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru bundle->fKeys = uprv_realloc(bundle->fKeys, bundle->fKeysCapacity); 1398b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if(bundle->fKeys == NULL) { 1399b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru *status = U_MEMORY_ALLOCATION_ERROR; 1400b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return -1; 1401b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1402b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 1403b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 140450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_memcpy(bundle->fKeys + keypos, keyBytes, length); 140550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 140650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return keypos; 140750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho} 140850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 140950294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoint32_t 141050294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehobundle_addtag(struct SRBRoot *bundle, const char *tag, UErrorCode *status) { 141150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho int32_t keypos; 141250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 141350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (U_FAILURE(*status)) { 141450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return -1; 141550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 141650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 141750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (tag == NULL) { 141850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* no error: the root table and array items have no keys */ 141950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return -1; 142050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 1421b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 142250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho keypos = bundle_addKeyBytes(bundle, tag, (int32_t)(uprv_strlen(tag) + 1), status); 142350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (U_SUCCESS(*status)) { 142450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho ++bundle->fKeysCount; 142550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 1426b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return keypos; 1427b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 142850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 142950294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic int32_t 143050294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehocompareInt32(int32_t lPos, int32_t rPos) { 143150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* 143250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho * Compare possibly-negative key offsets. Don't just return lPos - rPos 143350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho * because that is prone to negative-integer underflows. 143450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho */ 143550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (lPos < rPos) { 143650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return -1; 143750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } else if (lPos > rPos) { 143850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return 1; 143950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } else { 144050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return 0; 144150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 144250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho} 144350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 144450294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic int32_t U_CALLCONV 144550294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehocompareKeySuffixes(const void *context, const void *l, const void *r) { 144650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const struct SRBRoot *bundle=(const struct SRBRoot *)context; 144750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho int32_t lPos = ((const KeyMapEntry *)l)->oldpos; 144850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho int32_t rPos = ((const KeyMapEntry *)r)->oldpos; 144950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const char *lStart = getKeyString(bundle, lPos); 145050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const char *lLimit = lStart; 145150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const char *rStart = getKeyString(bundle, rPos); 145250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const char *rLimit = rStart; 145350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho int32_t diff; 145450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho while (*lLimit != 0) { ++lLimit; } 145550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho while (*rLimit != 0) { ++rLimit; } 145650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* compare keys in reverse character order */ 145750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho while (lStart < lLimit && rStart < rLimit) { 145850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho diff = (int32_t)(uint8_t)*--lLimit - (int32_t)(uint8_t)*--rLimit; 145950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (diff != 0) { 146050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return diff; 146150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 146250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 146350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* sort equal suffixes by descending key length */ 146450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho diff = (int32_t)(rLimit - rStart) - (int32_t)(lLimit - lStart); 146550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (diff != 0) { 146650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return diff; 146750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 146850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Sort pool bundle keys first (negative oldpos), and otherwise keys in parsing order. */ 146950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return compareInt32(lPos, rPos); 147050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho} 147150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 147250294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic int32_t U_CALLCONV 147350294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehocompareKeyNewpos(const void *context, const void *l, const void *r) { 147450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return compareInt32(((const KeyMapEntry *)l)->newpos, ((const KeyMapEntry *)r)->newpos); 147550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho} 147650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 147750294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic int32_t U_CALLCONV 147850294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehocompareKeyOldpos(const void *context, const void *l, const void *r) { 147950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return compareInt32(((const KeyMapEntry *)l)->oldpos, ((const KeyMapEntry *)r)->oldpos); 148050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho} 148150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 148250294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehovoid 148350294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehobundle_compactKeys(struct SRBRoot *bundle, UErrorCode *status) { 148450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho KeyMapEntry *map; 148550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho char *keys; 148650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho int32_t i; 148750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho int32_t keysCount = bundle->fPoolBundleKeysCount + bundle->fKeysCount; 148850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (U_FAILURE(*status) || bundle->fKeysCount == 0 || bundle->fKeyMap != NULL) { 148950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return; 149050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 149150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho map = (KeyMapEntry *)uprv_malloc(keysCount * sizeof(KeyMapEntry)); 149250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (map == NULL) { 149350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *status = U_MEMORY_ALLOCATION_ERROR; 149450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return; 149550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 149650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho keys = (char *)bundle->fPoolBundleKeys; 149750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (i = 0; i < bundle->fPoolBundleKeysCount; ++i) { 149850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho map[i].oldpos = 149950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho (int32_t)(keys - bundle->fPoolBundleKeys) | 0x80000000; /* negative oldpos */ 150050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho map[i].newpos = 0; 150150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho while (*keys != 0) { ++keys; } /* skip the key */ 150250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho ++keys; /* skip the NUL */ 150350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 150450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho keys = bundle->fKeys + bundle->fKeysBottom; 150550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (; i < keysCount; ++i) { 150650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho map[i].oldpos = (int32_t)(keys - bundle->fKeys); 150750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho map[i].newpos = 0; 150850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho while (*keys != 0) { ++keys; } /* skip the key */ 150950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho ++keys; /* skip the NUL */ 151050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 151150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Sort the keys so that each one is immediately followed by all of its suffixes. */ 151250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_sortArray(map, keysCount, (int32_t)sizeof(KeyMapEntry), 151350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho compareKeySuffixes, bundle, FALSE, status); 151450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* 151550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho * Make suffixes point into earlier, longer strings that contain them 151650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho * and mark the old, now unused suffix bytes as deleted. 151750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho */ 151850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (U_SUCCESS(*status)) { 151950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho keys = bundle->fKeys; 152050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (i = 0; i < keysCount;) { 152150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* 152250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho * This key is not a suffix of the previous one; 152350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho * keep this one and delete the following ones that are 152450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho * suffixes of this one. 152550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho */ 152650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const char *key; 152750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const char *keyLimit; 152850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho int32_t j = i + 1; 152950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho map[i].newpos = map[i].oldpos; 153050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (j < keysCount && map[j].oldpos < 0) { 153150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Key string from the pool bundle, do not delete. */ 153250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho i = j; 153350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho continue; 153450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 153550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho key = getKeyString(bundle, map[i].oldpos); 153650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (keyLimit = key; *keyLimit != 0; ++keyLimit) {} 153750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (; j < keysCount && map[j].oldpos >= 0; ++j) { 153850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const char *k; 153950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho char *suffix; 154050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const char *suffixLimit; 154150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho int32_t offset; 154250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho suffix = keys + map[j].oldpos; 154350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (suffixLimit = suffix; *suffixLimit != 0; ++suffixLimit) {} 154450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho offset = (int32_t)(keyLimit - key) - (suffixLimit - suffix); 154550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (offset < 0) { 154650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break; /* suffix cannot be longer than the original */ 154750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 154850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Is it a suffix of the earlier, longer key? */ 154950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (k = keyLimit; suffix < suffixLimit && *--k == *--suffixLimit;) {} 155050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (suffix == suffixLimit && *k == *suffixLimit) { 155150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho map[j].newpos = map[i].oldpos + offset; /* yes, point to the earlier key */ 155250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* mark the suffix as deleted */ 155350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho while (*suffix != 0) { *suffix++ = 1; } 155450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *suffix = 1; 155550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } else { 155650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break; /* not a suffix, restart from here */ 155750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 155850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 155950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho i = j; 156050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 156150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* 156250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho * Re-sort by newpos, then modify the key characters array in-place 156350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho * to squeeze out unused bytes, and readjust the newpos offsets. 156450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho */ 156550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_sortArray(map, keysCount, (int32_t)sizeof(KeyMapEntry), 156650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho compareKeyNewpos, NULL, FALSE, status); 156750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (U_SUCCESS(*status)) { 156850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho int32_t oldpos, newpos, limit; 156950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho oldpos = newpos = bundle->fKeysBottom; 157050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho limit = bundle->fKeysTop; 157150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* skip key offsets that point into the pool bundle rather than this new bundle */ 157250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (i = 0; i < keysCount && map[i].newpos < 0; ++i) {} 157350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (i < keysCount) { 157450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho while (oldpos < limit) { 157550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (keys[oldpos] == 1) { 157650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho ++oldpos; /* skip unused bytes */ 157750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } else { 157850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* adjust the new offsets for keys starting here */ 157950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho while (i < keysCount && map[i].newpos == oldpos) { 158050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho map[i++].newpos = newpos; 158150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 158250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* move the key characters to their new position */ 158350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho keys[newpos++] = keys[oldpos++]; 158450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 158550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 158650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho assert(i == keysCount); 158750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 158850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho bundle->fKeysTop = newpos; 158950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Re-sort once more, by old offsets for binary searching. */ 159050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_sortArray(map, keysCount, (int32_t)sizeof(KeyMapEntry), 159150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho compareKeyOldpos, NULL, FALSE, status); 159250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (U_SUCCESS(*status)) { 159350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* key size reduction by limit - newpos */ 159450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho bundle->fKeyMap = map; 159550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho map = NULL; 159650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 159750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 159850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 159950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_free(map); 160050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho} 160150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 160250294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic int32_t U_CALLCONV 160350294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehocompareStringSuffixes(const void *context, const void *l, const void *r) { 160450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho struct SResource *left = *((struct SResource **)l); 160550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho struct SResource *right = *((struct SResource **)r); 160650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const UChar *lStart = left->u.fString.fChars; 160750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const UChar *lLimit = lStart + left->u.fString.fLength; 160850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const UChar *rStart = right->u.fString.fChars; 160950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const UChar *rLimit = rStart + right->u.fString.fLength; 161050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho int32_t diff; 161150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* compare keys in reverse character order */ 161250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho while (lStart < lLimit && rStart < rLimit) { 161350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho diff = (int32_t)*--lLimit - (int32_t)*--rLimit; 161450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (diff != 0) { 161550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return diff; 161650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 161750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 161850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* sort equal suffixes by descending string length */ 161950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return right->u.fString.fLength - left->u.fString.fLength; 162050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho} 162150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 162250294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic int32_t U_CALLCONV 162350294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehocompareStringLengths(const void *context, const void *l, const void *r) { 162450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho struct SResource *left = *((struct SResource **)l); 162550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho struct SResource *right = *((struct SResource **)r); 162650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho int32_t diff; 162750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Make "is suffix of another string" compare greater than a non-suffix. */ 162850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho diff = (int)(left->u.fString.fSame != NULL) - (int)(right->u.fString.fSame != NULL); 162950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (diff != 0) { 163050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return diff; 163150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 163250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* sort by ascending string length */ 163350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return left->u.fString.fLength - right->u.fString.fLength; 163450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho} 163550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 163650294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic int32_t 163750294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostring_writeUTF16v2(struct SRBRoot *bundle, struct SResource *res, int32_t utf16Length) { 163850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho int32_t length = res->u.fString.fLength; 163950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->fRes = URES_MAKE_RESOURCE(URES_STRING_V2, utf16Length); 164050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->fWritten = TRUE; 164150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho switch(res->u.fString.fNumCharsForLength) { 164250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho case 0: 164350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break; 164450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho case 1: 164550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho bundle->f16BitUnits[utf16Length++] = (uint16_t)(0xdc00 + length); 164650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break; 164750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho case 2: 164850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho bundle->f16BitUnits[utf16Length] = (uint16_t)(0xdfef + (length >> 16)); 164950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho bundle->f16BitUnits[utf16Length + 1] = (uint16_t)length; 165050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho utf16Length += 2; 165150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break; 165250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho case 3: 165350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho bundle->f16BitUnits[utf16Length] = 0xdfff; 165450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho bundle->f16BitUnits[utf16Length + 1] = (uint16_t)(length >> 16); 165550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho bundle->f16BitUnits[utf16Length + 2] = (uint16_t)length; 165650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho utf16Length += 3; 165750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break; 165850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho default: 165950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break; /* will not occur */ 166050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 166150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho u_memcpy(bundle->f16BitUnits + utf16Length, res->u.fString.fChars, length + 1); 166250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return utf16Length + length + 1; 166350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho} 166450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 166550294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic void 166650294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehobundle_compactStrings(struct SRBRoot *bundle, UErrorCode *status) { 166750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (U_FAILURE(*status)) { 166850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return; 166950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 167050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho switch(bundle->fStringsForm) { 167150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho case STRINGS_UTF16_V2: 167250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (bundle->f16BitUnitsLength > 0) { 167350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho struct SResource **array; 167450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho int32_t count = uhash_count(bundle->fStringSet); 167550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho int32_t i, pos; 167650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* 167750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho * Allocate enough space for the initial NUL and the UTF-16 v2 strings, 167850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho * and some extra for URES_TABLE16 and URES_ARRAY16 values. 167950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho * Round down to an even number. 168050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho */ 168150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho int32_t utf16Length = (bundle->f16BitUnitsLength + 20000) & ~1; 168250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho bundle->f16BitUnits = (UChar *)uprv_malloc(utf16Length * U_SIZEOF_UCHAR); 168350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho array = (struct SResource **)uprv_malloc(count * sizeof(struct SResource **)); 168450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (bundle->f16BitUnits == NULL || array == NULL) { 168550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_free(bundle->f16BitUnits); 168650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho bundle->f16BitUnits = NULL; 168750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_free(array); 168850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *status = U_MEMORY_ALLOCATION_ERROR; 168950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return; 169050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 169150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho bundle->f16BitUnitsCapacity = utf16Length; 169250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* insert the initial NUL */ 169350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho bundle->f16BitUnits[0] = 0; 169450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho utf16Length = 1; 169550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho ++bundle->f16BitUnitsLength; 169650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (pos = -1, i = 0; i < count; ++i) { 169750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho array[i] = (struct SResource *)uhash_nextElement(bundle->fStringSet, &pos)->key.pointer; 169850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 169950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Sort the strings so that each one is immediately followed by all of its suffixes. */ 170050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_sortArray(array, count, (int32_t)sizeof(struct SResource **), 170150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho compareStringSuffixes, NULL, FALSE, status); 170250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* 170350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho * Make suffixes point into earlier, longer strings that contain them. 170450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho * Temporarily use fSame and fSuffixOffset for suffix strings to 170550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho * refer to the remaining ones. 170650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho */ 170750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (U_SUCCESS(*status)) { 170850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (i = 0; i < count;) { 170950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* 171050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho * This string is not a suffix of the previous one; 171150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho * write this one and subsume the following ones that are 171250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho * suffixes of this one. 171350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho */ 171450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho struct SResource *res = array[i]; 171550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const UChar *strLimit = res->u.fString.fChars + res->u.fString.fLength; 171650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho int32_t j; 171750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (j = i + 1; j < count; ++j) { 171850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho struct SResource *suffixRes = array[j]; 171950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const UChar *s; 172050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const UChar *suffix = suffixRes->u.fString.fChars; 172150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const UChar *suffixLimit = suffix + suffixRes->u.fString.fLength; 172250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho int32_t offset = res->u.fString.fLength - suffixRes->u.fString.fLength; 172350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (offset < 0) { 172450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break; /* suffix cannot be longer than the original */ 172550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 172650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Is it a suffix of the earlier, longer key? */ 172750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (s = strLimit; suffix < suffixLimit && *--s == *--suffixLimit;) {} 172850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (suffix == suffixLimit && *s == *suffixLimit) { 172950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (suffixRes->u.fString.fNumCharsForLength == 0) { 173050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* yes, point to the earlier string */ 173150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho suffixRes->u.fString.fSame = res; 173250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho suffixRes->u.fString.fSuffixOffset = offset; 173350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } else { 173450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* write the suffix by itself if we need explicit length */ 173550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 173650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } else { 173750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break; /* not a suffix, restart from here */ 173850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 173950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 174050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho i = j; 174150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 174250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 174350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* 174450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho * Re-sort the strings by ascending length (except suffixes last) 174550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho * to optimize for URES_TABLE16 and URES_ARRAY16: 174650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho * Keep as many as possible within reach of 16-bit offsets. 174750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho */ 174850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_sortArray(array, count, (int32_t)sizeof(struct SResource **), 174950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho compareStringLengths, NULL, FALSE, status); 175050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (U_SUCCESS(*status)) { 175150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Write the non-suffix strings. */ 175250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (i = 0; i < count && array[i]->u.fString.fSame == NULL; ++i) { 175350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho utf16Length = string_writeUTF16v2(bundle, array[i], utf16Length); 175450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 175550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho /* Write the suffix strings. Make each point to the real string. */ 175650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (; i < count; ++i) { 175750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho struct SResource *res = array[i]; 175850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho struct SResource *same = res->u.fString.fSame; 175950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->fRes = same->fRes + same->u.fString.fNumCharsForLength + res->u.fString.fSuffixOffset; 176050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->u.fString.fSame = NULL; 176150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho res->fWritten = TRUE; 176250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 176350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 176450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho assert(utf16Length <= bundle->f16BitUnitsLength); 176550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho bundle->f16BitUnitsLength = utf16Length; 176650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_free(array); 176750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 176850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break; 176950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho default: 177050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break; 177150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 177250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho} 1773