public unsafe override int GetByteCount(char* chars, int count, EncoderNLS encoder)
{
// Just need to ASSERT, this is called by something else internal that checked parameters already
Debug.Assert(count >= 0, "[SBCSCodePageEncoding.GetByteCount]count is negative");
Debug.Assert(chars != null, "[SBCSCodePageEncoding.GetByteCount]chars is null");
// Assert because we shouldn't be able to have a null encoder.
Debug.Assert(EncoderFallback != null, "[SBCSCodePageEncoding.GetByteCount]Attempting to use null fallback");
CheckMemorySection();
// Need to test fallback
EncoderReplacementFallback fallback = null;
// Get any left over characters
char charLeftOver = (char)0;
if (encoder != null)
{
charLeftOver = encoder.charLeftOver;
Debug.Assert(charLeftOver == 0 || Char.IsHighSurrogate(charLeftOver),
"[SBCSCodePageEncoding.GetByteCount]leftover character should be high surrogate");
fallback = encoder.Fallback as EncoderReplacementFallback;
// Verify that we have no fallbackbuffer, actually for SBCS this is always empty, so just assert
Debug.Assert(!encoder.m_throwOnOverflow || !encoder.InternalHasFallbackBuffer ||
encoder.FallbackBuffer.Remaining == 0,
"[SBCSCodePageEncoding.GetByteCount]Expected empty fallback buffer at start");
}
else
{
// If we aren't using default fallback then we may have a complicated count.
fallback = EncoderFallback as EncoderReplacementFallback;
}
if ((fallback != null && fallback.MaxCharCount == 1)/* || bIsBestFit*/)
{
// Replacement fallback encodes surrogate pairs as two ?? (or two whatever), so return size is always
// same as input size.
// Note that no existing SBCS code pages map code points to supplementary characters, so this is easy.
// We could however have 1 extra byte if the last call had an encoder and a funky fallback and
// if we don't use the funky fallback this time.
// Do we have an extra char left over from last time?
if (charLeftOver > 0)
count++;
return (count);
}
// It had a funky fallback, so it's more complicated
// May need buffer later
EncoderFallbackBuffer fallbackBuffer = null;
// prepare our end
int byteCount = 0;
char* charEnd = chars + count;
EncoderFallbackBufferHelper fallbackHelper = new EncoderFallbackBufferHelper(fallbackBuffer);
// We may have a left over character from last time, try and process it.
if (charLeftOver > 0)
{
// Since leftover char was a surrogate, it'll have to be fallen back.
// Get fallback
Debug.Assert(encoder != null, "[SBCSCodePageEncoding.GetByteCount]Expect to have encoder if we have a charLeftOver");
fallbackBuffer = encoder.FallbackBuffer;
fallbackHelper = new EncoderFallbackBufferHelper(fallbackBuffer);
fallbackHelper.InternalInitialize(chars, charEnd, encoder, false);
// This will fallback a pair if *chars is a low surrogate
fallbackHelper.InternalFallback(charLeftOver, ref chars);
}
// Now we may have fallback char[] already from the encoder
// Go ahead and do it, including the fallback.
char ch;
while ((ch = (fallbackBuffer == null) ? '\0' : fallbackHelper.InternalGetNextChar()) != 0 || chars < charEnd)
{
// First unwind any fallback
if (ch == 0)
{
// No fallback, just get next char
ch = *chars;
chars++;
}
// get byte for this char
byte bTemp = _mapUnicodeToBytes[ch];
// Check for fallback, this'll catch surrogate pairs too.
if (bTemp == 0 && ch != (char)0)
{
if (fallbackBuffer == null)
{
// Create & init fallback buffer
if (encoder == null)
fallbackBuffer = EncoderFallback.CreateFallbackBuffer();
else
fallbackBuffer = encoder.FallbackBuffer;
fallbackHelper = new EncoderFallbackBufferHelper(fallbackBuffer);
// chars has moved so we need to remember figure it out so Exception fallback
// index will be correct
fallbackHelper.InternalInitialize(charEnd - count, charEnd, encoder, false);
}
// Get Fallback
fallbackHelper.InternalFallback(ch, ref chars);
continue;
}
// We'll use this one
byteCount++;
}
Debug.Assert(fallbackBuffer == null || fallbackBuffer.Remaining == 0,
"[SBCSEncoding.GetByteCount]Expected Empty fallback buffer at end");
return (int)byteCount;
}