mirror of
https://github.com/unicode-org/icu.git
synced 2025-04-06 22:15:31 +00:00
ICU-388 and jb 853: ucnv_safeClone - the guts of the implementation
X-SVN-Rev: 3657
This commit is contained in:
parent
2a17db6667
commit
5479dd7c73
6 changed files with 207 additions and 8 deletions
|
@ -135,6 +135,63 @@ UConverter* ucnv_openCCSID (int32_t codepage,
|
|||
return createConverter (myName, err);
|
||||
}
|
||||
|
||||
/* Creating a temporary stack-based object that can be used in one thread,
|
||||
and created from a converter that is shared across threads.
|
||||
*/
|
||||
|
||||
UConverter *ucnv_safeClone(const UConverter* cnv, void *stackBuffer, int32_t *pBufferSize, UErrorCode *status)
|
||||
{
|
||||
UConverter * localConverter;
|
||||
int32_t bufferSizeNeeded;
|
||||
|
||||
if (status == NULL || U_FAILURE(*status)){
|
||||
return 0;
|
||||
}
|
||||
if (!pBufferSize || !cnv){
|
||||
*status = U_ILLEGAL_ARGUMENT_ERROR;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (cnv->sharedData->impl->safeClone != NULL) {
|
||||
/* call the custom safeClone function for sizing */
|
||||
bufferSizeNeeded = 0;
|
||||
cnv->sharedData->impl->safeClone(cnv, stackBuffer, &bufferSizeNeeded, status);
|
||||
}
|
||||
else
|
||||
{
|
||||
bufferSizeNeeded = sizeof(UConverter);
|
||||
}
|
||||
|
||||
if (*pBufferSize == 0){ /* 'preflighting' request - set needed size into *pBufferSize */
|
||||
*pBufferSize = bufferSizeNeeded;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (*pBufferSize < bufferSizeNeeded || stackBuffer == NULL)
|
||||
{
|
||||
/* allocate one here...*/
|
||||
localConverter = createConverter (ucnv_getName (cnv, status), status);
|
||||
if (U_SUCCESS(*status))
|
||||
{
|
||||
*status = U_SAFECLONE_ALLOCATED_ERROR;
|
||||
}
|
||||
} else {
|
||||
if (cnv->sharedData->impl->safeClone != NULL) {
|
||||
/* call the custom safeClone function */
|
||||
localConverter = cnv->sharedData->impl->safeClone(cnv, stackBuffer, pBufferSize, status);
|
||||
}
|
||||
else
|
||||
{
|
||||
localConverter = (UConverter *)stackBuffer;
|
||||
memcpy(localConverter, cnv, sizeof(UConverter));
|
||||
localConverter->isCopyLocal = TRUE;
|
||||
}
|
||||
}
|
||||
return localConverter;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*Decreases the reference counter in the shared immutable section of the object
|
||||
*and frees the mutable part*/
|
||||
|
||||
|
@ -163,7 +220,7 @@ void ucnv_close (UConverter * converter)
|
|||
};
|
||||
UErrorCode errorCode;
|
||||
|
||||
if (converter == NULL)
|
||||
if (converter == NULL || converter->isCopyLocal)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -313,6 +313,7 @@ static void _ISO2022Close(UConverter *converter);
|
|||
static void _ISO2022Reset(UConverter *converter, UConverterResetChoice choice);
|
||||
static const char* _ISO2022getName(const UConverter* cnv);
|
||||
U_CFUNC void _ISO_2022_WriteSub(UConverterFromUnicodeArgs *args, int32_t offsetIndex, UErrorCode *err) ;
|
||||
U_CFUNC UConverter * _ISO_2022_SafeClone(const UConverter *cnv, void *stackBuffer, int32_t *pBufferSize, UErrorCode *status);
|
||||
/************ protos of functions for setting the initial state *********************/
|
||||
static void setInitialStateToUnicodeJPCN(UConverter* converter,UConverterDataISO2022 *myConverterData);
|
||||
static void setInitialStateFromUnicodeJPCN(UConverter* converter,UConverterDataISO2022 *myConverterData);
|
||||
|
@ -337,7 +338,9 @@ static const UConverterImpl _ISO2022Impl={
|
|||
T_UConverter_getNextUChar_ISO_2022,
|
||||
|
||||
NULL,
|
||||
_ISO2022getName
|
||||
_ISO2022getName,
|
||||
_ISO_2022_WriteSub,
|
||||
_ISO_2022_SafeClone
|
||||
};
|
||||
|
||||
const UConverterStaticData _ISO2022StaticData={
|
||||
|
@ -388,7 +391,8 @@ static const UConverterImpl _ISO2022JPImpl={
|
|||
|
||||
NULL,
|
||||
_ISO2022getName,
|
||||
_ISO_2022_WriteSub
|
||||
_ISO_2022_WriteSub,
|
||||
_ISO_2022_SafeClone
|
||||
};
|
||||
const UConverterStaticData _ISO2022JPStaticData={
|
||||
sizeof(UConverterStaticData),
|
||||
|
@ -436,7 +440,8 @@ static const UConverterImpl _ISO2022KRImpl={
|
|||
|
||||
NULL,
|
||||
_ISO2022getName,
|
||||
_ISO_2022_WriteSub
|
||||
_ISO_2022_WriteSub,
|
||||
_ISO_2022_SafeClone
|
||||
};
|
||||
const UConverterStaticData _ISO2022KRStaticData={
|
||||
sizeof(UConverterStaticData),
|
||||
|
@ -484,8 +489,8 @@ static const UConverterImpl _ISO2022CNImpl={
|
|||
|
||||
NULL,
|
||||
_ISO2022getName,
|
||||
_ISO_2022_WriteSub
|
||||
|
||||
_ISO_2022_WriteSub,
|
||||
_ISO_2022_SafeClone
|
||||
};
|
||||
const UConverterStaticData _ISO2022CNStaticData={
|
||||
sizeof(UConverterStaticData),
|
||||
|
@ -3098,3 +3103,40 @@ _ISO_2022_WriteSub(UConverterFromUnicodeArgs *args, int32_t offsetIndex, UErrorC
|
|||
buffer, (int32_t)(p - buffer),
|
||||
offsetIndex, err);
|
||||
}
|
||||
|
||||
/* structure for SafeClone calculations */
|
||||
struct cloneStruct
|
||||
{
|
||||
UConverter cnv;
|
||||
UConverterDataISO2022 mydata;
|
||||
};
|
||||
|
||||
|
||||
U_CFUNC UConverter *
|
||||
_ISO_2022_SafeClone(
|
||||
const UConverter *cnv,
|
||||
void *stackBuffer,
|
||||
int32_t *pBufferSize,
|
||||
UErrorCode *status)
|
||||
{
|
||||
struct cloneStruct * localClone;
|
||||
int32_t bufferSizeNeeded = sizeof(struct cloneStruct);
|
||||
|
||||
if (U_FAILURE(*status)){
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (*pBufferSize == 0){ /* 'preflighting' request - set needed size into *pBufferSize */
|
||||
*pBufferSize = bufferSizeNeeded;
|
||||
return 0;
|
||||
}
|
||||
|
||||
localClone = (struct cloneStruct *)stackBuffer;
|
||||
memcpy(&localClone->cnv, cnv, sizeof(UConverter));
|
||||
localClone->cnv.isCopyLocal = TRUE;
|
||||
|
||||
memcpy(&localClone->mydata, cnv->extraInfo, sizeof(UConverterDataISO2022));
|
||||
localClone->cnv.extraInfo = &localClone->mydata;
|
||||
|
||||
return &localClone->cnv;
|
||||
}
|
||||
|
|
|
@ -153,6 +153,7 @@ struct UConverter {
|
|||
|
||||
void *fromUContext;
|
||||
void *toUContext;
|
||||
UBool isCopyLocal; /* TRUE if created by safeClone with no allocation or ref count */
|
||||
UConverterSharedData *sharedData; /* Pointer to the shared immutable part of the converter object */
|
||||
|
||||
/*
|
||||
|
|
|
@ -83,6 +83,16 @@ typedef const char * (*UConverterGetName) (const UConverter *cnv);
|
|||
*/
|
||||
typedef void (*UConverterWriteSub) (UConverterFromUnicodeArgs *pArgs, int32_t offsetIndex, UErrorCode *pErrorCode);
|
||||
|
||||
/**
|
||||
* For converter-specific safeClone processing
|
||||
* If this function is not set, then ucnv_safeClone assumes that the converter has no private data that changes
|
||||
* after the converter is done opening.
|
||||
*/
|
||||
typedef UConverter * (*UConverterSafeClone) ( const UConverter *cnv,
|
||||
void *stackBuffer,
|
||||
int32_t *pBufferSize,
|
||||
UErrorCode *status);
|
||||
|
||||
UBool CONVERSION_U_SUCCESS (UErrorCode err);
|
||||
|
||||
void flushInternalUnicodeBuffer (UConverter * _this,
|
||||
|
@ -134,6 +144,7 @@ struct UConverterImpl {
|
|||
UConverterGetStarters getStarters;
|
||||
UConverterGetName getName;
|
||||
UConverterWriteSub writeSub;
|
||||
UConverterSafeClone safeClone;
|
||||
};
|
||||
|
||||
extern const UConverterSharedData
|
||||
|
|
|
@ -56,6 +56,7 @@ static void _HZClose(UConverter *converter);
|
|||
static void _HZReset(UConverter *converter, UConverterResetChoice choice);
|
||||
|
||||
U_CFUNC void _HZ_WriteSub(UConverterFromUnicodeArgs *args, int32_t offsetIndex, UErrorCode *err);
|
||||
U_CFUNC UConverter * _HZ_SafeClone(const UConverter *cnv, void *stackBuffer, int32_t *pBufferSize, UErrorCode *status);
|
||||
|
||||
U_CFUNC void UConverter_toUnicode_HZ_OFFSETS_LOGIC (UConverterToUnicodeArgs *args,
|
||||
UErrorCode *err);
|
||||
|
@ -82,7 +83,8 @@ static UConverterImpl _HZImpl={
|
|||
|
||||
NULL,
|
||||
NULL,
|
||||
_HZ_WriteSub
|
||||
_HZ_WriteSub,
|
||||
_HZ_SafeClone
|
||||
};
|
||||
|
||||
const UConverterStaticData _HZStaticData={
|
||||
|
@ -643,3 +645,42 @@ _HZ_WriteSub(UConverterFromUnicodeArgs *args, int32_t offsetIndex, UErrorCode *e
|
|||
buffer, (int32_t)(p - buffer),
|
||||
offsetIndex, err);
|
||||
}
|
||||
|
||||
/* structure for SafeClone calculations */
|
||||
struct cloneStruct
|
||||
{
|
||||
UConverter cnv;
|
||||
UConverterDataHZ mydata;
|
||||
};
|
||||
|
||||
|
||||
U_CFUNC UConverter *
|
||||
_HZ_SafeClone(
|
||||
const UConverter *cnv,
|
||||
void *stackBuffer,
|
||||
int32_t *pBufferSize,
|
||||
UErrorCode *status)
|
||||
{
|
||||
struct cloneStruct * localClone;
|
||||
int32_t bufferSizeNeeded = sizeof(struct cloneStruct);
|
||||
|
||||
if (U_FAILURE(*status)){
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (*pBufferSize == 0){ /* 'preflighting' request - set needed size into *pBufferSize */
|
||||
*pBufferSize = bufferSizeNeeded;
|
||||
return 0;
|
||||
}
|
||||
|
||||
localClone = (struct cloneStruct *)stackBuffer;
|
||||
memcpy(&localClone->cnv, cnv, sizeof(UConverter));
|
||||
localClone->cnv.isCopyLocal = TRUE;
|
||||
|
||||
memcpy(&localClone->mydata, cnv->extraInfo, sizeof(UConverterDataHZ));
|
||||
localClone->cnv.extraInfo = &localClone->mydata;
|
||||
|
||||
return &localClone->cnv;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -55,6 +55,12 @@ U_CFUNC void
|
|||
_SCSUWriteSub(UConverterFromUnicodeArgs *pArgs,
|
||||
int32_t offsetIndex,
|
||||
UErrorCode *pErrorCode);
|
||||
U_CFUNC UConverter *
|
||||
_SCSUSafeClone(const UConverter *cnv,
|
||||
void *stackBuffer,
|
||||
int32_t *pBufferSize,
|
||||
UErrorCode *status);
|
||||
|
||||
|
||||
/* SCSU definitions --------------------------------------------------------- */
|
||||
|
||||
|
@ -1361,6 +1367,46 @@ _SCSUWriteSub(UConverterFromUnicodeArgs *pArgs,
|
|||
}
|
||||
}
|
||||
|
||||
/* structure for SafeClone calculations */
|
||||
struct cloneStruct
|
||||
{
|
||||
UConverter cnv;
|
||||
SCSUData mydata;
|
||||
};
|
||||
|
||||
U_CFUNC UConverter *
|
||||
_SCSUSafeClone(
|
||||
const UConverter *cnv,
|
||||
void *stackBuffer,
|
||||
int32_t *pBufferSize,
|
||||
UErrorCode *status)
|
||||
{
|
||||
struct cloneStruct * localClone;
|
||||
int32_t bufferSizeNeeded = sizeof(struct cloneStruct);
|
||||
|
||||
if (U_FAILURE(*status)){
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (*pBufferSize == 0){ /* 'preflighting' request - set needed size into *pBufferSize */
|
||||
*pBufferSize = bufferSizeNeeded;
|
||||
return 0;
|
||||
}
|
||||
|
||||
localClone = (struct cloneStruct *)stackBuffer;
|
||||
memcpy(&localClone->cnv, cnv, sizeof(UConverter));
|
||||
localClone->cnv.isCopyLocal = TRUE;
|
||||
|
||||
memcpy(&localClone->mydata, cnv->extraInfo, sizeof(SCSUData));
|
||||
localClone->cnv.extraInfo = &localClone->mydata;
|
||||
|
||||
return &localClone->cnv;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
static const UConverterImpl _SCSUImpl={
|
||||
UCNV_SCSU,
|
||||
|
||||
|
@ -1379,7 +1425,8 @@ static const UConverterImpl _SCSUImpl={
|
|||
|
||||
NULL,
|
||||
_SCSUGetName,
|
||||
_SCSUWriteSub
|
||||
_SCSUWriteSub,
|
||||
_SCSUSafeClone
|
||||
};
|
||||
|
||||
static const UConverterStaticData _SCSUStaticData={
|
||||
|
|
Loading…
Add table
Reference in a new issue