ICU-6208 Refactor collation initialization code so that ucol_openBinary works in more conditions.

X-SVN-Rev: 23558
This commit is contained in:
George Rhoten 2008-03-12 06:24:36 +00:00
parent adb20088d3
commit 4162dd185d
3 changed files with 118 additions and 111 deletions

View file

@ -42,6 +42,7 @@ typedef enum ECleanupI18NType {
UCLN_I18N_USEARCH,
UCLN_I18N_COLLATOR,
UCLN_I18N_UCOL,
UCLN_I18N_UCOL_RES,
UCLN_I18N_UCOL_BLD,
UCLN_I18N_CSDET,
UCLN_I18N_COUNT /* This must be last */

View file

@ -54,13 +54,6 @@ U_NAMESPACE_USE
#define ZERO_CC_LIMIT_ 0xC0
// static UCA. There is only one. Collators don't use it.
// It is referenced only in ucol_initUCA and ucol_cleanup
static UCollator* _staticUCA = NULL;
// static pointer to udata memory. Inited in ucol_initUCA
// used for cleanup in ucol_cleanup
static UDataMemory* UCA_DATA_MEM = NULL;
// this is static pointer to the normalizer fcdTrieIndex
// it is always the same between calls to u_cleanup
// and therefore writing to it is not synchronized.
@ -77,35 +70,12 @@ static const int32_t maxImplicitPrimary = 0xE4;
U_CDECL_BEGIN
static UBool U_CALLCONV
isAcceptableUCA(void * /*context*/,
const char * /*type*/, const char * /*name*/,
const UDataInfo *pInfo){
/* context, type & name are intentionally not used */
if( pInfo->size>=20 &&
pInfo->isBigEndian==U_IS_BIG_ENDIAN &&
pInfo->charsetFamily==U_CHARSET_FAMILY &&
pInfo->dataFormat[0]==UCA_DATA_FORMAT_0 && /* dataFormat="UCol" */
pInfo->dataFormat[1]==UCA_DATA_FORMAT_1 &&
pInfo->dataFormat[2]==UCA_DATA_FORMAT_2 &&
pInfo->dataFormat[3]==UCA_DATA_FORMAT_3 &&
pInfo->formatVersion[0]==UCA_FORMAT_VERSION_0 &&
pInfo->formatVersion[1]>=UCA_FORMAT_VERSION_1// &&
//pInfo->formatVersion[1]==UCA_FORMAT_VERSION_1 &&
//pInfo->formatVersion[2]==UCA_FORMAT_VERSION_2 && // Too harsh
//pInfo->formatVersion[3]==UCA_FORMAT_VERSION_3 && // Too harsh
) {
UVersionInfo UCDVersion;
u_getUnicodeVersion(UCDVersion);
return (UBool)(pInfo->dataVersion[0]==UCDVersion[0]
&& pInfo->dataVersion[1]==UCDVersion[1]);
//&& pInfo->dataVersion[2]==ucaDataInfo.dataVersion[2]
//&& pInfo->dataVersion[3]==ucaDataInfo.dataVersion[3]);
} else {
return FALSE;
}
ucol_cleanup(void)
{
fcdTrieIndex = NULL;
return TRUE;
}
static int32_t U_CALLCONV
_getFoldingOffset(uint32_t data) {
return (int32_t)(data&0xFFFFFF);
@ -114,8 +84,9 @@ _getFoldingOffset(uint32_t data) {
U_CDECL_END
static
inline void IInit_collIterate(const UCollator *collator, const UChar *sourceString,
int32_t sourceLen, collIterate *s) {
inline void IInit_collIterate(const UCollator *collator, const UChar *sourceString,
int32_t sourceLen, collIterate *s)
{
(s)->string = (s)->pos = (UChar *)(sourceString);
(s)->origFlags = 0;
(s)->flags = 0;
@ -774,6 +745,13 @@ UCollator* ucol_initCollator(const UCATableHeader *image, UCollator *fillIn, con
result->freeOnClose = FALSE;
}
// init FCD data
if (fcdTrieIndex == NULL) {
// The result is constant, until the library is reloaded.
fcdTrieIndex = unorm_getFCDTrie(status);
ucln_i18n_registerCleanup(UCLN_I18N_UCOL, ucol_cleanup);
}
result->image = image;
result->mapping.getFoldingOffset = _getFoldingOffset;
const uint8_t *mapping = (uint8_t*)result->image+result->image->mappingPosition;
@ -1197,73 +1175,6 @@ uprv_uca_initImplicitConstants(UErrorCode *status) {
initImplicitConstants(minImplicitPrimary, maxImplicitPrimary, 0x04, 0xFE, 1, 1, status);
}
U_CDECL_BEGIN
static UBool U_CALLCONV
ucol_cleanup(void)
{
if (UCA_DATA_MEM) {
udata_close(UCA_DATA_MEM);
UCA_DATA_MEM = NULL;
}
if (_staticUCA) {
ucol_close(_staticUCA);
_staticUCA = NULL;
}
fcdTrieIndex = NULL;
return TRUE;
}
U_CDECL_END
/* do not close UCA returned by ucol_initUCA! */
UCollator *
ucol_initUCA(UErrorCode *status) {
if(U_FAILURE(*status)) {
return NULL;
}
UBool needsInit;
UMTX_CHECK(NULL, (_staticUCA == NULL), needsInit);
if(needsInit) {
// init FCD data
if (fcdTrieIndex == NULL) {
// The result is constant, until the library is reloaded.
fcdTrieIndex = unorm_getFCDTrie(status);
ucln_i18n_registerCleanup(UCLN_I18N_UCOL, ucol_cleanup);
}
UDataMemory *result = udata_openChoice(NULL, UCA_DATA_TYPE, UCA_DATA_NAME, isAcceptableUCA, NULL, status);
if(U_SUCCESS(*status)){
UCollator *newUCA = ucol_initCollator((const UCATableHeader *)udata_getMemory(result), NULL, NULL, status);
if(U_SUCCESS(*status)){
umtx_lock(NULL);
if(_staticUCA == NULL) {
_staticUCA = newUCA;
newUCA = NULL;
UCA_DATA_MEM = result;
result = NULL;
}
umtx_unlock(NULL);
ucln_i18n_registerCleanup(UCLN_I18N_UCOL, ucol_cleanup);
if(newUCA != NULL) {
ucol_close(newUCA);
udata_close(result);
}
// Initalize variables for implicit generation
uprv_uca_initImplicitConstants(status);
}else{
ucol_close(newUCA);
udata_close(result);
}
}
else {
udata_close(result);
}
}
return _staticUCA;
}
/* collIterNormalize Incremental Normalization happens here. */
/* pick up the range of chars identifed by FCD, */
@ -8515,12 +8426,5 @@ ucol_getUCAVersion(const UCollator* coll, UVersionInfo info) {
}
}
U_CAPI void U_EXPORT2
ucol_forgetUCA(void)
{
_staticUCA = NULL;
UCA_DATA_MEM = NULL;
}
#endif /* #if !UCONFIG_NO_COLLATION */

View file

@ -38,6 +38,7 @@
#include "ustr_imp.h"
#include "cstring.h"
#include "umutex.h"
#include "ucln_in.h"
#include "ustrenum.h"
#include "putilimp.h"
#include "utracimp.h"
@ -45,6 +46,108 @@
U_NAMESPACE_USE
// static UCA. There is only one. Collators don't use it.
// It is referenced only in ucol_initUCA and ucol_cleanup
static UCollator* _staticUCA = NULL;
// static pointer to udata memory. Inited in ucol_initUCA
// used for cleanup in ucol_cleanup
static UDataMemory* UCA_DATA_MEM = NULL;
U_CDECL_BEGIN
static UBool U_CALLCONV
ucol_res_cleanup(void)
{
if (UCA_DATA_MEM) {
udata_close(UCA_DATA_MEM);
UCA_DATA_MEM = NULL;
}
if (_staticUCA) {
ucol_close(_staticUCA);
_staticUCA = NULL;
}
return TRUE;
}
static UBool U_CALLCONV
isAcceptableUCA(void * /*context*/,
const char * /*type*/, const char * /*name*/,
const UDataInfo *pInfo){
/* context, type & name are intentionally not used */
if( pInfo->size>=20 &&
pInfo->isBigEndian==U_IS_BIG_ENDIAN &&
pInfo->charsetFamily==U_CHARSET_FAMILY &&
pInfo->dataFormat[0]==UCA_DATA_FORMAT_0 && /* dataFormat="UCol" */
pInfo->dataFormat[1]==UCA_DATA_FORMAT_1 &&
pInfo->dataFormat[2]==UCA_DATA_FORMAT_2 &&
pInfo->dataFormat[3]==UCA_DATA_FORMAT_3 &&
pInfo->formatVersion[0]==UCA_FORMAT_VERSION_0 &&
pInfo->formatVersion[1]>=UCA_FORMAT_VERSION_1// &&
//pInfo->formatVersion[1]==UCA_FORMAT_VERSION_1 &&
//pInfo->formatVersion[2]==UCA_FORMAT_VERSION_2 && // Too harsh
//pInfo->formatVersion[3]==UCA_FORMAT_VERSION_3 && // Too harsh
) {
UVersionInfo UCDVersion;
u_getUnicodeVersion(UCDVersion);
return (UBool)(pInfo->dataVersion[0]==UCDVersion[0]
&& pInfo->dataVersion[1]==UCDVersion[1]);
//&& pInfo->dataVersion[2]==ucaDataInfo.dataVersion[2]
//&& pInfo->dataVersion[3]==ucaDataInfo.dataVersion[3]);
} else {
return FALSE;
}
}
U_CDECL_END
/* do not close UCA returned by ucol_initUCA! */
UCollator *
ucol_initUCA(UErrorCode *status) {
if(U_FAILURE(*status)) {
return NULL;
}
UBool needsInit;
UMTX_CHECK(NULL, (_staticUCA == NULL), needsInit);
if(needsInit) {
UDataMemory *result = udata_openChoice(NULL, UCA_DATA_TYPE, UCA_DATA_NAME, isAcceptableUCA, NULL, status);
if(U_SUCCESS(*status)){
UCollator *newUCA = ucol_initCollator((const UCATableHeader *)udata_getMemory(result), NULL, NULL, status);
if(U_SUCCESS(*status)){
umtx_lock(NULL);
if(_staticUCA == NULL) {
_staticUCA = newUCA;
newUCA = NULL;
UCA_DATA_MEM = result;
result = NULL;
}
umtx_unlock(NULL);
ucln_i18n_registerCleanup(UCLN_I18N_UCOL_RES, ucol_res_cleanup);
if(newUCA != NULL) {
ucol_close(newUCA);
udata_close(result);
}
// Initalize variables for implicit generation
uprv_uca_initImplicitConstants(status);
}else{
ucol_close(newUCA);
udata_close(result);
}
}
else {
udata_close(result);
}
}
return _staticUCA;
}
U_CAPI void U_EXPORT2
ucol_forgetUCA(void)
{
_staticUCA = NULL;
UCA_DATA_MEM = NULL;
}
/****************************************************************************/
/* Following are the open/close functions */
/* */
@ -54,7 +157,6 @@ tryOpeningFromRules(UResourceBundle *collElem, UErrorCode *status) {
int32_t rulesLen = 0;
const UChar *rules = ures_getStringByKey(collElem, "Sequence", &rulesLen, status);
return ucol_openRules(rules, rulesLen, UCOL_DEFAULT, UCOL_DEFAULT, NULL, status);
}