ICU-4163 ucol_cloneBinary & ucol_openBinary APIs

X-SVN-Rev: 16637
This commit is contained in:
Vladimir Weinstein 2004-10-27 00:31:04 +00:00
parent 5a5375439d
commit 6f97dd1568
5 changed files with 226 additions and 10 deletions

View file

@ -576,6 +576,8 @@ typedef enum UErrorCode {
U_ENUM_OUT_OF_SYNC_ERROR = 25, /**< UEnumeration out of sync with underlying collection */
U_INVARIANT_CONVERSION_ERROR = 26, /**< Unable to convert a UChar* string to char* with the invariant converter. */
U_INVALID_STATE_ERROR = 27, /**< Requested operation can not be completed with ICU in its current state */
U_COLLATOR_VERSION_MISMATCH = 28, /**< Collator version is not compatible with the base version */
U_USELESS_COLLATOR_ERROR = 29, /**< Collator is options only and no base is specified */
U_STANDARD_ERROR_LIMIT, /**< This must always be the last value to indicate the limit for standard errors */
/*

View file

@ -98,7 +98,9 @@ _uErrorName[U_STANDARD_ERROR_LIMIT]={
"U_TOO_MANY_ALIASES_ERROR",
"U_ENUM_OUT_OF_SYNC_ERROR",
"U_INVARIANT_CONVERSION_ERROR",
"U_INVALID_STATE_ERROR"
"U_INVALID_STATE_ERROR",
"U_COLLATOR_VERSION_MISMATCH",
"U_USELESS_COLLATOR_ERROR"
};
static const char * const
_uFmtErrorName[U_FMT_PARSE_ERROR_LIMIT - U_FMT_PARSE_ERROR_START] = {

View file

@ -1,4 +1,4 @@
/*
/*
*******************************************************************************
* Copyright (C) 1996-2004, International Business Machines
* Corporation and others. All Rights Reserved.
@ -491,6 +491,7 @@ clean:
return result;
}
U_CAPI void U_EXPORT2
ucol_setReqValidLocales(UCollator *coll, char *requestedLocaleToAdopt, char *validLocaleToAdopt)
{
@ -1730,7 +1731,7 @@ inline uint32_t ucol_IGetNextCE(const UCollator *coll, collIterate *collationSou
if(order > UCOL_NOT_FOUND) { /* if a CE is special */
order = ucol_prv_getSpecialCE(coll, ch, order, collationSource, status); /* and try to get the special CE */
}
if(order == UCOL_NOT_FOUND) { /* We couldn't find a good CE in the tailoring */
if(order == UCOL_NOT_FOUND && coll->UCA) { /* We couldn't find a good CE in the tailoring */
/* if we got here, the codepoint MUST be over 0xFF - so we look directly in the trie */
order = UTRIE_GET32_FROM_LEAD(coll->UCA->mapping, ch);
@ -2140,10 +2141,12 @@ inline uint32_t ucol_IGetPrevCE(const UCollator *coll, collIterate *data,
}
else {
/*result = ucmpe32_get(UCA->mapping, ch);*/
if(coll->UCA) {
result = UTRIE_GET32_FROM_LEAD(coll->UCA->mapping, ch);
}
}
if (result > UCOL_NOT_FOUND) {
if (result > UCOL_NOT_FOUND && coll->UCA) {
result = ucol_prv_getSpecialPrevCE(coll->UCA, ch, result, data, status);
}
}
@ -6999,7 +7002,7 @@ ucol_setUpLatinOne(UCollator *coll, UErrorCode *status) {
CE = coll->latinOneMapping[ch];
} else {
CE = UTRIE_GET32_FROM_LEAD(coll->mapping, ch);
if(CE == UCOL_NOT_FOUND) {
if(CE == UCOL_NOT_FOUND && coll->UCA) {
CE = UTRIE_GET32_FROM_LEAD(coll->UCA->mapping, ch);
}
}
@ -7634,7 +7637,11 @@ ucol_getVersion(const UCollator* coll,
versionInfo[0] = (uint8_t)(cmbVersion>>8);
versionInfo[1] = (uint8_t)cmbVersion;
versionInfo[2] = coll->image->version[1];
versionInfo[3] = coll->UCA->image->UCAVersion[0];
if(coll->UCA) {
versionInfo[3] = coll->UCA->image->UCAVersion[0];
} else {
versionInfo[3] = 0;
}
}
@ -7648,7 +7655,7 @@ ucol_isTailored(const UCollator *coll, const UChar u, UErrorCode *status) {
return FALSE;
} else if(u < 0x100) { /* latin-1 */
CE = coll->latinOneMapping[u];
if(CE == coll->UCA->latinOneMapping[u]) {
if(coll->UCA && CE == coll->UCA->latinOneMapping[u]) {
return FALSE;
}
} else { /* regular */
@ -9116,7 +9123,7 @@ ucol_getTailoredSet(const UCollator *coll, UErrorCode *status)
if(status == NULL || U_FAILURE(*status)) {
return NULL;
}
if(coll == NULL) {
if(coll == NULL || coll->UCA == NULL) {
*status = U_ILLEGAL_ARGUMENT_ERROR;
}
UParseError parseError;
@ -9268,10 +9275,173 @@ returnResult:
U_CAPI void U_EXPORT2
ucol_getUCAVersion(const UCollator* coll, UVersionInfo info) {
if(coll) {
if(coll && coll->UCA) {
uprv_memcpy(info, coll->UCA->image->UCAVersion, sizeof(UVersionInfo));
}
}
U_CAPI int32_t U_EXPORT2
ucol_cloneBinary(const UCollator *coll,
uint8_t *buffer, int32_t capacity,
UErrorCode *status)
{
int32_t length = 0;
if(U_FAILURE(*status)) {
return NULL;
}
if(coll->hasRealData == TRUE) {
length = coll->image->size;
if(length <= capacity) {
uprv_memcpy(buffer, coll->image, length);
}
} else {
length = (int32_t)(paddedsize(sizeof(UCATableHeader))+paddedsize(sizeof(UColOptionSet)));
if(length <= capacity) {
/* build the UCATableHeader with minimal entries */
/* do not copy the header from the UCA file because its values are wrong! */
/* uprv_memcpy(result, UCA->image, sizeof(UCATableHeader)); */
/* reset everything */
uprv_memset(buffer, 0, length);
/* set the tailoring-specific values */
UCATableHeader *myData = (UCATableHeader *)buffer;
myData->size = length;
/* offset for the options, the only part of the data that is present after the header */
myData->options = sizeof(UCATableHeader);
/* need to always set the expansion value for an upper bound of the options */
myData->expansion = myData->options + sizeof(UColOptionSet);
myData->magic = UCOL_HEADER_MAGIC;
myData->isBigEndian = U_IS_BIG_ENDIAN;
myData->charSetFamily = U_CHARSET_FAMILY;
/* copy UCA's version; genrb will override all but the builder version with tailoring data */
uprv_memcpy(myData->version, coll->image->version, sizeof(UVersionInfo));
uprv_memcpy(myData->UCAVersion, coll->image->UCAVersion, sizeof(UVersionInfo));
uprv_memcpy(myData->UCDVersion, coll->image->UCDVersion, sizeof(UVersionInfo));
uprv_memcpy(myData->formatVersion, coll->image->formatVersion, sizeof(UVersionInfo));
myData->jamoSpecial = coll->image->jamoSpecial;
/* copy the collator options */
uprv_memcpy(buffer+paddedsize(sizeof(UCATableHeader)), coll->options, sizeof(UColOptionSet));
}
}
return length;
}
U_CAPI UCollator* U_EXPORT2
ucol_openBinary(const uint8_t *bin, int32_t length,
const UCollator *base,
UErrorCode *status)
{
UCollator *result = NULL;
if(U_FAILURE(*status)){
return NULL;
}
if(base == NULL) {
// we don't support null base yet
*status = U_ILLEGAL_ARGUMENT_ERROR;
return NULL;
}
UCATableHeader *colData = (UCATableHeader *)bin;
// do we want version check here? We're trying to figure out whether collators are compatible
if(uprv_memcmp(colData->UCAVersion, base->image->UCAVersion, sizeof(UVersionInfo)) != 0 ||
uprv_memcmp(colData->UCDVersion, base->image->UCDVersion, sizeof(UVersionInfo)) != 0 ||
colData->version[0] != UCOL_BUILDER_VERSION) {
*status = U_COLLATOR_VERSION_MISMATCH;
return NULL;
} 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 {
if(base) {
result = ucol_initCollator(base->image, result, base, status);
ucol_setOptionsFromHeader(result, (UColOptionSet *)(bin+((const UCATableHeader *)bin)->options), status);
if(U_FAILURE(*status)){
return NULL;
}
result->hasRealData = FALSE;
} else {
*status = U_USELESS_COLLATOR_ERROR;
return NULL;
}
}
result->freeImageOnClose = FALSE;
}
result->validLocale = NULL;
result->requestedLocale = NULL;
result->rules = NULL;
result->rulesLength = 0;
result->freeRulesOnClose = FALSE;
result->rb = NULL;
result->elements = NULL;
return result;
}
U_CAPI UCollator* U_EXPORT2
ucol_openFromImage( const uint8_t *image,
UCollator *coll,
UErrorCode *status)
{
return NULL;
#if 0
if(status == NULL || U_FAILURE(*status)){
return 0;
}
if(image == NULL) {
*status = U_ILLEGAL_ARGUMENT_ERROR;
return 0;
}
ucol_initUCA(status);
if(U_FAILURE(*status)){
return NULL;
}
int32_t len = ((UCATableHeader *)image)->size;
UCATableHeader *table = (UCATableHeader *) uprv_malloc(len);
/* test for NULL */
if (table == NULL) {
*status = U_MEMORY_ALLOCATION_ERROR;
return NULL;
}
uprv_memcpy(table, image, len);
UCollator *result = ucol_initCollator(table,0,status);
if (result != NULL) {
result->freeImageOnClose = TRUE;
result->rules = NULL;
result->rulesLength = 0;
result->freeRulesOnClose = FALSE;
result->rb = NULL;
result->elements = NULL;
result->validLocale = NULL;
result->requestedLocale = NULL;
if(U_SUCCESS(*status)) {
result->dataInfo.dataVersion[0] = UCOL_BUILDER_VERSION;
result->hasRealData = len > paddedsize(sizeof(UCATableHeader)) + paddedsize(sizeof(UColOptionSet));
} else {
ucol_close(result);
result = NULL;
}
} else {
uprv_free(table);
}
return result;
#endif
}
#endif /* #if !UCONFIG_NO_COLLATION */

View file

@ -1138,6 +1138,45 @@ ucol_getUnsafeSet( const UCollator *coll,
USet *unsafe,
UErrorCode *status);
/** Creates a binary image of a collator. This binary image can be stored and
* later used to instantiate a collator using ucol_openBinary.
* This API supports preflighting.
* @param coll Collator
* @param buffer a fill-in buffer to receive the binary image
* @param capacity capacity of the destination buffer
* @param status for catching errors
* @return size of the image
* @see ucol_openBinary
* @draft ICU 3.2
*/
U_DRAFT int32_t U_EXPORT2
ucol_cloneBinary(const UCollator *coll,
uint8_t *buffer, int32_t capacity,
UErrorCode *status);
/** Opens a collator from a collator binary image created using
* ucol_cloneBinary. Binary image used in instantiation of the
* collator remains owned by the user and should stay around for
* the lifetime of the collator. The API also takes a base collator
* which usualy should be UCA.
* @param bin binary image owned by the user and required through the
* lifetime of the collator
* @param length size of the image. If negative, the API will try to
* figure out the length of the image
* @param base fallback collator, usually UCA. Base is required to be
* present through the lifetime of the collator. Currently
* it cannot be NULL.
* @param status for catching errors
* @return newly created collator
* @see ucol_cloneBinary
* @draft ICU 3.2
*/
U_DRAFT UCollator* U_EXPORT2
ucol_openBinary(const uint8_t *bin, int32_t length,
const UCollator *base,
UErrorCode *status);
#endif /* #if !UCONFIG_NO_COLLATION */
#endif

View file

@ -691,7 +691,10 @@ addCollation(struct SResource *result, uint32_t startline, UErrorCode *status)
if (U_SUCCESS(intStatus) && coll != NULL)
{
data = ucol_cloneRuleData(coll, &len, &intStatus);
len = ucol_cloneBinary(coll, NULL, 0, &intStatus);
data = (uint8_t *)uprv_malloc(len);
len = ucol_cloneBinary(coll, data, len, &intStatus);
//data = ucol_cloneRuleData(coll, &len, &intStatus);
/* tailoring rules version */
/* This is wrong! */