Thecharactersetsarearrangedsothatthesinglebytesetsallappear beforethemulti-bytecharactersets.Whenweneedtotellwhethera
group byte is for a single byte char set or not we use this define: */
#define ULMBCS_HT 0x09 /* Fixed control char - Horizontal Tab */ #define ULMBCS_LF 0x0A /* Fixed control char - Line Feed */ #define ULMBCS_CR 0x0D /* Fixed control char - Carriage Return */
/* Then, 1-2-3 reserved a special single-byte character to put at the
beginning of internal 'system' range names: */
#define ULMBCS_123SYSTEMRANGE 0x19
/* Then we needed a place to put all the other ansi control characters thatmustbemovedtodifferentvaluesbecauseLMBCSreservesthose valuesforotherpurposes.Torepresentthecontrolcharacters,westart withafirstbyteof0xF&addthecontrolcharactervalueasthe
second byte */ #define ULMBCS_GRP_CTRL 0x0F
/* For the C0 controls (less than 0x20), we add 0x20 to preserve the usefuldoctrinethatanybytelessthan0x20inaLMBCScharmustbe
the first byte of a character:*/ #define ULMBCS_CTRLOFFSET 0x20
[G]D1, where'G'wasoneofthesingle-bytecharactergroups,and D1waslessthan0x80.Thesesequencesaregatheredtogether intoaLotus-inventeddoublebytecharactersettorepresenta lotofstrayvalues.Internally,inthisimplementation,wetrackthis
as group '0', as a place to tuck this exceptions list.*/
#define ULMBCS_GRP_EXCEPT 0x00 /* Finally,asthedurabilityandusefulnessofUNICODEbecameclear, LOTUSaddedanewgroup0x14toholdUnicodevaluesnototherwise
represented in LMBCS: */ #define ULMBCS_GRP_UNICODE 0x14 /* The two bytes appearing after a 0x14 are interpreted as UFT-16 BE (Big-Endian)characters.TheexceptioncomeswhentheUTF16 representationwouldhaveazeroasthesecondbyte.Inthatcase, 'F6'isusedinitsplace,andthebytesareswapped.(Thisprevents LMBCSfromencodinganyUnicodevaluesoftheformU+F6xx,butthat'sOK:
0xF6xx is in the middle of the Private Use Area.)*/ #define ULMBCS_UNICOMPATZERO 0xF6
/* It is also useful in our code to have a constant for the size of
a LMBCS char that holds a literal Unicode value */ #define ULMBCS_UNICODE_SIZE 3
For Notes, the optimzation group is always 0x1.*/ #define ULMBCS_DEFAULTOPTGROUP 0x1 /* For 1-2-3 files, the optimzation group is stored in the header of the 1-2-3 file.
Becauseoftheextensiveuseofothercharactersets,theLMBCSconverter keepsamappingbetweenoptimizationgroupsandIBMcharactersets,sothat
ICU converters can be created and used as needed. */
/* As you can see, even though any byte below 0x20 could be an optimization byte,onlythoseat0x13orbelowcanmaptoanactualconverter.Tolimit
some loops and searches, we define a value for that last group converter:*/
#define ULMBCS_GRP_LAST 0x13 /* last LMBCS group that has a converter */
#define ULMBCS_AMBIGUOUS_SBCS 0x80 /* could fit in more than one LMBCSsbcsnativeencoding
(example: most accented latin) */ #define ULMBCS_AMBIGUOUS_MBCS 0x81 /* could fit in more than one LMBCSmbcsnativeencoding
(example: Unihan) */ #define ULMBCS_AMBIGUOUS_ALL 0x82 /* And here's a simple way to see if a group falls in an appropriate range */ #define ULMBCS_AMBIGUOUS_MATCH(agroup, xgroup) \
((((agroup) == ULMBCS_AMBIGUOUS_SBCS) && \
(xgroup) < ULMBCS_DOUBLEOPTGROUP_START) || \
(((agroup) == ULMBCS_AMBIGUOUS_MBCS) && \
(xgroup) >= ULMBCS_DOUBLEOPTGROUP_START)) || \
((agroup) == ULMBCS_AMBIGUOUS_ALL)
/* Wealsoaskthecreatorofaconvertertosendinapreferredlocale thatwecanuseinresolvingambiguousmappings.Theysendthelocale inasastring,andwemapit,ifpossible,tooneofthe LMBCSgroups.Weusethistable,andtheassociatedcode,to
do the lookup: */
/* The only function we needed to duplicate 12 times was the 'open' function,whichwilldobasicallythesamethingexceptsetadifferent optimizationgroup.So,weputthecommonstuffintoaworkerfunction,
and set up another macro to stamp out the 12 open functions:*/ #define DEFINE_LMBCS_OPEN(n) \ staticvoid U_CALLCONV \
_LMBCSOpen##n(UConverter* _this, UConverterLoadArgs* pArgs, UErrorCode* err) \
{ _LMBCSOpenWorker(_this, pArgs, err, n); }
/* Here's the open worker & the common close function */ staticvoid
_LMBCSOpenWorker(UConverter* _this,
UConverterLoadArgs *pArgs,
UErrorCode* err,
ulmbcs_byte_t OptGroup)
{
UConverterDataLMBCS* extraInfo = static_cast<UConverterDataLMBCS*>(uprv_malloc(sizeof(UConverterDataLMBCS)));
_this->extraInfo = extraInfo; if(extraInfo != nullptr)
{
UConverterNamePieces stackPieces;
UConverterLoadArgs stackArgs= UCNV_LOAD_ARGS_INITIALIZER;
ulmbcs_byte_t i;
static size_t
LMBCSConversionWorker (
UConverterDataLMBCS * extraInfo, /* subconverters, opt & locale groups */
ulmbcs_byte_t group, /* The group to try */
ulmbcs_byte_t * pStartLMBCS, /* where to put the results */
char16_t * pUniChar, /* The input unicode character */
ulmbcs_byte_t * lastConverterIndex, /* output: track last successful group used */
UBool * groups_tried /* output: track any unsuccessful groups */
)
{
ulmbcs_byte_t * pLMBCS = pStartLMBCS;
UConverterSharedData * xcnv = extraInfo->OptGrpConverter[group];
int bytesConverted;
uint32_t value;
ulmbcs_byte_t firstByte;
/* get the first result byte */ if(bytesConverted > 0) {
firstByte = (ulmbcs_byte_t)(value >> ((bytesConverted - 1) * 8));
} else { /* most common failure mode is an unassigned character */
groups_tried[group] = true; return0;
}
*lastConverterIndex = group;
/* All initial byte values in lower ascii range should have been caught by now, exceptwiththeexceptiongroup.
*/
U_ASSERT((firstByte <= ULMBCS_C0END) || (firstByte >= ULMBCS_C1START) || (group == ULMBCS_GRP_EXCEPT));
/* use converted data: first write 0, 1 or two group bytes */ if (group != ULMBCS_GRP_EXCEPT && extraInfo->OptGroup != group)
{
*pLMBCS++ = group; if (bytesConverted == 1 && group >= ULMBCS_DOUBLEOPTGROUP_START)
{
*pLMBCS++ = group;
}
}
/* don't emit control chars */ if ( bytesConverted == 1 && firstByte < 0x20 ) return0;
/* then move over the converted data */ switch(bytesConverted)
{ case4:
*pLMBCS++ = (ulmbcs_byte_t)(value >> 24);
U_FALLTHROUGH; case3:
*pLMBCS++ = (ulmbcs_byte_t)(value >> 16);
U_FALLTHROUGH; case2:
*pLMBCS++ = (ulmbcs_byte_t)(value >> 8);
U_FALLTHROUGH; case1:
*pLMBCS++ = (ulmbcs_byte_t)value;
U_FALLTHROUGH; default: /* will never occur */ break;
}
return (pLMBCS - pStartLMBCS);
}
/* This is a much simpler version of above, when we knowwearewritingLMBCSusingtheUnicodegroup
*/ static size_t
LMBCSConvertUni(ulmbcs_byte_t * pLMBCS, char16_t uniChar)
{ /* encode into LMBCS Unicode range */
uint8_t LowCh = (uint8_t)(uniChar & 0x00FF);
uint8_t HighCh = (uint8_t)(uniChar >> 8);
bytes_written = (int32_t)(pLMBCS - LMBCS);
} elseif (group == ULMBCS_GRP_CTRL) /* (Strategy 2B) */
{ /* Handle control characters here */ if (uniChar <= ULMBCS_C0END)
{
*pLMBCS++ = ULMBCS_GRP_CTRL;
*pLMBCS++ = (ulmbcs_byte_t)(ULMBCS_CTRLOFFSET + uniChar);
} elseif (uniChar >= ULMBCS_C1START && uniChar <= ULMBCS_C1START + ULMBCS_CTRLOFFSET)
{
*pLMBCS++ = ULMBCS_GRP_CTRL;
*pLMBCS++ = (ulmbcs_byte_t ) (uniChar & 0x00FF);
}
bytes_written = (int32_t)(pLMBCS - LMBCS);
} elseif (group < ULMBCS_GRP_UNICODE) /* (Strategy 2C) */
{ /* a specific converter has been identified - use it */
bytes_written = (int32_t)LMBCSConversionWorker (
extraInfo, group, pLMBCS, &uniChar,
&lastConverterIndex, groups_tried);
} if (!bytes_written) /* the ambiguous group cases (Strategy 3) */
{
uprv_memset(groups_tried, 0, sizeof(groups_tried));
/* check for non-default optimization group (Strategy 3A )*/ if ((extraInfo->OptGroup != 1) && (ULMBCS_AMBIGUOUS_MATCH(group, extraInfo->OptGroup)))
{ /*zhujin: upgrade, merge #39299 here (Lotus) */ /*To make R5 compatible translation, look for exceptional group first for non-DBCS*/
/* we have a translation. increment source and write as much as possible to target */
args->source++;
pLMBCS = LMBCS; while (args->target < args->targetLimit && bytes_written--)
{
*(args->target)++ = *pLMBCS++; if (args->offsets)
{
*(args->offsets)++ = sourceIndex;
}
}
sourceIndex++; if (bytes_written > 0)
{ /* write any bytes that didn't fit in target to the error buffer, commoncodewillmovethistotargetifwegetcalledbackwith enoughtargetroom
*/
uint8_t * pErrorBuffer = args->converter->charErrorBuffer;
*err = U_BUFFER_OVERFLOW_ERROR;
args->converter->charErrorBufferLength = (int8_t)bytes_written; while (bytes_written--)
{
*pErrorBuffer++ = *pLMBCS++;
}
} /*Fix for SPR#DJOE66JFN3 (Lotus)*/
extraInfo->localeConverterIndex = OldConverterIndex;
}
}
/* Now, the Unicode from LMBCS section */
/* A function to call when we are looking at the Unicode group byte in LMBCS */ static char16_t
GetUniFromLMBCSUni(charconst ** ppLMBCSin) /* Called with LMBCS-style Unicode byte stream */
{
uint8_t HighCh = *(*ppLMBCSin)++; /* Big-endian Unicode in LMBCS compatibility group*/
uint8_t LowCh = *(*ppLMBCSin)++;
if (HighCh == ULMBCS_UNICOMPATZERO )
{
HighCh = LowCh;
LowCh = 0; /* zero-byte in LSB special character */
} return (char16_t)((HighCh << 8) | LowCh);
}
/* CHECK_SOURCE_LIMIT: Helper macro to verify that there are at least'index' bytesleftinsourceuptosourceLimit.Errorsappropriatelyifnot. Ifwereachthelimit,thenupdatethesourcepointertotheretoconsume allinputasrequiredbyICUconvertersemantics.
*/
if (CurByte >= ULMBCS_C1START)
{
uniChar = _MBCS_SINGLE_SIMPLE_GET_NEXT_BMP(cnv, CurByte);
} else
{ /* The non-optimizable oddballs where there is an explicit byte *ANDthesecondbyteisnotintheupperasciirange
*/ char bytes[2];
/* Lookup value must include opt group */
bytes[0] = group;
bytes[1] = CurByte;
uniChar = ucnv_MBCSSimpleGetNextUChar(cnv, bytes, 2, false);
}
}
} elseif (CurByte >= ULMBCS_C1START) /* group byte is implicit */
{
extraInfo = (UConverterDataLMBCS *) args->converter->extraInfo;
group = extraInfo->OptGroup;
cnv = extraInfo->OptGrpConverter[group]; if (group >= ULMBCS_DOUBLEOPTGROUP_START) /* double byte conversion */
{ if (!ucnv_MBCSIsLeadByte(cnv, CurByte))
{
CHECK_SOURCE_LIMIT(0);
/* let the MBCS conversion consume CurByte again */
uniChar = ucnv_MBCSSimpleGetNextUChar(cnv, args->source - 1, 1, false);
} else
{
CHECK_SOURCE_LIMIT(1); /* let the MBCS conversion consume CurByte again */
uniChar = ucnv_MBCSSimpleGetNextUChar(cnv, args->source - 1, 2, false);
++args->source;
}
} else/* single byte conversion */
{
uniChar = _MBCS_SINGLE_SIMPLE_GET_NEXT_BMP(cnv, CurByte);
}
}
} return uniChar;
}
/* The exported function that converts lmbcs to one or more UChars-currentlyUTF-16
*/ staticvoid U_CALLCONV
_LMBCSToUnicodeWithOffsets(UConverterToUnicodeArgs* args,
UErrorCode* err)
{ char LMBCS [ULMBCS_CHARSIZE_MAX];
char16_t uniChar; /* one output UNICODE char */ constchar * saveSource; /* beginning of current code point */ constchar * pStartLMBCS = args->source; /* beginning of whole string */ constchar * errSource = nullptr; /* pointer to actual input in case an error occurs */
int8_t savebytes = 0;
/* Process from source to limit, or until error */ while (U_SUCCESS(*err) && args->sourceLimit > args->source && args->targetLimit > args->target)
{
saveSource = args->source; /* beginning of current code point */
if (args->converter->toULength) /* reassemble char from previous call */
{ constchar *saveSourceLimit;
size_t size_old = args->converter->toULength;
/* limit from source is either remainder of temp buffer, or user limit on source */
size_t size_new_maybe_1 = sizeof(LMBCS) - size_old;
size_t size_new_maybe_2 = args->sourceLimit - args->source;
size_t size_new = (size_new_maybe_1 < size_new_maybe_2) ? size_new_maybe_1 : size_new_maybe_2;
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.