| File: System\Text\EncodingByteBuffer.cs | Web Access |
| Project: src\runtime\src\libraries\System.Text.Encoding.CodePages\src\System.Text.Encoding.CodePages.csproj (System.Text.Encoding.CodePages) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System.Diagnostics; namespace System.Text { internal sealed class EncodingByteBuffer { private unsafe byte* _bytes; private readonly unsafe byte* _byteStart; private readonly unsafe byte* _byteEnd; private unsafe char* _chars; private readonly unsafe char* _charStart; private readonly unsafe char* _charEnd; private int _byteCountResult; private readonly EncodingNLS _enc; private readonly EncoderNLS? _encoder; internal EncoderFallbackBuffer fallbackBuffer; internal EncoderFallbackBufferHelper fallbackBufferHelper; 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); } internal unsafe bool AddByte(byte b, int moreBytesExpected) { Debug.Assert(moreBytesExpected >= 0, "[EncodingByteBuffer.AddByte]expected non-negative moreBytesExpected"); if (_bytes != null) { if (_bytes >= _byteEnd - moreBytesExpected) { // Throw maybe. Check which buffer to back up (only matters if Converting) MovePrevious(true); // Throw if necessary return false; // No throw, but no store either } *(_bytes++) = b; } _byteCountResult++; return true; } internal bool AddByte(byte b1) { return (AddByte(b1, 0)); } internal bool AddByte(byte b1, byte b2) { return (AddByte(b1, b2, 0)); } internal bool AddByte(byte b1, byte b2, int moreBytesExpected) { return (AddByte(b1, 1 + moreBytesExpected) && AddByte(b2, moreBytesExpected)); } internal bool AddByte(byte b1, byte b2, byte b3) { return AddByte(b1, b2, b3, (int)0); } internal bool AddByte(byte b1, byte b2, byte b3, int moreBytesExpected) { return (AddByte(b1, 2 + moreBytesExpected) && AddByte(b2, 1 + moreBytesExpected) && AddByte(b3, moreBytesExpected)); } internal bool AddByte(byte b1, byte b2, byte b3, byte b4) { return (AddByte(b1, 3) && AddByte(b2, 2) && AddByte(b3, 1) && AddByte(b4, 0)); } internal unsafe void MovePrevious(bool bThrow) { if (fallbackBufferHelper.bFallingBack) fallbackBuffer.MovePrevious(); // don't use last fallback else { Debug.Assert(_chars > _charStart || (bThrow && (_bytes == _byteStart)), "[EncodingByteBuffer.MovePrevious]expected previous data or throw"); if (_chars > _charStart) _chars--; // don't use last char } if (bThrow) _enc.ThrowBytesOverflow(_encoder, _bytes == _byteStart); // Throw? (and reset fallback if not converting) } internal unsafe bool Fallback(char charFallback) { // Do the fallback return fallbackBufferHelper.InternalFallback(charFallback, ref _chars); } internal unsafe bool MoreData { get { // See if fallbackBuffer is not empty or if there's data left in chars buffer. return ((fallbackBuffer.Remaining > 0) || (_chars < _charEnd)); } } internal unsafe char GetNextChar() { // See if there's something in our fallback buffer char cReturn = fallbackBufferHelper.InternalGetNextChar(); // Nothing in the fallback buffer, return our normal data. if (cReturn == 0) { if (_chars < _charEnd) cReturn = *(_chars++); } return cReturn; } internal unsafe int CharsUsed { get { return (int)(_chars - _charStart); } } internal int Count { get { return _byteCountResult; } } } }