Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/dotnet/aspnetcore.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'src/Mvc/src/Microsoft.AspNetCore.Mvc.ViewFeatures/Internal/PagedCharBuffer.cs')
-rw-r--r--src/Mvc/src/Microsoft.AspNetCore.Mvc.ViewFeatures/Internal/PagedCharBuffer.cs159
1 files changed, 159 insertions, 0 deletions
diff --git a/src/Mvc/src/Microsoft.AspNetCore.Mvc.ViewFeatures/Internal/PagedCharBuffer.cs b/src/Mvc/src/Microsoft.AspNetCore.Mvc.ViewFeatures/Internal/PagedCharBuffer.cs
new file mode 100644
index 0000000000..f086daf67b
--- /dev/null
+++ b/src/Mvc/src/Microsoft.AspNetCore.Mvc.ViewFeatures/Internal/PagedCharBuffer.cs
@@ -0,0 +1,159 @@
+// Copyright (c) .NET Foundation. All rights reserved.
+// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+
+namespace Microsoft.AspNetCore.Mvc.ViewFeatures.Internal
+{
+ public class PagedCharBuffer : IDisposable
+ {
+ public const int PageSize = 1024;
+ private int _charIndex;
+
+ public PagedCharBuffer(ICharBufferSource bufferSource)
+ {
+ BufferSource = bufferSource;
+ }
+
+ public ICharBufferSource BufferSource { get; }
+
+ public IList<char[]> Pages { get; } = new List<char[]>();
+
+ public int Length
+ {
+ get
+ {
+ var length = _charIndex;
+ for (var i = 0; i < Pages.Count - 1; i++)
+ {
+ length += Pages[i].Length;
+ }
+
+ return length;
+ }
+ }
+
+ private char[] CurrentPage { get; set; }
+
+ public void Append(char value)
+ {
+ var page = GetCurrentPage();
+ page[_charIndex++] = value;
+ }
+
+ public void Append(string value)
+ {
+ if (value == null)
+ {
+ return;
+ }
+
+ var index = 0;
+ var count = value.Length;
+
+ while (count > 0)
+ {
+ var page = GetCurrentPage();
+ var copyLength = Math.Min(count, page.Length - _charIndex);
+ Debug.Assert(copyLength > 0);
+
+ value.CopyTo(
+ index,
+ page,
+ _charIndex,
+ copyLength);
+
+ _charIndex += copyLength;
+ index += copyLength;
+
+ count -= copyLength;
+ }
+ }
+
+ public void Append(char[] buffer, int index, int count)
+ {
+ while (count > 0)
+ {
+ var page = GetCurrentPage();
+ var copyLength = Math.Min(count, page.Length - _charIndex);
+ Debug.Assert(copyLength > 0);
+
+ Array.Copy(
+ buffer,
+ index,
+ page,
+ _charIndex,
+ copyLength);
+
+ _charIndex += copyLength;
+ index += copyLength;
+ count -= copyLength;
+ }
+ }
+
+ /// <summary>
+ /// Return all but one of the pages to the <see cref="ICharBufferSource"/>.
+ /// This way if someone writes a large chunk of content, we can return those buffers and avoid holding them
+ /// for extended durations.
+ /// </summary>
+ public void Clear()
+ {
+ for (var i = Pages.Count - 1; i > 0; i--)
+ {
+ var page = Pages[i];
+
+ try
+ {
+ Pages.RemoveAt(i);
+ }
+ finally
+ {
+ BufferSource.Return(page);
+ }
+ }
+
+ _charIndex = 0;
+ CurrentPage = Pages.Count > 0 ? Pages[0] : null;
+ }
+
+ private char[] GetCurrentPage()
+ {
+ if (CurrentPage == null || _charIndex == CurrentPage.Length)
+ {
+ CurrentPage = NewPage();
+ _charIndex = 0;
+ }
+
+ return CurrentPage;
+ }
+
+ private char[] NewPage()
+ {
+ char[] page = null;
+ try
+ {
+ page = BufferSource.Rent(PageSize);
+ Pages.Add(page);
+ }
+ catch when (page != null)
+ {
+ BufferSource.Return(page);
+ throw;
+ }
+
+ return page;
+ }
+
+ public void Dispose()
+ {
+ for (var i = 0; i < Pages.Count; i++)
+ {
+ BufferSource.Return(Pages[i]);
+ }
+
+ Pages.Clear();
+ }
+ }
+}