public static DisposableSegment GetBytesUsingThreadStaticBuffer(this Encoding encoding, string value) { if (encoding == null) { throw new ArgumentNullException(nameof(encoding)); } if (value == null) { throw new ArgumentNullException(nameof(value)); } var length = value.Length; if (length == 0) { return(new DisposableSegment(null, __emptySegment)); } var maxSize = encoding.GetMaxByteCount(length); var rentedBuffer = ThreadStaticBuffer.RentBuffer(maxSize); var size = encoding.GetBytes(value, 0, length, rentedBuffer.Bytes, 0); var segment = new ArraySegment <byte>(rentedBuffer.Bytes, 0, size); return(new DisposableSegment(rentedBuffer, segment)); }
/// <inheritdoc/> public override void WriteCString(string value) { if (value == null) { throw new ArgumentNullException("value"); } ThrowIfDisposed(); var maxLength = CStringUtf8Encoding.GetMaxByteCount(value.Length) + 1; PrepareToWrite(maxLength); int actualLength; var segment = _buffer.AccessBackingBytes(_position); if (segment.Count >= maxLength) { actualLength = CStringUtf8Encoding.GetBytes(value, segment.Array, segment.Offset, Utf8Encodings.Strict); segment.Array[segment.Offset + actualLength] = 0; } else { // Compare to 128 to preserve original behavior const int maxLengthToUseCStringUtf8EncodingWith = 128; if (maxLength <= maxLengthToUseCStringUtf8EncodingWith) { using var rentedBuffer = ThreadStaticBuffer.RentBuffer(maxLengthToUseCStringUtf8EncodingWith); actualLength = CStringUtf8Encoding.GetBytes(value, rentedBuffer.Bytes, 0, Utf8Encodings.Strict); SetBytes(rentedBuffer.Bytes, actualLength); } else { using var rentedSegmentEncoded = Utf8Encodings.Strict.GetBytesUsingThreadStaticBuffer(value); var segmentEncoded = rentedSegmentEncoded.Segment; actualLength = segmentEncoded.Count; if (Array.IndexOf <byte>(segmentEncoded.Array, 0, 0, actualLength) != -1) { throw new ArgumentException("A CString cannot contain null bytes.", "value"); } SetBytes(segmentEncoded.Array, actualLength); } void SetBytes(byte[] bytes, int lenght) { _buffer.SetBytes(_position, bytes, 0, actualLength); _buffer.SetByte(_position + actualLength, 0); } } SetPositionAfterWrite(_position + actualLength + 1); }
/// <inheritdoc/> public override string ReadString(UTF8Encoding encoding) { if (encoding == null) { throw new ArgumentNullException("encoding"); } ThrowIfDisposed(); var length = ReadInt32(); if (length <= 0) { var message = string.Format("Invalid string length: {0}.", length); throw new FormatException(message); } var segment = _buffer.AccessBackingBytes(_position); if (segment.Count >= length) { ThrowIfEndOfStream(length); if (segment.Array[segment.Offset + length - 1] != 0) { throw new FormatException("String is missing terminating null byte."); } _position += length; return(Utf8Helper.DecodeUtf8String(segment.Array, segment.Offset, length - 1, encoding)); } else { using var rentedBuffer = ThreadStaticBuffer.RentBuffer(length); var bytes = rentedBuffer.Bytes; this.ReadBytes(bytes, 0, length); if (bytes[length - 1] != 0) { throw new FormatException("String is missing terminating null byte."); } return(Utf8Helper.DecodeUtf8String(bytes, 0, length - 1, encoding)); } }
/// <inheritdoc/> public override string ReadString(UTF8Encoding encoding) { if (encoding == null) { throw new ArgumentNullException("encoding"); } ThrowIfDisposed(); var length = ReadInt32(); using var rentedBuffer = ThreadStaticBuffer.RentBuffer(length); var bytes = rentedBuffer.Bytes; this.ReadBytes(bytes, 0, length); if (bytes[length - 1] != 0) { throw new FormatException("String is missing terminating null byte."); } return(encoding.GetString(bytes, 0, length - 1)); }
/// <inheritdoc/> public override void WriteCString(string value) { if (value == null) { throw new ArgumentNullException("value"); } ThrowIfDisposed(); // Compare to 128 to preserve original behavior const int maxLengthToUseCStringUtf8EncodingWith = 128; if (CStringUtf8Encoding.GetMaxByteCount(value.Length) <= maxLengthToUseCStringUtf8EncodingWith) { using var rentedBuffer = ThreadStaticBuffer.RentBuffer(maxLengthToUseCStringUtf8EncodingWith); var length = CStringUtf8Encoding.GetBytes(value, rentedBuffer.Bytes, 0, Utf8Encodings.Strict); WriteBytes(rentedBuffer.Bytes, length); } else { using var rentedSegment = Utf8Encodings.Strict.GetBytesUsingThreadStaticBuffer(value); var segment = rentedSegment.Segment; if (Array.IndexOf <byte>(segment.Array, 0, 0, segment.Count) != -1) { throw new ArgumentException("A CString cannot contain null bytes.", "value"); } WriteBytes(segment.Array, segment.Count); } void WriteBytes(byte[] bytes, int length) { _stream.Write(bytes, 0, length); _stream.WriteByte(0); } }