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 */
|