e79aa3c0ed
Former-commit-id: a2155e9bd80020e49e72e86c44da02a8ac0e57a4
147 lines
4.9 KiB
C#
147 lines
4.9 KiB
C#
//------------------------------------------------------------------------------
|
|
// <copyright file="LosWriter.cs" company="Microsoft">
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
// </copyright>
|
|
//------------------------------------------------------------------------------
|
|
|
|
#if !OBJECTSTATEFORMATTER
|
|
|
|
namespace System.Web.UI {
|
|
using System.Text;
|
|
using System.IO;
|
|
using System.Collections;
|
|
using System.Globalization;
|
|
using System.Web.Configuration;
|
|
|
|
internal class LosWriter : TextWriter{
|
|
|
|
private const int BUFFER_SIZE = 4096;
|
|
private const int MAX_FREE_BUFFERS = 16;
|
|
|
|
private static CharBufferAllocator _charBufferAllocator;
|
|
private static CharBufferAllocator _charBufferAllocatorBase64;
|
|
private static UbyteBufferAllocator _byteBufferAllocator;
|
|
|
|
|
|
private char[] _charBuffer;
|
|
private byte[] _byteBuffer;
|
|
private int _size;
|
|
private int _freePos;
|
|
private bool _recyclable;
|
|
|
|
static LosWriter() {
|
|
_charBufferAllocator = new CharBufferAllocator(BUFFER_SIZE, MAX_FREE_BUFFERS);
|
|
|
|
int byteBufferSize = Encoding.UTF8.GetMaxByteCount(BUFFER_SIZE);
|
|
_byteBufferAllocator = new UbyteBufferAllocator(byteBufferSize, MAX_FREE_BUFFERS);
|
|
|
|
// base64 increases data by up to 33%, so we err on the side of caution here
|
|
_charBufferAllocatorBase64 = new CharBufferAllocator((int) (byteBufferSize * 1.35), MAX_FREE_BUFFERS);
|
|
}
|
|
|
|
internal LosWriter() {
|
|
_charBuffer = (char[])_charBufferAllocator.GetBuffer();
|
|
_size = _charBuffer.Length;
|
|
_freePos = 0;
|
|
_recyclable = true;
|
|
}
|
|
|
|
internal void Dispose() {
|
|
if (_recyclable) {
|
|
if (_charBuffer != null)
|
|
_charBufferAllocator.ReuseBuffer(_charBuffer);
|
|
|
|
if (_byteBuffer != null)
|
|
_byteBufferAllocator.ReuseBuffer(_byteBuffer);
|
|
}
|
|
|
|
_byteBuffer = null;
|
|
_charBuffer = null;
|
|
}
|
|
|
|
public override Encoding Encoding {
|
|
get { return null; }
|
|
}
|
|
|
|
|
|
private void Grow(int newSize) {
|
|
if (newSize <= _size)
|
|
return;
|
|
|
|
if (newSize < _size*2)
|
|
newSize = _size*2;
|
|
|
|
char[] newBuffer = new char[newSize];
|
|
|
|
if (_freePos > 0)
|
|
Array.Copy(_charBuffer, newBuffer, _freePos);
|
|
|
|
_charBuffer = newBuffer;
|
|
_size = newSize;
|
|
_recyclable = false;
|
|
}
|
|
|
|
public override void Write(char ch) {
|
|
if (_freePos >= _size)
|
|
Grow(_freePos+1);
|
|
|
|
_charBuffer[_freePos++] = ch;
|
|
}
|
|
|
|
public override void Write(String s) {
|
|
int len = s.Length;
|
|
int newFreePos = _freePos + len;
|
|
|
|
if (newFreePos > _size)
|
|
Grow(newFreePos);
|
|
|
|
s.CopyTo(0, _charBuffer, _freePos, len);
|
|
_freePos = newFreePos;
|
|
}
|
|
|
|
|
|
internal /*public*/ void CompleteTransforms(TextWriter output, bool enableMac, byte[] macKey) {
|
|
int len = 0;
|
|
|
|
// convert to bytes
|
|
if (_recyclable) {
|
|
// still using the original recyclable char buffer
|
|
// -- can use recyclable byte buffer
|
|
_byteBuffer = (byte[])_byteBufferAllocator.GetBuffer();
|
|
|
|
if (_freePos > 0)
|
|
len = Encoding.UTF8.GetBytes(_charBuffer, 0, _freePos, _byteBuffer, 0);
|
|
|
|
// do the mac encoding if requested
|
|
if (enableMac) {
|
|
// the size of the output array depends on the key length and encryption type
|
|
// so we can't use the recyclable buffers after this
|
|
byte[] data = MachineKeySection.GetEncodedData(_byteBuffer, macKey, 0, ref len);
|
|
string serialized = Convert.ToBase64String(data, 0, len);
|
|
output.Write(serialized);
|
|
}
|
|
else {
|
|
char[] base64chars = (char[]) _charBufferAllocatorBase64.GetBuffer();
|
|
len = Convert.ToBase64CharArray(_byteBuffer, 0, len, base64chars, 0);
|
|
output.Write(base64chars, 0, len);
|
|
_charBufferAllocatorBase64.ReuseBuffer(base64chars);
|
|
}
|
|
}
|
|
else {
|
|
_byteBuffer = Encoding.UTF8.GetBytes(_charBuffer, 0, _freePos);
|
|
|
|
|
|
len = _byteBuffer.Length;
|
|
if (enableMac)
|
|
_byteBuffer = MachineKeySection.GetEncodedData(_byteBuffer, macKey, 0, ref len);
|
|
|
|
string serialized = Convert.ToBase64String(_byteBuffer);
|
|
output.Write(serialized);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
#endif // !OBJECTSTATEFORMATTER
|
|
|