]>
Commit | Line | Data |
---|---|---|
f3c0d7a5 A |
1 | // © 2016 and later: Unicode, Inc. and others. |
2 | // License & terms of use: http://www.unicode.org/copyright.html | |
b75a7d8f A |
3 | /* |
4 | ******************************************************************************* | |
5 | * | |
2ca993e8 | 6 | * Copyright (C) 2000-2015, International Business Machines |
b75a7d8f A |
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 | ||
374ca955 | 23 | #define KEY_SPACE_SIZE 65536 |
b75a7d8f A |
24 | #define RESLIST_MAX_INT_VECTOR 2048 |
25 | ||
3d1f044b A |
26 | #include <functional> |
27 | ||
b75a7d8f | 28 | #include "unicode/utypes.h" |
2ca993e8 | 29 | #include "unicode/unistr.h" |
b75a7d8f A |
30 | #include "unicode/ures.h" |
31 | #include "unicode/ustring.h" | |
b75a7d8f A |
32 | #include "cmemory.h" |
33 | #include "cstring.h" | |
2ca993e8 | 34 | #include "uhash.h" |
b75a7d8f | 35 | #include "unewdata.h" |
2ca993e8 | 36 | #include "uresdata.h" |
374ca955 | 37 | #include "ustr.h" |
b75a7d8f A |
38 | |
39 | U_CDECL_BEGIN | |
40 | ||
3d1f044b | 41 | class PathFilter; |
2ca993e8 | 42 | class PseudoListResource; |
3d1f044b | 43 | class ResKeyPath; |
2ca993e8 A |
44 | |
45 | struct ResFile { | |
46 | ResFile() | |
47 | : fBytes(NULL), fIndexes(NULL), | |
48 | fKeys(NULL), fKeysLength(0), fKeysCount(0), | |
49 | fStrings(NULL), fStringIndexLimit(0), | |
50 | fChecksum(0) {} | |
51 | ~ResFile() { close(); } | |
52 | ||
53 | void close(); | |
54 | ||
55 | uint8_t *fBytes; | |
56 | const int32_t *fIndexes; | |
57 | const char *fKeys; | |
58 | int32_t fKeysLength; | |
59 | int32_t fKeysCount; | |
60 | ||
61 | PseudoListResource *fStrings; | |
62 | int32_t fStringIndexLimit; | |
63 | ||
64 | int32_t fChecksum; | |
65 | }; | |
66 | ||
67 | struct SResource; | |
68 | ||
729e4ab9 A |
69 | typedef struct KeyMapEntry { |
70 | int32_t oldpos, newpos; | |
71 | } KeyMapEntry; | |
72 | ||
b75a7d8f A |
73 | /* Resource bundle root table */ |
74 | struct SRBRoot { | |
2ca993e8 A |
75 | SRBRoot(const UString *comment, UBool isPoolBundle, UErrorCode &errorCode); |
76 | ~SRBRoot(); | |
77 | ||
78 | void write(const char *outputDir, const char *outputPkg, | |
79 | char *writtenFilename, int writtenFilenameLen, UErrorCode &errorCode); | |
80 | ||
81 | void setLocale(UChar *locale, UErrorCode &errorCode); | |
82 | int32_t addTag(const char *tag, UErrorCode &errorCode); | |
83 | ||
84 | const char *getKeyString(int32_t key) const; | |
85 | const char *getKeyBytes(int32_t *pLength) const; | |
86 | ||
87 | int32_t addKeyBytes(const char *keyBytes, int32_t length, UErrorCode &errorCode); | |
88 | ||
89 | void compactKeys(UErrorCode &errorCode); | |
90 | ||
91 | int32_t makeRes16(uint32_t resWord) const; | |
92 | int32_t mapKey(int32_t oldpos) const; | |
93 | ||
94 | private: | |
95 | void compactStringsV2(UHashtable *stringSet, UErrorCode &errorCode); | |
96 | ||
97 | public: | |
98 | // TODO: private | |
99 | ||
100 | SResource *fRoot; // Normally a TableResource. | |
729e4ab9 A |
101 | char *fLocale; |
102 | int32_t fIndexLength; | |
374ca955 | 103 | int32_t fMaxTableLength; |
2ca993e8 | 104 | UBool fNoFallback; /* see URES_ATT_NO_FALLBACK */ |
729e4ab9 A |
105 | int8_t fStringsForm; /* default STRINGS_UTF16_V1 */ |
106 | UBool fIsPoolBundle; | |
107 | ||
108 | char *fKeys; | |
109 | KeyMapEntry *fKeyMap; | |
110 | int32_t fKeysBottom, fKeysTop; | |
111 | int32_t fKeysCapacity; | |
112 | int32_t fKeysCount; | |
113 | int32_t fLocalKeyLimit; /* key offset < limit fits into URES_TABLE */ | |
114 | ||
2ca993e8 A |
115 | icu::UnicodeString f16BitUnits; |
116 | int32_t f16BitStringsLength; | |
729e4ab9 | 117 | |
2ca993e8 A |
118 | const ResFile *fUsePoolBundle; |
119 | int32_t fPoolStringIndexLimit; | |
120 | int32_t fPoolStringIndex16Limit; | |
121 | int32_t fLocalStringIndexLimit; | |
122 | SRBRoot *fWritePoolBundle; | |
b75a7d8f A |
123 | }; |
124 | ||
b75a7d8f | 125 | /* write a java resource file */ |
2ca993e8 | 126 | // TODO: C++ify |
b75a7d8f A |
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); | |
129 | ||
130 | /* write a xml resource file */ | |
2ca993e8 | 131 | // TODO: C++ify |
b75a7d8f A |
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); | |
134 | ||
b75a7d8f A |
135 | /* Various resource types */ |
136 | ||
46f4442e A |
137 | /* |
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.) | |
141 | */ | |
142 | struct SResource* res_none(void); | |
143 | ||
2ca993e8 A |
144 | class ArrayResource; |
145 | class TableResource; | |
146 | class IntVectorResource; | |
147 | ||
148 | TableResource *table_open(struct SRBRoot *bundle, const char *tag, const struct UString* comment, UErrorCode *status); | |
149 | ||
150 | ArrayResource *array_open(struct SRBRoot *bundle, const char *tag, const struct UString* comment, UErrorCode *status); | |
151 | ||
152 | struct SResource *string_open(struct SRBRoot *bundle, const char *tag, const UChar *value, int32_t len, const struct UString* comment, UErrorCode *status); | |
153 | ||
154 | struct SResource *alias_open(struct SRBRoot *bundle, const char *tag, UChar *value, int32_t len, const struct UString* comment, UErrorCode *status); | |
155 | ||
156 | IntVectorResource *intvector_open(struct SRBRoot *bundle, const char *tag, const struct UString* comment, UErrorCode *status); | |
157 | ||
158 | struct SResource *int_open(struct SRBRoot *bundle, const char *tag, int32_t value, const struct UString* comment, UErrorCode *status); | |
159 | ||
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); | |
161 | ||
162 | /* Resource place holder */ | |
163 | ||
164 | struct SResource { | |
165 | SResource(); | |
166 | SResource(SRBRoot *bundle, const char *tag, int8_t type, const UString* comment, | |
167 | UErrorCode &errorCode); | |
168 | virtual ~SResource(); | |
169 | ||
170 | UBool isTable() const { return fType == URES_TABLE; } | |
171 | UBool isString() const { return fType == URES_STRING; } | |
172 | ||
173 | const char *getKeyString(const SRBRoot *bundle) const; | |
174 | ||
175 | /** | |
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. | |
180 | * | |
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). | |
183 | */ | |
184 | void preflightStrings(SRBRoot *bundle, UHashtable *stringSet, UErrorCode &errorCode); | |
185 | virtual void handlePreflightStrings(SRBRoot *bundle, UHashtable *stringSet, UErrorCode &errorCode); | |
186 | ||
187 | /** | |
188 | * Writes resource values into f16BitUnits | |
189 | * and determines the resource item word, if possible. | |
190 | */ | |
191 | void write16(SRBRoot *bundle); | |
192 | virtual void handleWrite16(SRBRoot *bundle); | |
193 | ||
194 | /** | |
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. | |
198 | * | |
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. | |
202 | * | |
203 | * The preWrite() and write() functions start and end at the same | |
204 | * byteOffset values. | |
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. | |
208 | */ | |
209 | void preWrite(uint32_t *byteOffset); | |
210 | virtual void handlePreWrite(uint32_t *byteOffset); | |
211 | ||
212 | /** | |
213 | * Writes the resource's data to mem and updates the byteOffset | |
214 | * in parallel. | |
215 | */ | |
216 | void write(UNewDataMemory *mem, uint32_t *byteOffset); | |
217 | virtual void handleWrite(UNewDataMemory *mem, uint32_t *byteOffset); | |
218 | ||
3d1f044b A |
219 | /** |
220 | * Applies the given filter with the given base path to this resource. | |
221 | * Removes child resources rejected by the filter recursively. | |
222 | * | |
223 | * @param bundle Needed in order to access the key for this and child resources. | |
224 | */ | |
225 | virtual void applyFilter(const PathFilter& filter, ResKeyPath& path, const SRBRoot* bundle); | |
226 | ||
227 | /** | |
228 | * Calls the given function for every key ID present in this tree. | |
229 | */ | |
230 | virtual void collectKeys(std::function<void(int32_t)> collector) const; | |
231 | ||
2ca993e8 A |
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; | |
241 | }; | |
242 | ||
243 | class ContainerResource : public SResource { | |
244 | public: | |
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(); | |
250 | ||
3d1f044b A |
251 | void handlePreflightStrings(SRBRoot *bundle, UHashtable *stringSet, UErrorCode &errorCode) override; |
252 | ||
253 | void collectKeys(std::function<void(int32_t)> collector) const override; | |
254 | ||
2ca993e8 A |
255 | protected: |
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); | |
260 | ||
261 | public: | |
262 | // TODO: private with getter? | |
374ca955 | 263 | uint32_t fCount; |
2ca993e8 | 264 | SResource *fFirst; |
b75a7d8f A |
265 | }; |
266 | ||
2ca993e8 A |
267 | class TableResource : public ContainerResource { |
268 | public: | |
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(); | |
b75a7d8f | 274 | |
2ca993e8 A |
275 | void add(SResource *res, int linenumber, UErrorCode &errorCode); |
276 | ||
3d1f044b A |
277 | void handleWrite16(SRBRoot *bundle) override; |
278 | void handlePreWrite(uint32_t *byteOffset) override; | |
279 | void handleWrite(UNewDataMemory *mem, uint32_t *byteOffset) override; | |
280 | ||
281 | void applyFilter(const PathFilter& filter, ResKeyPath& path, const SRBRoot* bundle) override; | |
2ca993e8 A |
282 | |
283 | int8_t fTableType; // determined by table_write16() for table_preWrite() & table_write() | |
284 | SRBRoot *fRoot; | |
b75a7d8f A |
285 | }; |
286 | ||
2ca993e8 A |
287 | class ArrayResource : public ContainerResource { |
288 | public: | |
289 | ArrayResource(SRBRoot *bundle, const char *tag, | |
290 | const UString* comment, UErrorCode &errorCode) | |
291 | : ContainerResource(bundle, tag, URES_ARRAY, comment, errorCode), | |
292 | fLast(NULL) {} | |
293 | virtual ~ArrayResource(); | |
b75a7d8f | 294 | |
2ca993e8 A |
295 | void add(SResource *res); |
296 | ||
297 | virtual void handleWrite16(SRBRoot *bundle); | |
298 | virtual void handlePreWrite(uint32_t *byteOffset); | |
299 | virtual void handleWrite(UNewDataMemory *mem, uint32_t *byteOffset); | |
300 | ||
301 | SResource *fLast; | |
b75a7d8f A |
302 | }; |
303 | ||
2ca993e8 A |
304 | /** |
305 | * List of resources for a pool bundle. | |
306 | * Writes an empty table resource, rather than a container structure. | |
307 | */ | |
308 | class PseudoListResource : public ContainerResource { | |
309 | public: | |
310 | PseudoListResource(SRBRoot *bundle, UErrorCode &errorCode) | |
311 | : ContainerResource(bundle, NULL, URES_TABLE, NULL, errorCode) {} | |
312 | virtual ~PseudoListResource(); | |
b75a7d8f | 313 | |
2ca993e8 | 314 | void add(SResource *res); |
b75a7d8f | 315 | |
2ca993e8 | 316 | virtual void handleWrite16(SRBRoot *bundle); |
b75a7d8f A |
317 | }; |
318 | ||
2ca993e8 A |
319 | class StringBaseResource : public SResource { |
320 | public: | |
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(); | |
328 | ||
f3c0d7a5 | 329 | const UChar *getBuffer() const { return icu::toUCharPtr(fString.getBuffer()); } |
2ca993e8 | 330 | int32_t length() const { return fString.length(); } |
b75a7d8f | 331 | |
2ca993e8 A |
332 | virtual void handlePreWrite(uint32_t *byteOffset); |
333 | virtual void handleWrite(UNewDataMemory *mem, uint32_t *byteOffset); | |
334 | ||
335 | // TODO: private with getter? | |
336 | icu::UnicodeString fString; | |
b75a7d8f A |
337 | }; |
338 | ||
2ca993e8 A |
339 | class StringResource : public StringBaseResource { |
340 | public: | |
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); | |
358 | fWritten = TRUE; | |
359 | } | |
360 | virtual ~StringResource(); | |
361 | ||
362 | int32_t get16BitStringsLength() const { | |
363 | return fNumCharsForLength + length() + 1; // +1 for the NUL | |
364 | } | |
365 | ||
366 | virtual void handlePreflightStrings(SRBRoot *bundle, UHashtable *stringSet, UErrorCode &errorCode); | |
367 | virtual void handleWrite16(SRBRoot *bundle); | |
368 | ||
369 | void writeUTF16v2(int32_t base, icu::UnicodeString &dest); | |
370 | ||
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; | |
376 | }; | |
b75a7d8f | 377 | |
2ca993e8 A |
378 | class AliasResource : public StringBaseResource { |
379 | public: | |
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(); | |
b75a7d8f A |
384 | }; |
385 | ||
2ca993e8 A |
386 | class IntResource : public SResource { |
387 | public: | |
388 | IntResource(SRBRoot *bundle, const char *tag, int32_t value, | |
389 | const UString* comment, UErrorCode &errorCode); | |
390 | virtual ~IntResource(); | |
b75a7d8f | 391 | |
2ca993e8 A |
392 | // TODO: private with getter? |
393 | int32_t fValue; | |
394 | }; | |
b75a7d8f | 395 | |
2ca993e8 A |
396 | class IntVectorResource : public SResource { |
397 | public: | |
398 | IntVectorResource(SRBRoot *bundle, const char *tag, | |
399 | const UString* comment, UErrorCode &errorCode); | |
400 | virtual ~IntVectorResource(); | |
401 | ||
402 | void add(int32_t value, UErrorCode &errorCode); | |
403 | ||
404 | virtual void handlePreWrite(uint32_t *byteOffset); | |
405 | virtual void handleWrite(UNewDataMemory *mem, uint32_t *byteOffset); | |
406 | ||
407 | // TODO: UVector32 | |
408 | uint32_t fCount; | |
409 | uint32_t *fArray; | |
b75a7d8f A |
410 | }; |
411 | ||
2ca993e8 A |
412 | class BinaryResource : public SResource { |
413 | public: | |
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(); | |
418 | ||
419 | virtual void handlePreWrite(uint32_t *byteOffset); | |
420 | virtual void handleWrite(UNewDataMemory *mem, uint32_t *byteOffset); | |
729e4ab9 | 421 | |
2ca993e8 A |
422 | // TODO: CharString? |
423 | uint32_t fLength; | |
424 | uint8_t *fData; | |
425 | // TODO: CharString | |
426 | char* fFileName; // file name for binary or import binary tags if any | |
427 | }; | |
428 | ||
429 | // TODO: use LocalPointer or delete | |
46f4442e | 430 | void res_close(struct SResource *res); |
729e4ab9 | 431 | |
b75a7d8f A |
432 | void setIncludeCopyright(UBool val); |
433 | UBool getIncludeCopyright(void); | |
434 | ||
729e4ab9 A |
435 | void setFormatVersion(int32_t formatVersion); |
436 | ||
2ca993e8 A |
437 | int32_t getFormatVersion(); |
438 | ||
729e4ab9 A |
439 | void setUsePoolBundle(UBool use); |
440 | ||
441 | /* in wrtxml.cpp */ | |
2ca993e8 | 442 | uint32_t computeCRC(const char *ptr, uint32_t len, uint32_t lastcrc); |
729e4ab9 | 443 | |
b75a7d8f A |
444 | U_CDECL_END |
445 | #endif /* #ifndef RESLIST_H */ |