ln.json/ln.json/JSONParser.cs

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();
}
}
}