//----------------------------------------------------------------------------
// Copyright (C) 2004-2023 by EMGU Corporation. All rights reserved.
//----------------------------------------------------------------------------
using System;
using System.Text;
using System.Xml;
using System.Xml.Linq;
using System.Xml.Serialization;
using System.IO;
using System.Runtime.InteropServices;
using System.Diagnostics;
using System.Collections.Generic;
using System.Reflection;
namespace Emgu.Util
{
///
/// utilities functions for Emgu
///
public static class Toolbox
{
#region xml serilization and deserialization
///
/// Convert an object to an xml document
///
/// The type of the object to be converted
/// The object to be serialized
/// An xml document that represents the object
public static XDocument XmlSerialize(T sourceObject)
{
StringBuilder sb = new StringBuilder();
using (StringWriter sw = new StringWriter(sb))
(new XmlSerializer(typeof(T))).Serialize(sw, sourceObject);
return XDocument.Parse(sb.ToString());
}
///
/// Convert an object to an xml document
///
/// The type of the object to be converted
/// The object to be serialized
/// Other types that it must known ahead to serialize the object
/// An xml document that represents the object
public static XDocument XmlSerialize(T sourceObject, Type[] knownTypes)
{
StringBuilder sb = new StringBuilder();
using (StringWriter sw = new StringWriter(sb))
(new XmlSerializer(typeof(T), knownTypes)).Serialize(sw, sourceObject);
return XDocument.Parse(sb.ToString());
}
///
/// Convert an xml document to an object
///
/// The type of the object to be converted to
/// The xml document
/// The object representation as a result of the deserialization of the xml document
public static T XmlDeserialize(XDocument document)
{
using (XmlReader reader = document.Root.CreateReader())
{
if (reader.CanReadBinaryContent)
return (T)(new XmlSerializer(typeof(T))).Deserialize(reader);
else
{
return XmlStringDeserialize(document.ToString());
}
}
}
///
/// Convert an xml document to an object
///
/// The type of the object to be converted to
/// The xml document
/// Other types that it must known ahead to deserialize the object
/// The object representation as a result of the deserialization of the xml document
public static T XmlDeserialize(XDocument xDoc, Type[] knownTypes)
{
using (XmlReader reader = xDoc.Root.CreateReader())
{
if (reader.CanReadBinaryContent)
return (T)(new XmlSerializer(typeof(T), knownTypes)).Deserialize(reader);
else
{
using (StringReader stringReader = new StringReader(xDoc.ToString()))
{
return (T)(new XmlSerializer(typeof(T), knownTypes)).Deserialize(stringReader);
}
}
}
}
///
/// Convert an xml string to an object
///
/// The type of the object to be converted to
/// The xml document as a string
/// The object representation as a result of the deserialization of the xml string
public static T XmlStringDeserialize(String xmlString)
{
using (StringReader stringReader = new StringReader(xmlString))
return (T)(new XmlSerializer(typeof(T))).Deserialize(stringReader);
}
#endregion
///
/// Similar to Marshal.SizeOf function
///
/// The type
/// The size of T in bytes
public static int SizeOf()
{
return Marshal.SizeOf();
}
/*
///
/// Read a text file to an array of string, each row are separated using by the input separator
///
/// The text file to read from
/// The row separator
///
public static string FileToString(string fileName, char separator)
{
StringBuilder res = new StringBuilder();
string input;
using (StreamReader sr = File.OpenText(fileName))
while ((input = sr.ReadLine()) != null)
res.AppendFormat("{0}{1}", input, separator);
return res.ToString();
}*/
///
/// Merges two byte vector into one
///
/// the first byte vector to be merged
/// the second byte vector to be merged
/// The bytes that is a concatenation of a and b
public static Byte[] MergeBytes(Byte[] a, Byte[] b)
{
Byte[] c = new byte[a.Length + b.Length]; // just one array allocation
Buffer.BlockCopy(a, 0, c, 0, a.Length);
Buffer.BlockCopy(b, 0, c, a.Length, b.Length);
return c;
}
///
/// Call a command from command line
///
/// The name of the executable
/// The arguments to the executable
/// The standard output
public static string ExecuteCmd(string execFileName, string arguments)
{
using (Process processor = new Process())
{
processor.StartInfo.FileName = execFileName;
processor.StartInfo.Arguments = arguments;
processor.StartInfo.UseShellExecute = false;
processor.StartInfo.RedirectStandardOutput = true;
processor.StartInfo.RedirectStandardError = true;
//string error = string.Empty;
try
{
processor.Start();
}
catch (Exception)
{
//error = e.Message;
}
//processor.BeginErrorReadLine();
//String error2 = processor.StandardError.ReadToEnd();
string output = processor.StandardOutput.ReadToEnd();
processor.WaitForExit();
processor.Close();
return output;
}
}
///
/// Use reflection to find the base type. If such type do not exist, null is returned
///
/// The type to search from
/// The name of the base class to search
/// The base type
public static Type GetBaseType(Type currentType, String baseClassName)
{
if (currentType.Name.Equals(baseClassName))
return currentType;
Type baseType = currentType.BaseType;
return (baseType == null) ?
null : GetBaseType(baseType, baseClassName);
}
#region memory copy
///
/// Convert some generic vector to vector of Bytes
///
/// type of the input vector
/// array of data
/// the byte vector
public static Byte[] ToBytes(TData[] data)
{
int size = Marshal.SizeOf() * data.Length;
Byte[] res = new Byte[size];
GCHandle handle = GCHandle.Alloc(data, GCHandleType.Pinned);
Marshal.Copy(handle.AddrOfPinnedObject(), res, 0, size);
handle.Free();
return res;
}
///
/// Perform first degree interpolation give the sorted data and the interpolation
///
/// The sorted data that will be interpolated from
/// The indexes of the interpolate result
/// The type of the data to be interpolated
/// The interpolated data
public static IEnumerable LinearInterpolate(IEnumerable src, IEnumerable indexes) where T : IInterpolatable, new()
{
using (IEnumerator sampleEnumerator = src.GetEnumerator())
{
if (!sampleEnumerator.MoveNext())
yield break;
T old = sampleEnumerator.Current;
if (!sampleEnumerator.MoveNext())
yield break;
T current = sampleEnumerator.Current;
foreach (double index in indexes)
{
while (index > current.InterpolationIndex && sampleEnumerator.MoveNext())
{
old = current;
current = sampleEnumerator.Current;
}
//yield return LinearInterpolate(old, current, index);
yield return old.LinearInterpolate(current, index);
}
}
}
///
/// Get subsamples with the specific rate
///
/// The source which the subsamples will be derived from
/// The subsample rate
/// subsampled with the specific rate
/// The type of the object
public static IEnumerable LinearSubsample(IEnumerable src, double subsampleRate) where T : IInterpolatable, new()
{
using (IEnumerator sampleEnumerator = src.GetEnumerator())
{
if (!sampleEnumerator.MoveNext())
yield break;
T old = sampleEnumerator.Current;
yield return old;
if (!sampleEnumerator.MoveNext())
yield break;
T current = sampleEnumerator.Current;
double currentIndex = old.InterpolationIndex + subsampleRate;
bool endOfSubsample = false;
while (!endOfSubsample)
{
while (currentIndex > current.InterpolationIndex)
{
if (endOfSubsample = !sampleEnumerator.MoveNext())
break;
old = current;
current = sampleEnumerator.Current;
}
if (!endOfSubsample)
{
yield return old.LinearInterpolate(current, currentIndex);
//yield return LinearInterpolate(old, current, currentIndex);
currentIndex += subsampleRate;
}
}
}
}
///
/// Joining multiple index ascending IInterpolatables together as a single index ascending IInterpolatable.
///
/// The type of objects that will be joined
/// The enumerables, each should be stored in index ascending order
/// A single enumerable sorted in index ascending order
public static IEnumerable JoinInterpolatables(params IEnumerable[] enums) where T : IInterpolatable, new()
{
if (enums.Length == 0)
yield break;
else if (enums.Length == 1)
{
foreach (T sample in enums[0])
yield return sample;
}
else if (enums.Length == 2)
{
foreach (T sample in JoinTwoInterpolatables(enums[0], enums[1]))
yield return sample;
}
else
{
int middle = enums.Length / 2;
IEnumerable[] lower = new IEnumerable[middle];
IEnumerable[] upper = new IEnumerable[enums.Length - middle];
Array.Copy(enums, lower, middle);
Array.Copy(enums, middle, upper, 0, enums.Length - middle);
foreach (T sample in JoinTwoInterpolatables(JoinInterpolatables(lower), JoinInterpolatables(upper)))
yield return sample;
}
}
private static IEnumerable JoinTwoInterpolatables(IEnumerable enum1, IEnumerable enum2) where T : IInterpolatable, new()
{
IEnumerator l1 = enum1.GetEnumerator();
IEnumerator l2 = enum2.GetEnumerator();
if (!l1.MoveNext())
{
while (l2.MoveNext())
yield return l2.Current;
yield break;
}
else if (!l2.MoveNext())
{
while (l1.MoveNext())
yield return l1.Current;
yield break;
}
T s1 = l1.Current;
T s2 = l2.Current;
while (true)
{
if (s1.InterpolationIndex < s2.InterpolationIndex)
{
yield return s1;
if (l1.MoveNext())
s1 = l1.Current;
else
{
while (l2.MoveNext())
yield return l2.Current;
yield break;
}
}
else
{
yield return s2;
if (l2.MoveNext())
s2 = l2.Current;
else
{
while (l1.MoveNext())
yield return l1.Current;
yield break;
}
}
}
}
/*
///
/// Use the two IInterpolatable and the index to perform first degree interpolation
///
/// The first element to interpolate from
/// The second eleemnt to interpolate from
/// The interpolation index
/// The interpolatation result
private static T LinearInterpolate(T i1, T i2, double index) where T : IInterpolatable, new()
{
double f = (i2.InterpolationIndex - index) / (i2.InterpolationIndex - i1.InterpolationIndex);
//compute result = i1 * f + i2 * (1.0 - f)
T a = new T();
a.Add(i1);
a.Mul(f);
T b = new T();
b.Add(i2);
b.Mul(1.0 - f);
a.Add(b);
return a;
}*/
#endregion
private static System.Collections.Generic.Dictionary _assemblyNameDict = new Dictionary();
///
/// Load all the assemblies.
///
/// All the assemblies loaded.
public static System.Reflection.Assembly[] LoadAllDependentAssemblies()
{
try
{
lock (_assemblyNameDict)
{
System.Reflection.Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
bool dirty = false;
foreach (Assembly assembly in assemblies)
{
AssemblyName name = assembly.GetName();
if (!_assemblyNameDict.ContainsKey(name.ToString()))
_assemblyNameDict.Add(name.ToString(), name);
}
foreach (Assembly assembly in assemblies)
{
AssemblyName[] referencedAssemblyNames = assembly.GetReferencedAssemblies();
foreach (AssemblyName name in referencedAssemblyNames)
{
if (!_assemblyNameDict.ContainsKey(name.ToString()))
{
try
{
Assembly.Load(name);
_assemblyNameDict.Add(name.ToString(), name);
dirty = true;
}
catch (Exception e)
{
//if failed to load, it is ok, we will continue.
Debug.WriteLine(e);
}
}
}
}
if (dirty)
return AppDomain.CurrentDomain.GetAssemblies();
else
{
return assemblies;
}
}
}
catch (Exception e)
{
Debug.WriteLine(e);
}
return null;
}
///
/// Get the interface implementation from assemblies
///
/// The interface
/// The types that implement the specific interface
public static Type[] GetInterfaceImplementationFromAssembly()
{
System.Reflection.Assembly[] assemblies = LoadAllDependentAssemblies();
List types = new List();
if (assemblies != null)
{
foreach (Assembly assembly in assemblies)
{
foreach (Type t in assembly.GetTypes())
{
if (typeof(T).IsAssignableFrom(t) && typeof(T) != t)
{
types.Add(t);
}
}
}
}
return types.ToArray();
}
///
/// Find the loaded assembly with the specific assembly name
///
/// The name of the assembly
/// The assembly.
public static System.Reflection.Assembly FindAssembly(String assembleName)
{
try
{
System.Reflection.Assembly[] asms = AppDomain.CurrentDomain.GetAssemblies();
foreach (System.Reflection.Assembly asm in asms)
{
if (asm.ManifestModule.Name.Equals(assembleName))
return asm;
}
}
catch (Exception exception)
{
Trace.WriteLine(String.Format("FindAssembly({0}) failed: {1}", assembleName, exception.Message));
}
return null;
}
private static IntPtr LoadLibraryExWindows(String dllname, int flags)
{
IntPtr handler = LoadLibraryEx(dllname, IntPtr.Zero, flags);
if (handler == IntPtr.Zero)
{
int error = Marshal.GetLastWin32Error();
System.ComponentModel.Win32Exception ex = new System.ComponentModel.Win32Exception(error);
System.Diagnostics.Trace.WriteLine(String.Format(
"LoadLibraryEx(\"{0}\", 0, {3}) failed with error code {1}: {2}",
dllname,
(uint) error,
ex.Message,
flags));
if (error == 5)
{
System.Diagnostics.Trace.WriteLine(String.Format(
"Please check if the current user has execute permission for file: {0} ", dllname));
}
}
else
{
System.Diagnostics.Trace.WriteLine(String.Format("LoadLibraryEx(\"{0}\", 0, {1}) successfully loaded library.", dllname, flags));
}
return handler;
}
private static IntPtr LoadLibraryWindows(String dllname)
{
const int loadLibrarySearchDllLoadDir = 0x00000100;
const int loadLibrarySearchDefaultDirs = 0x00001000;
int flags;
if (System.IO.Path.IsPathRooted(dllname))
{
flags = loadLibrarySearchDllLoadDir | loadLibrarySearchDefaultDirs;
}
else
{
flags = loadLibrarySearchDefaultDirs;
}
IntPtr handler = LoadLibraryExWindows(dllname, flags);
if (handler == IntPtr.Zero)
{
//Try again with the '0' flags.
//The first attempt above may fail, if the native dll is within a folder in the PATH environment variable.
//The call below will also search for folders in PATH environment variable.
handler = LoadLibraryExWindows(dllname, 0);
}
// LoadPackagedLibrary() is supported from Windows 8 (6.2) onwards
if (handler == IntPtr.Zero && Environment.OSVersion.Version >= new Version(6, 2))
{
//Also try loadPackagedLibrary
IntPtr packagedLibraryHandler = LoadPackagedLibrary(dllname, 0);
if (packagedLibraryHandler == IntPtr.Zero)
{
int error = Marshal.GetLastWin32Error();
var ex = new System.ComponentModel.Win32Exception(error);
System.Diagnostics.Debug.WriteLine(String.Format(
"LoadPackagedLibrary {0} failed with error code {1}: {2}", dllname, (uint)error,
ex.Message));
}
else
{
System.Diagnostics.Trace.WriteLine(String.Format("LoadPackagedLibrary loaded: {0}", dllname));
return packagedLibraryHandler;
}
}
return handler;
}
///
/// Maps the specified executable module into the address space of the calling process.
///
/// The name of the dll
/// The handle to the library
public static IntPtr LoadLibrary(String dllname)
{
#if UNITY_EDITOR_WIN
return LoadLibraryWindows(dllname);
#else
if (Platform.OperationSystem == Emgu.Util.Platform.OS.Windows)
{
return LoadLibraryWindows(dllname);
}
else
{
IntPtr handler;
try
{
handler = Dlopen(dllname, 0x00102); // 0x00002 == RTLD_NOW, 0x00100 = RTL_GLOBAL
if (handler == IntPtr.Zero)
{
System.Diagnostics.Trace.WriteLine(String.Format("Failed to use dlopen to load {0}", dllname));
}
}
catch
{
System.Diagnostics.Trace.WriteLine(String.Format("Failed to use dlopen from libdl.so to load {0}, will try using libdl.so.2 instead", dllname));
handler = Dlopen2(dllname, 0x00102); // 0x00002 == RTLD_NOW, 0x00100 = RTL_GLOBAL
if (handler == IntPtr.Zero)
{
System.Diagnostics.Trace.WriteLine(String.Format("Failed to use dlopen from libdl.so.2 to load {0}", dllname));
}
}
return handler;
}
#endif
}
/*
[DllImport("kernel32", CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true)]
static extern UIntPtr GetProcAddress(IntPtr hModule, string procName);
private static bool? _kernel32HasLoadPackagedLibrary = null;
private static IntPtr LoadPackagedLibrarySafe(String fileName, int dwFlags)
{
if (_kernel32HasLoadPackagedLibrary == null)
{
UIntPtr = GetProcAddress("")
}
}*/
[DllImport("Kernel32.dll", SetLastError = true)]
private static extern IntPtr LoadPackagedLibrary(
[MarshalAs(UnmanagedType.LPStr)]
String fileName,
int dwFlags);
[DllImport("Kernel32.dll", SetLastError = true)]
private static extern IntPtr LoadLibraryEx(
[MarshalAs(UnmanagedType.LPStr)]
String fileName,
IntPtr hFile,
int dwFlags);
[DllImport("dl", EntryPoint = "dlopen")]
private static extern IntPtr Dlopen(
[MarshalAs(UnmanagedType.LPStr)]
String dllname, int mode);
[DllImport("libdl.so.2", EntryPoint = "dlopen")]
private static extern IntPtr Dlopen2(
[MarshalAs(UnmanagedType.LPStr)]
String dllname, int mode);
/*
///
/// Decrements the reference count of the loaded dynamic-link library (DLL). When the reference count reaches zero, the module is unmapped from the address space of the calling process and the handle is no longer valid
///
/// The handle to the library
/// If the function succeeds, the return value is true. If the function fails, the return value is false.
[DllImport("kernel32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool FreeLibrary(IntPtr handle);
*/
///
/// Set the directory to the search path used to locate DLLs for the application
///
/// The directory to be searched for DLLs
/// True if success
[DllImport("Kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool SetDllDirectory(String path);
///
/// Get the search path used to locate DLLs for the application
///
///
/// If the function succeeds, the return value is the search path used to locate DLLs for the application
/// If the function fails, the return value is null.To get extended error information, call GetLastError.
///
public static String GetDllDirectory()
{
int maxSize = 2048;
IntPtr buffer = Marshal.AllocHGlobal(maxSize);
try
{
bool success = GetDllDirectory((uint) maxSize, buffer);
if (!success)
return null;
return Marshal.PtrToStringUni(buffer);
}
catch (Exception e)
{
Trace.WriteLine("Failed to call into GetDllDirectory:" + Environment.NewLine + e.StackTrace);
return null;
}
finally
{
Marshal.FreeHGlobal(buffer);
}
}
[DllImport("Kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool GetDllDirectory(uint nBufferLength, IntPtr lpBuffer);
///
/// Adds a directory to the search path used to locate DLLs for the application
///
/// The directory to be searched for DLLs
/// True if success
[DllImport("Kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool AddDllDirectory(String path);
}
}