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