Example #1
0
        [System.Security.SecurityCritical]  // auto-generated
        internal unsafe EncodingCharBuffer(EncodingNLS enc, DecoderNLS decoder, char* charStart, int charCount, byte* byteStart, int byteCount)
        {
            _enc = enc;
            _decoder = decoder;

            _chars = charStart;
            _charStart = charStart;
            _charEnd = charStart + charCount;

            _byteStart = byteStart;
            _bytes = byteStart;
            _byteEnd = byteStart + byteCount;

            if (_decoder == null)
                _fallbackBuffer = enc.DecoderFallback.CreateFallbackBuffer();
            else
                _fallbackBuffer = _decoder.FallbackBuffer;

            // If we're getting chars or getting char count we don't expect to have
            // to remember fallbacks between calls (so it should be empty)
            Debug.Assert(_fallbackBuffer.Remaining == 0,
                "[Encoding.EncodingCharBuffer.EncodingCharBuffer]Expected empty fallback buffer for getchars/charcount");
            _fallbackBufferHelper = new DecoderFallbackBufferHelper(_fallbackBuffer);
            _fallbackBufferHelper.InternalInitialize(_bytes, _charEnd);
        }
Example #2
0
        [System.Security.SecurityCritical]  // auto-generated
        public override unsafe int GetChars(byte* bytes, int byteCount,
                                                char* chars, int charCount, DecoderNLS baseDecoder)
        {
            // Just need to ASSERT, this is called by something else internal that checked parameters already
            Debug.Assert(bytes != null, "[DBCSCodePageEncoding.GetChars]bytes is null");
            Debug.Assert(byteCount >= 0, "[DBCSCodePageEncoding.GetChars]byteCount is negative");
            Debug.Assert(chars != null, "[DBCSCodePageEncoding.GetChars]chars is null");
            Debug.Assert(charCount >= 0, "[DBCSCodePageEncoding.GetChars]charCount is negative");

            CheckMemorySection();

            // Fix our decoder
            DBCSDecoder decoder = (DBCSDecoder)baseDecoder;

            // We'll need to know where the end is
            byte* byteStart = bytes;
            byte* byteEnd = bytes + byteCount;
            char* charStart = chars;
            char* charEnd = chars + charCount;
            bool bUsedDecoder = false;

            // Get our fallback
            DecoderFallbackBuffer fallbackBuffer = null;

            // Shouldn't have anything in fallback buffer for GetChars
            Debug.Assert(decoder == null || !decoder.m_throwOnOverflow ||
                !decoder.InternalHasFallbackBuffer || decoder.FallbackBuffer.Remaining == 0,
                "[DBCSCodePageEncoding.GetChars]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 (byteCount == 0)
                {
                    // No input though
                    if (!decoder.MustFlush)
                    {
                        // Don't have to flush
                        return 0;
                    }

                    // Well, we're flushing, so use '?' or fallback
                    // fallback leftover byte
                    Debug.Assert(fallbackBuffer == null,
                        "[DBCSCodePageEncoding.GetChars]Expected empty fallback");
                    fallbackBuffer = decoder.FallbackBuffer;
                    fallbackHelper = new DecoderFallbackBufferHelper(fallbackBuffer);
                    fallbackHelper.InternalInitialize(bytes, charEnd);

                    // If no room, it's hopeless, this was 1st fallback
                    byte[] byteBuffer = new byte[] { unchecked((byte)decoder.bLeftOver) };
                    if (!fallbackHelper.InternalFallback(byteBuffer, bytes, ref chars))
                        ThrowCharsOverflow(decoder, true);

                    decoder.bLeftOver = 0;

                    // Done, return it
                    return (int)(chars - charStart);
                }

                // Get our full info
                int iBytes = decoder.bLeftOver << 8;
                iBytes |= (*bytes);
                bytes++;

                // Look up our bytes
                char cDecoder = mapBytesToUnicode[iBytes];
                if (cDecoder == UNKNOWN_CHAR_FLAG && iBytes != 0)
                {
                    Debug.Assert(fallbackBuffer == null,
                        "[DBCSCodePageEncoding.GetChars]Expected empty fallback for two bytes");
                    fallbackBuffer = decoder.FallbackBuffer;
                    fallbackHelper = new DecoderFallbackBufferHelper(fallbackBuffer);
                    fallbackHelper.InternalInitialize(byteEnd - byteCount, charEnd);

                    byte[] byteBuffer = new byte[] { unchecked((byte)(iBytes >> 8)), unchecked((byte)iBytes) };
                    if (!fallbackHelper.InternalFallback(byteBuffer, bytes, ref chars))
                        ThrowCharsOverflow(decoder, true);
                }
                else
                {
                    // Do we have output room?, hopeless if not, this is first char
                    if (chars >= charEnd)
                        ThrowCharsOverflow(decoder, true);

                    *(chars++) = cDecoder;
                }
            }

            // Loop, paying attention to our 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)
                {
                    // Its a 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
                            c = UNKNOWN_CHAR_FLAG;
                        }
                        else
                        {
                            // Stick it in decoder
                            bUsedDecoder = true;
                            decoder.bLeftOver = (byte)iBytes;
                            break;
                        }
                    }
                }

                // See if it was unknown
                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 - byteCount, charEnd);
                    }

                    // Do fallback
                    byte[] byteBuffer = null;
                    if (iBytes < 0x100)
                        byteBuffer = new byte[] { unchecked((byte)iBytes) };
                    else
                        byteBuffer = new byte[] { unchecked((byte)(iBytes >> 8)), unchecked((byte)iBytes) };
                    if (!fallbackHelper.InternalFallback(byteBuffer, bytes, ref chars))
                    {
                        // May or may not throw, but we didn't get these byte(s)
                        Debug.Assert(bytes >= byteStart + byteBuffer.Length,
                            "[DBCSCodePageEncoding.GetChars]Expected bytes to have advanced for fallback");
                        bytes -= byteBuffer.Length;                           // didn't use these byte(s)
                        fallbackHelper.InternalReset();                     // Didn't fall this back
                        ThrowCharsOverflow(decoder, bytes == byteStart);    // throw?
                        break;                                              // don't throw, but stop loop
                    }
                }
                else
                {
                    // Do we have buffer room?
                    if (chars >= charEnd)
                    {
                        // May or may not throw, but we didn't get these byte(s)
                        Debug.Assert(bytes > byteStart,
                            "[DBCSCodePageEncoding.GetChars]Expected bytes to have advanced for lead byte");
                        bytes--;                                            // unused byte
                        if (iBytes >= 0x100)
                        {
                            Debug.Assert(bytes > byteStart,
                                "[DBCSCodePageEncoding.GetChars]Expected bytes to have advanced for trail byte");
                            bytes--;                                        // 2nd unused byte
                        }
                        ThrowCharsOverflow(decoder, bytes == byteStart);    // throw?
                        break;                                              // don't throw, but stop loop
                    }

                    *(chars++) = c;
                }
            }

            // We already stuck it in encoder if necessary, but we have to clear cases where nothing new got into decoder
            if (decoder != null)
            {
                // Clear it in case of MustFlush
                if (bUsedDecoder == false)
                {
                    decoder.bLeftOver = 0;
                }

                // Remember our count
                decoder.m_bytesUsed = (int)(bytes - byteStart);
            }

            // Shouldn't have anything in fallback buffer for GetChars
            Debug.Assert(decoder == null || !decoder.m_throwOnOverflow ||
                !decoder.InternalHasFallbackBuffer || decoder.FallbackBuffer.Remaining == 0,
                "[DBCSCodePageEncoding.GetChars]Expected empty fallback buffer at end");

            // Return length of our output
            return (int)(chars - charStart);
        }
Example #3
0
        [System.Security.SecurityCritical]  // auto-generated
        public override unsafe 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;
        }
Example #4
0
        public override unsafe int GetChars(byte *bytes, int byteCount,
                                            char *chars, int charCount, DecoderNLS decoder)
        {
            // Just need to ASSERT, this is called by something else internal that checked parameters already
            Debug.Assert(bytes != null, "[SBCSCodePageEncoding.GetChars]bytes is null");
            Debug.Assert(byteCount >= 0, "[SBCSCodePageEncoding.GetChars]byteCount is negative");
            Debug.Assert(chars != null, "[SBCSCodePageEncoding.GetChars]chars is null");
            Debug.Assert(charCount >= 0, "[SBCSCodePageEncoding.GetChars]charCount is negative");

            CheckMemorySection();

            // See if we have best fit
            bool bUseBestFit = false;

            // Do it fast way if using ? replacement or best fit fallbacks
            byte *byteEnd   = bytes + byteCount;
            byte *byteStart = bytes;
            char *charStart = chars;

            // Only need decoder fallback buffer if not using default replacement fallback or best fit fallback.
            DecoderReplacementFallback fallback = null;

            if (decoder == null)
            {
                fallback    = DecoderFallback as DecoderReplacementFallback;
                bUseBestFit = DecoderFallback is InternalDecoderBestFitFallback;
            }
            else
            {
                fallback    = decoder.Fallback as DecoderReplacementFallback;
                bUseBestFit = decoder.Fallback is InternalDecoderBestFitFallback;
                Debug.Assert(!decoder.m_throwOnOverflow || !decoder.InternalHasFallbackBuffer ||
                             decoder.FallbackBuffer.Remaining == 0,
                             "[SBCSCodePageEncoding.GetChars]Expected empty fallback buffer at start");
            }

            if (bUseBestFit || (fallback != null && fallback.MaxCharCount == 1))
            {
                // Try it the fast way
                char replacementChar;
                if (fallback == null)
                {
                    replacementChar = '?';  // Best fit always has ? for fallback for SBCS
                }
                else
                {
                    replacementChar = fallback.DefaultString[0];
                }

                // Need byteCount chars, otherwise too small buffer
                if (charCount < byteCount)
                {
                    // Need at least 1 output byte, throw if must throw
                    ThrowCharsOverflow(decoder, charCount < 1);

                    // Not throwing, use what we can
                    byteEnd = bytes + charCount;
                }

                // Quick loop, just do '?' replacement because we don't have fallbacks for decodings.
                while (bytes < byteEnd)
                {
                    char c;
                    if (bUseBestFit)
                    {
                        if (arrayBytesBestFit == null)
                        {
                            ReadBestFitTable();
                        }
                        c = arrayBytesBestFit[*bytes];
                    }
                    else
                    {
                        c = _mapBytesToUnicode[*bytes];
                    }
                    bytes++;

                    if (c == UNKNOWN_CHAR)
                    {
                        // This is an invalid byte in the ASCII encoding.
                        *chars = replacementChar;
                    }
                    else
                    {
                        *chars = c;
                    }
                    chars++;
                }

                // bytes & chars used are the same
                if (decoder != null)
                {
                    decoder.m_bytesUsed = (int)(bytes - byteStart);
                }
                return((int)(chars - charStart));
            }

            // Slower way's going to need a fallback buffer
            DecoderFallbackBuffer fallbackBuffer = null;

            byte[] byteBuffer = new byte[1];
            char * charEnd    = chars + charCount;

            DecoderFallbackBufferHelper fallbackHelper = new DecoderFallbackBufferHelper(null);

            // Not quite so fast loop
            while (bytes < byteEnd)
            {
                // Faster if don't use *bytes++;
                char c = _mapBytesToUnicode[*bytes];
                bytes++;

                // See if it was unknown
                if (c == UNKNOWN_CHAR)
                {
                    // Make sure we have a fallback buffer
                    if (fallbackBuffer == null)
                    {
                        if (decoder == null)
                        {
                            fallbackBuffer = DecoderFallback.CreateFallbackBuffer();
                        }
                        else
                        {
                            fallbackBuffer = decoder.FallbackBuffer;
                        }

                        fallbackHelper = new DecoderFallbackBufferHelper(fallbackBuffer);

                        fallbackHelper.InternalInitialize(byteEnd - byteCount, charEnd);
                    }

                    // Use fallback buffer
                    Debug.Assert(bytes > byteStart,
                                 "[SBCSCodePageEncoding.GetChars]Expected bytes to have advanced already (unknown byte)");
                    byteBuffer[0] = *(bytes - 1);
                    // Fallback adds fallback to chars, but doesn't increment chars unless the whole thing fits.
                    if (!fallbackHelper.InternalFallback(byteBuffer, bytes, ref chars))
                    {
                        // May or may not throw, but we didn't get this byte
                        bytes--;                                            // unused byte
                        fallbackHelper.InternalReset();                     // Didn't fall this back
                        ThrowCharsOverflow(decoder, bytes == byteStart);    // throw?
                        break;                                              // don't throw, but stop loop
                    }
                }
                else
                {
                    // Make sure we have buffer space
                    if (chars >= charEnd)
                    {
                        Debug.Assert(bytes > byteStart,
                                     "[SBCSCodePageEncoding.GetChars]Expected bytes to have advanced already (known byte)");
                        bytes--;                                            // unused byte
                        ThrowCharsOverflow(decoder, bytes == byteStart);    // throw?
                        break;                                              // don't throw, but stop loop
                    }

                    *(chars) = c;
                    chars++;
                }
            }

            // Might have had decoder fallback stuff.
            if (decoder != null)
            {
                decoder.m_bytesUsed = (int)(bytes - byteStart);
            }

            // Expect Empty fallback buffer for GetChars
            Debug.Assert(fallbackBuffer == null || fallbackBuffer.Remaining == 0,
                         "[SBCSEncoding.GetChars]Expected Empty fallback buffer at end");

            return((int)(chars - charStart));
        }
Example #5
0
        // This is internal and called by something else,
        public override unsafe int GetCharCount(byte *bytes, int count, DecoderNLS decoder)
        {
            // Just assert, we're called internally so these should be safe, checked already
            Debug.Assert(bytes != null, "[SBCSCodePageEncoding.GetCharCount]bytes is null");
            Debug.Assert(count >= 0, "[SBCSCodePageEncoding.GetCharCount]byteCount is negative");

            CheckMemorySection();

            // See if we have best fit
            bool bUseBestFit = false;

            // Only need decoder fallback buffer if not using default replacement fallback or best fit fallback.
            DecoderReplacementFallback fallback = null;

            if (decoder == null)
            {
                fallback    = DecoderFallback as DecoderReplacementFallback;
                bUseBestFit = DecoderFallback is InternalDecoderBestFitFallback;
            }
            else
            {
                fallback    = decoder.Fallback as DecoderReplacementFallback;
                bUseBestFit = decoder.Fallback is InternalDecoderBestFitFallback;
                Debug.Assert(!decoder.m_throwOnOverflow || !decoder.InternalHasFallbackBuffer ||
                             decoder.FallbackBuffer.Remaining == 0,
                             "[SBCSCodePageEncoding.GetChars]Expected empty fallback buffer at start");
            }

            if (bUseBestFit || (fallback != null && fallback.MaxCharCount == 1))
            {
                // Just return length, SBCS stay the same length because they don't map to surrogate
                // pairs and we don't have a decoder fallback.
                return(count);
            }

            // Might need one of these later
            DecoderFallbackBuffer       fallbackBuffer = null;
            DecoderFallbackBufferHelper fallbackHelper = new DecoderFallbackBufferHelper(fallbackBuffer);

            // Have to do it the hard way.
            // Assume charCount will be == count
            int charCount = count;

            byte[] byteBuffer = new byte[1];

            // Do it our fast way
            byte *byteEnd = bytes + count;

            // Quick loop
            while (bytes < byteEnd)
            {
                // Faster if don't use *bytes++;
                char c;
                c = _mapBytesToUnicode[*bytes];
                bytes++;

                // If unknown we have to do fallback count
                if (c == UNKNOWN_CHAR)
                {
                    // Must have a fallback buffer
                    if (fallbackBuffer == null)
                    {
                        // Need to adjust count so we get real start
                        if (decoder == null)
                        {
                            fallbackBuffer = DecoderFallback.CreateFallbackBuffer();
                        }
                        else
                        {
                            fallbackBuffer = decoder.FallbackBuffer;
                        }

                        fallbackHelper = new DecoderFallbackBufferHelper(fallbackBuffer);

                        fallbackHelper.InternalInitialize(byteEnd - count, null);
                    }

                    // Use fallback buffer
                    byteBuffer[0] = *(bytes - 1);
                    charCount--;                            // We'd already reserved one for *(bytes-1)
                    charCount += fallbackHelper.InternalFallback(byteBuffer, bytes);
                }
            }

            // Fallback buffer must be empty
            Debug.Assert(fallbackBuffer == null || fallbackBuffer.Remaining == 0,
                         "[SBCSEncoding.GetCharCount]Expected Empty fallback buffer at end");

            // Converted sequence is same length as input
            return(charCount);
        }
Example #6
0
        public unsafe override int GetChars(byte* bytes, int byteCount,
                                                char* chars, int charCount, DecoderNLS decoder)
        {
            // Just need to ASSERT, this is called by something else internal that checked parameters already
            Debug.Assert(bytes != null, "[SBCSCodePageEncoding.GetChars]bytes is null");
            Debug.Assert(byteCount >= 0, "[SBCSCodePageEncoding.GetChars]byteCount is negative");
            Debug.Assert(chars != null, "[SBCSCodePageEncoding.GetChars]chars is null");
            Debug.Assert(charCount >= 0, "[SBCSCodePageEncoding.GetChars]charCount is negative");

            CheckMemorySection();

            // See if we have best fit
            bool bUseBestFit = false;

            // Do it fast way if using ? replacement or best fit fallbacks
            byte* byteEnd = bytes + byteCount;
            byte* byteStart = bytes;
            char* charStart = chars;

            // Only need decoder fallback buffer if not using default replacement fallback or best fit fallback.
            DecoderReplacementFallback fallback = null;

            if (decoder == null)
            {
                fallback = DecoderFallback as DecoderReplacementFallback;
                bUseBestFit = DecoderFallback is InternalDecoderBestFitFallback;
            }
            else
            {
                fallback = decoder.Fallback as DecoderReplacementFallback;
                bUseBestFit = decoder.Fallback is InternalDecoderBestFitFallback;
                Debug.Assert(!decoder.m_throwOnOverflow || !decoder.InternalHasFallbackBuffer ||
                    decoder.FallbackBuffer.Remaining == 0,
                    "[SBCSCodePageEncoding.GetChars]Expected empty fallback buffer at start");
            }

            if (bUseBestFit || (fallback != null && fallback.MaxCharCount == 1))
            {
                // Try it the fast way
                char replacementChar;
                if (fallback == null)
                    replacementChar = '?';  // Best fit always has ? for fallback for SBCS
                else
                    replacementChar = fallback.DefaultString[0];

                // Need byteCount chars, otherwise too small buffer
                if (charCount < byteCount)
                {
                    // Need at least 1 output byte, throw if must throw
                    ThrowCharsOverflow(decoder, charCount < 1);

                    // Not throwing, use what we can
                    byteEnd = bytes + charCount;
                }

                // Quick loop, just do '?' replacement because we don't have fallbacks for decodings.
                while (bytes < byteEnd)
                {
                    char c;
                    if (bUseBestFit)
                    {
                        if (arrayBytesBestFit == null)
                        {
                            ReadBestFitTable();
                        }
                        c = arrayBytesBestFit[*bytes];
                    }
                    else
                        c = _mapBytesToUnicode[*bytes];
                    bytes++;

                    if (c == UNKNOWN_CHAR)
                        // This is an invalid byte in the ASCII encoding.
                        *chars = replacementChar;
                    else
                        *chars = c;
                    chars++;
                }

                // bytes & chars used are the same
                if (decoder != null)
                    decoder.m_bytesUsed = (int)(bytes - byteStart);
                return (int)(chars - charStart);
            }

            // Slower way's going to need a fallback buffer
            DecoderFallbackBuffer fallbackBuffer = null;
            byte[] byteBuffer = new byte[1];
            char* charEnd = chars + charCount;

            DecoderFallbackBufferHelper fallbackHelper = new DecoderFallbackBufferHelper(
                decoder != null ? decoder.FallbackBuffer : DecoderFallback.CreateFallbackBuffer());

            // Not quite so fast loop
            while (bytes < byteEnd)
            {
                // Faster if don't use *bytes++;
                char c = _mapBytesToUnicode[*bytes];
                bytes++;

                // See if it was unknown
                if (c == UNKNOWN_CHAR)
                {
                    // Make sure we have a fallback buffer
                    if (fallbackBuffer == null)
                    {
                        if (decoder == null)
                            fallbackBuffer = DecoderFallback.CreateFallbackBuffer();
                        else
                            fallbackBuffer = decoder.FallbackBuffer;

                        fallbackHelper = new DecoderFallbackBufferHelper(fallbackBuffer);

                        fallbackHelper.InternalInitialize(byteEnd - byteCount, charEnd);
                    }

                    // Use fallback buffer
                    Debug.Assert(bytes > byteStart,
                        "[SBCSCodePageEncoding.GetChars]Expected bytes to have advanced already (unknown byte)");
                    byteBuffer[0] = *(bytes - 1);
                    // Fallback adds fallback to chars, but doesn't increment chars unless the whole thing fits.
                    if (!fallbackHelper.InternalFallback(byteBuffer, bytes, ref chars))
                    {
                        // May or may not throw, but we didn't get this byte
                        bytes--;                                            // unused byte
                        fallbackHelper.InternalReset();                     // Didn't fall this back
                        ThrowCharsOverflow(decoder, bytes == byteStart);    // throw?
                        break;                                              // don't throw, but stop loop
                    }
                }
                else
                {
                    // Make sure we have buffer space
                    if (chars >= charEnd)
                    {
                        Debug.Assert(bytes > byteStart,
                            "[SBCSCodePageEncoding.GetChars]Expected bytes to have advanced already (known byte)");
                        bytes--;                                            // unused byte
                        ThrowCharsOverflow(decoder, bytes == byteStart);    // throw?
                        break;                                              // don't throw, but stop loop
                    }

                    *(chars) = c;
                    chars++;
                }
            }

            // Might have had decoder fallback stuff.
            if (decoder != null)
                decoder.m_bytesUsed = (int)(bytes - byteStart);

            // Expect Empty fallback buffer for GetChars
            Debug.Assert(fallbackBuffer == null || fallbackBuffer.Remaining == 0,
                "[SBCSEncoding.GetChars]Expected Empty fallback buffer at end");

            return (int)(chars - charStart);
        }
Example #7
0
        public unsafe override int GetCharCount(byte* bytes, int count, DecoderNLS decoder)
        {
            // Just assert, we're called internally so these should be safe, checked already
            Debug.Assert(bytes != null, "[SBCSCodePageEncoding.GetCharCount]bytes is null");
            Debug.Assert(count >= 0, "[SBCSCodePageEncoding.GetCharCount]byteCount is negative");

            CheckMemorySection();

            // See if we have best fit
            bool bUseBestFit = false;

            // Only need decoder fallback buffer if not using default replacement fallback or best fit fallback.
            DecoderReplacementFallback fallback = null;

            if (decoder == null)
            {
                fallback = DecoderFallback as DecoderReplacementFallback;
                bUseBestFit = DecoderFallback is InternalDecoderBestFitFallback;
            }
            else
            {
                fallback = decoder.Fallback as DecoderReplacementFallback;
                bUseBestFit = decoder.Fallback is InternalDecoderBestFitFallback;
                Debug.Assert(!decoder.m_throwOnOverflow || !decoder.InternalHasFallbackBuffer ||
                    decoder.FallbackBuffer.Remaining == 0,
                    "[SBCSCodePageEncoding.GetChars]Expected empty fallback buffer at start");
            }

            if (bUseBestFit || (fallback != null && fallback.MaxCharCount == 1))
            {
                // Just return length, SBCS stay the same length because they don't map to surrogate
                // pairs and we don't have a decoder fallback.
                return count;
            }

            // Might need one of these later
            DecoderFallbackBuffer fallbackBuffer = null;
            DecoderFallbackBufferHelper fallbackHelper = new DecoderFallbackBufferHelper(fallbackBuffer);

            // Have to do it the hard way.
            // Assume charCount will be == count
            int charCount = count;
            byte[] byteBuffer = new byte[1];

            // Do it our fast way
            byte* byteEnd = bytes + count;

            // Quick loop
            while (bytes < byteEnd)
            {
                // Faster if don't use *bytes++;
                char c;
                c = _mapBytesToUnicode[*bytes];
                bytes++;

                // If unknown we have to do fallback count
                if (c == UNKNOWN_CHAR)
                {
                    // Must have a fallback buffer
                    if (fallbackBuffer == null)
                    {
                        // Need to adjust count so we get real start
                        if (decoder == null)
                            fallbackBuffer = DecoderFallback.CreateFallbackBuffer();
                        else
                            fallbackBuffer = decoder.FallbackBuffer;

                        fallbackHelper = new DecoderFallbackBufferHelper(fallbackBuffer);

                        fallbackHelper.InternalInitialize(byteEnd - count, null);
                    }

                    // Use fallback buffer
                    byteBuffer[0] = *(bytes - 1);
                    charCount--;                            // We'd already reserved one for *(bytes-1)
                    charCount += fallbackHelper.InternalFallback(byteBuffer, bytes);
                }
            }

            // Fallback buffer must be empty
            Debug.Assert(fallbackBuffer == null || fallbackBuffer.Remaining == 0,
                "[SBCSEncoding.GetCharCount]Expected Empty fallback buffer at end");

            // Converted sequence is same length as input
            return charCount;
        }