2 **********************************************************************
3 * Copyright (C) 2000-2004, International Business Machines
4 * Corporation and others. All Rights Reserved.
5 **********************************************************************
7 * External APIs for the ICU's codeset conversion library
10 * Modification History:
12 * Date Name Description
13 * 7/28/2000 srl Implementation
17 * @name Character Conversion C API
21 #include "unicode/utypes.h"
23 #if !UCONFIG_NO_CONVERSION
25 #include "unicode/ucnv_cb.h"
30 /* need to update the offsets when the target moves. */
31 /* Note: Recursion may occur in the cb functions, be sure to update the offsets correctly
32 if you don't use ucnv_cbXXX functions. Make sure you don't use the same callback within
33 the same call stack if the complexity arises. */
35 ucnv_cbFromUWriteBytes (UConverterFromUnicodeArgs
*args
,
48 &args
->target
, args
->targetLimit
,
49 &args
->offsets
, offsetIndex
,
54 ucnv_cbFromUWriteUChars(UConverterFromUnicodeArgs
*args
,
56 const UChar
* sourceLimit
,
61 This is a fun one. Recursion can occur - we're basically going to
62 just retry shoving data through the same converter. Note, if you got
63 here through some kind of invalid sequence, you maybe should emit a
64 reset sequence of some kind and/or call ucnv_reset(). Since this
65 IS an actual conversion, take care that you've changed the callback
66 or the data, or you'll get an infinite loop.
68 Please set the err value to something reasonable before calling
79 oldTarget
= args
->target
;
81 ucnv_fromUnicode(args
->converter
,
86 NULL
, /* no offsets */
92 while (args
->target
!= oldTarget
) /* if it moved at all.. */
94 *(args
->offsets
)++ = offsetIndex
;
100 Note, if you did something like used a Stop subcallback, things would get interesting.
101 In fact, here's where we want to return the partially consumed in-source!
103 if(*err
== U_BUFFER_OVERFLOW_ERROR
)
104 /* && (*source < sourceLimit && args->target >= args->targetLimit)
107 /* Overflowed the target. Now, we'll write into the charErrorBuffer.
108 It's a fixed size. If we overflow it... Hmm */
110 const char *newTargetLimit
;
111 UErrorCode err2
= U_ZERO_ERROR
;
115 errBuffLen
= args
->converter
->charErrorBufferLength
;
117 /* start the new target at the first free slot in the errbuff.. */
118 newTarget
= (char *)(args
->converter
->charErrorBuffer
+ errBuffLen
);
120 newTargetLimit
= (char *)(args
->converter
->charErrorBuffer
+
121 sizeof(args
->converter
->charErrorBuffer
));
123 if(newTarget
>= newTargetLimit
)
125 *err
= U_INTERNAL_PROGRAM_ERROR
;
129 /* We're going to tell the converter that the errbuff len is empty.
130 This prevents the existing errbuff from being 'flushed' out onto
131 itself. If the errbuff is needed by the converter this time,
132 we're hosed - we're out of space! */
134 args
->converter
->charErrorBufferLength
= 0;
136 ucnv_fromUnicode(args
->converter
,
145 /* We can go ahead and overwrite the length here. We know just how
146 to recalculate it. */
148 args
->converter
->charErrorBufferLength
= (int8_t)(
149 newTarget
- (char*)args
->converter
->charErrorBuffer
);
151 if((newTarget
>= newTargetLimit
) || (err2
== U_BUFFER_OVERFLOW_ERROR
))
153 /* now we're REALLY in trouble.
154 Internal program error - callback shouldn't have written this much
157 *err
= U_INTERNAL_PROGRAM_ERROR
;
162 /* sub errs could be invalid/truncated/illegal chars or w/e.
163 These might want to be passed on up.. But the problem is, we already
164 need to pass U_BUFFER_OVERFLOW_ERROR. That has to override these
175 U_CAPI
void U_EXPORT2
176 ucnv_cbFromUWriteSub (UConverterFromUnicodeArgs
*args
,
180 if(U_FAILURE(*err
)) {
184 if(args
->converter
->sharedData
->impl
->writeSub
!=NULL
) {
185 args
->converter
->sharedData
->impl
->writeSub(args
, offsetIndex
, err
);
186 } else if(args
->converter
->subChar1
!=0 && args
->converter
->invalidUCharBuffer
[0]<=0xff) {
187 ucnv_cbFromUWriteBytes(args
,
188 (const char *)&args
->converter
->subChar1
, 1,
191 ucnv_cbFromUWriteBytes(args
,
192 (const char *)args
->converter
->subChar
, args
->converter
->subCharLen
,
197 U_CAPI
void U_EXPORT2
198 ucnv_cbToUWriteUChars (UConverterToUnicodeArgs
*args
,
204 if(U_FAILURE(*err
)) {
211 &args
->target
, args
->targetLimit
,
212 &args
->offsets
, offsetIndex
,
216 U_CAPI
void U_EXPORT2
217 ucnv_cbToUWriteSub (UConverterToUnicodeArgs
*args
,
221 static const UChar kSubstituteChar1
= 0x1A, kSubstituteChar
= 0xFFFD;
223 /* could optimize this case, just one uchar */
224 if(args
->converter
->invalidCharLength
== 1 && args
->converter
->subChar1
!= 0) {
225 ucnv_cbToUWriteUChars(args
, &kSubstituteChar1
, 1, offsetIndex
, err
);
227 ucnv_cbToUWriteUChars(args
, &kSubstituteChar
, 1, offsetIndex
, err
);