1 // Copyright (C) 2016 and later: Unicode, Inc. and others. 2 // License & terms of use: http://www.unicode.org/copyright.html 3 /* 4 ******************************************************************************* 5 * 6 * Copyright (C) 2000-2015, International Business Machines 7 * Corporation and others. All Rights Reserved. 8 * 9 ******************************************************************************* 10 * 11 * File reslist.h 12 * 13 * Modification History: 14 * 15 * Date Name Description 16 * 02/21/00 weiv Creation. 17 ******************************************************************************* 18 */ 19 20 #ifndef RESLIST_H 21 #define RESLIST_H 22 23 #define KEY_SPACE_SIZE 65536 24 #define RESLIST_MAX_INT_VECTOR 2048 25 26 #include "unicode/utypes.h" 27 #include "unicode/unistr.h" 28 #include "unicode/ures.h" 29 #include "unicode/ustring.h" 30 #include "cmemory.h" 31 #include "cstring.h" 32 #include "uhash.h" 33 #include "unewdata.h" 34 #include "uresdata.h" 35 #include "ustr.h" 36 37 U_CDECL_BEGIN 38 39 class PseudoListResource; 40 41 struct ResFile { ResFileResFile42 ResFile() 43 : fBytes(NULL), fIndexes(NULL), 44 fKeys(NULL), fKeysLength(0), fKeysCount(0), 45 fStrings(NULL), fStringIndexLimit(0), 46 fChecksum(0) {} ~ResFileResFile47 ~ResFile() { close(); } 48 49 void close(); 50 51 uint8_t *fBytes; 52 const int32_t *fIndexes; 53 const char *fKeys; 54 int32_t fKeysLength; 55 int32_t fKeysCount; 56 57 PseudoListResource *fStrings; 58 int32_t fStringIndexLimit; 59 60 int32_t fChecksum; 61 }; 62 63 struct SResource; 64 65 typedef struct KeyMapEntry { 66 int32_t oldpos, newpos; 67 } KeyMapEntry; 68 69 /* Resource bundle root table */ 70 struct SRBRoot { 71 SRBRoot(const UString *comment, UBool isPoolBundle, UErrorCode &errorCode); 72 ~SRBRoot(); 73 74 void write(const char *outputDir, const char *outputPkg, 75 char *writtenFilename, int writtenFilenameLen, UErrorCode &errorCode); 76 77 void setLocale(UChar *locale, UErrorCode &errorCode); 78 int32_t addTag(const char *tag, UErrorCode &errorCode); 79 80 const char *getKeyString(int32_t key) const; 81 const char *getKeyBytes(int32_t *pLength) const; 82 83 int32_t addKeyBytes(const char *keyBytes, int32_t length, UErrorCode &errorCode); 84 85 void compactKeys(UErrorCode &errorCode); 86 87 int32_t makeRes16(uint32_t resWord) const; 88 int32_t mapKey(int32_t oldpos) const; 89 90 private: 91 void compactStringsV2(UHashtable *stringSet, UErrorCode &errorCode); 92 93 public: 94 // TODO: private 95 96 SResource *fRoot; // Normally a TableResource. 97 char *fLocale; 98 int32_t fIndexLength; 99 int32_t fMaxTableLength; 100 UBool fNoFallback; /* see URES_ATT_NO_FALLBACK */ 101 int8_t fStringsForm; /* default STRINGS_UTF16_V1 */ 102 UBool fIsPoolBundle; 103 104 char *fKeys; 105 KeyMapEntry *fKeyMap; 106 int32_t fKeysBottom, fKeysTop; 107 int32_t fKeysCapacity; 108 int32_t fKeysCount; 109 int32_t fLocalKeyLimit; /* key offset < limit fits into URES_TABLE */ 110 111 icu::UnicodeString f16BitUnits; 112 int32_t f16BitStringsLength; 113 114 const ResFile *fUsePoolBundle; 115 int32_t fPoolStringIndexLimit; 116 int32_t fPoolStringIndex16Limit; 117 int32_t fLocalStringIndexLimit; 118 SRBRoot *fWritePoolBundle; 119 }; 120 121 /* write a java resource file */ 122 // TODO: C++ify 123 void bundle_write_java(struct SRBRoot *bundle, const char *outputDir, const char* outputEnc, char *writtenFilename, 124 int writtenFilenameLen, const char* packageName, const char* bundleName, UErrorCode *status); 125 126 /* write a xml resource file */ 127 // TODO: C++ify 128 void bundle_write_xml(struct SRBRoot *bundle, const char *outputDir,const char* outputEnc, const char* rbname, 129 char *writtenFilename, int writtenFilenameLen, const char* language, const char* package, UErrorCode *status); 130 131 /* Various resource types */ 132 133 /* 134 * Return a unique pointer to a dummy object, 135 * for use in non-error cases when no resource is to be added to the bundle. 136 * (NULL is used in error cases.) 137 */ 138 struct SResource* res_none(void); 139 140 class ArrayResource; 141 class TableResource; 142 class IntVectorResource; 143 144 TableResource *table_open(struct SRBRoot *bundle, const char *tag, const struct UString* comment, UErrorCode *status); 145 146 ArrayResource *array_open(struct SRBRoot *bundle, const char *tag, const struct UString* comment, UErrorCode *status); 147 148 struct SResource *string_open(struct SRBRoot *bundle, const char *tag, const UChar *value, int32_t len, const struct UString* comment, UErrorCode *status); 149 150 struct SResource *alias_open(struct SRBRoot *bundle, const char *tag, UChar *value, int32_t len, const struct UString* comment, UErrorCode *status); 151 152 IntVectorResource *intvector_open(struct SRBRoot *bundle, const char *tag, const struct UString* comment, UErrorCode *status); 153 154 struct SResource *int_open(struct SRBRoot *bundle, const char *tag, int32_t value, const struct UString* comment, UErrorCode *status); 155 156 struct SResource *bin_open(struct SRBRoot *bundle, const char *tag, uint32_t length, uint8_t *data, const char* fileName, const struct UString* comment, UErrorCode *status); 157 158 /* Resource place holder */ 159 160 struct SResource { 161 SResource(); 162 SResource(SRBRoot *bundle, const char *tag, int8_t type, const UString* comment, 163 UErrorCode &errorCode); 164 virtual ~SResource(); 165 isTableSResource166 UBool isTable() const { return fType == URES_TABLE; } isStringSResource167 UBool isString() const { return fType == URES_STRING; } 168 169 const char *getKeyString(const SRBRoot *bundle) const; 170 171 /** 172 * Preflights strings. 173 * Finds duplicates and counts the total number of string code units 174 * so that they can be written first to the 16-bit array, 175 * for minimal string and container storage. 176 * 177 * We walk the final parse tree, rather than collecting this information while building it, 178 * so that we need not deal with changes to the parse tree (especially removing resources). 179 */ 180 void preflightStrings(SRBRoot *bundle, UHashtable *stringSet, UErrorCode &errorCode); 181 virtual void handlePreflightStrings(SRBRoot *bundle, UHashtable *stringSet, UErrorCode &errorCode); 182 183 /** 184 * Writes resource values into f16BitUnits 185 * and determines the resource item word, if possible. 186 */ 187 void write16(SRBRoot *bundle); 188 virtual void handleWrite16(SRBRoot *bundle); 189 190 /** 191 * Calculates ("preflights") and advances the *byteOffset 192 * by the size of the resource's data in the binary file and 193 * determines the resource item word. 194 * 195 * Most handlePreWrite() functions may add any number of bytes, but preWrite() 196 * will always pad it to a multiple of 4. 197 * The resource item type may be a related subtype of the fType. 198 * 199 * The preWrite() and write() functions start and end at the same 200 * byteOffset values. 201 * Prewriting allows bundle.write() to determine the root resource item word, 202 * before actually writing the bundle contents to the file, 203 * which is necessary because the root item is stored at the beginning. 204 */ 205 void preWrite(uint32_t *byteOffset); 206 virtual void handlePreWrite(uint32_t *byteOffset); 207 208 /** 209 * Writes the resource's data to mem and updates the byteOffset 210 * in parallel. 211 */ 212 void write(UNewDataMemory *mem, uint32_t *byteOffset); 213 virtual void handleWrite(UNewDataMemory *mem, uint32_t *byteOffset); 214 215 int8_t fType; /* nominal type: fRes (when != 0xffffffff) may use subtype */ 216 UBool fWritten; /* res_write() can exit early */ 217 uint32_t fRes; /* resource item word; RES_BOGUS=0xffffffff if not known yet */ 218 int32_t fRes16; /* Res16 version of fRes for Table, Table16, Array16; -1 if it does not fit. */ 219 int32_t fKey; /* Index into bundle->fKeys; -1 if no key. */ 220 int32_t fKey16; /* Key16 version of fKey for Table & Table16; -1 if no key or it does not fit. */ 221 int line; /* used internally to report duplicate keys in tables */ 222 SResource *fNext; /* This is for internal chaining while building */ 223 struct UString fComment; 224 }; 225 226 class ContainerResource : public SResource { 227 public: ContainerResource(SRBRoot * bundle,const char * tag,int8_t type,const UString * comment,UErrorCode & errorCode)228 ContainerResource(SRBRoot *bundle, const char *tag, int8_t type, 229 const UString* comment, UErrorCode &errorCode) 230 : SResource(bundle, tag, type, comment, errorCode), 231 fCount(0), fFirst(NULL) {} 232 virtual ~ContainerResource(); 233 234 virtual void handlePreflightStrings(SRBRoot *bundle, UHashtable *stringSet, UErrorCode &errorCode); 235 protected: 236 void writeAllRes16(SRBRoot *bundle); 237 void preWriteAllRes(uint32_t *byteOffset); 238 void writeAllRes(UNewDataMemory *mem, uint32_t *byteOffset); 239 void writeAllRes32(UNewDataMemory *mem, uint32_t *byteOffset); 240 241 public: 242 // TODO: private with getter? 243 uint32_t fCount; 244 SResource *fFirst; 245 }; 246 247 class TableResource : public ContainerResource { 248 public: TableResource(SRBRoot * bundle,const char * tag,const UString * comment,UErrorCode & errorCode)249 TableResource(SRBRoot *bundle, const char *tag, 250 const UString* comment, UErrorCode &errorCode) 251 : ContainerResource(bundle, tag, URES_TABLE, comment, errorCode), 252 fTableType(URES_TABLE), fRoot(bundle) {} 253 virtual ~TableResource(); 254 255 void add(SResource *res, int linenumber, UErrorCode &errorCode); 256 257 virtual void handleWrite16(SRBRoot *bundle); 258 virtual void handlePreWrite(uint32_t *byteOffset); 259 virtual void handleWrite(UNewDataMemory *mem, uint32_t *byteOffset); 260 261 int8_t fTableType; // determined by table_write16() for table_preWrite() & table_write() 262 SRBRoot *fRoot; 263 }; 264 265 class ArrayResource : public ContainerResource { 266 public: ArrayResource(SRBRoot * bundle,const char * tag,const UString * comment,UErrorCode & errorCode)267 ArrayResource(SRBRoot *bundle, const char *tag, 268 const UString* comment, UErrorCode &errorCode) 269 : ContainerResource(bundle, tag, URES_ARRAY, comment, errorCode), 270 fLast(NULL) {} 271 virtual ~ArrayResource(); 272 273 void add(SResource *res); 274 275 virtual void handleWrite16(SRBRoot *bundle); 276 virtual void handlePreWrite(uint32_t *byteOffset); 277 virtual void handleWrite(UNewDataMemory *mem, uint32_t *byteOffset); 278 279 SResource *fLast; 280 }; 281 282 /** 283 * List of resources for a pool bundle. 284 * Writes an empty table resource, rather than a container structure. 285 */ 286 class PseudoListResource : public ContainerResource { 287 public: PseudoListResource(SRBRoot * bundle,UErrorCode & errorCode)288 PseudoListResource(SRBRoot *bundle, UErrorCode &errorCode) 289 : ContainerResource(bundle, NULL, URES_TABLE, NULL, errorCode) {} 290 virtual ~PseudoListResource(); 291 292 void add(SResource *res); 293 294 virtual void handleWrite16(SRBRoot *bundle); 295 }; 296 297 class StringBaseResource : public SResource { 298 public: 299 StringBaseResource(SRBRoot *bundle, const char *tag, int8_t type, 300 const UChar *value, int32_t len, 301 const UString* comment, UErrorCode &errorCode); 302 StringBaseResource(SRBRoot *bundle, int8_t type, 303 const icu::UnicodeString &value, UErrorCode &errorCode); 304 StringBaseResource(int8_t type, const UChar *value, int32_t len, UErrorCode &errorCode); 305 virtual ~StringBaseResource(); 306 getBuffer()307 const UChar *getBuffer() const { return fString.getBuffer(); } length()308 int32_t length() const { return fString.length(); } 309 310 virtual void handlePreWrite(uint32_t *byteOffset); 311 virtual void handleWrite(UNewDataMemory *mem, uint32_t *byteOffset); 312 313 // TODO: private with getter? 314 icu::UnicodeString fString; 315 }; 316 317 class StringResource : public StringBaseResource { 318 public: StringResource(SRBRoot * bundle,const char * tag,const UChar * value,int32_t len,const UString * comment,UErrorCode & errorCode)319 StringResource(SRBRoot *bundle, const char *tag, const UChar *value, int32_t len, 320 const UString* comment, UErrorCode &errorCode) 321 : StringBaseResource(bundle, tag, URES_STRING, value, len, comment, errorCode), 322 fSame(NULL), fSuffixOffset(0), 323 fNumCopies(0), fNumUnitsSaved(0), fNumCharsForLength(0) {} StringResource(SRBRoot * bundle,const icu::UnicodeString & value,UErrorCode & errorCode)324 StringResource(SRBRoot *bundle, const icu::UnicodeString &value, UErrorCode &errorCode) 325 : StringBaseResource(bundle, URES_STRING, value, errorCode), 326 fSame(NULL), fSuffixOffset(0), 327 fNumCopies(0), fNumUnitsSaved(0), fNumCharsForLength(0) {} StringResource(int32_t poolStringIndex,int8_t numCharsForLength,const UChar * value,int32_t length,UErrorCode & errorCode)328 StringResource(int32_t poolStringIndex, int8_t numCharsForLength, 329 const UChar *value, int32_t length, 330 UErrorCode &errorCode) 331 : StringBaseResource(URES_STRING, value, length, errorCode), 332 fSame(NULL), fSuffixOffset(0), 333 fNumCopies(0), fNumUnitsSaved(0), fNumCharsForLength(numCharsForLength) { 334 // v3 pool string encoded as string-v2 with low offset 335 fRes = URES_MAKE_RESOURCE(URES_STRING_V2, poolStringIndex); 336 fWritten = TRUE; 337 } 338 virtual ~StringResource(); 339 get16BitStringsLength()340 int32_t get16BitStringsLength() const { 341 return fNumCharsForLength + length() + 1; // +1 for the NUL 342 } 343 344 virtual void handlePreflightStrings(SRBRoot *bundle, UHashtable *stringSet, UErrorCode &errorCode); 345 virtual void handleWrite16(SRBRoot *bundle); 346 347 void writeUTF16v2(int32_t base, icu::UnicodeString &dest); 348 349 StringResource *fSame; // used for duplicates 350 int32_t fSuffixOffset; // this string is a suffix of fSame at this offset 351 int32_t fNumCopies; // number of equal strings represented by one stringSet element 352 int32_t fNumUnitsSaved; // from not writing duplicates and suffixes 353 int8_t fNumCharsForLength; 354 }; 355 356 class AliasResource : public StringBaseResource { 357 public: AliasResource(SRBRoot * bundle,const char * tag,const UChar * value,int32_t len,const UString * comment,UErrorCode & errorCode)358 AliasResource(SRBRoot *bundle, const char *tag, const UChar *value, int32_t len, 359 const UString* comment, UErrorCode &errorCode) 360 : StringBaseResource(bundle, tag, URES_ALIAS, value, len, comment, errorCode) {} 361 virtual ~AliasResource(); 362 }; 363 364 class IntResource : public SResource { 365 public: 366 IntResource(SRBRoot *bundle, const char *tag, int32_t value, 367 const UString* comment, UErrorCode &errorCode); 368 virtual ~IntResource(); 369 370 // TODO: private with getter? 371 int32_t fValue; 372 }; 373 374 class IntVectorResource : public SResource { 375 public: 376 IntVectorResource(SRBRoot *bundle, const char *tag, 377 const UString* comment, UErrorCode &errorCode); 378 virtual ~IntVectorResource(); 379 380 void add(int32_t value, UErrorCode &errorCode); 381 382 virtual void handlePreWrite(uint32_t *byteOffset); 383 virtual void handleWrite(UNewDataMemory *mem, uint32_t *byteOffset); 384 385 // TODO: UVector32 386 uint32_t fCount; 387 uint32_t *fArray; 388 }; 389 390 class BinaryResource : public SResource { 391 public: 392 BinaryResource(SRBRoot *bundle, const char *tag, 393 uint32_t length, uint8_t *data, const char* fileName, 394 const UString* comment, UErrorCode &errorCode); 395 virtual ~BinaryResource(); 396 397 virtual void handlePreWrite(uint32_t *byteOffset); 398 virtual void handleWrite(UNewDataMemory *mem, uint32_t *byteOffset); 399 400 // TODO: CharString? 401 uint32_t fLength; 402 uint8_t *fData; 403 // TODO: CharString 404 char* fFileName; // file name for binary or import binary tags if any 405 }; 406 407 // TODO: use LocalPointer or delete 408 void res_close(struct SResource *res); 409 410 void setIncludeCopyright(UBool val); 411 UBool getIncludeCopyright(void); 412 413 void setFormatVersion(int32_t formatVersion); 414 415 int32_t getFormatVersion(); 416 417 void setUsePoolBundle(UBool use); 418 419 /* in wrtxml.cpp */ 420 uint32_t computeCRC(const char *ptr, uint32_t len, uint32_t lastcrc); 421 422 U_CDECL_END 423 #endif /* #ifndef RESLIST_H */ 424