ln.json/JSONParser.cs

279 lines
8.7 KiB
C#
Raw Normal View History

2019-08-07 23:02:00 +02:00
// /**
// * File: JSONParser.cs
// * Author: haraldwolff
// *
// * This file and it's content is copyrighted by the Author and / or copyright holder.
// * Any use wihtout proper permission is illegal and may lead to legal actions.
// *
// *
// **/
using System;
2020-11-18 00:36:18 +01:00
using ln.type;
2019-08-07 23:02:00 +02:00
using System.Text;
using System.Globalization;
2020-11-18 00:36:18 +01:00
using System.IO;
2019-08-07 23:02:00 +02:00
namespace ln.json
2017-11-03 13:13:09 +01:00
{
2019-08-07 23:02:00 +02:00
public class JSONParser
{
static char[] chNull = new char[] { 'n', 'u', 'l', 'l' };
static char[] chTrue = new char[] { 't', 'r', 'u', 'e' };
static char[] chFalse = new char[] { 'f', 'a', 'l', 's', 'e' };
public static JSONValue Parse(String jsonSource)
{
2020-11-18 00:36:18 +01:00
return ParseValue(new StringReader(jsonSource));
}
public static JSONValue Parse(TextReader reader) => ParseValue(reader);
public static JSONValue ParseFile(string filename)
{
using (StreamReader streamReader = new StreamReader(filename))
return ParseValue(streamReader);
2019-08-07 23:02:00 +02:00
}
2020-11-18 00:36:18 +01:00
static void SkipWhitespace(TextReader reader)
{
while (char.IsWhiteSpace((char) reader.Peek()) && (reader.Peek()!=-1))
reader.Read();
}
2019-08-07 23:02:00 +02:00
2020-11-18 00:36:18 +01:00
static void Read(TextReader reader, StringBuilder stringBuilder, Func<char, bool> condition)
{
int ch;
while (condition((char) (ch = reader.Peek())) && (ch!=-1))
stringBuilder.Append((char)reader.Read());
}
static JSONValue ParseValue(TextReader reader)
2019-08-07 23:02:00 +02:00
{
2020-11-18 00:36:18 +01:00
SkipWhitespace(reader);
switch (reader.Peek())
2019-08-07 23:02:00 +02:00
{
case '"':
2020-11-18 00:36:18 +01:00
return parseString(reader);
2019-08-07 23:02:00 +02:00
case 't':
2020-11-18 00:36:18 +01:00
return parseTrue(reader);
2019-08-07 23:02:00 +02:00
case 'f':
2020-11-18 00:36:18 +01:00
return parseFalse(reader);
2019-08-07 23:02:00 +02:00
case 'n':
2020-11-18 00:36:18 +01:00
return parseNull(reader);
2019-08-07 23:02:00 +02:00
case '[':
2020-11-18 00:36:18 +01:00
return parseArray(reader);
2019-08-07 23:02:00 +02:00
case '{':
2020-11-18 00:36:18 +01:00
return parseObject(reader);
2019-08-07 23:02:00 +02:00
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
case '-':
2020-11-18 00:36:18 +01:00
return parseNumber(reader);
2019-08-07 23:02:00 +02:00
default:
2020-11-18 00:36:18 +01:00
throw new FormatException(String.Format("Unexpected character: {0} [ 0x{0:x4} ]", reader.Peek()));
2019-08-07 23:02:00 +02:00
}
}
2020-11-18 00:36:18 +01:00
static JSONString parseString(TextReader reader)
2019-08-07 23:02:00 +02:00
{
2020-11-18 00:36:18 +01:00
if (reader.Peek() != '"')
2019-08-07 23:02:00 +02:00
throw new FormatException("Unexpected character");
StringBuilder stringBuilder = new StringBuilder();
2020-11-18 00:36:18 +01:00
reader.Read();
int ch;
while ((ch = reader.Read()) != '"')
2019-08-07 23:02:00 +02:00
{
2020-11-18 00:36:18 +01:00
if (ch == -1)
throw new EndOfStreamException();
stringBuilder.Append((char) ch);
if (ch == '\\')
stringBuilder.Append((char) reader.Read());
// if (ch == '\\')
// {
// ch = reader.Read();
// if (ch == -1)
// throw new EndOfStreamException();
// switch (ch)
// {
// case '\\':
// stringBuilder.Append('\\');
// break;
// case '/':
// stringBuilder.Append('/');
// break;
// case 'b':
// stringBuilder.Append('\b');
// break;
// case 'f':
// stringBuilder.Append('\f');
// break;
// case 'n':
// stringBuilder.Append('\n');
// break;
// case 'r':
// stringBuilder.Append('\r');
// break;
// case 't':
// stringBuilder.Append('\t');
// break;
// case '"':
// stringBuilder.Append('"');
// break;
// case 'u':
// char[] hexDigits = new char[4];
// reader.ReadBlock(hexDigits, 0, 4);
// ch = int.Parse(hexDigits, System.Globalization.NumberStyles.HexNumber);
// stringBuilder.Append((char) ch);
// break;
// default:
// throw new FormatException();
// }
// }
// else
// stringBuilder.Append((char) ch);
2019-08-07 23:02:00 +02:00
}
2020-11-18 00:36:18 +01:00
SkipWhitespace(reader);
2019-08-07 23:02:00 +02:00
return new JSONString(JSONString.Unescape(stringBuilder.ToString()));
}
2020-11-18 00:36:18 +01:00
static JSONNumber parseNumber(TextReader reader)
2019-08-07 23:02:00 +02:00
{
StringBuilder sb = new StringBuilder();
2020-11-18 00:36:18 +01:00
if (reader.Peek() == '-')
2019-08-07 23:02:00 +02:00
{
2020-11-18 00:36:18 +01:00
sb.Append((char)reader.Read());
2019-08-07 23:02:00 +02:00
}
2020-11-18 00:36:18 +01:00
Read(reader,sb,char.IsDigit);
if (reader.Peek() == '.')
2019-08-07 23:02:00 +02:00
{
sb.Append('.');
2020-11-18 00:36:18 +01:00
reader.Read();
Read(reader,sb,char.IsDigit);
2019-08-07 23:02:00 +02:00
}
2020-11-18 00:36:18 +01:00
if ((reader.Peek() == 'e') || (reader.Peek() == 'E'))
2019-08-07 23:02:00 +02:00
{
sb.Append('e');
2020-11-18 00:36:18 +01:00
if ((reader.Peek() == '-')|| (reader.Peek() == '+'))
2019-08-07 23:02:00 +02:00
{
2020-11-18 00:36:18 +01:00
sb.Append((char)reader.Read());
2019-08-07 23:02:00 +02:00
}
2020-11-18 00:36:18 +01:00
Read(reader, sb, char.IsDigit);
2019-08-07 23:02:00 +02:00
}
2020-11-18 00:36:18 +01:00
SkipWhitespace(reader);
2019-08-07 23:02:00 +02:00
return new JSONNumber(decimal.Parse(sb.ToString(),CultureInfo.InvariantCulture));
}
2020-11-18 00:36:18 +01:00
static JSONArray parseArray(TextReader reader)
2019-08-07 23:02:00 +02:00
{
2020-11-18 00:36:18 +01:00
if (reader.Peek() != '[')
2019-08-07 23:02:00 +02:00
throw new FormatException("Unexpected character");
JSONArray array = new JSONArray();
2020-11-18 00:36:18 +01:00
reader.Read();
while (reader.Peek() != ']')
2019-08-07 23:02:00 +02:00
{
2020-11-18 00:36:18 +01:00
array.Add(ParseValue(reader));
if (reader.Peek() == ',')
2019-08-07 23:02:00 +02:00
{
2020-11-18 00:36:18 +01:00
reader.Read();
SkipWhitespace(reader);
2019-08-07 23:02:00 +02:00
}
}
2020-11-18 00:36:18 +01:00
reader.Read();
SkipWhitespace(reader);
2019-08-07 23:02:00 +02:00
return array;
}
2020-11-18 00:36:18 +01:00
static JSONObject parseObject(TextReader reader)
2019-08-07 23:02:00 +02:00
{
2020-11-18 00:36:18 +01:00
if (reader.Peek() != '{')
2019-08-07 23:02:00 +02:00
throw new FormatException("Unexpected character");
JSONObject o = new JSONObject();
2020-11-18 00:36:18 +01:00
reader.Read();
SkipWhitespace(reader);
2019-08-07 23:02:00 +02:00
2020-11-18 00:36:18 +01:00
while (reader.Peek() != '}')
2019-08-07 23:02:00 +02:00
{
2020-11-18 00:36:18 +01:00
JSONString s = parseString(reader);
if (reader.Peek() != ':')
2019-08-07 23:02:00 +02:00
throw new FormatException("expected :");
2020-11-18 00:36:18 +01:00
reader.Read();
o.Add(s.Value, ParseValue(reader));
2019-08-07 23:02:00 +02:00
2020-11-18 00:36:18 +01:00
if (reader.Peek() == ',')
2019-08-07 23:02:00 +02:00
{
2020-11-18 00:36:18 +01:00
reader.Read();
SkipWhitespace(reader);
2019-08-07 23:02:00 +02:00
}
}
2020-11-18 00:36:18 +01:00
reader.Read();
SkipWhitespace(reader);
2019-08-07 23:02:00 +02:00
return o;
}
2020-11-18 00:36:18 +01:00
static JSONTrue parseTrue(TextReader reader)
2019-08-07 23:02:00 +02:00
{
char[] ch = new char[4];
for (int n = 0; n < ch.Length; n++)
{
2020-11-18 00:36:18 +01:00
ch[n] = (char)reader.Read();
2019-08-07 23:02:00 +02:00
}
if (ch.AreEqual(chTrue))
{
2020-11-18 00:36:18 +01:00
SkipWhitespace(reader);
2019-08-07 23:02:00 +02:00
return JSONTrue.Instance;
}
2020-11-18 00:36:18 +01:00
2019-08-07 23:02:00 +02:00
throw new FormatException();
}
2020-11-18 00:36:18 +01:00
static JSONFalse parseFalse(TextReader reader)
2019-08-07 23:02:00 +02:00
{
char[] ch = new char[5];
for (int n = 0; n < ch.Length; n++)
{
2020-11-18 00:36:18 +01:00
ch[n] = (char)reader.Read();
2019-08-07 23:02:00 +02:00
}
if (ch.AreEqual(chFalse))
{
2020-11-18 00:36:18 +01:00
SkipWhitespace(reader);
2019-08-07 23:02:00 +02:00
return JSONFalse.Instance;
}
throw new FormatException();
}
2020-11-18 00:36:18 +01:00
static JSONNull parseNull(TextReader reader)
2019-08-07 23:02:00 +02:00
{
char[] ch = new char[4];
for (int n=0;n<ch.Length;n++)
{
2020-11-18 00:36:18 +01:00
ch[n] = (char)reader.Read();
2019-08-07 23:02:00 +02:00
}
if (ch.AreEqual(chNull))
{
2020-11-18 00:36:18 +01:00
SkipWhitespace(reader);
2019-08-07 23:02:00 +02:00
return JSONNull.Instance;
}
throw new FormatException();
}
}
2017-11-03 13:13:09 +01:00
}