mirror of
https://github.com/unicode-org/icu.git
synced 2025-04-17 02:37:25 +00:00
ICU-11761 simpler memory management with UnicodeString & LocalArray
X-SVN-Rev: 37644
This commit is contained in:
parent
9312cb2d1a
commit
a1348758c1
3 changed files with 61 additions and 113 deletions
|
@ -2043,7 +2043,7 @@ parse(UCHARBUF *buf, const char *inputDir, const char *outputDir, const char *fi
|
|||
* This is the same as a regular table, but also sets the
|
||||
* URES_ATT_NO_FALLBACK flag in indexes[URES_INDEX_ATTRIBUTES] .
|
||||
*/
|
||||
state.bundle->noFallback=TRUE;
|
||||
state.bundle->fNoFallback=TRUE;
|
||||
}
|
||||
/* top-level tables need not handle special table names like "collations" */
|
||||
realParseTable(&state, state.bundle->fRoot, NULL, line, status);
|
||||
|
|
|
@ -333,7 +333,7 @@ StringResource::handlePreflightStrings(SRBRoot *bundle, UHashtable *stringSet,
|
|||
} else {
|
||||
fNumCharsForLength = 3;
|
||||
}
|
||||
bundle->f16BitUnitsLength += fNumCharsForLength + len + 1; /* +1 for the NUL */
|
||||
bundle->f16BitStringsLength += fNumCharsForLength + len + 1; /* +1 for the NUL */
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -367,33 +367,6 @@ SResource::handlePreflightStrings(SRBRoot * /*bundle*/, UHashtable * /*stringSet
|
|||
/* Neither a string nor a container. */
|
||||
}
|
||||
|
||||
uint16_t *
|
||||
SRBRoot::reserve16BitUnits(int32_t length, UErrorCode &errorCode) {
|
||||
if (U_FAILURE(errorCode)) {
|
||||
return NULL;
|
||||
}
|
||||
if ((f16BitUnitsLength + length) > f16BitUnitsCapacity) {
|
||||
uint16_t *newUnits;
|
||||
int32_t capacity = 2 * f16BitUnitsCapacity + length + 1024;
|
||||
capacity &= ~1; /* ensures padding fits if f16BitUnitsLength needs it */
|
||||
newUnits = (uint16_t *)uprv_malloc(capacity * 2);
|
||||
if (newUnits == NULL) {
|
||||
errorCode = U_MEMORY_ALLOCATION_ERROR;
|
||||
return NULL;
|
||||
}
|
||||
if (f16BitUnitsLength > 0) {
|
||||
uprv_memcpy(newUnits, f16BitUnits, f16BitUnitsLength * 2);
|
||||
} else {
|
||||
newUnits[0] = 0;
|
||||
f16BitUnitsLength = 1;
|
||||
}
|
||||
uprv_free(f16BitUnits);
|
||||
f16BitUnits = newUnits;
|
||||
f16BitUnitsCapacity = capacity;
|
||||
}
|
||||
return f16BitUnits + f16BitUnitsLength;
|
||||
}
|
||||
|
||||
static int32_t
|
||||
makeRes16(uint32_t resWord) {
|
||||
uint32_t type, offset;
|
||||
|
@ -442,7 +415,7 @@ SRBRoot::makeKey16(int32_t key) const {
|
|||
|
||||
/*
|
||||
* Only called for UTF-16 v1 strings and duplicate UTF-16 v2 strings.
|
||||
* For unique UTF-16 v2 strings, res_write16() sees fRes != RES_BOGUS
|
||||
* For unique UTF-16 v2 strings, write16() sees fRes != RES_BOGUS
|
||||
* and exits early.
|
||||
*/
|
||||
void
|
||||
|
@ -470,15 +443,14 @@ ArrayResource::handleWrite16(SRBRoot *bundle, UErrorCode &errorCode) {
|
|||
res16 |= makeRes16(current->fRes);
|
||||
}
|
||||
if (U_SUCCESS(errorCode) && fCount <= 0xffff && res16 >= 0 && gFormatVersion > 1) {
|
||||
uint16_t *p16 = bundle->reserve16BitUnits(1 + fCount, errorCode);
|
||||
if (U_SUCCESS(errorCode)) {
|
||||
fRes = URES_MAKE_RESOURCE(URES_ARRAY16, bundle->f16BitUnitsLength);
|
||||
*p16++ = (uint16_t)fCount;
|
||||
for (SResource *current = fFirst; current != NULL; current = current->fNext) {
|
||||
*p16++ = (uint16_t)makeRes16(current->fRes);
|
||||
}
|
||||
bundle->f16BitUnitsLength += 1 + fCount;
|
||||
fWritten = TRUE;
|
||||
fRes = URES_MAKE_RESOURCE(URES_ARRAY16, bundle->f16BitUnits.length());
|
||||
bundle->f16BitUnits.append((UChar)fCount);
|
||||
for (SResource *current = fFirst; current != NULL; current = current->fNext) {
|
||||
bundle->f16BitUnits.append((UChar)makeRes16(current->fRes));
|
||||
}
|
||||
fWritten = TRUE;
|
||||
if (bundle->f16BitUnits.isBogus()) {
|
||||
errorCode = U_MEMORY_ALLOCATION_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -524,19 +496,18 @@ TableResource::handleWrite16(SRBRoot *bundle, UErrorCode &errorCode) {
|
|||
(!hasPoolKeys || maxPoolKey < (0x10000 - bundle->fLocalKeyLimit))
|
||||
) {
|
||||
if (res16 >= 0 && gFormatVersion > 1) {
|
||||
uint16_t *p16 = bundle->reserve16BitUnits(1 + fCount * 2, errorCode);
|
||||
if (U_SUCCESS(errorCode)) {
|
||||
/* 16-bit count, key offsets and values */
|
||||
fRes = URES_MAKE_RESOURCE(URES_TABLE16, bundle->f16BitUnitsLength);
|
||||
*p16++ = (uint16_t)fCount;
|
||||
for (SResource *current = fFirst; current != NULL; current = current->fNext) {
|
||||
*p16++ = bundle->makeKey16(current->fKey);
|
||||
}
|
||||
for (SResource *current = fFirst; current != NULL; current = current->fNext) {
|
||||
*p16++ = (uint16_t)makeRes16(current->fRes);
|
||||
}
|
||||
bundle->f16BitUnitsLength += 1 + fCount * 2;
|
||||
fWritten = TRUE;
|
||||
/* 16-bit count, key offsets and values */
|
||||
fRes = URES_MAKE_RESOURCE(URES_TABLE16, bundle->f16BitUnits.length());
|
||||
bundle->f16BitUnits.append((UChar)fCount);
|
||||
for (SResource *current = fFirst; current != NULL; current = current->fNext) {
|
||||
bundle->f16BitUnits.append((UChar)bundle->makeKey16(current->fKey));
|
||||
}
|
||||
for (SResource *current = fFirst; current != NULL; current = current->fNext) {
|
||||
bundle->f16BitUnits.append((UChar)makeRes16(current->fRes));
|
||||
}
|
||||
fWritten = TRUE;
|
||||
if (bundle->f16BitUnits.isBogus()) {
|
||||
errorCode = U_MEMORY_ALLOCATION_ERROR;
|
||||
}
|
||||
} else {
|
||||
/* 16-bit count, 16-bit key offsets, 32-bit values */
|
||||
|
@ -572,7 +543,7 @@ SResource::handleWrite16(SRBRoot * /*bundle*/, UErrorCode & /*errorCode*/) {
|
|||
|
||||
/*
|
||||
* Only called for UTF-16 v1 strings, and for aliases.
|
||||
* For UTF-16 v2 strings, res_preWrite() sees fRes != RES_BOGUS
|
||||
* For UTF-16 v2 strings, preWrite() sees fRes != RES_BOGUS
|
||||
* and exits early.
|
||||
*/
|
||||
void
|
||||
|
@ -660,7 +631,7 @@ SResource::handlePreWrite(uint32_t * /*byteOffset*/, SRBRoot * /*bundle*/,
|
|||
|
||||
/*
|
||||
* Only called for UTF-16 v1 strings, and for aliases. For UTF-16 v2 strings,
|
||||
* res_write() sees fWritten and exits early.
|
||||
* write() sees fWritten and exits early.
|
||||
*/
|
||||
void
|
||||
StringBaseResource::handleWrite(UNewDataMemory *mem, uint32_t *byteOffset,
|
||||
|
@ -814,14 +785,14 @@ void SRBRoot::write(const char *outputDir, const char *outputPkg,
|
|||
|
||||
compactStrings(errorCode);
|
||||
fRoot->write16(this, errorCode);
|
||||
if (f16BitUnitsLength & 1) {
|
||||
f16BitUnits[f16BitUnitsLength++] = 0xaaaa; /* pad to multiple of 4 bytes */
|
||||
if (f16BitUnits.length() & 1) {
|
||||
f16BitUnits.append((UChar)0xaaaa); /* pad to multiple of 4 bytes */
|
||||
}
|
||||
/* all keys have been mapped */
|
||||
uprv_free(fKeyMap);
|
||||
fKeyMap = NULL;
|
||||
|
||||
byteOffset = fKeysTop + f16BitUnitsLength * 2;
|
||||
byteOffset = fKeysTop + f16BitUnits.length() * 2;
|
||||
fRoot->preWrite(&byteOffset, this, errorCode);
|
||||
|
||||
/* total size including the root item */
|
||||
|
@ -913,7 +884,7 @@ void SRBRoot::write(const char *outputDir, const char *outputPkg,
|
|||
* write indexes[URES_INDEX_ATTRIBUTES] with URES_ATT_NO_FALLBACK set or not set
|
||||
* the memset() above initialized all indexes[] to 0
|
||||
*/
|
||||
if (noFallback) {
|
||||
if (fNoFallback) {
|
||||
indexes[URES_INDEX_ATTRIBUTES]=URES_ATT_NO_FALLBACK;
|
||||
}
|
||||
/*
|
||||
|
@ -921,7 +892,7 @@ void SRBRoot::write(const char *outputDir, const char *outputPkg,
|
|||
* more compact string value storage, optional pool bundle
|
||||
*/
|
||||
if (URES_INDEX_16BIT_TOP < fIndexLength) {
|
||||
indexes[URES_INDEX_16BIT_TOP] = (fKeysTop>>2) + (f16BitUnitsLength>>1);
|
||||
indexes[URES_INDEX_16BIT_TOP] = (fKeysTop>>2) + (f16BitUnits.length()>>1);
|
||||
}
|
||||
if (URES_INDEX_POOL_CHECKSUM < fIndexLength) {
|
||||
if (fIsPoolBundle) {
|
||||
|
@ -944,10 +915,10 @@ void SRBRoot::write(const char *outputDir, const char *outputPkg,
|
|||
fKeysTop-fKeysBottom);
|
||||
|
||||
/* write the v2 UTF-16 strings, URES_TABLE16 and URES_ARRAY16 */
|
||||
udata_writeBlock(mem, f16BitUnits, f16BitUnitsLength*2);
|
||||
udata_writeBlock(mem, f16BitUnits.getBuffer(), f16BitUnits.length()*2);
|
||||
|
||||
/* write all of the bundle contents: the root item and its children */
|
||||
byteOffset = fKeysTop + f16BitUnitsLength * 2;
|
||||
byteOffset = fKeysTop + f16BitUnits.length() * 2;
|
||||
fRoot->write(mem, &byteOffset, this, errorCode);
|
||||
assert(byteOffset == top);
|
||||
|
||||
|
@ -1015,11 +986,11 @@ struct SResource *bin_open(struct SRBRoot *bundle, const char *tag, uint32_t len
|
|||
}
|
||||
|
||||
SRBRoot::SRBRoot(const UString *comment, UBool isPoolBundle, UErrorCode &errorCode)
|
||||
: fRoot(NULL), fLocale(NULL), fIndexLength(0), fMaxTableLength(0), noFallback(FALSE),
|
||||
: fRoot(NULL), fLocale(NULL), fIndexLength(0), fMaxTableLength(0), fNoFallback(FALSE),
|
||||
fStringsForm(0), fIsPoolBundle(FALSE),
|
||||
fKeys(NULL), fKeyMap(NULL),
|
||||
fKeysBottom(0), fKeysTop(0), fKeysCapacity(0), fKeysCount(0), fLocalKeyLimit(0),
|
||||
f16BitUnits(NULL), f16BitUnitsCapacity(0), f16BitUnitsLength(0),
|
||||
f16BitUnits(), f16BitStringsLength(0),
|
||||
fPoolBundleKeys(NULL), fPoolBundleKeysLength(0), fPoolBundleKeysCount(0),
|
||||
fPoolChecksum(0) {
|
||||
if (U_FAILURE(errorCode)) {
|
||||
|
@ -1067,7 +1038,6 @@ SRBRoot::~SRBRoot() {
|
|||
uprv_free(fLocale);
|
||||
uprv_free(fKeys);
|
||||
uprv_free(fKeyMap);
|
||||
uprv_free(f16BitUnits);
|
||||
}
|
||||
|
||||
/* Misc Functions */
|
||||
|
@ -1369,35 +1339,31 @@ compareStringLengths(const void * /*context*/, const void *l, const void *r) {
|
|||
return left->length() - right->length();
|
||||
}
|
||||
|
||||
int32_t
|
||||
StringResource::writeUTF16v2(SRBRoot *bundle, int32_t utf16Length) {
|
||||
void
|
||||
StringResource::writeUTF16v2(UnicodeString &dest) {
|
||||
int32_t len = length();
|
||||
fRes = URES_MAKE_RESOURCE(URES_STRING_V2, utf16Length);
|
||||
fRes = URES_MAKE_RESOURCE(URES_STRING_V2, dest.length());
|
||||
fWritten = TRUE;
|
||||
switch(fNumCharsForLength) {
|
||||
case 0:
|
||||
break;
|
||||
case 1:
|
||||
bundle->f16BitUnits[utf16Length++] = (uint16_t)(0xdc00 + len);
|
||||
dest.append((UChar)(0xdc00 + len));
|
||||
break;
|
||||
case 2:
|
||||
bundle->f16BitUnits[utf16Length] = (uint16_t)(0xdfef + (len >> 16));
|
||||
bundle->f16BitUnits[utf16Length + 1] = (uint16_t)len;
|
||||
utf16Length += 2;
|
||||
dest.append((UChar)(0xdfef + (len >> 16)));
|
||||
dest.append((UChar)len);
|
||||
break;
|
||||
case 3:
|
||||
bundle->f16BitUnits[utf16Length] = 0xdfff;
|
||||
bundle->f16BitUnits[utf16Length + 1] = (uint16_t)(len >> 16);
|
||||
bundle->f16BitUnits[utf16Length + 2] = (uint16_t)len;
|
||||
utf16Length += 3;
|
||||
dest.append((UChar)0xdfff);
|
||||
dest.append((UChar)(len >> 16));
|
||||
dest.append((UChar)len);
|
||||
break;
|
||||
default:
|
||||
break; /* will not occur */
|
||||
}
|
||||
// u_memcpy note: Type of bundle->f16BitUnits is (uint16_t *). u_memcpy wants (UChar *).
|
||||
// On Windows, these are different, UChar is typedefed to wchar_t.
|
||||
u_memcpy((UChar *)(bundle->f16BitUnits + utf16Length), getBuffer(), len + 1);
|
||||
return utf16Length + len + 1;
|
||||
dest.append(fString);
|
||||
dest.append((UChar)0);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -1415,37 +1381,23 @@ SRBRoot::compactStrings(UErrorCode &errorCode) {
|
|||
}
|
||||
switch(fStringsForm) {
|
||||
case STRINGS_UTF16_V2:
|
||||
if (f16BitUnitsLength > 0) {
|
||||
StringResource **array;
|
||||
if (f16BitStringsLength > 0) {
|
||||
int32_t count = uhash_count(stringSet);
|
||||
int32_t i, pos;
|
||||
/*
|
||||
* Allocate enough space for the initial NUL and the UTF-16 v2 strings,
|
||||
* and some extra for URES_TABLE16 and URES_ARRAY16 values.
|
||||
* Round down to an even number.
|
||||
*/
|
||||
int32_t utf16Length = (f16BitUnitsLength + 20000) & ~1;
|
||||
f16BitUnits = (uint16_t *)uprv_malloc(utf16Length * U_SIZEOF_UCHAR);
|
||||
// TODO: LocalArray
|
||||
array = (StringResource **)uprv_malloc(count * sizeof(StringResource **));
|
||||
if (f16BitUnits == NULL || array == NULL) {
|
||||
uprv_free(f16BitUnits);
|
||||
f16BitUnits = NULL;
|
||||
uprv_free(array);
|
||||
LocalArray<StringResource *> array(new StringResource *[count], errorCode);
|
||||
if (array.isNull()) {
|
||||
uhash_close(stringSet);
|
||||
errorCode = U_MEMORY_ALLOCATION_ERROR;
|
||||
return;
|
||||
}
|
||||
f16BitUnitsCapacity = utf16Length;
|
||||
/* insert the initial NUL */
|
||||
f16BitUnits[0] = 0;
|
||||
utf16Length = 1;
|
||||
++f16BitUnitsLength;
|
||||
f16BitUnits.append((UChar)0);
|
||||
++f16BitStringsLength;
|
||||
for (pos = UHASH_FIRST, i = 0; i < count; ++i) {
|
||||
array[i] = (StringResource *)uhash_nextElement(stringSet, &pos)->key.pointer;
|
||||
}
|
||||
/* Sort the strings so that each one is immediately followed by all of its suffixes. */
|
||||
uprv_sortArray(array, count, (int32_t)sizeof(struct SResource **),
|
||||
uprv_sortArray(array.getAlias(), count, (int32_t)sizeof(struct SResource **),
|
||||
compareStringSuffixes, NULL, FALSE, &errorCode);
|
||||
/*
|
||||
* Make suffixes point into earlier, longer strings that contain them.
|
||||
|
@ -1493,12 +1445,15 @@ SRBRoot::compactStrings(UErrorCode &errorCode) {
|
|||
* to optimize for URES_TABLE16 and URES_ARRAY16:
|
||||
* Keep as many as possible within reach of 16-bit offsets.
|
||||
*/
|
||||
uprv_sortArray(array, count, (int32_t)sizeof(struct SResource **),
|
||||
uprv_sortArray(array.getAlias(), count, (int32_t)sizeof(struct SResource **),
|
||||
compareStringLengths, NULL, FALSE, &errorCode);
|
||||
if (U_SUCCESS(errorCode)) {
|
||||
/* Write the non-suffix strings. */
|
||||
for (i = 0; i < count && array[i]->fSame == NULL; ++i) {
|
||||
utf16Length = array[i]->writeUTF16v2(this, utf16Length);
|
||||
array[i]->writeUTF16v2(f16BitUnits);
|
||||
}
|
||||
if (f16BitUnits.isBogus()) {
|
||||
errorCode = U_MEMORY_ALLOCATION_ERROR;
|
||||
}
|
||||
/* Write the suffix strings. Make each point to the real string. */
|
||||
for (; i < count; ++i) {
|
||||
|
@ -1509,9 +1464,7 @@ SRBRoot::compactStrings(UErrorCode &errorCode) {
|
|||
res->fWritten = TRUE;
|
||||
}
|
||||
}
|
||||
assert(utf16Length <= f16BitUnitsLength);
|
||||
f16BitUnitsLength = utf16Length;
|
||||
uprv_free(array);
|
||||
assert(f16BitUnits.length() <= f16BitStringsLength);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
|
|
|
@ -51,7 +51,6 @@ struct SRBRoot {
|
|||
void setLocale(UChar *locale, UErrorCode &errorCode);
|
||||
int32_t addTag(const char *tag, UErrorCode &errorCode);
|
||||
|
||||
// TODO: private for SResource
|
||||
const char *getKeyString(int32_t key) const;
|
||||
const char *getKeyBytes(int32_t *pLength) const;
|
||||
|
||||
|
@ -59,8 +58,6 @@ struct SRBRoot {
|
|||
|
||||
void compactKeys(UErrorCode &errorCode);
|
||||
|
||||
// TODO: private for some subclasses of SResource
|
||||
uint16_t *reserve16BitUnits(int32_t length, UErrorCode &errorCode);
|
||||
int32_t mapKey(int32_t oldpos) const;
|
||||
uint16_t makeKey16(int32_t key) const;
|
||||
|
||||
|
@ -74,7 +71,7 @@ public:
|
|||
char *fLocale;
|
||||
int32_t fIndexLength;
|
||||
int32_t fMaxTableLength;
|
||||
UBool noFallback; /* see URES_ATT_NO_FALLBACK */
|
||||
UBool fNoFallback; /* see URES_ATT_NO_FALLBACK */
|
||||
int8_t fStringsForm; /* default STRINGS_UTF16_V1 */
|
||||
UBool fIsPoolBundle;
|
||||
|
||||
|
@ -85,10 +82,8 @@ public:
|
|||
int32_t fKeysCount;
|
||||
int32_t fLocalKeyLimit; /* key offset < limit fits into URES_TABLE */
|
||||
|
||||
// TODO: UnicodeString
|
||||
uint16_t *f16BitUnits;
|
||||
int32_t f16BitUnitsCapacity;
|
||||
int32_t f16BitUnitsLength;
|
||||
icu::UnicodeString f16BitUnits;
|
||||
int32_t f16BitStringsLength;
|
||||
|
||||
const char *fPoolBundleKeys;
|
||||
int32_t fPoolBundleKeysLength;
|
||||
|
@ -280,7 +275,7 @@ public:
|
|||
virtual void handlePreflightStrings(SRBRoot *bundle, UHashtable *stringSet, UErrorCode &errorCode);
|
||||
virtual void handleWrite16(SRBRoot *bundle, UErrorCode &errorCode);
|
||||
|
||||
int32_t writeUTF16v2(SRBRoot *bundle, int32_t utf16Length);
|
||||
void writeUTF16v2(icu::UnicodeString &dest);
|
||||
|
||||
StringResource *fSame; // used for duplicates
|
||||
int32_t fSuffixOffset; // this string is a suffix of fSame at this offset
|
||||
|
|
Loading…
Add table
Reference in a new issue