1 // © 2016 and later: Unicode, Inc. and others.
2 // License & terms of use: http://www.unicode.org/copyright.html
4 *******************************************************************************
6 * Copyright (C) 2000-2015, International Business Machines
7 * Corporation and others. All Rights Reserved.
9 *******************************************************************************
13 * Modification History:
15 * Date Name Description
16 * 02/21/00 weiv Creation.
17 *******************************************************************************
23 #define KEY_SPACE_SIZE 65536
24 #define RESLIST_MAX_INT_VECTOR 2048
28 #include "unicode/utypes.h"
29 #include "unicode/unistr.h"
30 #include "unicode/ures.h"
31 #include "unicode/ustring.h"
42 class PseudoListResource
;
47 : fBytes(NULL
), fIndexes(NULL
),
48 fKeys(NULL
), fKeysLength(0), fKeysCount(0),
49 fStrings(NULL
), fStringIndexLimit(0),
51 ~ResFile() { close(); }
56 const int32_t *fIndexes
;
61 PseudoListResource
*fStrings
;
62 int32_t fStringIndexLimit
;
69 typedef struct KeyMapEntry
{
70 int32_t oldpos
, newpos
;
73 /* Resource bundle root table */
75 SRBRoot(const UString
*comment
, UBool isPoolBundle
, UErrorCode
&errorCode
);
78 void write(const char *outputDir
, const char *outputPkg
,
79 char *writtenFilename
, int writtenFilenameLen
, UErrorCode
&errorCode
);
81 void setLocale(UChar
*locale
, UErrorCode
&errorCode
);
82 int32_t addTag(const char *tag
, UErrorCode
&errorCode
);
84 const char *getKeyString(int32_t key
) const;
85 const char *getKeyBytes(int32_t *pLength
) const;
87 int32_t addKeyBytes(const char *keyBytes
, int32_t length
, UErrorCode
&errorCode
);
89 void compactKeys(UErrorCode
&errorCode
);
91 int32_t makeRes16(uint32_t resWord
) const;
92 int32_t mapKey(int32_t oldpos
) const;
95 void compactStringsV2(UHashtable
*stringSet
, UErrorCode
&errorCode
);
100 SResource
*fRoot
; // Normally a TableResource.
102 int32_t fIndexLength
;
103 int32_t fMaxTableLength
;
104 UBool fNoFallback
; /* see URES_ATT_NO_FALLBACK */
105 int8_t fStringsForm
; /* default STRINGS_UTF16_V1 */
109 KeyMapEntry
*fKeyMap
;
110 int32_t fKeysBottom
, fKeysTop
;
111 int32_t fKeysCapacity
;
113 int32_t fLocalKeyLimit
; /* key offset < limit fits into URES_TABLE */
115 icu::UnicodeString f16BitUnits
;
116 int32_t f16BitStringsLength
;
118 const ResFile
*fUsePoolBundle
;
119 int32_t fPoolStringIndexLimit
;
120 int32_t fPoolStringIndex16Limit
;
121 int32_t fLocalStringIndexLimit
;
122 SRBRoot
*fWritePoolBundle
;
125 /* write a java resource file */
127 void bundle_write_java(struct SRBRoot
*bundle
, const char *outputDir
, const char* outputEnc
, char *writtenFilename
,
128 int writtenFilenameLen
, const char* packageName
, const char* bundleName
, UErrorCode
*status
);
130 /* write a xml resource file */
132 void bundle_write_xml(struct SRBRoot
*bundle
, const char *outputDir
,const char* outputEnc
, const char* rbname
,
133 char *writtenFilename
, int writtenFilenameLen
, const char* language
, const char* package
, UErrorCode
*status
);
135 /* Various resource types */
138 * Return a unique pointer to a dummy object,
139 * for use in non-error cases when no resource is to be added to the bundle.
140 * (NULL is used in error cases.)
142 struct SResource
* res_none(void);
146 class IntVectorResource
;
148 TableResource
*table_open(struct SRBRoot
*bundle
, const char *tag
, const struct UString
* comment
, UErrorCode
*status
);
150 ArrayResource
*array_open(struct SRBRoot
*bundle
, const char *tag
, const struct UString
* comment
, UErrorCode
*status
);
152 struct SResource
*string_open(struct SRBRoot
*bundle
, const char *tag
, const UChar
*value
, int32_t len
, const struct UString
* comment
, UErrorCode
*status
);
154 struct SResource
*alias_open(struct SRBRoot
*bundle
, const char *tag
, UChar
*value
, int32_t len
, const struct UString
* comment
, UErrorCode
*status
);
156 IntVectorResource
*intvector_open(struct SRBRoot
*bundle
, const char *tag
, const struct UString
* comment
, UErrorCode
*status
);
158 struct SResource
*int_open(struct SRBRoot
*bundle
, const char *tag
, int32_t value
, const struct UString
* comment
, UErrorCode
*status
);
160 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
);
162 /* Resource place holder */
166 SResource(SRBRoot
*bundle
, const char *tag
, int8_t type
, const UString
* comment
,
167 UErrorCode
&errorCode
);
168 virtual ~SResource();
170 UBool
isTable() const { return fType
== URES_TABLE
; }
171 UBool
isString() const { return fType
== URES_STRING
; }
173 const char *getKeyString(const SRBRoot
*bundle
) const;
176 * Preflights strings.
177 * Finds duplicates and counts the total number of string code units
178 * so that they can be written first to the 16-bit array,
179 * for minimal string and container storage.
181 * We walk the final parse tree, rather than collecting this information while building it,
182 * so that we need not deal with changes to the parse tree (especially removing resources).
184 void preflightStrings(SRBRoot
*bundle
, UHashtable
*stringSet
, UErrorCode
&errorCode
);
185 virtual void handlePreflightStrings(SRBRoot
*bundle
, UHashtable
*stringSet
, UErrorCode
&errorCode
);
188 * Writes resource values into f16BitUnits
189 * and determines the resource item word, if possible.
191 void write16(SRBRoot
*bundle
);
192 virtual void handleWrite16(SRBRoot
*bundle
);
195 * Calculates ("preflights") and advances the *byteOffset
196 * by the size of the resource's data in the binary file and
197 * determines the resource item word.
199 * Most handlePreWrite() functions may add any number of bytes, but preWrite()
200 * will always pad it to a multiple of 4.
201 * The resource item type may be a related subtype of the fType.
203 * The preWrite() and write() functions start and end at the same
205 * Prewriting allows bundle.write() to determine the root resource item word,
206 * before actually writing the bundle contents to the file,
207 * which is necessary because the root item is stored at the beginning.
209 void preWrite(uint32_t *byteOffset
);
210 virtual void handlePreWrite(uint32_t *byteOffset
);
213 * Writes the resource's data to mem and updates the byteOffset
216 void write(UNewDataMemory
*mem
, uint32_t *byteOffset
);
217 virtual void handleWrite(UNewDataMemory
*mem
, uint32_t *byteOffset
);
220 * Applies the given filter with the given base path to this resource.
221 * Removes child resources rejected by the filter recursively.
223 * @param bundle Needed in order to access the key for this and child resources.
225 virtual void applyFilter(const PathFilter
& filter
, ResKeyPath
& path
, const SRBRoot
* bundle
);
228 * Calls the given function for every key ID present in this tree.
230 virtual void collectKeys(std::function
<void(int32_t)> collector
) const;
232 int8_t fType
; /* nominal type: fRes (when != 0xffffffff) may use subtype */
233 UBool fWritten
; /* res_write() can exit early */
234 uint32_t fRes
; /* resource item word; RES_BOGUS=0xffffffff if not known yet */
235 int32_t fRes16
; /* Res16 version of fRes for Table, Table16, Array16; -1 if it does not fit. */
236 int32_t fKey
; /* Index into bundle->fKeys; -1 if no key. */
237 int32_t fKey16
; /* Key16 version of fKey for Table & Table16; -1 if no key or it does not fit. */
238 int line
; /* used internally to report duplicate keys in tables */
239 SResource
*fNext
; /* This is for internal chaining while building */
240 struct UString fComment
;
243 class ContainerResource
: public SResource
{
245 ContainerResource(SRBRoot
*bundle
, const char *tag
, int8_t type
,
246 const UString
* comment
, UErrorCode
&errorCode
)
247 : SResource(bundle
, tag
, type
, comment
, errorCode
),
248 fCount(0), fFirst(NULL
) {}
249 virtual ~ContainerResource();
251 void handlePreflightStrings(SRBRoot
*bundle
, UHashtable
*stringSet
, UErrorCode
&errorCode
) override
;
253 void collectKeys(std::function
<void(int32_t)> collector
) const override
;
256 void writeAllRes16(SRBRoot
*bundle
);
257 void preWriteAllRes(uint32_t *byteOffset
);
258 void writeAllRes(UNewDataMemory
*mem
, uint32_t *byteOffset
);
259 void writeAllRes32(UNewDataMemory
*mem
, uint32_t *byteOffset
);
262 // TODO: private with getter?
267 class TableResource
: public ContainerResource
{
269 TableResource(SRBRoot
*bundle
, const char *tag
,
270 const UString
* comment
, UErrorCode
&errorCode
)
271 : ContainerResource(bundle
, tag
, URES_TABLE
, comment
, errorCode
),
272 fTableType(URES_TABLE
), fRoot(bundle
) {}
273 virtual ~TableResource();
275 void add(SResource
*res
, int linenumber
, UErrorCode
&errorCode
);
277 void handleWrite16(SRBRoot
*bundle
) override
;
278 void handlePreWrite(uint32_t *byteOffset
) override
;
279 void handleWrite(UNewDataMemory
*mem
, uint32_t *byteOffset
) override
;
281 void applyFilter(const PathFilter
& filter
, ResKeyPath
& path
, const SRBRoot
* bundle
) override
;
283 int8_t fTableType
; // determined by table_write16() for table_preWrite() & table_write()
287 class ArrayResource
: public ContainerResource
{
289 ArrayResource(SRBRoot
*bundle
, const char *tag
,
290 const UString
* comment
, UErrorCode
&errorCode
)
291 : ContainerResource(bundle
, tag
, URES_ARRAY
, comment
, errorCode
),
293 virtual ~ArrayResource();
295 void add(SResource
*res
);
297 virtual void handleWrite16(SRBRoot
*bundle
);
298 virtual void handlePreWrite(uint32_t *byteOffset
);
299 virtual void handleWrite(UNewDataMemory
*mem
, uint32_t *byteOffset
);
305 * List of resources for a pool bundle.
306 * Writes an empty table resource, rather than a container structure.
308 class PseudoListResource
: public ContainerResource
{
310 PseudoListResource(SRBRoot
*bundle
, UErrorCode
&errorCode
)
311 : ContainerResource(bundle
, NULL
, URES_TABLE
, NULL
, errorCode
) {}
312 virtual ~PseudoListResource();
314 void add(SResource
*res
);
316 virtual void handleWrite16(SRBRoot
*bundle
);
319 class StringBaseResource
: public SResource
{
321 StringBaseResource(SRBRoot
*bundle
, const char *tag
, int8_t type
,
322 const UChar
*value
, int32_t len
,
323 const UString
* comment
, UErrorCode
&errorCode
);
324 StringBaseResource(SRBRoot
*bundle
, int8_t type
,
325 const icu::UnicodeString
&value
, UErrorCode
&errorCode
);
326 StringBaseResource(int8_t type
, const UChar
*value
, int32_t len
, UErrorCode
&errorCode
);
327 virtual ~StringBaseResource();
329 const UChar
*getBuffer() const { return icu::toUCharPtr(fString
.getBuffer()); }
330 int32_t length() const { return fString
.length(); }
332 virtual void handlePreWrite(uint32_t *byteOffset
);
333 virtual void handleWrite(UNewDataMemory
*mem
, uint32_t *byteOffset
);
335 // TODO: private with getter?
336 icu::UnicodeString fString
;
339 class StringResource
: public StringBaseResource
{
341 StringResource(SRBRoot
*bundle
, const char *tag
, const UChar
*value
, int32_t len
,
342 const UString
* comment
, UErrorCode
&errorCode
)
343 : StringBaseResource(bundle
, tag
, URES_STRING
, value
, len
, comment
, errorCode
),
344 fSame(NULL
), fSuffixOffset(0),
345 fNumCopies(0), fNumUnitsSaved(0), fNumCharsForLength(0) {}
346 StringResource(SRBRoot
*bundle
, const icu::UnicodeString
&value
, UErrorCode
&errorCode
)
347 : StringBaseResource(bundle
, URES_STRING
, value
, errorCode
),
348 fSame(NULL
), fSuffixOffset(0),
349 fNumCopies(0), fNumUnitsSaved(0), fNumCharsForLength(0) {}
350 StringResource(int32_t poolStringIndex
, int8_t numCharsForLength
,
351 const UChar
*value
, int32_t length
,
352 UErrorCode
&errorCode
)
353 : StringBaseResource(URES_STRING
, value
, length
, errorCode
),
354 fSame(NULL
), fSuffixOffset(0),
355 fNumCopies(0), fNumUnitsSaved(0), fNumCharsForLength(numCharsForLength
) {
356 // v3 pool string encoded as string-v2 with low offset
357 fRes
= URES_MAKE_RESOURCE(URES_STRING_V2
, poolStringIndex
);
360 virtual ~StringResource();
362 int32_t get16BitStringsLength() const {
363 return fNumCharsForLength
+ length() + 1; // +1 for the NUL
366 virtual void handlePreflightStrings(SRBRoot
*bundle
, UHashtable
*stringSet
, UErrorCode
&errorCode
);
367 virtual void handleWrite16(SRBRoot
*bundle
);
369 void writeUTF16v2(int32_t base
, icu::UnicodeString
&dest
);
371 StringResource
*fSame
; // used for duplicates
372 int32_t fSuffixOffset
; // this string is a suffix of fSame at this offset
373 int32_t fNumCopies
; // number of equal strings represented by one stringSet element
374 int32_t fNumUnitsSaved
; // from not writing duplicates and suffixes
375 int8_t fNumCharsForLength
;
378 class AliasResource
: public StringBaseResource
{
380 AliasResource(SRBRoot
*bundle
, const char *tag
, const UChar
*value
, int32_t len
,
381 const UString
* comment
, UErrorCode
&errorCode
)
382 : StringBaseResource(bundle
, tag
, URES_ALIAS
, value
, len
, comment
, errorCode
) {}
383 virtual ~AliasResource();
386 class IntResource
: public SResource
{
388 IntResource(SRBRoot
*bundle
, const char *tag
, int32_t value
,
389 const UString
* comment
, UErrorCode
&errorCode
);
390 virtual ~IntResource();
392 // TODO: private with getter?
396 class IntVectorResource
: public SResource
{
398 IntVectorResource(SRBRoot
*bundle
, const char *tag
,
399 const UString
* comment
, UErrorCode
&errorCode
);
400 virtual ~IntVectorResource();
402 void add(int32_t value
, UErrorCode
&errorCode
);
404 virtual void handlePreWrite(uint32_t *byteOffset
);
405 virtual void handleWrite(UNewDataMemory
*mem
, uint32_t *byteOffset
);
412 class BinaryResource
: public SResource
{
414 BinaryResource(SRBRoot
*bundle
, const char *tag
,
415 uint32_t length
, uint8_t *data
, const char* fileName
,
416 const UString
* comment
, UErrorCode
&errorCode
);
417 virtual ~BinaryResource();
419 virtual void handlePreWrite(uint32_t *byteOffset
);
420 virtual void handleWrite(UNewDataMemory
*mem
, uint32_t *byteOffset
);
426 char* fFileName
; // file name for binary or import binary tags if any
429 // TODO: use LocalPointer or delete
430 void res_close(struct SResource
*res
);
432 void setIncludeCopyright(UBool val
);
433 UBool
getIncludeCopyright(void);
435 void setFormatVersion(int32_t formatVersion
);
437 int32_t getFormatVersion();
439 void setUsePoolBundle(UBool use
);
442 uint32_t computeCRC(const char *ptr
, uint32_t len
, uint32_t lastcrc
);
445 #endif /* #ifndef RESLIST_H */