private unsafe int GetBytesCP50225KR(char* chars, int charCount,
byte* bytes, int byteCount, ISO2022Encoder encoder)
{
// prepare our helpers
EncodingByteBuffer buffer = new EncodingByteBuffer(this, encoder, bytes, byteCount, chars, charCount);
// Get our mode
ISO2022Modes currentMode = ISO2022Modes.ModeASCII; // Mode
ISO2022Modes shiftOutMode = ISO2022Modes.ModeASCII; // ModeKR if already stamped lead bytes
// Check our encoder
if (encoder != null)
{
// May have leftover stuff
char charLeftOver = encoder.charLeftOver;
currentMode = encoder.currentMode;
shiftOutMode = encoder.shiftInOutMode;
// We may have a l left over character from last time, try and process it.
if (charLeftOver > 0)
{
Debug.Assert(Char.IsHighSurrogate(charLeftOver), "[ISO2022Encoding.GetBytesCP50225KR]leftover character should be high surrogate");
// It has to be a high surrogate, which we don't support, so it has to be a fallback
buffer.Fallback(charLeftOver);
}
}
while (buffer.MoreData)
{
// Get our data
char ch = buffer.GetNextChar();
// Get our bytes
ushort iBytes = mapUnicodeToBytes[ch];
// Check for double byte bytes
byte bLeadByte = (byte)(iBytes >> 8);
byte bTrailByte = (byte)(iBytes & 0xff);
if (bLeadByte != 0)
{
//
// It's a double byte character.
//
// If we haven't done our Korean designator, then do so, if we have any input
if (shiftOutMode != ISO2022Modes.ModeKR)
{
// Add our code page designator sequence
if (!buffer.AddByte(ESCAPE, unchecked((byte)'$'), unchecked((byte)')'), unchecked((byte)'C')))
break; // No room during convert.
shiftOutMode = ISO2022Modes.ModeKR;
}
// May have to switch to ModeKR first
if (currentMode != ISO2022Modes.ModeKR)
{
if (!buffer.AddByte(SHIFT_OUT))
break; // No convert room
currentMode = ISO2022Modes.ModeKR;
}
// Add the bytes
if (!buffer.AddByte(bLeadByte, bTrailByte))
break; // no convert room
continue;
}
else if (iBytes != 0 || ch == 0)
{
// Its a single byte character, switch to ASCII if we have to
if (currentMode != ISO2022Modes.ModeASCII)
{
if (!buffer.AddByte(SHIFT_IN))
break;
currentMode = ISO2022Modes.ModeASCII;
}
// Add the ASCII char
if (!buffer.AddByte(bTrailByte))
break;
continue;
}
// Its unknown, do fallback, throws if recursive (knows because we called InternalGetNextChar)
buffer.Fallback(ch);
}
// Switch back to ASCII if MustFlush or no encoder
if (currentMode != ISO2022Modes.ModeASCII &&
(encoder == null || encoder.MustFlush))
{
// Get back to ASCII to be safe. Only do it if it success.
if (buffer.AddByte(SHIFT_IN))
currentMode = ISO2022Modes.ModeASCII;
else
// If not successful, convert will maintain state for next time, also
// AddByte will have decremented our char count, however we need it to remain the same
buffer.GetNextChar();
}
// Remember our encoder state
if (bytes != null && encoder != null)
{
// If we didn't use the encoder, then there's no chars left over
if (!buffer.fallbackBufferHelper.bUsedEncoder)
{
encoder.charLeftOver = (char)0;
}
// This is ASCII if we had to flush
encoder.currentMode = currentMode;
// We don't use shift out mode, but if we've flushed we need to reset it so it doesn't
// get output again.
if (!encoder.MustFlush || encoder.charLeftOver != (char)0)
{
// We should be not flushing or converting
Debug.Assert(!encoder.MustFlush || !encoder.m_throwOnOverflow,
"[ISO2022Encoding.GetBytesCP50225KR]Expected no left over data or not flushing or not converting");
encoder.shiftInOutMode = shiftOutMode;
}
else
encoder.shiftInOutMode = ISO2022Modes.ModeASCII;
encoder.m_charsUsed = buffer.CharsUsed;
}
// Return our length
return buffer.Count;
}