/* check the input byte against the lowest and highest section bytes */
start = static_cast<int32_t>(UCNV_EXT_TO_U_GET_BYTE(toUSection[0]));
limit = static_cast<int32_t>(UCNV_EXT_TO_U_GET_BYTE(toUSection[length - 1])); if(byte<start || limit<byte) { return0; /* the byte is out of range */
}
if(length==((limit-start)+1)) { /* direct access on a linear array */ return UCNV_EXT_TO_U_GET_VALUE(toUSection[byte-start]); /* could be 0 */
}
/* word0 is suitable for <=toUSection[] comparison, word for <toUSection[] */
word0=UCNV_EXT_TO_U_MAKE_WORD(byte, 0);
if(sisoState==0) { /* SBCS state of an SI/SO stateful converter, look at only exactly 1 byte */ if(preLength>1) { return0; /* no match of a DBCS sequence in SBCS mode */
} elseif(preLength==1) {
srcLength=0;
} else/* preLength==0 */ { if(srcLength>1) {
srcLength=1;
}
}
flush=true;
}
/* we must not remember fallback matches when not using fallbacks */
/* match input units until there is a full match or the input is consumed */ for(;;) { /* go to the next section */
toUSection=toUTable+idx;
/* read first pair of the section */
value=*toUSection++;
length=UCNV_EXT_TO_U_GET_BYTE(value);
value=UCNV_EXT_TO_U_GET_VALUE(value); if( value!=0 &&
(UCNV_EXT_TO_U_IS_ROUNDTRIP(value) ||
TO_U_USE_FALLBACK(useFallback)) &&
UCNV_EXT_TO_U_VERIFY_SISO_MATCH(sisoState, i+j)
) { /* remember longest match so far */
matchValue=value;
matchLength=i+j;
}
/* match pre[] then src[] */ if(i<preLength) {
b = static_cast<uint8_t>(pre[i++]);
} elseif(j<srcLength) {
b = static_cast<uint8_t>(src[j++]);
} else { /* all input consumed, partial match */ if(flush || (length=(i+j))>UCNV_EXT_MAX_BYTES) { /* *endoftheentireinputstream,stopwiththelongestmatchsofar *or:partialmatchmustnotbelongerthanUCNV_EXT_MAX_BYTES *becauseitmustfitintostatebuffers
*/ break;
} else { /* continue with more input next time */ return -length;
}
}
/* search for the current char16_t */
value=ucnv_extFindToU(toUSection, length, b); if(value==0) { /* no match here, stop with the longest match so far */ break;
} else { if(UCNV_EXT_TO_U_IS_PARTIAL(value)) { /* partial match, continue */
idx = static_cast<int32_t>(UCNV_EXT_TO_U_GET_PARTIAL_INDEX(value));
} else { if( (UCNV_EXT_TO_U_IS_ROUNDTRIP(value) ||
TO_U_USE_FALLBACK(useFallback)) &&
UCNV_EXT_TO_U_VERIFY_SISO_MATCH(sisoState, i+j)
) { /* full match, stop with result */
matchValue=value;
matchLength=i+j;
} else { /* full match on fallback not taken, stop with the longest match so far */
} break;
}
}
}
if(matchLength==0) { /* no match at all */ return0;
}
/* return result */
*pMatchValue=UCNV_EXT_TO_U_MASK_ROUNDTRIP(matchValue); return matchLength;
}
staticinlinevoid
ucnv_extWriteToU(UConverter *cnv, const int32_t *cx,
uint32_t value,
char16_t **target, const char16_t *targetLimit,
int32_t **offsets, int32_t srcIndex,
UErrorCode *pErrorCode) { /* output the result */ if(UCNV_EXT_TO_U_IS_CODE_POINT(value)) { /* output a single code point */
ucnv_toUWriteCodePoint(
cnv, UCNV_EXT_TO_U_GET_CODE_POINT(value),
target, targetLimit,
offsets, srcIndex,
pErrorCode);
} else { /* output a string - with correct data we have resultLength>0 */
ucnv_toUWriteUChars(
cnv,
UCNV_EXT_ARRAY(cx, UCNV_EXT_TO_U_UCHARS_INDEX, char16_t)+
UCNV_EXT_TO_U_GET_INDEX(value),
UCNV_EXT_TO_U_GET_LENGTH(value),
target, targetLimit,
offsets, srcIndex,
pErrorCode);
}
}
/* try to match */
match=ucnv_extMatchToU(cx, (int8_t)UCNV_SISO_STATE(cnv),
(constchar *)cnv->toUBytes, firstLength,
*src, (int32_t)(srcLimit-*src),
&value,
cnv->useFallback, flush); if(match>0) { /* advance src pointer for the consumed input */
*src+=match-firstLength;
/* write result to target */
ucnv_extWriteToU(cnv, cx,
value,
target, targetLimit,
offsets, srcIndex,
pErrorCode); return true;
} elseif(match<0) { /* save state for partial match */ constchar *s;
int32_t j;
/* copy the first code point */
s=(constchar *)cnv->toUBytes;
cnv->preToUFirstLength=(int8_t)firstLength; for(j=0; j<firstLength; ++j) {
cnv->preToU[j]=*s++;
}
/* now copy the newly consumed input */
s=*src;
match=-match; for(; j<match; ++j) {
cnv->preToU[j]=*s++;
}
*src=s; /* same as *src=srcLimit; because we reached the end of input */
cnv->preToULength=(int8_t)match; return true;
} else/* match==0 no match */ { returnfalse;
}
}
U_CFUNC UChar32
ucnv_extSimpleMatchToU(const int32_t *cx, constchar *source, int32_t length,
UBool useFallback) {
uint32_t value = 0; /* initialize output-only param to 0 to silence gcc */
int32_t match;
if(length<=0) { return0xffff;
}
/* try to match */
match=ucnv_extMatchToU(cx, -1,
source, length,
nullptr, 0,
&value,
useFallback, true); if(match==length) { /* write result for simple, single-character conversion */ if(UCNV_EXT_TO_U_IS_CODE_POINT(value)) { return UCNV_EXT_TO_U_GET_CODE_POINT(value);
}
}
match=ucnv_extMatchToU(cnv->sharedData->mbcs.extIndexes, (int8_t)UCNV_SISO_STATE(cnv),
cnv->preToU, cnv->preToULength,
pArgs->source, (int32_t)(pArgs->sourceLimit-pArgs->source),
&value,
cnv->useFallback, pArgs->flush); if(match>0) { if(match>=cnv->preToULength) { /* advance src pointer for the consumed input */
pArgs->source+=match-cnv->preToULength;
cnv->preToULength=0;
} else { /* the match did not use all of preToU[] - keep the rest for replay */
length=cnv->preToULength-match;
uprv_memmove(cnv->preToU, cnv->preToU+match, length);
cnv->preToULength=(int8_t)-length;
}
/* write result */
ucnv_extWriteToU(cnv, cnv->sharedData->mbcs.extIndexes,
value,
&pArgs->target, pArgs->targetLimit,
&pArgs->offsets, srcIndex,
pErrorCode);
} elseif(match<0) { /* save state for partial match */ constchar *s;
int32_t j;
/* just _append_ the newly consumed input to preToU[] */
s=pArgs->source;
match=-match; for(j=cnv->preToULength; j<match; ++j) {
cnv->preToU[j]=*s++;
}
pArgs->source=s; /* same as *src=srcLimit; because we reached the end of input */
cnv->preToULength=(int8_t)match;
} else/* match==0 */ { /* *nomatch * *Weneedtosplitthepreviousinputintotwoparts: * *1.Thefirstcodepagecharacterisunmappable-that'showwegotinto *tryingtheextensiondatainthefirstplace. *WeneedtomoveitfromthepreToUbuffer *totheerrorbuffer,setanerrorcode, *andpreparetherestofthepreviousinputfor2. * *2.Therestofthepreviousinputmustbeconvertedoncewe *comebackfromthecallbackforthefirstcharacter. *Atthattime,wehavetotryagainfromscratchtoconvert *theseinputcharacters. *Thereplaywillbehandledbytheucnv.cconversioncode.
*/
/* move the first codepage character to the error field */
uprv_memcpy(cnv->toUBytes, cnv->preToU, cnv->preToUFirstLength);
cnv->toULength=cnv->preToUFirstLength;
/* move the rest up inside the buffer */
length=cnv->preToULength-cnv->preToUFirstLength; if(length>0) {
uprv_memmove(cnv->preToU, cnv->preToU+cnv->preToUFirstLength, length);
}
/* mark preToU for replay */
cnv->preToULength=(int8_t)-length;
/* set the error code for unassigned */
*pErrorCode=U_INVALID_CHAR_FOUND;
}
}
/* from Unicode ------------------------------------------------------------- */
// Use roundtrips, "good one-way" mappings, and some normal fallbacks. staticinline UBool
extFromUUseMapping(UBool useFallback, uint32_t value, UChar32 firstCP) { return
((value&UCNV_EXT_FROM_U_STATUS_MASK)!=0 ||
FROM_U_USE_FALLBACK(useFallback, firstCP)) &&
(value&UCNV_EXT_FROM_U_RESERVED_MASK)==0;
}
if(cx==nullptr) { return0; /* no extension data, no match */
}
/* trie lookup of firstCP */
idx=firstCP>>10; /* stage 1 index */ if(idx>=cx[UCNV_EXT_FROM_U_STAGE_1_LENGTH]) { return0; /* the first code point is outside the trie */
}
/* we must not remember fallback matches when not using fallbacks */
/* match input units until there is a full match or the input is consumed */ for(;;) { /* go to the next section */
fromUSectionUChars=fromUTableUChars+idx;
fromUSectionValues=fromUTableValues+idx;
/* read first pair of the section */
length=*fromUSectionUChars++;
value=*fromUSectionValues++; if(value!=0 && extFromUUseMapping(useFallback, value, firstCP)) { /* remember longest match so far */
matchValue=value;
matchLength=2+i+j;
}
/* match pre[] then src[] */ if(i<preLength) {
c=pre[i++];
} elseif(j<srcLength) {
c=src[j++];
} else { /* all input consumed, partial match */ if(flush || (length=(i+j))>UCNV_EXT_MAX_UCHARS) { /* *endoftheentireinputstream,stopwiththelongestmatchsofar *or:partialmatchmustnotbelongerthanUCNV_EXT_MAX_UCHARS *becauseitmustfitintostatebuffers
*/ break;
} else { /* continue with more input next time */ return -(2+length);
}
}
/* search for the current char16_t */
idx=ucnv_extFindFromU(fromUSectionUChars, length, c); if(idx<0) { /* no match here, stop with the longest match so far */ break;
} else {
value=fromUSectionValues[idx]; if(UCNV_EXT_FROM_U_IS_PARTIAL(value)) { /* partial match, continue */
idx = static_cast<int32_t>(UCNV_EXT_FROM_U_GET_PARTIAL_INDEX(value));
} else { if(extFromUUseMapping(useFallback, value, firstCP)) { /* full match, stop with result */
matchValue=value;
matchLength=2+i+j;
} else { /* full match on fallback not taken, stop with the longest match so far */
} break;
}
}
}
if(matchLength==0) { /* no match at all */ return0;
}
} else/* result from firstCP trie lookup */ { if(extFromUUseMapping(useFallback, value, firstCP)) { /* full match, stop with result */
matchValue=value;
matchLength=2;
} else { /* fallback not taken */ return0;
}
}
/* try to match */
match=ucnv_extMatchFromU(cx, cp,
nullptr, 0,
*src, (int32_t)(srcLimit-*src),
&value,
cnv->useFallback, flush);
/* reject a match if the result is a single byte for DBCS-only */ if( match>=2 &&
!(UCNV_EXT_FROM_U_GET_LENGTH(value)==1 &&
cnv->sharedData->mbcs.outputType==MBCS_OUTPUT_DBCS_ONLY)
) { /* advance src pointer for the consumed input */
*src+=match-2; /* remove 2 for the initial code point */
/* write result to target */
ucnv_extWriteFromU(cnv, cx,
value,
target, targetLimit,
offsets, srcIndex,
pErrorCode); return true;
} elseif(match<0) { /* save state for partial match */ const char16_t *s;
int32_t j;
/* copy the first code point */
cnv->preFromUFirstCP=cp;
/* now copy the newly consumed input */
s=*src;
match=-match-2; /* remove 2 for the initial code point */ for(j=0; j<match; ++j) {
cnv->preFromU[j]=*s++;
}
*src=s; /* same as *src=srcLimit; because we reached the end of input */
cnv->preFromULength=(int8_t)match; return true;
} elseif(match==1) { /* matched, no mapping but request for <subchar1> */
cnv->useSubChar1=true; returnfalse;
} else/* match==0 no match */ { returnfalse;
}
}
match=ucnv_extMatchFromU(cnv->sharedData->mbcs.extIndexes,
cnv->preFromUFirstCP,
cnv->preFromU, cnv->preFromULength,
pArgs->source, (int32_t)(pArgs->sourceLimit-pArgs->source),
&value,
cnv->useFallback, pArgs->flush); if(match>=2) {
match-=2; /* remove 2 for the initial code point */
if(match>=cnv->preFromULength) { /* advance src pointer for the consumed input */
pArgs->source+=match-cnv->preFromULength;
cnv->preFromULength=0;
} else { /* the match did not use all of preFromU[] - keep the rest for replay */
int32_t length=cnv->preFromULength-match;
u_memmove(cnv->preFromU, cnv->preFromU+match, length);
cnv->preFromULength=(int8_t)-length;
}
/* finish the partial match */
cnv->preFromUFirstCP=U_SENTINEL;
/* write result */
ucnv_extWriteFromU(cnv, cnv->sharedData->mbcs.extIndexes,
value,
&pArgs->target, pArgs->targetLimit,
&pArgs->offsets, srcIndex,
pErrorCode);
} elseif(match<0) { /* save state for partial match */ const char16_t *s;
int32_t j;
/* just _append_ the newly consumed input to preFromU[] */
s=pArgs->source;
match=-match-2; /* remove 2 for the initial code point */ for(j=cnv->preFromULength; j<match; ++j) {
U_ASSERT(j>=0);
cnv->preFromU[j]=*s++;
}
pArgs->source=s; /* same as *src=srcLimit; because we reached the end of input */
cnv->preFromULength=(int8_t)match;
} else/* match==0 or 1 */ { /* *nomatch * *Weneedtosplitthepreviousinputintotwoparts: * *1.Thefirstcodepointisunmappable-that'showwegotinto *tryingtheextensiondatainthefirstplace. *WeneedtomoveitfromthepreFromUbuffer *totheerrorbuffer,setanerrorcode, *andpreparetherestofthepreviousinputfor2. * *2.Therestofthepreviousinputmustbeconvertedoncewe *comebackfromthecallbackforthefirstcodepoint. *Atthattime,wehavetotryagainfromscratchtoconvert *theseinputcharacters. *Thereplaywillbehandledbytheucnv.cconversioncode.
*/
if(match==1) { /* matched, no mapping but request for <subchar1> */
cnv->useSubChar1=true;
}
/* move the first code point to the error field */
cnv->fromUChar32=cnv->preFromUFirstCP;
cnv->preFromUFirstCP=U_SENTINEL;
/* mark preFromU for replay */
cnv->preFromULength=-cnv->preFromULength;
/* set the error code for unassigned */
*pErrorCode=U_INVALID_CHAR_FOUND;
}
}
static UBool
extSetUseMapping(UConverterUnicodeSet which, int32_t minLength, uint32_t value) { if(which==UCNV_ROUNDTRIP_SET) { // Add only code points for which the roundtrip flag is set. // Do not add any fallbacks, even if ucnv_fromUnicode() would use them // (fallbacks from PUA). See the API docs for ucnv_getUnicodeSet(). // // By analogy, also do not add "good one-way" mappings. // // Do not add entries with reserved bits set. if(((value&(UCNV_EXT_FROM_U_ROUNDTRIP_FLAG|UCNV_EXT_FROM_U_RESERVED_MASK))!=
UCNV_EXT_FROM_U_ROUNDTRIP_FLAG)) { returnfalse;
}
} else/* UCNV_ROUNDTRIP_AND_FALLBACK_SET */ { // Do not add entries with reserved bits set. if((value&UCNV_EXT_FROM_U_RESERVED_MASK)!=0) { returnfalse;
}
} // Do not add <subchar1> entries or other (future?) pseudo-entries // with an output length of 0. return UCNV_EXT_FROM_U_GET_LENGTH(value)>=minLength;
}
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.