Home | History | Annotate | Download | only in genrb
      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 {
     40     ResFile()
     41             : fBytes(NULL), fIndexes(NULL),
     42               fKeys(NULL), fKeysLength(0), fKeysCount(0),
     43               fStrings(NULL), fStringIndexLimit(0),
     44               fChecksum(0) {}
     45     ~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 
    164     UBool isTable() const { return fType == URES_TABLE; }
    165     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:
    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:
    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:
    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:
    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 
    305     const UChar *getBuffer() const { return fString.getBuffer(); }
    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:
    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) {}
    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) {}
    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 
    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:
    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