Home | History | Annotate | Download | only in genrb
      1 //  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 {
     42     ResFile()
     43             : fBytes(NULL), fIndexes(NULL),
     44               fKeys(NULL), fKeysLength(0), fKeysCount(0),
     45               fStrings(NULL), fStringIndexLimit(0),
     46               fChecksum(0) {}
     47     ~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 
    166     UBool isTable() const { return fType == URES_TABLE; }
    167     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:
    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:
    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:
    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:
    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 
    307     const UChar *getBuffer() const { return icu::toUCharPtr(fString.getBuffer()); }
    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:
    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) {}
    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) {}
    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 
    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:
    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