/* number of lead bytes */ #define BOCU1_COUNT (BOCU1_MAX_LEAD-BOCU1_MIN+1)
/* adjust trail byte counts for the use of some C0 control byte values */ #define BOCU1_TRAIL_CONTROLS_COUNT 20 #define BOCU1_TRAIL_BYTE_OFFSET (BOCU1_MIN-BOCU1_TRAIL_CONTROLS_COUNT)
/* number of trail bytes */ #define BOCU1_TRAIL_COUNT ((BOCU1_MAX_TRAIL-BOCU1_MIN+1)+BOCU1_TRAIL_CONTROLS_COUNT)
/* number of lead bytes for positive and negative 2/3/4-byte sequences */ #define BOCU1_LEAD_2 43 #define BOCU1_LEAD_3 3 #define BOCU1_LEAD_4 1
/* The difference value range for single-byters. */ #define BOCU1_REACH_POS_1 (BOCU1_SINGLE-1) #define BOCU1_REACH_NEG_1 (-BOCU1_SINGLE)
/* The difference value range for double-byters. */ #define BOCU1_REACH_POS_2 (BOCU1_REACH_POS_1+BOCU1_LEAD_2*BOCU1_TRAIL_COUNT) #define BOCU1_REACH_NEG_2 (BOCU1_REACH_NEG_1-BOCU1_LEAD_2*BOCU1_TRAIL_COUNT)
/* The difference value range for 3-byters. */ #define BOCU1_REACH_POS_3 \
(BOCU1_REACH_POS_2+BOCU1_LEAD_3*BOCU1_TRAIL_COUNT*BOCU1_TRAIL_COUNT)
/* The length of a byte sequence, according to the lead byte (!=BOCU1_RESET). */ #define BOCU1_LENGTH_FROM_LEAD(lead) \
((BOCU1_START_NEG_2<=(lead) && (lead)<BOCU1_START_POS_2) ? 1 : \
(BOCU1_START_NEG_3<=(lead) && (lead)<BOCU1_START_POS_3) ? 2 : \
(BOCU1_START_NEG_4<=(lead) && (lead)<BOCU1_START_POS_4) ? 3 : 4)
/* The length of a byte sequence, according to its packed form. */ #define BOCU1_LENGTH_FROM_PACKED(packed) \
((uint32_t)(packed)<0x04000000 ? (packed)>>24 : 4)
U_ASSERT(!DIFF_IS_SINGLE(diff)); /* assume we won't be called where diff==BOCU1_REACH_NEG_1=-64 */ if(diff>=BOCU1_REACH_NEG_1) { /* mostly positive differences, and single-byte negative ones */ #if0/* single-byte case handled in macros, see below */ if(diff<=BOCU1_REACH_POS_1) { /* single byte */ return0x01000000|(BOCU1_MIDDLE+diff);
} else #endif if(diff<=BOCU1_REACH_POS_2) { /* two bytes */
diff-=BOCU1_REACH_POS_1+1;
result=0x02000000;
/* set up the local pointers */
cnv=pArgs->converter;
source=pArgs->source;
sourceLimit=pArgs->sourceLimit;
target = reinterpret_cast<uint8_t*>(pArgs->target);
targetCapacity = static_cast<int32_t>(pArgs->targetLimit - pArgs->target);
offsets=pArgs->offsets;
/* get the converter state from UConverter */
c=cnv->fromUChar32;
prev = static_cast<int32_t>(cnv->fromUnicodeStatus); if(prev==0) {
prev=BOCU1_ASCII_PREV;
}
/* sourceIndex=-1 if the current character began in the previous buffer */
sourceIndex= c==0 ? 0 : -1;
nextSourceIndex=0;
/* write the output character bytes from diff and length */ /* 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++ = static_cast<uint8_t>(diff >> 24);
*offsets++=sourceIndex;
U_FALLTHROUGH; case3:
*target++ = static_cast<uint8_t>(diff >> 16);
*offsets++=sourceIndex;
U_FALLTHROUGH; case2:
*target++ = static_cast<uint8_t>(diff >> 8);
*offsets++=sourceIndex; /* case 1: handled above */
*target++ = static_cast<uint8_t>(diff);
*offsets++=sourceIndex;
U_FALLTHROUGH; default: /* will never occur */ break;
}
targetCapacity-=length;
sourceIndex=nextSourceIndex;
} else {
uint8_t *charErrorBuffer;
/* *Weactuallydothisbackwardshere: *Inordertosaveanintermediatevariable,weoutput *firsttotheoverflowbufferwhatdoesnotfitintothe *regulartarget.
*/ /* we know that 1<=targetCapacity<length<=4 */
length-=targetCapacity;
charErrorBuffer=(uint8_t *)cnv->charErrorBuffer; switch(length) { /* each branch falls through to the next one */ case3:
*charErrorBuffer++ = static_cast<uint8_t>(diff >> 16);
U_FALLTHROUGH; case2:
*charErrorBuffer++ = static_cast<uint8_t>(diff >> 8);
U_FALLTHROUGH; case1:
*charErrorBuffer = static_cast<uint8_t>(diff);
U_FALLTHROUGH; default: /* will never occur */ break;
}
cnv->charErrorBufferLength = static_cast<int8_t>(length);
/* now output what fits into the regular target */
diff>>=8*length; /* length was reduced by targetCapacity */ switch(targetCapacity) { /* each branch falls through to the next one */ case3:
*target++ = static_cast<uint8_t>(diff >> 16);
*offsets++=sourceIndex;
U_FALLTHROUGH; case2:
*target++ = static_cast<uint8_t>(diff >> 8);
*offsets++=sourceIndex;
U_FALLTHROUGH; case1:
*target++ = static_cast<uint8_t>(diff);
*offsets++=sourceIndex;
U_FALLTHROUGH; default: /* will never occur */ break;
}
/* set up the local pointers */
cnv=pArgs->converter;
source=pArgs->source;
sourceLimit=pArgs->sourceLimit;
target = reinterpret_cast<uint8_t*>(pArgs->target);
targetCapacity = static_cast<int32_t>(pArgs->targetLimit - pArgs->target);
/* get the converter state from UConverter */
c=cnv->fromUChar32;
prev = static_cast<int32_t>(cnv->fromUnicodeStatus); if(prev==0) {
prev=BOCU1_ASCII_PREV;
}
if(U16_IS_LEAD(c)) {
getTrail: if(source<sourceLimit) { /* test the following code unit */
char16_t trail=*source; if(U16_IS_TRAIL(trail)) {
++source;
c=U16_GET_SUPPLEMENTARY(c, trail);
}
} else { /* no more input */
c=-c; /* negative lead surrogate as "incomplete" indicator to avoid c=0 everywhere else */ break;
}
}
/* write the output character bytes from diff and length */ /* 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++ = static_cast<uint8_t>(diff >> 24);
U_FALLTHROUGH; case3:
*target++ = static_cast<uint8_t>(diff >> 16); /* case 2: handled above */
*target++ = static_cast<uint8_t>(diff >> 8); /* case 1: handled above */
*target++ = static_cast<uint8_t>(diff);
U_FALLTHROUGH; default: /* will never occur */ break;
}
targetCapacity-=length;
} else {
uint8_t *charErrorBuffer;
/* *Weactuallydothisbackwardshere: *Inordertosaveanintermediatevariable,weoutput *firsttotheoverflowbufferwhatdoesnotfitintothe *regulartarget.
*/ /* we know that 1<=targetCapacity<length<=4 */
length-=targetCapacity;
charErrorBuffer=(uint8_t *)cnv->charErrorBuffer; switch(length) { /* each branch falls through to the next one */ case3:
*charErrorBuffer++ = static_cast<uint8_t>(diff >> 16);
U_FALLTHROUGH; case2:
*charErrorBuffer++ = static_cast<uint8_t>(diff >> 8);
U_FALLTHROUGH; case1:
*charErrorBuffer = static_cast<uint8_t>(diff);
U_FALLTHROUGH; default: /* will never occur */ break;
}
cnv->charErrorBufferLength = static_cast<int8_t>(length);
/* now output what fits into the regular target */
diff>>=8*length; /* length was reduced by targetCapacity */ switch(targetCapacity) { /* each branch falls through to the next one */ case3:
*target++ = static_cast<uint8_t>(diff >> 16);
U_FALLTHROUGH; case2:
*target++ = static_cast<uint8_t>(diff >> 8);
U_FALLTHROUGH; case1:
*target++ = static_cast<uint8_t>(diff);
U_FALLTHROUGH; default: /* will never occur */ break;
}
/* return the state for decoding the trail byte(s) */ return (static_cast<uint32_t>(diff) << 2) | count;
}
/** *FunctionforBOCU-1decoder;handlesmulti-bytetrailbytes. * *@paramcountnumberofremainingtrailbytesincludingthisone *@parambtrailbyte *@returnnewdeltafordiffincludingb-<0indicatesanerror * *@seedecodeBocu1
*/ staticinline int32_t
decodeBocu1TrailByte(int32_t count, int32_t b) { if(b<=0x20) { /* skip some C0 controls and make the trail byte range contiguous */
b=bocu1ByteToTrail[b]; /* b<0 for an illegal trail byte value will result in return<0 below */ #if BOCU1_MAX_TRAIL<0xff
} elseif(b>BOCU1_MAX_TRAIL) { return -99; #endif
} else {
b-=BOCU1_TRAIL_BYTE_OFFSET;
}
/* set up the local pointers */
cnv=pArgs->converter;
source = reinterpret_cast<const uint8_t*>(pArgs->source);
sourceLimit = reinterpret_cast<const uint8_t*>(pArgs->sourceLimit);
target=pArgs->target;
targetLimit=pArgs->targetLimit;
offsets=pArgs->offsets;
/* get the converter state from UConverter */
prev = static_cast<int32_t>(cnv->toUnicodeStatus); if(prev==0) {
prev=BOCU1_ASCII_PREV;
}
diff=cnv->mode; /* mode may be set to UCNV_SI by ucnv_bld.c but then toULength==0 */
count=diff&3;
diff>>=2;
byteIndex=cnv->toULength;
bytes=cnv->toUBytes;
/* sourceIndex=-1 if the current character began in the previous buffer */
sourceIndex=byteIndex==0 ? 0 : -1;
nextSourceIndex=0;
/* conversion "loop" similar to _SCSUToUnicodeWithOffsets() */ if(count>0 && byteIndex>0 && target<targetLimit) { goto getTrail;
}
fastSingle: /* fast loop for single-byte differences */ /* use count as the only loop counter variable */
diff = static_cast<int32_t>(sourceLimit - source);
count = static_cast<int32_t>(pArgs->targetLimit - target); if(count>diff) {
count=diff;
} while(count>0) { if(BOCU1_START_NEG_2<=(c=*source) && c<BOCU1_START_POS_2) {
c=prev+(c-BOCU1_MIDDLE); if(c<0x3000) {
*target++ = static_cast<char16_t>(c);
*offsets++=nextSourceIndex++;
prev=BOCU1_SIMPLE_PREV(c);
} else { break;
}
} elseif(c<=0x20) { if(c!=0x20) {
prev=BOCU1_ASCII_PREV;
}
*target++ = static_cast<char16_t>(c);
*offsets++=nextSourceIndex++;
} else { break;
}
++source;
--count;
}
sourceIndex=nextSourceIndex; /* wrong if offsets==nullptr but does not matter */
/* decode a sequence of single and lead bytes */ while(source<sourceLimit) { if(target>=targetLimit) { /* target is full */
*pErrorCode=U_BUFFER_OVERFLOW_ERROR; break;
}
if(*pErrorCode==U_ILLEGAL_CHAR_FOUND) { /* set the converter state in UConverter to deal with the next character */
cnv->toUnicodeStatus=BOCU1_ASCII_PREV;
cnv->mode=0;
} else { /* set the converter state back into UConverter */
cnv->toUnicodeStatus = static_cast<uint32_t>(prev);
cnv->mode = static_cast<int32_t>(static_cast<uint32_t>(diff) << 2) | count;
}
cnv->toULength=byteIndex;
/* write back the updated pointers */
pArgs->source = reinterpret_cast<constchar*>(source);
pArgs->target=target;
pArgs->offsets=offsets;
}
/* set up the local pointers */
cnv=pArgs->converter;
source = reinterpret_cast<const uint8_t*>(pArgs->source);
sourceLimit = reinterpret_cast<const uint8_t*>(pArgs->sourceLimit);
target=pArgs->target;
targetLimit=pArgs->targetLimit;
/* get the converter state from UConverter */
prev = static_cast<int32_t>(cnv->toUnicodeStatus); if(prev==0) {
prev=BOCU1_ASCII_PREV;
}
diff=cnv->mode; /* mode may be set to UCNV_SI by ucnv_bld.c but then toULength==0 */
count=diff&3;
diff>>=2;
byteIndex=cnv->toULength;
bytes=cnv->toUBytes;
/* conversion "loop" similar to _SCSUToUnicodeWithOffsets() */ if(count>0 && byteIndex>0 && target<targetLimit) { goto getTrail;
}
/* decode a sequence of single and lead bytes */ while(source<sourceLimit) { if(target>=targetLimit) { /* target is full */
*pErrorCode=U_BUFFER_OVERFLOW_ERROR; break;
}
if(*pErrorCode==U_ILLEGAL_CHAR_FOUND) { /* set the converter state in UConverter to deal with the next character */
cnv->toUnicodeStatus=BOCU1_ASCII_PREV;
cnv->mode=0;
} else { /* set the converter state back into UConverter */
cnv->toUnicodeStatus = static_cast<uint32_t>(prev);
cnv->mode = (static_cast<uint32_t>(diff) << 2) | count;
}
cnv->toULength=byteIndex;
/* write back the updated pointers */
pArgs->source = reinterpret_cast<constchar*>(source);
pArgs->target=target;
}
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.