Xamarin Public Jenkins (auto-signing) e79aa3c0ed Imported Upstream version 4.6.0.125
Former-commit-id: a2155e9bd80020e49e72e86c44da02a8ac0e57a4
2016-08-03 10:59:49 +00:00

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