• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 {
ResFileResFile42     ResFile()
43             : fBytes(NULL), fIndexes(NULL),
44               fKeys(NULL), fKeysLength(0), fKeysCount(0),
45               fStrings(NULL), fStringIndexLimit(0),
46               fChecksum(0) {}
~ResFileResFile47     ~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 
isTableSResource166     UBool isTable() const { return fType == URES_TABLE; }
isStringSResource167     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:
ContainerResource(SRBRoot * bundle,const char * tag,int8_t type,const UString * comment,UErrorCode & errorCode)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:
TableResource(SRBRoot * bundle,const char * tag,const UString * comment,UErrorCode & errorCode)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:
ArrayResource(SRBRoot * bundle,const char * tag,const UString * comment,UErrorCode & errorCode)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:
PseudoListResource(SRBRoot * bundle,UErrorCode & errorCode)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 
getBuffer()307     const UChar *getBuffer() const { return icu::toUCharPtr(fString.getBuffer()); }
length()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:
StringResource(SRBRoot * bundle,const char * tag,const UChar * value,int32_t len,const UString * comment,UErrorCode & errorCode)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) {}
StringResource(SRBRoot * bundle,const icu::UnicodeString & value,UErrorCode & errorCode)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) {}
StringResource(int32_t poolStringIndex,int8_t numCharsForLength,const UChar * value,int32_t length,UErrorCode & errorCode)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 
get16BitStringsLength()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:
AliasResource(SRBRoot * bundle,const char * tag,const UChar * value,int32_t len,const UString * comment,UErrorCode & errorCode)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