MemoryTemplate<T>
Represents generic template for buffer rendering.
using System;
using System.Buffers;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
namespace DotNext.Buffers
{
[StructLayout(LayoutKind.Auto)]
public readonly struct MemoryTemplate<T> where T : IEquatable<T>
{
private sealed class Placeholder
{
internal readonly int Offset;
[System.Runtime.CompilerServices.Nullable(new byte[] {
2,
0
})]
internal Placeholder Next;
internal Placeholder(int offset)
{
Offset = offset;
}
}
[System.Runtime.CompilerServices.Nullable(new byte[] {
0,
1
})]
private readonly ReadOnlyMemory<T> template;
[System.Runtime.CompilerServices.Nullable(new byte[] {
2,
0
})]
private readonly Placeholder firstOccurence;
private readonly int placeholderLength;
[System.Runtime.CompilerServices.Nullable(new byte[] {
0,
1
})]
public ReadOnlyMemory<T> Value {
[return: System.Runtime.CompilerServices.Nullable(new byte[] {
0,
1
})]
get {
return template;
}
}
public MemoryTemplate([System.Runtime.CompilerServices.Nullable(new byte[] {
0,
1
})] ReadOnlyMemory<T> template, [System.Runtime.CompilerServices.Nullable(new byte[] {
0,
1
})] ReadOnlySpan<T> placeholder)
{
this.template = template;
if (placeholder.IsEmpty || placeholder.Length > template.Length) {
placeholderLength = 0;
firstOccurence = null;
} else {
placeholderLength = placeholder.Length;
firstOccurence = BuildPlaceholdersChain(template.Span, placeholder);
}
}
[return: System.Runtime.CompilerServices.Nullable(new byte[] {
2,
0
})]
private static Placeholder BuildPlaceholdersChain([System.Runtime.CompilerServices.Nullable(new byte[] {
0,
1
})] ReadOnlySpan<T> source, [System.Runtime.CompilerServices.Nullable(new byte[] {
0,
1
})] ReadOnlySpan<T> placeholder)
{
Placeholder head = null;
Placeholder tail = null;
int num = 0;
while (num < source.Length - placeholder.Length + 1) {
if (MemoryExtensions.SequenceEqual<T>(source.Slice(num, placeholder.Length), placeholder)) {
CreateNode(ref head, ref tail, num);
num += placeholder.Length;
} else
num++;
}
return head;
}
private static void CreateNode([System.Runtime.CompilerServices.Nullable(new byte[] {
2,
0
})] ref Placeholder head, [System.Runtime.CompilerServices.Nullable(new byte[] {
2,
0
})] ref Placeholder tail, int offset)
{
if (head == null || tail == null)
head = (tail = new Placeholder(offset));
else {
Placeholder placeholder = tail;
tail = (placeholder.Next = new Placeholder(offset));
}
}
[System.Runtime.CompilerServices.NullableContext(1)]
public void Render<TWriter>(TWriter output, Action<int, TWriter> rewriter) where TWriter : class, IBufferWriter<T>
{
Render(output, rewriter, Span.CopyTo<T>);
}
[System.Runtime.CompilerServices.NullableContext(1)]
public void Render<[System.Runtime.CompilerServices.Nullable(2)] TArg>(TArg arg, Action<int, TArg> rewriter, ReadOnlySpanAction<T, TArg> output)
{
ReadOnlySpan<T> span = this.template.Span;
Placeholder placeholder = this.firstOccurence;
int offset = 0;
int num = 0;
int num2 = 0;
bool isPlaceholder;
while (this.MoveNext(ref offset, ref placeholder, out isPlaceholder)) {
if (isPlaceholder)
rewriter(num2++, arg);
else
output(span.Slice(num, offset - num), arg);
num = offset;
}
}
private bool MoveNext(ref int offset, [System.Runtime.CompilerServices.Nullable(new byte[] {
2,
0
})] ref Placeholder placeholder, out bool isPlaceholder)
{
if (offset >= template.Length) {
isPlaceholder = false;
return false;
}
if (placeholder == null) {
isPlaceholder = false;
offset = template.Length;
} else if (placeholder.Offset == offset) {
isPlaceholder = true;
offset += placeholderLength;
placeholder = placeholder.Next;
} else {
offset = placeholder.Offset;
isPlaceholder = false;
}
return true;
}
}
}