[System.Security.SecurityCritical] // auto-generated
private unsafe int GetCharsCP5022xJP(byte* bytes, int byteCount,
char* chars, int charCount, ISO2022Decoder decoder)
{
// Get our info.
Encoding.EncodingCharBuffer buffer = new Encoding.EncodingCharBuffer(
this, decoder, chars, charCount, bytes, byteCount);
// No mode information yet
ISO2022Modes currentMode = ISO2022Modes.ModeASCII; // Our current Mode
ISO2022Modes shiftInMode = ISO2022Modes.ModeASCII; // Mode that we'll shift in to
byte[] escapeBytes = new byte[4];
int escapeCount = 0;
if (decoder != null)
{
currentMode = decoder.currentMode;
shiftInMode = decoder.shiftInOutMode;
// See if we have leftover decoder buffer to use
// Load our bytesLeftOver
escapeCount = decoder.bytesLeftOverCount;
// Don't want to mess up decoder if we're counting or throw an exception
for (int i = 0; i < escapeCount; i++)
escapeBytes[i] = decoder.bytesLeftOver[i];
}
// Do this until the end
while (buffer.MoreData || escapeCount > 0)
{
byte ch;
if (escapeCount > 0)
{
// Get more escape sequences if necessary
if (escapeBytes[0] == ESCAPE)
{
// Stop if no more input
if (!buffer.MoreData)
{
if (decoder != null && !decoder.MustFlush)
break;
}
else
{
// Add it to the sequence we can check
escapeBytes[escapeCount++] = buffer.GetNextByte();
// We have an escape sequence
ISO2022Modes modeReturn =
CheckEscapeSequenceJP(escapeBytes, escapeCount);
if (modeReturn != ISO2022Modes.ModeInvalidEscape)
{
if (modeReturn != ISO2022Modes.ModeIncompleteEscape)
{
// Processed escape correctly
escapeCount = 0;
// We're now this mode
currentMode = shiftInMode = modeReturn;
}
// Either way, continue to get next escape or real byte
continue;
}
}
// If ModeInvalidEscape, or no input & must flush, then fall through to add escape.
}
// Read next escape byte and move them down one.
ch = DecrementEscapeBytes(ref escapeBytes, ref escapeCount);
}
else
{
// Get our next byte
ch = buffer.GetNextByte();
if (ch == ESCAPE)
{
// We'll have an escape sequence, use it if we don't have one buffered already
if (escapeCount == 0)
{
// Start this new escape sequence
escapeBytes[0] = ch;
escapeCount = 1;
continue;
}
// Flush the previous escape sequence, then reuse this escape byte
buffer.AdjustBytes(-1);
}
}
if (ch == SHIFT_OUT)
{
shiftInMode = currentMode;
currentMode = ISO2022Modes.ModeHalfwidthKatakana;
continue;
}
else if (ch == SHIFT_IN)
{
currentMode = shiftInMode;
continue;
}
// Get our full character
ushort iBytes = ch;
bool b2Bytes = false;
if (currentMode == ISO2022Modes.ModeJIS0208)
{
//
// To handle errors, we need to check:
// 1. if trailbyte is there
// 2. if code is valid
//
if (escapeCount > 0)
{
// Let another escape fall through
if (escapeBytes[0] != ESCAPE)
{
// Move them down one & get the next data
iBytes <<= 8;
iBytes |= DecrementEscapeBytes(ref escapeBytes, ref escapeCount);
b2Bytes = true;
}
}
else if (buffer.MoreData)
{
iBytes <<= 8;
iBytes |= buffer.GetNextByte();
b2Bytes = true;
}
else
{
// Not enough input, use decoder if possible
if (decoder == null || decoder.MustFlush)
{
// No decoder, do fallback for this byte
buffer.Fallback(ch);
break;
}
// Stick it in the decoder if we're not counting
if (chars != null)
{
escapeBytes[0] = ch;
escapeCount = 1;
}
break;
}
// MLang treated JIS 0208 '*' lead byte like a single halfwidth katakana
// escape, so use 0x8e00 as katakana lead byte and keep same trail byte.
// 0x2a lead byte range is normally unused in JIS 0208, so shouldn't have
// any wierd compatibility issues.
if ((b2Bytes == true) && ((iBytes & 0xff00) == 0x2a00))
{
iBytes = (ushort)(iBytes & 0xff);
iBytes |= (LEADBYTE_HALFWIDTH << 8); // Put us in the halfwidth katakana range
}
}
else if (iBytes >= 0xA1 && iBytes <= 0xDF)
{
// Everett accidentally mapped Katakana like shift-jis (932),
// even though this is a 7 bit code page. We keep that mapping
iBytes |= (LEADBYTE_HALFWIDTH << 8); // Map to halfwidth katakana range
iBytes &= 0xff7f; // remove extra 0x80
}
else if (currentMode == ISO2022Modes.ModeHalfwidthKatakana )
{
// Add 0x10 lead byte that our encoding expects for Katakana:
iBytes |= (LEADBYTE_HALFWIDTH << 8);
}
// We have an iBytes to try to convert.
char c = mapBytesToUnicode[iBytes];
// See if it was unknown
if (c == UNKNOWN_CHAR_FLAG && iBytes != 0)
{
// Have to do fallback
if (b2Bytes)
{
if (!buffer.Fallback((byte)(iBytes >> 8), (byte)iBytes))
break;
}
else
{
if (!buffer.Fallback(ch))
break;
}
}
else
{
// If we were JIS 0208, then we consumed an extra byte
if (!buffer.AddChar(c, b2Bytes ? 2:1))
break;
}
}
// Make sure our decoder state matches our mode, if not counting
if (chars != null && decoder != null)
{
// Remember it if we don't flush
if (!decoder.MustFlush || escapeCount != 0)
{
// Either not flushing or had state (from convert)
Contract.Assert(!decoder.MustFlush || !decoder.m_throwOnOverflow,
"[ISO2022Encoding.GetCharsCP5022xJP]Expected no state or not converting or not flushing");
decoder.currentMode = currentMode;
decoder.shiftInOutMode = shiftInMode;
// Remember escape buffer
decoder.bytesLeftOverCount = escapeCount;
decoder.bytesLeftOver = escapeBytes;
}
else
{
// We flush, clear buffer
decoder.currentMode = ISO2022Modes.ModeASCII;
decoder.shiftInOutMode = ISO2022Modes.ModeASCII;
decoder.bytesLeftOverCount = 0;
// Slightly different if counting/not counting
}
decoder.m_bytesUsed = buffer.BytesUsed;
}
// Return # of characters we found
return buffer.Count;
}