Skip to content

Commit

Permalink
Rewrite of JSON parser
Browse files Browse the repository at this point in the history
  • Loading branch information
activa committed Nov 23, 2013
1 parent 7dc99bf commit cef98c6
Show file tree
Hide file tree
Showing 61 changed files with 11,785 additions and 2,492 deletions.
15 changes: 9 additions & 6 deletions Library/CoreExtensions.cs
Expand Up @@ -36,17 +36,20 @@ namespace Vici.Core
#if PCL
public delegate TOutput Converter<TInput, TOutput>(TInput value);
#endif

public static class CoreExtensions
{
public static TOutput[] ConvertAll<TInput, TOutput>(this TInput[] array, Converter<TInput, TOutput> converter)
{
if (array == null)
throw new ArgumentException();
#if PCL
return array.Select(item => converter(item)).ToArray();
#else
return Array.ConvertAll(array,converter);
#endif
throw new ArgumentNullException("array");

var newArray = new TOutput[array.Length];

for (int i = 0; i < array.Length; i++)
newArray[i] = converter(array[i]);

return newArray;
}

#if PCL
Expand Down
102 changes: 53 additions & 49 deletions Library/CompatibilityLayer.cs → Library/FileIO.cs
@@ -1,49 +1,53 @@
#region License
//=============================================================================
// Vici Core - Productivity Library for .NET 3.5
//
// Copyright (c) 2008-2012 Philippe Leybaert
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//=============================================================================
#endregion

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;

namespace Vici.Core.CompatibilityLayer
{
#if !PCL
public static class File
{
public static string ReadAllText(string filename)
{
return System.IO.File.ReadAllText(filename);
}

public static void AppendAllText(string filename, string text)
{
System.IO.File.AppendAllText(filename,text);
}

}
#endif
}
#region License
//=============================================================================
// Vici Core - Productivity Library for .NET 3.5
//
// Copyright (c) 2008-2012 Philippe Leybaert
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//=============================================================================
#endregion

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;

namespace Vici.Core
{
public static class FileIO
{
public class FileIODelegates
{
public Func<string,string> ReadAllText;
public Func<string, string> BuildFullPath;
}

public static FileIODelegates Delegates = new FileIODelegates()
#if PCL
;
#else
{
ReadAllText = path => File.ReadAllText(path),
BuildFullPath = path => Path.GetFullPath(path)
};
#endif

}
}
86 changes: 52 additions & 34 deletions Library/Json/JSONParser.cs
Expand Up @@ -35,25 +35,35 @@ namespace Vici.Core.Json
{
public class JsonParser
{
public static JsonObject Parse(string json)
{
return new JsonParser()._Parse(json);
}

public static T Parse<T>(string json) where T : class,new()
{
return new JsonParser()._Parse<T>(json);
}

private Token[] _tokens;
private int _currentToken;

public T Parse<T>(string json) where T:class, new()
private T _Parse<T>(string json) where T:class, new()
{
Tokenize(json);

_currentToken = 0;

return (T) ParseObject(typeof(T));
return ParseObject(typeof(T)).As<T>();
}

public object Parse(string json)
private JsonObject _Parse(string json)
{
Tokenize(json);

_currentToken = 0;

return ParseObject(typeof (object));
return ParseValue();
}

private void Tokenize(string json)
Expand All @@ -77,7 +87,7 @@ private void NextToken()
_currentToken++;
}

private object ParseObject(Type objectType)
private JsonObject ParseObject(Type objectType = null)
{
if (CurrentToken().TokenMatcher is NullTokenMatcher)
{
Expand All @@ -92,9 +102,9 @@ private object ParseObject(Type objectType)
object obj;
bool isDictionary = false;

if (objectType == typeof(object))
if (objectType == null)
{
obj = new Dictionary<string, object>();
obj = new Dictionary<string, JsonObject>();

isDictionary = true;
}
Expand Down Expand Up @@ -126,7 +136,7 @@ private object ParseObject(Type objectType)
{
Type fieldType = (property != null) ? property.PropertyType : field.FieldType;

object fieldvalue = ParseValue(fieldType);
object fieldvalue = ParseValue(fieldType).As(fieldType);

if (property != null)
property.SetValue(obj, fieldvalue, null);
Expand All @@ -140,7 +150,7 @@ private object ParseObject(Type objectType)
}
else
{
((Dictionary<string, object>) obj)[propName] = ParseValue(typeof (object));
((Dictionary<string, JsonObject>) obj)[propName] = ParseValue();
}

if (!(CurrentToken().TokenMatcher is CommaTokenMatcher))
Expand All @@ -154,19 +164,22 @@ private object ParseObject(Type objectType)

NextToken();

return obj;
return new JsonObject(obj);
}

private static bool IsArray(Type type)
{
return type.Inspector().ImplementsOrInherits<IList>()
return type != null && (
type.Inspector().ImplementsOrInherits<IList>()
||
type.Inspector().ImplementsOrInherits(typeof (IList<>));
type.Inspector().ImplementsOrInherits(typeof (IList<>)));
}

private object ParseValue(Type type)
private JsonObject ParseValue(Type type = null)
{
if (type == typeof(object))
bool isArray = false;

if (type == null)
{
if (CurrentToken().TokenMatcher is StringTokenMatcher)
type = typeof(string);
Expand All @@ -177,13 +190,20 @@ private object ParseValue(Type type)
else if (CurrentToken().TokenMatcher is TrueTokenMatcher || CurrentToken().TokenMatcher is FalseTokenMatcher)
type = typeof(bool);
else if (CurrentToken().TokenMatcher is ArrayStartTokenMatcher)
type = typeof(object[]);
else if (CurrentToken().TokenMatcher is ObjectStartTokenMatcher || CurrentToken().TokenMatcher is NullTokenMatcher)
type = typeof (object);
isArray = true;
else if (CurrentToken().TokenMatcher is ObjectStartTokenMatcher ||
CurrentToken().TokenMatcher is NullTokenMatcher)
{}
else
throw new Exception("Unexpected token " + CurrentToken());
}

if (isArray || IsArray(type))
return ParseArray(type);

if (type == null)
return ParseObject();

if (type == typeof(string))
return ParseString();

Expand All @@ -193,19 +213,16 @@ private object ParseValue(Type type)

NextToken();

return value;
return new JsonObject(value);
}

if (type == typeof(int) || type == typeof(short) || type == typeof(long) || type == typeof(double) || type == typeof(float) || type == typeof(decimal))
return ParseNumber(type);

if (IsArray(type))
return ParseArray(type);


return ParseObject(type);
}

private object ParseNumber(Type type)
private JsonObject ParseNumber(Type type)
{
if (!(CurrentToken().TokenMatcher is IntegerTokenMatcher) && !(CurrentToken().TokenMatcher is FloatTokenMatcher))
throw new Exception("Number expected");
Expand All @@ -223,12 +240,12 @@ private object ParseNumber(Type type)

_currentToken++;

return Convert.ChangeType(n, type, null);
return new JsonObject(Convert.ChangeType(n, type, null));
}



private object ParseString()
private JsonObject ParseString()
{
if (!(CurrentToken().TokenMatcher is StringTokenMatcher))
throw new Exception("Expected string");
Expand All @@ -239,31 +256,32 @@ private object ParseString()

_currentToken++;

return s;
return new JsonObject(s);
}

private object ParseArray(Type type)
private JsonObject ParseArray(Type type)
{
Type elementType = null;

if (type.IsArray)
{
if (type != null && type.IsArray)
elementType = type.GetElementType();
}

if (!(CurrentToken().TokenMatcher is ArrayStartTokenMatcher))
throw new Exception("Expected [");

_currentToken++;

List<object> list = new List<object>();
var list = new List<object>();

for(;;)
{
if (CurrentToken().TokenMatcher is ArrayEndTokenMatcher)
break;

list.Add(ParseValue(elementType));
if (elementType == null)
list.Add(ParseValue());
else
list.Add(ParseValue().As(elementType));

if (!(CurrentToken().TokenMatcher is CommaTokenMatcher))
break;
Expand All @@ -276,12 +294,12 @@ private object ParseArray(Type type)

_currentToken++;

Array array = Array.CreateInstance(elementType, list.Count);
Array array = Array.CreateInstance(elementType ?? typeof(JsonObject), list.Count);

for (int i = 0; i < array.Length; i++ )
array.SetValue(list[i],i);

return array;
return new JsonObject(array);
}
}
}
4 changes: 2 additions & 2 deletions Library/Json/Json.cs
Expand Up @@ -29,9 +29,9 @@

namespace Vici.Core.Json
{
public static class Json
public partial class JsonParser
{
public static object Parse(string json)
public static JsonObject Parse(string json)
{
return new JsonParser().Parse(json);
}
Expand Down

0 comments on commit cef98c6

Please sign in to comment.