summaryrefslogtreecommitdiffstats
path: root/intl/icu/source/tools/genrb/reslist.h
blob: 17797bc36cbb10451dc0421a8e427ba4e23677a2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
// © 2016 and later: Unicode, Inc. and others.
// License & terms of use: http://www.unicode.org/copyright.html
/*
*******************************************************************************
*
*   Copyright (C) 2000-2015, International Business Machines
*   Corporation and others.  All Rights Reserved.
*
*******************************************************************************
*
* File reslist.h
*
* Modification History:
*
*   Date        Name        Description
*   02/21/00    weiv        Creation.
*******************************************************************************
*/

#ifndef RESLIST_H
#define RESLIST_H

#define KEY_SPACE_SIZE 65536
#define RESLIST_INT_VECTOR_INIT_SIZE 2048

#include <functional>

#include "unicode/utypes.h"
#include "unicode/unistr.h"
#include "unicode/ures.h"
#include "unicode/ustring.h"
#include "cmemory.h"
#include "cstring.h"
#include "uhash.h"
#include "unewdata.h"
#include "uresdata.h"
#include "ustr.h"

U_CDECL_BEGIN

class PathFilter;
class PseudoListResource;
class ResKeyPath;

struct ResFile {
    ResFile()
            : fBytes(nullptr), fIndexes(nullptr),
              fKeys(nullptr), fKeysLength(0), fKeysCount(0),
              fStrings(nullptr), fStringIndexLimit(0),
              fChecksum(0) {}
    ~ResFile() { close(); }

    void close();

    uint8_t *fBytes;
    const int32_t *fIndexes;
    const char *fKeys;
    int32_t fKeysLength;
    int32_t fKeysCount;

    PseudoListResource *fStrings;
    int32_t fStringIndexLimit;

    int32_t fChecksum;
};

struct SResource;

typedef struct KeyMapEntry {
    int32_t oldpos, newpos;
} KeyMapEntry;

/* Resource bundle root table */
struct SRBRoot {
    SRBRoot(const UString *comment, UBool isPoolBundle, UErrorCode &errorCode);
    ~SRBRoot();

    void write(const char *outputDir, const char *outputPkg,
               char *writtenFilename, int writtenFilenameLen, UErrorCode &errorCode);

    void setLocale(char16_t *locale, UErrorCode &errorCode);
    int32_t addTag(const char *tag, UErrorCode &errorCode);

    const char *getKeyString(int32_t key) const;
    const char *getKeyBytes(int32_t *pLength) const;

    int32_t addKeyBytes(const char *keyBytes, int32_t length, UErrorCode &errorCode);

    void compactKeys(UErrorCode &errorCode);

    int32_t makeRes16(uint32_t resWord) const;
    int32_t mapKey(int32_t oldpos) const;

private:
    void compactStringsV2(UHashtable *stringSet, UErrorCode &errorCode);

public:
    // TODO: private

  SResource *fRoot;  // Normally a TableResource.
  char *fLocale;
  int32_t fIndexLength;
  int32_t fMaxTableLength;
  UBool fNoFallback; /* see URES_ATT_NO_FALLBACK */
  int8_t fStringsForm; /* default STRINGS_UTF16_V1 */
  UBool fIsPoolBundle;

  char *fKeys;
  KeyMapEntry *fKeyMap;
  int32_t fKeysBottom, fKeysTop;
  int32_t fKeysCapacity;
  int32_t fKeysCount;
  int32_t fLocalKeyLimit; /* key offset < limit fits into URES_TABLE */

  icu::UnicodeString f16BitUnits;
  int32_t f16BitStringsLength;

  const ResFile *fUsePoolBundle;
  int32_t fPoolStringIndexLimit;
  int32_t fPoolStringIndex16Limit;
  int32_t fLocalStringIndexLimit;
  SRBRoot *fWritePoolBundle;
};

/* write a java resource file */
// TODO: C++ify
void bundle_write_java(struct SRBRoot *bundle, const char *outputDir, const char* outputEnc, char *writtenFilename, 
                       int writtenFilenameLen, const char* packageName, const char* bundleName, UErrorCode *status);

/* write a xml resource file */
// TODO: C++ify
void bundle_write_xml(struct SRBRoot *bundle, const char *outputDir,const char* outputEnc, const char* rbname,
                  char *writtenFilename, int writtenFilenameLen, const char* language, const char* package, UErrorCode *status);

/* Various resource types */

/*
 * Return a unique pointer to a dummy object,
 * for use in non-error cases when no resource is to be added to the bundle.
 * (nullptr is used in error cases.)
 */
struct SResource* res_none();

class ArrayResource;
class TableResource;
class IntVectorResource;

TableResource *table_open(struct SRBRoot *bundle, const char *tag, const struct UString* comment, UErrorCode *status);

ArrayResource *array_open(struct SRBRoot *bundle, const char *tag, const struct UString* comment, UErrorCode *status);

struct SResource *string_open(struct SRBRoot *bundle, const char *tag, const char16_t *value, int32_t len, const struct UString* comment, UErrorCode *status);

struct SResource *alias_open(struct SRBRoot *bundle, const char *tag, char16_t *value, int32_t len, const struct UString* comment, UErrorCode *status);

IntVectorResource *intvector_open(struct SRBRoot *bundle, const char *tag,  const struct UString* comment, UErrorCode *status);

struct SResource *int_open(struct SRBRoot *bundle, const char *tag, int32_t value, const struct UString* comment, UErrorCode *status);

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);

/* Resource place holder */

struct SResource {
    SResource();
    SResource(SRBRoot *bundle, const char *tag, int8_t type, const UString* comment,
              UErrorCode &errorCode);
    virtual ~SResource();

    UBool isTable() const { return fType == URES_TABLE; }
    UBool isString() const { return fType == URES_STRING; }

    const char *getKeyString(const SRBRoot *bundle) const;

    /**
     * Preflights strings.
     * Finds duplicates and counts the total number of string code units
     * so that they can be written first to the 16-bit array,
     * for minimal string and container storage.
     *
     * We walk the final parse tree, rather than collecting this information while building it,
     * so that we need not deal with changes to the parse tree (especially removing resources).
     */
    void preflightStrings(SRBRoot *bundle, UHashtable *stringSet, UErrorCode &errorCode);
    virtual void handlePreflightStrings(SRBRoot *bundle, UHashtable *stringSet, UErrorCode &errorCode);

    /**
     * Writes resource values into f16BitUnits
     * and determines the resource item word, if possible.
     */
    void write16(SRBRoot *bundle);
    virtual void handleWrite16(SRBRoot *bundle);

    /**
     * Calculates ("preflights") and advances the *byteOffset
     * by the size of the resource's data in the binary file and
     * determines the resource item word.
     *
     * Most handlePreWrite() functions may add any number of bytes, but preWrite()
     * will always pad it to a multiple of 4.
     * The resource item type may be a related subtype of the fType.
     *
     * The preWrite() and write() functions start and end at the same
     * byteOffset values.
     * Prewriting allows bundle.write() to determine the root resource item word,
     * before actually writing the bundle contents to the file,
     * which is necessary because the root item is stored at the beginning.
     */
    void preWrite(uint32_t *byteOffset);
    virtual void handlePreWrite(uint32_t *byteOffset);

    /**
     * Writes the resource's data to mem and updates the byteOffset
     * in parallel.
     */
    void write(UNewDataMemory *mem, uint32_t *byteOffset);
    virtual void handleWrite(UNewDataMemory *mem, uint32_t *byteOffset);

    /**
     * Applies the given filter with the given base path to this resource.
     * Removes child resources rejected by the filter recursively.
     * 
     * @param bundle Needed in order to access the key for this and child resources.
     */
    virtual void applyFilter(const PathFilter& filter, ResKeyPath& path, const SRBRoot* bundle);

    /**
     * Calls the given function for every key ID present in this tree.
     */
    virtual void collectKeys(std::function<void(int32_t)> collector) const;

    int8_t   fType;     /* nominal type: fRes (when != 0xffffffff) may use subtype */
    UBool    fWritten;  /* res_write() can exit early */
    uint32_t fRes;      /* resource item word; RES_BOGUS=0xffffffff if not known yet */
    int32_t  fRes16;    /* Res16 version of fRes for Table, Table16, Array16; -1 if it does not fit. */
    int32_t  fKey;      /* Index into bundle->fKeys; -1 if no key. */
    int32_t  fKey16;    /* Key16 version of fKey for Table & Table16; -1 if no key or it does not fit. */
    int      line;      /* used internally to report duplicate keys in tables */
    SResource *fNext;   /* This is for internal chaining while building */
    struct UString fComment;
};

class ContainerResource : public SResource {
public:
    ContainerResource(SRBRoot *bundle, const char *tag, int8_t type,
                      const UString* comment, UErrorCode &errorCode)
            : SResource(bundle, tag, type, comment, errorCode),
              fCount(0), fFirst(nullptr) {}
    virtual ~ContainerResource();

    void handlePreflightStrings(SRBRoot *bundle, UHashtable *stringSet, UErrorCode &errorCode) override;

    void collectKeys(std::function<void(int32_t)> collector) const override;

protected:
    void writeAllRes16(SRBRoot *bundle);
    void preWriteAllRes(uint32_t *byteOffset);
    void writeAllRes(UNewDataMemory *mem, uint32_t *byteOffset);
    void writeAllRes32(UNewDataMemory *mem, uint32_t *byteOffset);

public:
    // TODO: private with getter?
    uint32_t fCount;
    SResource *fFirst;
};

class TableResource : public ContainerResource {
public:
    TableResource(SRBRoot *bundle, const char *tag,
                  const UString* comment, UErrorCode &errorCode)
            : ContainerResource(bundle, tag, URES_TABLE, comment, errorCode),
              fTableType(URES_TABLE), fRoot(bundle) {}
    virtual ~TableResource();

    void add(SResource *res, int linenumber, UErrorCode &errorCode);

    void handleWrite16(SRBRoot *bundle) override;
    void handlePreWrite(uint32_t *byteOffset) override;
    void handleWrite(UNewDataMemory *mem, uint32_t *byteOffset) override;

    void applyFilter(const PathFilter& filter, ResKeyPath& path, const SRBRoot* bundle) override;

    int8_t fTableType;  // determined by table_write16() for table_preWrite() & table_write()
    SRBRoot *fRoot;
};

class ArrayResource : public ContainerResource {
public:
    ArrayResource(SRBRoot *bundle, const char *tag,
                  const UString* comment, UErrorCode &errorCode)
            : ContainerResource(bundle, tag, URES_ARRAY, comment, errorCode),
              fLast(nullptr) {}
    virtual ~ArrayResource();

    void add(SResource *res);

    virtual void handleWrite16(SRBRoot *bundle) override;
    virtual void handlePreWrite(uint32_t *byteOffset) override;
    virtual void handleWrite(UNewDataMemory *mem, uint32_t *byteOffset) override;

    SResource *fLast;
};

/**
 * List of resources for a pool bundle.
 * Writes an empty table resource, rather than a container structure.
 */
class PseudoListResource : public ContainerResource {
public:
    PseudoListResource(SRBRoot *bundle, UErrorCode &errorCode)
            : ContainerResource(bundle, nullptr, URES_TABLE, nullptr, errorCode) {}
    virtual ~PseudoListResource();

    void add(SResource *res);

    virtual void handleWrite16(SRBRoot *bundle) override;
};

class StringBaseResource : public SResource {
public:
    StringBaseResource(SRBRoot *bundle, const char *tag, int8_t type,
                       const char16_t *value, int32_t len,
                       const UString* comment, UErrorCode &errorCode);
    StringBaseResource(SRBRoot *bundle, int8_t type,
                       const icu::UnicodeString &value, UErrorCode &errorCode);
    StringBaseResource(int8_t type, const char16_t *value, int32_t len, UErrorCode &errorCode);
    virtual ~StringBaseResource();

    const char16_t *getBuffer() const { return icu::toUCharPtr(fString.getBuffer()); }
    int32_t length() const { return fString.length(); }

    virtual void handlePreWrite(uint32_t *byteOffset) override;
    virtual void handleWrite(UNewDataMemory *mem, uint32_t *byteOffset) override;

    // TODO: private with getter?
    icu::UnicodeString fString;
};

class StringResource : public StringBaseResource {
public:
    StringResource(SRBRoot *bundle, const char *tag, const char16_t *value, int32_t len,
                   const UString* comment, UErrorCode &errorCode)
            : StringBaseResource(bundle, tag, URES_STRING, value, len, comment, errorCode),
              fSame(nullptr), fSuffixOffset(0),
              fNumCopies(0), fNumUnitsSaved(0), fNumCharsForLength(0) {}
    StringResource(SRBRoot *bundle, const icu::UnicodeString &value, UErrorCode &errorCode)
            : StringBaseResource(bundle, URES_STRING, value, errorCode),
              fSame(nullptr), fSuffixOffset(0),
              fNumCopies(0), fNumUnitsSaved(0), fNumCharsForLength(0) {}
    StringResource(int32_t poolStringIndex, int8_t numCharsForLength,
                   const char16_t *value, int32_t length,
                   UErrorCode &errorCode)
            : StringBaseResource(URES_STRING, value, length, errorCode),
              fSame(nullptr), fSuffixOffset(0),
              fNumCopies(0), fNumUnitsSaved(0), fNumCharsForLength(numCharsForLength) {
        // v3 pool string encoded as string-v2 with low offset
        fRes = URES_MAKE_RESOURCE(URES_STRING_V2, poolStringIndex);
        fWritten = true;
    }
    virtual ~StringResource();

    int32_t get16BitStringsLength() const {
        return fNumCharsForLength + length() + 1;  // +1 for the NUL
    }

    virtual void handlePreflightStrings(SRBRoot *bundle, UHashtable *stringSet, UErrorCode &errorCode) override;
    virtual void handleWrite16(SRBRoot *bundle) override;

    void writeUTF16v2(int32_t base, icu::UnicodeString &dest);

    StringResource *fSame;  // used for duplicates
    int32_t fSuffixOffset;  // this string is a suffix of fSame at this offset
    int32_t fNumCopies;     // number of equal strings represented by one stringSet element
    int32_t fNumUnitsSaved;  // from not writing duplicates and suffixes
    int8_t fNumCharsForLength;
};

class AliasResource : public StringBaseResource {
public:
    AliasResource(SRBRoot *bundle, const char *tag, const char16_t *value, int32_t len,
                  const UString* comment, UErrorCode &errorCode)
            : StringBaseResource(bundle, tag, URES_ALIAS, value, len, comment, errorCode) {}
    virtual ~AliasResource();
};

class IntResource : public SResource {
public:
    IntResource(SRBRoot *bundle, const char *tag, int32_t value,
                const UString* comment, UErrorCode &errorCode);
    virtual ~IntResource();

    // TODO: private with getter?
    int32_t fValue;
};

class IntVectorResource : public SResource {
public:
    IntVectorResource(SRBRoot *bundle, const char *tag,
                      const UString* comment, UErrorCode &errorCode);
    virtual ~IntVectorResource();

    void add(int32_t value, UErrorCode &errorCode);

    virtual void handlePreWrite(uint32_t *byteOffset) override;
    virtual void handleWrite(UNewDataMemory *mem, uint32_t *byteOffset) override;

    // TODO: UVector32
    size_t fCount;
    size_t fSize;
    uint32_t *fArray;
};

class BinaryResource : public SResource {
public:
    BinaryResource(SRBRoot *bundle, const char *tag,
                   uint32_t length, uint8_t *data, const char* fileName,
                   const UString* comment, UErrorCode &errorCode);
    virtual ~BinaryResource();

    virtual void handlePreWrite(uint32_t *byteOffset) override;
    virtual void handleWrite(UNewDataMemory *mem, uint32_t *byteOffset) override;

    // TODO: CharString?
    uint32_t fLength;
    uint8_t *fData;
    // TODO: CharString
    char* fFileName;  // file name for binary or import binary tags if any
};

// TODO: use LocalPointer or delete
void res_close(struct SResource *res);

void setIncludeCopyright(UBool val);
UBool getIncludeCopyright();

void setFormatVersion(int32_t formatVersion);

int32_t getFormatVersion();

void setUsePoolBundle(UBool use);

/* in wrtxml.cpp */
uint32_t computeCRC(const char *ptr, uint32_t len, uint32_t lastcrc);

U_CDECL_END
#endif /* #ifndef RESLIST_H */