示例#1
0
		public void HandleFallback(ref EncoderFallbackBuffer buffer,
			char[] chars, ref int charIndex, ref int charCount,
			byte[] bytes, ref int byteIndex, ref int byteCount, object state)
		{
			if (buffer == null)
				buffer = EncoderFallback.CreateFallbackBuffer();

			// THIS IS WERE THE BUG IS!! (pruiz)
			if (charCount > 1 && (Char.IsSurrogate(chars[charIndex]) && Char.IsSurrogate(chars[charIndex + 1])))
			{
				buffer.Fallback (chars[charIndex], chars[charIndex + 1], charIndex);
				charIndex++;
				charCount--;
			}
			else
				buffer.Fallback (chars[charIndex], charIndex);

			char[] tmp = new char[buffer.Remaining];
			int idx = 0;
			while (buffer.Remaining > 0)
				tmp[idx++] = buffer.GetNextChar();

			var len = state == null ?
				GetBytes(tmp, 0, tmp.Length, bytes, byteIndex)
				: GetBytesInternal(tmp, 0, tmp.Length, bytes, byteIndex, true, state);
			byteIndex += len;
			byteCount -= len;
		}
示例#2
0
		public unsafe void HandleFallback (ref EncoderFallbackBuffer buffer,
			char* chars, ref int charIndex, ref int charCount,
			byte* bytes, ref int byteIndex, ref int byteCount)
		{
			HandleFallback(ref buffer, chars, ref charIndex, ref charCount,
				bytes, ref byteIndex, ref byteCount, null);
		}
示例#3
0
		public unsafe void HandleFallback (ref EncoderFallbackBuffer buffer,
			char* chars, ref int charIndex, ref int charCount,
			byte* bytes, ref int byteIndex, ref int byteCount, object state)
		{
			if (buffer == null)
				buffer = EncoderFallback.CreateFallbackBuffer ();

			if (charCount > 1 && (Char.IsSurrogate (chars [charIndex]) && Char.IsSurrogate (chars [charIndex + 1]))) {
				buffer.Fallback (chars [charIndex], chars [charIndex + 1], charIndex);
				charIndex++;
				charCount--;
			}
			else
				buffer.Fallback (chars [charIndex], charIndex);
			char [] tmp = new char [buffer.Remaining];
			int idx = 0;
			while (buffer.Remaining > 0)
				tmp [idx++] = buffer.GetNextChar ();

			fixed (char* tmparr = tmp) {
				var outbytes = bytes == null ? null : bytes + byteIndex;
				var len = state == null ?
					GetBytes(tmparr, tmp.Length, outbytes, byteCount)
					: GetBytesInternal(tmparr, tmp.Length, outbytes, byteCount, true, state);

				byteIndex += len;
				byteCount -= len;
			}
		}
示例#4
0
        internal unsafe EncodingByteBuffer(EncodingNLS inEncoding, EncoderNLS inEncoder, byte* inByteStart, int inByteCount, char* inCharStart, int inCharCount)
        {
            _enc = inEncoding;
            _encoder = inEncoder;

            _charStart = inCharStart;
            _chars = inCharStart;
            _charEnd = inCharStart + inCharCount;

            _bytes = inByteStart;
            _byteStart = inByteStart;
            _byteEnd = inByteStart + inByteCount;

            if (_encoder == null)
                fallbackBuffer = _enc.EncoderFallback.CreateFallbackBuffer();
            else
            {
                fallbackBuffer = _encoder.FallbackBuffer;
                // If we're not converting we must not have data in our fallback buffer
                if (_encoder.m_throwOnOverflow && _encoder.InternalHasFallbackBuffer && fallbackBuffer.Remaining > 0)
                    throw new ArgumentException(SR.Format(SR.Argument_EncoderFallbackNotEmpty, _encoder.Encoding.EncodingName, _encoder.Fallback.GetType()));
            }
            fallbackBufferHelper = new EncoderFallbackBufferHelper(fallbackBuffer);
            fallbackBufferHelper.InternalInitialize(_chars, _charEnd, _encoder, _bytes != null);
        }
 public unsafe EncoderFallbackBufferHelper(EncoderFallbackBuffer fallbackBuffer)
 {
     _fallbackBuffer = fallbackBuffer;
     bFallingBack = bUsedEncoder = setEncoder = false;
     iRecursionCount = 0;
     charEnd = charStart = null;
     encoder = null;
 }
		public unsafe void HandleFallback (ref EncoderFallbackBuffer buffer,
			char* chars, ref int charIndex, ref int charCount,
			byte* bytes, ref int byteIndex, ref int byteCount)
		{
			if (buffer == null)
				buffer = EncoderFallback.CreateFallbackBuffer ();
			if (Char.IsSurrogate (chars [charIndex]) && charCount > 0 &&
				Char.IsSurrogate (chars [charIndex + 1])) {
				buffer.Fallback (chars [charIndex], chars [charIndex + 1], charIndex);
				charIndex++;
				charCount--;
			}
			else
				buffer.Fallback (chars [charIndex], charIndex);
			char [] tmp = new char [buffer.Remaining];
			int idx = 0;
			while (buffer.Remaining > 0)
				tmp [idx++] = buffer.GetNextChar ();
			fixed (char* tmparr = tmp) {
				byteIndex += GetBytes (tmparr, tmp.Length, bytes + byteIndex, byteCount);
			}
		}
        internal override unsafe int GetBytes(char *chars, int charCount, byte *bytes, int byteCount, EncoderNLS encoder)
        {
            char ch4;
            char charLeftOver = '\0';
            EncoderReplacementFallback encoderFallback = null;
            EncoderFallbackBuffer      fallbackBuffer  = null;
            char *charEnd   = chars + charCount;
            byte *numPtr    = bytes;
            char *charStart = chars;

            if (encoder != null)
            {
                charLeftOver    = encoder.charLeftOver;
                encoderFallback = encoder.Fallback as EncoderReplacementFallback;
                if (encoder.InternalHasFallbackBuffer)
                {
                    fallbackBuffer = encoder.FallbackBuffer;
                    if ((fallbackBuffer.Remaining > 0) && encoder.m_throwOnOverflow)
                    {
                        throw new ArgumentException(Environment.GetResourceString("Argument_EncoderFallbackNotEmpty", new object[] { this.EncodingName, encoder.Fallback.GetType() }));
                    }
                    fallbackBuffer.InternalInitialize(charStart, charEnd, encoder, true);
                }
            }
            else
            {
                encoderFallback = base.EncoderFallback as EncoderReplacementFallback;
            }
            if ((encoderFallback != null) && (encoderFallback.MaxCharCount == 1))
            {
                char ch2 = encoderFallback.DefaultString[0];
                if (ch2 <= '\x007f')
                {
                    if (charLeftOver > '\0')
                    {
                        if (byteCount == 0)
                        {
                            base.ThrowBytesOverflow(encoder, true);
                        }
                        bytes++;
                        bytes[0] = (byte)ch2;
                        byteCount--;
                    }
                    if (byteCount < charCount)
                    {
                        base.ThrowBytesOverflow(encoder, byteCount < 1);
                        charEnd = chars + byteCount;
                    }
                    while (chars < charEnd)
                    {
                        chars++;
                        char ch3 = chars[0];
                        if (ch3 >= '\x0080')
                        {
                            bytes++;
                            bytes[0] = (byte)ch2;
                        }
                        else
                        {
                            bytes++;
                            bytes[0] = (byte)ch3;
                        }
                    }
                    if (encoder != null)
                    {
                        encoder.charLeftOver = '\0';
                        encoder.m_charsUsed  = (int)((long)((chars - charStart) / 2));
                    }
                    return((int)((long)((bytes - numPtr) / 1)));
                }
            }
            byte *numPtr2 = bytes + byteCount;

            if (charLeftOver > '\0')
            {
                fallbackBuffer = encoder.FallbackBuffer;
                fallbackBuffer.InternalInitialize(chars, charEnd, encoder, true);
                fallbackBuffer.InternalFallback(charLeftOver, ref chars);
            }
            while (((ch4 = (fallbackBuffer == null) ? '\0' : fallbackBuffer.InternalGetNextChar()) != '\0') || (chars < charEnd))
            {
                if (ch4 == '\0')
                {
                    ch4 = chars[0];
                    chars++;
                }
                if (ch4 > '\x007f')
                {
                    if (fallbackBuffer == null)
                    {
                        if (encoder == null)
                        {
                            fallbackBuffer = base.encoderFallback.CreateFallbackBuffer();
                        }
                        else
                        {
                            fallbackBuffer = encoder.FallbackBuffer;
                        }
                        fallbackBuffer.InternalInitialize(charEnd - charCount, charEnd, encoder, true);
                    }
                    fallbackBuffer.InternalFallback(ch4, ref chars);
                }
                else
                {
                    if (bytes >= numPtr2)
                    {
                        if ((fallbackBuffer == null) || !fallbackBuffer.bFallingBack)
                        {
                            chars--;
                        }
                        else
                        {
                            fallbackBuffer.MovePrevious();
                        }
                        base.ThrowBytesOverflow(encoder, bytes == numPtr);
                        break;
                    }
                    bytes[0] = (byte)ch4;
                    bytes++;
                }
            }
            if (encoder != null)
            {
                if ((fallbackBuffer != null) && !fallbackBuffer.bUsedEncoder)
                {
                    encoder.charLeftOver = '\0';
                }
                encoder.m_charsUsed = (int)((long)((chars - charStart) / 2));
            }
            return((int)((long)((bytes - numPtr) / 1)));
        }
示例#8
0
        [System.Security.SecurityCritical]  // auto-generated
        internal override unsafe int GetByteCount(char *chars, int count, EncoderNLS encoder)
        {
            // Just need to ASSERT, this is called by something else internal that checked parameters already
            Contract.Assert(count >= 0, "[SBCSCodePageEncoding.GetByteCount]count is negative");
            Contract.Assert(chars != null, "[SBCSCodePageEncoding.GetByteCount]chars is null");

            // Assert because we shouldn't be able to have a null encoder.
            Contract.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;
                Contract.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
                Contract.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 = 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)
                {
                    count++;
                }

                return(count);
            }

            // It had a funky fallback, so its more complicated
            // Need buffer maybe later
            EncoderFallbackBuffer fallbackBuffer = null;

            // prepare our end
            int   byteCount = 0;
            char *charEnd   = chars + count;

            // We may have a left over character from last time, try and process it.
            if (charLeftOver > 0)
            {
                // Since left over char was a surrogate, it'll have to be fallen back.
                // Get Fallback
                Contract.Assert(encoder != null, "[SBCSCodePageEncoding.GetByteCount]Expect to have encoder if we have a charLeftOver");
                fallbackBuffer = encoder.FallbackBuffer;
                fallbackBuffer.InternalInitialize(chars, charEnd, encoder, false);

                // 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++;
                }

                // 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 = this.encoderFallback.CreateFallbackBuffer();
                        }
                        else
                        {
                            fallbackBuffer = encoder.FallbackBuffer;
                        }

                        // chars has moved so we need to remember figure it out so Exception fallback
                        // index will be correct
                        fallbackBuffer.InternalInitialize(charEnd - count, charEnd, encoder, false);
                    }

                    // Get Fallback
                    fallbackBuffer.InternalFallback(ch, ref chars);
                    continue;
                }

                // We'll use this one
                byteCount++;
            }

            Contract.Assert(fallbackBuffer == null || fallbackBuffer.Remaining == 0,
                            "[SBCSEncoding.GetByteCount]Expected Empty fallback buffer at end");

            return((int)byteCount);
        }
示例#9
0
        //
        // End of standard methods copied from EncodingNLS.cs
        //

        // GetByteCount
        // Note: We start by assuming that the output will be the same as count.  Having
        // an encoder or fallback may change that assumption
        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
            Debug.Assert(charCount >= 0, "[ASCIIEncoding.GetByteCount]count is negative");
            Debug.Assert(chars != null, "[ASCIIEncoding.GetByteCount]chars is null");

            // Assert because we shouldn't be able to have a null encoder.
            Debug.Assert(encoderFallback != null, "[ASCIIEncoding.GetByteCount]Attempting to use null fallback encoder");

            char charLeftOver = (char)0;
            EncoderReplacementFallback fallback = null;

            // 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;
            char *charsForFallback;

            if (encoder != null)
            {
                charLeftOver = encoder._charLeftOver;
                Debug.Assert(charLeftOver == 0 || Char.IsHighSurrogate(charLeftOver),
                             "[ASCIIEncoding.GetByteCount]leftover character should be high surrogate");

                fallback = encoder.Fallback as EncoderReplacementFallback;

                // We mustn't have left over fallback data when counting
                if (encoder.InternalHasFallbackBuffer)
                {
                    // We always need the fallback buffer in get bytes so we can flush any remaining ones if necessary
                    fallbackBuffer = encoder.FallbackBuffer;
                    if (fallbackBuffer.Remaining > 0 && encoder._throwOnOverflow)
                    {
                        throw new ArgumentException(SR.Format(SR.Argument_EncoderFallbackNotEmpty, this.EncodingName, encoder.Fallback.GetType()));
                    }

                    // Set our internal fallback interesting things.
                    fallbackBuffer.InternalInitialize(chars, charEnd, encoder, false);
                }

                // Verify that we have no fallbackbuffer, for ASCII its always empty, so just assert
                Debug.Assert(!encoder._throwOnOverflow || !encoder.InternalHasFallbackBuffer ||
                             encoder.FallbackBuffer.Remaining == 0,
                             "[ASCIICodePageEncoding.GetByteCount]Expected empty fallback buffer");
            }
            else
            {
                fallback = this.EncoderFallback as EncoderReplacementFallback;
            }

            // If we have an encoder AND we aren't using default fallback,
            // then we may have a complicated count.
            if (fallback != null && fallback.MaxCharCount == 1)
            {
                // 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;

            // We may have a left over character from last time, try and process it.
            if (charLeftOver > 0)
            {
                Debug.Assert(Char.IsHighSurrogate(charLeftOver), "[ASCIIEncoding.GetByteCount]leftover character should be high surrogate");
                Debug.Assert(encoder != null, "[ASCIIEncoding.GetByteCount]Expected encoder");

                // Since left over char was a surrogate, it'll have to be fallen back.
                // Get Fallback
                fallbackBuffer = encoder.FallbackBuffer;
                fallbackBuffer.InternalInitialize(chars, charEnd, encoder, false);

                // This will fallback a pair if *chars is a low surrogate
                charsForFallback = chars; // Avoid passing chars by reference to allow it to be enregistered
                fallbackBuffer.InternalFallback(charLeftOver, ref charsForFallback);
                chars = charsForFallback;
            }

            // 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 >= 0x80 are allowed.
                if (ch > 0x7f)
                {
                    if (fallbackBuffer == null)
                    {
                        // Initialize the buffer
                        if (encoder == null)
                        {
                            fallbackBuffer = this.encoderFallback.CreateFallbackBuffer();
                        }
                        else
                        {
                            fallbackBuffer = encoder.FallbackBuffer;
                        }
                        fallbackBuffer.InternalInitialize(charEnd - charCount, charEnd, encoder, false);
                    }

                    // Get Fallback
                    charsForFallback = chars; // Avoid passing chars by reference to allow it to be enregistered
                    fallbackBuffer.InternalFallback(ch, ref charsForFallback);
                    chars = charsForFallback;
                    continue;
                }

                // We'll use this one
                byteCount++;
            }

            Debug.Assert(fallbackBuffer == null || fallbackBuffer.Remaining == 0,
                         "[ASCIIEncoding.GetByteCount]Expected Empty fallback buffer");

            return(byteCount);
        }
示例#10
0
	internal unsafe static EncoderStatus InternalGetBytesCount (
		char[] chars, int charIndex, int charCount,
		EncoderFallbackBuffer fallbackBuffer,
		out int charsProcessed, out int bytesProcessed,
		ref uint leftChar,
		bool flush)
	{
		if (chars == null)
			throw new ArgumentNullException ("chars");
		if (charIndex < 0 || charIndex > chars.Length)
			throw new ArgumentOutOfRangeException ("charIndex", _("ArgRange_Array"));
		if (charCount < 0 || charCount > (chars.Length - charIndex))
			throw new ArgumentOutOfRangeException ("charCount", _("ArgRange_Array"));

		fixed (char *cptr = chars) {
			return InternalGetBytes (
				cptr + charIndex, charCount,
				null, -1,
				fallbackBuffer,
				out charsProcessed, out bytesProcessed,
				ref leftChar,
				flush);
		}
	}
示例#11
0
        unsafe int InternalGetBytes(char *chars, int charLength, int charIndex, int charCount,
                                    byte[] bytes, int byteIndex,
                                    ref EncoderFallbackBuffer buffer,
                                    ref char [] fallback_chars)
        {
            if (bytes == null)
            {
                throw new ArgumentNullException("bytes");
            }
            if (charIndex < 0 || charIndex > charLength)
            {
                throw new ArgumentOutOfRangeException("charIndex", _("ArgRange_StringIndex"));
            }
            if (charCount < 0 || charCount > (charLength - charIndex))
            {
                throw new ArgumentOutOfRangeException("charCount", _("ArgRange_StringRange"));
            }
            if (byteIndex < 0 || byteIndex > bytes.Length)
            {
                throw new ArgumentOutOfRangeException("byteIndex", _("ArgRange_Array"));
            }
            if ((bytes.Length - byteIndex) < charCount)
            {
                throw new ArgumentException(_("Arg_InsufficientSpace"));
            }

            int  count = charCount;
            char ch;

            while (count-- > 0)
            {
                ch = chars [charIndex++];
                if (ch < (char)0x80)
                {
                    bytes [byteIndex++] = (byte)ch;
                }
                else
                {
                    if (buffer == null)
                    {
                        buffer = EncoderFallback.CreateFallbackBuffer();
                    }
                    if (Char.IsSurrogate(ch) && count > 1 &&
                        Char.IsSurrogate(chars [charIndex]))
                    {
                        buffer.Fallback(ch, chars [charIndex], charIndex++ - 1);
                    }
                    else
                    {
                        buffer.Fallback(ch, charIndex - 1);
                    }
                    if (fallback_chars == null || fallback_chars.Length < buffer.Remaining)
                    {
                        fallback_chars = new char [buffer.Remaining];
                    }
                    for (int i = 0; i < fallback_chars.Length; i++)
                    {
                        fallback_chars [i] = buffer.GetNextChar();
                    }
                    byteIndex += GetBytes(fallback_chars, 0,
                                          fallback_chars.Length, bytes, byteIndex,
                                          ref buffer, ref fallback_chars);
                }
            }
            return(charCount);
        }
 internal override unsafe int GetByteCount(char* chars, int charCount, EncoderNLS encoder)
 {
     EncoderReplacementFallback encoderFallback;
     char ch2;
     char charLeftOver = '\0';
     if (encoder != null)
     {
         charLeftOver = encoder.charLeftOver;
         encoderFallback = encoder.Fallback as EncoderReplacementFallback;
     }
     else
     {
         encoderFallback = base.EncoderFallback as EncoderReplacementFallback;
     }
     if ((encoderFallback != null) && (encoderFallback.MaxCharCount == 1))
     {
         if (charLeftOver > '\0')
         {
             charCount++;
         }
         return charCount;
     }
     int num = 0;
     char* charEnd = chars + charCount;
     EncoderFallbackBuffer fallbackBuffer = null;
     if (charLeftOver > '\0')
     {
         fallbackBuffer = encoder.FallbackBuffer;
         fallbackBuffer.InternalInitialize(chars, charEnd, encoder, false);
         fallbackBuffer.InternalFallback(charLeftOver, ref chars);
     }
     while (((ch2 = (fallbackBuffer == null) ? '\0' : fallbackBuffer.InternalGetNextChar()) != '\0') || (chars < charEnd))
     {
         if (ch2 == '\0')
         {
             ch2 = chars[0];
             chars++;
         }
         if (ch2 > '\x00ff')
         {
             if (fallbackBuffer == null)
             {
                 if (encoder == null)
                 {
                     fallbackBuffer = base.encoderFallback.CreateFallbackBuffer();
                 }
                 else
                 {
                     fallbackBuffer = encoder.FallbackBuffer;
                 }
                 fallbackBuffer.InternalInitialize(charEnd - charCount, charEnd, encoder, false);
             }
             fallbackBuffer.InternalFallback(ch2, ref chars);
         }
         else
         {
             num++;
         }
     }
     return num;
 }
示例#13
0
        internal override unsafe int GetBytes(char *chars, int charCount, byte *bytes, int byteCount, EncoderNLS encoder)
        {
            this.CheckMemorySection();
            char ch1 = char.MinValue;
            EncoderReplacementFallback replacementFallback;

            if (encoder != null)
            {
                ch1 = encoder.charLeftOver;
                replacementFallback = encoder.Fallback as EncoderReplacementFallback;
            }
            else
            {
                replacementFallback = this.EncoderFallback as EncoderReplacementFallback;
            }
            char *charEnd = chars + charCount;
            byte *numPtr1 = bytes;
            char *chPtr   = chars;

            if (replacementFallback != null && replacementFallback.MaxCharCount == 1)
            {
                byte num1 = this.mapUnicodeToBytes[(int)replacementFallback.DefaultString[0]];
                if ((int)num1 != 0)
                {
                    if ((int)ch1 > 0)
                    {
                        if (byteCount == 0)
                        {
                            this.ThrowBytesOverflow(encoder, true);
                        }
                        *bytes++ = num1;
                        --byteCount;
                    }
                    if (byteCount < charCount)
                    {
                        this.ThrowBytesOverflow(encoder, byteCount < 1);
                        charEnd = chars + byteCount;
                    }
                    while (chars < charEnd)
                    {
                        char ch2 = *chars;
                        chars += 2;
                        byte num2  = this.mapUnicodeToBytes[(int)ch2];
                        *    bytes = (int)num2 != 0 || (int)ch2 == 0 ? num2 : num1;
                        ++bytes;
                    }
                    if (encoder != null)
                    {
                        encoder.charLeftOver = char.MinValue;
                        encoder.m_charsUsed  = (int)(chars - chPtr);
                    }
                    return((int)(bytes - numPtr1));
                }
            }
            EncoderFallbackBuffer encoderFallbackBuffer = (EncoderFallbackBuffer)null;
            byte *numPtr2 = bytes + byteCount;

            if ((int)ch1 > 0)
            {
                encoderFallbackBuffer = encoder.FallbackBuffer;
                encoderFallbackBuffer.InternalInitialize(chars, charEnd, encoder, true);
                encoderFallbackBuffer.InternalFallback(ch1, ref chars);
                if ((long)encoderFallbackBuffer.Remaining > numPtr2 - bytes)
                {
                    this.ThrowBytesOverflow(encoder, true);
                }
            }
            char ch3;

            while ((int)(ch3 = encoderFallbackBuffer == null ? char.MinValue : encoderFallbackBuffer.InternalGetNextChar()) != 0 || chars < charEnd)
            {
                if ((int)ch3 == 0)
                {
                    ch3    = *chars;
                    chars += 2;
                }
                byte num = this.mapUnicodeToBytes[(int)ch3];
                if ((int)num == 0 && (int)ch3 != 0)
                {
                    if (encoderFallbackBuffer == null)
                    {
                        encoderFallbackBuffer = encoder != null ? encoder.FallbackBuffer : this.encoderFallback.CreateFallbackBuffer();
                        encoderFallbackBuffer.InternalInitialize(charEnd - charCount, charEnd, encoder, true);
                    }
                    encoderFallbackBuffer.InternalFallback(ch3, ref chars);
                    if ((long)encoderFallbackBuffer.Remaining > numPtr2 - bytes)
                    {
                        chars -= 2;
                        encoderFallbackBuffer.InternalReset();
                        this.ThrowBytesOverflow(encoder, chars == chPtr);
                        break;
                    }
                }
                else
                {
                    if (bytes >= numPtr2)
                    {
                        if (encoderFallbackBuffer == null || !encoderFallbackBuffer.bFallingBack)
                        {
                            chars -= 2;
                        }
                        this.ThrowBytesOverflow(encoder, chars == chPtr);
                        break;
                    }
                    *bytes = num;
                    ++bytes;
                }
            }
            if (encoder != null)
            {
                if (encoderFallbackBuffer != null && !encoderFallbackBuffer.bUsedEncoder)
                {
                    encoder.charLeftOver = char.MinValue;
                }
                encoder.m_charsUsed = (int)(chars - chPtr);
            }
            return((int)(bytes - numPtr1));
        }
示例#14
0
        internal override unsafe int GetBytes(char *chars, int charCount, byte *bytes, int byteCount, EncoderNLS encoder)
        {
            this.CheckMemorySection();
            EncoderFallbackBuffer encoderFallbackBuffer = (EncoderFallbackBuffer)null;
            char *charEnd = chars + charCount;
            char *chPtr   = chars;
            byte *numPtr1 = bytes;
            byte *numPtr2 = bytes + byteCount;

            if (encoder != null)
            {
                char ch = encoder.charLeftOver;
                encoderFallbackBuffer = encoder.FallbackBuffer;
                encoderFallbackBuffer.InternalInitialize(chars, charEnd, encoder, true);
                if (encoder.m_throwOnOverflow && encoderFallbackBuffer.Remaining > 0)
                {
                    throw new ArgumentException(Environment.GetResourceString("Argument_EncoderFallbackNotEmpty", (object)this.EncodingName, (object)encoder.Fallback.GetType()));
                }
                if ((int)ch > 0)
                {
                    encoderFallbackBuffer.InternalFallback(ch, ref chars);
                }
            }
            char ch1;

            while ((int)(ch1 = encoderFallbackBuffer == null ? char.MinValue : encoderFallbackBuffer.InternalGetNextChar()) != 0 || chars < charEnd)
            {
                if ((int)ch1 == 0)
                {
                    ch1    = *chars;
                    chars += 2;
                }
                ushort num = this.mapUnicodeToBytes[ch1];
                if ((int)num == 0 && (int)ch1 != 0)
                {
                    if (encoderFallbackBuffer == null)
                    {
                        encoderFallbackBuffer = this.encoderFallback.CreateFallbackBuffer();
                        encoderFallbackBuffer.InternalInitialize(charEnd - charCount, charEnd, encoder, true);
                    }
                    encoderFallbackBuffer.InternalFallback(ch1, ref chars);
                }
                else
                {
                    if ((int)num >= 256)
                    {
                        if (bytes + 1 >= numPtr2)
                        {
                            if (encoderFallbackBuffer == null || !encoderFallbackBuffer.bFallingBack)
                            {
                                chars -= 2;
                            }
                            else
                            {
                                encoderFallbackBuffer.MovePrevious();
                            }
                            this.ThrowBytesOverflow(encoder, chars == chPtr);
                            break;
                        }
                        *bytes = (byte)((uint)num >> 8);
                        ++bytes;
                    }
                    else if (bytes >= numPtr2)
                    {
                        if (encoderFallbackBuffer == null || !encoderFallbackBuffer.bFallingBack)
                        {
                            chars -= 2;
                        }
                        else
                        {
                            encoderFallbackBuffer.MovePrevious();
                        }
                        this.ThrowBytesOverflow(encoder, chars == chPtr);
                        break;
                    }
                    *bytes = (byte)((uint)num & (uint)byte.MaxValue);
                    ++bytes;
                }
            }
            if (encoder != null)
            {
                if (encoderFallbackBuffer != null && !encoderFallbackBuffer.bUsedEncoder)
                {
                    encoder.charLeftOver = char.MinValue;
                }
                encoder.m_charsUsed = (int)(chars - chPtr);
            }
            return((int)(bytes - numPtr1));
        }
        private int GetBytes(string chars, int charIndex, int charCount, byte[] bytes, int byteIndex, ref EncoderFallbackBuffer buffer, ref char[] fallback_chars)
        {
            if (chars == null)
            {
                throw new ArgumentNullException("chars");
            }
            if (bytes == null)
            {
                throw new ArgumentNullException("bytes");
            }
            if (charIndex < 0 || charIndex > chars.Length)
            {
                throw new ArgumentOutOfRangeException("charIndex", Encoding._("ArgRange_StringIndex"));
            }
            if (charCount < 0 || charCount > chars.Length - charIndex)
            {
                throw new ArgumentOutOfRangeException("charCount", Encoding._("ArgRange_StringRange"));
            }
            if (byteIndex < 0 || byteIndex > bytes.Length)
            {
                throw new ArgumentOutOfRangeException("byteIndex", Encoding._("ArgRange_Array"));
            }
            if (bytes.Length - byteIndex < charCount)
            {
                throw new ArgumentException(Encoding._("Arg_InsufficientSpace"));
            }
            int num = charCount;

            while (num-- > 0)
            {
                char c = chars[charIndex++];
                if (c < '\u0080')
                {
                    bytes[byteIndex++] = (byte)c;
                }
                else
                {
                    if (buffer == null)
                    {
                        buffer = base.EncoderFallback.CreateFallbackBuffer();
                    }
                    if (char.IsSurrogate(c) && num > 1 && char.IsSurrogate(chars[charIndex]))
                    {
                        buffer.Fallback(c, chars[charIndex], charIndex++ - 1);
                    }
                    else
                    {
                        buffer.Fallback(c, charIndex - 1);
                    }
                    if (fallback_chars == null || fallback_chars.Length < buffer.Remaining)
                    {
                        fallback_chars = new char[buffer.Remaining];
                    }
                    for (int i = 0; i < fallback_chars.Length; i++)
                    {
                        fallback_chars[i] = buffer.GetNextChar();
                    }
                    byteIndex += this.GetBytes(fallback_chars, 0, fallback_chars.Length, bytes, byteIndex, ref buffer, ref fallback_chars);
                }
            }
            return(charCount);
        }
示例#16
0
        internal override unsafe int GetBytes(char *chars, int charCount, byte *bytes, int byteCount, EncoderNLS encoder)
        {
            char ch1 = char.MinValue;
            EncoderFallbackBuffer encoderFallbackBuffer = (EncoderFallbackBuffer)null;
            char *charEnd   = chars + charCount;
            byte *numPtr1   = bytes;
            char *charStart = chars;
            EncoderReplacementFallback replacementFallback;

            if (encoder != null)
            {
                ch1 = encoder.charLeftOver;
                replacementFallback = encoder.Fallback as EncoderReplacementFallback;
                if (encoder.InternalHasFallbackBuffer)
                {
                    encoderFallbackBuffer = encoder.FallbackBuffer;
                    if (encoderFallbackBuffer.Remaining > 0 && encoder.m_throwOnOverflow)
                    {
                        throw new ArgumentException(Environment.GetResourceString("Argument_EncoderFallbackNotEmpty", (object)this.EncodingName, (object)encoder.Fallback.GetType()));
                    }
                    encoderFallbackBuffer.InternalInitialize(charStart, charEnd, encoder, true);
                }
            }
            else
            {
                replacementFallback = this.EncoderFallback as EncoderReplacementFallback;
            }
            if (replacementFallback != null && replacementFallback.MaxCharCount == 1)
            {
                char ch2 = replacementFallback.DefaultString[0];
                if ((int)ch2 <= (int)sbyte.MaxValue)
                {
                    if ((int)ch1 > 0)
                    {
                        if (byteCount == 0)
                        {
                            this.ThrowBytesOverflow(encoder, true);
                        }
                        *bytes++ = (byte)ch2;
                        --byteCount;
                    }
                    if (byteCount < charCount)
                    {
                        this.ThrowBytesOverflow(encoder, byteCount < 1);
                        charEnd = chars + byteCount;
                    }
                    while (chars < charEnd)
                    {
                        char ch3     = *chars++;
                        *    bytes++ = (int)ch3 < 128 ? (byte)ch3 : (byte)ch2;
                    }
                    if (encoder != null)
                    {
                        encoder.charLeftOver = char.MinValue;
                        encoder.m_charsUsed  = (int)(chars - charStart);
                    }
                    return((int)(bytes - numPtr1));
                }
            }
            byte *numPtr2 = bytes + byteCount;

            if ((int)ch1 > 0)
            {
                encoderFallbackBuffer = encoder.FallbackBuffer;
                encoderFallbackBuffer.InternalInitialize(chars, charEnd, encoder, true);
                encoderFallbackBuffer.InternalFallback(ch1, ref chars);
            }
            char ch4;

            while ((int)(ch4 = encoderFallbackBuffer == null ? char.MinValue : encoderFallbackBuffer.InternalGetNextChar()) != 0 || chars < charEnd)
            {
                if ((int)ch4 == 0)
                {
                    ch4    = *chars;
                    chars += 2;
                }
                if ((int)ch4 > (int)sbyte.MaxValue)
                {
                    if (encoderFallbackBuffer == null)
                    {
                        encoderFallbackBuffer = encoder != null ? encoder.FallbackBuffer : this.encoderFallback.CreateFallbackBuffer();
                        encoderFallbackBuffer.InternalInitialize(charEnd - charCount, charEnd, encoder, true);
                    }
                    encoderFallbackBuffer.InternalFallback(ch4, ref chars);
                }
                else
                {
                    if (bytes >= numPtr2)
                    {
                        if (encoderFallbackBuffer == null || !encoderFallbackBuffer.bFallingBack)
                        {
                            chars -= 2;
                        }
                        else
                        {
                            encoderFallbackBuffer.MovePrevious();
                        }
                        this.ThrowBytesOverflow(encoder, bytes == numPtr1);
                        break;
                    }
                    *bytes = (byte)ch4;
                    ++bytes;
                }
            }
            if (encoder != null)
            {
                if (encoderFallbackBuffer != null && !encoderFallbackBuffer.bUsedEncoder)
                {
                    encoder.charLeftOver = char.MinValue;
                }
                encoder.m_charsUsed = (int)(chars - charStart);
            }
            return((int)(bytes - numPtr1));
        }
示例#17
0
        internal override unsafe int GetByteCount(char *chars, int charCount, EncoderNLS encoder)
        {
            char  ch1     = char.MinValue;
            char *charEnd = chars + charCount;
            EncoderFallbackBuffer      encoderFallbackBuffer = (EncoderFallbackBuffer)null;
            EncoderReplacementFallback replacementFallback;

            if (encoder != null)
            {
                ch1 = encoder.charLeftOver;
                replacementFallback = encoder.Fallback as EncoderReplacementFallback;
                if (encoder.InternalHasFallbackBuffer)
                {
                    encoderFallbackBuffer = encoder.FallbackBuffer;
                    if (encoderFallbackBuffer.Remaining > 0 && encoder.m_throwOnOverflow)
                    {
                        throw new ArgumentException(Environment.GetResourceString("Argument_EncoderFallbackNotEmpty", (object)this.EncodingName, (object)encoder.Fallback.GetType()));
                    }
                    encoderFallbackBuffer.InternalInitialize(chars, charEnd, encoder, false);
                }
            }
            else
            {
                replacementFallback = this.EncoderFallback as EncoderReplacementFallback;
            }
            if (replacementFallback != null && replacementFallback.MaxCharCount == 1)
            {
                if ((int)ch1 > 0)
                {
                    ++charCount;
                }
                return(charCount);
            }
            int num = 0;

            if ((int)ch1 > 0)
            {
                encoderFallbackBuffer = encoder.FallbackBuffer;
                encoderFallbackBuffer.InternalInitialize(chars, charEnd, encoder, false);
                encoderFallbackBuffer.InternalFallback(ch1, ref chars);
            }
            char ch2;

            while ((int)(ch2 = encoderFallbackBuffer == null ? char.MinValue : encoderFallbackBuffer.InternalGetNextChar()) != 0 || chars < charEnd)
            {
                if ((int)ch2 == 0)
                {
                    ch2    = *chars;
                    chars += 2;
                }
                if ((int)ch2 > (int)sbyte.MaxValue)
                {
                    if (encoderFallbackBuffer == null)
                    {
                        encoderFallbackBuffer = encoder != null ? encoder.FallbackBuffer : this.encoderFallback.CreateFallbackBuffer();
                        encoderFallbackBuffer.InternalInitialize(charEnd - charCount, charEnd, encoder, false);
                    }
                    encoderFallbackBuffer.InternalFallback(ch2, ref chars);
                }
                else
                {
                    ++num;
                }
            }
            return(num);
        }
	int GetBytes (char[] chars, int charIndex, int charCount,
		      byte[] bytes, int byteIndex,
		      ref EncoderFallbackBuffer buffer,
		      ref char [] fallback_chars)
	{
		if (chars == null)
			throw new ArgumentNullException ("chars");

		unsafe {
			fixed (char *cptr = chars) {
				return InternalGetBytes (cptr, chars.Length, charIndex, charCount, bytes, byteIndex, ref buffer, ref fallback_chars);
			}
		}
	}
	// Internal version of "GetBytes" which can handle a rolling
	// state between multiple calls to this method.
	private static int InternalGetBytes (char[] chars, int charIndex,
					     int charCount, byte[] bytes,
					     int byteIndex,
						 EncoderFallback fallback, ref EncoderFallbackBuffer buffer,
						 ref char leftOver, bool flush)
	{
		// Validate the parameters.
		if (chars == null) {
			throw new ArgumentNullException ("chars");
		}
		if (bytes == null) {
			throw new ArgumentNullException ("bytes");
		}
		if (charIndex < 0 || charIndex > chars.Length) {
			throw new ArgumentOutOfRangeException ("charIndex", _("ArgRange_Array"));
		}
		if (charCount < 0 || charCount > (chars.Length - charIndex)) {
			throw new ArgumentOutOfRangeException ("charCount", _("ArgRange_Array"));
		}
		if (byteIndex < 0 || byteIndex > bytes.Length) {
			throw new ArgumentOutOfRangeException ("byteIndex", _("ArgRange_Array"));
		}

		if (charIndex == chars.Length) {
			if (flush && leftOver != '\0') {
				// FIXME: use EncoderFallback.
				//
				// By default it is empty, so I do nothing for now.
				leftOver = '\0';
			}
			return 0;
		}

		unsafe {
			fixed (char* cptr = chars) {
				if (bytes.Length == byteIndex)
					return InternalGetBytes (
						cptr + charIndex, charCount, 
						null, 0, fallback, ref buffer, ref leftOver, flush);
				fixed (byte *bptr = bytes) {
					return InternalGetBytes (
						cptr + charIndex, charCount,
						bptr + byteIndex, bytes.Length - byteIndex,
						fallback, ref buffer,
						ref leftOver, flush);
				}
			}
		}
	}
        internal unsafe override int GetByteCount(char *chars, int count, EncoderNLS encoder)
        {
            base.CheckMemorySection();
            char c = '\0';

            if (encoder != null)
            {
                c = encoder.charLeftOver;
                if (encoder.InternalHasFallbackBuffer && encoder.FallbackBuffer.Remaining > 0)
                {
                    throw new ArgumentException(Environment.GetResourceString("Argument_EncoderFallbackNotEmpty", new object[]
                    {
                        this.EncodingName,
                        encoder.Fallback.GetType()
                    }));
                }
            }
            int   num = 0;
            char *ptr = chars + count;
            EncoderFallbackBuffer encoderFallbackBuffer = null;

            if (c > '\0')
            {
                encoderFallbackBuffer = encoder.FallbackBuffer;
                encoderFallbackBuffer.InternalInitialize(chars, ptr, encoder, false);
                encoderFallbackBuffer.InternalFallback(c, ref chars);
            }
            char c2;

            while ((c2 = ((encoderFallbackBuffer == null) ? '\0' : encoderFallbackBuffer.InternalGetNextChar())) != '\0' || chars < ptr)
            {
                if (c2 == '\0')
                {
                    c2 = *chars;
                    chars++;
                }
                ushort num2 = this.mapUnicodeToBytes[(IntPtr)c2];
                if (num2 == 0 && c2 != '\0')
                {
                    if (encoderFallbackBuffer == null)
                    {
                        if (encoder == null)
                        {
                            encoderFallbackBuffer = this.encoderFallback.CreateFallbackBuffer();
                        }
                        else
                        {
                            encoderFallbackBuffer = encoder.FallbackBuffer;
                        }
                        encoderFallbackBuffer.InternalInitialize(ptr - count, ptr, encoder, false);
                    }
                    encoderFallbackBuffer.InternalFallback(c2, ref chars);
                }
                else
                {
                    num++;
                    if (num2 >= 256)
                    {
                        num++;
                    }
                }
            }
            return(num);
        }
        internal unsafe override int GetBytes(char *chars, int charCount, byte *bytes, int byteCount, EncoderNLS encoder)
        {
            base.CheckMemorySection();
            EncoderFallbackBuffer encoderFallbackBuffer = null;
            char *ptr  = chars + charCount;
            char *ptr2 = chars;
            byte *ptr3 = bytes;
            byte *ptr4 = bytes + byteCount;

            if (encoder != null)
            {
                char charLeftOver = encoder.charLeftOver;
                encoderFallbackBuffer = encoder.FallbackBuffer;
                encoderFallbackBuffer.InternalInitialize(chars, ptr, encoder, true);
                if (encoder.m_throwOnOverflow && encoderFallbackBuffer.Remaining > 0)
                {
                    throw new ArgumentException(Environment.GetResourceString("Argument_EncoderFallbackNotEmpty", new object[]
                    {
                        this.EncodingName,
                        encoder.Fallback.GetType()
                    }));
                }
                if (charLeftOver > '\0')
                {
                    encoderFallbackBuffer.InternalFallback(charLeftOver, ref chars);
                }
            }
            char c;

            while ((c = ((encoderFallbackBuffer == null) ? '\0' : encoderFallbackBuffer.InternalGetNextChar())) != '\0' || chars < ptr)
            {
                if (c == '\0')
                {
                    c = *chars;
                    chars++;
                }
                ushort num = this.mapUnicodeToBytes[(IntPtr)c];
                if (num == 0 && c != '\0')
                {
                    if (encoderFallbackBuffer == null)
                    {
                        encoderFallbackBuffer = this.encoderFallback.CreateFallbackBuffer();
                        encoderFallbackBuffer.InternalInitialize(ptr - charCount, ptr, encoder, true);
                    }
                    encoderFallbackBuffer.InternalFallback(c, ref chars);
                }
                else
                {
                    if (num >= 256)
                    {
                        if (bytes + 1 >= ptr4)
                        {
                            if (encoderFallbackBuffer == null || !encoderFallbackBuffer.bFallingBack)
                            {
                                chars--;
                            }
                            else
                            {
                                encoderFallbackBuffer.MovePrevious();
                            }
                            base.ThrowBytesOverflow(encoder, chars == ptr2);
                            break;
                        }
                        *bytes = (byte)(num >> 8);
                        bytes++;
                    }
                    else if (bytes >= ptr4)
                    {
                        if (encoderFallbackBuffer == null || !encoderFallbackBuffer.bFallingBack)
                        {
                            chars--;
                        }
                        else
                        {
                            encoderFallbackBuffer.MovePrevious();
                        }
                        base.ThrowBytesOverflow(encoder, chars == ptr2);
                        break;
                    }
                    *bytes = (byte)(num & 255);
                    bytes++;
                }
            }
            if (encoder != null)
            {
                if (encoderFallbackBuffer != null && !encoderFallbackBuffer.bUsedEncoder)
                {
                    encoder.charLeftOver = '\0';
                }
                encoder.m_charsUsed = (int)((long)(chars - ptr2));
            }
            return((int)((long)(bytes - ptr3)));
        }
示例#22
0
        internal override unsafe int GetBytes(char *chars, int charCount,
                                              byte *bytes, int byteCount, EncoderNLS encoder)
        {
            Debug.Assert(chars != null, "[UTF32Encoding.GetBytes]chars!=null");
            Debug.Assert(bytes != null, "[UTF32Encoding.GetBytes]bytes!=null");
            Debug.Assert(byteCount >= 0, "[UTF32Encoding.GetBytes]byteCount >=0");
            Debug.Assert(charCount >= 0, "[UTF32Encoding.GetBytes]charCount >=0");

            char *charStart = chars;
            char *charEnd   = chars + charCount;
            byte *byteStart = bytes;
            byte *byteEnd   = bytes + byteCount;

            char highSurrogate = '\0';

            // For fallback we may need a fallback buffer
            EncoderFallbackBuffer fallbackBuffer = null;

            if (encoder != null)
            {
                highSurrogate  = encoder.charLeftOver;
                fallbackBuffer = encoder.FallbackBuffer;

                // We mustn't have left over fallback data when not converting
                if (encoder.m_throwOnOverflow && fallbackBuffer.Remaining > 0)
                {
                    throw new ArgumentException(SR.Format(SR.Argument_EncoderFallbackNotEmpty,
                                                          this.EncodingName, encoder.Fallback.GetType()));
                }
            }
            else
            {
                fallbackBuffer = this.encoderFallback.CreateFallbackBuffer();
            }

            // Set our internal fallback interesting things.
            fallbackBuffer.InternalInitialize(charStart, charEnd, encoder, true);

            char ch;

TryAgain:

            while (((ch = fallbackBuffer.InternalGetNextChar()) != 0) || chars < charEnd)
            {
                // First unwind any fallback
                if (ch == 0)
                {
                    // No fallback, just get next char
                    ch = *chars;
                    chars++;
                }

                // Do we need a low surrogate?
                if (highSurrogate != '\0')
                {
                    //
                    // In previous char, we encountered a high surrogate, so we are expecting a low surrogate here.
                    //
                    if (Char.IsLowSurrogate(ch))
                    {
                        // Is it a legal one?
                        uint iTemp = GetSurrogate(highSurrogate, ch);
                        highSurrogate = '\0';

                        //
                        // One surrogate pair will be translated into 4 bytes UTF32.
                        //
                        if (bytes + 3 >= byteEnd)
                        {
                            // Don't have 4 bytes
                            if (fallbackBuffer.bFallingBack)
                            {
                                fallbackBuffer.MovePrevious();                  // Aren't using these 2 fallback chars
                                fallbackBuffer.MovePrevious();
                            }
                            else
                            {
                                // If we don't have enough room, then either we should've advanced a while
                                // or we should have bytes==byteStart and throw below
                                Debug.Assert(chars > charStart + 1 || bytes == byteStart,
                                             "[UnicodeEncoding.GetBytes]Expected chars to have when no room to add surrogate pair");
                                chars -= 2;                                     // Aren't using those 2 chars
                            }
                            ThrowBytesOverflow(encoder, bytes == byteStart);    // Throw maybe (if no bytes written)
                            highSurrogate = (char)0;                            // Nothing left over (we backed up to start of pair if supplimentary)
                            break;
                        }

                        if (_bigEndian)
                        {
                            *(bytes++) = (byte)(0x00);
                            *(bytes++) = (byte)(iTemp >> 16);       // Implies & 0xFF, which isn't needed cause high are all 0
                            *(bytes++) = (byte)(iTemp >> 8);        // Implies & 0xFF
                            *(bytes++) = (byte)(iTemp);             // Implies & 0xFF
                        }
                        else
                        {
                            *(bytes++) = (byte)(iTemp);             // Implies & 0xFF
                            *(bytes++) = (byte)(iTemp >> 8);        // Implies & 0xFF
                            *(bytes++) = (byte)(iTemp >> 16);       // Implies & 0xFF, which isn't needed cause high are all 0
                            *(bytes++) = (byte)(0x00);
                        }
                        continue;
                    }

                    // We are missing our low surrogate, decrement chars and fallback the high surrogate
                    // The high surrogate may have come from the encoder, but nothing else did.
                    Debug.Assert(chars > charStart,
                                 "[UTF32Encoding.GetBytes]Expected chars to have advanced if no low surrogate");
                    chars--;

                    // Do the fallback
                    fallbackBuffer.InternalFallback(highSurrogate, ref chars);

                    // We're going to fallback the old high surrogate.
                    highSurrogate = '\0';
                    continue;
                }

                // Do we have another high surrogate?, if so remember it
                if (Char.IsHighSurrogate(ch))
                {
                    //
                    // We'll have a high surrogate to check next time.
                    //
                    highSurrogate = ch;
                    continue;
                }

                // Check for illegal characters (low surrogate)
                if (Char.IsLowSurrogate(ch))
                {
                    // We have a leading low surrogate, do the fallback
                    fallbackBuffer.InternalFallback(ch, ref chars);

                    // Try again with fallback buffer
                    continue;
                }

                // We get to add the character, yippee.
                if (bytes + 3 >= byteEnd)
                {
                    // Don't have 4 bytes
                    if (fallbackBuffer.bFallingBack)
                    {
                        fallbackBuffer.MovePrevious();                  // Aren't using this fallback char
                    }
                    else
                    {
                        // Must've advanced already
                        Debug.Assert(chars > charStart,
                                     "[UTF32Encoding.GetBytes]Expected chars to have advanced if normal character");
                        chars--;                                        // Aren't using this char
                    }
                    ThrowBytesOverflow(encoder, bytes == byteStart);    // Throw maybe (if no bytes written)
                    break;                                              // Didn't throw, stop
                }

                if (_bigEndian)
                {
                    *(bytes++) = (byte)(0x00);
                    *(bytes++) = (byte)(0x00);
                    *(bytes++) = (byte)((uint)ch >> 8); // Implies & 0xFF
                    *(bytes++) = (byte)(ch);            // Implies & 0xFF
                }
                else
                {
                    *(bytes++) = (byte)(ch);            // Implies & 0xFF
                    *(bytes++) = (byte)((uint)ch >> 8); // Implies & 0xFF
                    *(bytes++) = (byte)(0x00);
                    *(bytes++) = (byte)(0x00);
                }
            }

            // May have to do our last surrogate
            if ((encoder == null || encoder.MustFlush) && highSurrogate > 0)
            {
                // We have to do the fallback for the lonely high surrogate
                fallbackBuffer.InternalFallback(highSurrogate, ref chars);
                highSurrogate = (char)0;
                goto TryAgain;
            }

            // Fix our encoder if we have one
            Debug.Assert(highSurrogate == 0 || (encoder != null && !encoder.MustFlush),
                         "[UTF32Encoding.GetBytes]Expected encoder to be flushed.");

            if (encoder != null)
            {
                // Remember our left over surrogate (or 0 if flushing)
                encoder.charLeftOver = highSurrogate;

                // Need # chars used
                encoder.m_charsUsed = (int)(chars - charStart);
            }

            // return the new length
            return((int)(bytes - byteStart));
        }
示例#23
0
	// InternalGetBytes processor. Can encode or count space needed for
	// encoding, depending on the enabled mode:
	//   - encoder
	//       enabled when byteCount >= 0 (but bytes may be null)
	//   - counter
	//       enabled when bytes == null && byteCount < 0
	internal unsafe static EncoderStatus InternalGetBytes (
		char* chars, int charCount,
		byte* bytes, int byteCount,
		EncoderFallbackBuffer fallbackBuffer,
		out int charsProcessed, out int bytesProcessed,
		ref uint leftChar,
		bool flush)
	{
		EncoderStatus s;
		int t_charsProcessed, t_bytesProcessed;

		// Validate the parameters
		if (charCount < 0)
			throw new ArgumentOutOfRangeException ("charCount", _("ArgRange_NonNegative"));
		else
			if (charCount > 0 && chars == null)
				throw new ArgumentNullException ("chars");
 		if (bytes == null) {
 			if (byteCount > 0)
				throw new ArgumentNullException ("bytes");
		} else {
			if (byteCount <= 0)
				throw new ArgumentOutOfRangeException ("byteCount", _("ArgRange_NonNegative"));
		}

		// reset counters
		charsProcessed = 0;
		bytesProcessed = 0;

		// char processing loop
		while (charCount - charsProcessed > 0) {
			s = bytes != null
				? InternalGetByte (
					chars + charsProcessed, charCount - charsProcessed,
					bytes + bytesProcessed, byteCount - bytesProcessed,
					out t_charsProcessed, out t_bytesProcessed, ref leftChar)
				: InternalGetByte (
					chars + charsProcessed, charCount - charsProcessed,
					null, byteCount,
					out t_charsProcessed, out t_bytesProcessed, ref leftChar);

			// if not enough space return here
			// NOTE: maybe we should restore the original encoder
			//       state ... we should check what ms do in this case
			if(s == EncoderStatus.InsufficientSpace)
				return EncoderStatus.InsufficientSpace;

			// update counters
			charsProcessed += t_charsProcessed;
			bytesProcessed += t_bytesProcessed;

			switch (s) {
			case EncoderStatus.Ok:
				break;	// everything OK :D

			case EncoderStatus.InputRunOut:
				return flush
					? InternalGetBytesFlush (
						bytes, byteCount,
						fallbackBuffer,
						charsProcessed, ref bytesProcessed,
						ref leftChar)
					: EncoderStatus.InputRunOut;

			case EncoderStatus.InvalidChar:
			case EncoderStatus.InvalidSurrogate:
				s = InternalGetBytesFlush (
					bytes, byteCount,
					fallbackBuffer,
					charsProcessed, ref bytesProcessed,
					ref leftChar);
				if (s != EncoderStatus.Ok)
					return s;
				break;
			}
		}
		return flush
			? InternalGetBytesFlush (
				bytes, byteCount,
				fallbackBuffer,
				charsProcessed, ref bytesProcessed,
				ref leftChar)
			: EncoderStatus.Ok;
	}
示例#24
0
        int GetBytes(char[] chars, int charIndex, int charCount,
                     byte[] bytes, int byteIndex,
                     ref EncoderFallbackBuffer buffer,
                     ref char [] fallback_chars)
        {
#endif
            if (chars == null)
            {
                throw new ArgumentNullException("chars");
            }
            if (bytes == null)
            {
                throw new ArgumentNullException("bytes");
            }
            if (charIndex < 0 || charIndex > chars.Length)
            {
                throw new ArgumentOutOfRangeException("charIndex", _("ArgRange_Array"));
            }
            if (charCount < 0 || charCount > (chars.Length - charIndex))
            {
                throw new ArgumentOutOfRangeException("charCount", _("ArgRange_Array"));
            }
            if (byteIndex < 0 || byteIndex > bytes.Length)
            {
                throw new ArgumentOutOfRangeException("byteIndex", _("ArgRange_Array"));
            }
            if ((bytes.Length - byteIndex) < charCount)
            {
                throw new ArgumentException(_("Arg_InsufficientSpace"));
            }
            int  count = charCount;
            char ch;
            while (count-- > 0)
            {
                ch = chars[charIndex++];
                if (ch < (char)0x0100)
                {
                    bytes[byteIndex++] = (byte)ch;
                }
                else if (ch >= '\uFF01' && ch <= '\uFF5E')
                {
                    bytes[byteIndex++] = (byte)(ch - 0xFEE0);
                }
                else
                {
#if NET_2_0
                    if (buffer == null)
                    {
                        buffer = EncoderFallback.CreateFallbackBuffer();
                    }
                    if (Char.IsSurrogate(ch) && count > 1 &&
                        Char.IsSurrogate(chars [charIndex]))
                    {
                        buffer.Fallback(ch, chars [charIndex], charIndex++ - 1);
                    }
                    else
                    {
                        buffer.Fallback(ch, charIndex - 1);
                    }
                    if (fallback_chars == null || fallback_chars.Length < buffer.Remaining)
                    {
                        fallback_chars = new char [buffer.Remaining];
                    }
                    for (int i = 0; i < fallback_chars.Length; i++)
                    {
                        fallback_chars [i] = buffer.GetNextChar();
                    }
                    byteIndex += GetBytes(fallback_chars, 0,
                                          fallback_chars.Length, bytes, byteIndex,
                                          ref buffer, ref fallback_chars);
#else
                    bytes[byteIndex++] = (byte)'?';
#endif
                }
            }
            return(charCount);
        }
示例#25
0
        // End of overridden methods which use EncodingForwarder

        internal override unsafe int GetByteCount(char *chars, int count, EncoderNLS encoder)
        {
            Debug.Assert(chars != null, "[UTF32Encoding.GetByteCount]chars!=null");
            Debug.Assert(count >= 0, "[UTF32Encoding.GetByteCount]count >=0");

            char *end       = chars + count;
            char *charStart = chars;
            int   byteCount = 0;

            char highSurrogate = '\0';

            // For fallback we may need a fallback buffer
            EncoderFallbackBuffer fallbackBuffer = null;

            if (encoder != null)
            {
                highSurrogate  = encoder.charLeftOver;
                fallbackBuffer = encoder.FallbackBuffer;

                // We mustn't have left over fallback data when counting
                if (fallbackBuffer.Remaining > 0)
                {
                    throw new ArgumentException(SR.Format(SR.Argument_EncoderFallbackNotEmpty,
                                                          this.EncodingName, encoder.Fallback.GetType()));
                }
            }
            else
            {
                fallbackBuffer = this.encoderFallback.CreateFallbackBuffer();
            }

            // Set our internal fallback interesting things.
            fallbackBuffer.InternalInitialize(charStart, end, encoder, false);

            char ch;

TryAgain:

            while (((ch = fallbackBuffer.InternalGetNextChar()) != 0) || chars < end)
            {
                // First unwind any fallback
                if (ch == 0)
                {
                    // No fallback, just get next char
                    ch = *chars;
                    chars++;
                }

                // Do we need a low surrogate?
                if (highSurrogate != '\0')
                {
                    //
                    // In previous char, we encounter a high surrogate, so we are expecting a low surrogate here.
                    //
                    if (Char.IsLowSurrogate(ch))
                    {
                        // They're all legal
                        highSurrogate = '\0';

                        //
                        // One surrogate pair will be translated into 4 bytes UTF32.
                        //

                        byteCount += 4;
                        continue;
                    }

                    // We are missing our low surrogate, decrement chars and fallback the high surrogate
                    // The high surrogate may have come from the encoder, but nothing else did.
                    Debug.Assert(chars > charStart,
                                 "[UTF32Encoding.GetByteCount]Expected chars to have advanced if no low surrogate");
                    chars--;

                    // Do the fallback
                    fallbackBuffer.InternalFallback(highSurrogate, ref chars);

                    // We're going to fallback the old high surrogate.
                    highSurrogate = '\0';
                    continue;
                }

                // Do we have another high surrogate?
                if (Char.IsHighSurrogate(ch))
                {
                    //
                    // We'll have a high surrogate to check next time.
                    //
                    highSurrogate = ch;
                    continue;
                }

                // Check for illegal characters
                if (Char.IsLowSurrogate(ch))
                {
                    // We have a leading low surrogate, do the fallback
                    fallbackBuffer.InternalFallback(ch, ref chars);

                    // Try again with fallback buffer
                    continue;
                }

                // We get to add the character (4 bytes UTF32)
                byteCount += 4;
            }

            // May have to do our last surrogate
            if ((encoder == null || encoder.MustFlush) && highSurrogate > 0)
            {
                // We have to do the fallback for the lonely high surrogate
                fallbackBuffer.InternalFallback(highSurrogate, ref chars);
                highSurrogate = (char)0;
                goto TryAgain;
            }

            // Check for overflows.
            if (byteCount < 0)
            {
                throw new ArgumentOutOfRangeException(nameof(count), SR.ArgumentOutOfRange_GetByteCountOverflow);
            }

            // Shouldn't have anything in fallback buffer for GetByteCount
            // (don't have to check m_throwOnOverflow for count)
            Debug.Assert(fallbackBuffer.Remaining == 0,
                         "[UTF32Encoding.GetByteCount]Expected empty fallback buffer at end");

            // Return our count
            return(byteCount);
        }
示例#26
0
	internal unsafe static EncoderStatus InternalGetBytesCount (
		char* chars, int charCount,
		EncoderFallbackBuffer fallbackBuffer,
		out int charsProcessed, out int bytesProcessed,
		ref uint leftChar,
		bool flush)
	{
		if (charCount < 0)
			throw new ArgumentOutOfRangeException ("charCount", _("ArgRange_Array"));

		return InternalGetBytes (
			chars, charCount,
			null, -1,
			fallbackBuffer,
			out charsProcessed, out bytesProcessed,
			ref leftChar,
			flush);
	}
示例#27
0
	int GetBytes (char[] chars, int charIndex, int charCount,
		      byte[] bytes, int byteIndex,
		      ref EncoderFallbackBuffer buffer,
		      ref char [] fallback_chars)
	{
#endif
		if (chars == null) {
			throw new ArgumentNullException ("chars");
		}
		if (bytes == null) {
			throw new ArgumentNullException ("bytes");
		}
		if (charIndex < 0 || charIndex > chars.Length) {
			throw new ArgumentOutOfRangeException ("charIndex", _("ArgRange_Array"));
		}
		if (charCount < 0 || charCount > (chars.Length - charIndex)) {
			throw new ArgumentOutOfRangeException ("charCount", _("ArgRange_Array"));
		}
		if (byteIndex < 0 || byteIndex > bytes.Length) {
			throw new ArgumentOutOfRangeException ("byteIndex", _("ArgRange_Array"));
		}
		if ((bytes.Length - byteIndex) < charCount) {
			throw new ArgumentException (_("Arg_InsufficientSpace"));
		}
		int count = charCount;
		char ch;
		while (count-- > 0) {
			ch = chars [charIndex++];
			if (ch < (char)0x0100) {
				bytes [byteIndex++] = (byte)ch;
			} else if (ch >= '\uFF01' && ch <= '\uFF5E') {
				bytes [byteIndex++] = (byte)(ch - 0xFEE0);
			} else {
#if NET_2_0
				if (buffer == null)
					buffer = EncoderFallback.CreateFallbackBuffer ();
				if (Char.IsSurrogate (ch) && count > 1 &&
				    Char.IsSurrogate (chars [charIndex]))
					buffer.Fallback (ch, chars [charIndex], charIndex++ - 1);
				else
					buffer.Fallback (ch, charIndex - 1);
				if (fallback_chars == null || fallback_chars.Length < buffer.Remaining)
					fallback_chars = new char [buffer.Remaining];
				for (int i = 0; i < fallback_chars.Length; i++)
					fallback_chars [i] = buffer.GetNextChar ();
				byteIndex += GetBytes (fallback_chars, 0, 
					fallback_chars.Length, bytes, byteIndex,
					ref buffer, ref fallback_chars);
#else
				bytes [byteIndex++] = (byte)'?';
#endif
			}
		}
		return charCount;
	}
示例#28
0
        private unsafe static int InternalGetByteCount(char *chars, int count, EncoderFallback fallback, ref char leftOver, bool flush)
        {
            int   length = 0;
            char *end    = chars + count;
            char *start  = chars;
            EncoderFallbackBuffer buffer = null;

            while (chars < end)
            {
                if (leftOver == 0)
                {
                    for (; chars < end; chars++)
                    {
                        if (*chars < '\x80')
                        {
                            ++length;
                        }
                        else if (*chars < '\x800')
                        {
                            length += 2;
                        }
                        else if (*chars < '\uD800' || *chars > '\uDFFF')
                        {
                            length += 3;
                        }
                        else if (*chars <= '\uDBFF')
                        {
                            // This is a surrogate start char, exit the inner loop only
                            // if we don't find the complete surrogate pair.
                            if (chars + 1 < end && chars [1] >= '\uDC00' && chars [1] <= '\uDFFF')
                            {
                                length += 4;
                                chars++;
                                continue;
                            }
                            leftOver = *chars;
                            chars++;
                            break;
                        }
                        else
                        {
                            // We have a surrogate tail without
                            // leading surrogate.
                            char [] fallback_chars = GetFallbackChars(chars, start, fallback, ref buffer);
                            fixed(char *fb_chars = fallback_chars)
                            {
                                char dummy = '\0';

                                length += InternalGetByteCount(fb_chars, fallback_chars.Length, fallback, ref dummy, true);
                            }

                            leftOver = '\0';
                        }
                    }
                }
                else
                {
                    if (*chars >= '\uDC00' && *chars <= '\uDFFF')
                    {
                        // We have a correct surrogate pair.
                        length += 4;
                        chars++;
                    }
                    else
                    {
                        // We have a surrogate start followed by a
                        // regular character.  Technically, this is
                        // invalid, but we have to do something.
                        // We write out the surrogate start and then
                        // re-visit the current character again.
                        char [] fallback_chars = GetFallbackChars(chars, start, fallback, ref buffer);
                        fixed(char *fb_chars = fallback_chars)
                        {
                            char dummy = '\0';

                            length += InternalGetByteCount(fb_chars, fallback_chars.Length, fallback, ref dummy, true);
                        }
                    }
                    leftOver = '\0';
                }
            }
            if (flush)
            {
                // Flush the left-over surrogate pair start.
                if (leftOver != '\0')
                {
                    length  += 3;
                    leftOver = '\0';
                }
            }
            return(length);
        }
示例#29
0
        internal override unsafe int GetBytes(char *chars, int charCount, byte *bytes, int byteCount, EncoderNLS encoder)
        {
            char ch1 = char.MinValue;
            EncoderReplacementFallback replacementFallback;

            if (encoder != null)
            {
                ch1 = encoder.charLeftOver;
                replacementFallback = encoder.Fallback as EncoderReplacementFallback;
            }
            else
            {
                replacementFallback = this.EncoderFallback as EncoderReplacementFallback;
            }
            char *charEnd = chars + charCount;
            byte *numPtr1 = bytes;
            char *chPtr   = chars;

            if (replacementFallback != null && replacementFallback.MaxCharCount == 1)
            {
                char ch2 = replacementFallback.DefaultString[0];
                if ((int)ch2 <= (int)byte.MaxValue)
                {
                    if ((int)ch1 > 0)
                    {
                        if (byteCount == 0)
                        {
                            this.ThrowBytesOverflow(encoder, true);
                        }
                        *bytes++ = (byte)ch2;
                        --byteCount;
                    }
                    if (byteCount < charCount)
                    {
                        this.ThrowBytesOverflow(encoder, byteCount < 1);
                        charEnd = chars + byteCount;
                    }
                    while (chars < charEnd)
                    {
                        char ch3     = *chars++;
                        *    bytes++ = (int)ch3 <= (int)byte.MaxValue ? (byte)ch3 : (byte)ch2;
                    }
                    if (encoder != null)
                    {
                        encoder.charLeftOver = char.MinValue;
                        encoder.m_charsUsed  = (int)(chars - chPtr);
                    }
                    return((int)(bytes - numPtr1));
                }
            }
            byte *numPtr2 = bytes + byteCount;
            EncoderFallbackBuffer encoderFallbackBuffer = (EncoderFallbackBuffer)null;

            if ((int)ch1 > 0)
            {
                encoderFallbackBuffer = encoder.FallbackBuffer;
                encoderFallbackBuffer.InternalInitialize(chars, charEnd, encoder, true);
                encoderFallbackBuffer.InternalFallback(ch1, ref chars);
                if ((long)encoderFallbackBuffer.Remaining > numPtr2 - bytes)
                {
                    this.ThrowBytesOverflow(encoder, true);
                }
            }
            char ch4;

            while ((int)(ch4 = encoderFallbackBuffer == null ? char.MinValue : encoderFallbackBuffer.InternalGetNextChar()) != 0 || chars < charEnd)
            {
                if ((int)ch4 == 0)
                {
                    ch4    = *chars;
                    chars += 2;
                }
                if ((int)ch4 > (int)byte.MaxValue)
                {
                    if (encoderFallbackBuffer == null)
                    {
                        encoderFallbackBuffer = encoder != null ? encoder.FallbackBuffer : this.encoderFallback.CreateFallbackBuffer();
                        encoderFallbackBuffer.InternalInitialize(charEnd - charCount, charEnd, encoder, true);
                    }
                    encoderFallbackBuffer.InternalFallback(ch4, ref chars);
                    if ((long)encoderFallbackBuffer.Remaining > numPtr2 - bytes)
                    {
                        chars -= 2;
                        encoderFallbackBuffer.InternalReset();
                        this.ThrowBytesOverflow(encoder, chars == chPtr);
                        break;
                    }
                }
                else
                {
                    if (bytes >= numPtr2)
                    {
                        if (encoderFallbackBuffer == null || !encoderFallbackBuffer.bFallingBack)
                        {
                            chars -= 2;
                        }
                        this.ThrowBytesOverflow(encoder, chars == chPtr);
                        break;
                    }
                    *bytes = (byte)ch4;
                    ++bytes;
                }
            }
            if (encoder != null)
            {
                if (encoderFallbackBuffer != null && !encoderFallbackBuffer.bUsedEncoder)
                {
                    encoder.charLeftOver = char.MinValue;
                }
                encoder.m_charsUsed = (int)(chars - chPtr);
            }
            return((int)(bytes - numPtr1));
        }
示例#30
0
        unsafe static char [] GetFallbackChars(char *chars, char *start, EncoderFallback fallback, ref EncoderFallbackBuffer buffer)
        {
            if (buffer == null)
            {
                buffer = fallback.CreateFallbackBuffer();
            }

            buffer.Fallback(*chars, (int)(chars - start));

            char [] fallback_chars = new char [buffer.Remaining];
            for (int i = 0; i < fallback_chars.Length; i++)
            {
                fallback_chars [i] = buffer.GetNextChar();
            }

            buffer.Reset();

            return(fallback_chars);
        }
示例#31
0
        internal override unsafe int GetBytes(char *chars, int charCount,
                                              byte *bytes, int byteCount, EncoderNLS encoder)
        {
            // Just need to ASSERT, this is called by something else internal that checked parameters already
            Debug.Assert(bytes != null, "[ASCIIEncoding.GetBytes]bytes is null");
            Debug.Assert(byteCount >= 0, "[ASCIIEncoding.GetBytes]byteCount is negative");
            Debug.Assert(chars != null, "[ASCIIEncoding.GetBytes]chars is null");
            Debug.Assert(charCount >= 0, "[ASCIIEncoding.GetBytes]charCount is negative");

            // Assert because we shouldn't be able to have a null encoder.
            Debug.Assert(encoderFallback != null, "[ASCIIEncoding.GetBytes]Attempting to use null encoder fallback");

            // Get any left over characters
            char charLeftOver = (char)0;
            EncoderReplacementFallback fallback = null;

            // For fallback we may need a fallback buffer, we know we aren't default fallback.
            EncoderFallbackBuffer fallbackBuffer = null;
            char *charsForFallback;

            // prepare our end
            char *charEnd   = chars + charCount;
            byte *byteStart = bytes;
            char *charStart = chars;

            if (encoder != null)
            {
                charLeftOver = encoder._charLeftOver;
                fallback     = encoder.Fallback as EncoderReplacementFallback;

                // We mustn't have left over fallback data when counting
                if (encoder.InternalHasFallbackBuffer)
                {
                    // We always need the fallback buffer in get bytes so we can flush any remaining ones if necessary
                    fallbackBuffer = encoder.FallbackBuffer;
                    if (fallbackBuffer.Remaining > 0 && encoder._throwOnOverflow)
                    {
                        throw new ArgumentException(SR.Format(SR.Argument_EncoderFallbackNotEmpty, this.EncodingName, encoder.Fallback.GetType()));
                    }

                    // Set our internal fallback interesting things.
                    fallbackBuffer.InternalInitialize(charStart, charEnd, encoder, true);
                }

                Debug.Assert(charLeftOver == 0 || Char.IsHighSurrogate(charLeftOver),
                             "[ASCIIEncoding.GetBytes]leftover character should be high surrogate");

                // Verify that we have no fallbackbuffer, for ASCII its always empty, so just assert
                Debug.Assert(!encoder._throwOnOverflow || !encoder.InternalHasFallbackBuffer ||
                             encoder.FallbackBuffer.Remaining == 0,
                             "[ASCIICodePageEncoding.GetBytes]Expected empty fallback buffer");
            }
            else
            {
                fallback = this.EncoderFallback as EncoderReplacementFallback;
            }


            // See if we do the fast default or slightly slower fallback
            if (fallback != null && fallback.MaxCharCount == 1)
            {
                // Fast version
                char cReplacement = fallback.DefaultString[0];

                // Check for replacements in range, otherwise fall back to slow version.
                if (cReplacement <= (char)0x7f)
                {
                    // We should have exactly as many output bytes as input bytes, unless there's a left
                    // over character, in which case we may need one more.
                    // If we had a left over character will have to add a ?  (This happens if they had a funky
                    // fallback last time, but not this time.) (We can't spit any out though
                    // because with fallback encoder each surrogate is treated as a seperate code point)
                    if (charLeftOver > 0)
                    {
                        // Have to have room
                        // Throw even if doing no throw version because this is just 1 char,
                        // so buffer will never be big enough
                        if (byteCount == 0)
                        {
                            ThrowBytesOverflow(encoder, true);
                        }

                        // This'll make sure we still have more room and also make sure our return value is correct.
                        *(bytes++) = (byte)cReplacement;
                        byteCount--;                // We used one of the ones we were counting.
                    }

                    // This keeps us from overrunning our output buffer
                    if (byteCount < charCount)
                    {
                        // Throw or make buffer smaller?
                        ThrowBytesOverflow(encoder, byteCount < 1);

                        // Just use what we can
                        charEnd = chars + byteCount;
                    }

                    // We just do a quick copy
                    while (chars < charEnd)
                    {
                        char ch2 = *(chars++);
                        if (ch2 >= 0x0080)
                        {
                            *(bytes++) = (byte)cReplacement;
                        }
                        else
                        {
                            *(bytes++) = unchecked ((byte)(ch2));
                        }
                    }

                    // Clear encoder
                    if (encoder != null)
                    {
                        encoder._charLeftOver = (char)0;
                        encoder._charsUsed    = (int)(chars - charStart);
                    }

                    return((int)(bytes - byteStart));
                }
            }

            // Slower version, have to do real fallback.

            // prepare our end
            byte *byteEnd = bytes + byteCount;

            // We may have a left over character from last time, try and process it.
            if (charLeftOver > 0)
            {
                // Initialize the buffer
                Debug.Assert(encoder != null,
                             "[ASCIIEncoding.GetBytes]Expected non null encoder if we have surrogate left over");
                fallbackBuffer = encoder.FallbackBuffer;
                fallbackBuffer.InternalInitialize(chars, charEnd, encoder, true);

                // 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
                charsForFallback = chars; // Avoid passing chars by reference to allow it to be enregistered
                fallbackBuffer.InternalFallback(charLeftOver, ref charsForFallback);
                chars = charsForFallback;
            }

            // 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.
                // All characters >= 0x80 must fall back.
                if (ch > 0x7f)
                {
                    // Initialize the buffer
                    if (fallbackBuffer == null)
                    {
                        if (encoder == null)
                        {
                            fallbackBuffer = this.encoderFallback.CreateFallbackBuffer();
                        }
                        else
                        {
                            fallbackBuffer = encoder.FallbackBuffer;
                        }
                        fallbackBuffer.InternalInitialize(charEnd - charCount, charEnd, encoder, true);
                    }

                    // Get Fallback
                    charsForFallback = chars; // Avoid passing chars by reference to allow it to be enregistered
                    fallbackBuffer.InternalFallback(ch, ref charsForFallback);
                    chars = charsForFallback;

                    // Go ahead & continue (& do the fallback)
                    continue;
                }

                // We'll use this one
                // Bounds check
                if (bytes >= byteEnd)
                {
                    // didn't use this char, we'll throw or use buffer
                    if (fallbackBuffer == null || fallbackBuffer.bFallingBack == false)
                    {
                        Debug.Assert(chars > charStart || bytes == byteStart,
                                     "[ASCIIEncoding.GetBytes]Expected chars to have advanced already.");
                        chars--;                                        // don't use last char
                    }
                    else
                    {
                        fallbackBuffer.MovePrevious();
                    }

                    // Are we throwing or using buffer?
                    ThrowBytesOverflow(encoder, bytes == byteStart);    // throw?
                    break;                                              // don't throw, stop
                }

                // Go ahead and add it
                *bytes = unchecked ((byte)ch);
                bytes++;
            }

            // Need to do encoder stuff
            if (encoder != null)
            {
                // Fallback stuck it in encoder if necessary, but we have to clear MustFlush cases
                if (fallbackBuffer != null && !fallbackBuffer.bUsedEncoder)
                {
                    // Clear it in case of MustFlush
                    encoder._charLeftOver = (char)0;
                }

                // Set our chars used count
                encoder._charsUsed = (int)(chars - charStart);
            }

            Debug.Assert(fallbackBuffer == null || fallbackBuffer.Remaining == 0 ||
                         (encoder != null && !encoder._throwOnOverflow),
                         "[ASCIIEncoding.GetBytes]Expected Empty fallback buffer at end");

            return((int)(bytes - byteStart));
        }
示例#32
0
        // Internal version of "GetBytes" which can handle a rolling
        // state between multiple calls to this method.
        private static int InternalGetBytes(char[] chars, int charIndex,
                                            int charCount, byte[] bytes,
                                            int byteIndex,
                                            EncoderFallback fallback, ref EncoderFallbackBuffer buffer,
                                            ref char leftOver, bool flush)
        {
            // Validate the parameters.
            if (chars == null)
            {
                throw new ArgumentNullException("chars");
            }
            if (bytes == null)
            {
                throw new ArgumentNullException("bytes");
            }
            if (charIndex < 0 || charIndex > chars.Length)
            {
                throw new ArgumentOutOfRangeException("charIndex", _("ArgRange_Array"));
            }
            if (charCount < 0 || charCount > (chars.Length - charIndex))
            {
                throw new ArgumentOutOfRangeException("charCount", _("ArgRange_Array"));
            }
            if (byteIndex < 0 || byteIndex > bytes.Length)
            {
                throw new ArgumentOutOfRangeException("byteIndex", _("ArgRange_Array"));
            }

            if (charIndex == chars.Length)
            {
                if (flush && leftOver != '\0')
                {
                    // FIXME: use EncoderFallback.
                    //
                    // By default it is empty, so I do nothing for now.
                    leftOver = '\0';
                }
                return(0);
            }

            unsafe
            {
                fixed(char *cptr = chars)
                {
                    if (bytes.Length == byteIndex)
                    {
                        return(InternalGetBytes(
                                   cptr + charIndex, charCount,
                                   null, 0, fallback, ref buffer, ref leftOver, flush));

                        fixed(byte *bptr = bytes)
                        {
                            return(InternalGetBytes(
                                       cptr + charIndex, charCount,
                                       bptr + byteIndex, bytes.Length - byteIndex,
                                       fallback, ref buffer,
                                       ref leftOver, flush));
                        }
                }
            }
        }
示例#33
0
        [System.Security.SecurityCritical]  // auto-generated
        internal override unsafe int GetBytes(char *chars, int charCount,
                                              byte *bytes, int byteCount, EncoderNLS encoder)
        {
            // Just need to ASSERT, this is called by something else internal that checked parameters already
            Contract.Assert(bytes != null, "[SBCSCodePageEncoding.GetBytes]bytes is null");
            Contract.Assert(byteCount >= 0, "[SBCSCodePageEncoding.GetBytes]byteCount is negative");
            Contract.Assert(chars != null, "[SBCSCodePageEncoding.GetBytes]chars is null");
            Contract.Assert(charCount >= 0, "[SBCSCodePageEncoding.GetBytes]charCount is negative");

            // Assert because we shouldn't be able to have a null encoder.
            Contract.Assert(encoderFallback != null, "[SBCSCodePageEncoding.GetBytes]Attempting to use null encoder fallback");

            CheckMemorySection();

            // Need to test fallback
            EncoderReplacementFallback fallback = null;

            // Get any left over characters
            char charLeftOver = (char)0;

            if (encoder != null)
            {
                charLeftOver = encoder.charLeftOver;
                Contract.Assert(charLeftOver == 0 || Char.IsHighSurrogate(charLeftOver),
                                "[SBCSCodePageEncoding.GetBytes]leftover character should be high surrogate");
                fallback = encoder.Fallback as EncoderReplacementFallback;

                // Verify that we have no fallbackbuffer, for SBCS its always empty, so just assert
                Contract.Assert(!encoder.m_throwOnOverflow || !encoder.InternalHasFallbackBuffer ||
                                encoder.FallbackBuffer.Remaining == 0,
                                "[SBCSCodePageEncoding.GetBytes]Expected empty fallback buffer at start");
//                if (encoder.m_throwOnOverflow && encoder.InternalHasFallbackBuffer &&
//                    encoder.FallbackBuffer.Remaining > 0)
//                    throw new ArgumentException(Environment.GetResourceString("Argument_EncoderFallbackNotEmpty",
//                        this.EncodingName, encoder.Fallback.GetType()));
            }
            else
            {
                // If we aren't using default fallback then we may have a complicated count.
                fallback = this.EncoderFallback as EncoderReplacementFallback;
            }

            // prepare our end
            char *charEnd   = chars + charCount;
            byte *byteStart = bytes;
            char *charStart = chars;

            // See if we do the fast default or slightly slower fallback
            if (fallback != null && fallback.MaxCharCount == 1)
            {
                // Make sure our fallback character is valid first
                byte bReplacement = mapUnicodeToBytes[fallback.DefaultString[0]];

                // Check for replacements in range, otherwise fall back to slow version.
                if (bReplacement != 0)
                {
                    // We should have exactly as many output bytes as input bytes, unless there's a left
                    // over character, in which case we may need one more.

                    // If we had a left over character will have to add a ?  (This happens if they had a funky
                    // fallback last time, but not this time.) (We can't spit any out though
                    // because with fallback encoder each surrogate is treated as a seperate code point)
                    if (charLeftOver > 0)
                    {
                        // Have to have room
                        // Throw even if doing no throw version because this is just 1 char,
                        // so buffer will never be big enough
                        if (byteCount == 0)
                        {
                            ThrowBytesOverflow(encoder, true);
                        }

                        // This'll make sure we still have more room and also make sure our return value is correct.
                        *(bytes++) = bReplacement;
                        byteCount--;                // We used one of the ones we were counting.
                    }

                    // This keeps us from overrunning our output buffer
                    if (byteCount < charCount)
                    {
                        // Throw or make buffer smaller?
                        ThrowBytesOverflow(encoder, byteCount < 1);

                        // Just use what we can
                        charEnd = chars + byteCount;
                    }

                    // Simple way
                    while (chars < charEnd)
                    {
                        char ch2 = *chars;
                        chars++;

                        byte bTemp = mapUnicodeToBytes[ch2];

                        // Check for fallback
                        if (bTemp == 0 && ch2 != (char)0)
                        {
                            *bytes = bReplacement;
                        }
                        else
                        {
                            *bytes = bTemp;
                        }

                        bytes++;
                    }

                    // Clear encoder
                    if (encoder != null)
                    {
                        encoder.charLeftOver = (char)0;
                        encoder.m_charsUsed  = (int)(chars - charStart);
                    }
                    return((int)(bytes - byteStart));
                }
            }

            // Slower version, have to do real fallback.

            // For fallback we may need a fallback buffer, we know we aren't default fallback
            EncoderFallbackBuffer fallbackBuffer = null;

            // prepare our end
            byte *byteEnd = bytes + byteCount;

            // We may have a left over character from last time, try and process it.
            if (charLeftOver > 0)
            {
                // Since left over char was a surrogate, it'll have to be fallen back.
                // Get Fallback
                Contract.Assert(encoder != null, "[SBCSCodePageEncoding.GetBytes]Expect to have encoder if we have a charLeftOver");
                fallbackBuffer = encoder.FallbackBuffer;
                fallbackBuffer.InternalInitialize(chars, charEnd, encoder, true);

                // This will fallback a pair if *chars is a low surrogate
                fallbackBuffer.InternalFallback(charLeftOver, ref chars);
                if (fallbackBuffer.Remaining > byteEnd - bytes)
                {
                    // Throw it, if we don't have enough for this we never will
                    ThrowBytesOverflow(encoder, true);
                }
            }

            // Now we may have fallback char[] already from the encoder fallback above

            // 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++;
                }

                // get byte for this char
                byte bTemp = mapUnicodeToBytes[ch];

                // Check for fallback, this'll catch surrogate pairs too.
                if (bTemp == 0 && ch != (char)0)
                {
                    // Get Fallback
                    if (fallbackBuffer == null)
                    {
                        // Create & init fallback buffer
                        if (encoder == null)
                        {
                            fallbackBuffer = this.encoderFallback.CreateFallbackBuffer();
                        }
                        else
                        {
                            fallbackBuffer = encoder.FallbackBuffer;
                        }
                        // chars has moved so we need to remember figure it out so Exception fallback
                        // index will be correct
                        fallbackBuffer.InternalInitialize(charEnd - charCount, charEnd, encoder, true);
                    }

                    // Make sure we have enough room.  Each fallback char will be 1 output char
                    // (or recursion exception will be thrown)
                    fallbackBuffer.InternalFallback(ch, ref chars);
                    if (fallbackBuffer.Remaining > byteEnd - bytes)
                    {
                        // Didn't use this char, reset it
                        Contract.Assert(chars > charStart,
                                        "[SBCSCodePageEncoding.GetBytes]Expected chars to have advanced (fallback)");
                        chars--;
                        fallbackBuffer.InternalReset();

                        // Throw it & drop this data
                        ThrowBytesOverflow(encoder, chars == charStart);
                        break;
                    }
                    continue;
                }

                // We'll use this one
                // Bounds check
                if (bytes >= byteEnd)
                {
                    // didn't use this char, we'll throw or use buffer
                    Contract.Assert(fallbackBuffer == null || fallbackBuffer.bFallingBack == false,
                                    "[SBCSCodePageEncoding.GetBytes]Expected to NOT be falling back");
                    if (fallbackBuffer == null || fallbackBuffer.bFallingBack == false)
                    {
                        Contract.Assert(chars > charStart,
                                        "[SBCSCodePageEncoding.GetBytes]Expected chars to have advanced (normal)");
                        chars--;                                        // don't use last char
                    }
                    ThrowBytesOverflow(encoder, chars == charStart);    // throw ?
                    break;                                              // don't throw, stop
                }

                // Go ahead and add it
                *bytes = bTemp;
                bytes++;
            }

            // encoder stuff if we have one
            if (encoder != null)
            {
                // Fallback stuck it in encoder if necessary, but we have to clear MustFlush cases
                if (fallbackBuffer != null && !fallbackBuffer.bUsedEncoder)
                {
                    // Clear it in case of MustFlush
                    encoder.charLeftOver = (char)0;
                }

                // Set our chars used count
                encoder.m_charsUsed = (int)(chars - charStart);
            }

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

            return((int)(bytes - byteStart));
        }
示例#34
0
        private unsafe static int InternalGetBytes(char *chars, int count, byte *bytes, int bcount, EncoderFallback fallback, ref EncoderFallbackBuffer buffer, ref char leftOver, bool flush)
        {
            char *end         = chars + count;
            char *start       = chars;
            byte *start_bytes = bytes;
            byte *end_bytes   = bytes + bcount;

            while (chars < end)
            {
                if (leftOver == 0)
                {
                    for (; chars < end; chars++)
                    {
                        int ch = *chars;
                        if (ch < '\x80')
                        {
                            if (bytes >= end_bytes)
                            {
                                goto fail_no_space;
                            }
                            *bytes++ = (byte)ch;
                        }
                        else if (ch < '\x800')
                        {
                            if (bytes + 1 >= end_bytes)
                            {
                                goto fail_no_space;
                            }
                            bytes [0] = (byte)(0xC0 | (ch >> 6));
                            bytes [1] = (byte)(0x80 | (ch & 0x3F));
                            bytes    += 2;
                        }
                        else if (ch < '\uD800' || ch > '\uDFFF')
                        {
                            if (bytes + 2 >= end_bytes)
                            {
                                goto fail_no_space;
                            }
                            bytes [0] = (byte)(0xE0 | (ch >> 12));
                            bytes [1] = (byte)(0x80 | ((ch >> 6) & 0x3F));
                            bytes [2] = (byte)(0x80 | (ch & 0x3F));
                            bytes    += 3;
                        }
                        else if (ch <= '\uDBFF')
                        {
                            // This is a surrogate char, exit the inner loop.
                            leftOver = *chars;
                            chars++;
                            break;
                        }
                        else
                        {
                            // We have a surrogate tail without
                            // leading surrogate.
                            char [] fallback_chars = GetFallbackChars(chars, start, fallback, ref buffer);
                            char    dummy          = '\0';
                            if (bytes + InternalGetByteCount(fallback_chars, 0, fallback_chars.Length, fallback, ref dummy, true) > end_bytes)
                                goto fail_no_space;
                            fixed(char *fb_chars = fallback_chars)
                            {
                                bytes += InternalGetBytes(fb_chars, fallback_chars.Length, bytes, bcount - (int)(bytes - start_bytes), fallback, ref buffer, ref dummy, true);
                            }

                            leftOver = '\0';
                        }
                    }
                }
                else
                {
                    if (*chars >= '\uDC00' && *chars <= '\uDFFF')
                    {
                        // We have a correct surrogate pair.
                        int ch = 0x10000 + (int)*chars - 0xDC00 + (((int)leftOver - 0xD800) << 10);
                        if (bytes + 3 >= end_bytes)
                        {
                            goto fail_no_space;
                        }
                        bytes [0] = (byte)(0xF0 | (ch >> 18));
                        bytes [1] = (byte)(0x80 | ((ch >> 12) & 0x3F));
                        bytes [2] = (byte)(0x80 | ((ch >> 6) & 0x3F));
                        bytes [3] = (byte)(0x80 | (ch & 0x3F));
                        bytes    += 4;
                        chars++;
                    }
                    else
                    {
                        // We have a surrogate start followed by a
                        // regular character.  Technically, this is
                        // invalid, but we have to do something.
                        // We write out the surrogate start and then
                        // re-visit the current character again.
                        char [] fallback_chars = GetFallbackChars(chars, start, fallback, ref buffer);
                        char    dummy          = '\0';
                        if (bytes + InternalGetByteCount(fallback_chars, 0, fallback_chars.Length, fallback, ref dummy, true) > end_bytes)
                            goto fail_no_space;
                        fixed(char *fb_chars = fallback_chars)
                        {
                            InternalGetBytes(fb_chars, fallback_chars.Length, bytes, bcount - (int)(bytes - start_bytes), fallback, ref buffer, ref dummy, true);
                        }

                        leftOver = '\0';
                    }
                    leftOver = '\0';
                }
            }
            if (flush)
            {
                // Flush the left-over surrogate pair start.
                if (leftOver != '\0')
                {
                    int ch = leftOver;
                    if (bytes + 2 < end_bytes)
                    {
                        bytes [0] = (byte)(0xE0 | (ch >> 12));
                        bytes [1] = (byte)(0x80 | ((ch >> 6) & 0x3F));
                        bytes [2] = (byte)(0x80 | (ch & 0x3F));
                        bytes    += 3;
                    }
                    else
                    {
                        goto fail_no_space;
                    }
                    leftOver = '\0';
                }
            }
            return((int)(bytes - (end_bytes - bcount)));

fail_no_space:
            throw new ArgumentException("Insufficient Space", "bytes");
        }
	unsafe int InternalGetBytes (char *chars, int charLength, int charIndex, int charCount,
		      byte[] bytes, int byteIndex,
		      ref EncoderFallbackBuffer buffer,
		      ref char [] fallback_chars)
	{
		if (bytes == null)
			throw new ArgumentNullException ("bytes");
		if (charIndex < 0 || charIndex > charLength)
			throw new ArgumentOutOfRangeException ("charIndex", _("ArgRange_StringIndex"));
		if (charCount < 0 || charCount > (charLength - charIndex))
			throw new ArgumentOutOfRangeException ("charCount", _("ArgRange_StringRange"));
		if (byteIndex < 0 || byteIndex > bytes.Length)
			throw new ArgumentOutOfRangeException ("byteIndex", _("ArgRange_Array"));
		if ((bytes.Length - byteIndex) < charCount)
			throw new ArgumentException (_("Arg_InsufficientSpace"));

		int count = charCount;
		char ch;
		while (count-- > 0) {
			ch = chars [charIndex++];
			if (ch < (char)0x80) {
				bytes [byteIndex++] = (byte)ch;
			} else {
				if (buffer == null)
					buffer = EncoderFallback.CreateFallbackBuffer ();
				if (Char.IsSurrogate (ch) && count > 1 &&
				    Char.IsSurrogate (chars [charIndex]))
					buffer.Fallback (ch, chars [charIndex], charIndex++ - 1);
				else
					buffer.Fallback (ch, charIndex - 1);
				if (fallback_chars == null || fallback_chars.Length < buffer.Remaining)
					fallback_chars = new char [buffer.Remaining];
				for (int i = 0; i < fallback_chars.Length; i++)
					fallback_chars [i] = buffer.GetNextChar ();
				byteIndex += GetBytes (fallback_chars, 0, 
					fallback_chars.Length, bytes, byteIndex,
					ref buffer, ref fallback_chars);
			}
		}
		return charCount;
	}
示例#36
0
        internal unsafe override int GetByteCount(char *chars, int charCount, EncoderNLS encoder)
        {
            char  c   = '\0';
            char *ptr = chars + charCount;
            EncoderFallbackBuffer      encoderFallbackBuffer = null;
            EncoderReplacementFallback encoderReplacementFallback;

            if (encoder != null)
            {
                c = encoder.charLeftOver;
                encoderReplacementFallback = (encoder.Fallback as EncoderReplacementFallback);
                if (encoder.InternalHasFallbackBuffer)
                {
                    encoderFallbackBuffer = encoder.FallbackBuffer;
                    if (encoderFallbackBuffer.Remaining > 0 && encoder.m_throwOnOverflow)
                    {
                        throw new ArgumentException(Environment.GetResourceString("Argument_EncoderFallbackNotEmpty", new object[]
                        {
                            this.EncodingName,
                            encoder.Fallback.GetType()
                        }));
                    }
                    encoderFallbackBuffer.InternalInitialize(chars, ptr, encoder, false);
                }
            }
            else
            {
                encoderReplacementFallback = (base.EncoderFallback as EncoderReplacementFallback);
            }
            if (encoderReplacementFallback != null && encoderReplacementFallback.MaxCharCount == 1)
            {
                if (c > '\0')
                {
                    charCount++;
                }
                return(charCount);
            }
            int num = 0;

            if (c > '\0')
            {
                encoderFallbackBuffer = encoder.FallbackBuffer;
                encoderFallbackBuffer.InternalInitialize(chars, ptr, encoder, false);
                encoderFallbackBuffer.InternalFallback(c, ref chars);
            }
            char c2;

            while ((c2 = ((encoderFallbackBuffer == null) ? '\0' : encoderFallbackBuffer.InternalGetNextChar())) != '\0' || chars < ptr)
            {
                if (c2 == '\0')
                {
                    c2 = *chars;
                    chars++;
                }
                if (c2 > '\u007f')
                {
                    if (encoderFallbackBuffer == null)
                    {
                        if (encoder == null)
                        {
                            encoderFallbackBuffer = this.encoderFallback.CreateFallbackBuffer();
                        }
                        else
                        {
                            encoderFallbackBuffer = encoder.FallbackBuffer;
                        }
                        encoderFallbackBuffer.InternalInitialize(ptr - charCount, ptr, encoder, false);
                    }
                    encoderFallbackBuffer.InternalFallback(c2, ref chars);
                }
                else
                {
                    num++;
                }
            }
            return(num);
        }
	unsafe static char [] GetFallbackChars (char *chars, char *start, EncoderFallback fallback, ref EncoderFallbackBuffer buffer)
	{
		if (buffer == null)
			buffer = fallback.CreateFallbackBuffer ();

		buffer.Fallback (*chars, (int) (chars - start));

		char [] fallback_chars = new char [buffer.Remaining];
		for (int i = 0; i < fallback_chars.Length; i++)
			fallback_chars [i] = buffer.GetNextChar ();

		buffer.Reset ();

		return fallback_chars;
	}
示例#38
0
        internal unsafe override int GetBytes(char *chars, int charCount, byte *bytes, int byteCount, EncoderNLS encoder)
        {
            char c = '\0';
            EncoderFallbackBuffer encoderFallbackBuffer = null;
            char *ptr  = chars + charCount;
            byte *ptr2 = bytes;
            char *ptr3 = chars;
            EncoderReplacementFallback encoderReplacementFallback;

            if (encoder != null)
            {
                c = encoder.charLeftOver;
                encoderReplacementFallback = (encoder.Fallback as EncoderReplacementFallback);
                if (encoder.InternalHasFallbackBuffer)
                {
                    encoderFallbackBuffer = encoder.FallbackBuffer;
                    if (encoderFallbackBuffer.Remaining > 0 && encoder.m_throwOnOverflow)
                    {
                        throw new ArgumentException(Environment.GetResourceString("Argument_EncoderFallbackNotEmpty", new object[]
                        {
                            this.EncodingName,
                            encoder.Fallback.GetType()
                        }));
                    }
                    encoderFallbackBuffer.InternalInitialize(ptr3, ptr, encoder, true);
                }
            }
            else
            {
                encoderReplacementFallback = (base.EncoderFallback as EncoderReplacementFallback);
            }
            if (encoderReplacementFallback != null && encoderReplacementFallback.MaxCharCount == 1)
            {
                char c2 = encoderReplacementFallback.DefaultString[0];
                if (c2 <= '\u007f')
                {
                    if (c > '\0')
                    {
                        if (byteCount == 0)
                        {
                            base.ThrowBytesOverflow(encoder, true);
                        }
                        *(bytes++) = (byte)c2;
                        byteCount--;
                    }
                    if (byteCount < charCount)
                    {
                        base.ThrowBytesOverflow(encoder, byteCount < 1);
                        ptr = chars + byteCount;
                    }
                    while (chars < ptr)
                    {
                        char c3 = *(chars++);
                        if (c3 >= '\u0080')
                        {
                            *(bytes++) = (byte)c2;
                        }
                        else
                        {
                            *(bytes++) = (byte)c3;
                        }
                    }
                    if (encoder != null)
                    {
                        encoder.charLeftOver = '\0';
                        encoder.m_charsUsed  = (int)((long)(chars - ptr3));
                    }
                    return((int)((long)(bytes - ptr2)));
                }
            }
            byte *ptr4 = bytes + byteCount;

            if (c > '\0')
            {
                encoderFallbackBuffer = encoder.FallbackBuffer;
                encoderFallbackBuffer.InternalInitialize(chars, ptr, encoder, true);
                encoderFallbackBuffer.InternalFallback(c, ref chars);
            }
            char c4;

            while ((c4 = ((encoderFallbackBuffer == null) ? '\0' : encoderFallbackBuffer.InternalGetNextChar())) != '\0' || chars < ptr)
            {
                if (c4 == '\0')
                {
                    c4 = *chars;
                    chars++;
                }
                if (c4 > '\u007f')
                {
                    if (encoderFallbackBuffer == null)
                    {
                        if (encoder == null)
                        {
                            encoderFallbackBuffer = this.encoderFallback.CreateFallbackBuffer();
                        }
                        else
                        {
                            encoderFallbackBuffer = encoder.FallbackBuffer;
                        }
                        encoderFallbackBuffer.InternalInitialize(ptr - charCount, ptr, encoder, true);
                    }
                    encoderFallbackBuffer.InternalFallback(c4, ref chars);
                }
                else
                {
                    if (bytes >= ptr4)
                    {
                        if (encoderFallbackBuffer == null || !encoderFallbackBuffer.bFallingBack)
                        {
                            chars--;
                        }
                        else
                        {
                            encoderFallbackBuffer.MovePrevious();
                        }
                        base.ThrowBytesOverflow(encoder, bytes == ptr2);
                        break;
                    }
                    *bytes = (byte)c4;
                    bytes++;
                }
            }
            if (encoder != null)
            {
                if (encoderFallbackBuffer != null && !encoderFallbackBuffer.bUsedEncoder)
                {
                    encoder.charLeftOver = '\0';
                }
                encoder.m_charsUsed = (int)((long)(chars - ptr3));
            }
            return((int)((long)(bytes - ptr2)));
        }
	private unsafe static int InternalGetBytes (char* chars, int count, byte* bytes, int bcount, EncoderFallback fallback, ref EncoderFallbackBuffer buffer, ref char leftOver, bool flush)
	{
		char* end = chars + count;
		char* start = chars;
		byte* start_bytes = bytes;
		byte* end_bytes = bytes + bcount;
		while (chars < end) {
			if (leftOver == 0) {
				for (; chars < end; chars++) {
					int ch = *chars;
					if (ch < '\x80') {
						if (bytes >= end_bytes)
							goto fail_no_space;
						*bytes++ = (byte)ch;
					} else if (ch < '\x800') {
						if (bytes + 1 >= end_bytes)
							goto fail_no_space;
						bytes [0] = (byte) (0xC0 | (ch >> 6));
						bytes [1] = (byte) (0x80 | (ch & 0x3F));
						bytes += 2;
					} else if (ch < '\uD800' || ch > '\uDFFF') {
						if (bytes + 2 >= end_bytes)
							goto fail_no_space;
						bytes [0] = (byte) (0xE0 | (ch >> 12));
						bytes [1] = (byte) (0x80 | ((ch >> 6) & 0x3F));
						bytes [2] = (byte) (0x80 | (ch & 0x3F));
						bytes += 3;
					} else if (ch <= '\uDBFF') {
						// This is a surrogate char, exit the inner loop.
						leftOver = *chars;
						chars++;
						break;
					} else {
						// We have a surrogate tail without 
						// leading surrogate. In NET_2_0 it
						// uses fallback. In NET_1_1 we output
						// wrong surrogate.
						char [] fallback_chars = GetFallbackChars (chars, start, fallback, ref buffer); 
						char dummy = '\0';
						if (bytes + InternalGetByteCount (fallback_chars, 0, fallback_chars.Length, fallback, ref dummy, true) > end_bytes)
							goto fail_no_space;
						fixed (char *fb_chars = fallback_chars) {
							bytes += InternalGetBytes (fb_chars, fallback_chars.Length, bytes, bcount - (int) (bytes - start_bytes), fallback, ref buffer, ref dummy, true);
						}

						leftOver = '\0';
					}
				}
			} else {
				if (*chars >= '\uDC00' && *chars <= '\uDFFF') {
					// We have a correct surrogate pair.
					int ch = 0x10000 + (int) *chars - 0xDC00 + (((int) leftOver - 0xD800) << 10);
					if (bytes + 3 >= end_bytes)
						goto fail_no_space;
					bytes [0] = (byte) (0xF0 | (ch >> 18));
					bytes [1] = (byte) (0x80 | ((ch >> 12) & 0x3F));
					bytes [2] = (byte) (0x80 | ((ch >> 6) & 0x3F));
					bytes [3] = (byte) (0x80 | (ch & 0x3F));
					bytes += 4;
					chars++;
				} else {
					// We have a surrogate start followed by a
					// regular character.  Technically, this is
					// invalid, but we have to do something.
					// We write out the surrogate start and then
					// re-visit the current character again.
					char [] fallback_chars = GetFallbackChars (chars, start, fallback, ref buffer); 
					char dummy = '\0';
					if (bytes + InternalGetByteCount (fallback_chars, 0, fallback_chars.Length, fallback, ref dummy, true) > end_bytes)
						goto fail_no_space;
					fixed (char *fb_chars = fallback_chars) {
						InternalGetBytes (fb_chars, fallback_chars.Length, bytes, bcount - (int) (bytes - start_bytes), fallback, ref buffer, ref dummy, true);
					}

					leftOver = '\0';
				}
				leftOver = '\0';
			}
		}
		if (flush) {
			// Flush the left-over surrogate pair start.
			if (leftOver != '\0') {
				int ch = leftOver;
				if (bytes + 2 < end_bytes) {
					bytes [0] = (byte) (0xE0 | (ch >> 12));
					bytes [1] = (byte) (0x80 | ((ch >> 6) & 0x3F));
					bytes [2] = (byte) (0x80 | (ch & 0x3F));
					bytes += 3;
				} else {
					goto fail_no_space;
				}
				leftOver = '\0';
			}
		}
		return (int)(bytes - (end_bytes - bcount));
fail_no_space:
		throw new ArgumentException ("Insufficient Space", "bytes");
	}
        internal unsafe override int GetByteCount(char *chars, int count, EncoderNLS encoder)
        {
            base.CheckMemorySection();
            char c = '\0';
            EncoderReplacementFallback encoderReplacementFallback;

            if (encoder != null)
            {
                c = encoder.charLeftOver;
                encoderReplacementFallback = (encoder.Fallback as EncoderReplacementFallback);
            }
            else
            {
                encoderReplacementFallback = (base.EncoderFallback as EncoderReplacementFallback);
            }
            if (encoderReplacementFallback != null && encoderReplacementFallback.MaxCharCount == 1)
            {
                if (c > '\0')
                {
                    count++;
                }
                return(count);
            }
            EncoderFallbackBuffer encoderFallbackBuffer = null;
            int   num = 0;
            char *ptr = chars + count;

            if (c > '\0')
            {
                encoderFallbackBuffer = encoder.FallbackBuffer;
                encoderFallbackBuffer.InternalInitialize(chars, ptr, encoder, false);
                encoderFallbackBuffer.InternalFallback(c, ref chars);
            }
            char c2;

            while ((c2 = ((encoderFallbackBuffer == null) ? '\0' : encoderFallbackBuffer.InternalGetNextChar())) != '\0' || chars < ptr)
            {
                if (c2 == '\0')
                {
                    c2 = *chars;
                    chars++;
                }
                if (this.mapUnicodeToBytes[c2] == 0 && c2 != '\0')
                {
                    if (encoderFallbackBuffer == null)
                    {
                        if (encoder == null)
                        {
                            encoderFallbackBuffer = this.encoderFallback.CreateFallbackBuffer();
                        }
                        else
                        {
                            encoderFallbackBuffer = encoder.FallbackBuffer;
                        }
                        encoderFallbackBuffer.InternalInitialize(ptr - count, ptr, encoder, false);
                    }
                    encoderFallbackBuffer.InternalFallback(c2, ref chars);
                }
                else
                {
                    num++;
                }
            }
            return(num);
        }
        internal unsafe override int GetBytes(char *chars, int charCount, byte *bytes, int byteCount, EncoderNLS encoder)
        {
            base.CheckMemorySection();
            char c = '\0';
            EncoderReplacementFallback encoderReplacementFallback;

            if (encoder != null)
            {
                c = encoder.charLeftOver;
                encoderReplacementFallback = (encoder.Fallback as EncoderReplacementFallback);
            }
            else
            {
                encoderReplacementFallback = (base.EncoderFallback as EncoderReplacementFallback);
            }
            char *ptr  = chars + charCount;
            byte *ptr2 = bytes;
            char *ptr3 = chars;

            if (encoderReplacementFallback != null && encoderReplacementFallback.MaxCharCount == 1)
            {
                byte b = this.mapUnicodeToBytes[encoderReplacementFallback.DefaultString[0]];
                if (b != 0)
                {
                    if (c > '\0')
                    {
                        if (byteCount == 0)
                        {
                            base.ThrowBytesOverflow(encoder, true);
                        }
                        *(bytes++) = b;
                        byteCount--;
                    }
                    if (byteCount < charCount)
                    {
                        base.ThrowBytesOverflow(encoder, byteCount < 1);
                        ptr = chars + byteCount;
                    }
                    while (chars < ptr)
                    {
                        char c2 = *chars;
                        chars++;
                        byte b2 = this.mapUnicodeToBytes[c2];
                        if (b2 == 0 && c2 != '\0')
                        {
                            *bytes = b;
                        }
                        else
                        {
                            *bytes = b2;
                        }
                        bytes++;
                    }
                    if (encoder != null)
                    {
                        encoder.charLeftOver = '\0';
                        encoder.m_charsUsed  = (int)((long)(chars - ptr3));
                    }
                    return((int)((long)(bytes - ptr2)));
                }
            }
            EncoderFallbackBuffer encoderFallbackBuffer = null;
            byte *ptr4 = bytes + byteCount;

            if (c > '\0')
            {
                encoderFallbackBuffer = encoder.FallbackBuffer;
                encoderFallbackBuffer.InternalInitialize(chars, ptr, encoder, true);
                encoderFallbackBuffer.InternalFallback(c, ref chars);
                if ((long)encoderFallbackBuffer.Remaining > (long)(ptr4 - bytes))
                {
                    base.ThrowBytesOverflow(encoder, true);
                }
            }
            char c3;

            while ((c3 = ((encoderFallbackBuffer == null) ? '\0' : encoderFallbackBuffer.InternalGetNextChar())) != '\0' || chars < ptr)
            {
                if (c3 == '\0')
                {
                    c3 = *chars;
                    chars++;
                }
                byte b3 = this.mapUnicodeToBytes[c3];
                if (b3 == 0 && c3 != '\0')
                {
                    if (encoderFallbackBuffer == null)
                    {
                        if (encoder == null)
                        {
                            encoderFallbackBuffer = this.encoderFallback.CreateFallbackBuffer();
                        }
                        else
                        {
                            encoderFallbackBuffer = encoder.FallbackBuffer;
                        }
                        encoderFallbackBuffer.InternalInitialize(ptr - charCount, ptr, encoder, true);
                    }
                    encoderFallbackBuffer.InternalFallback(c3, ref chars);
                    if ((long)encoderFallbackBuffer.Remaining > (long)(ptr4 - bytes))
                    {
                        chars--;
                        encoderFallbackBuffer.InternalReset();
                        base.ThrowBytesOverflow(encoder, chars == ptr3);
                        break;
                    }
                }
                else
                {
                    if (bytes >= ptr4)
                    {
                        if (encoderFallbackBuffer == null || !encoderFallbackBuffer.bFallingBack)
                        {
                            chars--;
                        }
                        base.ThrowBytesOverflow(encoder, chars == ptr3);
                        break;
                    }
                    *bytes = b3;
                    bytes++;
                }
            }
            if (encoder != null)
            {
                if (encoderFallbackBuffer != null && !encoderFallbackBuffer.bUsedEncoder)
                {
                    encoder.charLeftOver = '\0';
                }
                encoder.m_charsUsed = (int)((long)(chars - ptr3));
            }
            return((int)((long)(bytes - ptr2)));
        }
示例#42
0
        internal override unsafe int GetBytes(char *chars, int charCount, byte *bytes, int byteCount, EncoderNLS encoder)
        {
            char ch3;

            base.CheckMemorySection();
            EncoderReplacementFallback encoderFallback = null;
            char charLeftOver = '\0';

            if (encoder != null)
            {
                charLeftOver    = encoder.charLeftOver;
                encoderFallback = encoder.Fallback as EncoderReplacementFallback;
            }
            else
            {
                encoderFallback = base.EncoderFallback as EncoderReplacementFallback;
            }
            char *charEnd = chars + charCount;
            byte *numPtr  = bytes;
            char *chPtr2  = chars;

            if ((encoderFallback != null) && (encoderFallback.MaxCharCount == 1))
            {
                byte num = this.mapUnicodeToBytes[(int)((byte *)encoderFallback.DefaultString[0])];
                if (num != 0)
                {
                    if (charLeftOver > '\0')
                    {
                        if (byteCount == 0)
                        {
                            base.ThrowBytesOverflow(encoder, true);
                        }
                        bytes++;
                        bytes[0] = num;
                        byteCount--;
                    }
                    if (byteCount < charCount)
                    {
                        base.ThrowBytesOverflow(encoder, byteCount < 1);
                        charEnd = chars + byteCount;
                    }
                    while (chars < charEnd)
                    {
                        char ch2 = chars[0];
                        chars++;
                        byte num2 = this.mapUnicodeToBytes[(int)((byte *)ch2)];
                        if ((num2 == 0) && (ch2 != '\0'))
                        {
                            bytes[0] = num;
                        }
                        else
                        {
                            bytes[0] = num2;
                        }
                        bytes++;
                    }
                    if (encoder != null)
                    {
                        encoder.charLeftOver = '\0';
                        encoder.m_charsUsed  = (int)((long)((chars - chPtr2) / 2));
                    }
                    return((int)((long)((bytes - numPtr) / 1)));
                }
            }
            EncoderFallbackBuffer fallbackBuffer = null;
            byte *numPtr2 = bytes + byteCount;

            if (charLeftOver > '\0')
            {
                fallbackBuffer = encoder.FallbackBuffer;
                fallbackBuffer.InternalInitialize(chars, charEnd, encoder, true);
                fallbackBuffer.InternalFallback(charLeftOver, ref chars);
                if (fallbackBuffer.Remaining > ((long)((numPtr2 - bytes) / 1)))
                {
                    base.ThrowBytesOverflow(encoder, true);
                }
            }
            while (((ch3 = (fallbackBuffer == null) ? '\0' : fallbackBuffer.InternalGetNextChar()) != '\0') || (chars < charEnd))
            {
                if (ch3 == '\0')
                {
                    ch3 = chars[0];
                    chars++;
                }
                byte num3 = this.mapUnicodeToBytes[(int)((byte *)ch3)];
                if ((num3 == 0) && (ch3 != '\0'))
                {
                    if (fallbackBuffer == null)
                    {
                        if (encoder == null)
                        {
                            fallbackBuffer = base.encoderFallback.CreateFallbackBuffer();
                        }
                        else
                        {
                            fallbackBuffer = encoder.FallbackBuffer;
                        }
                        fallbackBuffer.InternalInitialize(charEnd - charCount, charEnd, encoder, true);
                    }
                    fallbackBuffer.InternalFallback(ch3, ref chars);
                    if (fallbackBuffer.Remaining <= ((long)((numPtr2 - bytes) / 1)))
                    {
                        continue;
                    }
                    chars--;
                    fallbackBuffer.InternalReset();
                    base.ThrowBytesOverflow(encoder, chars == chPtr2);
                    break;
                }
                if (bytes >= numPtr2)
                {
                    if ((fallbackBuffer == null) || !fallbackBuffer.bFallingBack)
                    {
                        chars--;
                    }
                    base.ThrowBytesOverflow(encoder, chars == chPtr2);
                    break;
                }
                bytes[0] = num3;
                bytes++;
            }
            if (encoder != null)
            {
                if ((fallbackBuffer != null) && !fallbackBuffer.bUsedEncoder)
                {
                    encoder.charLeftOver = '\0';
                }
                encoder.m_charsUsed = (int)((long)((chars - chPtr2) / 2));
            }
            return((int)((long)((bytes - numPtr) / 1)));
        }
示例#43
0
            [System.Security.SecurityCritical]  // auto-generated
            internal unsafe EncodingByteBuffer(Encoding inEncoding, EncoderNLS inEncoder,
                        byte* inByteStart, int inByteCount, char* inCharStart, int inCharCount)
            {
                this.enc = inEncoding;
                this.encoder = inEncoder;

                this.charStart = inCharStart;
                this.chars = inCharStart;
                this.charEnd = inCharStart + inCharCount;

                this.bytes = inByteStart;
                this.byteStart = inByteStart;
                this.byteEnd = inByteStart + inByteCount;

                if (this.encoder == null)
                    this.fallbackBuffer = enc.EncoderFallback.CreateFallbackBuffer();
                else
                {
                    this.fallbackBuffer = this.encoder.FallbackBuffer;
                    // If we're not converting we must not have data in our fallback buffer
                    if (encoder.m_throwOnOverflow && encoder.InternalHasFallbackBuffer &&
                        this.fallbackBuffer.Remaining > 0)
                        throw new ArgumentException(Environment.GetResourceString("Argument_EncoderFallbackNotEmpty",
                            encoder.Encoding.EncodingName, encoder.Fallback.GetType()));
                }
                fallbackBuffer.InternalInitialize(chars, charEnd, encoder, bytes != null);
            }
示例#44
0
        internal override unsafe int GetByteCount(char *chars, int count, EncoderNLS encoder)
        {
            char ch2;

            base.CheckMemorySection();
            EncoderReplacementFallback encoderFallback = null;
            char charLeftOver = '\0';

            if (encoder != null)
            {
                charLeftOver    = encoder.charLeftOver;
                encoderFallback = encoder.Fallback as EncoderReplacementFallback;
            }
            else
            {
                encoderFallback = base.EncoderFallback as EncoderReplacementFallback;
            }
            if ((encoderFallback != null) && (encoderFallback.MaxCharCount == 1))
            {
                if (charLeftOver > '\0')
                {
                    count++;
                }
                return(count);
            }
            EncoderFallbackBuffer fallbackBuffer = null;
            int   num     = 0;
            char *charEnd = chars + count;

            if (charLeftOver > '\0')
            {
                fallbackBuffer = encoder.FallbackBuffer;
                fallbackBuffer.InternalInitialize(chars, charEnd, encoder, false);
                fallbackBuffer.InternalFallback(charLeftOver, ref chars);
            }
            while (((ch2 = (fallbackBuffer == null) ? '\0' : fallbackBuffer.InternalGetNextChar()) != '\0') || (chars < charEnd))
            {
                if (ch2 == '\0')
                {
                    ch2 = chars[0];
                    chars++;
                }
                if ((this.mapUnicodeToBytes[ch2] == 0) && (ch2 != '\0'))
                {
                    if (fallbackBuffer == null)
                    {
                        if (encoder == null)
                        {
                            fallbackBuffer = base.encoderFallback.CreateFallbackBuffer();
                        }
                        else
                        {
                            fallbackBuffer = encoder.FallbackBuffer;
                        }
                        fallbackBuffer.InternalInitialize(charEnd - count, charEnd, encoder, false);
                    }
                    fallbackBuffer.InternalFallback(ch2, ref chars);
                }
                else
                {
                    num++;
                }
            }
            return(num);
        }
 internal unsafe EncodingByteBuffer(Encoding inEncoding, EncoderNLS inEncoder, byte* inByteStart, int inByteCount, char* inCharStart, int inCharCount)
 {
     this.enc = inEncoding;
     this.encoder = inEncoder;
     this.charStart = inCharStart;
     this.chars = inCharStart;
     this.charEnd = inCharStart + inCharCount;
     this.bytes = inByteStart;
     this.byteStart = inByteStart;
     this.byteEnd = inByteStart + inByteCount;
     if (this.encoder == null)
     {
         this.fallbackBuffer = this.enc.EncoderFallback.CreateFallbackBuffer();
     }
     else
     {
         this.fallbackBuffer = this.encoder.FallbackBuffer;
         if ((this.encoder.m_throwOnOverflow && this.encoder.InternalHasFallbackBuffer) && (this.fallbackBuffer.Remaining > 0))
         {
             throw new ArgumentException(Environment.GetResourceString("Argument_EncoderFallbackNotEmpty", new object[] { this.encoder.Encoding.EncodingName, this.encoder.Fallback.GetType() }));
         }
     }
     this.fallbackBuffer.InternalInitialize(this.chars, this.charEnd, this.encoder, this.bytes != null);
 }
示例#46
0
	// This function is called when we want to flush the decoder state
	// (i.e. in case of invalid UTF-16 characters or dangling surrogates)
	internal unsafe static EncoderStatus InternalGetBytesFlush (
		byte* bytes, int byteCount,
		EncoderFallbackBuffer fallbackBuffer,
		int charsProcessed, ref int bytesProcessed,
		ref uint leftChar)
	{
		int t_charsProcessed, t_bytesProcessed;

		// in normal circumstances fallbackBuffer never is null, except
		// when we have called InternalGetBytes from this function
		// (for avoiding infinite recursive calls)
		if (fallbackBuffer == null)
			return EncoderStatus.Ok;

		// if there is nothing to flush, then return silently
		if(leftChar == 0)
			return EncoderStatus.Ok;

		// invalid UTF-16 or invalid surrogate
		fallbackBuffer.Fallback ((char) leftChar, charsProcessed - 1);
		// if we've arrived here we are working in replacement mode:
		// build a replacement fallback_chars buffer
		char[] fallback_chars = new char [fallbackBuffer.Remaining];
		for (int i = 0; i < fallback_chars.Length; i++)
			fallback_chars [i] = fallbackBuffer.GetNextChar ();
		fallbackBuffer.Reset ();
		// and encode it into UTF8 bytes...
		fixed (char *fb_chars = fallback_chars) {
			leftChar = 0;
			switch (bytes != null
				? InternalGetBytes (
						fb_chars, fallback_chars.Length,
						bytes + bytesProcessed, byteCount - bytesProcessed,
						null, out t_charsProcessed, out t_bytesProcessed,
						ref leftChar,
						true)
				: InternalGetBytes (
						fb_chars, fallback_chars.Length,
						null, byteCount,
						null, out t_charsProcessed, out t_bytesProcessed,
						ref leftChar,
						true)) {
			case EncoderStatus.Ok:
				// everything OK :D
				bytesProcessed += t_bytesProcessed;
				break;
			case EncoderStatus.InsufficientSpace:
				return EncoderStatus.InsufficientSpace;
			case EncoderStatus.InputRunOut:
			case EncoderStatus.InvalidChar:
			case EncoderStatus.InvalidSurrogate:
				throw new ArgumentException ("Fallback chars are pure evil.", "fallback buffer bytes");
			}
		}
		// flush encoder state
		leftChar = 0;
		return EncoderStatus.Ok;
	}