mirror of
https://github.com/unicode-org/icu.git
synced 2025-04-08 06:53:45 +00:00
ICU-5190 Fix ucol_safeClone to properly clone a collator.
X-SVN-Rev: 19629
This commit is contained in:
parent
d2ec6dee38
commit
a4663ad545
2 changed files with 124 additions and 92 deletions
|
@ -351,7 +351,7 @@ ucol_initFromBinary(const uint8_t *bin, int32_t length,
|
|||
UErrorCode *status)
|
||||
{
|
||||
UCollator *result = fillIn;
|
||||
if(U_FAILURE(*status)){
|
||||
if(U_FAILURE(*status)) {
|
||||
return NULL;
|
||||
}
|
||||
/*
|
||||
|
@ -371,14 +371,16 @@ ucol_initFromBinary(const uint8_t *bin, int32_t length,
|
|||
{
|
||||
*status = U_COLLATOR_VERSION_MISMATCH;
|
||||
return NULL;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
if((uint32_t)length > (paddedsize(sizeof(UCATableHeader)) + paddedsize(sizeof(UColOptionSet)))) {
|
||||
result = ucol_initCollator((const UCATableHeader *)bin, result, base, status);
|
||||
if(U_FAILURE(*status)){
|
||||
return NULL;
|
||||
}
|
||||
result->hasRealData = TRUE;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
if(base) {
|
||||
result = ucol_initCollator(base->image, result, base, status);
|
||||
ucol_setOptionsFromHeader(result, (UColOptionSet *)(bin+((const UCATableHeader *)bin)->options), status);
|
||||
|
@ -386,7 +388,8 @@ ucol_initFromBinary(const uint8_t *bin, int32_t length,
|
|||
return NULL;
|
||||
}
|
||||
result->hasRealData = FALSE;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
*status = U_USELESS_COLLATOR_ERROR;
|
||||
return NULL;
|
||||
}
|
||||
|
@ -411,6 +414,90 @@ ucol_openBinary(const uint8_t *bin, int32_t length,
|
|||
return ucol_initFromBinary(bin, length, base, NULL, status);
|
||||
}
|
||||
|
||||
U_CAPI UCollator* U_EXPORT2
|
||||
ucol_safeClone(const UCollator *coll, void *stackBuffer, int32_t * pBufferSize, UErrorCode *status)
|
||||
{
|
||||
UCollator * localCollator;
|
||||
int32_t bufferSizeNeeded = (int32_t)sizeof(UCollator);
|
||||
char *stackBufferChars = (char *)stackBuffer;
|
||||
int32_t imageSize = 0;
|
||||
int32_t rulesSize = 0;
|
||||
int32_t rulesPadding = 0;
|
||||
uint8_t *image;
|
||||
UChar *rules;
|
||||
|
||||
if (status == NULL || U_FAILURE(*status)){
|
||||
return 0;
|
||||
}
|
||||
if ((stackBuffer && !pBufferSize) || !coll){
|
||||
*status = U_ILLEGAL_ARGUMENT_ERROR;
|
||||
return 0;
|
||||
}
|
||||
/* Pointers on 64-bit platforms need to be aligned
|
||||
* on a 64-bit boundry in memory.
|
||||
*/
|
||||
if (U_ALIGNMENT_OFFSET(stackBuffer) != 0) {
|
||||
int32_t offsetUp = (int32_t)U_ALIGNMENT_OFFSET_UP(stackBufferChars);
|
||||
*pBufferSize -= offsetUp;
|
||||
stackBufferChars += offsetUp;
|
||||
}
|
||||
stackBuffer = (void *)stackBufferChars;
|
||||
|
||||
if (!coll->freeImageOnClose) {
|
||||
UErrorCode tempStatus = U_ZERO_ERROR;
|
||||
imageSize = ucol_cloneBinary(coll, NULL, 0, &tempStatus);
|
||||
}
|
||||
if (coll->rules && coll->freeRulesOnClose) {
|
||||
rulesSize = (int32_t)(coll->rulesLength + 1)*sizeof(UChar);
|
||||
rulesPadding = (int32_t)(bufferSizeNeeded % sizeof(UChar));
|
||||
bufferSizeNeeded += rulesSize + rulesPadding;
|
||||
}
|
||||
if (stackBuffer && *pBufferSize <= 0){ /* 'preflighting' request - set needed size into *pBufferSize */
|
||||
*pBufferSize = bufferSizeNeeded;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!stackBuffer || *pBufferSize < bufferSizeNeeded) {
|
||||
/* allocate one here...*/
|
||||
stackBufferChars = (char *)uprv_malloc(bufferSizeNeeded);
|
||||
if (U_SUCCESS(*status)) {
|
||||
*status = U_SAFECLONE_ALLOCATED_WARNING;
|
||||
}
|
||||
}
|
||||
localCollator = (UCollator *)stackBufferChars;
|
||||
rules = (UChar *)(stackBufferChars + sizeof(UCollator) + rulesPadding);
|
||||
if (imageSize > 0) {
|
||||
image = (uint8_t *)uprv_malloc(imageSize);
|
||||
ucol_cloneBinary(coll, image, imageSize, status);
|
||||
}
|
||||
else {
|
||||
image = (uint8_t *)coll->image;
|
||||
}
|
||||
localCollator = ucol_initFromBinary(image, imageSize, coll->UCA, localCollator, status);
|
||||
|
||||
if (coll->rules) {
|
||||
if (coll->freeRulesOnClose) {
|
||||
localCollator->rules = u_strcpy(rules, coll->rules);
|
||||
//bufferEnd += rulesSize;
|
||||
}
|
||||
else {
|
||||
localCollator->rules = coll->rules;
|
||||
}
|
||||
localCollator->freeRulesOnClose = FALSE;
|
||||
localCollator->rulesLength = coll->rulesLength;
|
||||
}
|
||||
|
||||
int32_t i;
|
||||
for(i = 0; i < UCOL_ATTRIBUTE_COUNT; i++) {
|
||||
ucol_setAttribute(localCollator, (UColAttribute)i, ucol_getAttribute(coll, (UColAttribute)i, status), status);
|
||||
}
|
||||
localCollator->requestedLocale = NULL; // zero copies of pointers
|
||||
localCollator->validLocale = NULL;
|
||||
localCollator->rb = NULL;
|
||||
localCollator->elements = NULL;
|
||||
return localCollator;
|
||||
}
|
||||
|
||||
U_CAPI void U_EXPORT2
|
||||
ucol_close(UCollator *coll)
|
||||
{
|
||||
|
|
|
@ -108,7 +108,6 @@ ucol_open_internal(const char *loc,
|
|||
collElem = ures_getByKeyWithFallback(collations, keyBuffer, collElem, status);
|
||||
|
||||
UResourceBundle *binary = NULL;
|
||||
UErrorCode binaryStatus = U_ZERO_ERROR;
|
||||
|
||||
if(*status == U_MISSING_RESOURCE_ERROR) { /* We didn't find the tailoring data, we fallback to the UCA */
|
||||
*status = U_USING_DEFAULT_WARNING;
|
||||
|
@ -122,6 +121,9 @@ ucol_open_internal(const char *loc,
|
|||
ures_close(b);
|
||||
result->hasRealData = FALSE;
|
||||
} else if(U_SUCCESS(*status)) {
|
||||
int32_t len = 0;
|
||||
UErrorCode binaryStatus = U_ZERO_ERROR;
|
||||
|
||||
binary = ures_getByKey(collElem, "%%CollationBin", NULL, &binaryStatus);
|
||||
|
||||
if(binaryStatus == U_MISSING_RESOURCE_ERROR) { /* we didn't find the binary image, we should use the rules */
|
||||
|
@ -131,37 +133,42 @@ ucol_open_internal(const char *loc,
|
|||
goto clean;
|
||||
}
|
||||
} else if(U_SUCCESS(*status)) { /* otherwise, we'll pick a collation data that exists */
|
||||
int32_t len = 0;
|
||||
const uint8_t *inData = ures_getBinary(binary, &len, status);
|
||||
UCATableHeader *colData = (UCATableHeader *)inData;
|
||||
if(uprv_memcmp(colData->UCAVersion, UCA->image->UCAVersion, sizeof(UVersionInfo)) != 0 ||
|
||||
uprv_memcmp(colData->UCDVersion, UCA->image->UCDVersion, sizeof(UVersionInfo)) != 0 ||
|
||||
colData->version[0] != UCOL_BUILDER_VERSION) {
|
||||
*status = U_DIFFERENT_UCA_VERSION;
|
||||
result = tryOpeningFromRules(collElem, status);
|
||||
} else {
|
||||
colData->version[0] != UCOL_BUILDER_VERSION)
|
||||
{
|
||||
*status = U_DIFFERENT_UCA_VERSION;
|
||||
result = tryOpeningFromRules(collElem, status);
|
||||
} else {
|
||||
if(U_FAILURE(*status)){
|
||||
goto clean;
|
||||
}
|
||||
if((uint32_t)len > (paddedsize(sizeof(UCATableHeader)) + paddedsize(sizeof(UColOptionSet)))) {
|
||||
result = ucol_initCollator((const UCATableHeader *)inData, result, UCA, status);
|
||||
if(U_FAILURE(*status)){
|
||||
goto clean;
|
||||
}
|
||||
if((uint32_t)len > (paddedsize(sizeof(UCATableHeader)) + paddedsize(sizeof(UColOptionSet)))) {
|
||||
result = ucol_initCollator((const UCATableHeader *)inData, result, UCA, status);
|
||||
if(U_FAILURE(*status)){
|
||||
goto clean;
|
||||
}
|
||||
result->hasRealData = TRUE;
|
||||
} else {
|
||||
result = ucol_initCollator(UCA->image, result, UCA, status);
|
||||
ucol_setOptionsFromHeader(result, (UColOptionSet *)(inData+((const UCATableHeader *)inData)->options), status);
|
||||
if(U_FAILURE(*status)){
|
||||
goto clean;
|
||||
}
|
||||
result->hasRealData = FALSE;
|
||||
result->hasRealData = TRUE;
|
||||
} else {
|
||||
result = ucol_initCollator(UCA->image, result, UCA, status);
|
||||
ucol_setOptionsFromHeader(result, (UColOptionSet *)(inData+((const UCATableHeader *)inData)->options), status);
|
||||
if(U_FAILURE(*status)){
|
||||
goto clean;
|
||||
}
|
||||
result->freeImageOnClose = FALSE;
|
||||
result->hasRealData = FALSE;
|
||||
}
|
||||
result->freeImageOnClose = FALSE;
|
||||
}
|
||||
}
|
||||
result->rb = b;
|
||||
result->elements = collElem;
|
||||
len = 0;
|
||||
binaryStatus = U_ZERO_ERROR;
|
||||
result->rules = ures_getStringByKey(result->elements, "Sequence", &len, &binaryStatus);
|
||||
result->rulesLength = len;
|
||||
result->freeRulesOnClose = FALSE;
|
||||
} else { /* There is another error, and we're just gonna clean up */
|
||||
goto clean;
|
||||
}
|
||||
|
@ -397,23 +404,14 @@ U_CAPI const UChar* U_EXPORT2
|
|||
ucol_getRules( const UCollator *coll,
|
||||
int32_t *length)
|
||||
{
|
||||
if(coll->rules != NULL) {
|
||||
*length = coll->rulesLength;
|
||||
return coll->rules;
|
||||
} else {
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
if(coll->elements != NULL) {
|
||||
if(U_SUCCESS(status)) {
|
||||
/*Semantic const */
|
||||
((UCollator *)coll)->rules = ures_getStringByKey(coll->elements, "Sequence", length, &status);
|
||||
((UCollator *)coll)->rulesLength = *length;
|
||||
((UCollator *)coll)->freeRulesOnClose = FALSE;
|
||||
if(coll->rules != NULL) {
|
||||
*length = coll->rulesLength;
|
||||
return coll->rules;
|
||||
}
|
||||
}
|
||||
*length = 0;
|
||||
return &_NUL;
|
||||
}
|
||||
else {
|
||||
*length = 0;
|
||||
return &_NUL;
|
||||
}
|
||||
}
|
||||
|
||||
U_CAPI UBool U_EXPORT2
|
||||
|
@ -718,57 +716,4 @@ ucol_getTailoredSet(const UCollator *coll, UErrorCode *status)
|
|||
return (USet *)tailored;
|
||||
}
|
||||
|
||||
U_CAPI UCollator* U_EXPORT2
|
||||
ucol_safeClone(const UCollator *coll, void *stackBuffer, int32_t * pBufferSize, UErrorCode *status)
|
||||
{
|
||||
UCollator * localCollator;
|
||||
int32_t bufferSizeNeeded = (int32_t)sizeof(UCollator);
|
||||
char *stackBufferChars = (char *)stackBuffer;
|
||||
|
||||
if (status == NULL || U_FAILURE(*status)){
|
||||
return 0;
|
||||
}
|
||||
if ((stackBuffer && !pBufferSize) || !coll){
|
||||
*status = U_ILLEGAL_ARGUMENT_ERROR;
|
||||
return 0;
|
||||
}
|
||||
/* Pointers on 64-bit platforms need to be aligned
|
||||
* on a 64-bit boundry in memory.
|
||||
*/
|
||||
if (U_ALIGNMENT_OFFSET(stackBuffer) != 0) {
|
||||
int32_t offsetUp = (int32_t)U_ALIGNMENT_OFFSET_UP(stackBufferChars);
|
||||
*pBufferSize -= offsetUp;
|
||||
stackBufferChars += offsetUp;
|
||||
}
|
||||
stackBuffer = (void *)stackBufferChars;
|
||||
|
||||
if (stackBuffer && *pBufferSize <= 0){ /* 'preflighting' request - set needed size into *pBufferSize */
|
||||
*pBufferSize = bufferSizeNeeded;
|
||||
return 0;
|
||||
}
|
||||
if (!stackBuffer || *pBufferSize < bufferSizeNeeded) {
|
||||
/* allocate one here...*/
|
||||
int32_t length;
|
||||
const UChar * rules = ucol_getRules(coll, &length);
|
||||
|
||||
localCollator = ucol_openRules(rules,
|
||||
length,
|
||||
ucol_getAttribute(coll, UCOL_NORMALIZATION_MODE, status),
|
||||
ucol_getStrength(coll),
|
||||
NULL,
|
||||
status);
|
||||
if (U_SUCCESS(*status))
|
||||
{
|
||||
*status = U_SAFECLONE_ALLOCATED_WARNING;
|
||||
}
|
||||
} else {
|
||||
localCollator = (UCollator *)stackBuffer;
|
||||
uprv_memcpy(localCollator, coll, sizeof(UCollator));
|
||||
localCollator->freeOnClose = FALSE;
|
||||
localCollator->requestedLocale = NULL; // zero copies of pointers
|
||||
localCollator->validLocale = NULL;
|
||||
}
|
||||
return localCollator;
|
||||
}
|
||||
|
||||
#endif /* #if !UCONFIG_NO_COLLATION */
|
||||
|
|
Loading…
Add table
Reference in a new issue