279 lines
8.7 KiB
C#
279 lines
8.7 KiB
C#
// /**
|
|
// * 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;
|
|
using ln.type;
|
|
using System.Text;
|
|
using System.Globalization;
|
|
using System.IO;
|
|
|
|
namespace ln.json
|
|
{
|
|
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)
|
|
{
|
|
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);
|
|
}
|
|
|
|
|
|
|
|
static void SkipWhitespace(TextReader reader)
|
|
{
|
|
while (char.IsWhiteSpace((char) reader.Peek()) && (reader.Peek()!=-1))
|
|
reader.Read();
|
|
}
|
|
|
|
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)
|
|
{
|
|
SkipWhitespace(reader);
|
|
switch (reader.Peek())
|
|
{
|
|
case '"':
|
|
return parseString(reader);
|
|
case 't':
|
|
return parseTrue(reader);
|
|
case 'f':
|
|
return parseFalse(reader);
|
|
case 'n':
|
|
return parseNull(reader);
|
|
case '[':
|
|
return parseArray(reader);
|
|
case '{':
|
|
return parseObject(reader);
|
|
case '0':
|
|
case '1':
|
|
case '2':
|
|
case '3':
|
|
case '4':
|
|
case '5':
|
|
case '6':
|
|
case '7':
|
|
case '8':
|
|
case '9':
|
|
case '-':
|
|
return parseNumber(reader);
|
|
default:
|
|
throw new FormatException(String.Format("Unexpected character: {0} [ 0x{0:x4} ]", reader.Peek()));
|
|
}
|
|
}
|
|
|
|
static JSONString parseString(TextReader reader)
|
|
{
|
|
if (reader.Peek() != '"')
|
|
throw new FormatException("Unexpected character");
|
|
|
|
StringBuilder stringBuilder = new StringBuilder();
|
|
|
|
reader.Read();
|
|
int ch;
|
|
while ((ch = reader.Read()) != '"')
|
|
{
|
|
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);
|
|
}
|
|
SkipWhitespace(reader);
|
|
return new JSONString(JSONString.Unescape(stringBuilder.ToString()));
|
|
}
|
|
static JSONNumber parseNumber(TextReader reader)
|
|
{
|
|
StringBuilder sb = new StringBuilder();
|
|
|
|
if (reader.Peek() == '-')
|
|
{
|
|
sb.Append((char)reader.Read());
|
|
}
|
|
Read(reader,sb,char.IsDigit);
|
|
if (reader.Peek() == '.')
|
|
{
|
|
sb.Append('.');
|
|
reader.Read();
|
|
Read(reader,sb,char.IsDigit);
|
|
}
|
|
if ((reader.Peek() == 'e') || (reader.Peek() == 'E'))
|
|
{
|
|
sb.Append('e');
|
|
if ((reader.Peek() == '-')|| (reader.Peek() == '+'))
|
|
{
|
|
sb.Append((char)reader.Read());
|
|
}
|
|
|
|
Read(reader, sb, char.IsDigit);
|
|
}
|
|
|
|
SkipWhitespace(reader);
|
|
return new JSONNumber(decimal.Parse(sb.ToString(),CultureInfo.InvariantCulture));
|
|
}
|
|
static JSONArray parseArray(TextReader reader)
|
|
{
|
|
if (reader.Peek() != '[')
|
|
throw new FormatException("Unexpected character");
|
|
|
|
JSONArray array = new JSONArray();
|
|
|
|
reader.Read();
|
|
while (reader.Peek() != ']')
|
|
{
|
|
array.Add(ParseValue(reader));
|
|
if (reader.Peek() == ',')
|
|
{
|
|
reader.Read();
|
|
SkipWhitespace(reader);
|
|
}
|
|
}
|
|
|
|
reader.Read();
|
|
SkipWhitespace(reader);
|
|
|
|
return array;
|
|
}
|
|
static JSONObject parseObject(TextReader reader)
|
|
{
|
|
if (reader.Peek() != '{')
|
|
throw new FormatException("Unexpected character");
|
|
|
|
JSONObject o = new JSONObject();
|
|
|
|
reader.Read();
|
|
SkipWhitespace(reader);
|
|
|
|
while (reader.Peek() != '}')
|
|
{
|
|
JSONString s = parseString(reader);
|
|
if (reader.Peek() != ':')
|
|
throw new FormatException("expected :");
|
|
reader.Read();
|
|
o.Add(s.Value, ParseValue(reader));
|
|
|
|
if (reader.Peek() == ',')
|
|
{
|
|
reader.Read();
|
|
SkipWhitespace(reader);
|
|
}
|
|
}
|
|
|
|
reader.Read();
|
|
SkipWhitespace(reader);
|
|
|
|
return o;
|
|
}
|
|
static JSONTrue parseTrue(TextReader reader)
|
|
{
|
|
char[] ch = new char[4];
|
|
for (int n = 0; n < ch.Length; n++)
|
|
{
|
|
ch[n] = (char)reader.Read();
|
|
}
|
|
if (ch.AreEqual(chTrue))
|
|
{
|
|
SkipWhitespace(reader);
|
|
return JSONTrue.Instance;
|
|
}
|
|
|
|
throw new FormatException();
|
|
}
|
|
static JSONFalse parseFalse(TextReader reader)
|
|
{
|
|
char[] ch = new char[5];
|
|
for (int n = 0; n < ch.Length; n++)
|
|
{
|
|
ch[n] = (char)reader.Read();
|
|
}
|
|
if (ch.AreEqual(chFalse))
|
|
{
|
|
SkipWhitespace(reader);
|
|
return JSONFalse.Instance;
|
|
}
|
|
|
|
throw new FormatException();
|
|
}
|
|
static JSONNull parseNull(TextReader reader)
|
|
{
|
|
char[] ch = new char[4];
|
|
for (int n=0;n<ch.Length;n++)
|
|
{
|
|
ch[n] = (char)reader.Read();
|
|
}
|
|
if (ch.AreEqual(chNull))
|
|
{
|
|
SkipWhitespace(reader);
|
|
return JSONNull.Instance;
|
|
}
|
|
|
|
throw new FormatException();
|
|
}
|
|
}
|
|
}
|