/*
* This file is part of NLua.
*
* Copyright (c) 2014 Vinicius Jarina (viniciusjarina@gmail.com)
* Copyright (C) 2012 Megax
*
* 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.
*/
using System;
using System.Linq;
using System.Collections.Generic;
using System.Reflection;
using System.Runtime.CompilerServices;
namespace NLua.Extensions
{
///
/// Some random extension stuff.
///
static class CheckNull
{
///
/// Determines whether the specified obj is null.
///
/// The obj.
///
/// true if the specified obj is null; otherwise, false.
///
///
#if USE_KOPILUA
public static bool IsNull (object obj)
{
return (obj == null);
}
#else
public static bool IsNull (IntPtr ptr)
{
return (ptr.Equals (IntPtr.Zero));
}
#endif
}
static class TypeExtensions
{
public static bool HasMethod (this Type t, string name)
{
var op = t.GetMethods (BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static);
return op.Any (m => m.Name == name);
}
public static bool HasAdditionOpertator (this Type t)
{
if (t.IsPrimitive ())
return true;
return t.HasMethod ("op_Addition");
}
public static bool HasSubtractionOpertator (this Type t)
{
if (t.IsPrimitive ())
return true;
return t.HasMethod ("op_Subtraction");
}
public static bool HasMultiplyOpertator (this Type t)
{
if (t.IsPrimitive ())
return true;
return t.HasMethod ("op_Multiply");
}
public static bool HasDivisionOpertator (this Type t)
{
if (t.IsPrimitive ())
return true;
return t.HasMethod ("op_Division");
}
public static bool HasModulusOpertator (this Type t)
{
if (t.IsPrimitive ())
return true;
return t.HasMethod ("op_Modulus");
}
public static bool HasUnaryNegationOpertator (this Type t)
{
if (t.IsPrimitive ())
return true;
// Unary - will always have only one version.
var op = t.GetMethod ("op_UnaryNegation", BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static);
return op != null;
}
public static bool HasEqualityOpertator (this Type t)
{
if (t.IsPrimitive ())
return true;
return t.HasMethod ("op_Equality");
}
public static bool HasLessThanOpertator (this Type t)
{
if (t.IsPrimitive ())
return true;
return t.HasMethod ("op_LessThan");
}
public static bool HasLessThanOrEqualOpertator (this Type t)
{
if (t.IsPrimitive ())
return true;
return t.HasMethod ("op_LessThanOrEqual");
}
public static MethodInfo [] GetMethods (this Type t, string name, BindingFlags flags)
{
return t.GetMethods (flags).Where (m => m.Name == name).ToArray ();
}
public static MethodInfo [] GetExtensionMethods (this Type type, IEnumerable assemblies = null)
{
List types = new List ();
types.AddRange (type.GetAssembly().GetTypes ().Where (t => t.IsPublic ()));
if (assemblies != null) {
foreach (Assembly item in assemblies) {
if (item == type.GetAssembly ())
continue;
types.AddRange (item.GetTypes ().Where (t => t.IsPublic ()));
}
}
var query = from extensionType in types
where extensionType.IsSealed() && !extensionType.IsGenericType() && !extensionType.IsNested
from method in extensionType.GetMethods (BindingFlags.Static | BindingFlags.Public)
where method.IsDefined (typeof (ExtensionAttribute), false)
where method.GetParameters () [0].ParameterType == type
select method;
return query.ToArray ();
}
///
/// Extends the System.Type-type to search for a given extended MethodeName.
///
/// Name of the Methode
/// the found Method or null
public static MethodInfo GetExtensionMethod (this Type t, string name, IEnumerable assemblies = null)
{
var mi = from methode in t.GetExtensionMethods (assemblies)
where methode.Name == name
select methode;
if (!mi.Any ())
return null;
else
return mi.First ();
}
public static bool IsPrimitive (this Type t)
{
#if NETFX_CORE
return t.GetTypeInfo ().IsPrimitive;
#else
return t.IsPrimitive;
#endif
}
public static bool IsClass (this Type t)
{
#if NETFX_CORE
return t.GetTypeInfo ().IsClass;
#else
return t.IsClass;
#endif
}
public static bool IsEnum (this Type t)
{
#if NETFX_CORE
return t.GetTypeInfo ().IsEnum;
#else
return t.IsEnum;
#endif
}
public static bool IsPublic (this Type t)
{
#if NETFX_CORE
return t.GetTypeInfo ().IsPublic;
#else
return t.IsPublic;
#endif
}
public static bool IsSealed (this Type t)
{
#if NETFX_CORE
return t.GetTypeInfo ().IsSealed;
#else
return t.IsSealed;
#endif
}
public static bool IsGenericType (this Type t)
{
#if NETFX_CORE
return t.GetTypeInfo ().IsGenericType;
#else
return t.IsGenericType;
#endif
}
public static bool IsInterface (this Type t)
{
#if NETFX_CORE
return t.GetTypeInfo ().IsInterface;
#else
return t.IsInterface;
#endif
}
public static Assembly GetAssembly (this Type t)
{
#if NETFX_CORE
return t.GetTypeInfo ().Assembly;
#else
return t.Assembly;
#endif
}
#if NETFX_CORE
// Missing Reflection methods from WinRT
public const BindingFlags Default = BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance;
public static MethodInfo GetMethod (this Type type, string name, BindingFlags flags, Type [] signature)
{
return GetMethods (type, flags).FirstOrDefault (c => c.Name == name && c.GetParameters ().Select (p => p.ParameterType).SequenceEqual (signature));
}
static IEnumerable GetTypes (this Assembly assembly)
{
return assembly.ExportedTypes;
}
public static bool IsAssignableFrom (this Type t, Type t2)
{
return t.GetTypeInfo ().IsAssignableFrom (t2.GetTypeInfo ());
}
public static MemberInfo [] GetMember (this Type type, string name, BindingFlags flags)
{
return GetMembers (type, flags).Where (m => m.Name == name).ToArray ();
}
public static MemberInfo [] GetMembers (this Type type, BindingFlags flags)
{
// Metro does have DeclaredMembers but nothing otherwise
return GetEvents (type, flags).Cast ()
.Concat (GetFields (type, flags).Cast ())
.Concat (GetMethods (type, flags).Cast ())
.Concat (GetProperties (type, flags).Cast ())
.ToArray ();
}
public static MethodInfo GetMethod (this Type type, string name)
{
return GetMethod (type, name, Default);
}
public static MethodInfo GetMethod (this Type type, string name, BindingFlags flags)
{
return GetMethods (type, flags).FirstOrDefault (m => m.Name == name);
}
public static MethodInfo [] GetMethods (this Type type)
{
return GetMethods (type, Default);
}
public static MethodInfo [] GetMethods (this Type type, BindingFlags flags)
{
var methods = type.GetRuntimeMethods ();
return methods.Where (m =>
((flags.HasFlag (BindingFlags.Static) == m.IsStatic) || (flags.HasFlag (BindingFlags.Instance) == !m.IsStatic)
) &&
(flags.HasFlag (BindingFlags.Public) == m.IsPublic)
).ToArray ();
}
public static PropertyInfo [] GetProperties (this Type type, BindingFlags flags)
{
var props = type.GetRuntimeProperties ();
return props.Where (p =>
((flags.HasFlag (BindingFlags.Static) == (p.GetMethod != null && p.GetMethod.IsStatic)) ||
(flags.HasFlag (BindingFlags.Instance) == (p.GetMethod != null && !p.GetMethod.IsStatic))
) &&
(flags.HasFlag (BindingFlags.Public) == (p.GetMethod != null && p.GetMethod.IsPublic)
)).ToArray ();
}
public static ConstructorInfo GetConstructor (this Type type, Type [] paramTypes)
{
return GetConstructors (type, Default).FirstOrDefault (c => c.GetParameters ().Select (p => p.ParameterType).SequenceEqual (paramTypes));
}
public static ConstructorInfo [] GetConstructors (this Type type)
{
return GetConstructors (type, Default);
}
public static ConstructorInfo [] GetConstructors (this Type type, BindingFlags flags)
{
var props = type.GetTypeInfo ().DeclaredConstructors;
return props.Where (p =>
((flags.HasFlag (BindingFlags.Static) == p.IsStatic) ||
(flags.HasFlag (BindingFlags.Instance) == !p.IsStatic)
) &&
(flags.HasFlag (BindingFlags.Public) == p.IsPublic)
).ToArray ();
}
public static EventInfo [] GetEvents (this Type type, BindingFlags flags)
{
var props = type.GetRuntimeEvents ();
return props.Where (p =>
((flags.HasFlag (BindingFlags.Static) == p.AddMethod.IsStatic) ||
(flags.HasFlag (BindingFlags.Instance) == !p.AddMethod.IsStatic)
) &&
(flags.HasFlag (BindingFlags.Public) == p.AddMethod.IsPublic)
).ToArray ();
}
public static FieldInfo GetField (this Type type, string name)
{
return GetField (type, name, Default);
}
public static FieldInfo GetField (this Type type, string name, BindingFlags flags)
{
return GetFields (type, flags).FirstOrDefault (f => f.Name == name);
}
public static FieldInfo [] GetFields (this Type type, BindingFlags flags)
{
var fields = type.GetRuntimeFields ();
return fields.Where (p =>
((flags.HasFlag (BindingFlags.Static) == p.IsStatic) || (flags.HasFlag (BindingFlags.Instance) == !p.IsStatic)
) &&
(flags.HasFlag (BindingFlags.Public) == p.IsPublic)
).ToArray ();
}
public static bool ImplementInterface (this Type t, string name)
{
return t.GetTypeInfo ().ImplementedInterfaces.Any (i => i.Name == name);
}
#endif
}
static class StringExtensions
{
public static IEnumerable SplitWithEscape (this string input, char separator, char escapeCharacter)
{
int start = 0;
int index = 0;
while (index < input.Length) {
index = input.IndexOf (separator, index);
if (index == -1)
break;
if (input [index - 1] == escapeCharacter) {
input = input.Remove (index - 1, 1);
continue;
}
yield return input.Substring (start, index - start);
index++;
start = index;
}
yield return input.Substring (start);
}
}
}