1f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)/* 2f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)********************************************************************** 3f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)* Copyright (C) 2000-2006, International Business Machines 4f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)* Corporation and others. All Rights Reserved. 5f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)********************************************************************** 6f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * ucnv_cb.c: 7f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * External APIs for the ICU's codeset conversion library 8f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * Helena Shih 9f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * 10f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * Modification History: 11f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * 12f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * Date Name Description 13f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * 7/28/2000 srl Implementation 14f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) */ 15f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 16f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)/** 17f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * @name Character Conversion C API 18f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * 19f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) */ 20f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 21f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#include "unicode/utypes.h" 22f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 23f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#if !UCONFIG_NO_CONVERSION 24f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 25f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#include "unicode/ucnv_cb.h" 26f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#include "ucnv_bld.h" 27f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#include "ucnv_cnv.h" 28f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#include "cmemory.h" 29f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 30f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)/* need to update the offsets when the target moves. */ 31f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)/* Note: Recursion may occur in the cb functions, be sure to update the offsets correctly 32f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)if you don't use ucnv_cbXXX functions. Make sure you don't use the same callback within 33f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)the same call stack if the complexity arises. */ 34f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)U_CAPI void U_EXPORT2 35f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)ucnv_cbFromUWriteBytes (UConverterFromUnicodeArgs *args, 36f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) const char* source, 37f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) int32_t length, 38f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) int32_t offsetIndex, 39f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) UErrorCode * err) 40f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles){ 41f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if(U_FAILURE(*err)) { 42f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return; 43f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 44f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 45f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) ucnv_fromUWriteBytes( 46f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) args->converter, 47f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) source, length, 48f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) &args->target, args->targetLimit, 49f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) &args->offsets, offsetIndex, 50f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) err); 51f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)} 52f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 53f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)U_CAPI void U_EXPORT2 54f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)ucnv_cbFromUWriteUChars(UConverterFromUnicodeArgs *args, 55f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) const UChar** source, 56f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) const UChar* sourceLimit, 57f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) int32_t offsetIndex, 58f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) UErrorCode * err) 59f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles){ 60f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* 61f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) This is a fun one. Recursion can occur - we're basically going to 62f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) just retry shoving data through the same converter. Note, if you got 63f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) here through some kind of invalid sequence, you maybe should emit a 64f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) reset sequence of some kind and/or call ucnv_reset(). Since this 65f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) IS an actual conversion, take care that you've changed the callback 66f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) or the data, or you'll get an infinite loop. 67f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 68f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) Please set the err value to something reasonable before calling 69f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) into this. 70f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) */ 71f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 72f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) char *oldTarget; 73f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 74f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if(U_FAILURE(*err)) 75f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) { 76f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return; 77f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 78f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 79f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) oldTarget = args->target; 80f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 81f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) ucnv_fromUnicode(args->converter, 82f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) &args->target, 83f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) args->targetLimit, 84f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) source, 85f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) sourceLimit, 86f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) NULL, /* no offsets */ 87f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) FALSE, /* no flush */ 88f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) err); 89f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 90f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if(args->offsets) 91f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) { 92f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) while (args->target != oldTarget) /* if it moved at all.. */ 93f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) { 94f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) *(args->offsets)++ = offsetIndex; 95f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) oldTarget++; 96f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 97f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 98f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 99f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* 100f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) Note, if you did something like used a Stop subcallback, things would get interesting. 101f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) In fact, here's where we want to return the partially consumed in-source! 102f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) */ 103f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if(*err == U_BUFFER_OVERFLOW_ERROR) 104f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* && (*source < sourceLimit && args->target >= args->targetLimit) 105f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) -- S. Hrcek */ 106f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) { 107f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* Overflowed the target. Now, we'll write into the charErrorBuffer. 108f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) It's a fixed size. If we overflow it... Hmm */ 109f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) char *newTarget; 110f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) const char *newTargetLimit; 111f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) UErrorCode err2 = U_ZERO_ERROR; 112f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 113f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) int8_t errBuffLen; 114f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 115f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) errBuffLen = args->converter->charErrorBufferLength; 116f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 117f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* start the new target at the first free slot in the errbuff.. */ 118f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) newTarget = (char *)(args->converter->charErrorBuffer + errBuffLen); 119f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 120f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) newTargetLimit = (char *)(args->converter->charErrorBuffer + 121f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) sizeof(args->converter->charErrorBuffer)); 122f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 123f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if(newTarget >= newTargetLimit) 124f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) { 125f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) *err = U_INTERNAL_PROGRAM_ERROR; 126f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return; 127f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 128f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 129f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* We're going to tell the converter that the errbuff len is empty. 130f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) This prevents the existing errbuff from being 'flushed' out onto 131f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) itself. If the errbuff is needed by the converter this time, 132f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) we're hosed - we're out of space! */ 133f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 134f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) args->converter->charErrorBufferLength = 0; 135f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 136f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) ucnv_fromUnicode(args->converter, 137f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) &newTarget, 138f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) newTargetLimit, 139f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) source, 140f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) sourceLimit, 141f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) NULL, 142f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) FALSE, 143f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) &err2); 144f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 145f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* We can go ahead and overwrite the length here. We know just how 146f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) to recalculate it. */ 147f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 148f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) args->converter->charErrorBufferLength = (int8_t)( 149f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) newTarget - (char*)args->converter->charErrorBuffer); 150f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 151f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if((newTarget >= newTargetLimit) || (err2 == U_BUFFER_OVERFLOW_ERROR)) 152f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) { 153f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* now we're REALLY in trouble. 154f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) Internal program error - callback shouldn't have written this much 155f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) data! 156f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) */ 157f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) *err = U_INTERNAL_PROGRAM_ERROR; 158f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return; 159f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 160f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /*else {*/ 161f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* sub errs could be invalid/truncated/illegal chars or w/e. 162f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) These might want to be passed on up.. But the problem is, we already 163f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) need to pass U_BUFFER_OVERFLOW_ERROR. That has to override these 164f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) other errs.. */ 165f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 166f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* 167f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if(U_FAILURE(err2)) 168f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) ?? 169f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) */ 170f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /*}*/ 171f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 172f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)} 173f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 174f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)U_CAPI void U_EXPORT2 175f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)ucnv_cbFromUWriteSub (UConverterFromUnicodeArgs *args, 176f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) int32_t offsetIndex, 177f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) UErrorCode * err) 178f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles){ 179f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) UConverter *converter; 180f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) int32_t length; 181f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 182f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if(U_FAILURE(*err)) { 183f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return; 184f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 185f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) converter = args->converter; 186f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) length = converter->subCharLen; 187f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 188f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if(length == 0) { 189f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return; 190f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 191f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 192f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if(length < 0) { 193f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* 194f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * Write/convert the substitution string. Its real length is -length. 195f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * Unlike the escape callback, we need not change the converter's 196f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * callback function because ucnv_setSubstString() verified that 197f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * the string can be converted, so we will not get a conversion error 198f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * and will not recurse. 199f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * At worst we should get a U_BUFFER_OVERFLOW_ERROR. 200f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) */ 201f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) const UChar *source = (const UChar *)converter->subChars; 202f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) ucnv_cbFromUWriteUChars(args, &source, source - length, offsetIndex, err); 203f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return; 204f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 205f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 206f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if(converter->sharedData->impl->writeSub!=NULL) { 207f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) converter->sharedData->impl->writeSub(args, offsetIndex, err); 208f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 209f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) else if(converter->subChar1!=0 && (uint16_t)converter->invalidUCharBuffer[0]<=(uint16_t)0xffu) { 210f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* 211f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) TODO: Is this untestable because the MBCS converter has a writeSub function to call 212f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) and the other converters don't use subChar1? 213f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) */ 214f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) ucnv_cbFromUWriteBytes(args, 215f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) (const char *)&converter->subChar1, 1, 216f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) offsetIndex, err); 217f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 218f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) else { 219f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) ucnv_cbFromUWriteBytes(args, 220f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) (const char *)converter->subChars, length, 221f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) offsetIndex, err); 222f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 223f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)} 224f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 225f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)U_CAPI void U_EXPORT2 226f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)ucnv_cbToUWriteUChars (UConverterToUnicodeArgs *args, 227f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) const UChar* source, 228f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) int32_t length, 229f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) int32_t offsetIndex, 230f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) UErrorCode * err) 231f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles){ 232f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if(U_FAILURE(*err)) { 233f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) return; 234f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 235f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 236f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) ucnv_toUWriteUChars( 237f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) args->converter, 238f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) source, length, 239f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) &args->target, args->targetLimit, 240f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) &args->offsets, offsetIndex, 241f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) err); 242f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)} 243f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 244f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)U_CAPI void U_EXPORT2 245f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)ucnv_cbToUWriteSub (UConverterToUnicodeArgs *args, 246f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) int32_t offsetIndex, 247f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) UErrorCode * err) 248f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles){ 249f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) static const UChar kSubstituteChar1 = 0x1A, kSubstituteChar = 0xFFFD; 250f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 251f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) /* could optimize this case, just one uchar */ 252f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) if(args->converter->invalidCharLength == 1 && args->converter->subChar1 != 0) { 253f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) ucnv_cbToUWriteUChars(args, &kSubstituteChar1, 1, offsetIndex, err); 254f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } else { 255f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) ucnv_cbToUWriteUChars(args, &kSubstituteChar, 1, offsetIndex, err); 256f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) } 257f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)} 258f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) 259f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#endif 260