public unsafe override int GetCharCount(byte* bytes, int count, DecoderNLS baseDecoder)
{
// Just assert, we're called internally so these should be safe, checked already
Debug.Assert(bytes != null, "[DBCSCodePageEncoding.GetCharCount]bytes is null");
Debug.Assert(count >= 0, "[DBCSCodePageEncoding.GetCharCount]byteCount is negative");
CheckMemorySection();
// Fix our decoder
DBCSDecoder decoder = (DBCSDecoder)baseDecoder;
// Get our fallback
DecoderFallbackBuffer fallbackBuffer = null;
// We'll need to know where the end is
byte* byteEnd = bytes + count;
int charCount = count; // Assume 1 char / byte
// Shouldn't have anything in fallback buffer for GetCharCount
// (don't have to check m_throwOnOverflow for count)
Debug.Assert(decoder == null ||
!decoder.InternalHasFallbackBuffer || decoder.FallbackBuffer.Remaining == 0,
"[DBCSCodePageEncoding.GetCharCount]Expected empty fallback buffer at start");
DecoderFallbackBufferHelper fallbackHelper = new DecoderFallbackBufferHelper(fallbackBuffer);
// If we have a left over byte, use it
if (decoder != null && decoder.bLeftOver > 0)
{
// We have a left over byte?
if (count == 0)
{
// No input though
if (!decoder.MustFlush)
{
// Don't have to flush
return 0;
}
Debug.Assert(fallbackBuffer == null,
"[DBCSCodePageEncoding.GetCharCount]Expected empty fallback buffer");
fallbackBuffer = decoder.FallbackBuffer;
fallbackHelper = new DecoderFallbackBufferHelper(fallbackBuffer);
fallbackHelper.InternalInitialize(bytes, null);
byte[] byteBuffer = new byte[] { unchecked((byte)decoder.bLeftOver) };
return fallbackHelper.InternalFallback(byteBuffer, bytes);
}
// Get our full info
int iBytes = decoder.bLeftOver << 8;
iBytes |= (*bytes);
bytes++;
// This is either 1 known char or fallback
// Already counted 1 char
// Look up our bytes
char cDecoder = mapBytesToUnicode[iBytes];
if (cDecoder == 0 && iBytes != 0)
{
// Deallocate preallocated one
charCount--;
// We'll need a fallback
Debug.Assert(fallbackBuffer == null,
"[DBCSCodePageEncoding.GetCharCount]Expected empty fallback buffer for unknown pair");
fallbackBuffer = decoder.FallbackBuffer;
fallbackHelper = new DecoderFallbackBufferHelper(fallbackBuffer);
fallbackHelper.InternalInitialize(byteEnd - count, null);
// Do fallback, we know there are 2 bytes
byte[] byteBuffer = new byte[] { unchecked((byte)(iBytes >> 8)), unchecked((byte)iBytes) };
charCount += fallbackHelper.InternalFallback(byteBuffer, bytes);
}
// else we already reserved space for this one.
}
// Loop, watch out for fallbacks
while (bytes < byteEnd)
{
// Faster if don't use *bytes++;
int iBytes = *bytes;
bytes++;
char c = mapBytesToUnicode[iBytes];
// See if it was a double byte character
if (c == LEAD_BYTE_CHAR)
{
// It's a lead byte
charCount--; // deallocate preallocated lead byte
if (bytes < byteEnd)
{
// Have another to use, so use it
iBytes <<= 8;
iBytes |= *bytes;
bytes++;
c = mapBytesToUnicode[iBytes];
}
else
{
// No input left
if (decoder == null || decoder.MustFlush)
{
// have to flush anyway, set to unknown so we use fallback
charCount++; // reallocate deallocated lead byte
c = UNKNOWN_CHAR_FLAG;
}
else
{
// We'll stick it in decoder
break;
}
}
}
// See if it was unknown.
// Unknown and known chars already allocated, but fallbacks aren't
if (c == UNKNOWN_CHAR_FLAG && iBytes != 0)
{
if (fallbackBuffer == null)
{
if (decoder == null)
fallbackBuffer = DecoderFallback.CreateFallbackBuffer();
else
fallbackBuffer = decoder.FallbackBuffer;
fallbackHelper = new DecoderFallbackBufferHelper(fallbackBuffer);
fallbackHelper.InternalInitialize(byteEnd - count, null);
}
// Do fallback
charCount--; // Get rid of preallocated extra char
byte[] byteBuffer = null;
if (iBytes < 0x100)
byteBuffer = new byte[] { unchecked((byte)iBytes) };
else
byteBuffer = new byte[] { unchecked((byte)(iBytes >> 8)), unchecked((byte)iBytes) };
charCount += fallbackHelper.InternalFallback(byteBuffer, bytes);
}
}
// Shouldn't have anything in fallback buffer for GetChars
Debug.Assert(decoder == null || !decoder.m_throwOnOverflow ||
!decoder.InternalHasFallbackBuffer || decoder.FallbackBuffer.Remaining == 0,
"[DBCSCodePageEncoding.GetCharCount]Expected empty fallback buffer at end");
// Return our count
return charCount;
}