| // © 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_INT_VECTOR_INIT_SIZE 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 |
| size_t fCount; |
| size_t fSize; |
| 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 */ |