Skip to content

Commit e22273f

Browse files
authored
Merge pull request #14 from EgorBo/update-managed
[WIP] Update managed port
2 parents 874cd81 + 0db8226 commit e22273f

11 files changed

Lines changed: 1477 additions & 1137 deletions

File tree

samples/HelloWorld/Program.cs

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System;
2+
using System.IO;
23
using System.Text;
34
using SimdJsonSharp;
45

@@ -8,31 +9,37 @@ class Program
89
{
910
static unsafe void Main(string[] args)
1011
{
11-
1212
string helloWorldJson = @"{ ""answer"": 42, ""name"": ""Egor"" }";
1313
ReadOnlySpan<byte> bytes = Encoding.UTF8.GetBytes(helloWorldJson);
14-
// SimdJson is UTF8 only
1514

1615
fixed (byte* ptr = bytes)
1716
{
1817
// SimdJsonN -- N stands for Native, it means we are using Bindings for simdjson native lib
1918
// SimdJson -- fully managed .NET Core 3.0 port
20-
using (ParsedJsonN doc = SimdJsonN.ParseJson(ptr, bytes.Length))
19+
using (ParsedJson doc = SimdJson.ParseJson(ptr, (ulong)bytes.Length))
2120
{
22-
Console.WriteLine($"Is json valid:{doc.IsValid()}\n");
21+
if (!doc.IsValid)
22+
{
23+
Console.WriteLine("Error: " + doc.ErrorCode);
24+
return;
25+
}
2326

24-
// open iterator:
25-
using (var iterator = new ParsedJsonIteratorN(doc))
27+
Console.WriteLine("Json is valid!");
28+
29+
//open iterator:
30+
using (var iterator = new ParsedJsonIterator(doc))
2631
{
2732
while (iterator.MoveForward())
2833
{
29-
if (iterator.IsInteger())
34+
if (iterator.IsInteger)
3035
Console.WriteLine("integer: " + iterator.GetInteger());
31-
if (iterator.IsString())
36+
if (iterator.IsString)
3237
Console.WriteLine("string: " + iterator.GetUtf16String());
3338
}
3439
}
3540
}
41+
42+
Console.WriteLine("Done");
3643
}
3744
}
3845
}

src/FullyManagedImpl/ParsedJson.cs

Lines changed: 64 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -2,46 +2,44 @@
22
// (c) Daniel Lemire and Geoff Langdale
33

44
using System;
5-
using System.Diagnostics;
65
using System.Runtime.CompilerServices;
7-
using System.Runtime.InteropServices;
86
using System.Runtime.Intrinsics.X86;
97

108
#region stdint types and friends
11-
// if you change something here please change it in other files too
129
using size_t = System.UInt64;
1310
using uint8_t = System.Byte;
1411
using uint64_t = System.UInt64;
1512
using uint32_t = System.UInt32;
1613
using int64_t = System.Int64;
17-
using bytechar = System.SByte;
18-
using unsigned_bytechar = System.Byte;
19-
using uintptr_t = System.UIntPtr;
14+
using char1 = System.SByte;
2015
using static SimdJsonSharp.Utils;
2116
#endregion
2217

2318
namespace SimdJsonSharp
2419
{
2520
public unsafe class ParsedJson : IDisposable
2621
{
27-
public size_t bytecapacity; // indicates how many bits are meant to be supported
28-
public size_t depthcapacity; // how deep we can go
29-
public size_t tapecapacity;
30-
public size_t stringcapacity;
31-
public uint32_t current_loc;
32-
public uint32_t n_structural_indexes;
33-
public uint32_t* structural_indexes;
34-
public uint64_t* tape;
35-
public uint32_t* containing_scope_offset;
36-
public bytechar* ret_address;
37-
public uint8_t* string_buf; // should be at least bytecapacity
38-
public uint8_t* current_string_buf_loc;
39-
public bool isvalid;
22+
internal size_t bytecapacity; // indicates how many bits are meant to be supported
23+
internal size_t depthcapacity; // how deep we can go
24+
internal size_t tapecapacity;
25+
internal size_t stringcapacity;
26+
internal uint32_t current_loc;
27+
internal uint32_t n_structural_indexes;
28+
internal uint32_t* structural_indexes;
29+
internal uint64_t* tape;
30+
internal uint32_t* containing_scope_offset;
31+
internal char1* ret_address;
32+
internal uint8_t* string_buf; // should be at least bytecapacity
33+
internal uint8_t* current_string_buf_loc;
34+
internal bool isvalid;
35+
internal bool isDisposed;
36+
37+
public JsonParseError ErrorCode { get; internal set; }
4038

4139
public ParsedJson()
4240
{
43-
if (!Avx2.IsSupported)
44-
throw new NotSupportedException("AVX2 is required form SimdJson");
41+
if (!Sse42.IsSupported || IntPtr.Size == 4)
42+
throw new NotSupportedException("SimdJson requires AVX2 or SSE42 and x64");
4543
}
4644

4745
// if needed, allocate memory so that the object is able to process JSON
@@ -50,32 +48,48 @@ public bool AllocateCapacity(size_t len, size_t maxdepth = DEFAULTMAXDEPTH)
5048
{
5149
if ((maxdepth == 0) || (len == 0))
5250
{
53-
Debug.WriteLine("capacities must be non-zero ");
5451
return false;
5552
}
56-
53+
if (len > SIMDJSON_MAXSIZE_BYTES)
54+
{
55+
return false;
56+
}
5757
if ((len <= bytecapacity) && (depthcapacity < maxdepth))
58+
{
5859
return true;
60+
}
5961
Deallocate();
60-
6162
isvalid = false;
6263
bytecapacity = 0; // will only set it to len after allocations are a success
6364
n_structural_indexes = 0;
64-
uint32_t max_structures = (uint32_t) ROUNDUP_N(len, 64) + 2 + 7;
65-
structural_indexes = Utils.allocate<uint32_t>(max_structures);
66-
size_t localtapecapacity = ROUNDUP_N(len, 64);
67-
size_t localstringcapacity = ROUNDUP_N(len, 64);
68-
string_buf = Utils.allocate<uint8_t>(localstringcapacity);
69-
tape = Utils.allocate<uint64_t>(localtapecapacity);
70-
containing_scope_offset = Utils.allocate<uint32_t>(maxdepth);
71-
ret_address = Utils.allocate<bytechar>(maxdepth);
65+
uint32_t max_structures = (uint32_t)(ROUNDUP_N(len, 64) + 2 + 7);
66+
structural_indexes = allocate<uint32_t>(max_structures);
67+
// a pathological input like "[[[[..." would generate len tape elements, so need a capacity of len + 1
68+
size_t localtapecapacity = ROUNDUP_N(len + 1, 64);
69+
// a document with only zero-length strings... could have len/3 string
70+
// and we would need len/3 * 5 bytes on the string buffer
71+
size_t localstringcapacity = ROUNDUP_N(5 * len / 3 + 32, 64);
72+
string_buf = allocate <uint8_t>(localstringcapacity);
73+
tape = allocate <uint64_t>(localtapecapacity);
74+
containing_scope_offset = allocate <uint32_t>(maxdepth);
75+
ret_address = allocate<char1>(maxdepth);
7276
if ((string_buf == null) || (tape == null) ||
7377
(containing_scope_offset == null) || (ret_address == null) || (structural_indexes == null))
7478
{
75-
Deallocate();
79+
delete(ret_address);
80+
delete(containing_scope_offset);
81+
delete(tape);
82+
delete(string_buf);
83+
delete(structural_indexes);
7684
return false;
7785
}
78-
86+
/*
87+
// We do not need to initialize this content for parsing, though we could
88+
// need to initialize it for safety.
89+
memset(string_buf, 0 , localstringcapacity);
90+
memset(structural_indexes, 0, max_structures * sizeof(uint32_t));
91+
memset(tape, 0, localtapecapacity * sizeof(uint64_t));
92+
*/
7993
bytecapacity = len;
8094
depthcapacity = maxdepth;
8195
tapecapacity = localtapecapacity;
@@ -85,48 +99,35 @@ public bool AllocateCapacity(size_t len, size_t maxdepth = DEFAULTMAXDEPTH)
8599

86100
private void Deallocate()
87101
{
88-
isvalid = false;
89102
bytecapacity = 0;
90103
depthcapacity = 0;
91104
tapecapacity = 0;
92105
stringcapacity = 0;
106+
delete(ret_address);
107+
delete(containing_scope_offset);
108+
delete(tape);
109+
delete(string_buf);
110+
delete(structural_indexes);
111+
isvalid = false;
112+
}
93113

94-
if (ret_address != null)
95-
{
96-
delete(ret_address);
97-
ret_address = null;
98-
}
99-
100-
if (containing_scope_offset != null)
101-
{
102-
delete(containing_scope_offset);
103-
containing_scope_offset = null;
104-
}
114+
public void Dispose() => Dispose(true);
105115

106-
if (tape != null)
107-
{
108-
delete(tape);
109-
tape = null;
110-
}
111-
112-
if (string_buf != null)
113-
{
114-
delete(string_buf);
115-
string_buf = null;
116-
}
116+
private void Dispose(bool disposing)
117+
{
118+
if (disposing)
119+
GC.SuppressFinalize(this);
117120

118-
if (structural_indexes != null)
121+
if (!isDisposed)
119122
{
120-
delete(structural_indexes);
121-
structural_indexes = null;
123+
isDisposed = true;
124+
Deallocate();
122125
}
123126
}
124127

125-
public void Dispose() => Deallocate();
126-
127128
~ParsedJson()
128129
{
129-
Dispose();
130+
Dispose(false);
130131
}
131132

132133
public bool IsValid => isvalid;

0 commit comments

Comments
 (0)