internal override unsafe int GetByteCount(char* chars, int charCount, EncoderNLS encoder)
{
// Just need to ASSERT, this is called by something else internal that checked parameters already
BCLDebug.Assert(charCount >= 0, "[Latin1Encoding.GetByteCount]count is negative");
BCLDebug.Assert(chars != null, "[Latin1Encoding.GetByteCount]chars is null");
// Assert because we shouldn't be able to have a null encoder.
BCLDebug.Assert(encoderFallback != null, "[Latin1Encoding.GetByteCount]Attempting to use null fallback encoder");
char charLeftOver = (char)0;
// If we have an encoder AND we aren't using default fallback,
// then we may have a complicated count.
EncoderReplacementFallback fallback;
if (encoder != null)
{
charLeftOver = encoder.charLeftOver;
BCLDebug.Assert(charLeftOver == 0 || Char.IsHighSurrogate(charLeftOver),
"[Latin1Encoding.GetByteCount]leftover character should be high surrogate");
fallback = encoder.Fallback as EncoderReplacementFallback;
// Verify that we have no fallbackbuffer, for Latin1 its always empty, so just assert
BCLDebug.Assert(!encoder.m_throwOnOverflow || !encoder.InternalHasFallbackBuffer ||
encoder.FallbackBuffer.Remaining == 0,
"[Latin1CodePageEncoding.GetByteCount]Expected empty fallback buffer");
}
else
fallback = this.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 supplimentary 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)
charCount++;
return (charCount);
}
// Count is more complicated if you have a funky fallback
// For fallback we may need a fallback buffer, we know we're not default fallback
int byteCount = 0;
// Start by assuming default count, then +/- for fallback characters
char* charEnd = chars + charCount;
// For fallback we may need a fallback buffer, we know we aren't default fallback.
EncoderFallbackBuffer fallbackBuffer = null;
// We may have a left over character from last time, try and process it.
if (charLeftOver > 0)
{
// Initialize the buffer
BCLDebug.Assert(encoder != null,
"[Latin1Encoding.GetByteCount]Expected encoder if we have charLeftOver");
fallbackBuffer = encoder.FallbackBuffer;
fallbackBuffer.InternalInitialize(chars, charEnd, encoder, false);
// Since left over char was a surrogate, it'll have to be fallen back.
// Get Fallback
// This will fallback a pair if *chars is a low surrogate
fallbackBuffer.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' : fallbackBuffer.InternalGetNextChar()) != 0 ||
chars < charEnd)
{
// First unwind any fallback
if (ch == 0)
{
// No fallback, just get next char
ch = *chars;
chars++;
}
// Check for fallback, this'll catch surrogate pairs too.
// no chars >= 0x100 are allowed.
if (ch > 0xff)
{
// Initialize the buffer
if (fallbackBuffer == null)
{
if (encoder == null)
fallbackBuffer = this.encoderFallback.CreateFallbackBuffer();
else
fallbackBuffer = encoder.FallbackBuffer;
fallbackBuffer.InternalInitialize(charEnd - charCount, charEnd, encoder, false);
}
// Get Fallback
fallbackBuffer.InternalFallback(ch, ref chars);
continue;
}
// We'll use this one
byteCount++;
}
BCLDebug.Assert(fallbackBuffer == null || fallbackBuffer.Remaining == 0,
"[Latin1Encoding.GetByteCount]Expected Empty fallback buffer");
return byteCount;
}