Skip to content

Commit 1e7d0a8

Browse files
authored
move buffers snippets to samples repo (#1642)
* add buffers snippets * review comments * remove symbol cache * add ionide folder to .gitignore * improve sentence
1 parent bd03885 commit 1e7d0a8

File tree

3 files changed

+316
-0
lines changed

3 files changed

+316
-0
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,3 +204,6 @@ _dependentPackages/
204204

205205
# Visual Studio Code
206206
.vscode/
207+
208+
# Ionide
209+
.ionide/
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<OutputType>Exe</OutputType>
5+
<TargetFramework>netcoreapp3.0</TargetFramework>
6+
</PropertyGroup>
7+
8+
</Project>

snippets/csharp/buffers/MyClass.cs

Lines changed: 305 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,305 @@
1+
using System;
2+
using System.Buffers;
3+
using System.Buffers.Binary;
4+
using System.Text;
5+
6+
namespace MyBuffers
7+
{
8+
class MyClass
9+
{
10+
#region snippet
11+
void WriteHello(IBufferWriter<byte> writer)
12+
{
13+
// Request at least 5 bytes.
14+
Span<byte> span = writer.GetSpan(5);
15+
ReadOnlySpan<char> helloSpan = "Hello".AsSpan();
16+
int written = Encoding.ASCII.GetBytes(helloSpan, span);
17+
18+
// Tell the writer how many bytes were written.
19+
writer.Advance(written);
20+
}
21+
#endregion
22+
23+
#region snippet3
24+
long FindIndexOf(in ReadOnlySequence<byte> buffer, byte data)
25+
{
26+
long position = 0;
27+
28+
foreach (ReadOnlyMemory<byte> segment in buffer)
29+
{
30+
ReadOnlySpan<byte> span = segment.Span;
31+
var index = span.IndexOf(data);
32+
if (index != -1)
33+
{
34+
return position + index;
35+
}
36+
37+
position += span.Length;
38+
}
39+
40+
return -1;
41+
}
42+
#endregion
43+
44+
#region snippet5
45+
bool TryParseHeaderLength(ref ReadOnlySequence<byte> buffer, out int length)
46+
{
47+
// If there's not enough space, the length can't be obtained.
48+
if (buffer.Length < 4)
49+
{
50+
length = 0;
51+
return false;
52+
}
53+
54+
// Grab the first 4 bytes of the buffer.
55+
var lengthSlice = buffer.Slice(buffer.Start, 4);
56+
if (lengthSlice.IsSingleSegment)
57+
{
58+
// Fast path since it's a single segment.
59+
length = BinaryPrimitives.ReadInt32BigEndian(lengthSlice.First.Span);
60+
}
61+
else
62+
{
63+
// There are 4 bytes split across multiple segments. Since it's so small, it
64+
// can be copied to a stack allocated buffer. This avoids a heap allocation.
65+
Span<byte> stackBuffer = stackalloc byte[4];
66+
lengthSlice.CopyTo(stackBuffer);
67+
length = BinaryPrimitives.ReadInt32BigEndian(stackBuffer);
68+
}
69+
70+
// Move the buffer 4 bytes ahead.
71+
buffer = buffer.Slice(lengthSlice.End);
72+
73+
return true;
74+
}
75+
#endregion
76+
77+
#region snippet6
78+
static bool TryParseLine(ref ReadOnlySequence<byte> buffer, out ReadOnlySequence<byte> line)
79+
{
80+
SequencePosition position = buffer.Start;
81+
SequencePosition previous = position;
82+
var index = -1;
83+
line = default;
84+
85+
while (buffer.TryGet(ref position, out ReadOnlyMemory<byte> segment))
86+
{
87+
ReadOnlySpan<byte> span = segment.Span;
88+
89+
// Look for \r in the current segment.
90+
index = span.IndexOf((byte)'\r');
91+
92+
if (index != -1)
93+
{
94+
// Check next segment for \n.
95+
if (index + 1 >= span.Length)
96+
{
97+
var next = position;
98+
if (!buffer.TryGet(ref next, out ReadOnlyMemory<byte> nextSegment))
99+
{
100+
// You're at the end of the sequence.
101+
return false;
102+
}
103+
else if (nextSegment.Span[0] == (byte)'\n')
104+
{
105+
// A match was found.
106+
break;
107+
}
108+
}
109+
// Check the current segment of \n.
110+
else if (span[index + 1] == (byte)'\n')
111+
{
112+
// It was found.
113+
break;
114+
}
115+
}
116+
117+
previous = position;
118+
}
119+
120+
if (index != -1)
121+
{
122+
// Get the position just before the \r\n.
123+
var delimeter = buffer.GetPosition(index, previous);
124+
125+
// Slice the line (excluding \r\n).
126+
line = buffer.Slice(buffer.Start, delimeter);
127+
128+
// Slice the buffer to get the remaining data after the line.
129+
buffer = buffer.Slice(buffer.GetPosition(2, delimeter));
130+
return true;
131+
}
132+
133+
return false;
134+
}
135+
#endregion
136+
137+
#region snippet7
138+
static void EmptySegments()
139+
{
140+
// This logic creates a ReadOnlySequence<byte> with 4 segments,
141+
// two of which are empty.
142+
var first = new BufferSegment(new byte[0]);
143+
var last = first.Append(new byte[] { 97 })
144+
.Append(new byte[0]).Append(new byte[] { 98 });
145+
146+
// Construct the ReadOnlySequence<byte> from the linked list segments.
147+
var data = new ReadOnlySequence<byte>(first, 0, last, 1);
148+
149+
// Slice using numbers.
150+
var sequence1 = data.Slice(0, 2);
151+
152+
// Slice using SequencePosition pointing at the empty segment.
153+
var sequence2 = data.Slice(data.Start, 2);
154+
155+
Console.WriteLine($"sequence1.Length={sequence1.Length}"); // sequence1.Length=2
156+
Console.WriteLine($"sequence2.Length={sequence2.Length}"); // sequence2.Length=2
157+
158+
// sequence1.FirstSpan.Length=1
159+
Console.WriteLine($"sequence1.FirstSpan.Length={sequence1.FirstSpan.Length}");
160+
161+
// Slicing using SequencePosition will Slice the ReadOnlySequence<byte> directly
162+
// on the empty segment!
163+
// sequence2.FirstSpan.Length=0
164+
Console.WriteLine($"sequence2.FirstSpan.Length={sequence2.FirstSpan.Length}");
165+
166+
// The following code prints 0, 1, 0, 1.
167+
SequencePosition position = data.Start;
168+
while (data.TryGet(ref position, out ReadOnlyMemory<byte> memory))
169+
{
170+
Console.WriteLine(memory.Length);
171+
}
172+
}
173+
174+
class BufferSegment : ReadOnlySequenceSegment<byte>
175+
{
176+
public BufferSegment(Memory<byte> memory)
177+
{
178+
Memory = memory;
179+
}
180+
181+
public BufferSegment Append(Memory<byte> memory)
182+
{
183+
var segment = new BufferSegment(memory)
184+
{
185+
RunningIndex = RunningIndex + Memory.Length
186+
};
187+
Next = segment;
188+
return segment;
189+
}
190+
}
191+
#endregion
192+
193+
#if DAVID_FIX_CODE
194+
public void Reader1()
195+
{
196+
#region snippet8
197+
while (!reader.End)
198+
{
199+
var b = reader.CurrentSpan[reader.CurrentSpanIndex];
200+
Process(b);
201+
reader.Advance(1);
202+
}
203+
#endregion
204+
}
205+
#endif
206+
207+
private void Process(object b)
208+
{
209+
throw new NotImplementedException();
210+
}
211+
212+
}
213+
214+
class MyClass2
215+
{
216+
#region snippet2
217+
void WriteHello(IBufferWriter<byte> writer)
218+
{
219+
byte[] helloBytes = Encoding.ASCII.GetBytes("Hello");
220+
221+
// Write helloBytes to the writer. There's no need to call Advance here
222+
// since Write calls Advance.
223+
writer.Write(helloBytes);
224+
}
225+
#endregion
226+
227+
#if DAVID_FIX_CODE
228+
#region snippet4
229+
SequencePosition? FindIndexOf(in ReadOnlySequence<byte> buffer, byte data)
230+
{
231+
SequencePosition position = buffer.Start;
232+
233+
while (buffer.TryGet(ref position, out ReadOnlyMemory<byte> segment))
234+
{
235+
ReadOnlySpan<byte> span = segment.Span;
236+
var index = span.IndexOf(data);
237+
if (index != -1)
238+
{
239+
return buffer.GetPosition(position, index);
240+
}
241+
}
242+
return null;
243+
}
244+
#endregion
245+
#endif
246+
247+
#region snippet9
248+
SequencePosition? FindIndexOf(in ReadOnlySequence<byte> buffer, byte data)
249+
{
250+
var reader = new SequenceReader<byte>(buffer);
251+
252+
while (!reader.End)
253+
{
254+
// Search for the byte in the current span.
255+
var index = reader.CurrentSpan.IndexOf(data);
256+
if (index != -1)
257+
{
258+
// It was found, so advance to the position.
259+
reader.Advance(index);
260+
261+
// Return the position.
262+
return reader.Position;
263+
}
264+
// Skip the current segment since there's nothing in it.
265+
reader.Advance(reader.CurrentSpan.Length);
266+
}
267+
268+
return null;
269+
}
270+
#endregion
271+
272+
#region snippet11
273+
bool TryParseHeaderLength(ref ReadOnlySequence<byte> buffer, out int length)
274+
{
275+
var reader = new SequenceReader<byte>(buffer);
276+
return reader.TryReadBigEndian(out length);
277+
}
278+
#endregion
279+
280+
}
281+
282+
public static class MyClass3
283+
{
284+
#region snippet10
285+
static ReadOnlySpan<byte> NewLine => new byte[] { (byte)'\r', (byte)'\n' };
286+
287+
static bool TryParseLine(ref ReadOnlySequence<byte> buffer,
288+
out ReadOnlySequence<byte> line)
289+
{
290+
var reader = new SequenceReader<byte>(buffer);
291+
292+
if (reader.TryReadTo(out line, NewLine))
293+
{
294+
buffer = buffer.Slice(reader.Position);
295+
296+
return true;
297+
}
298+
299+
line = default;
300+
return false;
301+
}
302+
#endregion
303+
304+
}
305+
}

0 commit comments

Comments
 (0)