2
******************************************************************************
4
* Copyright (C) 1998-2001, International Business Machines
5
* Corporation and others. All Rights Reserved.
7
******************************************************************************
10
* Implements APIs for the ICU's codeset conversion library;
11
* mostly calls through internal functions;
12
* created by Bertrand A. Damiba
14
* Modification History:
16
* Date Name Description
17
* 04/04/99 helena Fixed internal header inclusion.
18
* 05/09/00 helena Added implementation to handle fallback mappings.
19
* 06/20/2000 helena OS/400 port changes; mostly typecast.
22
#include "unicode/utypes.h"
23
#include "unicode/ustring.h"
24
#include "unicode/ures.h"
25
#include "unicode/ucnv.h"
26
#include "unicode/ucnv_err.h"
38
/* debugging for converters */
40
void UCNV_DEBUG_LOG(char *what, char *who, void *p, int l)
42
static FILE *f = NULL;
45
f = fopen("c:\\UCNV_DEBUG_LOG.txt", "w");
47
fprintf(f, "%-20s %-10s %p@%d\n",
51
# define UCNV_DEBUG_LOG(x,y,z) UCNV_DEBUG_LOG(x,y,z,__LINE__)
53
# define UCNV_DEBUG_LOG(x,y,z)
56
/* size of intermediate and preflighting buffers in ucnv_convert() */
57
#define CHUNK_SIZE 5*1024
59
typedef struct UAmbiguousConverter {
61
const UChar variant5c;
62
} UAmbiguousConverter;
64
static const UAmbiguousConverter ambiguousConverters[]={
65
{ "ibm-942_P120-2000", 0xa5 },
66
{ "ibm-943_P130-2000", 0xa5 },
67
{ "ibm-33722_P120-2000", 0xa5 },
68
{ "ibm-949_P110-2000", 0x20a9 },
69
{ "ibm-1363_P110-2000", 0x20a9 },
70
{ "ISO_2022,locale=ko,version=0", 0x20a9 }
73
U_CAPI const char* U_EXPORT2
74
ucnv_getDefaultName ()
76
return ucnv_io_getDefaultConverterName();
80
ucnv_setDefaultName (const char *converterName)
82
ucnv_io_setDefaultConverterName(converterName);
84
/*Calls through createConverter */
85
U_CAPI UConverter* U_EXPORT2
86
ucnv_open (const char *name,
89
if (err == NULL || U_FAILURE (*err)) {
93
return ucnv_createConverter (name, err);
96
/*Extracts the UChar* to a char* and calls through createConverter */
97
U_CAPI UConverter* U_EXPORT2
98
ucnv_openU (const UChar * name,
101
char asciiName[UCNV_MAX_CONVERTER_NAME_LENGTH];
103
if (U_FAILURE (*err))
106
return ucnv_open (NULL, err);
107
if (u_strlen (name) > UCNV_MAX_CONVERTER_NAME_LENGTH)
109
*err = U_ILLEGAL_ARGUMENT_ERROR;
112
return ucnv_open (u_austrcpy (asciiName, name), err);
115
/*Assumes a $platform-#codepage.$CONVERTER_FILE_EXTENSION scheme and calls
116
*through createConverter*/
117
U_CAPI UConverter* U_EXPORT2
118
ucnv_openCCSID (int32_t codepage,
119
UConverterPlatform platform,
122
char myName[UCNV_MAX_CONVERTER_NAME_LENGTH];
125
if (U_FAILURE (*err))
128
ucnv_copyPlatformString (myName, platform);
129
myNameLen = uprv_strlen(myName);
130
myName[myNameLen++] = '-';
131
myName[myNameLen] = 0;
132
T_CString_integerToString (myName + myNameLen, codepage, 10);
134
return ucnv_createConverter (myName, err);
137
/* Creating a temporary stack-based object that can be used in one thread,
138
and created from a converter that is shared across threads.
141
U_CAPI UConverter* U_EXPORT2
142
ucnv_safeClone(const UConverter* cnv, void *stackBuffer, int32_t *pBufferSize, UErrorCode *status)
144
UConverter * localConverter;
145
int32_t bufferSizeNeeded;
146
char *stackBufferChars = (char *)stackBuffer;
148
if (status == NULL || U_FAILURE(*status)){
151
if (!pBufferSize || !cnv){
152
*status = U_ILLEGAL_ARGUMENT_ERROR;
155
/* Pointers on 64-bit platforms need to be aligned
156
* on a 64-bit boundry in memory.
158
if (U_ALIGNMENT_OFFSET(stackBuffer) != 0) {
159
int32_t offsetUp = (int32_t)U_ALIGNMENT_OFFSET_UP(stackBufferChars);
160
*pBufferSize -= offsetUp;
161
stackBufferChars += offsetUp;
163
stackBuffer = (void *)stackBufferChars;
165
if (cnv->sharedData->impl->safeClone != NULL) {
166
/* call the custom safeClone function for sizing */
167
bufferSizeNeeded = 0;
168
cnv->sharedData->impl->safeClone(cnv, stackBuffer, &bufferSizeNeeded, status);
172
bufferSizeNeeded = sizeof(UConverter);
175
if (*pBufferSize <= 0){ /* 'preflighting' request - set needed size into *pBufferSize */
176
*pBufferSize = bufferSizeNeeded;
180
if (*pBufferSize < bufferSizeNeeded || stackBuffer == NULL)
182
/* allocate one here...*/
183
localConverter = ucnv_createConverter (ucnv_getName (cnv, status), status);
184
if (U_SUCCESS(*status))
186
*status = U_SAFECLONE_ALLOCATED_ERROR;
189
if (cnv->sharedData->impl->safeClone != NULL) {
190
/* call the custom safeClone function */
191
localConverter = cnv->sharedData->impl->safeClone(cnv, stackBuffer, pBufferSize, status);
195
localConverter = (UConverter *)stackBuffer;
196
uprv_memcpy(localConverter, cnv, sizeof(UConverter));
197
localConverter->isCopyLocal = TRUE;
200
return localConverter;
205
/*Decreases the reference counter in the shared immutable section of the object
206
*and frees the mutable part*/
208
U_CAPI void U_EXPORT2
209
ucnv_close (UConverter * converter)
211
/* first, notify the callback functions that the converter is closed */
212
UConverterToUnicodeArgs toUArgs = {
213
sizeof(UConverterToUnicodeArgs),
222
UConverterFromUnicodeArgs fromUArgs = {
223
sizeof(UConverterFromUnicodeArgs),
232
UErrorCode errorCode;
234
if (converter == NULL)
239
toUArgs.converter = fromUArgs.converter = converter;
240
errorCode = U_ZERO_ERROR;
241
converter->fromCharErrorBehaviour(converter->toUContext, &toUArgs, NULL, 0, UCNV_CLOSE, &errorCode);
242
errorCode = U_ZERO_ERROR;
243
converter->fromUCharErrorBehaviour(converter->fromUContext, &fromUArgs, NULL, 0, 0, UCNV_CLOSE, &errorCode);
245
if (converter->sharedData->impl->close != NULL) {
246
converter->sharedData->impl->close(converter);
248
if(!converter->isCopyLocal){
249
if (converter->sharedData->referenceCounter != ~0) {
251
if (converter->sharedData->referenceCounter != 0) {
252
converter->sharedData->referenceCounter--;
256
uprv_free (converter);
261
/*returns a single Name from the list, will return NULL if out of bounds
263
U_CAPI const char* U_EXPORT2
264
ucnv_getAvailableName (int32_t n)
266
if (0 <= n && n <= 0xffff) {
267
UErrorCode err = U_ZERO_ERROR;
268
const char *name = ucnv_io_getAvailableConverter((uint16_t)n, &err);
269
if (U_SUCCESS(err)) {
276
U_CAPI int32_t U_EXPORT2
277
ucnv_countAvailable ()
279
UErrorCode err = U_ZERO_ERROR;
280
return ucnv_io_countAvailableConverters(&err);
283
U_CAPI uint16_t U_EXPORT2
284
ucnv_countAliases(const char *alias, UErrorCode *pErrorCode)
287
return ucnv_io_getAliases(alias, &p, pErrorCode);
291
U_CAPI const char* U_EXPORT2
292
ucnv_getAlias(const char *alias, uint16_t n, UErrorCode *pErrorCode)
294
return ucnv_io_getAlias(alias, n, pErrorCode);
297
U_CAPI void U_EXPORT2
298
ucnv_getAliases(const char *alias, const char **aliases, UErrorCode *pErrorCode)
301
uint16_t count=ucnv_io_getAliases(alias, &p, pErrorCode);
304
/* skip a name, first the canonical converter name */
310
U_CAPI uint16_t U_EXPORT2
311
ucnv_countStandards(void)
313
UErrorCode err = U_ZERO_ERROR;
314
return ucnv_io_countStandards(&err);
317
U_CAPI void U_EXPORT2
318
ucnv_getSubstChars (const UConverter * converter,
323
if (U_FAILURE (*err))
326
if (*len < converter->subCharLen) /*not enough space in subChars */
328
*err = U_INDEX_OUTOFBOUNDS_ERROR;
332
uprv_memcpy (mySubChar, converter->subChar, converter->subCharLen); /*fills in the subchars */
333
*len = converter->subCharLen; /*store # of bytes copied to buffer */
334
uprv_memcpy (mySubChar, converter->subChar, converter->subCharLen); /*fills in the subchars */
335
*len = converter->subCharLen; /*store # of bytes copied to buffer */
338
U_CAPI void U_EXPORT2
339
ucnv_setSubstChars (UConverter * converter,
340
const char *mySubChar,
344
if (U_FAILURE (*err))
347
/*Makes sure that the subChar is within the codepages char length boundaries */
348
if ((len > converter->sharedData->staticData->maxBytesPerChar)
349
|| (len < converter->sharedData->staticData->minBytesPerChar))
351
*err = U_ILLEGAL_ARGUMENT_ERROR;
355
uprv_memcpy (converter->subChar, mySubChar, len); /*copies the subchars */
356
converter->subCharLen = len; /*sets the new len */
359
* There is currently (2001Feb) no separate API to set/get subChar1.
360
* In order to always have subChar written after it is explicitly set,
361
* we set subChar1 to 0.
363
converter->subChar1 = 0;
368
U_CAPI int32_t U_EXPORT2
369
ucnv_getDisplayName(const UConverter *cnv,
370
const char *displayLocale,
371
UChar *displayName, int32_t displayNameCapacity,
372
UErrorCode *pErrorCode) {
377
/* check arguments */
378
if(pErrorCode==NULL || U_FAILURE(*pErrorCode)) {
382
if(cnv==NULL || displayNameCapacity<0 || (displayNameCapacity>0 && displayName==NULL)) {
383
*pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
387
/* open the resource bundle and get the display name string */
388
rb=ures_open(NULL, displayLocale, pErrorCode);
389
if(U_FAILURE(*pErrorCode)) {
393
/* use the internal name as the key */
394
name=ures_getStringByKey(rb, cnv->sharedData->staticData->name, &length, pErrorCode);
397
if(U_SUCCESS(*pErrorCode)) {
398
/* copy the string */
399
u_memcpy(displayName, name, uprv_min(length, displayNameCapacity)*U_SIZEOF_UCHAR);
401
/* convert the internal name into a Unicode string */
402
*pErrorCode=U_ZERO_ERROR;
403
length=uprv_strlen(cnv->sharedData->staticData->name);
404
u_charsToUChars(cnv->sharedData->staticData->name, displayName, uprv_min(length, displayNameCapacity));
406
return u_terminateUChars(displayName, displayNameCapacity, length, pErrorCode);
409
/*resets the internal states of a converter
410
*goal : have the same behaviour than a freshly created converter
412
static void _reset(UConverter *converter, UConverterResetChoice choice) {
413
/* first, notify the callback functions that the converter is reset */
414
UConverterToUnicodeArgs toUArgs = {
415
sizeof(UConverterToUnicodeArgs),
424
UConverterFromUnicodeArgs fromUArgs = {
425
sizeof(UConverterFromUnicodeArgs),
434
UErrorCode errorCode;
436
if(converter == NULL) {
440
toUArgs.converter = fromUArgs.converter = converter;
441
if(choice<=UCNV_RESET_TO_UNICODE) {
442
errorCode = U_ZERO_ERROR;
443
converter->fromCharErrorBehaviour(converter->toUContext, &toUArgs, NULL, 0, UCNV_RESET, &errorCode);
445
if(choice!=UCNV_RESET_TO_UNICODE) {
446
errorCode = U_ZERO_ERROR;
447
converter->fromUCharErrorBehaviour(converter->fromUContext, &fromUArgs, NULL, 0, 0, UCNV_RESET, &errorCode);
450
/* now reset the converter itself */
451
if(choice<=UCNV_RESET_TO_UNICODE) {
452
converter->toUnicodeStatus = converter->sharedData->toUnicodeStatus;
453
converter->UCharErrorBufferLength = 0;
455
if(choice!=UCNV_RESET_TO_UNICODE) {
456
converter->fromUnicodeStatus = 0;
457
converter->charErrorBufferLength = 0;
460
if (converter->sharedData->impl->reset != NULL) {
461
/* call the custom reset function */
462
converter->sharedData->impl->reset(converter, choice);
463
} else if(choice<=UCNV_RESET_TO_UNICODE) {
464
converter->mode = UCNV_SI;
468
U_CAPI void U_EXPORT2
469
ucnv_reset(UConverter *converter)
471
_reset(converter, UCNV_RESET_BOTH);
474
U_CAPI void U_EXPORT2
475
ucnv_resetToUnicode(UConverter *converter)
477
_reset(converter, UCNV_RESET_TO_UNICODE);
480
U_CAPI void U_EXPORT2
481
ucnv_resetFromUnicode(UConverter *converter)
483
_reset(converter, UCNV_RESET_FROM_UNICODE);
486
U_CAPI int8_t U_EXPORT2
487
ucnv_getMaxCharSize (const UConverter * converter)
489
return converter->sharedData->staticData->maxBytesPerChar;
493
U_CAPI int8_t U_EXPORT2
494
ucnv_getMinCharSize (const UConverter * converter)
496
return converter->sharedData->staticData->minBytesPerChar;
499
U_CAPI const char* U_EXPORT2
500
ucnv_getName (const UConverter * converter, UErrorCode * err)
503
if (U_FAILURE (*err))
505
if(converter->sharedData->impl->getName){
506
const char* temp= converter->sharedData->impl->getName(converter);
510
return converter->sharedData->staticData->name;
513
U_CAPI int32_t U_EXPORT2
514
ucnv_getCCSID (const UConverter * converter,
517
if (U_FAILURE (*err))
520
return converter->sharedData->staticData->codepage;
524
U_CAPI UConverterPlatform U_EXPORT2
525
ucnv_getPlatform (const UConverter * converter,
528
if (U_FAILURE (*err))
531
return (UConverterPlatform)converter->sharedData->staticData->platform;
534
U_CAPI void U_EXPORT2
535
ucnv_getToUCallBack (const UConverter * converter,
536
UConverterToUCallback *action,
537
const void **context)
539
*action = converter->fromCharErrorBehaviour;
540
*context = converter->toUContext;
543
U_CAPI void U_EXPORT2
544
ucnv_getFromUCallBack (const UConverter * converter,
545
UConverterFromUCallback *action,
546
const void **context)
548
*action = converter->fromUCharErrorBehaviour;
549
*context = converter->fromUContext;
552
U_CAPI void U_EXPORT2
553
ucnv_setToUCallBack (UConverter * converter,
554
UConverterToUCallback newAction,
555
const void* newContext,
556
UConverterToUCallback *oldAction,
557
const void** oldContext,
560
if (U_FAILURE (*err))
562
if (oldAction) *oldAction = converter->fromCharErrorBehaviour;
563
converter->fromCharErrorBehaviour = newAction;
564
if (oldContext) *oldContext = converter->toUContext;
565
converter->toUContext = newContext;
568
U_CAPI void U_EXPORT2
569
ucnv_setFromUCallBack (UConverter * converter,
570
UConverterFromUCallback newAction,
571
const void* newContext,
572
UConverterFromUCallback *oldAction,
573
const void** oldContext,
576
if (U_FAILURE (*err))
578
if (oldAction) *oldAction = converter->fromUCharErrorBehaviour;
579
converter->fromUCharErrorBehaviour = newAction;
580
if (oldContext) *oldContext = converter->fromUContext;
581
converter->fromUContext = newContext;
584
U_CAPI void U_EXPORT2
585
ucnv_fromUnicode (UConverter * _this,
587
const char *targetLimit,
588
const UChar ** source,
589
const UChar * sourceLimit,
594
UConverterFromUnicodeArgs args;
598
* Check parameters in for all conversions
600
if (err == NULL || U_FAILURE (*err)) {
604
if (_this == NULL || target == NULL || source == NULL) {
605
*err = U_ILLEGAL_ARGUMENT_ERROR;
610
if (targetLimit < t || sourceLimit < *source)
612
*err = U_ILLEGAL_ARGUMENT_ERROR;
617
* Make sure that the target buffer size does not exceed the number range for int32_t
618
* because some functions use the size rather than comparing pointers.
619
* size_t is guaranteed to be unsigned.
621
if((size_t)(targetLimit - t) > (size_t)0x7fffffff && targetLimit > t)
623
targetLimit = t + 0x7fffffff;
627
* Deal with stored carry over data. This is done in the common location
628
* to avoid doing it for each conversion.
630
if (_this->charErrorBufferLength > 0)
632
int32_t myTargetIndex = 0;
634
ucnv_flushInternalCharBuffer (_this,
637
targetLimit - *target,
638
offsets?&offsets:NULL,
640
*target += myTargetIndex;
641
if (U_FAILURE (*err))
645
args.converter = _this;
647
args.offsets = offsets;
648
args.source = *source;
649
args.sourceLimit = sourceLimit;
650
args.target = *target;
651
args.targetLimit = targetLimit;
652
args.size = sizeof(args);
655
if (_this->sharedData->impl->fromUnicodeWithOffsets != NULL)
657
_this->sharedData->impl->fromUnicodeWithOffsets(&args, err);
658
*source = args.source;
659
*target = args.target;
663
/* there is no implementation that sets offsets, set them all to -1 */
664
int32_t i, targetSize = targetLimit - *target;
666
for (i=0; i<targetSize; i++) {
672
/*calls the specific conversion routines */
673
_this->sharedData->impl->fromUnicode(&args, err);
674
*source = args.source;
675
*target = args.target;
680
U_CAPI void U_EXPORT2
681
ucnv_toUnicode (UConverter * _this,
683
const UChar * targetLimit,
685
const char *sourceLimit,
690
UConverterToUnicodeArgs args;
694
* Check parameters in for all conversions
696
if (err == NULL || U_FAILURE (*err)) {
700
if (_this == NULL || target == NULL || source == NULL) {
701
*err = U_ILLEGAL_ARGUMENT_ERROR;
706
if (targetLimit < t || sourceLimit < *source) {
707
*err = U_ILLEGAL_ARGUMENT_ERROR;
712
* Make sure that the target buffer size does not exceed the number range for int32_t
713
* because some functions use the size rather than comparing pointers.
714
* size_t is guaranteed to be unsigned.
716
if((size_t)(targetLimit - t) > (size_t)0x3fffffff && targetLimit > t) {
717
targetLimit = t + 0x3fffffff;
721
* Deal with stored carry over data. This is done in the common location
722
* to avoid doing it for each conversion.
724
if (_this->UCharErrorBufferLength > 0)
726
int32_t myTargetIndex = 0;
728
ucnv_flushInternalUnicodeBuffer (_this,
731
targetLimit - *target,
732
offsets?&offsets:NULL,
734
*target += myTargetIndex;
735
if (U_FAILURE (*err))
739
args.converter = _this;
741
args.offsets = offsets;
742
args.source = (char *) *source;
743
args.sourceLimit = sourceLimit;
744
args.target = *target;
745
args.targetLimit = targetLimit;
746
args.size = sizeof(args);
748
if (_this->sharedData->impl->toUnicodeWithOffsets != NULL) {
749
_this->sharedData->impl->toUnicodeWithOffsets(&args, err);
750
*source = args.source;
751
*target = args.target;
754
/* there is no implementation that sets offsets, set them all to -1 */
755
int32_t i, targetSize = targetLimit - *target;
757
for (i=0; i<targetSize; i++) {
763
/*calls the specific conversion routines */
764
_this->sharedData->impl->toUnicode(&args, err);
766
*source = args.source;
767
*target = args.target;
771
U_CAPI int32_t U_EXPORT2
772
ucnv_fromUChars(UConverter *cnv,
773
char *dest, int32_t destCapacity,
774
const UChar *src, int32_t srcLength,
775
UErrorCode *pErrorCode) {
776
const UChar *srcLimit;
777
char *originalDest, *destLimit;
780
/* check arguments */
781
if(pErrorCode==NULL || U_FAILURE(*pErrorCode)) {
786
destCapacity<0 || (destCapacity>0 && dest==NULL) ||
787
srcLength<-1 || (srcLength!=0 && src==NULL)
789
*pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
794
ucnv_resetFromUnicode(cnv);
797
srcLength=u_strlen(src);
800
srcLimit=src+srcLength;
801
destLimit=dest+destCapacity;
803
/* pin the destination limit to U_MAX_PTR; NULL check is for OS/400 */
804
if(destLimit<dest || (destLimit==NULL && dest!=NULL)) {
805
destLimit=(char *)U_MAX_PTR(dest);
808
/* perform the conversion */
809
ucnv_fromUnicode(cnv, &dest, destLimit, &src, srcLimit, 0, TRUE, pErrorCode);
810
destLength=(int32_t)(dest-originalDest);
812
/* if an overflow occurs, then get the preflighting length */
813
if(*pErrorCode==U_BUFFER_OVERFLOW_ERROR) {
816
destLimit=buffer+sizeof(buffer);
819
*pErrorCode=U_ZERO_ERROR;
820
ucnv_fromUnicode(cnv, &dest, destLimit, &src, srcLimit, 0, TRUE, pErrorCode);
821
destLength+=(int32_t)(dest-buffer);
822
} while(*pErrorCode==U_BUFFER_OVERFLOW_ERROR);
828
return u_terminateChars(originalDest, destCapacity, destLength, pErrorCode);
831
U_CAPI int32_t U_EXPORT2
832
ucnv_toUChars(UConverter *cnv,
833
UChar *dest, int32_t destCapacity,
834
const char *src, int32_t srcLength,
835
UErrorCode *pErrorCode) {
836
const char *srcLimit;
837
UChar *originalDest, *destLimit;
840
/* check arguments */
841
if(pErrorCode==NULL || U_FAILURE(*pErrorCode)) {
846
destCapacity<0 || (destCapacity>0 && dest==NULL) ||
847
srcLength<-1 || (srcLength!=0 && src==NULL))
849
*pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
854
ucnv_resetToUnicode(cnv);
857
srcLength=uprv_strlen(src);
860
srcLimit=src+srcLength;
861
destLimit=dest+destCapacity;
863
/* pin the destination limit to U_MAX_PTR; NULL check is for OS/400 */
864
if(destLimit<dest || (destLimit==NULL && dest!=NULL)) {
865
destLimit=(UChar *)U_MAX_PTR(dest);
868
/* perform the conversion */
869
ucnv_toUnicode(cnv, &dest, destLimit, &src, srcLimit, 0, TRUE, pErrorCode);
870
destLength=(int32_t)(dest-originalDest);
872
/* if an overflow occurs, then get the preflighting length */
873
if(*pErrorCode==U_BUFFER_OVERFLOW_ERROR)
877
destLimit=buffer+sizeof(buffer)/U_SIZEOF_UCHAR;
880
*pErrorCode=U_ZERO_ERROR;
881
ucnv_toUnicode(cnv, &dest, destLimit, &src, srcLimit, 0, TRUE, pErrorCode);
882
destLength+=(int32_t)(dest-buffer);
884
while(*pErrorCode==U_BUFFER_OVERFLOW_ERROR);
890
return u_terminateUChars(originalDest, destCapacity, destLength, pErrorCode);
893
U_CAPI UChar32 U_EXPORT2
894
ucnv_getNextUChar(UConverter * converter,
896
const char *sourceLimit,
899
UConverterToUnicodeArgs args;
902
if(err == NULL || U_FAILURE(*err)) {
906
if(converter == NULL || source == NULL || sourceLimit < *source) {
907
*err = U_ILLEGAL_ARGUMENT_ERROR;
911
/* In case internal data had been stored
912
* we return the first UChar32 in the internal buffer,
913
* and update the internal state accordingly
915
if (converter->UCharErrorBufferLength > 0)
919
UTF_NEXT_CHAR(converter->UCharErrorBuffer, i, sizeof(converter->UCharErrorBuffer), myUChar);
920
/*In this memmove we update the internal buffer by
921
*popping the first character.
922
*Note that in the call itself we decrement
923
*UCharErrorBufferLength
925
uprv_memmove (converter->UCharErrorBuffer,
926
converter->UCharErrorBuffer + i,
927
(converter->UCharErrorBufferLength - i) * sizeof (UChar));
928
converter->UCharErrorBufferLength -= (int8_t)i;
931
/*calls the specific conversion routines */
932
/*as dictated in a code review, avoids a switch statement */
933
args.converter = converter;
936
args.source = *source;
937
args.sourceLimit = sourceLimit;
939
args.targetLimit = NULL;
940
args.size = sizeof(args);
941
if (converter->sharedData->impl->getNextUChar != NULL)
943
ch = converter->sharedData->impl->getNextUChar(&args, err);
945
/* default implementation */
946
ch = ucnv_getNextUCharFromToUImpl(&args, converter->sharedData->impl->toUnicode, FALSE, err);
948
*source = args.source;
952
U_CAPI int32_t U_EXPORT2
953
ucnv_convert(const char *toConverterName, const char *fromConverterName,
954
char *target, int32_t targetSize,
955
const char *source, int32_t sourceSize,
956
UErrorCode *pErrorCode) {
957
UChar pivotBuffer[CHUNK_SIZE];
958
UChar *pivot, *pivot2;
960
UConverter *inConverter, *outConverter;
962
const char *sourceLimit;
963
const char *targetLimit;
964
int32_t targetCapacity=0;
966
if(pErrorCode==NULL || U_FAILURE(*pErrorCode)) {
970
if(sourceSize<0 || targetSize<0 || source==NULL
971
|| (targetSize>0 && target==NULL))
973
*pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
977
/* if there is no input data, we're done */
982
/* create the converters */
983
inConverter=ucnv_open(fromConverterName, pErrorCode);
984
if(U_FAILURE(*pErrorCode)) {
988
outConverter=ucnv_open(toConverterName, pErrorCode);
989
if(U_FAILURE(*pErrorCode)) {
990
ucnv_close(inConverter);
994
/* set up the other variables */
995
sourceLimit=source+sourceSize;
996
pivot=pivot2=pivotBuffer;
1001
/* perform real conversion */
1004
* loops until the input buffer is completely consumed
1005
* or an error is encountered;
1006
* first we convert from inConverter codepage to Unicode
1007
* then from Unicode to outConverter codepage
1009
targetLimit=target+targetSize;
1012
ucnv_toUnicode(inConverter,
1013
&pivot, pivotBuffer+CHUNK_SIZE,
1014
&source, sourceLimit,
1019
/* U_BUFFER_OVERFLOW_ERROR only means that the pivot buffer is full */
1020
if(U_SUCCESS(*pErrorCode) || *pErrorCode==U_BUFFER_OVERFLOW_ERROR) {
1021
*pErrorCode=U_ZERO_ERROR;
1023
ucnv_fromUnicode(outConverter,
1024
&myTarget, targetLimit,
1025
(const UChar **)&pivot2, pivot,
1027
(UBool)(source==sourceLimit),
1030
* If this overflows the real target, then we must stop
1031
* converting and preflight with the loop below.
1034
} while(U_SUCCESS(*pErrorCode) && source!=sourceLimit);
1036
targetCapacity=myTarget-target;
1040
* If the output buffer is exhausted (or we are only "preflighting"), we need to stop writing
1041
* to it but continue the conversion in order to store in targetSize
1042
* the number of bytes that was required.
1044
if(*pErrorCode==U_BUFFER_OVERFLOW_ERROR || targetSize==0)
1046
char targetBuffer[CHUNK_SIZE];
1048
targetLimit=targetBuffer+CHUNK_SIZE;
1050
/* since the pivot buffer may still contain some characters, start with emptying it */
1051
*pErrorCode=U_ZERO_ERROR;
1052
while(pivot2!=pivot && U_SUCCESS(*pErrorCode)) {
1053
myTarget=targetBuffer;
1054
ucnv_fromUnicode(outConverter,
1055
&myTarget, targetLimit,
1056
(const UChar **)&pivot2, pivot,
1058
(UBool)(source==sourceLimit),
1060
targetCapacity+=(myTarget-targetBuffer);
1061
if(*pErrorCode==U_BUFFER_OVERFLOW_ERROR) {
1062
*pErrorCode=U_ZERO_ERROR;
1066
if(U_FAILURE(*pErrorCode)) {
1067
/* an error occurred: done */
1071
if(source==sourceLimit) {
1073
* source is consumed:
1074
* done, and set the buffer overflow error as
1075
* the result for the entire function
1077
*pErrorCode=U_BUFFER_OVERFLOW_ERROR;
1081
/* now convert from the source into the pivot buffer again */
1082
pivot=pivot2=pivotBuffer;
1083
ucnv_toUnicode(inConverter,
1084
&pivot, pivotBuffer+CHUNK_SIZE,
1085
&source, sourceLimit,
1090
while(U_SUCCESS(*pErrorCode) || *pErrorCode==U_BUFFER_OVERFLOW_ERROR);
1093
ucnv_close (inConverter);
1094
ucnv_close (outConverter);
1096
return u_terminateChars(target, targetSize, targetCapacity, pErrorCode);
1099
U_CAPI UConverterType U_EXPORT2
1100
ucnv_getType(const UConverter* converter)
1102
int8_t type = converter->sharedData->staticData->conversionType;
1103
if(type == UCNV_MBCS) {
1104
return _MBCSGetType(converter);
1106
return (UConverterType)type;
1109
U_CAPI void U_EXPORT2
1110
ucnv_getStarters(const UConverter* converter,
1111
UBool starters[256],
1114
if (err == NULL || U_FAILURE(*err)) {
1118
if(converter->sharedData->impl->getStarters != NULL) {
1119
converter->sharedData->impl->getStarters(converter, starters, err);
1121
*err = U_ILLEGAL_ARGUMENT_ERROR;
1125
static const UAmbiguousConverter *ucnv_getAmbiguous(const UConverter *cnv)
1127
UErrorCode errorCode;
1135
errorCode=U_ZERO_ERROR;
1136
name=ucnv_getName(cnv, &errorCode);
1137
if(U_FAILURE(errorCode)) {
1141
for(i=0; i<(int32_t)(sizeof(ambiguousConverters)/sizeof(UAmbiguousConverter)); ++i)
1143
if(0==uprv_strcmp(name, ambiguousConverters[i].name))
1145
return ambiguousConverters+i;
1152
U_CAPI void U_EXPORT2
1153
ucnv_fixFileSeparator(const UConverter *cnv,
1155
int32_t sourceLength) {
1156
const UAmbiguousConverter *a;
1160
if(cnv==NULL || source==NULL || sourceLength<=0 || (a=ucnv_getAmbiguous(cnv))==NULL)
1165
variant5c=a->variant5c;
1166
for(i=0; i<sourceLength; ++i) {
1167
if(source[i]==variant5c) {
1173
U_CAPI UBool U_EXPORT2
1174
ucnv_isAmbiguous(const UConverter *cnv) {
1175
return (UBool)(ucnv_getAmbiguous(cnv)!=NULL);
1178
U_CAPI void U_EXPORT2
1179
ucnv_setFallback(UConverter *cnv, UBool usesFallback)
1181
cnv->useFallback = usesFallback;
1184
U_CAPI UBool U_EXPORT2
1185
ucnv_usesFallback(const UConverter *cnv)
1187
return cnv->useFallback;
1190
U_CAPI void U_EXPORT2
1191
ucnv_getInvalidChars (const UConverter * converter,
1196
if (err == NULL || U_FAILURE(*err))
1200
if (len == NULL || errBytes == NULL || converter == NULL)
1202
*err = U_ILLEGAL_ARGUMENT_ERROR;
1205
if (*len < converter->invalidCharLength)
1207
*err = U_INDEX_OUTOFBOUNDS_ERROR;
1210
if ((*len = converter->invalidCharLength) > 0)
1212
uprv_memcpy (errBytes, converter->invalidCharBuffer, *len);
1216
U_CAPI void U_EXPORT2
1217
ucnv_getInvalidUChars (const UConverter * converter,
1222
if (err == NULL || U_FAILURE(*err))
1226
if (len == NULL || errChars == NULL || converter == NULL)
1228
*err = U_ILLEGAL_ARGUMENT_ERROR;
1231
if (*len < converter->invalidUCharLength)
1233
*err = U_INDEX_OUTOFBOUNDS_ERROR;
1236
if ((*len = converter->invalidUCharLength) > 0)
1238
uprv_memcpy (errChars, converter->invalidUCharBuffer, sizeof(UChar) * (*len));
1242
#define SIG_MAX_LEN 4
1244
U_CAPI const char* U_EXPORT2
1245
ucnv_detectUnicodeSignature( const char* source,
1246
int32_t sourceLength,
1247
int32_t* signatureLength,
1248
UErrorCode* pErrorCode){
1250
/* initial 0xa5 bytes: make sure that if we read <4
1251
* bytes we don't misdetect something
1253
char start[SIG_MAX_LEN]={ '\xa5', '\xa5', '\xa5', '\xa5' };
1256
if((pErrorCode==NULL) || U_FAILURE(*pErrorCode)){
1260
if(source == NULL || signatureLength == NULL || sourceLength < -1){
1261
*pErrorCode = U_ILLEGAL_ARGUMENT_ERROR;
1265
if(sourceLength==-1){
1266
sourceLength=uprv_strlen(source);
1270
while(i<sourceLength&& i<SIG_MAX_LEN){
1275
if(start[0] == '\xFE' && start[1] == '\xFF') {
1278
} else if(start[0] == '\xFF' && start[1] == '\xFE') {
1279
if(start[2] == '\x00' && start[3] =='\x00'){
1286
} else if(start[0] == '\xEF' && start[1] == '\xBB' && start[2] == '\xBF') {
1289
}else if(start[0] == '\x0E' && start[1] == '\xFE' && start[2] == '\xFF'){
1292
}else if(start[0] == '\x00' && start[1] == '\x00' &&
1293
start[2] == '\xFE' && start[3]=='\xFF'){
1303
* Hey, Emacs, please set the following:
1306
* indent-tabs-mode: nil