chore: 初始化北汽福田MES采集程序
This commit is contained in:
128
Common/00-1Json8.3/Json8.3/Utilities/Base64Encoder.cs
Normal file
128
Common/00-1Json8.3/Json8.3/Utilities/Base64Encoder.cs
Normal file
@@ -0,0 +1,128 @@
|
||||
#region License
|
||||
// Copyright (c) 2007 James Newton-King
|
||||
//
|
||||
// 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.IO;
|
||||
|
||||
namespace Newtonsoft.Json.Utilities
|
||||
{
|
||||
internal class Base64Encoder
|
||||
{
|
||||
private const int Base64LineSize = 76;
|
||||
private const int LineSizeInBytes = 57;
|
||||
|
||||
private readonly char[] _charsLine = new char[Base64LineSize];
|
||||
private readonly TextWriter _writer;
|
||||
|
||||
private byte[] _leftOverBytes;
|
||||
private int _leftOverBytesCount;
|
||||
|
||||
public Base64Encoder(TextWriter writer)
|
||||
{
|
||||
ValidationUtils.ArgumentNotNull(writer, nameof(writer));
|
||||
_writer = writer;
|
||||
}
|
||||
|
||||
public void Encode(byte[] buffer, int index, int count)
|
||||
{
|
||||
if (buffer == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(buffer));
|
||||
}
|
||||
|
||||
if (index < 0)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(index));
|
||||
}
|
||||
|
||||
if (count < 0)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(count));
|
||||
}
|
||||
|
||||
if (count > (buffer.Length - index))
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(count));
|
||||
}
|
||||
|
||||
if (_leftOverBytesCount > 0)
|
||||
{
|
||||
int leftOverBytesCount = _leftOverBytesCount;
|
||||
while (leftOverBytesCount < 3 && count > 0)
|
||||
{
|
||||
_leftOverBytes[leftOverBytesCount++] = buffer[index++];
|
||||
count--;
|
||||
}
|
||||
if (count == 0 && leftOverBytesCount < 3)
|
||||
{
|
||||
_leftOverBytesCount = leftOverBytesCount;
|
||||
return;
|
||||
}
|
||||
int num2 = Convert.ToBase64CharArray(_leftOverBytes, 0, 3, _charsLine, 0);
|
||||
WriteChars(_charsLine, 0, num2);
|
||||
}
|
||||
_leftOverBytesCount = count % 3;
|
||||
if (_leftOverBytesCount > 0)
|
||||
{
|
||||
count -= _leftOverBytesCount;
|
||||
if (_leftOverBytes == null)
|
||||
{
|
||||
_leftOverBytes = new byte[3];
|
||||
}
|
||||
for (int i = 0; i < _leftOverBytesCount; i++)
|
||||
{
|
||||
_leftOverBytes[i] = buffer[(index + count) + i];
|
||||
}
|
||||
}
|
||||
int num4 = index + count;
|
||||
int length = LineSizeInBytes;
|
||||
while (index < num4)
|
||||
{
|
||||
if ((index + length) > num4)
|
||||
{
|
||||
length = num4 - index;
|
||||
}
|
||||
int num6 = Convert.ToBase64CharArray(buffer, index, length, _charsLine, 0);
|
||||
WriteChars(_charsLine, 0, num6);
|
||||
index += length;
|
||||
}
|
||||
}
|
||||
|
||||
public void Flush()
|
||||
{
|
||||
if (_leftOverBytesCount > 0)
|
||||
{
|
||||
int count = Convert.ToBase64CharArray(_leftOverBytes, 0, _leftOverBytesCount, _charsLine, 0);
|
||||
WriteChars(_charsLine, 0, count);
|
||||
_leftOverBytesCount = 0;
|
||||
}
|
||||
}
|
||||
|
||||
private void WriteChars(char[] chars, int index, int count)
|
||||
{
|
||||
_writer.Write(chars, index, count);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
#region License
|
||||
// Copyright (c) 2007 James Newton-King
|
||||
//
|
||||
// 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.Globalization;
|
||||
|
||||
namespace Newtonsoft.Json.Utilities
|
||||
{
|
||||
internal class BidirectionalDictionary<TFirst, TSecond>
|
||||
{
|
||||
private readonly IDictionary<TFirst, TSecond> _firstToSecond;
|
||||
private readonly IDictionary<TSecond, TFirst> _secondToFirst;
|
||||
private readonly string _duplicateFirstErrorMessage;
|
||||
private readonly string _duplicateSecondErrorMessage;
|
||||
|
||||
public BidirectionalDictionary()
|
||||
: this(EqualityComparer<TFirst>.Default, EqualityComparer<TSecond>.Default)
|
||||
{
|
||||
}
|
||||
|
||||
public BidirectionalDictionary(IEqualityComparer<TFirst> firstEqualityComparer, IEqualityComparer<TSecond> secondEqualityComparer)
|
||||
: this(
|
||||
firstEqualityComparer,
|
||||
secondEqualityComparer,
|
||||
"Duplicate item already exists for '{0}'.",
|
||||
"Duplicate item already exists for '{0}'.")
|
||||
{
|
||||
}
|
||||
|
||||
public BidirectionalDictionary(IEqualityComparer<TFirst> firstEqualityComparer, IEqualityComparer<TSecond> secondEqualityComparer,
|
||||
string duplicateFirstErrorMessage, string duplicateSecondErrorMessage)
|
||||
{
|
||||
_firstToSecond = new Dictionary<TFirst, TSecond>(firstEqualityComparer);
|
||||
_secondToFirst = new Dictionary<TSecond, TFirst>(secondEqualityComparer);
|
||||
_duplicateFirstErrorMessage = duplicateFirstErrorMessage;
|
||||
_duplicateSecondErrorMessage = duplicateSecondErrorMessage;
|
||||
}
|
||||
|
||||
public void Set(TFirst first, TSecond second)
|
||||
{
|
||||
TFirst existingFirst;
|
||||
TSecond existingSecond;
|
||||
|
||||
if (_firstToSecond.TryGetValue(first, out existingSecond))
|
||||
{
|
||||
if (!existingSecond.Equals(second))
|
||||
{
|
||||
throw new ArgumentException(_duplicateFirstErrorMessage.FormatWith(CultureInfo.InvariantCulture, first));
|
||||
}
|
||||
}
|
||||
|
||||
if (_secondToFirst.TryGetValue(second, out existingFirst))
|
||||
{
|
||||
if (!existingFirst.Equals(first))
|
||||
{
|
||||
throw new ArgumentException(_duplicateSecondErrorMessage.FormatWith(CultureInfo.InvariantCulture, second));
|
||||
}
|
||||
}
|
||||
|
||||
_firstToSecond.Add(first, second);
|
||||
_secondToFirst.Add(second, first);
|
||||
}
|
||||
|
||||
public bool TryGetByFirst(TFirst first, out TSecond second)
|
||||
{
|
||||
return _firstToSecond.TryGetValue(first, out second);
|
||||
}
|
||||
|
||||
public bool TryGetBySecond(TSecond second, out TFirst first)
|
||||
{
|
||||
return _secondToFirst.TryGetValue(second, out first);
|
||||
}
|
||||
}
|
||||
}
|
||||
348
Common/00-1Json8.3/Json8.3/Utilities/CollectionUtils.cs
Normal file
348
Common/00-1Json8.3/Json8.3/Utilities/CollectionUtils.cs
Normal file
@@ -0,0 +1,348 @@
|
||||
#region License
|
||||
// Copyright (c) 2007 James Newton-King
|
||||
//
|
||||
// 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.Collections.ObjectModel;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Collections;
|
||||
#if NET20
|
||||
using Newtonsoft.Json.Utilities.LinqBridge;
|
||||
#else
|
||||
using System.Linq;
|
||||
#endif
|
||||
using System.Globalization;
|
||||
using Newtonsoft.Json.Serialization;
|
||||
|
||||
namespace Newtonsoft.Json.Utilities
|
||||
{
|
||||
internal static class CollectionUtils
|
||||
{
|
||||
/// <summary>
|
||||
/// Determines whether the collection is null or empty.
|
||||
/// </summary>
|
||||
/// <param name="collection">The collection.</param>
|
||||
/// <returns>
|
||||
/// <c>true</c> if the collection is null or empty; otherwise, <c>false</c>.
|
||||
/// </returns>
|
||||
public static bool IsNullOrEmpty<T>(ICollection<T> collection)
|
||||
{
|
||||
if (collection != null)
|
||||
{
|
||||
return (collection.Count == 0);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds the elements of the specified collection to the specified generic IList.
|
||||
/// </summary>
|
||||
/// <param name="initial">The list to add to.</param>
|
||||
/// <param name="collection">The collection of elements to add.</param>
|
||||
public static void AddRange<T>(this IList<T> initial, IEnumerable<T> collection)
|
||||
{
|
||||
if (initial == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(initial));
|
||||
}
|
||||
|
||||
if (collection == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (T value in collection)
|
||||
{
|
||||
initial.Add(value);
|
||||
}
|
||||
}
|
||||
|
||||
#if (NET20 || NET35 || PORTABLE40)
|
||||
public static void AddRange<T>(this IList<T> initial, IEnumerable collection)
|
||||
{
|
||||
ValidationUtils.ArgumentNotNull(initial, nameof(initial));
|
||||
|
||||
// because earlier versions of .NET didn't support covariant generics
|
||||
initial.AddRange(collection.Cast<T>());
|
||||
}
|
||||
#endif
|
||||
|
||||
public static bool IsDictionaryType(Type type)
|
||||
{
|
||||
ValidationUtils.ArgumentNotNull(type, nameof(type));
|
||||
|
||||
if (typeof(IDictionary).IsAssignableFrom(type))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if (ReflectionUtils.ImplementsGenericDefinition(type, typeof(IDictionary<,>)))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
#if !(NET40 || NET35 || NET20 || PORTABLE40)
|
||||
if (ReflectionUtils.ImplementsGenericDefinition(type, typeof(IReadOnlyDictionary<,>)))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static ConstructorInfo ResolveEnumerableCollectionConstructor(Type collectionType, Type collectionItemType)
|
||||
{
|
||||
Type genericEnumerable = typeof(IEnumerable<>).MakeGenericType(collectionItemType);
|
||||
ConstructorInfo match = null;
|
||||
|
||||
foreach (ConstructorInfo constructor in collectionType.GetConstructors(BindingFlags.Public | BindingFlags.Instance))
|
||||
{
|
||||
IList<ParameterInfo> parameters = constructor.GetParameters();
|
||||
|
||||
if (parameters.Count == 1)
|
||||
{
|
||||
if (genericEnumerable == parameters[0].ParameterType)
|
||||
{
|
||||
// exact match
|
||||
match = constructor;
|
||||
break;
|
||||
}
|
||||
|
||||
// incase we can't find an exact match, use first inexact
|
||||
if (match == null)
|
||||
{
|
||||
if (genericEnumerable.IsAssignableFrom(parameters[0].ParameterType))
|
||||
{
|
||||
match = constructor;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return match;
|
||||
}
|
||||
|
||||
public static bool AddDistinct<T>(this IList<T> list, T value)
|
||||
{
|
||||
return list.AddDistinct(value, EqualityComparer<T>.Default);
|
||||
}
|
||||
|
||||
public static bool AddDistinct<T>(this IList<T> list, T value, IEqualityComparer<T> comparer)
|
||||
{
|
||||
if (list.ContainsValue(value, comparer))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
list.Add(value);
|
||||
return true;
|
||||
}
|
||||
|
||||
// this is here because LINQ Bridge doesn't support Contains with IEqualityComparer<T>
|
||||
public static bool ContainsValue<TSource>(this IEnumerable<TSource> source, TSource value, IEqualityComparer<TSource> comparer)
|
||||
{
|
||||
if (comparer == null)
|
||||
{
|
||||
comparer = EqualityComparer<TSource>.Default;
|
||||
}
|
||||
|
||||
if (source == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(source));
|
||||
}
|
||||
|
||||
foreach (TSource local in source)
|
||||
{
|
||||
if (comparer.Equals(local, value))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static bool AddRangeDistinct<T>(this IList<T> list, IEnumerable<T> values, IEqualityComparer<T> comparer)
|
||||
{
|
||||
bool allAdded = true;
|
||||
foreach (T value in values)
|
||||
{
|
||||
if (!list.AddDistinct(value, comparer))
|
||||
{
|
||||
allAdded = false;
|
||||
}
|
||||
}
|
||||
|
||||
return allAdded;
|
||||
}
|
||||
|
||||
public static int IndexOf<T>(this IEnumerable<T> collection, Func<T, bool> predicate)
|
||||
{
|
||||
int index = 0;
|
||||
foreach (T value in collection)
|
||||
{
|
||||
if (predicate(value))
|
||||
{
|
||||
return index;
|
||||
}
|
||||
|
||||
index++;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
public static bool Contains(this IEnumerable list, object value, IEqualityComparer comparer)
|
||||
{
|
||||
foreach (object item in list)
|
||||
{
|
||||
if (comparer.Equals(item, value))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the index of the first occurrence in a sequence by using a specified IEqualityComparer{TSource}.
|
||||
/// </summary>
|
||||
/// <typeparam name="TSource">The type of the elements of source.</typeparam>
|
||||
/// <param name="list">A sequence in which to locate a value.</param>
|
||||
/// <param name="value">The object to locate in the sequence</param>
|
||||
/// <param name="comparer">An equality comparer to compare values.</param>
|
||||
/// <returns>The zero-based index of the first occurrence of value within the entire sequence, if found; otherwise, ?.</returns>
|
||||
public static int IndexOf<TSource>(this IEnumerable<TSource> list, TSource value, IEqualityComparer<TSource> comparer)
|
||||
{
|
||||
int index = 0;
|
||||
foreach (TSource item in list)
|
||||
{
|
||||
if (comparer.Equals(item, value))
|
||||
{
|
||||
return index;
|
||||
}
|
||||
index++;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
private static IList<int> GetDimensions(IList values, int dimensionsCount)
|
||||
{
|
||||
IList<int> dimensions = new List<int>();
|
||||
|
||||
IList currentArray = values;
|
||||
while (true)
|
||||
{
|
||||
dimensions.Add(currentArray.Count);
|
||||
|
||||
// don't keep calculating dimensions for arrays inside the value array
|
||||
if (dimensions.Count == dimensionsCount)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if (currentArray.Count == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
object v = currentArray[0];
|
||||
if (v is IList)
|
||||
{
|
||||
currentArray = (IList)v;
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return dimensions;
|
||||
}
|
||||
|
||||
private static void CopyFromJaggedToMultidimensionalArray(IList values, Array multidimensionalArray, int[] indices)
|
||||
{
|
||||
int dimension = indices.Length;
|
||||
if (dimension == multidimensionalArray.Rank)
|
||||
{
|
||||
multidimensionalArray.SetValue(JaggedArrayGetValue(values, indices), indices);
|
||||
return;
|
||||
}
|
||||
|
||||
int dimensionLength = multidimensionalArray.GetLength(dimension);
|
||||
IList list = (IList)JaggedArrayGetValue(values, indices);
|
||||
int currentValuesLength = list.Count;
|
||||
if (currentValuesLength != dimensionLength)
|
||||
{
|
||||
throw new Exception("Cannot deserialize non-cubical array as multidimensional array.");
|
||||
}
|
||||
|
||||
int[] newIndices = new int[dimension + 1];
|
||||
for (int i = 0; i < dimension; i++)
|
||||
{
|
||||
newIndices[i] = indices[i];
|
||||
}
|
||||
|
||||
for (int i = 0; i < multidimensionalArray.GetLength(dimension); i++)
|
||||
{
|
||||
newIndices[dimension] = i;
|
||||
CopyFromJaggedToMultidimensionalArray(values, multidimensionalArray, newIndices);
|
||||
}
|
||||
}
|
||||
|
||||
private static object JaggedArrayGetValue(IList values, int[] indices)
|
||||
{
|
||||
IList currentList = values;
|
||||
for (int i = 0; i < indices.Length; i++)
|
||||
{
|
||||
int index = indices[i];
|
||||
if (i == indices.Length - 1)
|
||||
{
|
||||
return currentList[index];
|
||||
}
|
||||
else
|
||||
{
|
||||
currentList = (IList)currentList[index];
|
||||
}
|
||||
}
|
||||
return currentList;
|
||||
}
|
||||
|
||||
public static Array ToMultidimensionalArray(IList values, Type type, int rank)
|
||||
{
|
||||
IList<int> dimensions = GetDimensions(values, rank);
|
||||
|
||||
while (dimensions.Count < rank)
|
||||
{
|
||||
dimensions.Add(0);
|
||||
}
|
||||
|
||||
Array multidimensionalArray = Array.CreateInstance(type, dimensions.ToArray());
|
||||
CopyFromJaggedToMultidimensionalArray(values, multidimensionalArray, new int[0]);
|
||||
|
||||
return multidimensionalArray;
|
||||
}
|
||||
}
|
||||
}
|
||||
348
Common/00-1Json8.3/Json8.3/Utilities/CollectionWrapper.cs
Normal file
348
Common/00-1Json8.3/Json8.3/Utilities/CollectionWrapper.cs
Normal file
@@ -0,0 +1,348 @@
|
||||
#region License
|
||||
// Copyright (c) 2007 James Newton-King
|
||||
//
|
||||
// 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;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using System.Globalization;
|
||||
#if NET20
|
||||
using Newtonsoft.Json.Utilities.LinqBridge;
|
||||
#else
|
||||
using System.Linq;
|
||||
|
||||
#endif
|
||||
|
||||
namespace Newtonsoft.Json.Utilities
|
||||
{
|
||||
internal interface IWrappedCollection : IList
|
||||
{
|
||||
object UnderlyingCollection { get; }
|
||||
}
|
||||
|
||||
internal class CollectionWrapper<T> : ICollection<T>, IWrappedCollection
|
||||
{
|
||||
private readonly IList _list;
|
||||
private readonly ICollection<T> _genericCollection;
|
||||
private object _syncRoot;
|
||||
|
||||
public CollectionWrapper(IList list)
|
||||
{
|
||||
ValidationUtils.ArgumentNotNull(list, nameof(list));
|
||||
|
||||
if (list is ICollection<T>)
|
||||
{
|
||||
_genericCollection = (ICollection<T>)list;
|
||||
}
|
||||
else
|
||||
{
|
||||
_list = list;
|
||||
}
|
||||
}
|
||||
|
||||
public CollectionWrapper(ICollection<T> list)
|
||||
{
|
||||
ValidationUtils.ArgumentNotNull(list, nameof(list));
|
||||
|
||||
_genericCollection = list;
|
||||
}
|
||||
|
||||
public virtual void Add(T item)
|
||||
{
|
||||
if (_genericCollection != null)
|
||||
{
|
||||
_genericCollection.Add(item);
|
||||
}
|
||||
else
|
||||
{
|
||||
_list.Add(item);
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void Clear()
|
||||
{
|
||||
if (_genericCollection != null)
|
||||
{
|
||||
_genericCollection.Clear();
|
||||
}
|
||||
else
|
||||
{
|
||||
_list.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
public virtual bool Contains(T item)
|
||||
{
|
||||
if (_genericCollection != null)
|
||||
{
|
||||
return _genericCollection.Contains(item);
|
||||
}
|
||||
else
|
||||
{
|
||||
return _list.Contains(item);
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void CopyTo(T[] array, int arrayIndex)
|
||||
{
|
||||
if (_genericCollection != null)
|
||||
{
|
||||
_genericCollection.CopyTo(array, arrayIndex);
|
||||
}
|
||||
else
|
||||
{
|
||||
_list.CopyTo(array, arrayIndex);
|
||||
}
|
||||
}
|
||||
|
||||
public virtual int Count
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_genericCollection != null)
|
||||
{
|
||||
return _genericCollection.Count;
|
||||
}
|
||||
else
|
||||
{
|
||||
return _list.Count;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public virtual bool IsReadOnly
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_genericCollection != null)
|
||||
{
|
||||
return _genericCollection.IsReadOnly;
|
||||
}
|
||||
else
|
||||
{
|
||||
return _list.IsReadOnly;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public virtual bool Remove(T item)
|
||||
{
|
||||
if (_genericCollection != null)
|
||||
{
|
||||
return _genericCollection.Remove(item);
|
||||
}
|
||||
else
|
||||
{
|
||||
bool contains = _list.Contains(item);
|
||||
|
||||
if (contains)
|
||||
{
|
||||
_list.Remove(item);
|
||||
}
|
||||
|
||||
return contains;
|
||||
}
|
||||
}
|
||||
|
||||
public virtual IEnumerator<T> GetEnumerator()
|
||||
{
|
||||
if (_genericCollection != null)
|
||||
{
|
||||
return _genericCollection.GetEnumerator();
|
||||
}
|
||||
|
||||
return _list.Cast<T>().GetEnumerator();
|
||||
}
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
{
|
||||
if (_genericCollection != null)
|
||||
{
|
||||
return _genericCollection.GetEnumerator();
|
||||
}
|
||||
else
|
||||
{
|
||||
return _list.GetEnumerator();
|
||||
}
|
||||
}
|
||||
|
||||
int IList.Add(object value)
|
||||
{
|
||||
VerifyValueType(value);
|
||||
Add((T)value);
|
||||
|
||||
return (Count - 1);
|
||||
}
|
||||
|
||||
bool IList.Contains(object value)
|
||||
{
|
||||
if (IsCompatibleObject(value))
|
||||
{
|
||||
return Contains((T)value);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
int IList.IndexOf(object value)
|
||||
{
|
||||
if (_genericCollection != null)
|
||||
{
|
||||
throw new InvalidOperationException("Wrapped ICollection<T> does not support IndexOf.");
|
||||
}
|
||||
|
||||
if (IsCompatibleObject(value))
|
||||
{
|
||||
return _list.IndexOf((T)value);
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
void IList.RemoveAt(int index)
|
||||
{
|
||||
if (_genericCollection != null)
|
||||
{
|
||||
throw new InvalidOperationException("Wrapped ICollection<T> does not support RemoveAt.");
|
||||
}
|
||||
|
||||
_list.RemoveAt(index);
|
||||
}
|
||||
|
||||
void IList.Insert(int index, object value)
|
||||
{
|
||||
if (_genericCollection != null)
|
||||
{
|
||||
throw new InvalidOperationException("Wrapped ICollection<T> does not support Insert.");
|
||||
}
|
||||
|
||||
VerifyValueType(value);
|
||||
_list.Insert(index, (T)value);
|
||||
}
|
||||
|
||||
bool IList.IsFixedSize
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_genericCollection != null)
|
||||
{
|
||||
// ICollection<T> only has IsReadOnly
|
||||
return _genericCollection.IsReadOnly;
|
||||
}
|
||||
else
|
||||
{
|
||||
return _list.IsFixedSize;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void IList.Remove(object value)
|
||||
{
|
||||
if (IsCompatibleObject(value))
|
||||
{
|
||||
Remove((T)value);
|
||||
}
|
||||
}
|
||||
|
||||
object IList.this[int index]
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_genericCollection != null)
|
||||
{
|
||||
throw new InvalidOperationException("Wrapped ICollection<T> does not support indexer.");
|
||||
}
|
||||
|
||||
return _list[index];
|
||||
}
|
||||
set
|
||||
{
|
||||
if (_genericCollection != null)
|
||||
{
|
||||
throw new InvalidOperationException("Wrapped ICollection<T> does not support indexer.");
|
||||
}
|
||||
|
||||
VerifyValueType(value);
|
||||
_list[index] = (T)value;
|
||||
}
|
||||
}
|
||||
|
||||
void ICollection.CopyTo(Array array, int arrayIndex)
|
||||
{
|
||||
CopyTo((T[])array, arrayIndex);
|
||||
}
|
||||
|
||||
bool ICollection.IsSynchronized
|
||||
{
|
||||
get { return false; }
|
||||
}
|
||||
|
||||
object ICollection.SyncRoot
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_syncRoot == null)
|
||||
{
|
||||
Interlocked.CompareExchange(ref _syncRoot, new object(), null);
|
||||
}
|
||||
|
||||
return _syncRoot;
|
||||
}
|
||||
}
|
||||
|
||||
private static void VerifyValueType(object value)
|
||||
{
|
||||
if (!IsCompatibleObject(value))
|
||||
{
|
||||
throw new ArgumentException("The value '{0}' is not of type '{1}' and cannot be used in this generic collection.".FormatWith(CultureInfo.InvariantCulture, value, typeof(T)), nameof(value));
|
||||
}
|
||||
}
|
||||
|
||||
private static bool IsCompatibleObject(object value)
|
||||
{
|
||||
if (!(value is T) && (value != null || (typeof(T).IsValueType() && !ReflectionUtils.IsNullableType(typeof(T)))))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public object UnderlyingCollection
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_genericCollection != null)
|
||||
{
|
||||
return _genericCollection;
|
||||
}
|
||||
else
|
||||
{
|
||||
return _list;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
987
Common/00-1Json8.3/Json8.3/Utilities/ConvertUtils.cs
Normal file
987
Common/00-1Json8.3/Json8.3/Utilities/ConvertUtils.cs
Normal file
@@ -0,0 +1,987 @@
|
||||
#region License
|
||||
// Copyright (c) 2007 James Newton-King
|
||||
//
|
||||
// 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.Globalization;
|
||||
using System.ComponentModel;
|
||||
#if !(NET20 || NET35 || PORTABLE40 || PORTABLE)
|
||||
using System.Numerics;
|
||||
#endif
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using Newtonsoft.Json.Serialization;
|
||||
using System.Reflection;
|
||||
#if NET20
|
||||
using Newtonsoft.Json.Utilities.LinqBridge;
|
||||
#endif
|
||||
#if !(DOTNET || PORTABLE40 || PORTABLE)
|
||||
using System.Data.SqlTypes;
|
||||
|
||||
#endif
|
||||
|
||||
namespace Newtonsoft.Json.Utilities
|
||||
{
|
||||
internal enum PrimitiveTypeCode
|
||||
{
|
||||
Empty = 0,
|
||||
Object = 1,
|
||||
Char = 2,
|
||||
CharNullable = 3,
|
||||
Boolean = 4,
|
||||
BooleanNullable = 5,
|
||||
SByte = 6,
|
||||
SByteNullable = 7,
|
||||
Int16 = 8,
|
||||
Int16Nullable = 9,
|
||||
UInt16 = 10,
|
||||
UInt16Nullable = 11,
|
||||
Int32 = 12,
|
||||
Int32Nullable = 13,
|
||||
Byte = 14,
|
||||
ByteNullable = 15,
|
||||
UInt32 = 16,
|
||||
UInt32Nullable = 17,
|
||||
Int64 = 18,
|
||||
Int64Nullable = 19,
|
||||
UInt64 = 20,
|
||||
UInt64Nullable = 21,
|
||||
Single = 22,
|
||||
SingleNullable = 23,
|
||||
Double = 24,
|
||||
DoubleNullable = 25,
|
||||
DateTime = 26,
|
||||
DateTimeNullable = 27,
|
||||
DateTimeOffset = 28,
|
||||
DateTimeOffsetNullable = 29,
|
||||
Decimal = 30,
|
||||
DecimalNullable = 31,
|
||||
Guid = 32,
|
||||
GuidNullable = 33,
|
||||
TimeSpan = 34,
|
||||
TimeSpanNullable = 35,
|
||||
BigInteger = 36,
|
||||
BigIntegerNullable = 37,
|
||||
Uri = 38,
|
||||
String = 39,
|
||||
Bytes = 40,
|
||||
DBNull = 41
|
||||
}
|
||||
|
||||
internal class TypeInformation
|
||||
{
|
||||
public Type Type { get; set; }
|
||||
public PrimitiveTypeCode TypeCode { get; set; }
|
||||
}
|
||||
|
||||
internal enum ParseResult
|
||||
{
|
||||
None = 0,
|
||||
Success = 1,
|
||||
Overflow = 2,
|
||||
Invalid = 3
|
||||
}
|
||||
|
||||
internal static class ConvertUtils
|
||||
{
|
||||
private static readonly Dictionary<Type, PrimitiveTypeCode> TypeCodeMap =
|
||||
new Dictionary<Type, PrimitiveTypeCode>
|
||||
{
|
||||
{ typeof(char), PrimitiveTypeCode.Char },
|
||||
{ typeof(char?), PrimitiveTypeCode.CharNullable },
|
||||
{ typeof(bool), PrimitiveTypeCode.Boolean },
|
||||
{ typeof(bool?), PrimitiveTypeCode.BooleanNullable },
|
||||
{ typeof(sbyte), PrimitiveTypeCode.SByte },
|
||||
{ typeof(sbyte?), PrimitiveTypeCode.SByteNullable },
|
||||
{ typeof(short), PrimitiveTypeCode.Int16 },
|
||||
{ typeof(short?), PrimitiveTypeCode.Int16Nullable },
|
||||
{ typeof(ushort), PrimitiveTypeCode.UInt16 },
|
||||
{ typeof(ushort?), PrimitiveTypeCode.UInt16Nullable },
|
||||
{ typeof(int), PrimitiveTypeCode.Int32 },
|
||||
{ typeof(int?), PrimitiveTypeCode.Int32Nullable },
|
||||
{ typeof(byte), PrimitiveTypeCode.Byte },
|
||||
{ typeof(byte?), PrimitiveTypeCode.ByteNullable },
|
||||
{ typeof(uint), PrimitiveTypeCode.UInt32 },
|
||||
{ typeof(uint?), PrimitiveTypeCode.UInt32Nullable },
|
||||
{ typeof(long), PrimitiveTypeCode.Int64 },
|
||||
{ typeof(long?), PrimitiveTypeCode.Int64Nullable },
|
||||
{ typeof(ulong), PrimitiveTypeCode.UInt64 },
|
||||
{ typeof(ulong?), PrimitiveTypeCode.UInt64Nullable },
|
||||
{ typeof(float), PrimitiveTypeCode.Single },
|
||||
{ typeof(float?), PrimitiveTypeCode.SingleNullable },
|
||||
{ typeof(double), PrimitiveTypeCode.Double },
|
||||
{ typeof(double?), PrimitiveTypeCode.DoubleNullable },
|
||||
{ typeof(DateTime), PrimitiveTypeCode.DateTime },
|
||||
{ typeof(DateTime?), PrimitiveTypeCode.DateTimeNullable },
|
||||
#if !NET20
|
||||
{ typeof(DateTimeOffset), PrimitiveTypeCode.DateTimeOffset },
|
||||
{ typeof(DateTimeOffset?), PrimitiveTypeCode.DateTimeOffsetNullable },
|
||||
#endif
|
||||
{ typeof(decimal), PrimitiveTypeCode.Decimal },
|
||||
{ typeof(decimal?), PrimitiveTypeCode.DecimalNullable },
|
||||
{ typeof(Guid), PrimitiveTypeCode.Guid },
|
||||
{ typeof(Guid?), PrimitiveTypeCode.GuidNullable },
|
||||
{ typeof(TimeSpan), PrimitiveTypeCode.TimeSpan },
|
||||
{ typeof(TimeSpan?), PrimitiveTypeCode.TimeSpanNullable },
|
||||
#if !(PORTABLE || PORTABLE40 || NET35 || NET20)
|
||||
{ typeof(BigInteger), PrimitiveTypeCode.BigInteger },
|
||||
{ typeof(BigInteger?), PrimitiveTypeCode.BigIntegerNullable },
|
||||
#endif
|
||||
{ typeof(Uri), PrimitiveTypeCode.Uri },
|
||||
{ typeof(string), PrimitiveTypeCode.String },
|
||||
{ typeof(byte[]), PrimitiveTypeCode.Bytes },
|
||||
#if !(PORTABLE || PORTABLE40 || DOTNET)
|
||||
{ typeof(DBNull), PrimitiveTypeCode.DBNull }
|
||||
#endif
|
||||
};
|
||||
|
||||
#if !PORTABLE
|
||||
private static readonly TypeInformation[] PrimitiveTypeCodes =
|
||||
{
|
||||
// need all of these. lookup against the index with TypeCode value
|
||||
new TypeInformation { Type = typeof(object), TypeCode = PrimitiveTypeCode.Empty },
|
||||
new TypeInformation { Type = typeof(object), TypeCode = PrimitiveTypeCode.Object },
|
||||
new TypeInformation { Type = typeof(object), TypeCode = PrimitiveTypeCode.DBNull },
|
||||
new TypeInformation { Type = typeof(bool), TypeCode = PrimitiveTypeCode.Boolean },
|
||||
new TypeInformation { Type = typeof(char), TypeCode = PrimitiveTypeCode.Char },
|
||||
new TypeInformation { Type = typeof(sbyte), TypeCode = PrimitiveTypeCode.SByte },
|
||||
new TypeInformation { Type = typeof(byte), TypeCode = PrimitiveTypeCode.Byte },
|
||||
new TypeInformation { Type = typeof(short), TypeCode = PrimitiveTypeCode.Int16 },
|
||||
new TypeInformation { Type = typeof(ushort), TypeCode = PrimitiveTypeCode.UInt16 },
|
||||
new TypeInformation { Type = typeof(int), TypeCode = PrimitiveTypeCode.Int32 },
|
||||
new TypeInformation { Type = typeof(uint), TypeCode = PrimitiveTypeCode.UInt32 },
|
||||
new TypeInformation { Type = typeof(long), TypeCode = PrimitiveTypeCode.Int64 },
|
||||
new TypeInformation { Type = typeof(ulong), TypeCode = PrimitiveTypeCode.UInt64 },
|
||||
new TypeInformation { Type = typeof(float), TypeCode = PrimitiveTypeCode.Single },
|
||||
new TypeInformation { Type = typeof(double), TypeCode = PrimitiveTypeCode.Double },
|
||||
new TypeInformation { Type = typeof(decimal), TypeCode = PrimitiveTypeCode.Decimal },
|
||||
new TypeInformation { Type = typeof(DateTime), TypeCode = PrimitiveTypeCode.DateTime },
|
||||
new TypeInformation { Type = typeof(object), TypeCode = PrimitiveTypeCode.Empty }, // no 17 in TypeCode for some reason
|
||||
new TypeInformation { Type = typeof(string), TypeCode = PrimitiveTypeCode.String }
|
||||
};
|
||||
#endif
|
||||
|
||||
public static PrimitiveTypeCode GetTypeCode(Type t)
|
||||
{
|
||||
bool isEnum;
|
||||
return GetTypeCode(t, out isEnum);
|
||||
}
|
||||
|
||||
public static PrimitiveTypeCode GetTypeCode(Type t, out bool isEnum)
|
||||
{
|
||||
PrimitiveTypeCode typeCode;
|
||||
if (TypeCodeMap.TryGetValue(t, out typeCode))
|
||||
{
|
||||
isEnum = false;
|
||||
return typeCode;
|
||||
}
|
||||
|
||||
if (t.IsEnum())
|
||||
{
|
||||
isEnum = true;
|
||||
return GetTypeCode(Enum.GetUnderlyingType(t));
|
||||
}
|
||||
|
||||
// performance?
|
||||
if (ReflectionUtils.IsNullableType(t))
|
||||
{
|
||||
Type nonNullable = Nullable.GetUnderlyingType(t);
|
||||
if (nonNullable.IsEnum())
|
||||
{
|
||||
Type nullableUnderlyingType = typeof(Nullable<>).MakeGenericType(Enum.GetUnderlyingType(nonNullable));
|
||||
isEnum = true;
|
||||
return GetTypeCode(nullableUnderlyingType);
|
||||
}
|
||||
}
|
||||
|
||||
isEnum = false;
|
||||
return PrimitiveTypeCode.Object;
|
||||
}
|
||||
|
||||
#if !PORTABLE
|
||||
public static TypeInformation GetTypeInformation(IConvertible convertable)
|
||||
{
|
||||
TypeInformation typeInformation = PrimitiveTypeCodes[(int)convertable.GetTypeCode()];
|
||||
return typeInformation;
|
||||
}
|
||||
#endif
|
||||
|
||||
public static bool IsConvertible(Type t)
|
||||
{
|
||||
#if !PORTABLE
|
||||
return typeof(IConvertible).IsAssignableFrom(t);
|
||||
#else
|
||||
return (
|
||||
t == typeof(bool) || t == typeof(byte) || t == typeof(char) || t == typeof(DateTime) || t == typeof(decimal) || t == typeof(double) || t == typeof(short) || t == typeof(int) ||
|
||||
t == typeof(long) || t == typeof(sbyte) || t == typeof(float) || t == typeof(string) || t == typeof(ushort) || t == typeof(uint) || t == typeof(ulong) || t.IsEnum());
|
||||
#endif
|
||||
}
|
||||
|
||||
public static TimeSpan ParseTimeSpan(string input)
|
||||
{
|
||||
#if !(NET35 || NET20)
|
||||
return TimeSpan.Parse(input, CultureInfo.InvariantCulture);
|
||||
#else
|
||||
return TimeSpan.Parse(input);
|
||||
#endif
|
||||
}
|
||||
|
||||
internal struct TypeConvertKey : IEquatable<TypeConvertKey>
|
||||
{
|
||||
private readonly Type _initialType;
|
||||
private readonly Type _targetType;
|
||||
|
||||
public Type InitialType
|
||||
{
|
||||
get { return _initialType; }
|
||||
}
|
||||
|
||||
public Type TargetType
|
||||
{
|
||||
get { return _targetType; }
|
||||
}
|
||||
|
||||
public TypeConvertKey(Type initialType, Type targetType)
|
||||
{
|
||||
_initialType = initialType;
|
||||
_targetType = targetType;
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return _initialType.GetHashCode() ^ _targetType.GetHashCode();
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
if (!(obj is TypeConvertKey))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return Equals((TypeConvertKey)obj);
|
||||
}
|
||||
|
||||
public bool Equals(TypeConvertKey other)
|
||||
{
|
||||
return (_initialType == other._initialType && _targetType == other._targetType);
|
||||
}
|
||||
}
|
||||
|
||||
private static readonly ThreadSafeStore<TypeConvertKey, Func<object, object>> CastConverters =
|
||||
new ThreadSafeStore<TypeConvertKey, Func<object, object>>(CreateCastConverter);
|
||||
|
||||
private static Func<object, object> CreateCastConverter(TypeConvertKey t)
|
||||
{
|
||||
MethodInfo castMethodInfo = t.TargetType.GetMethod("op_Implicit", new[] { t.InitialType });
|
||||
if (castMethodInfo == null)
|
||||
{
|
||||
castMethodInfo = t.TargetType.GetMethod("op_Explicit", new[] { t.InitialType });
|
||||
}
|
||||
|
||||
if (castMethodInfo == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
MethodCall<object, object> call = JsonTypeReflector.ReflectionDelegateFactory.CreateMethodCall<object>(castMethodInfo);
|
||||
|
||||
return o => call(null, o);
|
||||
}
|
||||
|
||||
#if !(NET20 || NET35 || PORTABLE || PORTABLE40)
|
||||
internal static BigInteger ToBigInteger(object value)
|
||||
{
|
||||
if (value is BigInteger)
|
||||
{
|
||||
return (BigInteger)value;
|
||||
}
|
||||
if (value is string)
|
||||
{
|
||||
return BigInteger.Parse((string)value, CultureInfo.InvariantCulture);
|
||||
}
|
||||
if (value is float)
|
||||
{
|
||||
return new BigInteger((float)value);
|
||||
}
|
||||
if (value is double)
|
||||
{
|
||||
return new BigInteger((double)value);
|
||||
}
|
||||
if (value is decimal)
|
||||
{
|
||||
return new BigInteger((decimal)value);
|
||||
}
|
||||
if (value is int)
|
||||
{
|
||||
return new BigInteger((int)value);
|
||||
}
|
||||
if (value is long)
|
||||
{
|
||||
return new BigInteger((long)value);
|
||||
}
|
||||
if (value is uint)
|
||||
{
|
||||
return new BigInteger((uint)value);
|
||||
}
|
||||
if (value is ulong)
|
||||
{
|
||||
return new BigInteger((ulong)value);
|
||||
}
|
||||
if (value is byte[])
|
||||
{
|
||||
return new BigInteger((byte[])value);
|
||||
}
|
||||
|
||||
throw new InvalidCastException("Cannot convert {0} to BigInteger.".FormatWith(CultureInfo.InvariantCulture, value.GetType()));
|
||||
}
|
||||
|
||||
public static object FromBigInteger(BigInteger i, Type targetType)
|
||||
{
|
||||
if (targetType == typeof(decimal))
|
||||
{
|
||||
return (decimal)i;
|
||||
}
|
||||
if (targetType == typeof(double))
|
||||
{
|
||||
return (double)i;
|
||||
}
|
||||
if (targetType == typeof(float))
|
||||
{
|
||||
return (float)i;
|
||||
}
|
||||
if (targetType == typeof(ulong))
|
||||
{
|
||||
return (ulong)i;
|
||||
}
|
||||
if (targetType == typeof(bool))
|
||||
{
|
||||
return i != 0;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
return System.Convert.ChangeType((long)i, targetType, CultureInfo.InvariantCulture);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new InvalidOperationException("Can not convert from BigInteger to {0}.".FormatWith(CultureInfo.InvariantCulture, targetType), ex);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#region TryConvert
|
||||
internal enum ConvertResult
|
||||
{
|
||||
Success = 0,
|
||||
CannotConvertNull = 1,
|
||||
NotInstantiableType = 2,
|
||||
NoValidConversion = 3
|
||||
}
|
||||
|
||||
public static object Convert(object initialValue, CultureInfo culture, Type targetType)
|
||||
{
|
||||
object value;
|
||||
switch (TryConvertInternal(initialValue, culture, targetType, out value))
|
||||
{
|
||||
case ConvertResult.Success:
|
||||
return value;
|
||||
case ConvertResult.CannotConvertNull:
|
||||
throw new Exception("Can not convert null {0} into non-nullable {1}.".FormatWith(CultureInfo.InvariantCulture, initialValue.GetType(), targetType));
|
||||
case ConvertResult.NotInstantiableType:
|
||||
throw new ArgumentException("Target type {0} is not a value type or a non-abstract class.".FormatWith(CultureInfo.InvariantCulture, targetType), nameof(targetType));
|
||||
case ConvertResult.NoValidConversion:
|
||||
throw new InvalidOperationException("Can not convert from {0} to {1}.".FormatWith(CultureInfo.InvariantCulture, initialValue.GetType(), targetType));
|
||||
default:
|
||||
throw new InvalidOperationException("Unexpected conversion result.");
|
||||
}
|
||||
}
|
||||
|
||||
private static bool TryConvert(object initialValue, CultureInfo culture, Type targetType, out object value)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (TryConvertInternal(initialValue, culture, targetType, out value) == ConvertResult.Success)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
value = null;
|
||||
return false;
|
||||
}
|
||||
catch
|
||||
{
|
||||
value = null;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private static ConvertResult TryConvertInternal(object initialValue, CultureInfo culture, Type targetType, out object value)
|
||||
{
|
||||
if (initialValue == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(initialValue));
|
||||
}
|
||||
|
||||
if (ReflectionUtils.IsNullableType(targetType))
|
||||
{
|
||||
targetType = Nullable.GetUnderlyingType(targetType);
|
||||
}
|
||||
|
||||
Type initialType = initialValue.GetType();
|
||||
|
||||
if (targetType == initialType)
|
||||
{
|
||||
value = initialValue;
|
||||
return ConvertResult.Success;
|
||||
}
|
||||
|
||||
// use Convert.ChangeType if both types are IConvertible
|
||||
if (ConvertUtils.IsConvertible(initialValue.GetType()) && ConvertUtils.IsConvertible(targetType))
|
||||
{
|
||||
if (targetType.IsEnum())
|
||||
{
|
||||
if (initialValue is string)
|
||||
{
|
||||
value = Enum.Parse(targetType, initialValue.ToString(), true);
|
||||
return ConvertResult.Success;
|
||||
}
|
||||
else if (IsInteger(initialValue))
|
||||
{
|
||||
value = Enum.ToObject(targetType, initialValue);
|
||||
return ConvertResult.Success;
|
||||
}
|
||||
}
|
||||
|
||||
value = System.Convert.ChangeType(initialValue, targetType, culture);
|
||||
return ConvertResult.Success;
|
||||
}
|
||||
|
||||
#if !NET20
|
||||
if (initialValue is DateTime && targetType == typeof(DateTimeOffset))
|
||||
{
|
||||
value = new DateTimeOffset((DateTime)initialValue);
|
||||
return ConvertResult.Success;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (initialValue is byte[] && targetType == typeof(Guid))
|
||||
{
|
||||
value = new Guid((byte[])initialValue);
|
||||
return ConvertResult.Success;
|
||||
}
|
||||
|
||||
if (initialValue is Guid && targetType == typeof(byte[]))
|
||||
{
|
||||
value = ((Guid)initialValue).ToByteArray();
|
||||
return ConvertResult.Success;
|
||||
}
|
||||
|
||||
string s = initialValue as string;
|
||||
if (s != null)
|
||||
{
|
||||
if (targetType == typeof(Guid))
|
||||
{
|
||||
value = new Guid(s);
|
||||
return ConvertResult.Success;
|
||||
}
|
||||
if (targetType == typeof(Uri))
|
||||
{
|
||||
value = new Uri(s, UriKind.RelativeOrAbsolute);
|
||||
return ConvertResult.Success;
|
||||
}
|
||||
if (targetType == typeof(TimeSpan))
|
||||
{
|
||||
value = ParseTimeSpan(s);
|
||||
return ConvertResult.Success;
|
||||
}
|
||||
if (targetType == typeof(byte[]))
|
||||
{
|
||||
value = System.Convert.FromBase64String(s);
|
||||
return ConvertResult.Success;
|
||||
}
|
||||
if (targetType == typeof(Version))
|
||||
{
|
||||
Version result;
|
||||
if (VersionTryParse(s, out result))
|
||||
{
|
||||
value = result;
|
||||
return ConvertResult.Success;
|
||||
}
|
||||
value = null;
|
||||
return ConvertResult.NoValidConversion;
|
||||
}
|
||||
if (typeof(Type).IsAssignableFrom(targetType))
|
||||
{
|
||||
value = Type.GetType(s, true);
|
||||
return ConvertResult.Success;
|
||||
}
|
||||
}
|
||||
|
||||
#if !(NET20 || NET35 || PORTABLE40 || PORTABLE)
|
||||
if (targetType == typeof(BigInteger))
|
||||
{
|
||||
value = ToBigInteger(initialValue);
|
||||
return ConvertResult.Success;
|
||||
}
|
||||
if (initialValue is BigInteger)
|
||||
{
|
||||
value = FromBigInteger((BigInteger)initialValue, targetType);
|
||||
return ConvertResult.Success;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !(PORTABLE40 || PORTABLE)
|
||||
// see if source or target types have a TypeConverter that converts between the two
|
||||
TypeConverter toConverter = GetConverter(initialType);
|
||||
|
||||
if (toConverter != null && toConverter.CanConvertTo(targetType))
|
||||
{
|
||||
value = toConverter.ConvertTo(null, culture, initialValue, targetType);
|
||||
return ConvertResult.Success;
|
||||
}
|
||||
|
||||
TypeConverter fromConverter = GetConverter(targetType);
|
||||
|
||||
if (fromConverter != null && fromConverter.CanConvertFrom(initialType))
|
||||
{
|
||||
value = fromConverter.ConvertFrom(null, culture, initialValue);
|
||||
return ConvertResult.Success;
|
||||
}
|
||||
#endif
|
||||
#if !(DOTNET || PORTABLE40 || PORTABLE)
|
||||
// handle DBNull and INullable
|
||||
if (initialValue == DBNull.Value)
|
||||
{
|
||||
if (ReflectionUtils.IsNullable(targetType))
|
||||
{
|
||||
value = EnsureTypeAssignable(null, initialType, targetType);
|
||||
return ConvertResult.Success;
|
||||
}
|
||||
|
||||
// cannot convert null to non-nullable
|
||||
value = null;
|
||||
return ConvertResult.CannotConvertNull;
|
||||
}
|
||||
#endif
|
||||
#if !(DOTNET || PORTABLE40 || PORTABLE)
|
||||
if (initialValue is INullable)
|
||||
{
|
||||
value = EnsureTypeAssignable(ToValue((INullable)initialValue), initialType, targetType);
|
||||
return ConvertResult.Success;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (targetType.IsInterface() || targetType.IsGenericTypeDefinition() || targetType.IsAbstract())
|
||||
{
|
||||
value = null;
|
||||
return ConvertResult.NotInstantiableType;
|
||||
}
|
||||
|
||||
value = null;
|
||||
return ConvertResult.NoValidConversion;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region ConvertOrCast
|
||||
/// <summary>
|
||||
/// Converts the value to the specified type. If the value is unable to be converted, the
|
||||
/// value is checked whether it assignable to the specified type.
|
||||
/// </summary>
|
||||
/// <param name="initialValue">The value to convert.</param>
|
||||
/// <param name="culture">The culture to use when converting.</param>
|
||||
/// <param name="targetType">The type to convert or cast the value to.</param>
|
||||
/// <returns>
|
||||
/// The converted type. If conversion was unsuccessful, the initial value
|
||||
/// is returned if assignable to the target type.
|
||||
/// </returns>
|
||||
public static object ConvertOrCast(object initialValue, CultureInfo culture, Type targetType)
|
||||
{
|
||||
object convertedValue;
|
||||
|
||||
if (targetType == typeof(object))
|
||||
{
|
||||
return initialValue;
|
||||
}
|
||||
|
||||
if (initialValue == null && ReflectionUtils.IsNullable(targetType))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
if (TryConvert(initialValue, culture, targetType, out convertedValue))
|
||||
{
|
||||
return convertedValue;
|
||||
}
|
||||
|
||||
return EnsureTypeAssignable(initialValue, ReflectionUtils.GetObjectType(initialValue), targetType);
|
||||
}
|
||||
#endregion
|
||||
|
||||
private static object EnsureTypeAssignable(object value, Type initialType, Type targetType)
|
||||
{
|
||||
Type valueType = (value != null) ? value.GetType() : null;
|
||||
|
||||
if (value != null)
|
||||
{
|
||||
if (targetType.IsAssignableFrom(valueType))
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
||||
Func<object, object> castConverter = CastConverters.Get(new TypeConvertKey(valueType, targetType));
|
||||
if (castConverter != null)
|
||||
{
|
||||
return castConverter(value);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ReflectionUtils.IsNullable(targetType))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
throw new ArgumentException("Could not cast or convert from {0} to {1}.".FormatWith(CultureInfo.InvariantCulture, (initialType != null) ? initialType.ToString() : "{null}", targetType));
|
||||
}
|
||||
|
||||
#if !(DOTNET || PORTABLE40 || PORTABLE)
|
||||
public static object ToValue(INullable nullableValue)
|
||||
{
|
||||
if (nullableValue == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
else if (nullableValue is SqlInt32)
|
||||
{
|
||||
return ToValue((SqlInt32)nullableValue);
|
||||
}
|
||||
else if (nullableValue is SqlInt64)
|
||||
{
|
||||
return ToValue((SqlInt64)nullableValue);
|
||||
}
|
||||
else if (nullableValue is SqlBoolean)
|
||||
{
|
||||
return ToValue((SqlBoolean)nullableValue);
|
||||
}
|
||||
else if (nullableValue is SqlString)
|
||||
{
|
||||
return ToValue((SqlString)nullableValue);
|
||||
}
|
||||
else if (nullableValue is SqlDateTime)
|
||||
{
|
||||
return ToValue((SqlDateTime)nullableValue);
|
||||
}
|
||||
|
||||
throw new ArgumentException("Unsupported INullable type: {0}".FormatWith(CultureInfo.InvariantCulture, nullableValue.GetType()));
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !(PORTABLE40 || PORTABLE)
|
||||
internal static TypeConverter GetConverter(Type t)
|
||||
{
|
||||
return JsonTypeReflector.GetTypeConverter(t);
|
||||
}
|
||||
#endif
|
||||
|
||||
public static bool VersionTryParse(string input, out Version result)
|
||||
{
|
||||
#if !(NET20 || NET35)
|
||||
return Version.TryParse(input, out result);
|
||||
#else
|
||||
// improve failure performance with regex?
|
||||
try
|
||||
{
|
||||
result = new Version(input);
|
||||
return true;
|
||||
}
|
||||
catch
|
||||
{
|
||||
result = null;
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
public static bool IsInteger(object value)
|
||||
{
|
||||
switch (GetTypeCode(value.GetType()))
|
||||
{
|
||||
case PrimitiveTypeCode.SByte:
|
||||
case PrimitiveTypeCode.Byte:
|
||||
case PrimitiveTypeCode.Int16:
|
||||
case PrimitiveTypeCode.UInt16:
|
||||
case PrimitiveTypeCode.Int32:
|
||||
case PrimitiveTypeCode.UInt32:
|
||||
case PrimitiveTypeCode.Int64:
|
||||
case PrimitiveTypeCode.UInt64:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static ParseResult Int32TryParse(char[] chars, int start, int length, out int value)
|
||||
{
|
||||
value = 0;
|
||||
|
||||
if (length == 0)
|
||||
{
|
||||
return ParseResult.Invalid;
|
||||
}
|
||||
|
||||
bool isNegative = (chars[start] == '-');
|
||||
|
||||
if (isNegative)
|
||||
{
|
||||
// text just a negative sign
|
||||
if (length == 1)
|
||||
{
|
||||
return ParseResult.Invalid;
|
||||
}
|
||||
|
||||
start++;
|
||||
length--;
|
||||
}
|
||||
|
||||
int end = start + length;
|
||||
|
||||
// Int32.MaxValue and MinValue are 10 chars
|
||||
// Or is 10 chars and start is greater than two
|
||||
// Need to improve this!
|
||||
if (length > 10 || (length == 10 && chars[start] - '0' > 2))
|
||||
{
|
||||
// invalid result takes precedence over overflow
|
||||
for (int i = start; i < end; i++)
|
||||
{
|
||||
int c = chars[i] - '0';
|
||||
|
||||
if (c < 0 || c > 9)
|
||||
{
|
||||
return ParseResult.Invalid;
|
||||
}
|
||||
}
|
||||
|
||||
return ParseResult.Overflow;
|
||||
}
|
||||
|
||||
for (int i = start; i < end; i++)
|
||||
{
|
||||
int c = chars[i] - '0';
|
||||
|
||||
if (c < 0 || c > 9)
|
||||
{
|
||||
return ParseResult.Invalid;
|
||||
}
|
||||
|
||||
int newValue = (10 * value) - c;
|
||||
|
||||
// overflow has caused the number to loop around
|
||||
if (newValue > value)
|
||||
{
|
||||
i++;
|
||||
|
||||
// double check the rest of the string that there wasn't anything invalid
|
||||
// invalid result takes precedence over overflow result
|
||||
for (; i < end; i++)
|
||||
{
|
||||
c = chars[i] - '0';
|
||||
|
||||
if (c < 0 || c > 9)
|
||||
{
|
||||
return ParseResult.Invalid;
|
||||
}
|
||||
}
|
||||
|
||||
return ParseResult.Overflow;
|
||||
}
|
||||
|
||||
value = newValue;
|
||||
}
|
||||
|
||||
// go from negative to positive to avoids overflow
|
||||
// negative can be slightly bigger than positive
|
||||
if (!isNegative)
|
||||
{
|
||||
// negative integer can be one bigger than positive
|
||||
if (value == int.MinValue)
|
||||
{
|
||||
return ParseResult.Overflow;
|
||||
}
|
||||
|
||||
value = -value;
|
||||
}
|
||||
|
||||
return ParseResult.Success;
|
||||
}
|
||||
|
||||
public static ParseResult Int64TryParse(char[] chars, int start, int length, out long value)
|
||||
{
|
||||
value = 0;
|
||||
|
||||
if (length == 0)
|
||||
{
|
||||
return ParseResult.Invalid;
|
||||
}
|
||||
|
||||
bool isNegative = (chars[start] == '-');
|
||||
|
||||
if (isNegative)
|
||||
{
|
||||
// text just a negative sign
|
||||
if (length == 1)
|
||||
{
|
||||
return ParseResult.Invalid;
|
||||
}
|
||||
|
||||
start++;
|
||||
length--;
|
||||
}
|
||||
|
||||
int end = start + length;
|
||||
|
||||
// Int64.MaxValue and MinValue are 19 chars
|
||||
if (length > 19)
|
||||
{
|
||||
// invalid result takes precedence over overflow
|
||||
for (int i = start; i < end; i++)
|
||||
{
|
||||
int c = chars[i] - '0';
|
||||
|
||||
if (c < 0 || c > 9)
|
||||
{
|
||||
return ParseResult.Invalid;
|
||||
}
|
||||
}
|
||||
|
||||
return ParseResult.Overflow;
|
||||
}
|
||||
|
||||
for (int i = start; i < end; i++)
|
||||
{
|
||||
int c = chars[i] - '0';
|
||||
|
||||
if (c < 0 || c > 9)
|
||||
{
|
||||
return ParseResult.Invalid;
|
||||
}
|
||||
|
||||
long newValue = (10 * value) - c;
|
||||
|
||||
// overflow has caused the number to loop around
|
||||
if (newValue > value)
|
||||
{
|
||||
i++;
|
||||
|
||||
// double check the rest of the string that there wasn't anything invalid
|
||||
// invalid result takes precedence over overflow result
|
||||
for (; i < end; i++)
|
||||
{
|
||||
c = chars[i] - '0';
|
||||
|
||||
if (c < 0 || c > 9)
|
||||
{
|
||||
return ParseResult.Invalid;
|
||||
}
|
||||
}
|
||||
|
||||
return ParseResult.Overflow;
|
||||
}
|
||||
|
||||
value = newValue;
|
||||
}
|
||||
|
||||
// go from negative to positive to avoids overflow
|
||||
// negative can be slightly bigger than positive
|
||||
if (!isNegative)
|
||||
{
|
||||
// negative integer can be one bigger than positive
|
||||
if (value == long.MinValue)
|
||||
{
|
||||
return ParseResult.Overflow;
|
||||
}
|
||||
|
||||
value = -value;
|
||||
}
|
||||
|
||||
return ParseResult.Success;
|
||||
}
|
||||
|
||||
public static bool TryConvertGuid(string s, out Guid g)
|
||||
{
|
||||
// GUID has to have format 00000000-0000-0000-0000-000000000000
|
||||
#if NET20 || NET35
|
||||
if (s == null)
|
||||
{
|
||||
throw new ArgumentNullException("s");
|
||||
}
|
||||
|
||||
Regex format = new Regex("^[A-Fa-f0-9]{8}-([A-Fa-f0-9]{4}-){3}[A-Fa-f0-9]{12}$");
|
||||
Match match = format.Match(s);
|
||||
if (match.Success)
|
||||
{
|
||||
g = new Guid(s);
|
||||
return true;
|
||||
}
|
||||
|
||||
g = Guid.Empty;
|
||||
return false;
|
||||
#else
|
||||
return Guid.TryParseExact(s, "D", out g);
|
||||
#endif
|
||||
}
|
||||
|
||||
public static int HexTextToInt(char[] text, int start, int end)
|
||||
{
|
||||
int value = 0;
|
||||
for (int i = start; i < end; i++)
|
||||
{
|
||||
value += HexCharToInt(text[i]) << ((end - 1 - i) * 4);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
private static int HexCharToInt(char ch)
|
||||
{
|
||||
if (ch <= 57 && ch >= 48)
|
||||
{
|
||||
return ch - 48;
|
||||
}
|
||||
|
||||
if (ch <= 70 && ch >= 65)
|
||||
{
|
||||
return ch - 55;
|
||||
}
|
||||
|
||||
if (ch <= 102 && ch >= 97)
|
||||
{
|
||||
return ch - 87;
|
||||
}
|
||||
|
||||
throw new FormatException("Invalid hex character: " + ch);
|
||||
}
|
||||
}
|
||||
}
|
||||
277
Common/00-1Json8.3/Json8.3/Utilities/DateTimeParser.cs
Normal file
277
Common/00-1Json8.3/Json8.3/Utilities/DateTimeParser.cs
Normal file
@@ -0,0 +1,277 @@
|
||||
#region License
|
||||
// Copyright (c) 2007 James Newton-King
|
||||
//
|
||||
// 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;
|
||||
|
||||
namespace Newtonsoft.Json.Utilities
|
||||
{
|
||||
internal enum ParserTimeZone
|
||||
{
|
||||
Unspecified = 0,
|
||||
Utc = 1,
|
||||
LocalWestOfUtc = 2,
|
||||
LocalEastOfUtc = 3
|
||||
}
|
||||
|
||||
internal struct DateTimeParser
|
||||
{
|
||||
static DateTimeParser()
|
||||
{
|
||||
Power10 = new[] { -1, 10, 100, 1000, 10000, 100000, 1000000 };
|
||||
|
||||
Lzyyyy = "yyyy".Length;
|
||||
Lzyyyy_ = "yyyy-".Length;
|
||||
Lzyyyy_MM = "yyyy-MM".Length;
|
||||
Lzyyyy_MM_ = "yyyy-MM-".Length;
|
||||
Lzyyyy_MM_dd = "yyyy-MM-dd".Length;
|
||||
Lzyyyy_MM_ddT = "yyyy-MM-ddT".Length;
|
||||
LzHH = "HH".Length;
|
||||
LzHH_ = "HH:".Length;
|
||||
LzHH_mm = "HH:mm".Length;
|
||||
LzHH_mm_ = "HH:mm:".Length;
|
||||
LzHH_mm_ss = "HH:mm:ss".Length;
|
||||
Lz_ = "-".Length;
|
||||
Lz_zz = "-zz".Length;
|
||||
}
|
||||
|
||||
public int Year;
|
||||
public int Month;
|
||||
public int Day;
|
||||
public int Hour;
|
||||
public int Minute;
|
||||
public int Second;
|
||||
public int Fraction;
|
||||
public int ZoneHour;
|
||||
public int ZoneMinute;
|
||||
public ParserTimeZone Zone;
|
||||
|
||||
private char[] _text;
|
||||
private int _end;
|
||||
|
||||
private static readonly int[] Power10;
|
||||
|
||||
private static readonly int Lzyyyy;
|
||||
private static readonly int Lzyyyy_;
|
||||
private static readonly int Lzyyyy_MM;
|
||||
private static readonly int Lzyyyy_MM_;
|
||||
private static readonly int Lzyyyy_MM_dd;
|
||||
private static readonly int Lzyyyy_MM_ddT;
|
||||
private static readonly int LzHH;
|
||||
private static readonly int LzHH_;
|
||||
private static readonly int LzHH_mm;
|
||||
private static readonly int LzHH_mm_;
|
||||
private static readonly int LzHH_mm_ss;
|
||||
private static readonly int Lz_;
|
||||
private static readonly int Lz_zz;
|
||||
|
||||
private const short MaxFractionDigits = 7;
|
||||
|
||||
public bool Parse(char[] text, int startIndex, int length)
|
||||
{
|
||||
_text = text;
|
||||
_end = startIndex + length;
|
||||
|
||||
if (ParseDate(startIndex) && ParseChar(Lzyyyy_MM_dd + startIndex, 'T') && ParseTimeAndZoneAndWhitespace(Lzyyyy_MM_ddT + startIndex))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private bool ParseDate(int start)
|
||||
{
|
||||
return (Parse4Digit(start, out Year)
|
||||
&& 1 <= Year
|
||||
&& ParseChar(start + Lzyyyy, '-')
|
||||
&& Parse2Digit(start + Lzyyyy_, out Month)
|
||||
&& 1 <= Month
|
||||
&& Month <= 12
|
||||
&& ParseChar(start + Lzyyyy_MM, '-')
|
||||
&& Parse2Digit(start + Lzyyyy_MM_, out Day)
|
||||
&& 1 <= Day
|
||||
&& Day <= DateTime.DaysInMonth(Year, Month));
|
||||
}
|
||||
|
||||
private bool ParseTimeAndZoneAndWhitespace(int start)
|
||||
{
|
||||
return (ParseTime(ref start) && ParseZone(start));
|
||||
}
|
||||
|
||||
private bool ParseTime(ref int start)
|
||||
{
|
||||
if (!(Parse2Digit(start, out Hour)
|
||||
&& Hour <= 24
|
||||
&& ParseChar(start + LzHH, ':')
|
||||
&& Parse2Digit(start + LzHH_, out Minute)
|
||||
&& Minute < 60
|
||||
&& ParseChar(start + LzHH_mm, ':')
|
||||
&& Parse2Digit(start + LzHH_mm_, out Second)
|
||||
&& Second < 60
|
||||
&& (Hour != 24 || (Minute == 0 && Second == 0)))) // hour can be 24 if minute/second is zero)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
start += LzHH_mm_ss;
|
||||
if (ParseChar(start, '.'))
|
||||
{
|
||||
Fraction = 0;
|
||||
int numberOfDigits = 0;
|
||||
|
||||
while (++start < _end && numberOfDigits < MaxFractionDigits)
|
||||
{
|
||||
int digit = _text[start] - '0';
|
||||
if (digit < 0 || digit > 9)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
Fraction = (Fraction * 10) + digit;
|
||||
|
||||
numberOfDigits++;
|
||||
}
|
||||
|
||||
if (numberOfDigits < MaxFractionDigits)
|
||||
{
|
||||
if (numberOfDigits == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
Fraction *= Power10[MaxFractionDigits - numberOfDigits];
|
||||
}
|
||||
|
||||
if (Hour == 24 && Fraction != 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private bool ParseZone(int start)
|
||||
{
|
||||
if (start < _end)
|
||||
{
|
||||
char ch = _text[start];
|
||||
if (ch == 'Z' || ch == 'z')
|
||||
{
|
||||
Zone = ParserTimeZone.Utc;
|
||||
start++;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (start + 2 < _end
|
||||
&& Parse2Digit(start + Lz_, out ZoneHour)
|
||||
&& ZoneHour <= 99)
|
||||
{
|
||||
switch (ch)
|
||||
{
|
||||
case '-':
|
||||
Zone = ParserTimeZone.LocalWestOfUtc;
|
||||
start += Lz_zz;
|
||||
break;
|
||||
|
||||
case '+':
|
||||
Zone = ParserTimeZone.LocalEastOfUtc;
|
||||
start += Lz_zz;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (start < _end)
|
||||
{
|
||||
if (ParseChar(start, ':'))
|
||||
{
|
||||
start += 1;
|
||||
|
||||
if (start + 1 < _end
|
||||
&& Parse2Digit(start, out ZoneMinute)
|
||||
&& ZoneMinute <= 99)
|
||||
{
|
||||
start += 2;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (start + 1 < _end
|
||||
&& Parse2Digit(start, out ZoneMinute)
|
||||
&& ZoneMinute <= 99)
|
||||
{
|
||||
start += 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (start == _end);
|
||||
}
|
||||
|
||||
private bool Parse4Digit(int start, out int num)
|
||||
{
|
||||
if (start + 3 < _end)
|
||||
{
|
||||
int digit1 = _text[start] - '0';
|
||||
int digit2 = _text[start + 1] - '0';
|
||||
int digit3 = _text[start + 2] - '0';
|
||||
int digit4 = _text[start + 3] - '0';
|
||||
if (0 <= digit1 && digit1 < 10
|
||||
&& 0 <= digit2 && digit2 < 10
|
||||
&& 0 <= digit3 && digit3 < 10
|
||||
&& 0 <= digit4 && digit4 < 10)
|
||||
{
|
||||
num = (((((digit1 * 10) + digit2) * 10) + digit3) * 10) + digit4;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
num = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
private bool Parse2Digit(int start, out int num)
|
||||
{
|
||||
if (start + 1 < _end)
|
||||
{
|
||||
int digit1 = _text[start] - '0';
|
||||
int digit2 = _text[start + 1] - '0';
|
||||
if (0 <= digit1 && digit1 < 10
|
||||
&& 0 <= digit2 && digit2 < 10)
|
||||
{
|
||||
num = (digit1 * 10) + digit2;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
num = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
private bool ParseChar(int start, char ch)
|
||||
{
|
||||
return (start < _end && _text[start] == ch);
|
||||
}
|
||||
}
|
||||
}
|
||||
824
Common/00-1Json8.3/Json8.3/Utilities/DateTimeUtils.cs
Normal file
824
Common/00-1Json8.3/Json8.3/Utilities/DateTimeUtils.cs
Normal file
@@ -0,0 +1,824 @@
|
||||
#region License
|
||||
// Copyright (c) 2007 James Newton-King
|
||||
//
|
||||
// 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.IO;
|
||||
using System.Xml;
|
||||
using System.Globalization;
|
||||
|
||||
namespace Newtonsoft.Json.Utilities
|
||||
{
|
||||
internal static class DateTimeUtils
|
||||
{
|
||||
internal static readonly long InitialJavaScriptDateTicks = 621355968000000000;
|
||||
private const string IsoDateFormat = "yyyy-MM-ddTHH:mm:ss.FFFFFFFK";
|
||||
|
||||
private const int DaysPer100Years = 36524;
|
||||
private const int DaysPer400Years = 146097;
|
||||
private const int DaysPer4Years = 1461;
|
||||
private const int DaysPerYear = 365;
|
||||
private const long TicksPerDay = 864000000000L;
|
||||
private static readonly int[] DaysToMonth365;
|
||||
private static readonly int[] DaysToMonth366;
|
||||
|
||||
static DateTimeUtils()
|
||||
{
|
||||
DaysToMonth365 = new[] { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 };
|
||||
DaysToMonth366 = new[] { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 };
|
||||
}
|
||||
|
||||
public static TimeSpan GetUtcOffset(this DateTime d)
|
||||
{
|
||||
#if NET20
|
||||
return TimeZone.CurrentTimeZone.GetUtcOffset(d);
|
||||
#else
|
||||
return TimeZoneInfo.Local.GetUtcOffset(d);
|
||||
#endif
|
||||
}
|
||||
|
||||
#if !(PORTABLE40 || PORTABLE)
|
||||
public static XmlDateTimeSerializationMode ToSerializationMode(DateTimeKind kind)
|
||||
{
|
||||
switch (kind)
|
||||
{
|
||||
case DateTimeKind.Local:
|
||||
return XmlDateTimeSerializationMode.Local;
|
||||
case DateTimeKind.Unspecified:
|
||||
return XmlDateTimeSerializationMode.Unspecified;
|
||||
case DateTimeKind.Utc:
|
||||
return XmlDateTimeSerializationMode.Utc;
|
||||
default:
|
||||
throw MiscellaneousUtils.CreateArgumentOutOfRangeException("kind", kind, "Unexpected DateTimeKind value.");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
internal static DateTime EnsureDateTime(DateTime value, DateTimeZoneHandling timeZone)
|
||||
{
|
||||
switch (timeZone)
|
||||
{
|
||||
case DateTimeZoneHandling.Local:
|
||||
value = SwitchToLocalTime(value);
|
||||
break;
|
||||
case DateTimeZoneHandling.Utc:
|
||||
value = SwitchToUtcTime(value);
|
||||
break;
|
||||
case DateTimeZoneHandling.Unspecified:
|
||||
value = new DateTime(value.Ticks, DateTimeKind.Unspecified);
|
||||
break;
|
||||
case DateTimeZoneHandling.RoundtripKind:
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentException("Invalid date time handling value.");
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
private static DateTime SwitchToLocalTime(DateTime value)
|
||||
{
|
||||
switch (value.Kind)
|
||||
{
|
||||
case DateTimeKind.Unspecified:
|
||||
return new DateTime(value.Ticks, DateTimeKind.Local);
|
||||
|
||||
case DateTimeKind.Utc:
|
||||
return value.ToLocalTime();
|
||||
|
||||
case DateTimeKind.Local:
|
||||
return value;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
private static DateTime SwitchToUtcTime(DateTime value)
|
||||
{
|
||||
switch (value.Kind)
|
||||
{
|
||||
case DateTimeKind.Unspecified:
|
||||
return new DateTime(value.Ticks, DateTimeKind.Utc);
|
||||
|
||||
case DateTimeKind.Utc:
|
||||
return value;
|
||||
|
||||
case DateTimeKind.Local:
|
||||
return value.ToUniversalTime();
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
private static long ToUniversalTicks(DateTime dateTime)
|
||||
{
|
||||
if (dateTime.Kind == DateTimeKind.Utc)
|
||||
{
|
||||
return dateTime.Ticks;
|
||||
}
|
||||
|
||||
return ToUniversalTicks(dateTime, dateTime.GetUtcOffset());
|
||||
}
|
||||
|
||||
private static long ToUniversalTicks(DateTime dateTime, TimeSpan offset)
|
||||
{
|
||||
// special case min and max value
|
||||
// they never have a timezone appended to avoid issues
|
||||
if (dateTime.Kind == DateTimeKind.Utc || dateTime == DateTime.MaxValue || dateTime == DateTime.MinValue)
|
||||
{
|
||||
return dateTime.Ticks;
|
||||
}
|
||||
|
||||
long ticks = dateTime.Ticks - offset.Ticks;
|
||||
if (ticks > 3155378975999999999L)
|
||||
{
|
||||
return 3155378975999999999L;
|
||||
}
|
||||
|
||||
if (ticks < 0L)
|
||||
{
|
||||
return 0L;
|
||||
}
|
||||
|
||||
return ticks;
|
||||
}
|
||||
|
||||
internal static long ConvertDateTimeToJavaScriptTicks(DateTime dateTime, TimeSpan offset)
|
||||
{
|
||||
long universialTicks = ToUniversalTicks(dateTime, offset);
|
||||
|
||||
return UniversialTicksToJavaScriptTicks(universialTicks);
|
||||
}
|
||||
|
||||
internal static long ConvertDateTimeToJavaScriptTicks(DateTime dateTime)
|
||||
{
|
||||
return ConvertDateTimeToJavaScriptTicks(dateTime, true);
|
||||
}
|
||||
|
||||
internal static long ConvertDateTimeToJavaScriptTicks(DateTime dateTime, bool convertToUtc)
|
||||
{
|
||||
long ticks = (convertToUtc) ? ToUniversalTicks(dateTime) : dateTime.Ticks;
|
||||
|
||||
return UniversialTicksToJavaScriptTicks(ticks);
|
||||
}
|
||||
|
||||
private static long UniversialTicksToJavaScriptTicks(long universialTicks)
|
||||
{
|
||||
long javaScriptTicks = (universialTicks - InitialJavaScriptDateTicks) / 10000;
|
||||
|
||||
return javaScriptTicks;
|
||||
}
|
||||
|
||||
internal static DateTime ConvertJavaScriptTicksToDateTime(long javaScriptTicks)
|
||||
{
|
||||
DateTime dateTime = new DateTime((javaScriptTicks * 10000) + InitialJavaScriptDateTicks, DateTimeKind.Utc);
|
||||
|
||||
return dateTime;
|
||||
}
|
||||
|
||||
#region Parse
|
||||
internal static bool TryParseDateTimeIso(StringReference text, DateTimeZoneHandling dateTimeZoneHandling, out DateTime dt)
|
||||
{
|
||||
DateTimeParser dateTimeParser = new DateTimeParser();
|
||||
if (!dateTimeParser.Parse(text.Chars, text.StartIndex, text.Length))
|
||||
{
|
||||
dt = default(DateTime);
|
||||
return false;
|
||||
}
|
||||
|
||||
DateTime d = CreateDateTime(dateTimeParser);
|
||||
|
||||
long ticks;
|
||||
|
||||
switch (dateTimeParser.Zone)
|
||||
{
|
||||
case ParserTimeZone.Utc:
|
||||
d = new DateTime(d.Ticks, DateTimeKind.Utc);
|
||||
break;
|
||||
|
||||
case ParserTimeZone.LocalWestOfUtc:
|
||||
{
|
||||
TimeSpan offset = new TimeSpan(dateTimeParser.ZoneHour, dateTimeParser.ZoneMinute, 0);
|
||||
ticks = d.Ticks + offset.Ticks;
|
||||
if (ticks <= DateTime.MaxValue.Ticks)
|
||||
{
|
||||
d = new DateTime(ticks, DateTimeKind.Utc).ToLocalTime();
|
||||
}
|
||||
else
|
||||
{
|
||||
ticks += d.GetUtcOffset().Ticks;
|
||||
if (ticks > DateTime.MaxValue.Ticks)
|
||||
{
|
||||
ticks = DateTime.MaxValue.Ticks;
|
||||
}
|
||||
|
||||
d = new DateTime(ticks, DateTimeKind.Local);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ParserTimeZone.LocalEastOfUtc:
|
||||
{
|
||||
TimeSpan offset = new TimeSpan(dateTimeParser.ZoneHour, dateTimeParser.ZoneMinute, 0);
|
||||
ticks = d.Ticks - offset.Ticks;
|
||||
if (ticks >= DateTime.MinValue.Ticks)
|
||||
{
|
||||
d = new DateTime(ticks, DateTimeKind.Utc).ToLocalTime();
|
||||
}
|
||||
else
|
||||
{
|
||||
ticks += d.GetUtcOffset().Ticks;
|
||||
if (ticks < DateTime.MinValue.Ticks)
|
||||
{
|
||||
ticks = DateTime.MinValue.Ticks;
|
||||
}
|
||||
|
||||
d = new DateTime(ticks, DateTimeKind.Local);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
dt = EnsureDateTime(d, dateTimeZoneHandling);
|
||||
return true;
|
||||
}
|
||||
|
||||
#if !NET20
|
||||
internal static bool TryParseDateTimeOffsetIso(StringReference text, out DateTimeOffset dt)
|
||||
{
|
||||
DateTimeParser dateTimeParser = new DateTimeParser();
|
||||
if (!dateTimeParser.Parse(text.Chars, text.StartIndex, text.Length))
|
||||
{
|
||||
dt = default(DateTimeOffset);
|
||||
return false;
|
||||
}
|
||||
|
||||
DateTime d = CreateDateTime(dateTimeParser);
|
||||
|
||||
TimeSpan offset;
|
||||
|
||||
switch (dateTimeParser.Zone)
|
||||
{
|
||||
case ParserTimeZone.Utc:
|
||||
offset = new TimeSpan(0L);
|
||||
break;
|
||||
case ParserTimeZone.LocalWestOfUtc:
|
||||
offset = new TimeSpan(-dateTimeParser.ZoneHour, -dateTimeParser.ZoneMinute, 0);
|
||||
break;
|
||||
case ParserTimeZone.LocalEastOfUtc:
|
||||
offset = new TimeSpan(dateTimeParser.ZoneHour, dateTimeParser.ZoneMinute, 0);
|
||||
break;
|
||||
default:
|
||||
offset = TimeZoneInfo.Local.GetUtcOffset(d);
|
||||
break;
|
||||
}
|
||||
|
||||
long ticks = d.Ticks - offset.Ticks;
|
||||
if (ticks < 0 || ticks > 3155378975999999999)
|
||||
{
|
||||
dt = default(DateTimeOffset);
|
||||
return false;
|
||||
}
|
||||
|
||||
dt = new DateTimeOffset(d, offset);
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
private static DateTime CreateDateTime(DateTimeParser dateTimeParser)
|
||||
{
|
||||
bool is24Hour;
|
||||
if (dateTimeParser.Hour == 24)
|
||||
{
|
||||
is24Hour = true;
|
||||
dateTimeParser.Hour = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
is24Hour = false;
|
||||
}
|
||||
|
||||
DateTime d = new DateTime(dateTimeParser.Year, dateTimeParser.Month, dateTimeParser.Day, dateTimeParser.Hour, dateTimeParser.Minute, dateTimeParser.Second);
|
||||
d = d.AddTicks(dateTimeParser.Fraction);
|
||||
|
||||
if (is24Hour)
|
||||
{
|
||||
d = d.AddDays(1);
|
||||
}
|
||||
return d;
|
||||
}
|
||||
|
||||
internal static bool TryParseDateTime(StringReference s, DateTimeZoneHandling dateTimeZoneHandling, string dateFormatString, CultureInfo culture, out DateTime dt)
|
||||
{
|
||||
if (s.Length > 0)
|
||||
{
|
||||
int i = s.StartIndex;
|
||||
if (s[i] == '/')
|
||||
{
|
||||
if (s.Length >= 9 && s.StartsWith("/Date(") && s.EndsWith(")/"))
|
||||
{
|
||||
if (TryParseDateTimeMicrosoft(s, dateTimeZoneHandling, out dt))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (s.Length >= 19 && s.Length <= 40 && char.IsDigit(s[i]) && s[i + 10] == 'T')
|
||||
{
|
||||
if (TryParseDateTimeIso(s, dateTimeZoneHandling, out dt))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(dateFormatString))
|
||||
{
|
||||
if (TryParseDateTimeExact(s.ToString(), dateTimeZoneHandling, dateFormatString, culture, out dt))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dt = default(DateTime);
|
||||
return false;
|
||||
}
|
||||
|
||||
internal static bool TryParseDateTime(string s, DateTimeZoneHandling dateTimeZoneHandling, string dateFormatString, CultureInfo culture, out DateTime dt)
|
||||
{
|
||||
if (s.Length > 0)
|
||||
{
|
||||
if (s[0] == '/')
|
||||
{
|
||||
if (s.Length >= 9 && s.StartsWith("/Date(", StringComparison.Ordinal) && s.EndsWith(")/", StringComparison.Ordinal))
|
||||
{
|
||||
if (TryParseDateTimeMicrosoft(new StringReference(s.ToCharArray(), 0, s.Length), dateTimeZoneHandling, out dt))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (s.Length >= 19 && s.Length <= 40 && char.IsDigit(s[0]) && s[10] == 'T')
|
||||
{
|
||||
if (DateTime.TryParseExact(s, IsoDateFormat, CultureInfo.InvariantCulture, DateTimeStyles.RoundtripKind, out dt))
|
||||
{
|
||||
dt = EnsureDateTime(dt, dateTimeZoneHandling);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(dateFormatString))
|
||||
{
|
||||
if (TryParseDateTimeExact(s, dateTimeZoneHandling, dateFormatString, culture, out dt))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dt = default(DateTime);
|
||||
return false;
|
||||
}
|
||||
|
||||
#if !NET20
|
||||
internal static bool TryParseDateTimeOffset(StringReference s, string dateFormatString, CultureInfo culture, out DateTimeOffset dt)
|
||||
{
|
||||
if (s.Length > 0)
|
||||
{
|
||||
int i = s.StartIndex;
|
||||
if (s[i] == '/')
|
||||
{
|
||||
if (s.Length >= 9 && s.StartsWith("/Date(") && s.EndsWith(")/"))
|
||||
{
|
||||
if (TryParseDateTimeOffsetMicrosoft(s, out dt))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (s.Length >= 19 && s.Length <= 40 && char.IsDigit(s[i]) && s[i + 10] == 'T')
|
||||
{
|
||||
if (TryParseDateTimeOffsetIso(s, out dt))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(dateFormatString))
|
||||
{
|
||||
if (TryParseDateTimeOffsetExact(s.ToString(), dateFormatString, culture, out dt))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dt = default(DateTimeOffset);
|
||||
return false;
|
||||
}
|
||||
|
||||
internal static bool TryParseDateTimeOffset(string s, string dateFormatString, CultureInfo culture, out DateTimeOffset dt)
|
||||
{
|
||||
if (s.Length > 0)
|
||||
{
|
||||
if (s[0] == '/')
|
||||
{
|
||||
if (s.Length >= 9 && s.StartsWith("/Date(", StringComparison.Ordinal) && s.EndsWith(")/", StringComparison.Ordinal))
|
||||
{
|
||||
if (TryParseDateTimeOffsetMicrosoft(new StringReference(s.ToCharArray(), 0, s.Length), out dt))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (s.Length >= 19 && s.Length <= 40 && char.IsDigit(s[0]) && s[10] == 'T')
|
||||
{
|
||||
if (DateTimeOffset.TryParseExact(s, IsoDateFormat, CultureInfo.InvariantCulture, DateTimeStyles.RoundtripKind, out dt))
|
||||
{
|
||||
if (TryParseDateTimeOffsetIso(new StringReference(s.ToCharArray(), 0, s.Length), out dt))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(dateFormatString))
|
||||
{
|
||||
if (TryParseDateTimeOffsetExact(s, dateFormatString, culture, out dt))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dt = default(DateTimeOffset);
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
private static bool TryParseMicrosoftDate(StringReference text, out long ticks, out TimeSpan offset, out DateTimeKind kind)
|
||||
{
|
||||
kind = DateTimeKind.Utc;
|
||||
|
||||
int index = text.IndexOf('+', 7, text.Length - 8);
|
||||
|
||||
if (index == -1)
|
||||
{
|
||||
index = text.IndexOf('-', 7, text.Length - 8);
|
||||
}
|
||||
|
||||
if (index != -1)
|
||||
{
|
||||
kind = DateTimeKind.Local;
|
||||
|
||||
if (!TryReadOffset(text, index + text.StartIndex, out offset))
|
||||
{
|
||||
ticks = 0;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
offset = TimeSpan.Zero;
|
||||
index = text.Length - 2;
|
||||
}
|
||||
|
||||
return (ConvertUtils.Int64TryParse(text.Chars, 6 + text.StartIndex, index - 6, out ticks) == ParseResult.Success);
|
||||
}
|
||||
|
||||
private static bool TryParseDateTimeMicrosoft(StringReference text, DateTimeZoneHandling dateTimeZoneHandling, out DateTime dt)
|
||||
{
|
||||
long ticks;
|
||||
TimeSpan offset;
|
||||
DateTimeKind kind;
|
||||
|
||||
if (!TryParseMicrosoftDate(text, out ticks, out offset, out kind))
|
||||
{
|
||||
dt = default(DateTime);
|
||||
return false;
|
||||
}
|
||||
|
||||
DateTime utcDateTime = ConvertJavaScriptTicksToDateTime(ticks);
|
||||
|
||||
switch (kind)
|
||||
{
|
||||
case DateTimeKind.Unspecified:
|
||||
dt = DateTime.SpecifyKind(utcDateTime.ToLocalTime(), DateTimeKind.Unspecified);
|
||||
break;
|
||||
case DateTimeKind.Local:
|
||||
dt = utcDateTime.ToLocalTime();
|
||||
break;
|
||||
default:
|
||||
dt = utcDateTime;
|
||||
break;
|
||||
}
|
||||
|
||||
dt = EnsureDateTime(dt, dateTimeZoneHandling);
|
||||
return true;
|
||||
}
|
||||
|
||||
private static bool TryParseDateTimeExact(string text, DateTimeZoneHandling dateTimeZoneHandling, string dateFormatString, CultureInfo culture, out DateTime dt)
|
||||
{
|
||||
DateTime temp;
|
||||
if (DateTime.TryParseExact(text, dateFormatString, culture, DateTimeStyles.RoundtripKind, out temp))
|
||||
{
|
||||
temp = EnsureDateTime(temp, dateTimeZoneHandling);
|
||||
dt = temp;
|
||||
return true;
|
||||
}
|
||||
|
||||
dt = default(DateTime);
|
||||
return false;
|
||||
}
|
||||
|
||||
#if !NET20
|
||||
private static bool TryParseDateTimeOffsetMicrosoft(StringReference text, out DateTimeOffset dt)
|
||||
{
|
||||
long ticks;
|
||||
TimeSpan offset;
|
||||
DateTimeKind kind;
|
||||
|
||||
if (!TryParseMicrosoftDate(text, out ticks, out offset, out kind))
|
||||
{
|
||||
dt = default(DateTime);
|
||||
return false;
|
||||
}
|
||||
|
||||
DateTime utcDateTime = ConvertJavaScriptTicksToDateTime(ticks);
|
||||
|
||||
dt = new DateTimeOffset(utcDateTime.Add(offset).Ticks, offset);
|
||||
return true;
|
||||
}
|
||||
|
||||
private static bool TryParseDateTimeOffsetExact(string text, string dateFormatString, CultureInfo culture, out DateTimeOffset dt)
|
||||
{
|
||||
DateTimeOffset temp;
|
||||
if (DateTimeOffset.TryParseExact(text, dateFormatString, culture, DateTimeStyles.RoundtripKind, out temp))
|
||||
{
|
||||
dt = temp;
|
||||
return true;
|
||||
}
|
||||
|
||||
dt = default(DateTimeOffset);
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
private static bool TryReadOffset(StringReference offsetText, int startIndex, out TimeSpan offset)
|
||||
{
|
||||
bool negative = (offsetText[startIndex] == '-');
|
||||
|
||||
int hours;
|
||||
if (ConvertUtils.Int32TryParse(offsetText.Chars, startIndex + 1, 2, out hours) != ParseResult.Success)
|
||||
{
|
||||
offset = default(TimeSpan);
|
||||
return false;
|
||||
}
|
||||
|
||||
int minutes = 0;
|
||||
if (offsetText.Length - startIndex > 5)
|
||||
{
|
||||
if (ConvertUtils.Int32TryParse(offsetText.Chars, startIndex + 3, 2, out minutes) != ParseResult.Success)
|
||||
{
|
||||
offset = default(TimeSpan);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
offset = TimeSpan.FromHours(hours) + TimeSpan.FromMinutes(minutes);
|
||||
if (negative)
|
||||
{
|
||||
offset = offset.Negate();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Write
|
||||
internal static void WriteDateTimeString(TextWriter writer, DateTime value, DateFormatHandling format, string formatString, CultureInfo culture)
|
||||
{
|
||||
if (string.IsNullOrEmpty(formatString))
|
||||
{
|
||||
char[] chars = new char[64];
|
||||
int pos = WriteDateTimeString(chars, 0, value, null, value.Kind, format);
|
||||
writer.Write(chars, 0, pos);
|
||||
}
|
||||
else
|
||||
{
|
||||
writer.Write(value.ToString(formatString, culture));
|
||||
}
|
||||
}
|
||||
|
||||
internal static int WriteDateTimeString(char[] chars, int start, DateTime value, TimeSpan? offset, DateTimeKind kind, DateFormatHandling format)
|
||||
{
|
||||
int pos = start;
|
||||
|
||||
if (format == DateFormatHandling.MicrosoftDateFormat)
|
||||
{
|
||||
TimeSpan o = offset ?? value.GetUtcOffset();
|
||||
|
||||
long javaScriptTicks = ConvertDateTimeToJavaScriptTicks(value, o);
|
||||
|
||||
@"\/Date(".CopyTo(0, chars, pos, 7);
|
||||
pos += 7;
|
||||
|
||||
string ticksText = javaScriptTicks.ToString(CultureInfo.InvariantCulture);
|
||||
ticksText.CopyTo(0, chars, pos, ticksText.Length);
|
||||
pos += ticksText.Length;
|
||||
|
||||
switch (kind)
|
||||
{
|
||||
case DateTimeKind.Unspecified:
|
||||
if (value != DateTime.MaxValue && value != DateTime.MinValue)
|
||||
{
|
||||
pos = WriteDateTimeOffset(chars, pos, o, format);
|
||||
}
|
||||
break;
|
||||
case DateTimeKind.Local:
|
||||
pos = WriteDateTimeOffset(chars, pos, o, format);
|
||||
break;
|
||||
}
|
||||
|
||||
@")\/".CopyTo(0, chars, pos, 3);
|
||||
pos += 3;
|
||||
}
|
||||
else
|
||||
{
|
||||
pos = WriteDefaultIsoDate(chars, pos, value);
|
||||
|
||||
switch (kind)
|
||||
{
|
||||
case DateTimeKind.Local:
|
||||
pos = WriteDateTimeOffset(chars, pos, offset ?? value.GetUtcOffset(), format);
|
||||
break;
|
||||
case DateTimeKind.Utc:
|
||||
chars[pos++] = 'Z';
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return pos;
|
||||
}
|
||||
|
||||
internal static int WriteDefaultIsoDate(char[] chars, int start, DateTime dt)
|
||||
{
|
||||
int length = 19;
|
||||
|
||||
int year;
|
||||
int month;
|
||||
int day;
|
||||
GetDateValues(dt, out year, out month, out day);
|
||||
|
||||
CopyIntToCharArray(chars, start, year, 4);
|
||||
chars[start + 4] = '-';
|
||||
CopyIntToCharArray(chars, start + 5, month, 2);
|
||||
chars[start + 7] = '-';
|
||||
CopyIntToCharArray(chars, start + 8, day, 2);
|
||||
chars[start + 10] = 'T';
|
||||
CopyIntToCharArray(chars, start + 11, dt.Hour, 2);
|
||||
chars[start + 13] = ':';
|
||||
CopyIntToCharArray(chars, start + 14, dt.Minute, 2);
|
||||
chars[start + 16] = ':';
|
||||
CopyIntToCharArray(chars, start + 17, dt.Second, 2);
|
||||
|
||||
int fraction = (int)(dt.Ticks % 10000000L);
|
||||
|
||||
if (fraction != 0)
|
||||
{
|
||||
int digits = 7;
|
||||
while ((fraction % 10) == 0)
|
||||
{
|
||||
digits--;
|
||||
fraction /= 10;
|
||||
}
|
||||
|
||||
chars[start + 19] = '.';
|
||||
CopyIntToCharArray(chars, start + 20, fraction, digits);
|
||||
|
||||
length += digits + 1;
|
||||
}
|
||||
|
||||
return start + length;
|
||||
}
|
||||
|
||||
private static void CopyIntToCharArray(char[] chars, int start, int value, int digits)
|
||||
{
|
||||
while (digits-- != 0)
|
||||
{
|
||||
chars[start + digits] = (char)((value % 10) + 48);
|
||||
value /= 10;
|
||||
}
|
||||
}
|
||||
|
||||
internal static int WriteDateTimeOffset(char[] chars, int start, TimeSpan offset, DateFormatHandling format)
|
||||
{
|
||||
chars[start++] = (offset.Ticks >= 0L) ? '+' : '-';
|
||||
|
||||
int absHours = Math.Abs(offset.Hours);
|
||||
CopyIntToCharArray(chars, start, absHours, 2);
|
||||
start += 2;
|
||||
|
||||
if (format == DateFormatHandling.IsoDateFormat)
|
||||
{
|
||||
chars[start++] = ':';
|
||||
}
|
||||
|
||||
int absMinutes = Math.Abs(offset.Minutes);
|
||||
CopyIntToCharArray(chars, start, absMinutes, 2);
|
||||
start += 2;
|
||||
|
||||
return start;
|
||||
}
|
||||
|
||||
#if !NET20
|
||||
internal static void WriteDateTimeOffsetString(TextWriter writer, DateTimeOffset value, DateFormatHandling format, string formatString, CultureInfo culture)
|
||||
{
|
||||
if (string.IsNullOrEmpty(formatString))
|
||||
{
|
||||
char[] chars = new char[64];
|
||||
int pos = WriteDateTimeString(chars, 0, (format == DateFormatHandling.IsoDateFormat) ? value.DateTime : value.UtcDateTime, value.Offset, DateTimeKind.Local, format);
|
||||
|
||||
writer.Write(chars, 0, pos);
|
||||
}
|
||||
else
|
||||
{
|
||||
writer.Write(value.ToString(formatString, culture));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endregion
|
||||
|
||||
private static void GetDateValues(DateTime td, out int year, out int month, out int day)
|
||||
{
|
||||
long ticks = td.Ticks;
|
||||
// n = number of days since 1/1/0001
|
||||
int n = (int)(ticks / TicksPerDay);
|
||||
// y400 = number of whole 400-year periods since 1/1/0001
|
||||
int y400 = n / DaysPer400Years;
|
||||
// n = day number within 400-year period
|
||||
n -= y400 * DaysPer400Years;
|
||||
// y100 = number of whole 100-year periods within 400-year period
|
||||
int y100 = n / DaysPer100Years;
|
||||
// Last 100-year period has an extra day, so decrement result if 4
|
||||
if (y100 == 4)
|
||||
{
|
||||
y100 = 3;
|
||||
}
|
||||
// n = day number within 100-year period
|
||||
n -= y100 * DaysPer100Years;
|
||||
// y4 = number of whole 4-year periods within 100-year period
|
||||
int y4 = n / DaysPer4Years;
|
||||
// n = day number within 4-year period
|
||||
n -= y4 * DaysPer4Years;
|
||||
// y1 = number of whole years within 4-year period
|
||||
int y1 = n / DaysPerYear;
|
||||
// Last year has an extra day, so decrement result if 4
|
||||
if (y1 == 4)
|
||||
{
|
||||
y1 = 3;
|
||||
}
|
||||
|
||||
year = y400 * 400 + y100 * 100 + y4 * 4 + y1 + 1;
|
||||
|
||||
// n = day number within year
|
||||
n -= y1 * DaysPerYear;
|
||||
|
||||
// Leap year calculation looks different from IsLeapYear since y1, y4,
|
||||
// and y100 are relative to year 1, not year 0
|
||||
bool leapYear = y1 == 3 && (y4 != 24 || y100 == 3);
|
||||
int[] days = leapYear ? DaysToMonth366 : DaysToMonth365;
|
||||
// All months have less than 32 days, so n >> 5 is a good conservative
|
||||
// estimate for the month
|
||||
int m = n >> 5 + 1;
|
||||
// m = 1-based month number
|
||||
while (n >= days[m])
|
||||
{
|
||||
m++;
|
||||
}
|
||||
|
||||
month = m;
|
||||
|
||||
// Return 1-based day-of-month
|
||||
day = n - days[m - 1] + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
700
Common/00-1Json8.3/Json8.3/Utilities/DictionaryWrapper.cs
Normal file
700
Common/00-1Json8.3/Json8.3/Utilities/DictionaryWrapper.cs
Normal file
@@ -0,0 +1,700 @@
|
||||
#region License
|
||||
// Copyright (c) 2007 James Newton-King
|
||||
//
|
||||
// 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.Collections;
|
||||
using System.Threading;
|
||||
#if NET20
|
||||
using Newtonsoft.Json.Utilities.LinqBridge;
|
||||
#else
|
||||
using System.Linq;
|
||||
|
||||
#endif
|
||||
|
||||
namespace Newtonsoft.Json.Utilities
|
||||
{
|
||||
internal interface IWrappedDictionary
|
||||
: IDictionary
|
||||
{
|
||||
object UnderlyingDictionary { get; }
|
||||
}
|
||||
|
||||
internal class DictionaryWrapper<TKey, TValue> : IDictionary<TKey, TValue>, IWrappedDictionary
|
||||
{
|
||||
private readonly IDictionary _dictionary;
|
||||
private readonly IDictionary<TKey, TValue> _genericDictionary;
|
||||
#if !(NET40 || NET35 || NET20 || PORTABLE40)
|
||||
private readonly IReadOnlyDictionary<TKey, TValue> _readOnlyDictionary;
|
||||
#endif
|
||||
private object _syncRoot;
|
||||
|
||||
public DictionaryWrapper(IDictionary dictionary)
|
||||
{
|
||||
ValidationUtils.ArgumentNotNull(dictionary, nameof(dictionary));
|
||||
|
||||
_dictionary = dictionary;
|
||||
}
|
||||
|
||||
public DictionaryWrapper(IDictionary<TKey, TValue> dictionary)
|
||||
{
|
||||
ValidationUtils.ArgumentNotNull(dictionary, nameof(dictionary));
|
||||
|
||||
_genericDictionary = dictionary;
|
||||
}
|
||||
|
||||
#if !(NET40 || NET35 || NET20 || PORTABLE40)
|
||||
public DictionaryWrapper(IReadOnlyDictionary<TKey, TValue> dictionary)
|
||||
{
|
||||
ValidationUtils.ArgumentNotNull(dictionary, nameof(dictionary));
|
||||
|
||||
_readOnlyDictionary = dictionary;
|
||||
}
|
||||
#endif
|
||||
|
||||
public void Add(TKey key, TValue value)
|
||||
{
|
||||
if (_dictionary != null)
|
||||
{
|
||||
_dictionary.Add(key, value);
|
||||
}
|
||||
else if (_genericDictionary != null)
|
||||
{
|
||||
_genericDictionary.Add(key, value);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
}
|
||||
|
||||
public bool ContainsKey(TKey key)
|
||||
{
|
||||
if (_dictionary != null)
|
||||
{
|
||||
return _dictionary.Contains(key);
|
||||
}
|
||||
#if !(NET40 || NET35 || NET20 || PORTABLE40)
|
||||
else if (_readOnlyDictionary != null)
|
||||
{
|
||||
return _readOnlyDictionary.ContainsKey(key);
|
||||
}
|
||||
#endif
|
||||
else
|
||||
{
|
||||
return _genericDictionary.ContainsKey(key);
|
||||
}
|
||||
}
|
||||
|
||||
public ICollection<TKey> Keys
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_dictionary != null)
|
||||
{
|
||||
return _dictionary.Keys.Cast<TKey>().ToList();
|
||||
}
|
||||
#if !(NET40 || NET35 || NET20 || PORTABLE40)
|
||||
else if (_readOnlyDictionary != null)
|
||||
{
|
||||
return _readOnlyDictionary.Keys.ToList();
|
||||
}
|
||||
#endif
|
||||
else
|
||||
{
|
||||
return _genericDictionary.Keys;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public bool Remove(TKey key)
|
||||
{
|
||||
if (_dictionary != null)
|
||||
{
|
||||
if (_dictionary.Contains(key))
|
||||
{
|
||||
_dictionary.Remove(key);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#if !(NET40 || NET35 || NET20 || PORTABLE40)
|
||||
else if (_readOnlyDictionary != null)
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
#endif
|
||||
else
|
||||
{
|
||||
return _genericDictionary.Remove(key);
|
||||
}
|
||||
}
|
||||
|
||||
public bool TryGetValue(TKey key, out TValue value)
|
||||
{
|
||||
if (_dictionary != null)
|
||||
{
|
||||
if (!_dictionary.Contains(key))
|
||||
{
|
||||
value = default(TValue);
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
value = (TValue)_dictionary[key];
|
||||
return true;
|
||||
}
|
||||
}
|
||||
#if !(NET40 || NET35 || NET20 || PORTABLE40)
|
||||
else if (_readOnlyDictionary != null)
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
#endif
|
||||
else
|
||||
{
|
||||
return _genericDictionary.TryGetValue(key, out value);
|
||||
}
|
||||
}
|
||||
|
||||
public ICollection<TValue> Values
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_dictionary != null)
|
||||
{
|
||||
return _dictionary.Values.Cast<TValue>().ToList();
|
||||
}
|
||||
#if !(NET40 || NET35 || NET20 || PORTABLE40)
|
||||
else if (_readOnlyDictionary != null)
|
||||
{
|
||||
return _readOnlyDictionary.Values.ToList();
|
||||
}
|
||||
#endif
|
||||
else
|
||||
{
|
||||
return _genericDictionary.Values;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public TValue this[TKey key]
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_dictionary != null)
|
||||
{
|
||||
return (TValue)_dictionary[key];
|
||||
}
|
||||
#if !(NET40 || NET35 || NET20 || PORTABLE40)
|
||||
else if (_readOnlyDictionary != null)
|
||||
{
|
||||
return _readOnlyDictionary[key];
|
||||
}
|
||||
#endif
|
||||
else
|
||||
{
|
||||
return _genericDictionary[key];
|
||||
}
|
||||
}
|
||||
set
|
||||
{
|
||||
if (_dictionary != null)
|
||||
{
|
||||
_dictionary[key] = value;
|
||||
}
|
||||
#if !(NET40 || NET35 || NET20 || PORTABLE40)
|
||||
else if (_readOnlyDictionary != null)
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
#endif
|
||||
else
|
||||
{
|
||||
_genericDictionary[key] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Add(KeyValuePair<TKey, TValue> item)
|
||||
{
|
||||
if (_dictionary != null)
|
||||
{
|
||||
((IList)_dictionary).Add(item);
|
||||
}
|
||||
#if !(NET40 || NET35 || NET20 || PORTABLE40)
|
||||
else if (_readOnlyDictionary != null)
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
#endif
|
||||
else if (_genericDictionary != null)
|
||||
{
|
||||
_genericDictionary.Add(item);
|
||||
}
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
if (_dictionary != null)
|
||||
{
|
||||
_dictionary.Clear();
|
||||
}
|
||||
#if !(NET40 || NET35 || NET20 || PORTABLE40)
|
||||
else if (_readOnlyDictionary != null)
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
#endif
|
||||
else
|
||||
{
|
||||
_genericDictionary.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
public bool Contains(KeyValuePair<TKey, TValue> item)
|
||||
{
|
||||
if (_dictionary != null)
|
||||
{
|
||||
return ((IList)_dictionary).Contains(item);
|
||||
}
|
||||
#if !(NET40 || NET35 || NET20 || PORTABLE40)
|
||||
else if (_readOnlyDictionary != null)
|
||||
{
|
||||
return _readOnlyDictionary.Contains(item);
|
||||
}
|
||||
#endif
|
||||
else
|
||||
{
|
||||
return _genericDictionary.Contains(item);
|
||||
}
|
||||
}
|
||||
|
||||
public void CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex)
|
||||
{
|
||||
if (_dictionary != null)
|
||||
{
|
||||
foreach (DictionaryEntry item in _dictionary)
|
||||
{
|
||||
array[arrayIndex++] = new KeyValuePair<TKey, TValue>((TKey)item.Key, (TValue)item.Value);
|
||||
}
|
||||
}
|
||||
#if !(NET40 || NET35 || NET20 || PORTABLE40)
|
||||
else if (_readOnlyDictionary != null)
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
#endif
|
||||
else
|
||||
{
|
||||
_genericDictionary.CopyTo(array, arrayIndex);
|
||||
}
|
||||
}
|
||||
|
||||
public int Count
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_dictionary != null)
|
||||
{
|
||||
return _dictionary.Count;
|
||||
}
|
||||
#if !(NET40 || NET35 || NET20 || PORTABLE40)
|
||||
else if (_readOnlyDictionary != null)
|
||||
{
|
||||
return _readOnlyDictionary.Count;
|
||||
}
|
||||
#endif
|
||||
else
|
||||
{
|
||||
return _genericDictionary.Count;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsReadOnly
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_dictionary != null)
|
||||
{
|
||||
return _dictionary.IsReadOnly;
|
||||
}
|
||||
#if !(NET40 || NET35 || NET20 || PORTABLE40)
|
||||
else if (_readOnlyDictionary != null)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
else
|
||||
{
|
||||
return _genericDictionary.IsReadOnly;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public bool Remove(KeyValuePair<TKey, TValue> item)
|
||||
{
|
||||
if (_dictionary != null)
|
||||
{
|
||||
if (_dictionary.Contains(item.Key))
|
||||
{
|
||||
object value = _dictionary[item.Key];
|
||||
|
||||
if (object.Equals(value, item.Value))
|
||||
{
|
||||
_dictionary.Remove(item.Key);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
#if !(NET40 || NET35 || NET20 || PORTABLE40)
|
||||
else if (_readOnlyDictionary != null)
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
#endif
|
||||
else
|
||||
{
|
||||
return _genericDictionary.Remove(item);
|
||||
}
|
||||
}
|
||||
|
||||
public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
|
||||
{
|
||||
if (_dictionary != null)
|
||||
{
|
||||
return _dictionary.Cast<DictionaryEntry>().Select(de => new KeyValuePair<TKey, TValue>((TKey)de.Key, (TValue)de.Value)).GetEnumerator();
|
||||
}
|
||||
#if !(NET40 || NET35 || NET20 || PORTABLE40)
|
||||
else if (_readOnlyDictionary != null)
|
||||
{
|
||||
return _readOnlyDictionary.GetEnumerator();
|
||||
}
|
||||
#endif
|
||||
else
|
||||
{
|
||||
return _genericDictionary.GetEnumerator();
|
||||
}
|
||||
}
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
{
|
||||
return GetEnumerator();
|
||||
}
|
||||
|
||||
void IDictionary.Add(object key, object value)
|
||||
{
|
||||
if (_dictionary != null)
|
||||
{
|
||||
_dictionary.Add(key, value);
|
||||
}
|
||||
#if !(NET40 || NET35 || NET20 || PORTABLE40)
|
||||
else if (_readOnlyDictionary != null)
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
#endif
|
||||
else
|
||||
{
|
||||
_genericDictionary.Add((TKey)key, (TValue)value);
|
||||
}
|
||||
}
|
||||
|
||||
object IDictionary.this[object key]
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_dictionary != null)
|
||||
{
|
||||
return _dictionary[key];
|
||||
}
|
||||
#if !(NET40 || NET35 || NET20 || PORTABLE40)
|
||||
else if (_readOnlyDictionary != null)
|
||||
{
|
||||
return _readOnlyDictionary[(TKey)key];
|
||||
}
|
||||
#endif
|
||||
else
|
||||
{
|
||||
return _genericDictionary[(TKey)key];
|
||||
}
|
||||
}
|
||||
set
|
||||
{
|
||||
if (_dictionary != null)
|
||||
{
|
||||
_dictionary[key] = value;
|
||||
}
|
||||
#if !(NET40 || NET35 || NET20 || PORTABLE40)
|
||||
else if (_readOnlyDictionary != null)
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
#endif
|
||||
else
|
||||
{
|
||||
_genericDictionary[(TKey)key] = (TValue)value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private struct DictionaryEnumerator<TEnumeratorKey, TEnumeratorValue> : IDictionaryEnumerator
|
||||
{
|
||||
private readonly IEnumerator<KeyValuePair<TEnumeratorKey, TEnumeratorValue>> _e;
|
||||
|
||||
public DictionaryEnumerator(IEnumerator<KeyValuePair<TEnumeratorKey, TEnumeratorValue>> e)
|
||||
{
|
||||
ValidationUtils.ArgumentNotNull(e, nameof(e));
|
||||
_e = e;
|
||||
}
|
||||
|
||||
public DictionaryEntry Entry
|
||||
{
|
||||
get { return (DictionaryEntry)Current; }
|
||||
}
|
||||
|
||||
public object Key
|
||||
{
|
||||
get { return Entry.Key; }
|
||||
}
|
||||
|
||||
public object Value
|
||||
{
|
||||
get { return Entry.Value; }
|
||||
}
|
||||
|
||||
public object Current
|
||||
{
|
||||
get { return new DictionaryEntry(_e.Current.Key, _e.Current.Value); }
|
||||
}
|
||||
|
||||
public bool MoveNext()
|
||||
{
|
||||
return _e.MoveNext();
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
_e.Reset();
|
||||
}
|
||||
}
|
||||
|
||||
IDictionaryEnumerator IDictionary.GetEnumerator()
|
||||
{
|
||||
if (_dictionary != null)
|
||||
{
|
||||
return _dictionary.GetEnumerator();
|
||||
}
|
||||
#if !(NET40 || NET35 || NET20 || PORTABLE40)
|
||||
else if (_readOnlyDictionary != null)
|
||||
{
|
||||
return new DictionaryEnumerator<TKey, TValue>(_readOnlyDictionary.GetEnumerator());
|
||||
}
|
||||
#endif
|
||||
else
|
||||
{
|
||||
return new DictionaryEnumerator<TKey, TValue>(_genericDictionary.GetEnumerator());
|
||||
}
|
||||
}
|
||||
|
||||
bool IDictionary.Contains(object key)
|
||||
{
|
||||
if (_genericDictionary != null)
|
||||
{
|
||||
return _genericDictionary.ContainsKey((TKey)key);
|
||||
}
|
||||
#if !(NET40 || NET35 || NET20 || PORTABLE40)
|
||||
else if (_readOnlyDictionary != null)
|
||||
{
|
||||
return _readOnlyDictionary.ContainsKey((TKey)key);
|
||||
}
|
||||
#endif
|
||||
else
|
||||
{
|
||||
return _dictionary.Contains(key);
|
||||
}
|
||||
}
|
||||
|
||||
bool IDictionary.IsFixedSize
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_genericDictionary != null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
#if !(NET40 || NET35 || NET20 || PORTABLE40)
|
||||
else if (_readOnlyDictionary != null)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
else
|
||||
{
|
||||
return _dictionary.IsFixedSize;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ICollection IDictionary.Keys
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_genericDictionary != null)
|
||||
{
|
||||
return _genericDictionary.Keys.ToList();
|
||||
}
|
||||
#if !(NET40 || NET35 || NET20 || PORTABLE40)
|
||||
else if (_readOnlyDictionary != null)
|
||||
{
|
||||
return _readOnlyDictionary.Keys.ToList();
|
||||
}
|
||||
#endif
|
||||
else
|
||||
{
|
||||
return _dictionary.Keys;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Remove(object key)
|
||||
{
|
||||
if (_dictionary != null)
|
||||
{
|
||||
_dictionary.Remove(key);
|
||||
}
|
||||
#if !(NET40 || NET35 || NET20 || PORTABLE40)
|
||||
else if (_readOnlyDictionary != null)
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
#endif
|
||||
else
|
||||
{
|
||||
_genericDictionary.Remove((TKey)key);
|
||||
}
|
||||
}
|
||||
|
||||
ICollection IDictionary.Values
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_genericDictionary != null)
|
||||
{
|
||||
return _genericDictionary.Values.ToList();
|
||||
}
|
||||
#if !(NET40 || NET35 || NET20 || PORTABLE40)
|
||||
else if (_readOnlyDictionary != null)
|
||||
{
|
||||
return _readOnlyDictionary.Values.ToList();
|
||||
}
|
||||
#endif
|
||||
else
|
||||
{
|
||||
return _dictionary.Values;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ICollection.CopyTo(Array array, int index)
|
||||
{
|
||||
if (_dictionary != null)
|
||||
{
|
||||
_dictionary.CopyTo(array, index);
|
||||
}
|
||||
#if !(NET40 || NET35 || NET20 || PORTABLE40)
|
||||
else if (_readOnlyDictionary != null)
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
#endif
|
||||
else
|
||||
{
|
||||
_genericDictionary.CopyTo((KeyValuePair<TKey, TValue>[])array, index);
|
||||
}
|
||||
}
|
||||
|
||||
bool ICollection.IsSynchronized
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_dictionary != null)
|
||||
{
|
||||
return _dictionary.IsSynchronized;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
object ICollection.SyncRoot
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_syncRoot == null)
|
||||
{
|
||||
Interlocked.CompareExchange(ref _syncRoot, new object(), null);
|
||||
}
|
||||
|
||||
return _syncRoot;
|
||||
}
|
||||
}
|
||||
|
||||
public object UnderlyingDictionary
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_dictionary != null)
|
||||
{
|
||||
return _dictionary;
|
||||
}
|
||||
#if !(NET40 || NET35 || NET20 || PORTABLE40)
|
||||
else if (_readOnlyDictionary != null)
|
||||
{
|
||||
return _readOnlyDictionary;
|
||||
}
|
||||
#endif
|
||||
else
|
||||
{
|
||||
return _genericDictionary;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
113
Common/00-1Json8.3/Json8.3/Utilities/DynamicProxy.cs
Normal file
113
Common/00-1Json8.3/Json8.3/Utilities/DynamicProxy.cs
Normal file
@@ -0,0 +1,113 @@
|
||||
#region License
|
||||
// Copyright (c) 2007 James Newton-King
|
||||
//
|
||||
// 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
|
||||
|
||||
#if !(NET35 || NET20 || PORTABLE40)
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Dynamic;
|
||||
using System.Linq;
|
||||
using System.Linq.Expressions;
|
||||
using System.Text;
|
||||
|
||||
namespace Newtonsoft.Json.Utilities
|
||||
{
|
||||
internal class DynamicProxy<T>
|
||||
{
|
||||
public virtual IEnumerable<string> GetDynamicMemberNames(T instance)
|
||||
{
|
||||
return new string[0];
|
||||
}
|
||||
|
||||
public virtual bool TryBinaryOperation(T instance, BinaryOperationBinder binder, object arg, out object result)
|
||||
{
|
||||
result = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
public virtual bool TryConvert(T instance, ConvertBinder binder, out object result)
|
||||
{
|
||||
result = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
public virtual bool TryCreateInstance(T instance, CreateInstanceBinder binder, object[] args, out object result)
|
||||
{
|
||||
result = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
public virtual bool TryDeleteIndex(T instance, DeleteIndexBinder binder, object[] indexes)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public virtual bool TryDeleteMember(T instance, DeleteMemberBinder binder)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public virtual bool TryGetIndex(T instance, GetIndexBinder binder, object[] indexes, out object result)
|
||||
{
|
||||
result = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
public virtual bool TryGetMember(T instance, GetMemberBinder binder, out object result)
|
||||
{
|
||||
result = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
public virtual bool TryInvoke(T instance, InvokeBinder binder, object[] args, out object result)
|
||||
{
|
||||
result = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
public virtual bool TryInvokeMember(T instance, InvokeMemberBinder binder, object[] args, out object result)
|
||||
{
|
||||
result = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
public virtual bool TrySetIndex(T instance, SetIndexBinder binder, object[] indexes, object value)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public virtual bool TrySetMember(T instance, SetMemberBinder binder, object value)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public virtual bool TryUnaryOperation(T instance, UnaryOperationBinder binder, out object result)
|
||||
{
|
||||
result = null;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
427
Common/00-1Json8.3/Json8.3/Utilities/DynamicProxyMetaObject.cs
Normal file
427
Common/00-1Json8.3/Json8.3/Utilities/DynamicProxyMetaObject.cs
Normal file
@@ -0,0 +1,427 @@
|
||||
#region License
|
||||
// Copyright (c) 2007 James Newton-King
|
||||
//
|
||||
// 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
|
||||
|
||||
#if !(NET35 || NET20 || PORTABLE40)
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Dynamic;
|
||||
using System.Linq;
|
||||
using System.Linq.Expressions;
|
||||
using System.Reflection;
|
||||
|
||||
namespace Newtonsoft.Json.Utilities
|
||||
{
|
||||
internal sealed class DynamicProxyMetaObject<T> : DynamicMetaObject
|
||||
{
|
||||
private readonly DynamicProxy<T> _proxy;
|
||||
private readonly bool _dontFallbackFirst;
|
||||
|
||||
internal DynamicProxyMetaObject(Expression expression, T value, DynamicProxy<T> proxy, bool dontFallbackFirst)
|
||||
: base(expression, BindingRestrictions.Empty, value)
|
||||
{
|
||||
_proxy = proxy;
|
||||
_dontFallbackFirst = dontFallbackFirst;
|
||||
}
|
||||
|
||||
private new T Value
|
||||
{
|
||||
get { return (T)base.Value; }
|
||||
}
|
||||
|
||||
private bool IsOverridden(string method)
|
||||
{
|
||||
return ReflectionUtils.IsMethodOverridden(_proxy.GetType(), typeof(DynamicProxy<T>), method);
|
||||
}
|
||||
|
||||
public override DynamicMetaObject BindGetMember(GetMemberBinder binder)
|
||||
{
|
||||
return IsOverridden("TryGetMember")
|
||||
? CallMethodWithResult("TryGetMember", binder, NoArgs, e => binder.FallbackGetMember(this, e))
|
||||
: base.BindGetMember(binder);
|
||||
}
|
||||
|
||||
public override DynamicMetaObject BindSetMember(SetMemberBinder binder, DynamicMetaObject value)
|
||||
{
|
||||
return IsOverridden("TrySetMember")
|
||||
? CallMethodReturnLast("TrySetMember", binder, GetArgs(value), e => binder.FallbackSetMember(this, value, e))
|
||||
: base.BindSetMember(binder, value);
|
||||
}
|
||||
|
||||
public override DynamicMetaObject BindDeleteMember(DeleteMemberBinder binder)
|
||||
{
|
||||
return IsOverridden("TryDeleteMember")
|
||||
? CallMethodNoResult("TryDeleteMember", binder, NoArgs, e => binder.FallbackDeleteMember(this, e))
|
||||
: base.BindDeleteMember(binder);
|
||||
}
|
||||
|
||||
public override DynamicMetaObject BindConvert(ConvertBinder binder)
|
||||
{
|
||||
return IsOverridden("TryConvert")
|
||||
? CallMethodWithResult("TryConvert", binder, NoArgs, e => binder.FallbackConvert(this, e))
|
||||
: base.BindConvert(binder);
|
||||
}
|
||||
|
||||
public override DynamicMetaObject BindInvokeMember(InvokeMemberBinder binder, DynamicMetaObject[] args)
|
||||
{
|
||||
if (!IsOverridden("TryInvokeMember"))
|
||||
{
|
||||
return base.BindInvokeMember(binder, args);
|
||||
}
|
||||
|
||||
//
|
||||
// Generate a tree like:
|
||||
//
|
||||
// {
|
||||
// object result;
|
||||
// TryInvokeMember(payload, out result)
|
||||
// ? result
|
||||
// : TryGetMember(payload, out result)
|
||||
// ? FallbackInvoke(result)
|
||||
// : fallbackResult
|
||||
// }
|
||||
//
|
||||
// Then it calls FallbackInvokeMember with this tree as the
|
||||
// "error", giving the language the option of using this
|
||||
// tree or doing .NET binding.
|
||||
//
|
||||
Fallback fallback = e => binder.FallbackInvokeMember(this, args, e);
|
||||
|
||||
DynamicMetaObject call = BuildCallMethodWithResult(
|
||||
"TryInvokeMember",
|
||||
binder,
|
||||
GetArgArray(args),
|
||||
BuildCallMethodWithResult(
|
||||
"TryGetMember",
|
||||
new GetBinderAdapter(binder),
|
||||
NoArgs,
|
||||
fallback(null),
|
||||
e => binder.FallbackInvoke(e, args, null)
|
||||
),
|
||||
null
|
||||
);
|
||||
|
||||
return _dontFallbackFirst ? call : fallback(call);
|
||||
}
|
||||
|
||||
public override DynamicMetaObject BindCreateInstance(CreateInstanceBinder binder, DynamicMetaObject[] args)
|
||||
{
|
||||
return IsOverridden("TryCreateInstance")
|
||||
? CallMethodWithResult("TryCreateInstance", binder, GetArgArray(args), e => binder.FallbackCreateInstance(this, args, e))
|
||||
: base.BindCreateInstance(binder, args);
|
||||
}
|
||||
|
||||
public override DynamicMetaObject BindInvoke(InvokeBinder binder, DynamicMetaObject[] args)
|
||||
{
|
||||
return IsOverridden("TryInvoke")
|
||||
? CallMethodWithResult("TryInvoke", binder, GetArgArray(args), e => binder.FallbackInvoke(this, args, e))
|
||||
: base.BindInvoke(binder, args);
|
||||
}
|
||||
|
||||
public override DynamicMetaObject BindBinaryOperation(BinaryOperationBinder binder, DynamicMetaObject arg)
|
||||
{
|
||||
return IsOverridden("TryBinaryOperation")
|
||||
? CallMethodWithResult("TryBinaryOperation", binder, GetArgs(arg), e => binder.FallbackBinaryOperation(this, arg, e))
|
||||
: base.BindBinaryOperation(binder, arg);
|
||||
}
|
||||
|
||||
public override DynamicMetaObject BindUnaryOperation(UnaryOperationBinder binder)
|
||||
{
|
||||
return IsOverridden("TryUnaryOperation")
|
||||
? CallMethodWithResult("TryUnaryOperation", binder, NoArgs, e => binder.FallbackUnaryOperation(this, e))
|
||||
: base.BindUnaryOperation(binder);
|
||||
}
|
||||
|
||||
public override DynamicMetaObject BindGetIndex(GetIndexBinder binder, DynamicMetaObject[] indexes)
|
||||
{
|
||||
return IsOverridden("TryGetIndex")
|
||||
? CallMethodWithResult("TryGetIndex", binder, GetArgArray(indexes), e => binder.FallbackGetIndex(this, indexes, e))
|
||||
: base.BindGetIndex(binder, indexes);
|
||||
}
|
||||
|
||||
public override DynamicMetaObject BindSetIndex(SetIndexBinder binder, DynamicMetaObject[] indexes, DynamicMetaObject value)
|
||||
{
|
||||
return IsOverridden("TrySetIndex")
|
||||
? CallMethodReturnLast("TrySetIndex", binder, GetArgArray(indexes, value), e => binder.FallbackSetIndex(this, indexes, value, e))
|
||||
: base.BindSetIndex(binder, indexes, value);
|
||||
}
|
||||
|
||||
public override DynamicMetaObject BindDeleteIndex(DeleteIndexBinder binder, DynamicMetaObject[] indexes)
|
||||
{
|
||||
return IsOverridden("TryDeleteIndex")
|
||||
? CallMethodNoResult("TryDeleteIndex", binder, GetArgArray(indexes), e => binder.FallbackDeleteIndex(this, indexes, e))
|
||||
: base.BindDeleteIndex(binder, indexes);
|
||||
}
|
||||
|
||||
private delegate DynamicMetaObject Fallback(DynamicMetaObject errorSuggestion);
|
||||
|
||||
private static readonly Expression[] NoArgs = new Expression[0];
|
||||
|
||||
private static Expression[] GetArgs(params DynamicMetaObject[] args)
|
||||
{
|
||||
return args.Select(arg => Expression.Convert(arg.Expression, typeof(object))).ToArray();
|
||||
}
|
||||
|
||||
private static Expression[] GetArgArray(DynamicMetaObject[] args)
|
||||
{
|
||||
return new[] { Expression.NewArrayInit(typeof(object), GetArgs(args)) };
|
||||
}
|
||||
|
||||
private static Expression[] GetArgArray(DynamicMetaObject[] args, DynamicMetaObject value)
|
||||
{
|
||||
return new Expression[]
|
||||
{
|
||||
Expression.NewArrayInit(typeof(object), GetArgs(args)),
|
||||
Expression.Convert(value.Expression, typeof(object))
|
||||
};
|
||||
}
|
||||
|
||||
private static ConstantExpression Constant(DynamicMetaObjectBinder binder)
|
||||
{
|
||||
Type t = binder.GetType();
|
||||
while (!t.IsVisible())
|
||||
{
|
||||
t = t.BaseType();
|
||||
}
|
||||
return Expression.Constant(binder, t);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Helper method for generating a MetaObject which calls a
|
||||
/// specific method on Dynamic that returns a result
|
||||
/// </summary>
|
||||
private DynamicMetaObject CallMethodWithResult(string methodName, DynamicMetaObjectBinder binder, Expression[] args, Fallback fallback, Fallback fallbackInvoke = null)
|
||||
{
|
||||
//
|
||||
// First, call fallback to do default binding
|
||||
// This produces either an error or a call to a .NET member
|
||||
//
|
||||
DynamicMetaObject fallbackResult = fallback(null);
|
||||
|
||||
DynamicMetaObject callDynamic = BuildCallMethodWithResult(methodName, binder, args, fallbackResult, fallbackInvoke);
|
||||
|
||||
//
|
||||
// Now, call fallback again using our new MO as the error
|
||||
// When we do this, one of two things can happen:
|
||||
// 1. Binding will succeed, and it will ignore our call to
|
||||
// the dynamic method, OR
|
||||
// 2. Binding will fail, and it will use the MO we created
|
||||
// above.
|
||||
//
|
||||
|
||||
return _dontFallbackFirst ? callDynamic : fallback(callDynamic);
|
||||
}
|
||||
|
||||
private DynamicMetaObject BuildCallMethodWithResult(string methodName, DynamicMetaObjectBinder binder, Expression[] args, DynamicMetaObject fallbackResult, Fallback fallbackInvoke)
|
||||
{
|
||||
//
|
||||
// Build a new expression like:
|
||||
// {
|
||||
// object result;
|
||||
// TryGetMember(payload, out result) ? fallbackInvoke(result) : fallbackResult
|
||||
// }
|
||||
//
|
||||
ParameterExpression result = Expression.Parameter(typeof(object), null);
|
||||
|
||||
IList<Expression> callArgs = new List<Expression>();
|
||||
callArgs.Add(Expression.Convert(Expression, typeof(T)));
|
||||
callArgs.Add(Constant(binder));
|
||||
callArgs.AddRange(args);
|
||||
callArgs.Add(result);
|
||||
|
||||
DynamicMetaObject resultMetaObject = new DynamicMetaObject(result, BindingRestrictions.Empty);
|
||||
|
||||
// Need to add a conversion if calling TryConvert
|
||||
if (binder.ReturnType != typeof(object))
|
||||
{
|
||||
UnaryExpression convert = Expression.Convert(resultMetaObject.Expression, binder.ReturnType);
|
||||
// will always be a cast or unbox
|
||||
|
||||
resultMetaObject = new DynamicMetaObject(convert, resultMetaObject.Restrictions);
|
||||
}
|
||||
|
||||
if (fallbackInvoke != null)
|
||||
{
|
||||
resultMetaObject = fallbackInvoke(resultMetaObject);
|
||||
}
|
||||
|
||||
DynamicMetaObject callDynamic = new DynamicMetaObject(
|
||||
Expression.Block(
|
||||
new[] { result },
|
||||
Expression.Condition(
|
||||
Expression.Call(
|
||||
Expression.Constant(_proxy),
|
||||
typeof(DynamicProxy<T>).GetMethod(methodName),
|
||||
callArgs
|
||||
),
|
||||
resultMetaObject.Expression,
|
||||
fallbackResult.Expression,
|
||||
binder.ReturnType
|
||||
)
|
||||
),
|
||||
GetRestrictions().Merge(resultMetaObject.Restrictions).Merge(fallbackResult.Restrictions)
|
||||
);
|
||||
|
||||
return callDynamic;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Helper method for generating a MetaObject which calls a
|
||||
/// specific method on Dynamic, but uses one of the arguments for
|
||||
/// the result.
|
||||
/// </summary>
|
||||
private DynamicMetaObject CallMethodReturnLast(string methodName, DynamicMetaObjectBinder binder, Expression[] args, Fallback fallback)
|
||||
{
|
||||
//
|
||||
// First, call fallback to do default binding
|
||||
// This produces either an error or a call to a .NET member
|
||||
//
|
||||
DynamicMetaObject fallbackResult = fallback(null);
|
||||
|
||||
//
|
||||
// Build a new expression like:
|
||||
// {
|
||||
// object result;
|
||||
// TrySetMember(payload, result = value) ? result : fallbackResult
|
||||
// }
|
||||
//
|
||||
ParameterExpression result = Expression.Parameter(typeof(object), null);
|
||||
|
||||
IList<Expression> callArgs = new List<Expression>();
|
||||
callArgs.Add(Expression.Convert(Expression, typeof(T)));
|
||||
callArgs.Add(Constant(binder));
|
||||
callArgs.AddRange(args);
|
||||
callArgs[args.Length + 1] = Expression.Assign(result, callArgs[args.Length + 1]);
|
||||
|
||||
DynamicMetaObject callDynamic = new DynamicMetaObject(
|
||||
Expression.Block(
|
||||
new[] { result },
|
||||
Expression.Condition(
|
||||
Expression.Call(
|
||||
Expression.Constant(_proxy),
|
||||
typeof(DynamicProxy<T>).GetMethod(methodName),
|
||||
callArgs
|
||||
),
|
||||
result,
|
||||
fallbackResult.Expression,
|
||||
typeof(object)
|
||||
)
|
||||
),
|
||||
GetRestrictions().Merge(fallbackResult.Restrictions)
|
||||
);
|
||||
|
||||
//
|
||||
// Now, call fallback again using our new MO as the error
|
||||
// When we do this, one of two things can happen:
|
||||
// 1. Binding will succeed, and it will ignore our call to
|
||||
// the dynamic method, OR
|
||||
// 2. Binding will fail, and it will use the MO we created
|
||||
// above.
|
||||
//
|
||||
return _dontFallbackFirst ? callDynamic : fallback(callDynamic);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Helper method for generating a MetaObject which calls a
|
||||
/// specific method on Dynamic, but uses one of the arguments for
|
||||
/// the result.
|
||||
/// </summary>
|
||||
private DynamicMetaObject CallMethodNoResult(string methodName, DynamicMetaObjectBinder binder, Expression[] args, Fallback fallback)
|
||||
{
|
||||
//
|
||||
// First, call fallback to do default binding
|
||||
// This produces either an error or a call to a .NET member
|
||||
//
|
||||
DynamicMetaObject fallbackResult = fallback(null);
|
||||
|
||||
IList<Expression> callArgs = new List<Expression>();
|
||||
callArgs.Add(Expression.Convert(Expression, typeof(T)));
|
||||
callArgs.Add(Constant(binder));
|
||||
callArgs.AddRange(args);
|
||||
|
||||
//
|
||||
// Build a new expression like:
|
||||
// if (TryDeleteMember(payload)) { } else { fallbackResult }
|
||||
//
|
||||
DynamicMetaObject callDynamic = new DynamicMetaObject(
|
||||
Expression.Condition(
|
||||
Expression.Call(
|
||||
Expression.Constant(_proxy),
|
||||
typeof(DynamicProxy<T>).GetMethod(methodName),
|
||||
callArgs
|
||||
),
|
||||
Expression.Empty(),
|
||||
fallbackResult.Expression,
|
||||
typeof(void)
|
||||
),
|
||||
GetRestrictions().Merge(fallbackResult.Restrictions)
|
||||
);
|
||||
|
||||
//
|
||||
// Now, call fallback again using our new MO as the error
|
||||
// When we do this, one of two things can happen:
|
||||
// 1. Binding will succeed, and it will ignore our call to
|
||||
// the dynamic method, OR
|
||||
// 2. Binding will fail, and it will use the MO we created
|
||||
// above.
|
||||
//
|
||||
return _dontFallbackFirst ? callDynamic : fallback(callDynamic);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a Restrictions object which includes our current restrictions merged
|
||||
/// with a restriction limiting our type
|
||||
/// </summary>
|
||||
private BindingRestrictions GetRestrictions()
|
||||
{
|
||||
return (Value == null && HasValue)
|
||||
? BindingRestrictions.GetInstanceRestriction(Expression, null)
|
||||
: BindingRestrictions.GetTypeRestriction(Expression, LimitType);
|
||||
}
|
||||
|
||||
public override IEnumerable<string> GetDynamicMemberNames()
|
||||
{
|
||||
return _proxy.GetDynamicMemberNames(Value);
|
||||
}
|
||||
|
||||
// It is okay to throw NotSupported from this binder. This object
|
||||
// is only used by DynamicObject.GetMember--it is not expected to
|
||||
// (and cannot) implement binding semantics. It is just so the DO
|
||||
// can use the Name and IgnoreCase properties.
|
||||
private sealed class GetBinderAdapter : GetMemberBinder
|
||||
{
|
||||
internal GetBinderAdapter(InvokeMemberBinder binder) :
|
||||
base(binder.Name, binder.IgnoreCase)
|
||||
{
|
||||
}
|
||||
|
||||
public override DynamicMetaObject FallbackGetMember(DynamicMetaObject target, DynamicMetaObject errorSuggestion)
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,360 @@
|
||||
#region License
|
||||
// Copyright (c) 2007 James Newton-King
|
||||
//
|
||||
// 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
|
||||
|
||||
#if !(DOTNET || PORTABLE || PORTABLE40)
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
#if NET20
|
||||
using Newtonsoft.Json.Utilities.LinqBridge;
|
||||
#endif
|
||||
using System.Reflection;
|
||||
using System.Reflection.Emit;
|
||||
using Newtonsoft.Json.Serialization;
|
||||
using System.Globalization;
|
||||
|
||||
namespace Newtonsoft.Json.Utilities
|
||||
{
|
||||
internal class DynamicReflectionDelegateFactory : ReflectionDelegateFactory
|
||||
{
|
||||
public static DynamicReflectionDelegateFactory Instance = new DynamicReflectionDelegateFactory();
|
||||
|
||||
private static DynamicMethod CreateDynamicMethod(string name, Type returnType, Type[] parameterTypes, Type owner)
|
||||
{
|
||||
DynamicMethod dynamicMethod = !owner.IsInterface()
|
||||
? new DynamicMethod(name, returnType, parameterTypes, owner, true)
|
||||
: new DynamicMethod(name, returnType, parameterTypes, owner.Module, true);
|
||||
|
||||
return dynamicMethod;
|
||||
}
|
||||
|
||||
public override ObjectConstructor<object> CreateParameterizedConstructor(MethodBase method)
|
||||
{
|
||||
DynamicMethod dynamicMethod = CreateDynamicMethod(method.ToString(), typeof(object), new[] { typeof(object[]) }, method.DeclaringType);
|
||||
ILGenerator generator = dynamicMethod.GetILGenerator();
|
||||
|
||||
GenerateCreateMethodCallIL(method, generator, 0);
|
||||
|
||||
return (ObjectConstructor<object>)dynamicMethod.CreateDelegate(typeof(ObjectConstructor<object>));
|
||||
}
|
||||
|
||||
public override MethodCall<T, object> CreateMethodCall<T>(MethodBase method)
|
||||
{
|
||||
DynamicMethod dynamicMethod = CreateDynamicMethod(method.ToString(), typeof(object), new[] { typeof(object), typeof(object[]) }, method.DeclaringType);
|
||||
ILGenerator generator = dynamicMethod.GetILGenerator();
|
||||
|
||||
GenerateCreateMethodCallIL(method, generator, 1);
|
||||
|
||||
return (MethodCall<T, object>)dynamicMethod.CreateDelegate(typeof(MethodCall<T, object>));
|
||||
}
|
||||
|
||||
private void GenerateCreateMethodCallIL(MethodBase method, ILGenerator generator, int argsIndex)
|
||||
{
|
||||
ParameterInfo[] args = method.GetParameters();
|
||||
|
||||
Label argsOk = generator.DefineLabel();
|
||||
|
||||
// throw an error if the number of argument values doesn't match method parameters
|
||||
generator.Emit(OpCodes.Ldarg, argsIndex);
|
||||
generator.Emit(OpCodes.Ldlen);
|
||||
generator.Emit(OpCodes.Ldc_I4, args.Length);
|
||||
generator.Emit(OpCodes.Beq, argsOk);
|
||||
generator.Emit(OpCodes.Newobj, typeof(TargetParameterCountException).GetConstructor(ReflectionUtils.EmptyTypes));
|
||||
generator.Emit(OpCodes.Throw);
|
||||
|
||||
generator.MarkLabel(argsOk);
|
||||
|
||||
if (!method.IsConstructor && !method.IsStatic)
|
||||
{
|
||||
generator.PushInstance(method.DeclaringType);
|
||||
}
|
||||
|
||||
int localVariableCount = 0;
|
||||
|
||||
for (int i = 0; i < args.Length; i++)
|
||||
{
|
||||
ParameterInfo parameter = args[i];
|
||||
Type parameterType = parameter.ParameterType;
|
||||
|
||||
if (parameterType.IsByRef)
|
||||
{
|
||||
parameterType = parameterType.GetElementType();
|
||||
|
||||
LocalBuilder localVariable = generator.DeclareLocal(parameterType);
|
||||
|
||||
// don't need to set variable for 'out' parameter
|
||||
if (!parameter.IsOut)
|
||||
{
|
||||
generator.PushArrayInstance(argsIndex, i);
|
||||
|
||||
if (parameterType.IsValueType())
|
||||
{
|
||||
Label skipSettingDefault = generator.DefineLabel();
|
||||
Label finishedProcessingParameter = generator.DefineLabel();
|
||||
|
||||
// check if parameter is not null
|
||||
generator.Emit(OpCodes.Brtrue_S, skipSettingDefault);
|
||||
|
||||
// parameter has no value, initialize to default
|
||||
generator.Emit(OpCodes.Ldloca_S, localVariable);
|
||||
generator.Emit(OpCodes.Initobj, parameterType);
|
||||
generator.Emit(OpCodes.Br_S, finishedProcessingParameter);
|
||||
|
||||
// parameter has value, get value from array again and unbox and set to variable
|
||||
generator.MarkLabel(skipSettingDefault);
|
||||
generator.PushArrayInstance(argsIndex, i);
|
||||
generator.UnboxIfNeeded(parameterType);
|
||||
generator.Emit(OpCodes.Stloc, localVariableCount);
|
||||
|
||||
// parameter finished, we out!
|
||||
generator.MarkLabel(finishedProcessingParameter);
|
||||
}
|
||||
else
|
||||
{
|
||||
generator.UnboxIfNeeded(parameterType);
|
||||
generator.Emit(OpCodes.Stloc, localVariableCount);
|
||||
}
|
||||
}
|
||||
|
||||
generator.Emit(OpCodes.Ldloca_S, localVariable);
|
||||
|
||||
localVariableCount++;
|
||||
}
|
||||
else if (parameterType.IsValueType())
|
||||
{
|
||||
generator.PushArrayInstance(argsIndex, i);
|
||||
|
||||
// have to check that value type parameters aren't null
|
||||
// otherwise they will error when unboxed
|
||||
Label skipSettingDefault = generator.DefineLabel();
|
||||
Label finishedProcessingParameter = generator.DefineLabel();
|
||||
|
||||
// check if parameter is not null
|
||||
generator.Emit(OpCodes.Brtrue_S, skipSettingDefault);
|
||||
|
||||
// parameter has no value, initialize to default
|
||||
LocalBuilder localVariable = generator.DeclareLocal(parameterType);
|
||||
generator.Emit(OpCodes.Ldloca_S, localVariable);
|
||||
generator.Emit(OpCodes.Initobj, parameterType);
|
||||
generator.Emit(OpCodes.Ldloc, localVariableCount);
|
||||
generator.Emit(OpCodes.Br_S, finishedProcessingParameter);
|
||||
|
||||
// parameter has value, get value from array again and unbox
|
||||
generator.MarkLabel(skipSettingDefault);
|
||||
generator.PushArrayInstance(argsIndex, i);
|
||||
generator.UnboxIfNeeded(parameterType);
|
||||
|
||||
// parameter finished, we out!
|
||||
generator.MarkLabel(finishedProcessingParameter);
|
||||
localVariableCount++;
|
||||
}
|
||||
else
|
||||
{
|
||||
generator.PushArrayInstance(argsIndex, i);
|
||||
|
||||
generator.UnboxIfNeeded(parameterType);
|
||||
}
|
||||
}
|
||||
|
||||
if (method.IsConstructor)
|
||||
{
|
||||
generator.Emit(OpCodes.Newobj, (ConstructorInfo)method);
|
||||
}
|
||||
else
|
||||
{
|
||||
generator.CallMethod((MethodInfo)method);
|
||||
}
|
||||
|
||||
Type returnType = method.IsConstructor
|
||||
? method.DeclaringType
|
||||
: ((MethodInfo)method).ReturnType;
|
||||
|
||||
if (returnType != typeof(void))
|
||||
{
|
||||
generator.BoxIfNeeded(returnType);
|
||||
}
|
||||
else
|
||||
{
|
||||
generator.Emit(OpCodes.Ldnull);
|
||||
}
|
||||
|
||||
generator.Return();
|
||||
}
|
||||
|
||||
public override Func<T> CreateDefaultConstructor<T>(Type type)
|
||||
{
|
||||
DynamicMethod dynamicMethod = CreateDynamicMethod("Create" + type.FullName, typeof(T), ReflectionUtils.EmptyTypes, type);
|
||||
dynamicMethod.InitLocals = true;
|
||||
ILGenerator generator = dynamicMethod.GetILGenerator();
|
||||
|
||||
GenerateCreateDefaultConstructorIL(type, generator);
|
||||
|
||||
return (Func<T>)dynamicMethod.CreateDelegate(typeof(Func<T>));
|
||||
}
|
||||
|
||||
private void GenerateCreateDefaultConstructorIL(Type type, ILGenerator generator)
|
||||
{
|
||||
if (type.IsValueType())
|
||||
{
|
||||
generator.DeclareLocal(type);
|
||||
generator.Emit(OpCodes.Ldloc_0);
|
||||
generator.Emit(OpCodes.Box, type);
|
||||
}
|
||||
else
|
||||
{
|
||||
ConstructorInfo constructorInfo =
|
||||
type.GetConstructor(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance, null,
|
||||
ReflectionUtils.EmptyTypes, null);
|
||||
|
||||
if (constructorInfo == null)
|
||||
{
|
||||
throw new ArgumentException("Could not get constructor for {0}.".FormatWith(CultureInfo.InvariantCulture, type));
|
||||
}
|
||||
|
||||
generator.Emit(OpCodes.Newobj, constructorInfo);
|
||||
}
|
||||
|
||||
generator.Return();
|
||||
}
|
||||
|
||||
public override Func<T, object> CreateGet<T>(PropertyInfo propertyInfo)
|
||||
{
|
||||
DynamicMethod dynamicMethod = CreateDynamicMethod("Get" + propertyInfo.Name, typeof(T), new[] { typeof(object) }, propertyInfo.DeclaringType);
|
||||
ILGenerator generator = dynamicMethod.GetILGenerator();
|
||||
|
||||
GenerateCreateGetPropertyIL(propertyInfo, generator);
|
||||
|
||||
return (Func<T, object>)dynamicMethod.CreateDelegate(typeof(Func<T, object>));
|
||||
}
|
||||
|
||||
private void GenerateCreateGetPropertyIL(PropertyInfo propertyInfo, ILGenerator generator)
|
||||
{
|
||||
MethodInfo getMethod = propertyInfo.GetGetMethod(true);
|
||||
if (getMethod == null)
|
||||
{
|
||||
throw new ArgumentException("Property '{0}' does not have a getter.".FormatWith(CultureInfo.InvariantCulture, propertyInfo.Name));
|
||||
}
|
||||
|
||||
if (!getMethod.IsStatic)
|
||||
{
|
||||
generator.PushInstance(propertyInfo.DeclaringType);
|
||||
}
|
||||
|
||||
generator.CallMethod(getMethod);
|
||||
generator.BoxIfNeeded(propertyInfo.PropertyType);
|
||||
generator.Return();
|
||||
}
|
||||
|
||||
public override Func<T, object> CreateGet<T>(FieldInfo fieldInfo)
|
||||
{
|
||||
if (fieldInfo.IsLiteral)
|
||||
{
|
||||
object constantValue = fieldInfo.GetValue(null);
|
||||
Func<T, object> getter = o => constantValue;
|
||||
return getter;
|
||||
}
|
||||
|
||||
DynamicMethod dynamicMethod = CreateDynamicMethod("Get" + fieldInfo.Name, typeof(T), new[] { typeof(object) }, fieldInfo.DeclaringType);
|
||||
ILGenerator generator = dynamicMethod.GetILGenerator();
|
||||
|
||||
GenerateCreateGetFieldIL(fieldInfo, generator);
|
||||
|
||||
return (Func<T, object>)dynamicMethod.CreateDelegate(typeof(Func<T, object>));
|
||||
}
|
||||
|
||||
private void GenerateCreateGetFieldIL(FieldInfo fieldInfo, ILGenerator generator)
|
||||
{
|
||||
if (!fieldInfo.IsStatic)
|
||||
{
|
||||
generator.PushInstance(fieldInfo.DeclaringType);
|
||||
generator.Emit(OpCodes.Ldfld, fieldInfo);
|
||||
}
|
||||
else
|
||||
{
|
||||
generator.Emit(OpCodes.Ldsfld, fieldInfo);
|
||||
}
|
||||
|
||||
generator.BoxIfNeeded(fieldInfo.FieldType);
|
||||
generator.Return();
|
||||
}
|
||||
|
||||
public override Action<T, object> CreateSet<T>(FieldInfo fieldInfo)
|
||||
{
|
||||
DynamicMethod dynamicMethod = CreateDynamicMethod("Set" + fieldInfo.Name, null, new[] { typeof(T), typeof(object) }, fieldInfo.DeclaringType);
|
||||
ILGenerator generator = dynamicMethod.GetILGenerator();
|
||||
|
||||
GenerateCreateSetFieldIL(fieldInfo, generator);
|
||||
|
||||
return (Action<T, object>)dynamicMethod.CreateDelegate(typeof(Action<T, object>));
|
||||
}
|
||||
|
||||
internal static void GenerateCreateSetFieldIL(FieldInfo fieldInfo, ILGenerator generator)
|
||||
{
|
||||
if (!fieldInfo.IsStatic)
|
||||
{
|
||||
generator.PushInstance(fieldInfo.DeclaringType);
|
||||
}
|
||||
|
||||
generator.Emit(OpCodes.Ldarg_1);
|
||||
generator.UnboxIfNeeded(fieldInfo.FieldType);
|
||||
|
||||
if (!fieldInfo.IsStatic)
|
||||
{
|
||||
generator.Emit(OpCodes.Stfld, fieldInfo);
|
||||
}
|
||||
else
|
||||
{
|
||||
generator.Emit(OpCodes.Stsfld, fieldInfo);
|
||||
}
|
||||
|
||||
generator.Return();
|
||||
}
|
||||
|
||||
public override Action<T, object> CreateSet<T>(PropertyInfo propertyInfo)
|
||||
{
|
||||
DynamicMethod dynamicMethod = CreateDynamicMethod("Set" + propertyInfo.Name, null, new[] { typeof(T), typeof(object) }, propertyInfo.DeclaringType);
|
||||
ILGenerator generator = dynamicMethod.GetILGenerator();
|
||||
|
||||
GenerateCreateSetPropertyIL(propertyInfo, generator);
|
||||
|
||||
return (Action<T, object>)dynamicMethod.CreateDelegate(typeof(Action<T, object>));
|
||||
}
|
||||
|
||||
internal static void GenerateCreateSetPropertyIL(PropertyInfo propertyInfo, ILGenerator generator)
|
||||
{
|
||||
MethodInfo setMethod = propertyInfo.GetSetMethod(true);
|
||||
if (!setMethod.IsStatic)
|
||||
{
|
||||
generator.PushInstance(propertyInfo.DeclaringType);
|
||||
}
|
||||
|
||||
generator.Emit(OpCodes.Ldarg_1);
|
||||
generator.UnboxIfNeeded(propertyInfo.PropertyType);
|
||||
generator.CallMethod(setMethod);
|
||||
generator.Return();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
210
Common/00-1Json8.3/Json8.3/Utilities/DynamicUtils.cs
Normal file
210
Common/00-1Json8.3/Json8.3/Utilities/DynamicUtils.cs
Normal file
@@ -0,0 +1,210 @@
|
||||
#region License
|
||||
// Copyright (c) 2007 James Newton-King
|
||||
//
|
||||
// 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
|
||||
|
||||
#if !(NET35 || NET20 || PORTABLE40)
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Dynamic;
|
||||
using System.Linq;
|
||||
using System.Linq.Expressions;
|
||||
#if !(PORTABLE)
|
||||
using System.Reflection;
|
||||
#else
|
||||
using Microsoft.CSharp.RuntimeBinder;
|
||||
#endif
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Text;
|
||||
using System.Globalization;
|
||||
using Newtonsoft.Json.Serialization;
|
||||
|
||||
namespace Newtonsoft.Json.Utilities
|
||||
{
|
||||
internal static class DynamicUtils
|
||||
{
|
||||
internal static class BinderWrapper
|
||||
{
|
||||
#if !(PORTABLE)
|
||||
public const string CSharpAssemblyName = "Microsoft.CSharp, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a";
|
||||
|
||||
private const string BinderTypeName = "Microsoft.CSharp.RuntimeBinder.Binder, " + CSharpAssemblyName;
|
||||
private const string CSharpArgumentInfoTypeName = "Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo, " + CSharpAssemblyName;
|
||||
private const string CSharpArgumentInfoFlagsTypeName = "Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfoFlags, " + CSharpAssemblyName;
|
||||
private const string CSharpBinderFlagsTypeName = "Microsoft.CSharp.RuntimeBinder.CSharpBinderFlags, " + CSharpAssemblyName;
|
||||
|
||||
private static object _getCSharpArgumentInfoArray;
|
||||
private static object _setCSharpArgumentInfoArray;
|
||||
private static MethodCall<object, object> _getMemberCall;
|
||||
private static MethodCall<object, object> _setMemberCall;
|
||||
private static bool _init;
|
||||
|
||||
private static void Init()
|
||||
{
|
||||
if (!_init)
|
||||
{
|
||||
Type binderType = Type.GetType(BinderTypeName, false);
|
||||
if (binderType == null)
|
||||
{
|
||||
throw new InvalidOperationException("Could not resolve type '{0}'. You may need to add a reference to Microsoft.CSharp.dll to work with dynamic types.".FormatWith(CultureInfo.InvariantCulture, BinderTypeName));
|
||||
}
|
||||
|
||||
// None
|
||||
_getCSharpArgumentInfoArray = CreateSharpArgumentInfoArray(0);
|
||||
// None, Constant | UseCompileTimeType
|
||||
_setCSharpArgumentInfoArray = CreateSharpArgumentInfoArray(0, 3);
|
||||
CreateMemberCalls();
|
||||
|
||||
_init = true;
|
||||
}
|
||||
}
|
||||
|
||||
private static object CreateSharpArgumentInfoArray(params int[] values)
|
||||
{
|
||||
Type csharpArgumentInfoType = Type.GetType(CSharpArgumentInfoTypeName);
|
||||
Type csharpArgumentInfoFlags = Type.GetType(CSharpArgumentInfoFlagsTypeName);
|
||||
|
||||
Array a = Array.CreateInstance(csharpArgumentInfoType, values.Length);
|
||||
|
||||
for (int i = 0; i < values.Length; i++)
|
||||
{
|
||||
MethodInfo createArgumentInfoMethod = csharpArgumentInfoType.GetMethod("Create", new[] { csharpArgumentInfoFlags, typeof(string) });
|
||||
object arg = createArgumentInfoMethod.Invoke(null, new object[] { 0, null });
|
||||
a.SetValue(arg, i);
|
||||
}
|
||||
|
||||
return a;
|
||||
}
|
||||
|
||||
private static void CreateMemberCalls()
|
||||
{
|
||||
Type csharpArgumentInfoType = Type.GetType(CSharpArgumentInfoTypeName, true);
|
||||
Type csharpBinderFlagsType = Type.GetType(CSharpBinderFlagsTypeName, true);
|
||||
Type binderType = Type.GetType(BinderTypeName, true);
|
||||
|
||||
Type csharpArgumentInfoTypeEnumerableType = typeof(IEnumerable<>).MakeGenericType(csharpArgumentInfoType);
|
||||
|
||||
MethodInfo getMemberMethod = binderType.GetMethod("GetMember", new[] { csharpBinderFlagsType, typeof(string), typeof(Type), csharpArgumentInfoTypeEnumerableType });
|
||||
_getMemberCall = JsonTypeReflector.ReflectionDelegateFactory.CreateMethodCall<object>(getMemberMethod);
|
||||
|
||||
MethodInfo setMemberMethod = binderType.GetMethod("SetMember", new[] { csharpBinderFlagsType, typeof(string), typeof(Type), csharpArgumentInfoTypeEnumerableType });
|
||||
_setMemberCall = JsonTypeReflector.ReflectionDelegateFactory.CreateMethodCall<object>(setMemberMethod);
|
||||
}
|
||||
#endif
|
||||
|
||||
public static CallSiteBinder GetMember(string name, Type context)
|
||||
{
|
||||
#if !(PORTABLE)
|
||||
Init();
|
||||
return (CallSiteBinder)_getMemberCall(null, 0, name, context, _getCSharpArgumentInfoArray);
|
||||
#else
|
||||
return Binder.GetMember(
|
||||
CSharpBinderFlags.None, name, context, new[] {CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null)});
|
||||
#endif
|
||||
}
|
||||
|
||||
public static CallSiteBinder SetMember(string name, Type context)
|
||||
{
|
||||
#if !(PORTABLE)
|
||||
Init();
|
||||
return (CallSiteBinder)_setMemberCall(null, 0, name, context, _setCSharpArgumentInfoArray);
|
||||
#else
|
||||
return Binder.SetMember(
|
||||
CSharpBinderFlags.None, name, context, new[]
|
||||
{
|
||||
CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.UseCompileTimeType, null),
|
||||
CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.Constant, null)
|
||||
});
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
public static IEnumerable<string> GetDynamicMemberNames(this IDynamicMetaObjectProvider dynamicProvider)
|
||||
{
|
||||
DynamicMetaObject metaObject = dynamicProvider.GetMetaObject(Expression.Constant(dynamicProvider));
|
||||
return metaObject.GetDynamicMemberNames();
|
||||
}
|
||||
}
|
||||
|
||||
internal class NoThrowGetBinderMember : GetMemberBinder
|
||||
{
|
||||
private readonly GetMemberBinder _innerBinder;
|
||||
|
||||
public NoThrowGetBinderMember(GetMemberBinder innerBinder)
|
||||
: base(innerBinder.Name, innerBinder.IgnoreCase)
|
||||
{
|
||||
_innerBinder = innerBinder;
|
||||
}
|
||||
|
||||
public override DynamicMetaObject FallbackGetMember(DynamicMetaObject target, DynamicMetaObject errorSuggestion)
|
||||
{
|
||||
DynamicMetaObject retMetaObject = _innerBinder.Bind(target, new DynamicMetaObject[] { });
|
||||
|
||||
NoThrowExpressionVisitor noThrowVisitor = new NoThrowExpressionVisitor();
|
||||
Expression resultExpression = noThrowVisitor.Visit(retMetaObject.Expression);
|
||||
|
||||
DynamicMetaObject finalMetaObject = new DynamicMetaObject(resultExpression, retMetaObject.Restrictions);
|
||||
return finalMetaObject;
|
||||
}
|
||||
}
|
||||
|
||||
internal class NoThrowSetBinderMember : SetMemberBinder
|
||||
{
|
||||
private readonly SetMemberBinder _innerBinder;
|
||||
|
||||
public NoThrowSetBinderMember(SetMemberBinder innerBinder)
|
||||
: base(innerBinder.Name, innerBinder.IgnoreCase)
|
||||
{
|
||||
_innerBinder = innerBinder;
|
||||
}
|
||||
|
||||
public override DynamicMetaObject FallbackSetMember(DynamicMetaObject target, DynamicMetaObject value, DynamicMetaObject errorSuggestion)
|
||||
{
|
||||
DynamicMetaObject retMetaObject = _innerBinder.Bind(target, new DynamicMetaObject[] { value });
|
||||
|
||||
NoThrowExpressionVisitor noThrowVisitor = new NoThrowExpressionVisitor();
|
||||
Expression resultExpression = noThrowVisitor.Visit(retMetaObject.Expression);
|
||||
|
||||
DynamicMetaObject finalMetaObject = new DynamicMetaObject(resultExpression, retMetaObject.Restrictions);
|
||||
return finalMetaObject;
|
||||
}
|
||||
}
|
||||
|
||||
internal class NoThrowExpressionVisitor : ExpressionVisitor
|
||||
{
|
||||
internal static readonly object ErrorResult = new object();
|
||||
|
||||
protected override Expression VisitConditional(ConditionalExpression node)
|
||||
{
|
||||
// if the result of a test is to throw an error, rewrite to result an error result value
|
||||
if (node.IfFalse.NodeType == ExpressionType.Throw)
|
||||
{
|
||||
return Expression.Condition(node.Test, node.IfTrue, Expression.Constant(ErrorResult));
|
||||
}
|
||||
|
||||
return base.VisitConditional(node);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
257
Common/00-1Json8.3/Json8.3/Utilities/EnumUtils.cs
Normal file
257
Common/00-1Json8.3/Json8.3/Utilities/EnumUtils.cs
Normal file
@@ -0,0 +1,257 @@
|
||||
#region License
|
||||
// Copyright (c) 2007 James Newton-King
|
||||
//
|
||||
// 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.Globalization;
|
||||
using System.Runtime.Serialization;
|
||||
#if NET20
|
||||
using Newtonsoft.Json.Utilities.LinqBridge;
|
||||
#else
|
||||
using System.Linq;
|
||||
#endif
|
||||
using System.Reflection;
|
||||
|
||||
namespace Newtonsoft.Json.Utilities
|
||||
{
|
||||
internal static class EnumUtils
|
||||
{
|
||||
private static readonly ThreadSafeStore<Type, BidirectionalDictionary<string, string>> EnumMemberNamesPerType = new ThreadSafeStore<Type, BidirectionalDictionary<string, string>>(InitializeEnumType);
|
||||
|
||||
private static BidirectionalDictionary<string, string> InitializeEnumType(Type type)
|
||||
{
|
||||
BidirectionalDictionary<string, string> map = new BidirectionalDictionary<string, string>(
|
||||
StringComparer.OrdinalIgnoreCase,
|
||||
StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
foreach (FieldInfo f in type.GetFields())
|
||||
{
|
||||
string n1 = f.Name;
|
||||
string n2;
|
||||
|
||||
#if !NET20
|
||||
n2 = f.GetCustomAttributes(typeof(EnumMemberAttribute), true)
|
||||
.Cast<EnumMemberAttribute>()
|
||||
.Select(a => a.Value)
|
||||
.SingleOrDefault() ?? f.Name;
|
||||
#else
|
||||
n2 = f.Name;
|
||||
#endif
|
||||
|
||||
string s;
|
||||
if (map.TryGetBySecond(n2, out s))
|
||||
{
|
||||
throw new InvalidOperationException("Enum name '{0}' already exists on enum '{1}'.".FormatWith(CultureInfo.InvariantCulture, n2, type.Name));
|
||||
}
|
||||
|
||||
map.Set(n1, n2);
|
||||
}
|
||||
|
||||
return map;
|
||||
}
|
||||
|
||||
public static IList<T> GetFlagsValues<T>(T value) where T : struct
|
||||
{
|
||||
Type enumType = typeof(T);
|
||||
|
||||
if (!enumType.IsDefined(typeof(FlagsAttribute), false))
|
||||
{
|
||||
throw new ArgumentException("Enum type {0} is not a set of flags.".FormatWith(CultureInfo.InvariantCulture, enumType));
|
||||
}
|
||||
|
||||
Type underlyingType = Enum.GetUnderlyingType(value.GetType());
|
||||
|
||||
ulong num = Convert.ToUInt64(value, CultureInfo.InvariantCulture);
|
||||
IList<EnumValue<ulong>> enumNameValues = GetNamesAndValues<T>();
|
||||
IList<T> selectedFlagsValues = new List<T>();
|
||||
|
||||
foreach (EnumValue<ulong> enumNameValue in enumNameValues)
|
||||
{
|
||||
if ((num & enumNameValue.Value) == enumNameValue.Value && enumNameValue.Value != 0)
|
||||
{
|
||||
selectedFlagsValues.Add((T)Convert.ChangeType(enumNameValue.Value, underlyingType, CultureInfo.CurrentCulture));
|
||||
}
|
||||
}
|
||||
|
||||
if (selectedFlagsValues.Count == 0 && enumNameValues.SingleOrDefault(v => v.Value == 0) != null)
|
||||
{
|
||||
selectedFlagsValues.Add(default(T));
|
||||
}
|
||||
|
||||
return selectedFlagsValues;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a dictionary of the names and values of an Enum type.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public static IList<EnumValue<ulong>> GetNamesAndValues<T>() where T : struct
|
||||
{
|
||||
return GetNamesAndValues<ulong>(typeof(T));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a dictionary of the names and values of an Enum type.
|
||||
/// </summary>
|
||||
/// <param name="enumType">The enum type to get names and values for.</param>
|
||||
/// <returns></returns>
|
||||
public static IList<EnumValue<TUnderlyingType>> GetNamesAndValues<TUnderlyingType>(Type enumType) where TUnderlyingType : struct
|
||||
{
|
||||
if (enumType == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(enumType));
|
||||
}
|
||||
|
||||
if (!enumType.IsEnum())
|
||||
{
|
||||
throw new ArgumentException("Type {0} is not an Enum.".FormatWith(CultureInfo.InvariantCulture, enumType), nameof(enumType));
|
||||
}
|
||||
|
||||
IList<object> enumValues = GetValues(enumType);
|
||||
IList<string> enumNames = GetNames(enumType);
|
||||
|
||||
IList<EnumValue<TUnderlyingType>> nameValues = new List<EnumValue<TUnderlyingType>>();
|
||||
|
||||
for (int i = 0; i < enumValues.Count; i++)
|
||||
{
|
||||
try
|
||||
{
|
||||
nameValues.Add(new EnumValue<TUnderlyingType>(enumNames[i], (TUnderlyingType)Convert.ChangeType(enumValues[i], typeof(TUnderlyingType), CultureInfo.CurrentCulture)));
|
||||
}
|
||||
catch (OverflowException e)
|
||||
{
|
||||
throw new InvalidOperationException(
|
||||
string.Format(CultureInfo.InvariantCulture, "Value from enum with the underlying type of {0} cannot be added to dictionary with a value type of {1}. Value was too large: {2}",
|
||||
Enum.GetUnderlyingType(enumType), typeof(TUnderlyingType), Convert.ToUInt64(enumValues[i], CultureInfo.InvariantCulture)), e);
|
||||
}
|
||||
}
|
||||
|
||||
return nameValues;
|
||||
}
|
||||
|
||||
public static IList<object> GetValues(Type enumType)
|
||||
{
|
||||
if (!enumType.IsEnum())
|
||||
{
|
||||
throw new ArgumentException("Type '" + enumType.Name + "' is not an enum.");
|
||||
}
|
||||
|
||||
List<object> values = new List<object>();
|
||||
|
||||
var fields = enumType.GetFields().Where(f => f.IsLiteral);
|
||||
|
||||
foreach (FieldInfo field in fields)
|
||||
{
|
||||
object value = field.GetValue(enumType);
|
||||
values.Add(value);
|
||||
}
|
||||
|
||||
return values;
|
||||
}
|
||||
|
||||
public static IList<string> GetNames(Type enumType)
|
||||
{
|
||||
if (!enumType.IsEnum())
|
||||
{
|
||||
throw new ArgumentException("Type '" + enumType.Name + "' is not an enum.");
|
||||
}
|
||||
|
||||
List<string> values = new List<string>();
|
||||
|
||||
var fields = enumType.GetFields().Where(f => f.IsLiteral);
|
||||
|
||||
foreach (FieldInfo field in fields)
|
||||
{
|
||||
values.Add(field.Name);
|
||||
}
|
||||
|
||||
return values;
|
||||
}
|
||||
|
||||
public static object ParseEnumName(string enumText, bool isNullable, Type t)
|
||||
{
|
||||
if (enumText == string.Empty && isNullable)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
string finalEnumText;
|
||||
|
||||
BidirectionalDictionary<string, string> map = EnumMemberNamesPerType.Get(t);
|
||||
if (enumText.IndexOf(',') != -1)
|
||||
{
|
||||
string[] names = enumText.Split(',');
|
||||
for (int i = 0; i < names.Length; i++)
|
||||
{
|
||||
string name = names[i].Trim();
|
||||
|
||||
names[i] = ResolvedEnumName(map, name);
|
||||
}
|
||||
|
||||
finalEnumText = string.Join(", ", names);
|
||||
}
|
||||
else
|
||||
{
|
||||
finalEnumText = ResolvedEnumName(map, enumText);
|
||||
}
|
||||
|
||||
return Enum.Parse(t, finalEnumText, true);
|
||||
}
|
||||
|
||||
public static string ToEnumName(Type enumType, string enumText, bool camelCaseText)
|
||||
{
|
||||
BidirectionalDictionary<string, string> map = EnumMemberNamesPerType.Get(enumType);
|
||||
|
||||
string[] names = enumText.Split(',');
|
||||
for (int i = 0; i < names.Length; i++)
|
||||
{
|
||||
string name = names[i].Trim();
|
||||
|
||||
string resolvedEnumName;
|
||||
map.TryGetByFirst(name, out resolvedEnumName);
|
||||
resolvedEnumName = resolvedEnumName ?? name;
|
||||
|
||||
if (camelCaseText)
|
||||
{
|
||||
resolvedEnumName = StringUtils.ToCamelCase(resolvedEnumName);
|
||||
}
|
||||
|
||||
names[i] = resolvedEnumName;
|
||||
}
|
||||
|
||||
string finalName = string.Join(", ", names);
|
||||
|
||||
return finalName;
|
||||
}
|
||||
|
||||
private static string ResolvedEnumName(BidirectionalDictionary<string, string> map, string enumText)
|
||||
{
|
||||
string resolvedEnumName;
|
||||
map.TryGetBySecond(enumText, out resolvedEnumName);
|
||||
resolvedEnumName = resolvedEnumName ?? enumText;
|
||||
return resolvedEnumName;
|
||||
}
|
||||
}
|
||||
}
|
||||
49
Common/00-1Json8.3/Json8.3/Utilities/EnumValue.cs
Normal file
49
Common/00-1Json8.3/Json8.3/Utilities/EnumValue.cs
Normal file
@@ -0,0 +1,49 @@
|
||||
#region License
|
||||
// Copyright (c) 2007 James Newton-King
|
||||
//
|
||||
// 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
|
||||
|
||||
namespace Newtonsoft.Json.Utilities
|
||||
{
|
||||
internal class EnumValue<T> where T : struct
|
||||
{
|
||||
private readonly string _name;
|
||||
private readonly T _value;
|
||||
|
||||
public string Name
|
||||
{
|
||||
get { return _name; }
|
||||
}
|
||||
|
||||
public T Value
|
||||
{
|
||||
get { return _value; }
|
||||
}
|
||||
|
||||
public EnumValue(string name, T value)
|
||||
{
|
||||
_name = name;
|
||||
_value = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,368 @@
|
||||
#region License
|
||||
// Copyright (c) 2007 James Newton-King
|
||||
//
|
||||
// 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
|
||||
|
||||
#if !(NET20 || NET35)
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System;
|
||||
using System.Linq.Expressions;
|
||||
using System.Reflection;
|
||||
using Newtonsoft.Json.Serialization;
|
||||
|
||||
namespace Newtonsoft.Json.Utilities
|
||||
{
|
||||
internal class ExpressionReflectionDelegateFactory : ReflectionDelegateFactory
|
||||
{
|
||||
private static readonly ExpressionReflectionDelegateFactory _instance = new ExpressionReflectionDelegateFactory();
|
||||
|
||||
internal static ReflectionDelegateFactory Instance
|
||||
{
|
||||
get { return _instance; }
|
||||
}
|
||||
|
||||
public override ObjectConstructor<object> CreateParameterizedConstructor(MethodBase method)
|
||||
{
|
||||
ValidationUtils.ArgumentNotNull(method, nameof(method));
|
||||
|
||||
Type type = typeof(object);
|
||||
|
||||
ParameterExpression argsParameterExpression = Expression.Parameter(typeof(object[]), "args");
|
||||
|
||||
Expression callExpression = BuildMethodCall(method, type, null, argsParameterExpression);
|
||||
|
||||
LambdaExpression lambdaExpression = Expression.Lambda(typeof(ObjectConstructor<object>), callExpression, argsParameterExpression);
|
||||
|
||||
ObjectConstructor<object> compiled = (ObjectConstructor<object>)lambdaExpression.Compile();
|
||||
return compiled;
|
||||
}
|
||||
|
||||
public override MethodCall<T, object> CreateMethodCall<T>(MethodBase method)
|
||||
{
|
||||
ValidationUtils.ArgumentNotNull(method, nameof(method));
|
||||
|
||||
Type type = typeof(object);
|
||||
|
||||
ParameterExpression targetParameterExpression = Expression.Parameter(type, "target");
|
||||
ParameterExpression argsParameterExpression = Expression.Parameter(typeof(object[]), "args");
|
||||
|
||||
Expression callExpression = BuildMethodCall(method, type, targetParameterExpression, argsParameterExpression);
|
||||
|
||||
LambdaExpression lambdaExpression = Expression.Lambda(typeof(MethodCall<T, object>), callExpression, targetParameterExpression, argsParameterExpression);
|
||||
|
||||
MethodCall<T, object> compiled = (MethodCall<T, object>)lambdaExpression.Compile();
|
||||
return compiled;
|
||||
}
|
||||
|
||||
private class ByRefParameter
|
||||
{
|
||||
public Expression Value;
|
||||
public ParameterExpression Variable;
|
||||
public bool IsOut;
|
||||
}
|
||||
|
||||
private Expression BuildMethodCall(MethodBase method, Type type, ParameterExpression targetParameterExpression, ParameterExpression argsParameterExpression)
|
||||
{
|
||||
ParameterInfo[] parametersInfo = method.GetParameters();
|
||||
|
||||
Expression[] argsExpression = new Expression[parametersInfo.Length];
|
||||
IList<ByRefParameter> refParameterMap = new List<ByRefParameter>();
|
||||
|
||||
for (int i = 0; i < parametersInfo.Length; i++)
|
||||
{
|
||||
ParameterInfo parameter = parametersInfo[i];
|
||||
Type parameterType = parameter.ParameterType;
|
||||
bool isByRef = false;
|
||||
if (parameterType.IsByRef)
|
||||
{
|
||||
parameterType = parameterType.GetElementType();
|
||||
isByRef = true;
|
||||
}
|
||||
|
||||
Expression indexExpression = Expression.Constant(i);
|
||||
|
||||
Expression paramAccessorExpression = Expression.ArrayIndex(argsParameterExpression, indexExpression);
|
||||
|
||||
Expression argExpression;
|
||||
|
||||
if (parameterType.IsValueType())
|
||||
{
|
||||
BinaryExpression ensureValueTypeNotNull = Expression.Coalesce(paramAccessorExpression, Expression.New(parameterType));
|
||||
|
||||
argExpression = EnsureCastExpression(ensureValueTypeNotNull, parameterType);
|
||||
}
|
||||
else
|
||||
{
|
||||
argExpression = EnsureCastExpression(paramAccessorExpression, parameterType);
|
||||
}
|
||||
|
||||
if (isByRef)
|
||||
{
|
||||
ParameterExpression variable = Expression.Variable(parameterType);
|
||||
refParameterMap.Add(new ByRefParameter
|
||||
{
|
||||
Value = argExpression,
|
||||
Variable = variable,
|
||||
IsOut = parameter.IsOut
|
||||
});
|
||||
|
||||
argExpression = variable;
|
||||
}
|
||||
|
||||
argsExpression[i] = argExpression;
|
||||
}
|
||||
|
||||
Expression callExpression;
|
||||
if (method.IsConstructor)
|
||||
{
|
||||
callExpression = Expression.New((ConstructorInfo)method, argsExpression);
|
||||
}
|
||||
else if (method.IsStatic)
|
||||
{
|
||||
callExpression = Expression.Call((MethodInfo)method, argsExpression);
|
||||
}
|
||||
else
|
||||
{
|
||||
Expression readParameter = EnsureCastExpression(targetParameterExpression, method.DeclaringType);
|
||||
|
||||
callExpression = Expression.Call(readParameter, (MethodInfo)method, argsExpression);
|
||||
}
|
||||
|
||||
if (method is MethodInfo)
|
||||
{
|
||||
MethodInfo m = (MethodInfo)method;
|
||||
if (m.ReturnType != typeof(void))
|
||||
{
|
||||
callExpression = EnsureCastExpression(callExpression, type);
|
||||
}
|
||||
else
|
||||
{
|
||||
callExpression = Expression.Block(callExpression, Expression.Constant(null));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
callExpression = EnsureCastExpression(callExpression, type);
|
||||
}
|
||||
|
||||
if (refParameterMap.Count > 0)
|
||||
{
|
||||
IList<ParameterExpression> variableExpressions = new List<ParameterExpression>();
|
||||
IList<Expression> bodyExpressions = new List<Expression>();
|
||||
foreach (ByRefParameter p in refParameterMap)
|
||||
{
|
||||
if (!p.IsOut)
|
||||
{
|
||||
bodyExpressions.Add(Expression.Assign(p.Variable, p.Value));
|
||||
}
|
||||
|
||||
variableExpressions.Add(p.Variable);
|
||||
}
|
||||
|
||||
bodyExpressions.Add(callExpression);
|
||||
|
||||
callExpression = Expression.Block(variableExpressions, bodyExpressions);
|
||||
}
|
||||
|
||||
return callExpression;
|
||||
}
|
||||
|
||||
public override Func<T> CreateDefaultConstructor<T>(Type type)
|
||||
{
|
||||
ValidationUtils.ArgumentNotNull(type, "type");
|
||||
|
||||
// avoid error from expressions compiler because of abstract class
|
||||
if (type.IsAbstract())
|
||||
{
|
||||
return () => (T)Activator.CreateInstance(type);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
Type resultType = typeof(T);
|
||||
|
||||
Expression expression = Expression.New(type);
|
||||
|
||||
expression = EnsureCastExpression(expression, resultType);
|
||||
|
||||
LambdaExpression lambdaExpression = Expression.Lambda(typeof(Func<T>), expression);
|
||||
|
||||
Func<T> compiled = (Func<T>)lambdaExpression.Compile();
|
||||
return compiled;
|
||||
}
|
||||
catch
|
||||
{
|
||||
// an error can be thrown if constructor is not valid on Win8
|
||||
// will have INVOCATION_FLAGS_NON_W8P_FX_API invocation flag
|
||||
return () => (T)Activator.CreateInstance(type);
|
||||
}
|
||||
}
|
||||
|
||||
public override Func<T, object> CreateGet<T>(PropertyInfo propertyInfo)
|
||||
{
|
||||
ValidationUtils.ArgumentNotNull(propertyInfo, nameof(propertyInfo));
|
||||
|
||||
Type instanceType = typeof(T);
|
||||
Type resultType = typeof(object);
|
||||
|
||||
ParameterExpression parameterExpression = Expression.Parameter(instanceType, "instance");
|
||||
Expression resultExpression;
|
||||
|
||||
MethodInfo getMethod = propertyInfo.GetGetMethod(true);
|
||||
|
||||
if (getMethod.IsStatic)
|
||||
{
|
||||
resultExpression = Expression.MakeMemberAccess(null, propertyInfo);
|
||||
}
|
||||
else
|
||||
{
|
||||
Expression readParameter = EnsureCastExpression(parameterExpression, propertyInfo.DeclaringType);
|
||||
|
||||
resultExpression = Expression.MakeMemberAccess(readParameter, propertyInfo);
|
||||
}
|
||||
|
||||
resultExpression = EnsureCastExpression(resultExpression, resultType);
|
||||
|
||||
LambdaExpression lambdaExpression = Expression.Lambda(typeof(Func<T, object>), resultExpression, parameterExpression);
|
||||
|
||||
Func<T, object> compiled = (Func<T, object>)lambdaExpression.Compile();
|
||||
return compiled;
|
||||
}
|
||||
|
||||
public override Func<T, object> CreateGet<T>(FieldInfo fieldInfo)
|
||||
{
|
||||
ValidationUtils.ArgumentNotNull(fieldInfo, nameof(fieldInfo));
|
||||
|
||||
ParameterExpression sourceParameter = Expression.Parameter(typeof(T), "source");
|
||||
|
||||
Expression fieldExpression;
|
||||
if (fieldInfo.IsStatic)
|
||||
{
|
||||
fieldExpression = Expression.Field(null, fieldInfo);
|
||||
}
|
||||
else
|
||||
{
|
||||
Expression sourceExpression = EnsureCastExpression(sourceParameter, fieldInfo.DeclaringType);
|
||||
|
||||
fieldExpression = Expression.Field(sourceExpression, fieldInfo);
|
||||
}
|
||||
|
||||
fieldExpression = EnsureCastExpression(fieldExpression, typeof(object));
|
||||
|
||||
Func<T, object> compiled = Expression.Lambda<Func<T, object>>(fieldExpression, sourceParameter).Compile();
|
||||
return compiled;
|
||||
}
|
||||
|
||||
public override Action<T, object> CreateSet<T>(FieldInfo fieldInfo)
|
||||
{
|
||||
ValidationUtils.ArgumentNotNull(fieldInfo, nameof(fieldInfo));
|
||||
|
||||
// use reflection for structs
|
||||
// expression doesn't correctly set value
|
||||
if (fieldInfo.DeclaringType.IsValueType() || fieldInfo.IsInitOnly)
|
||||
{
|
||||
return LateBoundReflectionDelegateFactory.Instance.CreateSet<T>(fieldInfo);
|
||||
}
|
||||
|
||||
ParameterExpression sourceParameterExpression = Expression.Parameter(typeof(T), "source");
|
||||
ParameterExpression valueParameterExpression = Expression.Parameter(typeof(object), "value");
|
||||
|
||||
Expression fieldExpression;
|
||||
if (fieldInfo.IsStatic)
|
||||
{
|
||||
fieldExpression = Expression.Field(null, fieldInfo);
|
||||
}
|
||||
else
|
||||
{
|
||||
Expression sourceExpression = EnsureCastExpression(sourceParameterExpression, fieldInfo.DeclaringType);
|
||||
|
||||
fieldExpression = Expression.Field(sourceExpression, fieldInfo);
|
||||
}
|
||||
|
||||
Expression valueExpression = EnsureCastExpression(valueParameterExpression, fieldExpression.Type);
|
||||
|
||||
BinaryExpression assignExpression = Expression.Assign(fieldExpression, valueExpression);
|
||||
|
||||
LambdaExpression lambdaExpression = Expression.Lambda(typeof(Action<T, object>), assignExpression, sourceParameterExpression, valueParameterExpression);
|
||||
|
||||
Action<T, object> compiled = (Action<T, object>)lambdaExpression.Compile();
|
||||
return compiled;
|
||||
}
|
||||
|
||||
public override Action<T, object> CreateSet<T>(PropertyInfo propertyInfo)
|
||||
{
|
||||
ValidationUtils.ArgumentNotNull(propertyInfo, nameof(propertyInfo));
|
||||
|
||||
// use reflection for structs
|
||||
// expression doesn't correctly set value
|
||||
if (propertyInfo.DeclaringType.IsValueType())
|
||||
{
|
||||
return LateBoundReflectionDelegateFactory.Instance.CreateSet<T>(propertyInfo);
|
||||
}
|
||||
|
||||
Type instanceType = typeof(T);
|
||||
Type valueType = typeof(object);
|
||||
|
||||
ParameterExpression instanceParameter = Expression.Parameter(instanceType, "instance");
|
||||
|
||||
ParameterExpression valueParameter = Expression.Parameter(valueType, "value");
|
||||
Expression readValueParameter = EnsureCastExpression(valueParameter, propertyInfo.PropertyType);
|
||||
|
||||
MethodInfo setMethod = propertyInfo.GetSetMethod(true);
|
||||
|
||||
Expression setExpression;
|
||||
if (setMethod.IsStatic)
|
||||
{
|
||||
setExpression = Expression.Call(setMethod, readValueParameter);
|
||||
}
|
||||
else
|
||||
{
|
||||
Expression readInstanceParameter = EnsureCastExpression(instanceParameter, propertyInfo.DeclaringType);
|
||||
|
||||
setExpression = Expression.Call(readInstanceParameter, setMethod, readValueParameter);
|
||||
}
|
||||
|
||||
LambdaExpression lambdaExpression = Expression.Lambda(typeof(Action<T, object>), setExpression, instanceParameter, valueParameter);
|
||||
|
||||
Action<T, object> compiled = (Action<T, object>)lambdaExpression.Compile();
|
||||
return compiled;
|
||||
}
|
||||
|
||||
private Expression EnsureCastExpression(Expression expression, Type targetType)
|
||||
{
|
||||
Type expressionType = expression.Type;
|
||||
|
||||
// check if a cast or conversion is required
|
||||
if (expressionType == targetType || (!expressionType.IsValueType() && targetType.IsAssignableFrom(expressionType)))
|
||||
{
|
||||
return expression;
|
||||
}
|
||||
|
||||
return Expression.Convert(expression, targetType);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
195
Common/00-1Json8.3/Json8.3/Utilities/FSharpUtils.cs
Normal file
195
Common/00-1Json8.3/Json8.3/Utilities/FSharpUtils.cs
Normal file
@@ -0,0 +1,195 @@
|
||||
#region License
|
||||
// Copyright (c) 2007 James Newton-King
|
||||
//
|
||||
// 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
|
||||
|
||||
#if !(NET35 || NET20)
|
||||
using System.Threading;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using Newtonsoft.Json.Serialization;
|
||||
|
||||
namespace Newtonsoft.Json.Utilities
|
||||
{
|
||||
internal class FSharpFunction
|
||||
{
|
||||
private readonly object _instance;
|
||||
private readonly MethodCall<object, object> _invoker;
|
||||
|
||||
public FSharpFunction(object instance, MethodCall<object, object> invoker)
|
||||
{
|
||||
_instance = instance;
|
||||
_invoker = invoker;
|
||||
}
|
||||
|
||||
public object Invoke(params object[] args)
|
||||
{
|
||||
object o = _invoker(_instance, args);
|
||||
|
||||
return o;
|
||||
}
|
||||
}
|
||||
|
||||
internal static class FSharpUtils
|
||||
{
|
||||
private static readonly object Lock = new object();
|
||||
|
||||
private static bool _initialized;
|
||||
private static MethodInfo _ofSeq;
|
||||
private static Type _mapType;
|
||||
|
||||
public static Assembly FSharpCoreAssembly { get; private set; }
|
||||
public static MethodCall<object, object> IsUnion { get; private set; }
|
||||
public static MethodCall<object, object> GetUnionCases { get; private set; }
|
||||
public static MethodCall<object, object> PreComputeUnionTagReader { get; private set; }
|
||||
public static MethodCall<object, object> PreComputeUnionReader { get; private set; }
|
||||
public static MethodCall<object, object> PreComputeUnionConstructor { get; private set; }
|
||||
public static Func<object, object> GetUnionCaseInfoDeclaringType { get; private set; }
|
||||
public static Func<object, object> GetUnionCaseInfoName { get; private set; }
|
||||
public static Func<object, object> GetUnionCaseInfoTag { get; private set; }
|
||||
public static MethodCall<object, object> GetUnionCaseInfoFields { get; private set; }
|
||||
|
||||
public const string FSharpSetTypeName = "FSharpSet`1";
|
||||
public const string FSharpListTypeName = "FSharpList`1";
|
||||
public const string FSharpMapTypeName = "FSharpMap`2";
|
||||
|
||||
public static void EnsureInitialized(Assembly fsharpCoreAssembly)
|
||||
{
|
||||
if (!_initialized)
|
||||
{
|
||||
lock (Lock)
|
||||
{
|
||||
if (!_initialized)
|
||||
{
|
||||
FSharpCoreAssembly = fsharpCoreAssembly;
|
||||
|
||||
Type fsharpType = fsharpCoreAssembly.GetType("Microsoft.FSharp.Reflection.FSharpType");
|
||||
|
||||
MethodInfo isUnionMethodInfo = GetMethodWithNonPublicFallback(fsharpType, "IsUnion", BindingFlags.Public | BindingFlags.Static);
|
||||
IsUnion = JsonTypeReflector.ReflectionDelegateFactory.CreateMethodCall<object>(isUnionMethodInfo);
|
||||
|
||||
MethodInfo getUnionCasesMethodInfo = GetMethodWithNonPublicFallback(fsharpType, "GetUnionCases", BindingFlags.Public | BindingFlags.Static);
|
||||
GetUnionCases = JsonTypeReflector.ReflectionDelegateFactory.CreateMethodCall<object>(getUnionCasesMethodInfo);
|
||||
|
||||
Type fsharpValue = fsharpCoreAssembly.GetType("Microsoft.FSharp.Reflection.FSharpValue");
|
||||
|
||||
PreComputeUnionTagReader = CreateFSharpFuncCall(fsharpValue, "PreComputeUnionTagReader");
|
||||
PreComputeUnionReader = CreateFSharpFuncCall(fsharpValue, "PreComputeUnionReader");
|
||||
PreComputeUnionConstructor = CreateFSharpFuncCall(fsharpValue, "PreComputeUnionConstructor");
|
||||
|
||||
Type unionCaseInfo = fsharpCoreAssembly.GetType("Microsoft.FSharp.Reflection.UnionCaseInfo");
|
||||
|
||||
GetUnionCaseInfoName = JsonTypeReflector.ReflectionDelegateFactory.CreateGet<object>(unionCaseInfo.GetProperty("Name"));
|
||||
GetUnionCaseInfoTag = JsonTypeReflector.ReflectionDelegateFactory.CreateGet<object>(unionCaseInfo.GetProperty("Tag"));
|
||||
GetUnionCaseInfoDeclaringType = JsonTypeReflector.ReflectionDelegateFactory.CreateGet<object>(unionCaseInfo.GetProperty("DeclaringType"));
|
||||
GetUnionCaseInfoFields = JsonTypeReflector.ReflectionDelegateFactory.CreateMethodCall<object>(unionCaseInfo.GetMethod("GetFields"));
|
||||
|
||||
Type listModule = fsharpCoreAssembly.GetType("Microsoft.FSharp.Collections.ListModule");
|
||||
_ofSeq = listModule.GetMethod("OfSeq");
|
||||
|
||||
_mapType = fsharpCoreAssembly.GetType("Microsoft.FSharp.Collections.FSharpMap`2");
|
||||
|
||||
#if !(DOTNET || PORTABLE)
|
||||
Thread.MemoryBarrier();
|
||||
#endif
|
||||
_initialized = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static MethodInfo GetMethodWithNonPublicFallback(Type type, string methodName, BindingFlags bindingFlags)
|
||||
{
|
||||
MethodInfo methodInfo = type.GetMethod(methodName, bindingFlags);
|
||||
|
||||
// if no matching method then attempt to find with nonpublic flag
|
||||
// this is required because in WinApps some methods are private but always using NonPublic breaks medium trust
|
||||
// https://github.com/JamesNK/Newtonsoft.Json/pull/649
|
||||
// https://github.com/JamesNK/Newtonsoft.Json/issues/821
|
||||
if (methodInfo == null && (bindingFlags & BindingFlags.NonPublic) != BindingFlags.NonPublic)
|
||||
{
|
||||
methodInfo = type.GetMethod(methodName, bindingFlags | BindingFlags.NonPublic);
|
||||
}
|
||||
|
||||
return methodInfo;
|
||||
}
|
||||
|
||||
private static MethodCall<object, object> CreateFSharpFuncCall(Type type, string methodName)
|
||||
{
|
||||
MethodInfo innerMethodInfo = GetMethodWithNonPublicFallback(type, methodName, BindingFlags.Public | BindingFlags.Static);
|
||||
MethodInfo invokeFunc = innerMethodInfo.ReturnType.GetMethod("Invoke", BindingFlags.Public | BindingFlags.Instance);
|
||||
|
||||
MethodCall<object, object> call = JsonTypeReflector.ReflectionDelegateFactory.CreateMethodCall<object>(innerMethodInfo);
|
||||
MethodCall<object, object> invoke = JsonTypeReflector.ReflectionDelegateFactory.CreateMethodCall<object>(invokeFunc);
|
||||
|
||||
MethodCall<object, object> createFunction = (target, args) =>
|
||||
{
|
||||
object result = call(target, args);
|
||||
|
||||
FSharpFunction f = new FSharpFunction(result, invoke);
|
||||
return f;
|
||||
};
|
||||
|
||||
return createFunction;
|
||||
}
|
||||
|
||||
public static ObjectConstructor<object> CreateSeq(Type t)
|
||||
{
|
||||
MethodInfo seqType = _ofSeq.MakeGenericMethod(t);
|
||||
|
||||
return JsonTypeReflector.ReflectionDelegateFactory.CreateParameterizedConstructor(seqType);
|
||||
}
|
||||
|
||||
public static ObjectConstructor<object> CreateMap(Type keyType, Type valueType)
|
||||
{
|
||||
MethodInfo creatorDefinition = typeof(FSharpUtils).GetMethod("BuildMapCreator");
|
||||
|
||||
MethodInfo creatorGeneric = creatorDefinition.MakeGenericMethod(keyType, valueType);
|
||||
|
||||
return (ObjectConstructor<object>)creatorGeneric.Invoke(null, null);
|
||||
}
|
||||
|
||||
public static ObjectConstructor<object> BuildMapCreator<TKey, TValue>()
|
||||
{
|
||||
Type genericMapType = _mapType.MakeGenericType(typeof(TKey), typeof(TValue));
|
||||
ConstructorInfo ctor = genericMapType.GetConstructor(new[] { typeof(IEnumerable<Tuple<TKey, TValue>>) });
|
||||
ObjectConstructor<object> ctorDelegate = JsonTypeReflector.ReflectionDelegateFactory.CreateParameterizedConstructor(ctor);
|
||||
|
||||
ObjectConstructor<object> creator = args =>
|
||||
{
|
||||
// convert dictionary KeyValuePairs to Tuples
|
||||
IEnumerable<KeyValuePair<TKey, TValue>> values = (IEnumerable<KeyValuePair<TKey, TValue>>)args[0];
|
||||
IEnumerable<Tuple<TKey, TValue>> tupleValues = values.Select(kv => new Tuple<TKey, TValue>(kv.Key, kv.Value));
|
||||
|
||||
return ctorDelegate(tupleValues);
|
||||
};
|
||||
|
||||
return creator;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,98 @@
|
||||
#region License
|
||||
// Copyright (c) 2007 James Newton-King
|
||||
//
|
||||
// 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
|
||||
|
||||
#if !(DOTNET || PORTABLE40 || PORTABLE)
|
||||
using System;
|
||||
using System.Reflection.Emit;
|
||||
using System.Reflection;
|
||||
|
||||
namespace Newtonsoft.Json.Utilities
|
||||
{
|
||||
internal static class ILGeneratorExtensions
|
||||
{
|
||||
public static void PushInstance(this ILGenerator generator, Type type)
|
||||
{
|
||||
generator.Emit(OpCodes.Ldarg_0);
|
||||
if (type.IsValueType())
|
||||
{
|
||||
generator.Emit(OpCodes.Unbox, type);
|
||||
}
|
||||
else
|
||||
{
|
||||
generator.Emit(OpCodes.Castclass, type);
|
||||
}
|
||||
}
|
||||
|
||||
public static void PushArrayInstance(this ILGenerator generator, int argsIndex, int arrayIndex)
|
||||
{
|
||||
generator.Emit(OpCodes.Ldarg, argsIndex);
|
||||
generator.Emit(OpCodes.Ldc_I4, arrayIndex);
|
||||
generator.Emit(OpCodes.Ldelem_Ref);
|
||||
}
|
||||
|
||||
public static void BoxIfNeeded(this ILGenerator generator, Type type)
|
||||
{
|
||||
if (type.IsValueType())
|
||||
{
|
||||
generator.Emit(OpCodes.Box, type);
|
||||
}
|
||||
else
|
||||
{
|
||||
generator.Emit(OpCodes.Castclass, type);
|
||||
}
|
||||
}
|
||||
|
||||
public static void UnboxIfNeeded(this ILGenerator generator, Type type)
|
||||
{
|
||||
if (type.IsValueType())
|
||||
{
|
||||
generator.Emit(OpCodes.Unbox_Any, type);
|
||||
}
|
||||
else
|
||||
{
|
||||
generator.Emit(OpCodes.Castclass, type);
|
||||
}
|
||||
}
|
||||
|
||||
public static void CallMethod(this ILGenerator generator, MethodInfo methodInfo)
|
||||
{
|
||||
if (methodInfo.IsFinal || !methodInfo.IsVirtual)
|
||||
{
|
||||
generator.Emit(OpCodes.Call, methodInfo);
|
||||
}
|
||||
else
|
||||
{
|
||||
generator.Emit(OpCodes.Callvirt, methodInfo);
|
||||
}
|
||||
}
|
||||
|
||||
public static void Return(this ILGenerator generator)
|
||||
{
|
||||
generator.Emit(OpCodes.Ret);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,176 @@
|
||||
#region License
|
||||
// Copyright (c) 2007 James Newton-King
|
||||
//
|
||||
// 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
|
||||
|
||||
#if !(NET20 || NET35 || NET40)
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Newtonsoft.Json.Serialization;
|
||||
|
||||
namespace Newtonsoft.Json.Utilities
|
||||
{
|
||||
internal static class ImmutableCollectionsUtils
|
||||
{
|
||||
internal class ImmutableCollectionTypeInfo
|
||||
{
|
||||
public ImmutableCollectionTypeInfo(string contractTypeName, string createdTypeName, string builderTypeName)
|
||||
{
|
||||
ContractTypeName = contractTypeName;
|
||||
CreatedTypeName = createdTypeName;
|
||||
BuilderTypeName = builderTypeName;
|
||||
}
|
||||
|
||||
public string ContractTypeName { get; set; }
|
||||
public string CreatedTypeName { get; set; }
|
||||
public string BuilderTypeName { get; set; }
|
||||
}
|
||||
|
||||
private const string ImmutableListGenericInterfaceTypeName = "System.Collections.Immutable.IImmutableList`1";
|
||||
private const string ImmutableQueueGenericInterfaceTypeName = "System.Collections.Immutable.IImmutableQueue`1";
|
||||
private const string ImmutableStackGenericInterfaceTypeName = "System.Collections.Immutable.IImmutableStack`1";
|
||||
private const string ImmutableSetGenericInterfaceTypeName = "System.Collections.Immutable.IImmutableSet`1";
|
||||
|
||||
private const string ImmutableArrayTypeName = "System.Collections.Immutable.ImmutableArray";
|
||||
private const string ImmutableArrayGenericTypeName = "System.Collections.Immutable.ImmutableArray`1";
|
||||
|
||||
private const string ImmutableListTypeName = "System.Collections.Immutable.ImmutableList";
|
||||
private const string ImmutableListGenericTypeName = "System.Collections.Immutable.ImmutableList`1";
|
||||
|
||||
private const string ImmutableQueueTypeName = "System.Collections.Immutable.ImmutableQueue";
|
||||
private const string ImmutableQueueGenericTypeName = "System.Collections.Immutable.ImmutableQueue`1";
|
||||
|
||||
private const string ImmutableStackTypeName = "System.Collections.Immutable.ImmutableStack";
|
||||
private const string ImmutableStackGenericTypeName = "System.Collections.Immutable.ImmutableStack`1";
|
||||
|
||||
private const string ImmutableSortedSetTypeName = "System.Collections.Immutable.ImmutableSortedSet";
|
||||
private const string ImmutableSortedSetGenericTypeName = "System.Collections.Immutable.ImmutableSortedSet`1";
|
||||
|
||||
private const string ImmutableHashSetTypeName = "System.Collections.Immutable.ImmutableHashSet";
|
||||
private const string ImmutableHashSetGenericTypeName = "System.Collections.Immutable.ImmutableHashSet`1";
|
||||
|
||||
private static readonly IList<ImmutableCollectionTypeInfo> ArrayContractImmutableCollectionDefinitions = new List<ImmutableCollectionTypeInfo>
|
||||
{
|
||||
new ImmutableCollectionTypeInfo(ImmutableListGenericInterfaceTypeName, ImmutableListGenericTypeName, ImmutableListTypeName),
|
||||
new ImmutableCollectionTypeInfo(ImmutableListGenericTypeName, ImmutableListGenericTypeName, ImmutableListTypeName),
|
||||
new ImmutableCollectionTypeInfo(ImmutableQueueGenericInterfaceTypeName, ImmutableQueueGenericTypeName, ImmutableQueueTypeName),
|
||||
new ImmutableCollectionTypeInfo(ImmutableQueueGenericTypeName, ImmutableQueueGenericTypeName, ImmutableQueueTypeName),
|
||||
new ImmutableCollectionTypeInfo(ImmutableStackGenericInterfaceTypeName, ImmutableStackGenericTypeName, ImmutableStackTypeName),
|
||||
new ImmutableCollectionTypeInfo(ImmutableStackGenericTypeName, ImmutableStackGenericTypeName, ImmutableStackTypeName),
|
||||
new ImmutableCollectionTypeInfo(ImmutableSetGenericInterfaceTypeName, ImmutableSortedSetGenericTypeName, ImmutableSortedSetTypeName),
|
||||
new ImmutableCollectionTypeInfo(ImmutableSortedSetGenericTypeName, ImmutableSortedSetGenericTypeName, ImmutableSortedSetTypeName),
|
||||
new ImmutableCollectionTypeInfo(ImmutableHashSetGenericTypeName, ImmutableHashSetGenericTypeName, ImmutableHashSetTypeName),
|
||||
new ImmutableCollectionTypeInfo(ImmutableArrayGenericTypeName, ImmutableArrayGenericTypeName, ImmutableArrayTypeName)
|
||||
};
|
||||
|
||||
private const string ImmutableDictionaryGenericInterfaceTypeName = "System.Collections.Immutable.IImmutableDictionary`2";
|
||||
|
||||
private const string ImmutableDictionaryTypeName = "System.Collections.Immutable.ImmutableDictionary";
|
||||
private const string ImmutableDictionaryGenericTypeName = "System.Collections.Immutable.ImmutableDictionary`2";
|
||||
|
||||
private const string ImmutableSortedDictionaryTypeName = "System.Collections.Immutable.ImmutableSortedDictionary";
|
||||
private const string ImmutableSortedDictionaryGenericTypeName = "System.Collections.Immutable.ImmutableSortedDictionary`2";
|
||||
|
||||
private static readonly IList<ImmutableCollectionTypeInfo> DictionaryContractImmutableCollectionDefinitions = new List<ImmutableCollectionTypeInfo>
|
||||
{
|
||||
new ImmutableCollectionTypeInfo(ImmutableDictionaryGenericInterfaceTypeName, ImmutableSortedDictionaryGenericTypeName, ImmutableSortedDictionaryTypeName),
|
||||
new ImmutableCollectionTypeInfo(ImmutableSortedDictionaryGenericTypeName, ImmutableSortedDictionaryGenericTypeName, ImmutableSortedDictionaryTypeName),
|
||||
new ImmutableCollectionTypeInfo(ImmutableDictionaryGenericTypeName, ImmutableDictionaryGenericTypeName, ImmutableDictionaryTypeName)
|
||||
};
|
||||
|
||||
internal static bool TryBuildImmutableForArrayContract(Type underlyingType, Type collectionItemType, out Type createdType, out ObjectConstructor<object> parameterizedCreator)
|
||||
{
|
||||
if (underlyingType.IsGenericType())
|
||||
{
|
||||
Type underlyingTypeDefinition = underlyingType.GetGenericTypeDefinition();
|
||||
string name = underlyingTypeDefinition.FullName;
|
||||
|
||||
ImmutableCollectionTypeInfo definition = ArrayContractImmutableCollectionDefinitions.FirstOrDefault(d => d.ContractTypeName == name);
|
||||
if (definition != null)
|
||||
{
|
||||
Type createdTypeDefinition = underlyingTypeDefinition.Assembly().GetType(definition.CreatedTypeName);
|
||||
Type builderTypeDefinition = underlyingTypeDefinition.Assembly().GetType(definition.BuilderTypeName);
|
||||
|
||||
if (createdTypeDefinition != null && builderTypeDefinition != null)
|
||||
{
|
||||
MethodInfo mb = builderTypeDefinition.GetMethods().FirstOrDefault(m => m.Name == "CreateRange" && m.GetParameters().Length == 1);
|
||||
if (mb != null)
|
||||
{
|
||||
createdType = createdTypeDefinition.MakeGenericType(collectionItemType);
|
||||
MethodInfo method = mb.MakeGenericMethod(collectionItemType);
|
||||
parameterizedCreator = JsonTypeReflector.ReflectionDelegateFactory.CreateParameterizedConstructor(method);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
createdType = null;
|
||||
parameterizedCreator = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
internal static bool TryBuildImmutableForDictionaryContract(Type underlyingType, Type keyItemType, Type valueItemType, out Type createdType, out ObjectConstructor<object> parameterizedCreator)
|
||||
{
|
||||
if (underlyingType.IsGenericType())
|
||||
{
|
||||
Type underlyingTypeDefinition = underlyingType.GetGenericTypeDefinition();
|
||||
string name = underlyingTypeDefinition.FullName;
|
||||
|
||||
ImmutableCollectionTypeInfo definition = DictionaryContractImmutableCollectionDefinitions.FirstOrDefault(d => d.ContractTypeName == name);
|
||||
if (definition != null)
|
||||
{
|
||||
Type createdTypeDefinition = underlyingTypeDefinition.Assembly().GetType(definition.CreatedTypeName);
|
||||
Type builderTypeDefinition = underlyingTypeDefinition.Assembly().GetType(definition.BuilderTypeName);
|
||||
|
||||
if (createdTypeDefinition != null && builderTypeDefinition != null)
|
||||
{
|
||||
MethodInfo mb = builderTypeDefinition.GetMethods().FirstOrDefault(m =>
|
||||
{
|
||||
ParameterInfo[] parameters = m.GetParameters();
|
||||
|
||||
return m.Name == "CreateRange" && parameters.Length == 1 && parameters[0].ParameterType.IsGenericType() && parameters[0].ParameterType.GetGenericTypeDefinition() == typeof(IEnumerable<>);
|
||||
});
|
||||
if (mb != null)
|
||||
{
|
||||
createdType = createdTypeDefinition.MakeGenericType(keyItemType, valueItemType);
|
||||
MethodInfo method = mb.MakeGenericMethod(keyItemType, valueItemType);
|
||||
parameterizedCreator = JsonTypeReflector.ReflectionDelegateFactory.CreateParameterizedConstructor(method);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
createdType = null;
|
||||
parameterizedCreator = null;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
318
Common/00-1Json8.3/Json8.3/Utilities/JavaScriptUtils.cs
Normal file
318
Common/00-1Json8.3/Json8.3/Utilities/JavaScriptUtils.cs
Normal file
@@ -0,0 +1,318 @@
|
||||
#region License
|
||||
// Copyright (c) 2007 James Newton-King
|
||||
//
|
||||
// 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;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Collections.Generic;
|
||||
#if NET20
|
||||
using Newtonsoft.Json.Utilities.LinqBridge;
|
||||
#else
|
||||
using System.Linq;
|
||||
|
||||
#endif
|
||||
|
||||
namespace Newtonsoft.Json.Utilities
|
||||
{
|
||||
internal static class BufferUtils
|
||||
{
|
||||
public static char[] RentBuffer(IArrayPool<char> bufferPool, int minSize)
|
||||
{
|
||||
if (bufferPool == null)
|
||||
{
|
||||
return new char[minSize];
|
||||
}
|
||||
|
||||
char[] buffer = bufferPool.Rent(minSize);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
public static void ReturnBuffer(IArrayPool<char> bufferPool, char[] buffer)
|
||||
{
|
||||
if (bufferPool == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
bufferPool.Return(buffer);
|
||||
}
|
||||
|
||||
public static char[] EnsureBufferSize(IArrayPool<char> bufferPool, int size, char[] buffer)
|
||||
{
|
||||
if (bufferPool == null)
|
||||
{
|
||||
return new char[size];
|
||||
}
|
||||
|
||||
if (buffer != null)
|
||||
{
|
||||
bufferPool.Return(buffer);
|
||||
}
|
||||
|
||||
return bufferPool.Rent(size);
|
||||
}
|
||||
}
|
||||
|
||||
internal static class JavaScriptUtils
|
||||
{
|
||||
internal static readonly bool[] SingleQuoteCharEscapeFlags = new bool[128];
|
||||
internal static readonly bool[] DoubleQuoteCharEscapeFlags = new bool[128];
|
||||
internal static readonly bool[] HtmlCharEscapeFlags = new bool[128];
|
||||
|
||||
private const int UnicodeTextLength = 6;
|
||||
|
||||
static JavaScriptUtils()
|
||||
{
|
||||
IList<char> escapeChars = new List<char>
|
||||
{
|
||||
'\n', '\r', '\t', '\\', '\f', '\b',
|
||||
};
|
||||
for (int i = 0; i < ' '; i++)
|
||||
{
|
||||
escapeChars.Add((char)i);
|
||||
}
|
||||
|
||||
foreach (var escapeChar in escapeChars.Union(new[] { '\'' }))
|
||||
{
|
||||
SingleQuoteCharEscapeFlags[escapeChar] = true;
|
||||
}
|
||||
foreach (var escapeChar in escapeChars.Union(new[] { '"' }))
|
||||
{
|
||||
DoubleQuoteCharEscapeFlags[escapeChar] = true;
|
||||
}
|
||||
foreach (var escapeChar in escapeChars.Union(new[] { '"', '\'', '<', '>', '&' }))
|
||||
{
|
||||
HtmlCharEscapeFlags[escapeChar] = true;
|
||||
}
|
||||
}
|
||||
|
||||
private const string EscapedUnicodeText = "!";
|
||||
|
||||
public static bool[] GetCharEscapeFlags(StringEscapeHandling stringEscapeHandling, char quoteChar)
|
||||
{
|
||||
if (stringEscapeHandling == StringEscapeHandling.EscapeHtml)
|
||||
{
|
||||
return HtmlCharEscapeFlags;
|
||||
}
|
||||
|
||||
if (quoteChar == '"')
|
||||
{
|
||||
return DoubleQuoteCharEscapeFlags;
|
||||
}
|
||||
|
||||
return SingleQuoteCharEscapeFlags;
|
||||
}
|
||||
|
||||
public static bool ShouldEscapeJavaScriptString(string s, bool[] charEscapeFlags)
|
||||
{
|
||||
if (s == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
foreach (char c in s)
|
||||
{
|
||||
if (c >= charEscapeFlags.Length || charEscapeFlags[c])
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static void WriteEscapedJavaScriptString(TextWriter writer, string s, char delimiter, bool appendDelimiters,
|
||||
bool[] charEscapeFlags, StringEscapeHandling stringEscapeHandling, IArrayPool<char> bufferPool, ref char[] writeBuffer)
|
||||
{
|
||||
// leading delimiter
|
||||
if (appendDelimiters)
|
||||
{
|
||||
writer.Write(delimiter);
|
||||
}
|
||||
|
||||
if (s != null)
|
||||
{
|
||||
int lastWritePosition = 0;
|
||||
|
||||
for (int i = 0; i < s.Length; i++)
|
||||
{
|
||||
var c = s[i];
|
||||
|
||||
if (c < charEscapeFlags.Length && !charEscapeFlags[c])
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
string escapedValue;
|
||||
|
||||
switch (c)
|
||||
{
|
||||
case '\t':
|
||||
escapedValue = @"\t";
|
||||
break;
|
||||
case '\n':
|
||||
escapedValue = @"\n";
|
||||
break;
|
||||
case '\r':
|
||||
escapedValue = @"\r";
|
||||
break;
|
||||
case '\f':
|
||||
escapedValue = @"\f";
|
||||
break;
|
||||
case '\b':
|
||||
escapedValue = @"\b";
|
||||
break;
|
||||
case '\\':
|
||||
escapedValue = @"\\";
|
||||
break;
|
||||
case '\u0085': // Next Line
|
||||
escapedValue = @"\u0085";
|
||||
break;
|
||||
case '\u2028': // Line Separator
|
||||
escapedValue = @"\u2028";
|
||||
break;
|
||||
case '\u2029': // Paragraph Separator
|
||||
escapedValue = @"\u2029";
|
||||
break;
|
||||
default:
|
||||
if (c < charEscapeFlags.Length || stringEscapeHandling == StringEscapeHandling.EscapeNonAscii)
|
||||
{
|
||||
if (c == '\'' && stringEscapeHandling != StringEscapeHandling.EscapeHtml)
|
||||
{
|
||||
escapedValue = @"\'";
|
||||
}
|
||||
else if (c == '"' && stringEscapeHandling != StringEscapeHandling.EscapeHtml)
|
||||
{
|
||||
escapedValue = @"\""";
|
||||
}
|
||||
else
|
||||
{
|
||||
if (writeBuffer == null || writeBuffer.Length < UnicodeTextLength)
|
||||
{
|
||||
writeBuffer = BufferUtils.EnsureBufferSize(bufferPool, UnicodeTextLength, writeBuffer);
|
||||
}
|
||||
|
||||
StringUtils.ToCharAsUnicode(c, writeBuffer);
|
||||
|
||||
// slightly hacky but it saves multiple conditions in if test
|
||||
escapedValue = EscapedUnicodeText;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
escapedValue = null;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (escapedValue == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
bool isEscapedUnicodeText = string.Equals(escapedValue, EscapedUnicodeText);
|
||||
|
||||
if (i > lastWritePosition)
|
||||
{
|
||||
int length = i - lastWritePosition + ((isEscapedUnicodeText) ? UnicodeTextLength : 0);
|
||||
int start = (isEscapedUnicodeText) ? UnicodeTextLength : 0;
|
||||
|
||||
if (writeBuffer == null || writeBuffer.Length < length)
|
||||
{
|
||||
char[] newBuffer = BufferUtils.RentBuffer(bufferPool, length);
|
||||
|
||||
// the unicode text is already in the buffer
|
||||
// copy it over when creating new buffer
|
||||
if (isEscapedUnicodeText)
|
||||
{
|
||||
Array.Copy(writeBuffer, newBuffer, UnicodeTextLength);
|
||||
}
|
||||
|
||||
BufferUtils.ReturnBuffer(bufferPool, writeBuffer);
|
||||
|
||||
writeBuffer = newBuffer;
|
||||
}
|
||||
|
||||
s.CopyTo(lastWritePosition, writeBuffer, start, length - start);
|
||||
|
||||
// write unchanged chars before writing escaped text
|
||||
writer.Write(writeBuffer, start, length - start);
|
||||
}
|
||||
|
||||
lastWritePosition = i + 1;
|
||||
if (!isEscapedUnicodeText)
|
||||
{
|
||||
writer.Write(escapedValue);
|
||||
}
|
||||
else
|
||||
{
|
||||
writer.Write(writeBuffer, 0, UnicodeTextLength);
|
||||
}
|
||||
}
|
||||
|
||||
if (lastWritePosition == 0)
|
||||
{
|
||||
// no escaped text, write entire string
|
||||
writer.Write(s);
|
||||
}
|
||||
else
|
||||
{
|
||||
int length = s.Length - lastWritePosition;
|
||||
|
||||
if (writeBuffer == null || writeBuffer.Length < length)
|
||||
{
|
||||
writeBuffer = BufferUtils.EnsureBufferSize(bufferPool, length, writeBuffer);
|
||||
}
|
||||
|
||||
s.CopyTo(lastWritePosition, writeBuffer, 0, length);
|
||||
|
||||
// write remaining text
|
||||
writer.Write(writeBuffer, 0, length);
|
||||
}
|
||||
}
|
||||
|
||||
// trailing delimiter
|
||||
if (appendDelimiters)
|
||||
{
|
||||
writer.Write(delimiter);
|
||||
}
|
||||
}
|
||||
|
||||
public static string ToEscapedJavaScriptString(string value, char delimiter, bool appendDelimiters, StringEscapeHandling stringEscapeHandling)
|
||||
{
|
||||
bool[] charEscapeFlags = GetCharEscapeFlags(stringEscapeHandling, delimiter);
|
||||
|
||||
using (StringWriter w = StringUtils.CreateStringWriter(StringUtils.GetLength(value) ?? 16))
|
||||
{
|
||||
char[] buffer = null;
|
||||
WriteEscapedJavaScriptString(w, value, delimiter, appendDelimiters, charEscapeFlags, stringEscapeHandling, null, ref buffer);
|
||||
return w.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
77
Common/00-1Json8.3/Json8.3/Utilities/JsonTokenUtils.cs
Normal file
77
Common/00-1Json8.3/Json8.3/Utilities/JsonTokenUtils.cs
Normal file
@@ -0,0 +1,77 @@
|
||||
#region License
|
||||
// Copyright (c) 2007 James Newton-King
|
||||
//
|
||||
// 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.Text;
|
||||
|
||||
namespace Newtonsoft.Json.Utilities
|
||||
{
|
||||
internal static class JsonTokenUtils
|
||||
{
|
||||
internal static bool IsEndToken(JsonToken token)
|
||||
{
|
||||
switch (token)
|
||||
{
|
||||
case JsonToken.EndObject:
|
||||
case JsonToken.EndArray:
|
||||
case JsonToken.EndConstructor:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
internal static bool IsStartToken(JsonToken token)
|
||||
{
|
||||
switch (token)
|
||||
{
|
||||
case JsonToken.StartObject:
|
||||
case JsonToken.StartArray:
|
||||
case JsonToken.StartConstructor:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
internal static bool IsPrimitiveToken(JsonToken token)
|
||||
{
|
||||
switch (token)
|
||||
{
|
||||
case JsonToken.Integer:
|
||||
case JsonToken.Float:
|
||||
case JsonToken.String:
|
||||
case JsonToken.Boolean:
|
||||
case JsonToken.Undefined:
|
||||
case JsonToken.Null:
|
||||
case JsonToken.Date:
|
||||
case JsonToken.Bytes:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,119 @@
|
||||
#region License
|
||||
// Copyright (c) 2007 James Newton-King
|
||||
//
|
||||
// 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 Newtonsoft.Json.Serialization;
|
||||
using System.Reflection;
|
||||
|
||||
#if NET20
|
||||
using Newtonsoft.Json.Utilities.LinqBridge;
|
||||
#endif
|
||||
|
||||
namespace Newtonsoft.Json.Utilities
|
||||
{
|
||||
internal class LateBoundReflectionDelegateFactory : ReflectionDelegateFactory
|
||||
{
|
||||
private static readonly LateBoundReflectionDelegateFactory _instance = new LateBoundReflectionDelegateFactory();
|
||||
|
||||
internal static ReflectionDelegateFactory Instance
|
||||
{
|
||||
get { return _instance; }
|
||||
}
|
||||
|
||||
public override ObjectConstructor<object> CreateParameterizedConstructor(MethodBase method)
|
||||
{
|
||||
ValidationUtils.ArgumentNotNull(method, nameof(method));
|
||||
|
||||
ConstructorInfo c = method as ConstructorInfo;
|
||||
if (c != null)
|
||||
{
|
||||
// don't convert to method group to avoid medium trust issues
|
||||
// https://github.com/JamesNK/Newtonsoft.Json/issues/476
|
||||
return a =>
|
||||
{
|
||||
object[] args = a;
|
||||
return c.Invoke(args);
|
||||
};
|
||||
}
|
||||
|
||||
return a => method.Invoke(null, a);
|
||||
}
|
||||
|
||||
public override MethodCall<T, object> CreateMethodCall<T>(MethodBase method)
|
||||
{
|
||||
ValidationUtils.ArgumentNotNull(method, nameof(method));
|
||||
|
||||
ConstructorInfo c = method as ConstructorInfo;
|
||||
if (c != null)
|
||||
{
|
||||
return (o, a) => c.Invoke(a);
|
||||
}
|
||||
|
||||
return (o, a) => method.Invoke(o, a);
|
||||
}
|
||||
|
||||
public override Func<T> CreateDefaultConstructor<T>(Type type)
|
||||
{
|
||||
ValidationUtils.ArgumentNotNull(type, nameof(type));
|
||||
|
||||
if (type.IsValueType())
|
||||
{
|
||||
return () => (T)Activator.CreateInstance(type);
|
||||
}
|
||||
|
||||
ConstructorInfo constructorInfo = ReflectionUtils.GetDefaultConstructor(type, true);
|
||||
|
||||
return () => (T)constructorInfo.Invoke(null);
|
||||
}
|
||||
|
||||
public override Func<T, object> CreateGet<T>(PropertyInfo propertyInfo)
|
||||
{
|
||||
ValidationUtils.ArgumentNotNull(propertyInfo, nameof(propertyInfo));
|
||||
|
||||
return o => propertyInfo.GetValue(o, null);
|
||||
}
|
||||
|
||||
public override Func<T, object> CreateGet<T>(FieldInfo fieldInfo)
|
||||
{
|
||||
ValidationUtils.ArgumentNotNull(fieldInfo, nameof(fieldInfo));
|
||||
|
||||
return o => fieldInfo.GetValue(o);
|
||||
}
|
||||
|
||||
public override Action<T, object> CreateSet<T>(FieldInfo fieldInfo)
|
||||
{
|
||||
ValidationUtils.ArgumentNotNull(fieldInfo, nameof(fieldInfo));
|
||||
|
||||
return (o, v) => fieldInfo.SetValue(o, v);
|
||||
}
|
||||
|
||||
public override Action<T, object> CreateSet<T>(PropertyInfo propertyInfo)
|
||||
{
|
||||
ValidationUtils.ArgumentNotNull(propertyInfo, nameof(propertyInfo));
|
||||
|
||||
return (o, v) => propertyInfo.SetValue(o, v, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
3014
Common/00-1Json8.3/Json8.3/Utilities/LinqBridge.cs
Normal file
3014
Common/00-1Json8.3/Json8.3/Utilities/LinqBridge.cs
Normal file
File diff suppressed because it is too large
Load Diff
187
Common/00-1Json8.3/Json8.3/Utilities/MathUtils.cs
Normal file
187
Common/00-1Json8.3/Json8.3/Utilities/MathUtils.cs
Normal file
@@ -0,0 +1,187 @@
|
||||
#region License
|
||||
// Copyright (c) 2007 James Newton-King
|
||||
//
|
||||
// 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.Text;
|
||||
|
||||
namespace Newtonsoft.Json.Utilities
|
||||
{
|
||||
internal static class MathUtils
|
||||
{
|
||||
public static int IntLength(ulong i)
|
||||
{
|
||||
if (i < 10000000000)
|
||||
{
|
||||
if (i < 10)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
if (i < 100)
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
if (i < 1000)
|
||||
{
|
||||
return 3;
|
||||
}
|
||||
if (i < 10000)
|
||||
{
|
||||
return 4;
|
||||
}
|
||||
if (i < 100000)
|
||||
{
|
||||
return 5;
|
||||
}
|
||||
if (i < 1000000)
|
||||
{
|
||||
return 6;
|
||||
}
|
||||
if (i < 10000000)
|
||||
{
|
||||
return 7;
|
||||
}
|
||||
if (i < 100000000)
|
||||
{
|
||||
return 8;
|
||||
}
|
||||
if (i < 1000000000)
|
||||
{
|
||||
return 9;
|
||||
}
|
||||
|
||||
return 10;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (i < 100000000000)
|
||||
{
|
||||
return 11;
|
||||
}
|
||||
if (i < 1000000000000)
|
||||
{
|
||||
return 12;
|
||||
}
|
||||
if (i < 10000000000000)
|
||||
{
|
||||
return 13;
|
||||
}
|
||||
if (i < 100000000000000)
|
||||
{
|
||||
return 14;
|
||||
}
|
||||
if (i < 1000000000000000)
|
||||
{
|
||||
return 15;
|
||||
}
|
||||
if (i < 10000000000000000)
|
||||
{
|
||||
return 16;
|
||||
}
|
||||
if (i < 100000000000000000)
|
||||
{
|
||||
return 17;
|
||||
}
|
||||
if (i < 1000000000000000000)
|
||||
{
|
||||
return 18;
|
||||
}
|
||||
if (i < 10000000000000000000)
|
||||
{
|
||||
return 19;
|
||||
}
|
||||
|
||||
return 20;
|
||||
}
|
||||
}
|
||||
|
||||
public static char IntToHex(int n)
|
||||
{
|
||||
if (n <= 9)
|
||||
{
|
||||
return (char)(n + 48);
|
||||
}
|
||||
|
||||
return (char)((n - 10) + 97);
|
||||
}
|
||||
|
||||
public static int? Min(int? val1, int? val2)
|
||||
{
|
||||
if (val1 == null)
|
||||
{
|
||||
return val2;
|
||||
}
|
||||
if (val2 == null)
|
||||
{
|
||||
return val1;
|
||||
}
|
||||
|
||||
return Math.Min(val1.GetValueOrDefault(), val2.GetValueOrDefault());
|
||||
}
|
||||
|
||||
public static int? Max(int? val1, int? val2)
|
||||
{
|
||||
if (val1 == null)
|
||||
{
|
||||
return val2;
|
||||
}
|
||||
if (val2 == null)
|
||||
{
|
||||
return val1;
|
||||
}
|
||||
|
||||
return Math.Max(val1.GetValueOrDefault(), val2.GetValueOrDefault());
|
||||
}
|
||||
|
||||
public static double? Max(double? val1, double? val2)
|
||||
{
|
||||
if (val1 == null)
|
||||
{
|
||||
return val2;
|
||||
}
|
||||
if (val2 == null)
|
||||
{
|
||||
return val1;
|
||||
}
|
||||
|
||||
return Math.Max(val1.GetValueOrDefault(), val2.GetValueOrDefault());
|
||||
}
|
||||
|
||||
public static bool ApproxEquals(double d1, double d2)
|
||||
{
|
||||
const double epsilon = 2.2204460492503131E-16;
|
||||
|
||||
if (d1 == d2)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
double tolerance = ((Math.Abs(d1) + Math.Abs(d2)) + 10.0) * epsilon;
|
||||
double difference = d1 - d2;
|
||||
|
||||
return (-tolerance < difference && tolerance > difference);
|
||||
}
|
||||
}
|
||||
}
|
||||
29
Common/00-1Json8.3/Json8.3/Utilities/MethodCall.cs
Normal file
29
Common/00-1Json8.3/Json8.3/Utilities/MethodCall.cs
Normal file
@@ -0,0 +1,29 @@
|
||||
#region License
|
||||
// Copyright (c) 2007 James Newton-King
|
||||
//
|
||||
// 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
|
||||
|
||||
namespace Newtonsoft.Json.Utilities
|
||||
{
|
||||
internal delegate TResult MethodCall<T, TResult>(T target, params object[] args);
|
||||
}
|
||||
162
Common/00-1Json8.3/Json8.3/Utilities/MiscellaneousUtils.cs
Normal file
162
Common/00-1Json8.3/Json8.3/Utilities/MiscellaneousUtils.cs
Normal file
@@ -0,0 +1,162 @@
|
||||
#region License
|
||||
// Copyright (c) 2007 James Newton-King
|
||||
//
|
||||
// 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;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Globalization;
|
||||
|
||||
namespace Newtonsoft.Json.Utilities
|
||||
{
|
||||
internal delegate T Creator<T>();
|
||||
|
||||
internal static class MiscellaneousUtils
|
||||
{
|
||||
public static bool ValueEquals(object objA, object objB)
|
||||
{
|
||||
if (objA == null && objB == null)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if (objA != null && objB == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (objA == null && objB != null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// comparing an Int32 and Int64 both of the same value returns false
|
||||
// make types the same then compare
|
||||
if (objA.GetType() != objB.GetType())
|
||||
{
|
||||
if (ConvertUtils.IsInteger(objA) && ConvertUtils.IsInteger(objB))
|
||||
{
|
||||
return Convert.ToDecimal(objA, CultureInfo.CurrentCulture).Equals(Convert.ToDecimal(objB, CultureInfo.CurrentCulture));
|
||||
}
|
||||
else if ((objA is double || objA is float || objA is decimal) && (objB is double || objB is float || objB is decimal))
|
||||
{
|
||||
return MathUtils.ApproxEquals(Convert.ToDouble(objA, CultureInfo.CurrentCulture), Convert.ToDouble(objB, CultureInfo.CurrentCulture));
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return objA.Equals(objB);
|
||||
}
|
||||
|
||||
public static ArgumentOutOfRangeException CreateArgumentOutOfRangeException(string paramName, object actualValue, string message)
|
||||
{
|
||||
string newMessage = message + Environment.NewLine + @"Actual value was {0}.".FormatWith(CultureInfo.InvariantCulture, actualValue);
|
||||
|
||||
return new ArgumentOutOfRangeException(paramName, newMessage);
|
||||
}
|
||||
|
||||
public static string ToString(object value)
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
return "{null}";
|
||||
}
|
||||
|
||||
return (value is string) ? @"""" + value.ToString() + @"""" : value.ToString();
|
||||
}
|
||||
|
||||
public static int ByteArrayCompare(byte[] a1, byte[] a2)
|
||||
{
|
||||
int lengthCompare = a1.Length.CompareTo(a2.Length);
|
||||
if (lengthCompare != 0)
|
||||
{
|
||||
return lengthCompare;
|
||||
}
|
||||
|
||||
for (int i = 0; i < a1.Length; i++)
|
||||
{
|
||||
int valueCompare = a1[i].CompareTo(a2[i]);
|
||||
if (valueCompare != 0)
|
||||
{
|
||||
return valueCompare;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
public static string GetPrefix(string qualifiedName)
|
||||
{
|
||||
string prefix;
|
||||
string localName;
|
||||
GetQualifiedNameParts(qualifiedName, out prefix, out localName);
|
||||
|
||||
return prefix;
|
||||
}
|
||||
|
||||
public static string GetLocalName(string qualifiedName)
|
||||
{
|
||||
string prefix;
|
||||
string localName;
|
||||
GetQualifiedNameParts(qualifiedName, out prefix, out localName);
|
||||
|
||||
return localName;
|
||||
}
|
||||
|
||||
public static void GetQualifiedNameParts(string qualifiedName, out string prefix, out string localName)
|
||||
{
|
||||
int colonPosition = qualifiedName.IndexOf(':');
|
||||
|
||||
if ((colonPosition == -1 || colonPosition == 0) || (qualifiedName.Length - 1) == colonPosition)
|
||||
{
|
||||
prefix = null;
|
||||
localName = qualifiedName;
|
||||
}
|
||||
else
|
||||
{
|
||||
prefix = qualifiedName.Substring(0, colonPosition);
|
||||
localName = qualifiedName.Substring(colonPosition + 1);
|
||||
}
|
||||
}
|
||||
|
||||
internal static string FormatValueForPrint(object value)
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
return "{null}";
|
||||
}
|
||||
|
||||
if (value is string)
|
||||
{
|
||||
return @"""" + value + @"""";
|
||||
}
|
||||
|
||||
return value.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
173
Common/00-1Json8.3/Json8.3/Utilities/PropertyNameTable.cs
Normal file
173
Common/00-1Json8.3/Json8.3/Utilities/PropertyNameTable.cs
Normal file
@@ -0,0 +1,173 @@
|
||||
#region License
|
||||
// Copyright (c) 2007 James Newton-King
|
||||
//
|
||||
// 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;
|
||||
|
||||
namespace Newtonsoft.Json.Utilities
|
||||
{
|
||||
internal class PropertyNameTable
|
||||
{
|
||||
// used to defeat hashtable DoS attack where someone passes in lots of strings that hash to the same hash code
|
||||
private static readonly int HashCodeRandomizer;
|
||||
|
||||
private int _count;
|
||||
private Entry[] _entries;
|
||||
private int _mask = 31;
|
||||
|
||||
static PropertyNameTable()
|
||||
{
|
||||
HashCodeRandomizer = Environment.TickCount;
|
||||
}
|
||||
|
||||
public PropertyNameTable()
|
||||
{
|
||||
_entries = new Entry[_mask + 1];
|
||||
}
|
||||
|
||||
public string Get(char[] key, int start, int length)
|
||||
{
|
||||
if (length == 0)
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
int hashCode = length + HashCodeRandomizer;
|
||||
hashCode += (hashCode << 7) ^ key[start];
|
||||
int end = start + length;
|
||||
for (int i = start + 1; i < end; i++)
|
||||
{
|
||||
hashCode += (hashCode << 7) ^ key[i];
|
||||
}
|
||||
hashCode -= hashCode >> 17;
|
||||
hashCode -= hashCode >> 11;
|
||||
hashCode -= hashCode >> 5;
|
||||
for (Entry entry = _entries[hashCode & _mask]; entry != null; entry = entry.Next)
|
||||
{
|
||||
if (entry.HashCode == hashCode && TextEquals(entry.Value, key, start, length))
|
||||
{
|
||||
return entry.Value;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public string Add(string key)
|
||||
{
|
||||
if (key == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(key));
|
||||
}
|
||||
|
||||
int length = key.Length;
|
||||
if (length == 0)
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
int hashCode = length + HashCodeRandomizer;
|
||||
for (int i = 0; i < key.Length; i++)
|
||||
{
|
||||
hashCode += (hashCode << 7) ^ key[i];
|
||||
}
|
||||
hashCode -= hashCode >> 17;
|
||||
hashCode -= hashCode >> 11;
|
||||
hashCode -= hashCode >> 5;
|
||||
for (Entry entry = _entries[hashCode & _mask]; entry != null; entry = entry.Next)
|
||||
{
|
||||
if (entry.HashCode == hashCode && entry.Value.Equals(key))
|
||||
{
|
||||
return entry.Value;
|
||||
}
|
||||
}
|
||||
|
||||
return AddEntry(key, hashCode);
|
||||
}
|
||||
|
||||
private string AddEntry(string str, int hashCode)
|
||||
{
|
||||
int index = hashCode & _mask;
|
||||
Entry entry = new Entry(str, hashCode, _entries[index]);
|
||||
_entries[index] = entry;
|
||||
if (_count++ == _mask)
|
||||
{
|
||||
Grow();
|
||||
}
|
||||
return entry.Value;
|
||||
}
|
||||
|
||||
private void Grow()
|
||||
{
|
||||
Entry[] entries = _entries;
|
||||
int newMask = (_mask * 2) + 1;
|
||||
Entry[] newEntries = new Entry[newMask + 1];
|
||||
|
||||
for (int i = 0; i < entries.Length; i++)
|
||||
{
|
||||
Entry next;
|
||||
for (Entry entry = entries[i]; entry != null; entry = next)
|
||||
{
|
||||
int index = entry.HashCode & newMask;
|
||||
next = entry.Next;
|
||||
entry.Next = newEntries[index];
|
||||
newEntries[index] = entry;
|
||||
}
|
||||
}
|
||||
_entries = newEntries;
|
||||
_mask = newMask;
|
||||
}
|
||||
|
||||
private static bool TextEquals(string str1, char[] str2, int str2Start, int str2Length)
|
||||
{
|
||||
if (str1.Length != str2Length)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int i = 0; i < str1.Length; i++)
|
||||
{
|
||||
if (str1[i] != str2[str2Start + i])
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private class Entry
|
||||
{
|
||||
internal readonly string Value;
|
||||
internal readonly int HashCode;
|
||||
internal Entry Next;
|
||||
|
||||
internal Entry(string value, int hashCode, Entry next)
|
||||
{
|
||||
Value = value;
|
||||
HashCode = hashCode;
|
||||
Next = next;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
#region License
|
||||
// Copyright (c) 2007 James Newton-King
|
||||
//
|
||||
// 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.Globalization;
|
||||
using System.Reflection;
|
||||
using Newtonsoft.Json.Serialization;
|
||||
|
||||
#if NET20
|
||||
using Newtonsoft.Json.Utilities.LinqBridge;
|
||||
#endif
|
||||
|
||||
namespace Newtonsoft.Json.Utilities
|
||||
{
|
||||
internal abstract class ReflectionDelegateFactory
|
||||
{
|
||||
public Func<T, object> CreateGet<T>(MemberInfo memberInfo)
|
||||
{
|
||||
PropertyInfo propertyInfo = memberInfo as PropertyInfo;
|
||||
if (propertyInfo != null)
|
||||
{
|
||||
return CreateGet<T>(propertyInfo);
|
||||
}
|
||||
|
||||
FieldInfo fieldInfo = memberInfo as FieldInfo;
|
||||
if (fieldInfo != null)
|
||||
{
|
||||
return CreateGet<T>(fieldInfo);
|
||||
}
|
||||
|
||||
throw new Exception("Could not create getter for {0}.".FormatWith(CultureInfo.InvariantCulture, memberInfo));
|
||||
}
|
||||
|
||||
public Action<T, object> CreateSet<T>(MemberInfo memberInfo)
|
||||
{
|
||||
PropertyInfo propertyInfo = memberInfo as PropertyInfo;
|
||||
if (propertyInfo != null)
|
||||
{
|
||||
return CreateSet<T>(propertyInfo);
|
||||
}
|
||||
|
||||
FieldInfo fieldInfo = memberInfo as FieldInfo;
|
||||
if (fieldInfo != null)
|
||||
{
|
||||
return CreateSet<T>(fieldInfo);
|
||||
}
|
||||
|
||||
throw new Exception("Could not create setter for {0}.".FormatWith(CultureInfo.InvariantCulture, memberInfo));
|
||||
}
|
||||
|
||||
public abstract MethodCall<T, object> CreateMethodCall<T>(MethodBase method);
|
||||
public abstract ObjectConstructor<object> CreateParameterizedConstructor(MethodBase method);
|
||||
public abstract Func<T> CreateDefaultConstructor<T>(Type type);
|
||||
public abstract Func<T, object> CreateGet<T>(PropertyInfo propertyInfo);
|
||||
public abstract Func<T, object> CreateGet<T>(FieldInfo fieldInfo);
|
||||
public abstract Action<T, object> CreateSet<T>(FieldInfo fieldInfo);
|
||||
public abstract Action<T, object> CreateSet<T>(PropertyInfo propertyInfo);
|
||||
}
|
||||
}
|
||||
165
Common/00-1Json8.3/Json8.3/Utilities/ReflectionObject.cs
Normal file
165
Common/00-1Json8.3/Json8.3/Utilities/ReflectionObject.cs
Normal file
@@ -0,0 +1,165 @@
|
||||
#region License
|
||||
// Copyright (c) 2007 James Newton-King
|
||||
//
|
||||
// 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 Newtonsoft.Json.Serialization;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using System.Globalization;
|
||||
#if NET20
|
||||
using Newtonsoft.Json.Utilities.LinqBridge;
|
||||
#else
|
||||
using System.Linq;
|
||||
|
||||
#endif
|
||||
|
||||
namespace Newtonsoft.Json.Utilities
|
||||
{
|
||||
internal class ReflectionMember
|
||||
{
|
||||
public Type MemberType { get; set; }
|
||||
public Func<object, object> Getter { get; set; }
|
||||
public Action<object, object> Setter { get; set; }
|
||||
}
|
||||
|
||||
internal class ReflectionObject
|
||||
{
|
||||
public ObjectConstructor<object> Creator { get; private set; }
|
||||
public IDictionary<string, ReflectionMember> Members { get; private set; }
|
||||
|
||||
public ReflectionObject()
|
||||
{
|
||||
Members = new Dictionary<string, ReflectionMember>();
|
||||
}
|
||||
|
||||
public object GetValue(object target, string member)
|
||||
{
|
||||
Func<object, object> getter = Members[member].Getter;
|
||||
return getter(target);
|
||||
}
|
||||
|
||||
public void SetValue(object target, string member, object value)
|
||||
{
|
||||
Action<object, object> setter = Members[member].Setter;
|
||||
setter(target, value);
|
||||
}
|
||||
|
||||
public Type GetType(string member)
|
||||
{
|
||||
return Members[member].MemberType;
|
||||
}
|
||||
|
||||
public static ReflectionObject Create(Type t, params string[] memberNames)
|
||||
{
|
||||
return Create(t, null, memberNames);
|
||||
}
|
||||
|
||||
public static ReflectionObject Create(Type t, MethodBase creator, params string[] memberNames)
|
||||
{
|
||||
ReflectionObject d = new ReflectionObject();
|
||||
|
||||
ReflectionDelegateFactory delegateFactory = JsonTypeReflector.ReflectionDelegateFactory;
|
||||
|
||||
if (creator != null)
|
||||
{
|
||||
d.Creator = delegateFactory.CreateParameterizedConstructor(creator);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ReflectionUtils.HasDefaultConstructor(t, false))
|
||||
{
|
||||
Func<object> ctor = delegateFactory.CreateDefaultConstructor<object>(t);
|
||||
|
||||
d.Creator = args => ctor();
|
||||
}
|
||||
}
|
||||
|
||||
foreach (string memberName in memberNames)
|
||||
{
|
||||
MemberInfo[] members = t.GetMember(memberName, BindingFlags.Instance | BindingFlags.Public);
|
||||
if (members.Length != 1)
|
||||
{
|
||||
throw new ArgumentException("Expected a single member with the name '{0}'.".FormatWith(CultureInfo.InvariantCulture, memberName));
|
||||
}
|
||||
|
||||
MemberInfo member = members.Single();
|
||||
|
||||
ReflectionMember reflectionMember = new ReflectionMember();
|
||||
|
||||
switch (member.MemberType())
|
||||
{
|
||||
case MemberTypes.Field:
|
||||
case MemberTypes.Property:
|
||||
if (ReflectionUtils.CanReadMemberValue(member, false))
|
||||
{
|
||||
reflectionMember.Getter = delegateFactory.CreateGet<object>(member);
|
||||
}
|
||||
|
||||
if (ReflectionUtils.CanSetMemberValue(member, false, false))
|
||||
{
|
||||
reflectionMember.Setter = delegateFactory.CreateSet<object>(member);
|
||||
}
|
||||
break;
|
||||
case MemberTypes.Method:
|
||||
MethodInfo method = (MethodInfo)member;
|
||||
if (method.IsPublic)
|
||||
{
|
||||
ParameterInfo[] parameters = method.GetParameters();
|
||||
if (parameters.Length == 0 && method.ReturnType != typeof(void))
|
||||
{
|
||||
MethodCall<object, object> call = delegateFactory.CreateMethodCall<object>(method);
|
||||
reflectionMember.Getter = target => call(target);
|
||||
}
|
||||
else if (parameters.Length == 1 && method.ReturnType == typeof(void))
|
||||
{
|
||||
MethodCall<object, object> call = delegateFactory.CreateMethodCall<object>(method);
|
||||
reflectionMember.Setter = (target, arg) => call(target, arg);
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentException("Unexpected member type '{0}' for member '{1}'.".FormatWith(CultureInfo.InvariantCulture, member.MemberType(), member.Name));
|
||||
}
|
||||
|
||||
if (ReflectionUtils.CanReadMemberValue(member, false))
|
||||
{
|
||||
reflectionMember.Getter = delegateFactory.CreateGet<object>(member);
|
||||
}
|
||||
|
||||
if (ReflectionUtils.CanSetMemberValue(member, false, false))
|
||||
{
|
||||
reflectionMember.Setter = delegateFactory.CreateSet<object>(member);
|
||||
}
|
||||
|
||||
reflectionMember.MemberType = ReflectionUtils.GetMemberUnderlyingType(member);
|
||||
|
||||
d.Members[memberName] = reflectionMember;
|
||||
}
|
||||
|
||||
return d;
|
||||
}
|
||||
}
|
||||
}
|
||||
1122
Common/00-1Json8.3/Json8.3/Utilities/ReflectionUtils.cs
Normal file
1122
Common/00-1Json8.3/Json8.3/Utilities/ReflectionUtils.cs
Normal file
File diff suppressed because it is too large
Load Diff
122
Common/00-1Json8.3/Json8.3/Utilities/StringBuffer.cs
Normal file
122
Common/00-1Json8.3/Json8.3/Utilities/StringBuffer.cs
Normal file
@@ -0,0 +1,122 @@
|
||||
#region License
|
||||
// Copyright (c) 2007 James Newton-King
|
||||
//
|
||||
// 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;
|
||||
|
||||
namespace Newtonsoft.Json.Utilities
|
||||
{
|
||||
/// <summary>
|
||||
/// Builds a string. Unlike StringBuilder this class lets you reuse it's internal buffer.
|
||||
/// </summary>
|
||||
internal struct StringBuffer
|
||||
{
|
||||
private char[] _buffer;
|
||||
private int _position;
|
||||
|
||||
public int Position
|
||||
{
|
||||
get { return _position; }
|
||||
set { _position = value; }
|
||||
}
|
||||
|
||||
public bool IsEmpty
|
||||
{
|
||||
get { return _buffer == null; }
|
||||
}
|
||||
|
||||
public StringBuffer(IArrayPool<char> bufferPool, int initalSize) : this(BufferUtils.RentBuffer(bufferPool, initalSize))
|
||||
{
|
||||
}
|
||||
|
||||
private StringBuffer(char[] buffer)
|
||||
{
|
||||
_buffer = buffer;
|
||||
_position = 0;
|
||||
}
|
||||
|
||||
public void Append(IArrayPool<char> bufferPool, char value)
|
||||
{
|
||||
// test if the buffer array is large enough to take the value
|
||||
if (_position == _buffer.Length)
|
||||
{
|
||||
EnsureSize(bufferPool, 1);
|
||||
}
|
||||
|
||||
// set value and increment poisition
|
||||
_buffer[_position++] = value;
|
||||
}
|
||||
|
||||
public void Append(IArrayPool<char> bufferPool, char[] buffer, int startIndex, int count)
|
||||
{
|
||||
if (_position + count >= _buffer.Length)
|
||||
{
|
||||
EnsureSize(bufferPool, count);
|
||||
}
|
||||
|
||||
Array.Copy(buffer, startIndex, _buffer, _position, count);
|
||||
|
||||
_position += count;
|
||||
}
|
||||
|
||||
public void Clear(IArrayPool<char> bufferPool)
|
||||
{
|
||||
if (_buffer != null)
|
||||
{
|
||||
BufferUtils.ReturnBuffer(bufferPool, _buffer);
|
||||
_buffer = null;
|
||||
}
|
||||
_position = 0;
|
||||
}
|
||||
|
||||
private void EnsureSize(IArrayPool<char> bufferPool, int appendLength)
|
||||
{
|
||||
char[] newBuffer = BufferUtils.RentBuffer(bufferPool, (_position + appendLength) * 2);
|
||||
|
||||
if (_buffer != null)
|
||||
{
|
||||
Array.Copy(_buffer, newBuffer, _position);
|
||||
BufferUtils.ReturnBuffer(bufferPool, _buffer);
|
||||
}
|
||||
|
||||
_buffer = newBuffer;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return ToString(0, _position);
|
||||
}
|
||||
|
||||
public string ToString(int start, int length)
|
||||
{
|
||||
// TODO: validation
|
||||
return new string(_buffer, start, length);
|
||||
}
|
||||
|
||||
public char[] InternalBuffer
|
||||
{
|
||||
get { return _buffer; }
|
||||
}
|
||||
}
|
||||
}
|
||||
123
Common/00-1Json8.3/Json8.3/Utilities/StringReference.cs
Normal file
123
Common/00-1Json8.3/Json8.3/Utilities/StringReference.cs
Normal file
@@ -0,0 +1,123 @@
|
||||
#region License
|
||||
// Copyright (c) 2007 James Newton-King
|
||||
//
|
||||
// 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;
|
||||
|
||||
namespace Newtonsoft.Json.Utilities
|
||||
{
|
||||
internal struct StringReference
|
||||
{
|
||||
private readonly char[] _chars;
|
||||
private readonly int _startIndex;
|
||||
private readonly int _length;
|
||||
|
||||
public char this[int i]
|
||||
{
|
||||
get { return _chars[i]; }
|
||||
}
|
||||
|
||||
public char[] Chars
|
||||
{
|
||||
get { return _chars; }
|
||||
}
|
||||
|
||||
public int StartIndex
|
||||
{
|
||||
get { return _startIndex; }
|
||||
}
|
||||
|
||||
public int Length
|
||||
{
|
||||
get { return _length; }
|
||||
}
|
||||
|
||||
public StringReference(char[] chars, int startIndex, int length)
|
||||
{
|
||||
_chars = chars;
|
||||
_startIndex = startIndex;
|
||||
_length = length;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return new string(_chars, _startIndex, _length);
|
||||
}
|
||||
}
|
||||
|
||||
internal static class StringReferenceExtensions
|
||||
{
|
||||
public static int IndexOf(this StringReference s, char c, int startIndex, int length)
|
||||
{
|
||||
int index = Array.IndexOf(s.Chars, c, s.StartIndex + startIndex, length);
|
||||
if (index == -1)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
return index - s.StartIndex;
|
||||
}
|
||||
|
||||
public static bool StartsWith(this StringReference s, string text)
|
||||
{
|
||||
if (text.Length > s.Length)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
char[] chars = s.Chars;
|
||||
|
||||
for (int i = 0; i < text.Length; i++)
|
||||
{
|
||||
if (text[i] != chars[i + s.StartIndex])
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static bool EndsWith(this StringReference s, string text)
|
||||
{
|
||||
if (text.Length > s.Length)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
char[] chars = s.Chars;
|
||||
|
||||
int start = s.StartIndex + s.Length - text.Length;
|
||||
for (int i = 0; i < text.Length; i++)
|
||||
{
|
||||
if (text[i] != chars[i + start])
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
231
Common/00-1Json8.3/Json8.3/Utilities/StringUtils.cs
Normal file
231
Common/00-1Json8.3/Json8.3/Utilities/StringUtils.cs
Normal file
@@ -0,0 +1,231 @@
|
||||
#region License
|
||||
// Copyright (c) 2007 James Newton-King
|
||||
//
|
||||
// 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.Text;
|
||||
using System.Globalization;
|
||||
#if NET20
|
||||
using Newtonsoft.Json.Utilities.LinqBridge;
|
||||
#else
|
||||
using System.Linq;
|
||||
#endif
|
||||
using Newtonsoft.Json.Serialization;
|
||||
|
||||
namespace Newtonsoft.Json.Utilities
|
||||
{
|
||||
internal static class StringUtils
|
||||
{
|
||||
public const string CarriageReturnLineFeed = "\r\n";
|
||||
public const string Empty = "";
|
||||
public const char CarriageReturn = '\r';
|
||||
public const char LineFeed = '\n';
|
||||
public const char Tab = '\t';
|
||||
|
||||
public static string FormatWith(this string format, IFormatProvider provider, object arg0)
|
||||
{
|
||||
return format.FormatWith(provider, new[] { arg0 });
|
||||
}
|
||||
|
||||
public static string FormatWith(this string format, IFormatProvider provider, object arg0, object arg1)
|
||||
{
|
||||
return format.FormatWith(provider, new[] { arg0, arg1 });
|
||||
}
|
||||
|
||||
public static string FormatWith(this string format, IFormatProvider provider, object arg0, object arg1, object arg2)
|
||||
{
|
||||
return format.FormatWith(provider, new[] { arg0, arg1, arg2 });
|
||||
}
|
||||
|
||||
public static string FormatWith(this string format, IFormatProvider provider, object arg0, object arg1, object arg2, object arg3)
|
||||
{
|
||||
return format.FormatWith(provider, new[] { arg0, arg1, arg2, arg3 });
|
||||
}
|
||||
|
||||
private static string FormatWith(this string format, IFormatProvider provider, params object[] args)
|
||||
{
|
||||
// leave this a private to force code to use an explicit overload
|
||||
// avoids stack memory being reserved for the object array
|
||||
ValidationUtils.ArgumentNotNull(format, nameof(format));
|
||||
|
||||
return string.Format(provider, format, args);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether the string is all white space. Empty string will return false.
|
||||
/// </summary>
|
||||
/// <param name="s">The string to test whether it is all white space.</param>
|
||||
/// <returns>
|
||||
/// <c>true</c> if the string is all white space; otherwise, <c>false</c>.
|
||||
/// </returns>
|
||||
public static bool IsWhiteSpace(string s)
|
||||
{
|
||||
if (s == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(s));
|
||||
}
|
||||
|
||||
if (s.Length == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int i = 0; i < s.Length; i++)
|
||||
{
|
||||
if (!char.IsWhiteSpace(s[i]))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Nulls an empty string.
|
||||
/// </summary>
|
||||
/// <param name="s">The string.</param>
|
||||
/// <returns>Null if the string was null, otherwise the string unchanged.</returns>
|
||||
public static string NullEmptyString(string s)
|
||||
{
|
||||
return (string.IsNullOrEmpty(s)) ? null : s;
|
||||
}
|
||||
|
||||
public static StringWriter CreateStringWriter(int capacity)
|
||||
{
|
||||
StringBuilder sb = new StringBuilder(capacity);
|
||||
StringWriter sw = new StringWriter(sb, CultureInfo.InvariantCulture);
|
||||
|
||||
return sw;
|
||||
}
|
||||
|
||||
public static int? GetLength(string value)
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
else
|
||||
{
|
||||
return value.Length;
|
||||
}
|
||||
}
|
||||
|
||||
public static void ToCharAsUnicode(char c, char[] buffer)
|
||||
{
|
||||
buffer[0] = '\\';
|
||||
buffer[1] = 'u';
|
||||
buffer[2] = MathUtils.IntToHex((c >> 12) & '\x000f');
|
||||
buffer[3] = MathUtils.IntToHex((c >> 8) & '\x000f');
|
||||
buffer[4] = MathUtils.IntToHex((c >> 4) & '\x000f');
|
||||
buffer[5] = MathUtils.IntToHex(c & '\x000f');
|
||||
}
|
||||
|
||||
public static TSource ForgivingCaseSensitiveFind<TSource>(this IEnumerable<TSource> source, Func<TSource, string> valueSelector, string testValue)
|
||||
{
|
||||
if (source == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(source));
|
||||
}
|
||||
if (valueSelector == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(valueSelector));
|
||||
}
|
||||
|
||||
var caseInsensitiveResults = source.Where(s => string.Equals(valueSelector(s), testValue, StringComparison.OrdinalIgnoreCase));
|
||||
if (caseInsensitiveResults.Count() <= 1)
|
||||
{
|
||||
return caseInsensitiveResults.SingleOrDefault();
|
||||
}
|
||||
else
|
||||
{
|
||||
// multiple results returned. now filter using case sensitivity
|
||||
var caseSensitiveResults = source.Where(s => string.Equals(valueSelector(s), testValue, StringComparison.Ordinal));
|
||||
return caseSensitiveResults.SingleOrDefault();
|
||||
}
|
||||
}
|
||||
|
||||
public static string ToCamelCase(string s)
|
||||
{
|
||||
if (string.IsNullOrEmpty(s) || !char.IsUpper(s[0]))
|
||||
{
|
||||
return s;
|
||||
}
|
||||
|
||||
char[] chars = s.ToCharArray();
|
||||
|
||||
for (int i = 0; i < chars.Length; i++)
|
||||
{
|
||||
if (i == 1 && !char.IsUpper(chars[i]))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
bool hasNext = (i + 1 < chars.Length);
|
||||
if (i > 0 && hasNext && !char.IsUpper(chars[i + 1]))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
#if !(DOTNET || PORTABLE)
|
||||
chars[i] = char.ToLower(chars[i], CultureInfo.InvariantCulture);
|
||||
#else
|
||||
chars[i] = char.ToLowerInvariant(chars[i]);
|
||||
#endif
|
||||
}
|
||||
|
||||
return new string(chars);
|
||||
}
|
||||
|
||||
public static bool IsHighSurrogate(char c)
|
||||
{
|
||||
#if !(PORTABLE40 || PORTABLE)
|
||||
return char.IsHighSurrogate(c);
|
||||
#else
|
||||
return (c >= 55296 && c <= 56319);
|
||||
#endif
|
||||
}
|
||||
|
||||
public static bool IsLowSurrogate(char c)
|
||||
{
|
||||
#if !(PORTABLE40 || PORTABLE)
|
||||
return char.IsLowSurrogate(c);
|
||||
#else
|
||||
return (c >= 56320 && c <= 57343);
|
||||
#endif
|
||||
}
|
||||
|
||||
public static bool StartsWith(this string source, char value)
|
||||
{
|
||||
return (source.Length > 0 && source[0] == value);
|
||||
}
|
||||
|
||||
public static bool EndsWith(this string source, char value)
|
||||
{
|
||||
return (source.Length > 0 && source[source.Length - 1] == value);
|
||||
}
|
||||
}
|
||||
}
|
||||
97
Common/00-1Json8.3/Json8.3/Utilities/ThreadSafeStore.cs
Normal file
97
Common/00-1Json8.3/Json8.3/Utilities/ThreadSafeStore.cs
Normal file
@@ -0,0 +1,97 @@
|
||||
#region License
|
||||
// Copyright (c) 2007 James Newton-King
|
||||
//
|
||||
// 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;
|
||||
#if NET20
|
||||
using Newtonsoft.Json.Utilities.LinqBridge;
|
||||
#endif
|
||||
using System.Threading;
|
||||
using Newtonsoft.Json.Serialization;
|
||||
|
||||
namespace Newtonsoft.Json.Utilities
|
||||
{
|
||||
internal class ThreadSafeStore<TKey, TValue>
|
||||
{
|
||||
private readonly object _lock = new object();
|
||||
private Dictionary<TKey, TValue> _store;
|
||||
private readonly Func<TKey, TValue> _creator;
|
||||
|
||||
public ThreadSafeStore(Func<TKey, TValue> creator)
|
||||
{
|
||||
if (creator == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(creator));
|
||||
}
|
||||
|
||||
_creator = creator;
|
||||
_store = new Dictionary<TKey, TValue>();
|
||||
}
|
||||
|
||||
public TValue Get(TKey key)
|
||||
{
|
||||
TValue value;
|
||||
if (!_store.TryGetValue(key, out value))
|
||||
{
|
||||
return AddValue(key);
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
private TValue AddValue(TKey key)
|
||||
{
|
||||
TValue value = _creator(key);
|
||||
|
||||
lock (_lock)
|
||||
{
|
||||
if (_store == null)
|
||||
{
|
||||
_store = new Dictionary<TKey, TValue>();
|
||||
_store[key] = value;
|
||||
}
|
||||
else
|
||||
{
|
||||
// double check locking
|
||||
TValue checkValue;
|
||||
if (_store.TryGetValue(key, out checkValue))
|
||||
{
|
||||
return checkValue;
|
||||
}
|
||||
|
||||
Dictionary<TKey, TValue> newStore = new Dictionary<TKey, TValue>(_store);
|
||||
newStore[key] = value;
|
||||
|
||||
#if !(DOTNET || PORTABLE)
|
||||
Thread.MemoryBarrier();
|
||||
#endif
|
||||
_store = newStore;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
628
Common/00-1Json8.3/Json8.3/Utilities/TypeExtensions.cs
Normal file
628
Common/00-1Json8.3/Json8.3/Utilities/TypeExtensions.cs
Normal file
@@ -0,0 +1,628 @@
|
||||
#region License
|
||||
// Copyright (c) 2007 James Newton-King
|
||||
//
|
||||
// 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.Reflection;
|
||||
#if NET20
|
||||
using Newtonsoft.Json.Utilities.LinqBridge;
|
||||
#else
|
||||
using System.Linq;
|
||||
#endif
|
||||
|
||||
namespace Newtonsoft.Json.Utilities
|
||||
{
|
||||
internal static class TypeExtensions
|
||||
{
|
||||
#if DOTNET || PORTABLE
|
||||
#if !DOTNET
|
||||
private static BindingFlags DefaultFlags = BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance;
|
||||
|
||||
public static MethodInfo GetGetMethod(this PropertyInfo propertyInfo)
|
||||
{
|
||||
return propertyInfo.GetGetMethod(false);
|
||||
}
|
||||
|
||||
public static MethodInfo GetGetMethod(this PropertyInfo propertyInfo, bool nonPublic)
|
||||
{
|
||||
MethodInfo getMethod = propertyInfo.GetMethod;
|
||||
if (getMethod != null && (getMethod.IsPublic || nonPublic))
|
||||
{
|
||||
return getMethod;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static MethodInfo GetSetMethod(this PropertyInfo propertyInfo)
|
||||
{
|
||||
return propertyInfo.GetSetMethod(false);
|
||||
}
|
||||
|
||||
public static MethodInfo GetSetMethod(this PropertyInfo propertyInfo, bool nonPublic)
|
||||
{
|
||||
MethodInfo setMethod = propertyInfo.SetMethod;
|
||||
if (setMethod != null && (setMethod.IsPublic || nonPublic))
|
||||
{
|
||||
return setMethod;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
#endif
|
||||
|
||||
public static bool IsSubclassOf(this Type type, Type c)
|
||||
{
|
||||
return type.GetTypeInfo().IsSubclassOf(c);
|
||||
}
|
||||
|
||||
#if !DOTNET
|
||||
public static bool IsAssignableFrom(this Type type, Type c)
|
||||
{
|
||||
return type.GetTypeInfo().IsAssignableFrom(c.GetTypeInfo());
|
||||
}
|
||||
#endif
|
||||
|
||||
public static bool IsInstanceOfType(this Type type, object o)
|
||||
{
|
||||
if (o == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return type.IsAssignableFrom(o.GetType());
|
||||
}
|
||||
#endif
|
||||
|
||||
public static MethodInfo Method(this Delegate d)
|
||||
{
|
||||
#if !(DOTNET || PORTABLE)
|
||||
return d.Method;
|
||||
#else
|
||||
return d.GetMethodInfo();
|
||||
#endif
|
||||
}
|
||||
|
||||
public static MemberTypes MemberType(this MemberInfo memberInfo)
|
||||
{
|
||||
#if !(DOTNET || PORTABLE || PORTABLE40)
|
||||
return memberInfo.MemberType;
|
||||
#else
|
||||
if (memberInfo is PropertyInfo)
|
||||
{
|
||||
return MemberTypes.Property;
|
||||
}
|
||||
else if (memberInfo is FieldInfo)
|
||||
{
|
||||
return MemberTypes.Field;
|
||||
}
|
||||
else if (memberInfo is EventInfo)
|
||||
{
|
||||
return MemberTypes.Event;
|
||||
}
|
||||
else if (memberInfo is MethodInfo)
|
||||
{
|
||||
return MemberTypes.Method;
|
||||
}
|
||||
else
|
||||
{
|
||||
return MemberTypes.Other;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
public static bool ContainsGenericParameters(this Type type)
|
||||
{
|
||||
#if !(DOTNET || PORTABLE)
|
||||
return type.ContainsGenericParameters;
|
||||
#else
|
||||
return type.GetTypeInfo().ContainsGenericParameters;
|
||||
#endif
|
||||
}
|
||||
|
||||
public static bool IsInterface(this Type type)
|
||||
{
|
||||
#if !(DOTNET || PORTABLE)
|
||||
return type.IsInterface;
|
||||
#else
|
||||
return type.GetTypeInfo().IsInterface;
|
||||
#endif
|
||||
}
|
||||
|
||||
public static bool IsGenericType(this Type type)
|
||||
{
|
||||
#if !(DOTNET || PORTABLE)
|
||||
return type.IsGenericType;
|
||||
#else
|
||||
return type.GetTypeInfo().IsGenericType;
|
||||
#endif
|
||||
}
|
||||
|
||||
public static bool IsGenericTypeDefinition(this Type type)
|
||||
{
|
||||
#if !(DOTNET || PORTABLE)
|
||||
return type.IsGenericTypeDefinition;
|
||||
#else
|
||||
return type.GetTypeInfo().IsGenericTypeDefinition;
|
||||
#endif
|
||||
}
|
||||
|
||||
public static Type BaseType(this Type type)
|
||||
{
|
||||
#if !(DOTNET || PORTABLE)
|
||||
return type.BaseType;
|
||||
#else
|
||||
return type.GetTypeInfo().BaseType;
|
||||
#endif
|
||||
}
|
||||
|
||||
public static Assembly Assembly(this Type type)
|
||||
{
|
||||
#if !(DOTNET || PORTABLE)
|
||||
return type.Assembly;
|
||||
#else
|
||||
return type.GetTypeInfo().Assembly;
|
||||
#endif
|
||||
}
|
||||
|
||||
public static bool IsEnum(this Type type)
|
||||
{
|
||||
#if !(DOTNET || PORTABLE)
|
||||
return type.IsEnum;
|
||||
#else
|
||||
return type.GetTypeInfo().IsEnum;
|
||||
#endif
|
||||
}
|
||||
|
||||
public static bool IsClass(this Type type)
|
||||
{
|
||||
#if !(DOTNET || PORTABLE)
|
||||
return type.IsClass;
|
||||
#else
|
||||
return type.GetTypeInfo().IsClass;
|
||||
#endif
|
||||
}
|
||||
|
||||
public static bool IsSealed(this Type type)
|
||||
{
|
||||
#if !(DOTNET || PORTABLE)
|
||||
return type.IsSealed;
|
||||
#else
|
||||
return type.GetTypeInfo().IsSealed;
|
||||
#endif
|
||||
}
|
||||
|
||||
#if (PORTABLE40 || DOTNET || PORTABLE)
|
||||
public static PropertyInfo GetProperty(this Type type, string name, BindingFlags bindingFlags, object placeholder1, Type propertyType, IList<Type> indexParameters, object placeholder2)
|
||||
{
|
||||
IEnumerable<PropertyInfo> propertyInfos = type.GetProperties(bindingFlags);
|
||||
|
||||
return propertyInfos.Where(p =>
|
||||
{
|
||||
if (name != null && name != p.Name)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (propertyType != null && propertyType != p.PropertyType)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (indexParameters != null)
|
||||
{
|
||||
if (!p.GetIndexParameters().Select(ip => ip.ParameterType).SequenceEqual(indexParameters))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}).SingleOrDefault();
|
||||
}
|
||||
|
||||
public static IEnumerable<MemberInfo> GetMember(this Type type, string name, MemberTypes memberType, BindingFlags bindingFlags)
|
||||
{
|
||||
#if PORTABLE
|
||||
return type.GetMemberInternal(name, memberType, bindingFlags);
|
||||
#else
|
||||
return type.GetMember(name, bindingFlags).Where(m =>
|
||||
{
|
||||
if (m.MemberType() != memberType)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
#if (DOTNET || PORTABLE)
|
||||
public static MethodInfo GetBaseDefinition(this MethodInfo method)
|
||||
{
|
||||
return method.GetRuntimeBaseDefinition();
|
||||
}
|
||||
#endif
|
||||
|
||||
#if (DOTNET || PORTABLE)
|
||||
public static bool IsDefined(this Type type, Type attributeType, bool inherit)
|
||||
{
|
||||
return type.GetTypeInfo().CustomAttributes.Any(a => a.AttributeType == attributeType);
|
||||
}
|
||||
|
||||
#if !DOTNET
|
||||
public static MethodInfo GetMethod(this Type type, string name)
|
||||
{
|
||||
return type.GetMethod(name, DefaultFlags);
|
||||
}
|
||||
|
||||
public static MethodInfo GetMethod(this Type type, string name, BindingFlags bindingFlags)
|
||||
{
|
||||
return type.GetTypeInfo().GetDeclaredMethod(name);
|
||||
}
|
||||
|
||||
public static MethodInfo GetMethod(this Type type, IList<Type> parameterTypes)
|
||||
{
|
||||
return type.GetMethod(null, parameterTypes);
|
||||
}
|
||||
|
||||
public static MethodInfo GetMethod(this Type type, string name, IList<Type> parameterTypes)
|
||||
{
|
||||
return type.GetMethod(name, DefaultFlags, null, parameterTypes, null);
|
||||
}
|
||||
|
||||
public static MethodInfo GetMethod(this Type type, string name, BindingFlags bindingFlags, object placeHolder1, IList<Type> parameterTypes, object placeHolder2)
|
||||
{
|
||||
return type.GetTypeInfo().DeclaredMethods.Where(
|
||||
m =>
|
||||
{
|
||||
if (name != null && m.Name != name)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!TestAccessibility(m, bindingFlags))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return m.GetParameters().Select(p => p.ParameterType).SequenceEqual(parameterTypes);
|
||||
}).SingleOrDefault();
|
||||
}
|
||||
|
||||
public static IEnumerable<ConstructorInfo> GetConstructors(this Type type)
|
||||
{
|
||||
return type.GetConstructors(DefaultFlags);
|
||||
}
|
||||
|
||||
public static IEnumerable<ConstructorInfo> GetConstructors(this Type type, BindingFlags bindingFlags)
|
||||
{
|
||||
return type.GetConstructors(bindingFlags, null);
|
||||
}
|
||||
|
||||
private static IEnumerable<ConstructorInfo> GetConstructors(this Type type, BindingFlags bindingFlags, IList<Type> parameterTypes)
|
||||
{
|
||||
return type.GetTypeInfo().DeclaredConstructors.Where(
|
||||
c =>
|
||||
{
|
||||
if (!TestAccessibility(c, bindingFlags))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (parameterTypes != null && !c.GetParameters().Select(p => p.ParameterType).SequenceEqual(parameterTypes))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
public static ConstructorInfo GetConstructor(this Type type, IList<Type> parameterTypes)
|
||||
{
|
||||
return type.GetConstructor(DefaultFlags, null, parameterTypes, null);
|
||||
}
|
||||
|
||||
public static ConstructorInfo GetConstructor(this Type type, BindingFlags bindingFlags, object placeholder1, IList<Type> parameterTypes, object placeholder2)
|
||||
{
|
||||
return type.GetConstructors(bindingFlags, parameterTypes).SingleOrDefault();
|
||||
}
|
||||
|
||||
public static MemberInfo[] GetMember(this Type type, string member)
|
||||
{
|
||||
return type.GetMemberInternal(member, null, DefaultFlags);
|
||||
}
|
||||
|
||||
public static MemberInfo[] GetMember(this Type type, string member, BindingFlags bindingFlags)
|
||||
{
|
||||
return type.GetMemberInternal(member, null, bindingFlags);
|
||||
}
|
||||
|
||||
public static MemberInfo[] GetMemberInternal(this Type type, string member, MemberTypes? memberType, BindingFlags bindingFlags)
|
||||
{
|
||||
return type.GetTypeInfo().GetMembersRecursive().Where(m =>
|
||||
m.Name == member &&
|
||||
// test type before accessibility - accessibility doesn't support some types
|
||||
(memberType == null || m.MemberType() == memberType) &&
|
||||
TestAccessibility(m, bindingFlags)).ToArray();
|
||||
}
|
||||
|
||||
public static MemberInfo GetField(this Type type, string member)
|
||||
{
|
||||
return type.GetField(member, DefaultFlags);
|
||||
}
|
||||
|
||||
public static MemberInfo GetField(this Type type, string member, BindingFlags bindingFlags)
|
||||
{
|
||||
return type.GetTypeInfo().GetDeclaredField(member);
|
||||
}
|
||||
|
||||
public static IEnumerable<PropertyInfo> GetProperties(this Type type, BindingFlags bindingFlags)
|
||||
{
|
||||
IList<PropertyInfo> properties = (bindingFlags.HasFlag(BindingFlags.DeclaredOnly))
|
||||
? type.GetTypeInfo().DeclaredProperties.ToList()
|
||||
: type.GetTypeInfo().GetPropertiesRecursive();
|
||||
|
||||
return properties.Where(p => TestAccessibility(p, bindingFlags));
|
||||
}
|
||||
|
||||
private static IList<MemberInfo> GetMembersRecursive(this TypeInfo type)
|
||||
{
|
||||
TypeInfo t = type;
|
||||
IList<MemberInfo> members = new List<MemberInfo>();
|
||||
while (t != null)
|
||||
{
|
||||
foreach (MemberInfo member in t.DeclaredMembers)
|
||||
{
|
||||
if (!members.Any(p => p.Name == member.Name))
|
||||
{
|
||||
members.Add(member);
|
||||
}
|
||||
}
|
||||
t = (t.BaseType != null) ? t.BaseType.GetTypeInfo() : null;
|
||||
}
|
||||
|
||||
return members;
|
||||
}
|
||||
|
||||
private static IList<PropertyInfo> GetPropertiesRecursive(this TypeInfo type)
|
||||
{
|
||||
TypeInfo t = type;
|
||||
IList<PropertyInfo> properties = new List<PropertyInfo>();
|
||||
while (t != null)
|
||||
{
|
||||
foreach (PropertyInfo member in t.DeclaredProperties)
|
||||
{
|
||||
if (!properties.Any(p => p.Name == member.Name))
|
||||
{
|
||||
properties.Add(member);
|
||||
}
|
||||
}
|
||||
t = (t.BaseType != null) ? t.BaseType.GetTypeInfo() : null;
|
||||
}
|
||||
|
||||
return properties;
|
||||
}
|
||||
|
||||
private static IList<FieldInfo> GetFieldsRecursive(this TypeInfo type)
|
||||
{
|
||||
TypeInfo t = type;
|
||||
IList<FieldInfo> fields = new List<FieldInfo>();
|
||||
while (t != null)
|
||||
{
|
||||
foreach (FieldInfo member in t.DeclaredFields)
|
||||
{
|
||||
if (!fields.Any(p => p.Name == member.Name))
|
||||
{
|
||||
fields.Add(member);
|
||||
}
|
||||
}
|
||||
t = (t.BaseType != null) ? t.BaseType.GetTypeInfo() : null;
|
||||
}
|
||||
|
||||
return fields;
|
||||
}
|
||||
|
||||
public static IEnumerable<MethodInfo> GetMethods(this Type type, BindingFlags bindingFlags)
|
||||
{
|
||||
return type.GetTypeInfo().DeclaredMethods;
|
||||
}
|
||||
|
||||
public static PropertyInfo GetProperty(this Type type, string name)
|
||||
{
|
||||
return type.GetProperty(name, DefaultFlags);
|
||||
}
|
||||
|
||||
public static PropertyInfo GetProperty(this Type type, string name, BindingFlags bindingFlags)
|
||||
{
|
||||
return type.GetTypeInfo().GetDeclaredProperty(name);
|
||||
}
|
||||
|
||||
public static IEnumerable<FieldInfo> GetFields(this Type type)
|
||||
{
|
||||
return type.GetFields(DefaultFlags);
|
||||
}
|
||||
|
||||
public static IEnumerable<FieldInfo> GetFields(this Type type, BindingFlags bindingFlags)
|
||||
{
|
||||
IList<FieldInfo> fields = (bindingFlags.HasFlag(BindingFlags.DeclaredOnly))
|
||||
? type.GetTypeInfo().DeclaredFields.ToList()
|
||||
: type.GetTypeInfo().GetFieldsRecursive();
|
||||
|
||||
return fields.Where(f => TestAccessibility(f, bindingFlags)).ToList();
|
||||
}
|
||||
|
||||
private static bool TestAccessibility(PropertyInfo member, BindingFlags bindingFlags)
|
||||
{
|
||||
if (member.GetMethod != null && TestAccessibility(member.GetMethod, bindingFlags))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (member.SetMethod != null && TestAccessibility(member.SetMethod, bindingFlags))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private static bool TestAccessibility(MemberInfo member, BindingFlags bindingFlags)
|
||||
{
|
||||
if (member is FieldInfo)
|
||||
{
|
||||
return TestAccessibility((FieldInfo) member, bindingFlags);
|
||||
}
|
||||
else if (member is MethodBase)
|
||||
{
|
||||
return TestAccessibility((MethodBase) member, bindingFlags);
|
||||
}
|
||||
else if (member is PropertyInfo)
|
||||
{
|
||||
return TestAccessibility((PropertyInfo) member, bindingFlags);
|
||||
}
|
||||
|
||||
throw new Exception("Unexpected member type.");
|
||||
}
|
||||
|
||||
private static bool TestAccessibility(FieldInfo member, BindingFlags bindingFlags)
|
||||
{
|
||||
bool visibility = (member.IsPublic && bindingFlags.HasFlag(BindingFlags.Public)) ||
|
||||
(!member.IsPublic && bindingFlags.HasFlag(BindingFlags.NonPublic));
|
||||
|
||||
bool instance = (member.IsStatic && bindingFlags.HasFlag(BindingFlags.Static)) ||
|
||||
(!member.IsStatic && bindingFlags.HasFlag(BindingFlags.Instance));
|
||||
|
||||
return visibility && instance;
|
||||
}
|
||||
|
||||
private static bool TestAccessibility(MethodBase member, BindingFlags bindingFlags)
|
||||
{
|
||||
bool visibility = (member.IsPublic && bindingFlags.HasFlag(BindingFlags.Public)) ||
|
||||
(!member.IsPublic && bindingFlags.HasFlag(BindingFlags.NonPublic));
|
||||
|
||||
bool instance = (member.IsStatic && bindingFlags.HasFlag(BindingFlags.Static)) ||
|
||||
(!member.IsStatic && bindingFlags.HasFlag(BindingFlags.Instance));
|
||||
|
||||
return visibility && instance;
|
||||
}
|
||||
|
||||
public static Type[] GetGenericArguments(this Type type)
|
||||
{
|
||||
return type.GetTypeInfo().GenericTypeArguments;
|
||||
}
|
||||
|
||||
public static IEnumerable<Type> GetInterfaces(this Type type)
|
||||
{
|
||||
return type.GetTypeInfo().ImplementedInterfaces;
|
||||
}
|
||||
|
||||
public static IEnumerable<MethodInfo> GetMethods(this Type type)
|
||||
{
|
||||
return type.GetTypeInfo().DeclaredMethods;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
public static bool IsAbstract(this Type type)
|
||||
{
|
||||
#if !(DOTNET || PORTABLE)
|
||||
return type.IsAbstract;
|
||||
#else
|
||||
return type.GetTypeInfo().IsAbstract;
|
||||
#endif
|
||||
}
|
||||
|
||||
public static bool IsVisible(this Type type)
|
||||
{
|
||||
#if !(DOTNET || PORTABLE)
|
||||
return type.IsVisible;
|
||||
#else
|
||||
return type.GetTypeInfo().IsVisible;
|
||||
#endif
|
||||
}
|
||||
|
||||
public static bool IsValueType(this Type type)
|
||||
{
|
||||
#if !(DOTNET || PORTABLE)
|
||||
return type.IsValueType;
|
||||
#else
|
||||
return type.GetTypeInfo().IsValueType;
|
||||
#endif
|
||||
}
|
||||
|
||||
public static bool AssignableToTypeName(this Type type, string fullTypeName, out Type match)
|
||||
{
|
||||
Type current = type;
|
||||
|
||||
while (current != null)
|
||||
{
|
||||
if (string.Equals(current.FullName, fullTypeName, StringComparison.Ordinal))
|
||||
{
|
||||
match = current;
|
||||
return true;
|
||||
}
|
||||
|
||||
current = current.BaseType();
|
||||
}
|
||||
|
||||
foreach (Type i in type.GetInterfaces())
|
||||
{
|
||||
if (string.Equals(i.Name, fullTypeName, StringComparison.Ordinal))
|
||||
{
|
||||
match = type;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
match = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
public static bool AssignableToTypeName(this Type type, string fullTypeName)
|
||||
{
|
||||
Type match;
|
||||
return type.AssignableToTypeName(fullTypeName, out match);
|
||||
}
|
||||
|
||||
public static bool ImplementInterface(this Type type, Type interfaceType)
|
||||
{
|
||||
for (Type currentType = type; currentType != null; currentType = currentType.BaseType())
|
||||
{
|
||||
IEnumerable<Type> interfaces = currentType.GetInterfaces();
|
||||
foreach (Type i in interfaces)
|
||||
{
|
||||
if (i == interfaceType || (i != null && i.ImplementInterface(interfaceType)))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
40
Common/00-1Json8.3/Json8.3/Utilities/ValidationUtils.cs
Normal file
40
Common/00-1Json8.3/Json8.3/Utilities/ValidationUtils.cs
Normal file
@@ -0,0 +1,40 @@
|
||||
#region License
|
||||
// Copyright (c) 2007 James Newton-King
|
||||
//
|
||||
// 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;
|
||||
|
||||
namespace Newtonsoft.Json.Utilities
|
||||
{
|
||||
internal static class ValidationUtils
|
||||
{
|
||||
public static void ArgumentNotNull(object value, string parameterName)
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
throw new ArgumentNullException(parameterName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user