/* get the state machine state */
isSingleByteMode=scsu->toUIsSingleByteMode;
state=scsu->toUState;
quoteWindow=scsu->toUQuoteWindow;
dynamicWindow=scsu->toUDynamicWindow;
byteOne=scsu->toUByteOne;
/* sourceIndex=-1 if the current character began in the previous buffer */
sourceIndex=state==readCommand ? 0 : -1;
nextSourceIndex=0;
/* set the converter state back into UConverter */ if(U_FAILURE(*pErrorCode) && *pErrorCode!=U_BUFFER_OVERFLOW_ERROR) { /* reset to deal with the next character */
state=readCommand;
} elseif(state==readCommand) { /* not in a multi-byte sequence, reset toULength */
cnv->toULength=0;
}
scsu->toUIsSingleByteMode=isSingleByteMode;
scsu->toUState=state;
scsu->toUQuoteWindow=quoteWindow;
scsu->toUDynamicWindow=dynamicWindow;
scsu->toUByteOne=byteOne;
/* write back the updated pointers */
pArgs->source=(constchar *)source;
pArgs->target=target;
pArgs->offsets=offsets;
}
/* get the state machine state */
isSingleByteMode=scsu->toUIsSingleByteMode;
state=scsu->toUState;
quoteWindow=scsu->toUQuoteWindow;
dynamicWindow=scsu->toUDynamicWindow;
byteOne=scsu->toUByteOne;
/* set the converter state back into UConverter */ if(U_FAILURE(*pErrorCode) && *pErrorCode!=U_BUFFER_OVERFLOW_ERROR) { /* reset to deal with the next character */
state=readCommand;
} elseif(state==readCommand) { /* not in a multi-byte sequence, reset toULength */
cnv->toULength=0;
}
scsu->toUIsSingleByteMode=isSingleByteMode;
scsu->toUState=state;
scsu->toUQuoteWindow=quoteWindow;
scsu->toUDynamicWindow=dynamicWindow;
scsu->toUByteOne=byteOne;
/* write back the updated pointers */
pArgs->source=(constchar *)source;
pArgs->target=target;
}
U_CDECL_END /* SCSU-from-Unicode conversion functions ----------------------------------- */
/* get the number of the window that this character is in, or -1 */ static int8_t
getWindow(const uint32_t offsets[8], uint32_t c) { int i; for(i=0; i<8; ++i) { if (c - offsets[i] <= 0x7f) { return static_cast<int8_t>(i);
}
} return -1;
}
/* is the character in the dynamic window starting at the offset, or in the direct-encoded range? */ static UBool
isInOffsetWindowOrDirect(uint32_t offset, uint32_t c) { return c<=offset+0x7f &&
(c>=offset || (c<=0x7f &&
(c>=0x20 || (1UL<<c)&0x2601))); /* binary 0010 0110 0000 0001,
check for b==0xd || b==0xa || b==9 || b==0 */
}
/* variables for compression heuristics */
uint32_t offset;
char16_t lead, trail; int code;
int8_t window;
/* set up the local pointers */
cnv=pArgs->converter;
scsu=(SCSUData *)cnv->extraInfo;
/* set up the local pointers */
source=pArgs->source;
sourceLimit=pArgs->sourceLimit;
target=(uint8_t *)pArgs->target;
targetCapacity=(int32_t)(pArgs->targetLimit-pArgs->target);
offsets=pArgs->offsets;
/* get the state machine state */
isSingleByteMode=scsu->fromUIsSingleByteMode;
dynamicWindow=scsu->fromUDynamicWindow;
currentOffset=scsu->fromUDynamicOffsets[dynamicWindow];
c=cnv->fromUChar32;
/* sourceIndex=-1 if the current character began in the previous buffer */
sourceIndex= c==0 ? 0 : -1;
nextSourceIndex=0;
/* similar conversion "loop" as in toUnicode */
loop: if(isSingleByteMode) { if(c!=0 && targetCapacity>0) { goto getTrailSingle;
}
/* state machine for single-byte mode */ /* singleByteMode: */ while(source<sourceLimit) { if(targetCapacity<=0) { /* target is full */
*pErrorCode=U_BUFFER_OVERFLOW_ERROR; break;
}
c=*source++;
++nextSourceIndex;
if((c-0x20)<=0x5f) { /* pass US-ASCII graphic character through */
*target++=(uint8_t)c; if(offsets!=nullptr) {
*offsets++=sourceIndex;
}
--targetCapacity;
} elseif(c<0x20) { if((1UL<<c)&0x2601 /* binary 0010 0110 0000 0001, check for b==0xd || b==0xa || b==9 || b==0 */) { /* CR/LF/TAB/NUL */
*target++=(uint8_t)c; if(offsets!=nullptr) {
*offsets++=sourceIndex;
}
--targetCapacity;
} else { /* quote C0 control character */
c|=SQ0<<8;
length=2; goto outputBytes;
}
} elseif((delta=c-currentOffset)<=0x7f) { /* use the current dynamic window */
*target++=(uint8_t)(delta|0x80); if(offsets!=nullptr) {
*offsets++=sourceIndex;
}
--targetCapacity;
} elseif(U16_IS_SURROGATE(c)) { if(U16_IS_SURROGATE_LEAD(c)) {
getTrailSingle:
lead=(char16_t)c; if(source<sourceLimit) { /* test the following code unit */
trail=*source; if(U16_IS_TRAIL(trail)) {
++source;
++nextSourceIndex;
c=U16_GET_SUPPLEMENTARY(c, trail); /* convert this surrogate code point */ /* exit this condition tree */
} else { /* this is an unmatched lead code unit (1st surrogate) */ /* callback(illegal) */
*pErrorCode=U_ILLEGAL_CHAR_FOUND; goto endloop;
}
} else { /* no more input */ break;
}
} else { /* this is an unmatched trail code unit (2nd surrogate) */ /* callback(illegal) */
*pErrorCode=U_ILLEGAL_CHAR_FOUND; goto endloop;
}
/* compress supplementary character U+10000..U+10ffff */ if((delta=c-currentOffset)<=0x7f) { /* use the current dynamic window */
*target++=(uint8_t)(delta|0x80); if(offsets!=nullptr) {
*offsets++=sourceIndex;
}
--targetCapacity;
} elseif((window=getWindow(scsu->fromUDynamicOffsets, c))>=0) { /* there is a dynamic window that contains this character, change to it */
dynamicWindow=window;
currentOffset=scsu->fromUDynamicOffsets[dynamicWindow];
useDynamicWindow(scsu, dynamicWindow);
c=((uint32_t)(SC0+dynamicWindow)<<8)|(c-currentOffset)|0x80;
length=2; goto outputBytes;
} elseif((code=getDynamicOffset(c, &offset))>=0) { /* might check if there are more characters in this window to come */ /* define an extended window with this character */
code-=0x200;
dynamicWindow=getNextDynamicWindow(scsu);
currentOffset=scsu->fromUDynamicOffsets[dynamicWindow]=offset;
useDynamicWindow(scsu, dynamicWindow);
c=((uint32_t)SDX<<24)|((uint32_t)dynamicWindow<<21)|((uint32_t)code<<8)|(c-currentOffset)|0x80;
length=4; goto outputBytes;
} else { /* change to Unicode mode and output this (lead, trail) pair */
isSingleByteMode=false;
*target++=(uint8_t)SCU; if(offsets!=nullptr) {
*offsets++=sourceIndex;
}
--targetCapacity;
c=((uint32_t)lead<<16)|trail;
length=4; goto outputBytes;
}
} elseif(c<0xa0) { /* quote C1 control character */
c=(c&0x7f)|(SQ0+1)<<8; /* SQ0+1==SQ1 */
length=2; goto outputBytes;
} elseif(c==0xfeff || c>=0xfff0) { /* quote signature character=byte order mark and specials */
c|=SQU<<16;
length=3; goto outputBytes;
} else { /* compress all other BMP characters */ if((window=getWindow(scsu->fromUDynamicOffsets, c))>=0) { /* there is a window defined that contains this character - switch to it or quote from it? */ if(source>=sourceLimit || isInOffsetWindowOrDirect(scsu->fromUDynamicOffsets[window], *source)) { /* change to dynamic window */
dynamicWindow=window;
currentOffset=scsu->fromUDynamicOffsets[dynamicWindow];
useDynamicWindow(scsu, dynamicWindow);
c=((uint32_t)(SC0+dynamicWindow)<<8)|(c-currentOffset)|0x80;
length=2; goto outputBytes;
} else { /* quote from dynamic window */
c=((uint32_t)(SQ0+window)<<8)|(c-scsu->fromUDynamicOffsets[window])|0x80;
length=2; goto outputBytes;
}
} elseif((window=getWindow(staticOffsets, c))>=0) { /* quote from static window */
c=((uint32_t)(SQ0+window)<<8)|(c-staticOffsets[window]);
length=2; goto outputBytes;
} elseif((code=getDynamicOffset(c, &offset))>=0) { /* define a dynamic window with this character */
dynamicWindow=getNextDynamicWindow(scsu);
currentOffset=scsu->fromUDynamicOffsets[dynamicWindow]=offset;
useDynamicWindow(scsu, dynamicWindow);
c=((uint32_t)(SD0+dynamicWindow)<<16)|((uint32_t)code<<8)|(c-currentOffset)|0x80;
length=3; goto outputBytes;
} elseif ((c - 0x3400) < (0xd800 - 0x3400) &&
(source >= sourceLimit || (uint32_t)(*source - 0x3400) < (0xd800 - 0x3400))
) { /* *thischaracterisnotcompressible(aBMPideographorsimilar); *switchtoUnicodemodeifthisisthelastcharacterintheblock *orthereisatleastonemoreideographfollowingimmediately
*/
isSingleByteMode=false;
c|=SCU<<16;
length=3; goto outputBytes;
} else { /* quote Unicode */
c|=SQU<<16;
length=3; goto outputBytes;
}
}
/* normal end of conversion: prepare for a new character */
c=0;
sourceIndex=nextSourceIndex;
}
} else { if(c!=0 && targetCapacity>0) { goto getTrailUnicode;
}
/* state machine for Unicode mode */ /* unicodeByteMode: */ while(source<sourceLimit) { if(targetCapacity<=0) { /* target is full */
*pErrorCode=U_BUFFER_OVERFLOW_ERROR; break;
}
c=*source++;
++nextSourceIndex;
if ((c - 0x3400) < (0xd800 - 0x3400)) { /* not compressible, write character directly */ if(targetCapacity>=2) {
*target++=(uint8_t)(c>>8);
*target++=(uint8_t)c; if(offsets!=nullptr) {
*offsets++=sourceIndex;
*offsets++=sourceIndex;
}
targetCapacity-=2;
} else {
length=2; goto outputBytes;
}
} elseif (c - 0x3400 >= 0xf300 - 0x3400 /* c<0x3400 || c>=0xf300 */) { /* compress BMP character if the following one is not an uncompressible ideograph */ if(!(source<sourceLimit && (uint32_t)(*source-0x3400)<(0xd800-0x3400))) { if (c - 0x30 < 10 || c - 0x61 < 26 || c - 0x41 < 26) { /* ASCII digit or letter */
isSingleByteMode=true;
c|=((uint32_t)(UC0+dynamicWindow)<<8)|c;
length=2; goto outputBytes;
} elseif((window=getWindow(scsu->fromUDynamicOffsets, c))>=0) { /* there is a dynamic window that contains this character, change to it */
isSingleByteMode=true;
dynamicWindow=window;
currentOffset=scsu->fromUDynamicOffsets[dynamicWindow];
useDynamicWindow(scsu, dynamicWindow);
c=((uint32_t)(UC0+dynamicWindow)<<8)|(c-currentOffset)|0x80;
length=2; goto outputBytes;
} elseif((code=getDynamicOffset(c, &offset))>=0) { /* define a dynamic window with this character */
isSingleByteMode=true;
dynamicWindow=getNextDynamicWindow(scsu);
currentOffset=scsu->fromUDynamicOffsets[dynamicWindow]=offset;
useDynamicWindow(scsu, dynamicWindow);
c=((uint32_t)(UD0+dynamicWindow)<<16)|((uint32_t)code<<8)|(c-currentOffset)|0x80;
length=3; goto outputBytes;
}
}
/* don't know how to compress this character, just write it directly */
length=2; goto outputBytes;
} elseif(c<0xe000) { /* c is a surrogate */ if(U16_IS_SURROGATE_LEAD(c)) {
getTrailUnicode:
lead=(char16_t)c; if(source<sourceLimit) { /* test the following code unit */
trail=*source; if(U16_IS_TRAIL(trail)) {
++source;
++nextSourceIndex;
c=U16_GET_SUPPLEMENTARY(c, trail); /* convert this surrogate code point */ /* exit this condition tree */
} else { /* this is an unmatched lead code unit (1st surrogate) */ /* callback(illegal) */
*pErrorCode=U_ILLEGAL_CHAR_FOUND; goto endloop;
}
} else { /* no more input */ break;
}
} else { /* this is an unmatched trail code unit (2nd surrogate) */ /* callback(illegal) */
*pErrorCode=U_ILLEGAL_CHAR_FOUND; goto endloop;
}
/* compress supplementary character */ if( (window=getWindow(scsu->fromUDynamicOffsets, c))>=0 &&
!(source<sourceLimit && (uint32_t)(*source-0x3400)<(0xd800-0x3400))
) { /* *thereisadynamicwindowthatcontainsthischaracterand *thefollowingcharacterisnotuncompressible, *changetothewindow
*/
isSingleByteMode=true;
dynamicWindow=window;
currentOffset=scsu->fromUDynamicOffsets[dynamicWindow];
useDynamicWindow(scsu, dynamicWindow);
c=((uint32_t)(UC0+dynamicWindow)<<8)|(c-currentOffset)|0x80;
length=2; goto outputBytes;
} elseif(source<sourceLimit && lead==*source && /* too lazy to check trail in same window as source[1] */
(code=getDynamicOffset(c, &offset))>=0
) { /* two supplementary characters in (probably) the same window - define an extended one */
isSingleByteMode=true;
code-=0x200;
dynamicWindow=getNextDynamicWindow(scsu);
currentOffset=scsu->fromUDynamicOffsets[dynamicWindow]=offset;
useDynamicWindow(scsu, dynamicWindow);
c=((uint32_t)UDX<<24)|((uint32_t)dynamicWindow<<21)|((uint32_t)code<<8)|(c-currentOffset)|0x80;
length=4; goto outputBytes;
} else { /* don't know how to compress this character, just write it directly */
c=((uint32_t)lead<<16)|trail;
length=4; goto outputBytes;
}
} else/* 0xe000<=c<0xf300 */ { /* quote to avoid SCSU tags */
c|=UQU<<16;
length=3; goto outputBytes;
}
/* normal end of conversion: prepare for a new character */
c=0;
sourceIndex=nextSourceIndex;
}
}
endloop:
/* set the converter state back into UConverter */
scsu->fromUIsSingleByteMode=isSingleByteMode;
scsu->fromUDynamicWindow=dynamicWindow;
cnv->fromUChar32=c;
/* write back the updated pointers */
pArgs->source=source;
pArgs->target=(char *)target;
pArgs->offsets=offsets; return;
outputBytes: /* write the output character bytes from c and length [code copied from ucnvmbcs.c] */ /* from the first if in the loop we know that targetCapacity>0 */ if(length<=targetCapacity) { if(offsets==nullptr) { switch(length) { /* each branch falls through to the next one */ case4:
*target++=(uint8_t)(c>>24);
U_FALLTHROUGH; case3:
*target++=(uint8_t)(c>>16);
U_FALLTHROUGH; case2:
*target++=(uint8_t)(c>>8);
U_FALLTHROUGH; case1:
*target++=(uint8_t)c;
U_FALLTHROUGH; default: /* will never occur */ break;
}
} else { switch(length) { /* each branch falls through to the next one */ case4:
*target++=(uint8_t)(c>>24);
*offsets++=sourceIndex;
U_FALLTHROUGH; case3:
*target++=(uint8_t)(c>>16);
*offsets++=sourceIndex;
U_FALLTHROUGH; case2:
*target++=(uint8_t)(c>>8);
*offsets++=sourceIndex;
U_FALLTHROUGH; case1:
*target++=(uint8_t)c;
*offsets++=sourceIndex;
U_FALLTHROUGH; default: /* will never occur */ break;
}
}
targetCapacity-=length;
/* normal end of conversion: prepare for a new character */
c=0;
sourceIndex=nextSourceIndex; goto loop;
} else {
uint8_t *p;
/* *Weactuallydothisbackwardshere: *Inordertosaveanintermediatevariable,weoutput *firsttotheoverflowbufferwhatdoesnotfitintothe *regulartarget.
*/ /* we know that 0<=targetCapacity<length<=4 */ /* targetCapacity==0 when SCU+supplementary where SCU used up targetCapacity==1 */
length-=targetCapacity;
p=(uint8_t *)cnv->charErrorBuffer; switch(length) { /* each branch falls through to the next one */ case4:
*p++=(uint8_t)(c>>24);
U_FALLTHROUGH; case3:
*p++=(uint8_t)(c>>16);
U_FALLTHROUGH; case2:
*p++=(uint8_t)(c>>8);
U_FALLTHROUGH; case1:
*p=(uint8_t)c;
U_FALLTHROUGH; default: /* will never occur */ break;
}
cnv->charErrorBufferLength=(int8_t)length;
/* now output what fits into the regular target */
c>>=8*length; /* length was reduced by targetCapacity */ switch(targetCapacity) { /* each branch falls through to the next one */ case3:
*target++=(uint8_t)(c>>16); if(offsets!=nullptr) {
*offsets++=sourceIndex;
}
U_FALLTHROUGH; case2:
*target++=(uint8_t)(c>>8); if(offsets!=nullptr) {
*offsets++=sourceIndex;
}
U_FALLTHROUGH; case1:
*target++=(uint8_t)c; if(offsets!=nullptr) {
*offsets++=sourceIndex;
}
U_FALLTHROUGH; default: break;
}
/* variables for compression heuristics */
uint32_t offset;
char16_t lead, trail; int code;
int8_t window;
/* set up the local pointers */
cnv=pArgs->converter;
scsu=(SCSUData *)cnv->extraInfo;
/* set up the local pointers */
source=pArgs->source;
sourceLimit=pArgs->sourceLimit;
target=(uint8_t *)pArgs->target;
targetCapacity=(int32_t)(pArgs->targetLimit-pArgs->target);
/* get the state machine state */
isSingleByteMode=scsu->fromUIsSingleByteMode;
dynamicWindow=scsu->fromUDynamicWindow;
currentOffset=scsu->fromUDynamicOffsets[dynamicWindow];
c=cnv->fromUChar32;
/* similar conversion "loop" as in toUnicode */
loop: if(isSingleByteMode) { if(c!=0 && targetCapacity>0) { goto getTrailSingle;
}
/* state machine for single-byte mode */ /* singleByteMode: */ while(source<sourceLimit) { if(targetCapacity<=0) { /* target is full */
*pErrorCode=U_BUFFER_OVERFLOW_ERROR; break;
}
c=*source++;
if((c-0x20)<=0x5f) { /* pass US-ASCII graphic character through */
*target++=(uint8_t)c;
--targetCapacity;
} elseif(c<0x20) { if((1UL<<c)&0x2601 /* binary 0010 0110 0000 0001, check for b==0xd || b==0xa || b==9 || b==0 */) { /* CR/LF/TAB/NUL */
*target++=(uint8_t)c;
--targetCapacity;
} else { /* quote C0 control character */
c|=SQ0<<8;
length=2; goto outputBytes;
}
} elseif((delta=c-currentOffset)<=0x7f) { /* use the current dynamic window */
*target++=(uint8_t)(delta|0x80);
--targetCapacity;
} elseif(U16_IS_SURROGATE(c)) { if(U16_IS_SURROGATE_LEAD(c)) {
getTrailSingle:
lead=(char16_t)c; if(source<sourceLimit) { /* test the following code unit */
trail=*source; if(U16_IS_TRAIL(trail)) {
++source;
c=U16_GET_SUPPLEMENTARY(c, trail); /* convert this surrogate code point */ /* exit this condition tree */
} else { /* this is an unmatched lead code unit (1st surrogate) */ /* callback(illegal) */
*pErrorCode=U_ILLEGAL_CHAR_FOUND; goto endloop;
}
} else { /* no more input */ break;
}
} else { /* this is an unmatched trail code unit (2nd surrogate) */ /* callback(illegal) */
*pErrorCode=U_ILLEGAL_CHAR_FOUND; goto endloop;
}
/* compress supplementary character U+10000..U+10ffff */ if((delta=c-currentOffset)<=0x7f) { /* use the current dynamic window */
*target++=(uint8_t)(delta|0x80);
--targetCapacity;
} elseif((window=getWindow(scsu->fromUDynamicOffsets, c))>=0) { /* there is a dynamic window that contains this character, change to it */
dynamicWindow=window;
currentOffset=scsu->fromUDynamicOffsets[dynamicWindow];
useDynamicWindow(scsu, dynamicWindow);
c=((uint32_t)(SC0+dynamicWindow)<<8)|(c-currentOffset)|0x80;
length=2; goto outputBytes;
} elseif((code=getDynamicOffset(c, &offset))>=0) { /* might check if there are more characters in this window to come */ /* define an extended window with this character */
code-=0x200;
dynamicWindow=getNextDynamicWindow(scsu);
currentOffset=scsu->fromUDynamicOffsets[dynamicWindow]=offset;
useDynamicWindow(scsu, dynamicWindow);
c=((uint32_t)SDX<<24)|((uint32_t)dynamicWindow<<21)|((uint32_t)code<<8)|(c-currentOffset)|0x80;
length=4; goto outputBytes;
} else { /* change to Unicode mode and output this (lead, trail) pair */
isSingleByteMode=false;
*target++=(uint8_t)SCU;
--targetCapacity;
c=((uint32_t)lead<<16)|trail;
length=4; goto outputBytes;
}
} elseif(c<0xa0) { /* quote C1 control character */
c=(c&0x7f)|(SQ0+1)<<8; /* SQ0+1==SQ1 */
length=2; goto outputBytes;
} elseif(c==0xfeff || c>=0xfff0) { /* quote signature character=byte order mark and specials */
c|=SQU<<16;
length=3; goto outputBytes;
} else { /* compress all other BMP characters */ if((window=getWindow(scsu->fromUDynamicOffsets, c))>=0) { /* there is a window defined that contains this character - switch to it or quote from it? */ if(source>=sourceLimit || isInOffsetWindowOrDirect(scsu->fromUDynamicOffsets[window], *source)) { /* change to dynamic window */
dynamicWindow=window;
currentOffset=scsu->fromUDynamicOffsets[dynamicWindow];
useDynamicWindow(scsu, dynamicWindow);
c=((uint32_t)(SC0+dynamicWindow)<<8)|(c-currentOffset)|0x80;
length=2; goto outputBytes;
} else { /* quote from dynamic window */
c=((uint32_t)(SQ0+window)<<8)|(c-scsu->fromUDynamicOffsets[window])|0x80;
length=2; goto outputBytes;
}
} elseif((window=getWindow(staticOffsets, c))>=0) { /* quote from static window */
c=((uint32_t)(SQ0+window)<<8)|(c-staticOffsets[window]);
length=2; goto outputBytes;
} elseif((code=getDynamicOffset(c, &offset))>=0) { /* define a dynamic window with this character */
dynamicWindow=getNextDynamicWindow(scsu);
currentOffset=scsu->fromUDynamicOffsets[dynamicWindow]=offset;
useDynamicWindow(scsu, dynamicWindow);
c=((uint32_t)(SD0+dynamicWindow)<<16)|((uint32_t)code<<8)|(c-currentOffset)|0x80;
length=3; goto outputBytes;
} elseif (c - 0x3400 < 0xd800 - 0x3400 &&
(source >= sourceLimit || static_cast<uint32_t>(*source - 0x3400) < 0xd800 - 0x3400)
) { /* *thischaracterisnotcompressible(aBMPideographorsimilar); *switchtoUnicodemodeifthisisthelastcharacterintheblock *orthereisatleastonemoreideographfollowingimmediately
*/
isSingleByteMode=false;
c|=SCU<<16;
length=3; goto outputBytes;
} else { /* quote Unicode */
c|=SQU<<16;
length=3; goto outputBytes;
}
}
/* normal end of conversion: prepare for a new character */
c=0;
}
} else { if(c!=0 && targetCapacity>0) { goto getTrailUnicode;
}
/* state machine for Unicode mode */ /* unicodeByteMode: */ while(source<sourceLimit) { if(targetCapacity<=0) { /* target is full */
*pErrorCode=U_BUFFER_OVERFLOW_ERROR; break;
}
c=*source++;
if (c - 0x3400 < 0xd800 - 0x3400) { /* not compressible, write character directly */ if(targetCapacity>=2) {
*target++=(uint8_t)(c>>8);
*target++=(uint8_t)c;
targetCapacity-=2;
} else {
length=2; goto outputBytes;
}
} elseif (c - 0x3400 >= 0xf300 - 0x3400 /* c<0x3400 || c>=0xf300 */) { /* compress BMP character if the following one is not an uncompressible ideograph */ if(!(source<sourceLimit && (uint32_t)(*source-0x3400)<(0xd800-0x3400))) { if (c - 0x30 < 10 || c - 0x61 < 26 || c - 0x41 < 26) { /* ASCII digit or letter */
isSingleByteMode=true;
c|=((uint32_t)(UC0+dynamicWindow)<<8)|c;
length=2; goto outputBytes;
} elseif((window=getWindow(scsu->fromUDynamicOffsets, c))>=0) { /* there is a dynamic window that contains this character, change to it */
isSingleByteMode=true;
dynamicWindow=window;
currentOffset=scsu->fromUDynamicOffsets[dynamicWindow];
useDynamicWindow(scsu, dynamicWindow);
c=((uint32_t)(UC0+dynamicWindow)<<8)|(c-currentOffset)|0x80;
length=2; goto outputBytes;
} elseif((code=getDynamicOffset(c, &offset))>=0) { /* define a dynamic window with this character */
isSingleByteMode=true;
dynamicWindow=getNextDynamicWindow(scsu);
currentOffset=scsu->fromUDynamicOffsets[dynamicWindow]=offset;
useDynamicWindow(scsu, dynamicWindow);
c=((uint32_t)(UD0+dynamicWindow)<<16)|((uint32_t)code<<8)|(c-currentOffset)|0x80;
length=3; goto outputBytes;
}
}
/* don't know how to compress this character, just write it directly */
length=2; goto outputBytes;
} elseif(c<0xe000) { /* c is a surrogate */ if(U16_IS_SURROGATE_LEAD(c)) {
getTrailUnicode:
lead=(char16_t)c; if(source<sourceLimit) { /* test the following code unit */
trail=*source; if(U16_IS_TRAIL(trail)) {
++source;
c=U16_GET_SUPPLEMENTARY(c, trail); /* convert this surrogate code point */ /* exit this condition tree */
} else { /* this is an unmatched lead code unit (1st surrogate) */ /* callback(illegal) */
*pErrorCode=U_ILLEGAL_CHAR_FOUND; goto endloop;
}
} else { /* no more input */ break;
}
} else { /* this is an unmatched trail code unit (2nd surrogate) */ /* callback(illegal) */
*pErrorCode=U_ILLEGAL_CHAR_FOUND; goto endloop;
}
/* compress supplementary character */ if( (window=getWindow(scsu->fromUDynamicOffsets, c))>=0 &&
!(source<sourceLimit && (uint32_t)(*source-0x3400)<(0xd800-0x3400))
) { /* *thereisadynamicwindowthatcontainsthischaracterand *thefollowingcharacterisnotuncompressible, *changetothewindow
*/
isSingleByteMode=true;
dynamicWindow=window;
currentOffset=scsu->fromUDynamicOffsets[dynamicWindow];
useDynamicWindow(scsu, dynamicWindow);
c=((uint32_t)(UC0+dynamicWindow)<<8)|(c-currentOffset)|0x80;
length=2; goto outputBytes;
} elseif(source<sourceLimit && lead==*source && /* too lazy to check trail in same window as source[1] */
(code=getDynamicOffset(c, &offset))>=0
) { /* two supplementary characters in (probably) the same window - define an extended one */
isSingleByteMode=true;
code-=0x200;
dynamicWindow=getNextDynamicWindow(scsu);
currentOffset=scsu->fromUDynamicOffsets[dynamicWindow]=offset;
useDynamicWindow(scsu, dynamicWindow);
c=((uint32_t)UDX<<24)|((uint32_t)dynamicWindow<<21)|((uint32_t)code<<8)|(c-currentOffset)|0x80;
length=4; goto outputBytes;
} else { /* don't know how to compress this character, just write it directly */
c=((uint32_t)lead<<16)|trail;
length=4; goto outputBytes;
}
} else/* 0xe000<=c<0xf300 */ { /* quote to avoid SCSU tags */
c|=UQU<<16;
length=3; goto outputBytes;
}
/* normal end of conversion: prepare for a new character */
c=0;
}
}
endloop:
/* set the converter state back into UConverter */
scsu->fromUIsSingleByteMode=isSingleByteMode;
scsu->fromUDynamicWindow=dynamicWindow;
cnv->fromUChar32=c;
/* write back the updated pointers */
pArgs->source=source;
pArgs->target=(char *)target; return;
outputBytes: /* write the output character bytes from c and length [code copied from ucnvmbcs.c] */ /* from the first if in the loop we know that targetCapacity>0 */ if(length<=targetCapacity) { switch(length) { /* each branch falls through to the next one */ case4:
*target++=(uint8_t)(c>>24);
U_FALLTHROUGH; case3:
*target++=(uint8_t)(c>>16);
U_FALLTHROUGH; case2:
*target++=(uint8_t)(c>>8);
U_FALLTHROUGH; case1:
*target++=(uint8_t)c;
U_FALLTHROUGH; default: /* will never occur */ break;
}
targetCapacity-=length;
/* normal end of conversion: prepare for a new character */
c=0; goto loop;
} else {
uint8_t *p;
/* *Weactuallydothisbackwardshere: *Inordertosaveanintermediatevariable,weoutput *firsttotheoverflowbufferwhatdoesnotfitintothe *regulartarget.
*/ /* we know that 0<=targetCapacity<length<=4 */ /* targetCapacity==0 when SCU+supplementary where SCU used up targetCapacity==1 */
length-=targetCapacity;
p=(uint8_t *)cnv->charErrorBuffer; switch(length) { /* each branch falls through to the next one */ case4:
*p++=(uint8_t)(c>>24);
U_FALLTHROUGH; case3:
*p++=(uint8_t)(c>>16);
U_FALLTHROUGH; case2:
*p++=(uint8_t)(c>>8);
U_FALLTHROUGH; case1:
*p=(uint8_t)c;
U_FALLTHROUGH; default: /* will never occur */ break;
}
cnv->charErrorBufferLength=(int8_t)length;
/* now output what fits into the regular target */
c = (length == 4) ? 0 : c >> 8*length; /* length was reduced by targetCapacity */ switch(targetCapacity) { /* each branch falls through to the next one */ case3:
*target++=(uint8_t)(c>>16);
U_FALLTHROUGH; case2:
*target++=(uint8_t)(c>>8);
U_FALLTHROUGH; case1:
*target++=(uint8_t)c;
U_FALLTHROUGH; default: break;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.