Skip to content

Instantly share code, notes, and snippets.

@danipen
Created March 15, 2023 20:32
Show Gist options
  • Save danipen/978156adae5fd17611a3ebbbba433277 to your computer and use it in GitHub Desktop.
Save danipen/978156adae5fd17611a3ebbbba433277 to your computer and use it in GitHub Desktop.
using System;
using System.IO;
using System.Text.Json;
namespace TextMateSharp.Internal.Parser.Json
{
public class JSONPListParser<T>
{
private bool theme;
public JSONPListParser(bool theme)
{
this.theme = theme;
}
public T Parse(StreamReader contents)
{
PList<T> pList = new PList<T>(theme);
var buffer = new byte[4096];
contents.BaseStream.Read(buffer);
JsonReaderOptions options = new JsonReaderOptions()
{
AllowTrailingCommas = true,
CommentHandling = JsonCommentHandling.Skip
};
// We set isFinalBlock to false since we expect more data in a subsequent read from the stream.
var reader = new Utf8JsonReader(buffer, isFinalBlock: false, state: new JsonReaderState(options));
while (true)
{
if (!reader.Read())
{
// Not enough of the JSON is in the buffer to complete a read.
if (GetMoreBytesFromStream(contents.BaseStream, buffer, ref reader) == 0)
break;
}
var nextToken = reader.TokenType;
switch (nextToken)
{
case JsonTokenType.StartArray:
pList.StartElement("array");
break;
case JsonTokenType.EndArray:
pList.EndElement("array");
break;
case JsonTokenType.StartObject:
pList.StartElement("dict");
break;
case JsonTokenType.EndObject:
pList.EndElement("dict");
break;
case JsonTokenType.PropertyName:
pList.StartElement("key");
pList.AddString(reader.GetString());
pList.EndElement("key");
break;
case JsonTokenType.String:
pList.StartElement("string");
pList.AddString(reader.GetString());
pList.EndElement("string");
break;
}
}
return pList.GetResult();
}
static int GetMoreBytesFromStream(Stream stream, byte[] buffer, ref Utf8JsonReader reader)
{
int bytesRead;
if (reader.BytesConsumed < buffer.Length)
{
ReadOnlySpan<byte> leftover = buffer.AsSpan((int)reader.BytesConsumed);
if (leftover.Length == buffer.Length)
{
Array.Resize(ref buffer, buffer.Length * 2);
}
leftover.CopyTo(buffer);
bytesRead = stream.Read(buffer.AsSpan(leftover.Length));
}
else
{
bytesRead = stream.Read(buffer);
}
reader = new Utf8JsonReader(buffer, isFinalBlock: bytesRead == 0, reader.CurrentState);
return bytesRead;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment