]> git.saurik.com Git - apple/icu.git/blobdiff - icuSources/tools/genrb/reslist.h
ICU-66108.tar.gz
[apple/icu.git] / icuSources / tools / genrb / reslist.h
index 34e35fd27c4612cf478cdbb7c8d43e8bd362f409..07874fdbaa8785d7cbacc5df3af2f5e78e2cf9cd 100644 (file)
@@ -1,7 +1,9 @@
+// © 2016 and later: Unicode, Inc. and others.
+// License & terms of use: http://www.unicode.org/copyright.html
 /*
 *******************************************************************************
 *
 /*
 *******************************************************************************
 *
-*   Copyright (C) 2000-2003, International Business Machines
+*   Copyright (C) 2000-2015, International Business Machines
 *   Corporation and others.  All Rights Reserved.
 *
 *******************************************************************************
 *   Corporation and others.  All Rights Reserved.
 *
 *******************************************************************************
 #define KEY_SPACE_SIZE 65536
 #define RESLIST_MAX_INT_VECTOR 2048
 
 #define KEY_SPACE_SIZE 65536
 #define RESLIST_MAX_INT_VECTOR 2048
 
+#include <functional>
+
 #include "unicode/utypes.h"
 #include "unicode/utypes.h"
+#include "unicode/unistr.h"
 #include "unicode/ures.h"
 #include "unicode/ustring.h"
 #include "unicode/ures.h"
 #include "unicode/ustring.h"
-#include "uresdata.h"
 #include "cmemory.h"
 #include "cstring.h"
 #include "cmemory.h"
 #include "cstring.h"
+#include "uhash.h"
 #include "unewdata.h"
 #include "unewdata.h"
+#include "uresdata.h"
 #include "ustr.h"
 
 U_CDECL_BEGIN
 
 #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 {
 /* 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;
   char *fLocale;
-  int32_t fKeyPoint;
+  int32_t fIndexLength;
+  int32_t fMaxTableLength;
+  UBool fNoFallback; /* see URES_ATT_NO_FALLBACK */
+  int8_t fStringsForm; /* default STRINGS_UTF16_V1 */
+  UBool fIsPoolBundle;
+
   char *fKeys;
   char *fKeys;
+  KeyMapEntry *fKeyMap;
+  int32_t fKeysBottom, fKeysTop;
   int32_t fKeysCapacity;
   int32_t fKeysCapacity;
-  int32_t fCount;
-  struct SResource *fRoot;
-  int32_t fMaxTableLength;
-};
+  int32_t fKeysCount;
+  int32_t fLocalKeyLimit; /* key offset < limit fits into URES_TABLE */
+
+  icu::UnicodeString f16BitUnits;
+  int32_t f16BitStringsLength;
 
 
-struct SRBRoot *bundle_open(const struct UString* comment, UErrorCode *status);
-void bundle_write(struct SRBRoot *bundle, const char *outputDir, const char *outputPkg, char *writtenFilename, int writtenFilenameLen, UErrorCode *status);
+  const ResFile *fUsePoolBundle;
+  int32_t fPoolStringIndexLimit;
+  int32_t fPoolStringIndex16Limit;
+  int32_t fLocalStringIndexLimit;
+  SRBRoot *fWritePoolBundle;
+};
 
 /* write a java resource file */
 
 /* 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 */
 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 */
-/* commented by Jing*/
-/* void bundle_write_xml(struct SRBRoot *bundle, const char *outputDir,const char* outputEnc, 
-                  char *writtenFilename, int writtenFilenameLen,UErrorCode *status); */
-
-/* added by Jing*/
+// 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);
 
 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);
 
-void bundle_close(struct SRBRoot *bundle, UErrorCode *status);
-void bundle_setlocale(struct SRBRoot *bundle, UChar *locale, UErrorCode *status);
-int32_t bundle_addtag(struct SRBRoot *bundle, const char *tag, UErrorCode *status);
-
 /* Various resource types */
 /* Various resource types */
-struct SResource* res_open(const struct UString* comment, UErrorCode* status);
 
 
-struct SResTable {
-    uint32_t fCount;
-    uint32_t fChildrenSize;
-    struct SResource *fFirst;
-    struct SRBRoot *fRoot;
+/*
+ * 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;
 };
 
 };
 
-struct SResource* table_open(struct SRBRoot *bundle, char *tag, const struct UString* comment, UErrorCode *status);
-void table_close(struct SResource *table, UErrorCode *status);
-void table_add(struct SResource *table, struct SResource *res, int linenumber, UErrorCode *status);
+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;
 
 
-struct SResArray {
+    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;
     uint32_t fCount;
-    uint32_t fChildrenSize;
-    struct SResource *fFirst;
-    struct SResource *fLast;
+    SResource *fFirst;
 };
 
 };
 
-struct SResource* array_open(struct SRBRoot *bundle, char *tag, const struct UString* comment, UErrorCode *status);
-void array_close(struct SResource *array, UErrorCode *status);
-void array_add(struct SResource *array, struct SResource *res, UErrorCode *status);
+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();
 
 
-struct SResString {
-    uint32_t fLength;
-    UChar *fChars;
+    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;
 };
 
 };
 
-struct SResource *string_open(struct SRBRoot *bundle, char *tag, const UChar *value, int32_t len, const struct UString* comment, UErrorCode *status);
-void string_close(struct SResource *string, UErrorCode *status);
+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();
 
 
-struct SResource *alias_open(struct SRBRoot *bundle, char *tag, UChar *value, int32_t len, const struct UString* comment, UErrorCode *status);
-void alias_close(struct SResource *string, UErrorCode *status);
+    void add(SResource *res);
 
 
-struct SResIntVector {
-    uint32_t fCount;
-    uint32_t *fArray;
+    virtual void handleWrite16(SRBRoot *bundle);
+    virtual void handlePreWrite(uint32_t *byteOffset);
+    virtual void handleWrite(UNewDataMemory *mem, uint32_t *byteOffset);
+
+    SResource *fLast;
 };
 
 };
 
-struct SResource* intvector_open(struct SRBRoot *bundle, char *tag,  const struct UString* comment, UErrorCode *status);
-void intvector_close(struct SResource *intvector, UErrorCode *status);
-void intvector_add(struct SResource *intvector, int32_t value, UErrorCode *status);
+/**
+ * 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();
 
 
-struct SResInt {
-    uint32_t fValue;
+    void add(SResource *res);
+
+    virtual void handleWrite16(SRBRoot *bundle);
 };
 
 };
 
-struct SResource *int_open(struct SRBRoot *bundle, char *tag, int32_t value, const struct UString* comment, UErrorCode *status);
-void int_close(struct SResource *intres, UErrorCode *status);
+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();
 
 
-struct SResBinary {
-    uint32_t fLength;
-    uint8_t *fData;
-    char* fFileName; /* file name for binary or import binary tags if any */
+    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;
 };
 
 };
 
-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);
-void bin_close(struct SResource *binres, UErrorCode *status);
+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();
 
 
-/* Resource place holder */
+    int32_t get16BitStringsLength() const {
+        return fNumCharsForLength + length() + 1;  // +1 for the NUL
+    }
 
 
-struct SResource {
-    UResType fType;
-    int32_t  fKey;
-    uint32_t fSize; /* Size in bytes outside the header part */
-    int      line;  /* used internally to report duplicate keys in tables */
-    struct SResource *fNext; /*This is for internal chaining while building*/
-    struct UString *fComment;
-    union {
-        struct SResTable fTable;
-        struct SResArray fArray;
-        struct SResString fString;
-        struct SResIntVector fIntVector;
-        struct SResInt fIntValue;
-        struct SResBinary fBinaryValue;
-    } u;
+    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
 };
 
 };
 
-void res_close(struct SResource *res, UErrorCode *status);
+// TODO: use LocalPointer or delete
+void res_close(struct SResource *res);
+
 void setIncludeCopyright(UBool val);
 UBool getIncludeCopyright(void);
 
 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 */
 U_CDECL_END
 #endif /* #ifndef RESLIST_H */