|  | // © 2016 and later: Unicode, Inc. and others. | 
|  | // License & terms of use: http://www.unicode.org/copyright.html | 
|  | /* | 
|  | ******************************************************************************* | 
|  | * | 
|  | *   Copyright (C) 2000-2015, International Business Machines | 
|  | *   Corporation and others.  All Rights Reserved. | 
|  | * | 
|  | ******************************************************************************* | 
|  | * | 
|  | * File reslist.h | 
|  | * | 
|  | * Modification History: | 
|  | * | 
|  | *   Date        Name        Description | 
|  | *   02/21/00    weiv        Creation. | 
|  | ******************************************************************************* | 
|  | */ | 
|  |  | 
|  | #ifndef RESLIST_H | 
|  | #define RESLIST_H | 
|  |  | 
|  | #define KEY_SPACE_SIZE 65536 | 
|  | #define RESLIST_MAX_INT_VECTOR 2048 | 
|  |  | 
|  | #include <functional> | 
|  |  | 
|  | #include "unicode/utypes.h" | 
|  | #include "unicode/unistr.h" | 
|  | #include "unicode/ures.h" | 
|  | #include "unicode/ustring.h" | 
|  | #include "cmemory.h" | 
|  | #include "cstring.h" | 
|  | #include "uhash.h" | 
|  | #include "unewdata.h" | 
|  | #include "uresdata.h" | 
|  | #include "ustr.h" | 
|  |  | 
|  | U_CDECL_BEGIN | 
|  |  | 
|  | class PathFilter; | 
|  | class PseudoListResource; | 
|  | class ResKeyPath; | 
|  |  | 
|  | struct ResFile { | 
|  | ResFile() | 
|  | : fBytes(NULL), fIndexes(NULL), | 
|  | fKeys(NULL), fKeysLength(0), fKeysCount(0), | 
|  | fStrings(NULL), fStringIndexLimit(0), | 
|  | fChecksum(0) {} | 
|  | ~ResFile() { close(); } | 
|  |  | 
|  | void close(); | 
|  |  | 
|  | uint8_t *fBytes; | 
|  | const int32_t *fIndexes; | 
|  | const char *fKeys; | 
|  | int32_t fKeysLength; | 
|  | int32_t fKeysCount; | 
|  |  | 
|  | PseudoListResource *fStrings; | 
|  | int32_t fStringIndexLimit; | 
|  |  | 
|  | int32_t fChecksum; | 
|  | }; | 
|  |  | 
|  | struct SResource; | 
|  |  | 
|  | typedef struct KeyMapEntry { | 
|  | int32_t oldpos, newpos; | 
|  | } KeyMapEntry; | 
|  |  | 
|  | /* Resource bundle root table */ | 
|  | struct SRBRoot { | 
|  | SRBRoot(const UString *comment, UBool isPoolBundle, UErrorCode &errorCode); | 
|  | ~SRBRoot(); | 
|  |  | 
|  | void write(const char *outputDir, const char *outputPkg, | 
|  | char *writtenFilename, int writtenFilenameLen, UErrorCode &errorCode); | 
|  |  | 
|  | void setLocale(UChar *locale, UErrorCode &errorCode); | 
|  | int32_t addTag(const char *tag, UErrorCode &errorCode); | 
|  |  | 
|  | const char *getKeyString(int32_t key) const; | 
|  | const char *getKeyBytes(int32_t *pLength) const; | 
|  |  | 
|  | int32_t addKeyBytes(const char *keyBytes, int32_t length, UErrorCode &errorCode); | 
|  |  | 
|  | void compactKeys(UErrorCode &errorCode); | 
|  |  | 
|  | int32_t makeRes16(uint32_t resWord) const; | 
|  | int32_t mapKey(int32_t oldpos) const; | 
|  |  | 
|  | private: | 
|  | void compactStringsV2(UHashtable *stringSet, UErrorCode &errorCode); | 
|  |  | 
|  | public: | 
|  | // TODO: private | 
|  |  | 
|  | SResource *fRoot;  // Normally a TableResource. | 
|  | char *fLocale; | 
|  | int32_t fIndexLength; | 
|  | int32_t fMaxTableLength; | 
|  | UBool fNoFallback; /* see URES_ATT_NO_FALLBACK */ | 
|  | int8_t fStringsForm; /* default STRINGS_UTF16_V1 */ | 
|  | UBool fIsPoolBundle; | 
|  |  | 
|  | char *fKeys; | 
|  | KeyMapEntry *fKeyMap; | 
|  | int32_t fKeysBottom, fKeysTop; | 
|  | int32_t fKeysCapacity; | 
|  | int32_t fKeysCount; | 
|  | int32_t fLocalKeyLimit; /* key offset < limit fits into URES_TABLE */ | 
|  |  | 
|  | icu::UnicodeString f16BitUnits; | 
|  | int32_t f16BitStringsLength; | 
|  |  | 
|  | const ResFile *fUsePoolBundle; | 
|  | int32_t fPoolStringIndexLimit; | 
|  | int32_t fPoolStringIndex16Limit; | 
|  | int32_t fLocalStringIndexLimit; | 
|  | SRBRoot *fWritePoolBundle; | 
|  | }; | 
|  |  | 
|  | /* write a java resource file */ | 
|  | // TODO: C++ify | 
|  | void bundle_write_java(struct SRBRoot *bundle, const char *outputDir, const char* outputEnc, char *writtenFilename, | 
|  | int writtenFilenameLen, const char* packageName, const char* bundleName, UErrorCode *status); | 
|  |  | 
|  | /* write a xml resource file */ | 
|  | // TODO: C++ify | 
|  | void bundle_write_xml(struct SRBRoot *bundle, const char *outputDir,const char* outputEnc, const char* rbname, | 
|  | char *writtenFilename, int writtenFilenameLen, const char* language, const char* package, UErrorCode *status); | 
|  |  | 
|  | /* Various resource types */ | 
|  |  | 
|  | /* | 
|  | * Return a unique pointer to a dummy object, | 
|  | * for use in non-error cases when no resource is to be added to the bundle. | 
|  | * (NULL is used in error cases.) | 
|  | */ | 
|  | struct SResource* res_none(void); | 
|  |  | 
|  | class ArrayResource; | 
|  | class TableResource; | 
|  | class IntVectorResource; | 
|  |  | 
|  | TableResource *table_open(struct SRBRoot *bundle, const char *tag, const struct UString* comment, UErrorCode *status); | 
|  |  | 
|  | ArrayResource *array_open(struct SRBRoot *bundle, const char *tag, const struct UString* comment, UErrorCode *status); | 
|  |  | 
|  | struct SResource *string_open(struct SRBRoot *bundle, const char *tag, const UChar *value, int32_t len, const struct UString* comment, UErrorCode *status); | 
|  |  | 
|  | struct SResource *alias_open(struct SRBRoot *bundle, const char *tag, UChar *value, int32_t len, const struct UString* comment, UErrorCode *status); | 
|  |  | 
|  | IntVectorResource *intvector_open(struct SRBRoot *bundle, const char *tag,  const struct UString* comment, UErrorCode *status); | 
|  |  | 
|  | struct SResource *int_open(struct SRBRoot *bundle, const char *tag, int32_t value, const struct UString* comment, UErrorCode *status); | 
|  |  | 
|  | 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); | 
|  |  | 
|  | /* Resource place holder */ | 
|  |  | 
|  | struct SResource { | 
|  | SResource(); | 
|  | SResource(SRBRoot *bundle, const char *tag, int8_t type, const UString* comment, | 
|  | UErrorCode &errorCode); | 
|  | virtual ~SResource(); | 
|  |  | 
|  | UBool isTable() const { return fType == URES_TABLE; } | 
|  | UBool isString() const { return fType == URES_STRING; } | 
|  |  | 
|  | const char *getKeyString(const SRBRoot *bundle) const; | 
|  |  | 
|  | /** | 
|  | * Preflights strings. | 
|  | * Finds duplicates and counts the total number of string code units | 
|  | * so that they can be written first to the 16-bit array, | 
|  | * for minimal string and container storage. | 
|  | * | 
|  | * We walk the final parse tree, rather than collecting this information while building it, | 
|  | * so that we need not deal with changes to the parse tree (especially removing resources). | 
|  | */ | 
|  | void preflightStrings(SRBRoot *bundle, UHashtable *stringSet, UErrorCode &errorCode); | 
|  | virtual void handlePreflightStrings(SRBRoot *bundle, UHashtable *stringSet, UErrorCode &errorCode); | 
|  |  | 
|  | /** | 
|  | * Writes resource values into f16BitUnits | 
|  | * and determines the resource item word, if possible. | 
|  | */ | 
|  | void write16(SRBRoot *bundle); | 
|  | virtual void handleWrite16(SRBRoot *bundle); | 
|  |  | 
|  | /** | 
|  | * Calculates ("preflights") and advances the *byteOffset | 
|  | * by the size of the resource's data in the binary file and | 
|  | * determines the resource item word. | 
|  | * | 
|  | * Most handlePreWrite() functions may add any number of bytes, but preWrite() | 
|  | * will always pad it to a multiple of 4. | 
|  | * The resource item type may be a related subtype of the fType. | 
|  | * | 
|  | * The preWrite() and write() functions start and end at the same | 
|  | * byteOffset values. | 
|  | * Prewriting allows bundle.write() to determine the root resource item word, | 
|  | * before actually writing the bundle contents to the file, | 
|  | * which is necessary because the root item is stored at the beginning. | 
|  | */ | 
|  | void preWrite(uint32_t *byteOffset); | 
|  | virtual void handlePreWrite(uint32_t *byteOffset); | 
|  |  | 
|  | /** | 
|  | * Writes the resource's data to mem and updates the byteOffset | 
|  | * in parallel. | 
|  | */ | 
|  | void write(UNewDataMemory *mem, uint32_t *byteOffset); | 
|  | virtual void handleWrite(UNewDataMemory *mem, uint32_t *byteOffset); | 
|  |  | 
|  | /** | 
|  | * Applies the given filter with the given base path to this resource. | 
|  | * Removes child resources rejected by the filter recursively. | 
|  | * | 
|  | * @param bundle Needed in order to access the key for this and child resources. | 
|  | */ | 
|  | virtual void applyFilter(const PathFilter& filter, ResKeyPath& path, const SRBRoot* bundle); | 
|  |  | 
|  | /** | 
|  | * Calls the given function for every key ID present in this tree. | 
|  | */ | 
|  | virtual void collectKeys(std::function<void(int32_t)> collector) const; | 
|  |  | 
|  | int8_t   fType;     /* nominal type: fRes (when != 0xffffffff) may use subtype */ | 
|  | UBool    fWritten;  /* res_write() can exit early */ | 
|  | uint32_t fRes;      /* resource item word; RES_BOGUS=0xffffffff if not known yet */ | 
|  | int32_t  fRes16;    /* Res16 version of fRes for Table, Table16, Array16; -1 if it does not fit. */ | 
|  | int32_t  fKey;      /* Index into bundle->fKeys; -1 if no key. */ | 
|  | int32_t  fKey16;    /* Key16 version of fKey for Table & Table16; -1 if no key or it does not fit. */ | 
|  | int      line;      /* used internally to report duplicate keys in tables */ | 
|  | SResource *fNext;   /* This is for internal chaining while building */ | 
|  | struct UString fComment; | 
|  | }; | 
|  |  | 
|  | class ContainerResource : public SResource { | 
|  | public: | 
|  | ContainerResource(SRBRoot *bundle, const char *tag, int8_t type, | 
|  | const UString* comment, UErrorCode &errorCode) | 
|  | : SResource(bundle, tag, type, comment, errorCode), | 
|  | fCount(0), fFirst(NULL) {} | 
|  | virtual ~ContainerResource(); | 
|  |  | 
|  | void handlePreflightStrings(SRBRoot *bundle, UHashtable *stringSet, UErrorCode &errorCode) override; | 
|  |  | 
|  | void collectKeys(std::function<void(int32_t)> collector) const override; | 
|  |  | 
|  | protected: | 
|  | void writeAllRes16(SRBRoot *bundle); | 
|  | void preWriteAllRes(uint32_t *byteOffset); | 
|  | void writeAllRes(UNewDataMemory *mem, uint32_t *byteOffset); | 
|  | void writeAllRes32(UNewDataMemory *mem, uint32_t *byteOffset); | 
|  |  | 
|  | public: | 
|  | // TODO: private with getter? | 
|  | uint32_t fCount; | 
|  | SResource *fFirst; | 
|  | }; | 
|  |  | 
|  | class TableResource : public ContainerResource { | 
|  | public: | 
|  | TableResource(SRBRoot *bundle, const char *tag, | 
|  | const UString* comment, UErrorCode &errorCode) | 
|  | : ContainerResource(bundle, tag, URES_TABLE, comment, errorCode), | 
|  | fTableType(URES_TABLE), fRoot(bundle) {} | 
|  | virtual ~TableResource(); | 
|  |  | 
|  | void add(SResource *res, int linenumber, UErrorCode &errorCode); | 
|  |  | 
|  | void handleWrite16(SRBRoot *bundle) override; | 
|  | void handlePreWrite(uint32_t *byteOffset) override; | 
|  | void handleWrite(UNewDataMemory *mem, uint32_t *byteOffset) override; | 
|  |  | 
|  | void applyFilter(const PathFilter& filter, ResKeyPath& path, const SRBRoot* bundle) override; | 
|  |  | 
|  | int8_t fTableType;  // determined by table_write16() for table_preWrite() & table_write() | 
|  | SRBRoot *fRoot; | 
|  | }; | 
|  |  | 
|  | class ArrayResource : public ContainerResource { | 
|  | public: | 
|  | ArrayResource(SRBRoot *bundle, const char *tag, | 
|  | const UString* comment, UErrorCode &errorCode) | 
|  | : ContainerResource(bundle, tag, URES_ARRAY, comment, errorCode), | 
|  | fLast(NULL) {} | 
|  | virtual ~ArrayResource(); | 
|  |  | 
|  | void add(SResource *res); | 
|  |  | 
|  | virtual void handleWrite16(SRBRoot *bundle); | 
|  | virtual void handlePreWrite(uint32_t *byteOffset); | 
|  | virtual void handleWrite(UNewDataMemory *mem, uint32_t *byteOffset); | 
|  |  | 
|  | SResource *fLast; | 
|  | }; | 
|  |  | 
|  | /** | 
|  | * List of resources for a pool bundle. | 
|  | * Writes an empty table resource, rather than a container structure. | 
|  | */ | 
|  | class PseudoListResource : public ContainerResource { | 
|  | public: | 
|  | PseudoListResource(SRBRoot *bundle, UErrorCode &errorCode) | 
|  | : ContainerResource(bundle, NULL, URES_TABLE, NULL, errorCode) {} | 
|  | virtual ~PseudoListResource(); | 
|  |  | 
|  | void add(SResource *res); | 
|  |  | 
|  | virtual void handleWrite16(SRBRoot *bundle); | 
|  | }; | 
|  |  | 
|  | class StringBaseResource : public SResource { | 
|  | public: | 
|  | StringBaseResource(SRBRoot *bundle, const char *tag, int8_t type, | 
|  | const UChar *value, int32_t len, | 
|  | const UString* comment, UErrorCode &errorCode); | 
|  | StringBaseResource(SRBRoot *bundle, int8_t type, | 
|  | const icu::UnicodeString &value, UErrorCode &errorCode); | 
|  | StringBaseResource(int8_t type, const UChar *value, int32_t len, UErrorCode &errorCode); | 
|  | virtual ~StringBaseResource(); | 
|  |  | 
|  | const UChar *getBuffer() const { return icu::toUCharPtr(fString.getBuffer()); } | 
|  | int32_t length() const { return fString.length(); } | 
|  |  | 
|  | virtual void handlePreWrite(uint32_t *byteOffset); | 
|  | virtual void handleWrite(UNewDataMemory *mem, uint32_t *byteOffset); | 
|  |  | 
|  | // TODO: private with getter? | 
|  | icu::UnicodeString fString; | 
|  | }; | 
|  |  | 
|  | class StringResource : public StringBaseResource { | 
|  | public: | 
|  | StringResource(SRBRoot *bundle, const char *tag, const UChar *value, int32_t len, | 
|  | const UString* comment, UErrorCode &errorCode) | 
|  | : StringBaseResource(bundle, tag, URES_STRING, value, len, comment, errorCode), | 
|  | fSame(NULL), fSuffixOffset(0), | 
|  | fNumCopies(0), fNumUnitsSaved(0), fNumCharsForLength(0) {} | 
|  | StringResource(SRBRoot *bundle, const icu::UnicodeString &value, UErrorCode &errorCode) | 
|  | : StringBaseResource(bundle, URES_STRING, value, errorCode), | 
|  | fSame(NULL), fSuffixOffset(0), | 
|  | fNumCopies(0), fNumUnitsSaved(0), fNumCharsForLength(0) {} | 
|  | StringResource(int32_t poolStringIndex, int8_t numCharsForLength, | 
|  | const UChar *value, int32_t length, | 
|  | UErrorCode &errorCode) | 
|  | : StringBaseResource(URES_STRING, value, length, errorCode), | 
|  | fSame(NULL), fSuffixOffset(0), | 
|  | fNumCopies(0), fNumUnitsSaved(0), fNumCharsForLength(numCharsForLength) { | 
|  | // v3 pool string encoded as string-v2 with low offset | 
|  | fRes = URES_MAKE_RESOURCE(URES_STRING_V2, poolStringIndex); | 
|  | fWritten = true; | 
|  | } | 
|  | virtual ~StringResource(); | 
|  |  | 
|  | int32_t get16BitStringsLength() const { | 
|  | return fNumCharsForLength + length() + 1;  // +1 for the NUL | 
|  | } | 
|  |  | 
|  | virtual void handlePreflightStrings(SRBRoot *bundle, UHashtable *stringSet, UErrorCode &errorCode); | 
|  | virtual void handleWrite16(SRBRoot *bundle); | 
|  |  | 
|  | void writeUTF16v2(int32_t base, icu::UnicodeString &dest); | 
|  |  | 
|  | StringResource *fSame;  // used for duplicates | 
|  | int32_t fSuffixOffset;  // this string is a suffix of fSame at this offset | 
|  | int32_t fNumCopies;     // number of equal strings represented by one stringSet element | 
|  | int32_t fNumUnitsSaved;  // from not writing duplicates and suffixes | 
|  | int8_t fNumCharsForLength; | 
|  | }; | 
|  |  | 
|  | class AliasResource : public StringBaseResource { | 
|  | public: | 
|  | AliasResource(SRBRoot *bundle, const char *tag, const UChar *value, int32_t len, | 
|  | const UString* comment, UErrorCode &errorCode) | 
|  | : StringBaseResource(bundle, tag, URES_ALIAS, value, len, comment, errorCode) {} | 
|  | virtual ~AliasResource(); | 
|  | }; | 
|  |  | 
|  | class IntResource : public SResource { | 
|  | public: | 
|  | IntResource(SRBRoot *bundle, const char *tag, int32_t value, | 
|  | const UString* comment, UErrorCode &errorCode); | 
|  | virtual ~IntResource(); | 
|  |  | 
|  | // TODO: private with getter? | 
|  | int32_t fValue; | 
|  | }; | 
|  |  | 
|  | class IntVectorResource : public SResource { | 
|  | public: | 
|  | IntVectorResource(SRBRoot *bundle, const char *tag, | 
|  | const UString* comment, UErrorCode &errorCode); | 
|  | virtual ~IntVectorResource(); | 
|  |  | 
|  | void add(int32_t value, UErrorCode &errorCode); | 
|  |  | 
|  | virtual void handlePreWrite(uint32_t *byteOffset); | 
|  | virtual void handleWrite(UNewDataMemory *mem, uint32_t *byteOffset); | 
|  |  | 
|  | // TODO: UVector32 | 
|  | uint32_t fCount; | 
|  | uint32_t *fArray; | 
|  | }; | 
|  |  | 
|  | class BinaryResource : public SResource { | 
|  | public: | 
|  | BinaryResource(SRBRoot *bundle, const char *tag, | 
|  | uint32_t length, uint8_t *data, const char* fileName, | 
|  | const UString* comment, UErrorCode &errorCode); | 
|  | virtual ~BinaryResource(); | 
|  |  | 
|  | virtual void handlePreWrite(uint32_t *byteOffset); | 
|  | virtual void handleWrite(UNewDataMemory *mem, uint32_t *byteOffset); | 
|  |  | 
|  | // TODO: CharString? | 
|  | uint32_t fLength; | 
|  | uint8_t *fData; | 
|  | // TODO: CharString | 
|  | char* fFileName;  // file name for binary or import binary tags if any | 
|  | }; | 
|  |  | 
|  | // TODO: use LocalPointer or delete | 
|  | void res_close(struct SResource *res); | 
|  |  | 
|  | void setIncludeCopyright(UBool val); | 
|  | UBool getIncludeCopyright(void); | 
|  |  | 
|  | void setFormatVersion(int32_t formatVersion); | 
|  |  | 
|  | int32_t getFormatVersion(); | 
|  |  | 
|  | void setUsePoolBundle(UBool use); | 
|  |  | 
|  | /* in wrtxml.cpp */ | 
|  | uint32_t computeCRC(const char *ptr, uint32_t len, uint32_t lastcrc); | 
|  |  | 
|  | U_CDECL_END | 
|  | #endif /* #ifndef RESLIST_H */ |