mirror of https://github.com/dahall/Vanara.git
Removed Core project unfinished files that were excluded.
parent
bd0c01d876
commit
5d711e9580
|
@ -1,67 +0,0 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Vanara.Collections
|
||||
{
|
||||
/// <summary>Represents a node in a <see cref="Hierarchy"/>.</summary>
|
||||
public class Entry
|
||||
{
|
||||
/// <summary>Initializes a new instance of the <see cref="Entry"/> class.</summary>
|
||||
/// <param name="key">The key.</param>
|
||||
public Entry(string key)
|
||||
{
|
||||
Key = key;
|
||||
}
|
||||
|
||||
/// <summary>Gets the children of this <see cref="Entry"/>.</summary>
|
||||
public Hierarchy Children { get; } = new Hierarchy();
|
||||
|
||||
/// <summary>Gets or sets the key for this <see cref="Entry"/>.</summary>
|
||||
/// <value>A unique string value.</value>
|
||||
public string Key { get; }
|
||||
}
|
||||
|
||||
/// <summary>Storage and parsing of flat string based folder hierarchy.</summary>
|
||||
/// <example>
|
||||
/// <code>
|
||||
/// Hierarchy cItems = new Hierarchy();
|
||||
/// cItems.AddEntry(sLine, 0);
|
||||
/// </code>
|
||||
/// </example>
|
||||
public class Hierarchy : Dictionary<string, Entry>
|
||||
{
|
||||
/// <summary>Gets or sets the separator used to split the hierarchy.</summary>
|
||||
/// <value>The separator.</value>
|
||||
public string Separator { get; set; } = "\\";
|
||||
|
||||
/// <summary>Parses and adds the entry to the hierarchy, creating any parent entries as required.</summary>
|
||||
/// <param name="entry">The entry.</param>
|
||||
/// <param name="startIndex">The start index.</param>
|
||||
public void AddEntry(string entry, int startIndex = 0)
|
||||
{
|
||||
if (string.IsNullOrEmpty(entry)) throw new ArgumentNullException(nameof(entry));
|
||||
if (startIndex >= entry.Length)
|
||||
return;
|
||||
|
||||
var endIndex = entry.IndexOf(Separator, startIndex, StringComparison.InvariantCulture);
|
||||
if (endIndex == -1)
|
||||
endIndex = entry.Length;
|
||||
var key = entry.Substring(startIndex, endIndex - startIndex);
|
||||
if (string.IsNullOrEmpty(key))
|
||||
return;
|
||||
|
||||
Entry item;
|
||||
if (ContainsKey(key))
|
||||
{
|
||||
item = this[key];
|
||||
}
|
||||
else
|
||||
{
|
||||
item = new Entry(key);
|
||||
Add(key, item);
|
||||
}
|
||||
// Now add the rest to the new item's children
|
||||
item.Children.AddEntry(entry, endIndex + 1);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,414 +0,0 @@
|
|||
#if !(NET20)
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Vanara.Collections
|
||||
{
|
||||
public static partial class TreeExtension
|
||||
{
|
||||
private const char defaultSeparator = '\\';
|
||||
|
||||
/// <summary>Parses and adds the entry to the hierarchy, creating any parent entries as required.</summary>
|
||||
/// <param name="tree">The tree.</param>
|
||||
/// <param name="entry">The delimiter separated list of child node values.</param>
|
||||
/// <param name="startIndex">The index of the character in <paramref name="entry"/> at which to start reading node values.</param>
|
||||
/// <param name="separator">The separator character used as the delimiter.</param>
|
||||
public static void AddEntry(this Tree<string> tree, string entry, int startIndex = 0, char separator = defaultSeparator)
|
||||
{
|
||||
AddEntry((TreeNode<string>)tree, entry, startIndex, separator);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the child, potentially many levels down, by supplying a backslash ('\') separated list of children's string representations of their <see cref="TreeNode{T}.Value"/>.
|
||||
/// </summary>
|
||||
/// <param name="tree">The tree.</param>
|
||||
/// <param name="childPath">The backslash ('\') separated list of children's string representations.</param>
|
||||
/// <returns>The requested <see cref="TreeNode{T}"/>, or <c>null</c> if not found.</returns>
|
||||
public static TreeNode<string> NodeFromPath(this Tree<string> tree, string childPath)
|
||||
{
|
||||
childPath = childPath?.TrimStart(defaultSeparator);
|
||||
if (string.IsNullOrEmpty(childPath)) return tree;
|
||||
try
|
||||
{
|
||||
return childPath.Split(defaultSeparator).Aggregate((TreeNode<string>)tree, (current, key) => current.Children.First(p => string.Equals(key, p.Value, StringComparison.InvariantCulture)));
|
||||
}
|
||||
catch
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static void AddEntry(this TreeNode<string> tree, string entry, int startIndex, char separator)
|
||||
{
|
||||
if (string.IsNullOrEmpty(entry)) throw new ArgumentNullException(nameof(entry));
|
||||
if (startIndex >= entry.Length)
|
||||
return;
|
||||
|
||||
var endIndex = entry.IndexOf(separator, startIndex);
|
||||
if (endIndex == -1)
|
||||
endIndex = entry.Length;
|
||||
var key = entry.Substring(startIndex, endIndex - startIndex);
|
||||
if (string.IsNullOrEmpty(key))
|
||||
return;
|
||||
|
||||
// Now add the rest to the new item's children
|
||||
var item = tree.Children.Contains(key) ? tree.Children.GetNode(key) : tree.Children.Add(key);
|
||||
AddEntry(item, entry, endIndex + 1);
|
||||
|
||||
/*while (startIndex < entry.Length)
|
||||
{
|
||||
var endIndex = entry.IndexOf(pathDesignator, startIndex);
|
||||
if (endIndex == -1) endIndex = entry.Length;
|
||||
var key = entry.Substring(startIndex, endIndex - startIndex);
|
||||
if (string.IsNullOrEmpty(key)) return;
|
||||
|
||||
node = enumChildren(node).FirstOrDefault(n => getPath(n) == key) ?? addChild(node, key);
|
||||
startIndex = endIndex + 1;
|
||||
}*/
|
||||
}
|
||||
}
|
||||
|
||||
public static partial class TupleExtension
|
||||
{
|
||||
public static void Add<T1, T2>(this IList<Tuple<T1, T2>> list, T1 item1, T2 item2)
|
||||
{
|
||||
list.Add(new Tuple<T1, T2>(item1, item2));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>A hierarchical tree containing nodes of type <typeparamref name="T"/>.</summary>
|
||||
/// <typeparam name="T">The type of the node.</typeparam>
|
||||
public class Tree<T> : TreeNode<T> where T : IComparable<T>
|
||||
{
|
||||
/// <summary>Gets the zero-based depth of the tree node in the <see cref="T:Vanara.PInvoke.Tree`1"/>.</summary>
|
||||
/// <value>The zero-based depth of the tree node in the <see cref="T:Vanara.PInvoke.Tree`1"/>.</value>
|
||||
public override int Level => 0;
|
||||
|
||||
/// <summary>Gets the parent tree node of the current tree node.</summary>
|
||||
/// <value>A <see cref="T:Vanara.PInvoke.TreeNode`1"/> that represents the parent of the current tree node.</value>
|
||||
public override TreeNode<T> Parent => null;
|
||||
|
||||
/// <summary>Gets the root node of the tree. If this node has no parent, then it will be returned.</summary>
|
||||
/// <value>The root node.</value>
|
||||
public override TreeNode<T> RootNode => this;
|
||||
|
||||
/// <summary>Creates a tree from a list of paired values.</summary>
|
||||
/// <param name="input">A list of paired values.</param>
|
||||
/// <returns>A tree of leafs constructed from the list.</returns>
|
||||
public static Tree<T> FromParentChildPairs(ICollection<Tuple<T, T>> input)
|
||||
{
|
||||
if (input == null) throw new ArgumentNullException(nameof(input));
|
||||
var ret = new Tree<T>();
|
||||
var uniq1 = input.Select(i => i.Item1).Distinct();
|
||||
var uniq2 = input.Select(i => i.Item2).Distinct();
|
||||
var roots = uniq1.Except(uniq2).ToArray();
|
||||
if (roots.Length == 1)
|
||||
{
|
||||
ret.Value = roots[0];
|
||||
roots = input.Where(i => Equals(i.Item1, ret.Value)).Select(i => i.Item2).ToArray();
|
||||
}
|
||||
ret.Children.AddRange(roots);
|
||||
var groups = input.GroupBy(i => i.Item1).ToArray();
|
||||
foreach (var n in ret.Children)
|
||||
n.AddChildren(groups);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/// <summary>Gets the child specified by the list of nodes.</summary>
|
||||
/// <param name="childKeys">The child values starting with the top-most child key.</param>
|
||||
/// <returns>The requested <see cref="TreeNode{T}"/>, or <c>null</c> if not found.</returns>
|
||||
public TreeNode<T> GetChild(params T[] childKeys)
|
||||
{
|
||||
try
|
||||
{
|
||||
return childKeys.Aggregate((TreeNode<T>)this, (current, key) => current.Children.First(n => Equals(n.Value, key)));
|
||||
}
|
||||
catch
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary></summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <seealso cref="System.IDisposable"/>
|
||||
public class TreeNode<T> : IDisposable where T : IComparable<T>
|
||||
{
|
||||
/// <summary>Initializes a new instance of the <see cref="TreeNode{T}"/> class.</summary>
|
||||
public TreeNode() { Children = new TreeNodeList(this); }
|
||||
|
||||
/// <summary>Initializes a new instance of the <see cref="TreeNode{T}"/> class.</summary>
|
||||
/// <param name="value">The value to assign to the <see cref="Value"/> property.</param>
|
||||
/// <param name="parent">Optionally nest this node to an existing parent <see cref="TreeNode{T}"/>.</param>
|
||||
public TreeNode(T value, TreeNode<T> parent = null) : this()
|
||||
{
|
||||
Value = value;
|
||||
Parent = parent;
|
||||
}
|
||||
|
||||
/// <summary>Gets the children (leafs) of the current node.</summary>
|
||||
/// <value>The children nodes.</value>
|
||||
public TreeNodeList Children { get; internal set; }
|
||||
|
||||
/// <summary>Gets the parent tree node of the current tree node.</summary>
|
||||
/// <value>A <see cref="TreeNode{T}"/> that represents the parent of the current tree node.</value>
|
||||
public virtual TreeNode<T> Parent { get; internal set; }
|
||||
|
||||
/// <summary>Gets the root node of the tree. If this node has no parent, then it will be returned.</summary>
|
||||
/// <value>The root node.</value>
|
||||
public virtual TreeNode<T> RootNode
|
||||
{
|
||||
get
|
||||
{
|
||||
var r = this;
|
||||
while (r.Parent != null) r = r.Parent;
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Gets or sets the value tied to this <see cref="TreeNode{T}"/>.</summary>
|
||||
/// <value>The value.</value>
|
||||
public virtual T Value { get; set; }
|
||||
|
||||
/// <summary>Gets the zero-based depth of the tree node in the <see cref="Tree{T}"/>.</summary>
|
||||
/// <value>The zero-based depth of the tree node in the <see cref="Tree{T}"/>.</value>
|
||||
public virtual int Level => Parent?.Level + 1 ?? 0;
|
||||
|
||||
/// <summary>Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.</summary>
|
||||
public virtual void Dispose()
|
||||
{
|
||||
Children.Dispose();
|
||||
(Value as IDisposable)?.Dispose();
|
||||
}
|
||||
|
||||
/// <summary>Returns a <see cref="System.String" /> that represents this instance.</summary>
|
||||
/// <returns>A <see cref="System.String" /> that represents this instance.</returns>
|
||||
public override string ToString() => $"{Value}";
|
||||
|
||||
internal void AddChildren(IGrouping<T, Tuple<T, T>>[] groups)
|
||||
{
|
||||
foreach (var child in groups.Where(g => Equals(g.Key, Value)))
|
||||
foreach (var pair in child)
|
||||
Children.Add(pair.Item2).AddChildren(groups);
|
||||
}
|
||||
|
||||
/// <summary>A list of leaf nodes for a <see cref="TreeNode{T}"/>. Exposed through the <see cref="TreeNode{T}.Children"/> property.</summary>
|
||||
/// <typeparam name="T">The type held by a node.</typeparam>
|
||||
/// <seealso cref="System.Collections.Generic.IList{Vanara.Collections.TreeNode{T}}"/>
|
||||
/// <seealso cref="System.IDisposable"/>
|
||||
public class TreeNodeList : IList<TreeNode<T>>, IDisposable
|
||||
{
|
||||
private readonly TreeNode<T> host;
|
||||
private readonly IList<TreeNode<T>> list;
|
||||
|
||||
// Prevent construction
|
||||
private TreeNodeList() { }
|
||||
|
||||
/// <summary>Initializes a new instance of the <see cref="TreeNodeList{T}"/> class.</summary>
|
||||
/// <param name="hostNode">The host node.</param>
|
||||
internal TreeNodeList(TreeNode<T> hostNode)
|
||||
{
|
||||
host = hostNode;
|
||||
list = new List<TreeNode<T>>();
|
||||
}
|
||||
|
||||
/// <summary>Gets the values for all nodes in this list.</summary>
|
||||
/// <value>The node values.</value>
|
||||
public IEnumerable<T> Values => list.Select(n => n.Value);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the number of elements contained in the <see cref="ICollection{T}" />.
|
||||
/// </summary>
|
||||
public int Count => list.Count;
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the <see cref="ICollection{T}" /> is read-only.
|
||||
/// </summary>
|
||||
bool ICollection<TreeNode<T>>.IsReadOnly => false;
|
||||
|
||||
/// <summary>Gets or sets the <see cref="TreeNode{T}"/> at the specified index. This will remove the tree node at this position</summary>
|
||||
/// <value>The <see cref="TreeNode{T}"/>.</value>
|
||||
/// <param name="index">The index.</param>
|
||||
/// <returns></returns>
|
||||
public TreeNode<T> this[int index]
|
||||
{
|
||||
get => list[index];
|
||||
set
|
||||
{
|
||||
value.Parent = host;
|
||||
list[index] = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Adds the specified item.</summary>
|
||||
/// <param name="item">The item.</param>
|
||||
/// <returns></returns>
|
||||
public virtual TreeNode<T> Add(T item)
|
||||
{
|
||||
var ret = MakeNode(item);
|
||||
list.Add(ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/// <summary>Adds an item to the <see cref="ICollection{T}" />.</summary>
|
||||
/// <param name="item">The object to add to the <see cref="ICollection{T}" />.</param>
|
||||
public void Add(TreeNode<T> item)
|
||||
{
|
||||
item.Parent = host;
|
||||
}
|
||||
|
||||
/// <summary>Adds the range.</summary>
|
||||
/// <param name="items">The items.</param>
|
||||
public void AddRange(IEnumerable<T> items)
|
||||
{
|
||||
foreach (var item in items)
|
||||
Add(item);
|
||||
}
|
||||
|
||||
/// <summary>Adds the range.</summary>
|
||||
/// <param name="items">The items.</param>
|
||||
public void AddRange(params T[] items)
|
||||
{
|
||||
AddRange(items.AsEnumerable());
|
||||
}
|
||||
|
||||
/// <summary>Removes all items from the <see cref="ICollection{T}" />.</summary>
|
||||
public virtual void Clear()
|
||||
{
|
||||
foreach (var n in list)
|
||||
n.Dispose();
|
||||
list.Clear();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether the <see cref="ICollection{T}" /> contains a specific value.
|
||||
/// </summary>
|
||||
/// <param name="item">The object to locate in the <see cref="ICollection{T}" />.</param>
|
||||
/// <returns>
|
||||
/// true if <paramref name="item" /> is found in the <see cref="ICollection{T}" />; otherwise, false.
|
||||
/// </returns>
|
||||
public bool Contains(TreeNode<T> item) => list.Contains(item);
|
||||
|
||||
/// <summary>Determines whether [contains] [the specified item].</summary>
|
||||
/// <param name="item">The item.</param>
|
||||
/// <returns><c>true</c> if [contains] [the specified item]; otherwise, <c>false</c>.</returns>
|
||||
public bool Contains(T item) => IndexOf(item) != -1;
|
||||
|
||||
/// <summary>
|
||||
/// Copies the elements of the <see cref="ICollection{T}" /> to an <see cref="T:System.Array" />, starting at a particular <see cref="T:System.Array" /> index.
|
||||
/// </summary>
|
||||
/// <param name="array">The one-dimensional <see cref="T:System.Array" /> that is the destination of the elements copied from <see cref="ICollection{T}" />. The <see cref="T:System.Array" /> must have zero-based indexing.</param>
|
||||
/// <param name="arrayIndex">The zero-based index in <paramref name="array" /> at which copying begins.</param>
|
||||
public void CopyTo(TreeNode<T>[] array, int arrayIndex)
|
||||
{
|
||||
list.CopyTo(array, arrayIndex);
|
||||
}
|
||||
|
||||
/// <summary>Copies to.</summary>
|
||||
/// <param name="array">The array.</param>
|
||||
/// <param name="arrayIndex">Index of the array.</param>
|
||||
public void CopyTo(T[] array, int arrayIndex)
|
||||
{
|
||||
list.Select(n => n.Value).ToArray().CopyTo(array, arrayIndex);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
|
||||
/// </summary>
|
||||
public virtual void Dispose()
|
||||
{
|
||||
Clear();
|
||||
}
|
||||
|
||||
/// <summary>Returns an enumerator that iterates through the collection.</summary>
|
||||
/// <returns>
|
||||
/// A <see cref="T:System.Collections.Generic.IEnumerator`1" /> that can be used to iterate through the collection.
|
||||
/// </returns>
|
||||
public IEnumerator<TreeNode<T>> GetEnumerator() => list.GetEnumerator();
|
||||
|
||||
/// <summary>Gets the node.</summary>
|
||||
/// <param name="item">The item.</param>
|
||||
/// <returns></returns>
|
||||
public TreeNode<T> GetNode(T item) => list.First(n => Equals(n.Value, item));
|
||||
|
||||
/// <summary>Indexes the of.</summary>
|
||||
/// <param name="item">The item.</param>
|
||||
/// <returns></returns>
|
||||
public virtual int IndexOf(T item) => ((List<TreeNode<T>>)list).FindIndex(n => Equals(n.Value, item));
|
||||
|
||||
/// <summary>Determines the index of a specific item in the <see cref="T:System.Collections.Generic.IList`1" />.</summary>
|
||||
/// <param name="item">The object to locate in the <see cref="T:System.Collections.Generic.IList`1" />.</param>
|
||||
/// <returns>The index of <paramref name="item" /> if found in the list; otherwise, -1.</returns>
|
||||
public int IndexOf(TreeNode<T> item) => list.IndexOf(item);
|
||||
|
||||
/// <summary>Inserts the specified index.</summary>
|
||||
/// <param name="index">The index.</param>
|
||||
/// <param name="item">The item.</param>
|
||||
/// <returns></returns>
|
||||
public virtual TreeNode<T> Insert(int index, T item)
|
||||
{
|
||||
var n = MakeNode(item);
|
||||
Insert(index, n);
|
||||
return n;
|
||||
}
|
||||
|
||||
/// <summary>Inserts an item to the <see cref="T:System.Collections.Generic.IList`1" /> at the specified index.</summary>
|
||||
/// <param name="index">The zero-based index at which <paramref name="item" /> should be inserted.</param>
|
||||
/// <param name="item">The object to insert into the <see cref="T:System.Collections.Generic.IList`1" />.</param>
|
||||
public void Insert(int index, TreeNode<T> item)
|
||||
{
|
||||
list.Insert(index, item);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes the first occurrence of a specific object from the <see cref="ICollection{T}" />.
|
||||
/// </summary>
|
||||
/// <param name="item">The object to remove from the <see cref="ICollection{T}" />.</param>
|
||||
/// <returns>
|
||||
/// true if <paramref name="item" /> was successfully removed from the <see cref="ICollection{T}" />; otherwise, false. This method also returns false if <paramref name="item" /> is not found in the original <see cref="ICollection{T}" />.
|
||||
/// </returns>
|
||||
public bool Remove(TreeNode<T> item) => list.Remove(item);
|
||||
|
||||
/// <summary>Removes the specified item.</summary>
|
||||
/// <param name="item">The item.</param>
|
||||
/// <returns></returns>
|
||||
public bool Remove(T item)
|
||||
{
|
||||
var i = IndexOf(item);
|
||||
if (i == -1) return false;
|
||||
list.RemoveAt(i);
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>Removes the <see cref="T:System.Collections.Generic.IList`1" /> item at the specified index.</summary>
|
||||
/// <param name="index">The zero-based index of the item to remove.</param>
|
||||
public void RemoveAt(int index)
|
||||
{
|
||||
list.RemoveAt(index);
|
||||
}
|
||||
|
||||
/// <summary>Returns a <see cref="System.String" /> that represents this instance.</summary>
|
||||
/// <returns>A <see cref="System.String" /> that represents this instance.</returns>
|
||||
public override string ToString() => $"Count:{list.Count}";
|
||||
|
||||
/// <summary>Returns an enumerator that iterates through a collection.</summary>
|
||||
/// <returns>
|
||||
/// An <see cref="T:System.Collections.IEnumerator" /> object that can be used to iterate through the collection.
|
||||
/// </returns>
|
||||
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
|
||||
|
||||
internal void InternalAdd(TreeNode<T> item)
|
||||
{
|
||||
list.Add(item);
|
||||
}
|
||||
|
||||
protected virtual TreeNode<T> MakeNode(T item) => new TreeNode<T>(item, host);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1,236 +0,0 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using Vanara.Extensions;
|
||||
|
||||
namespace Vanara.Collections
|
||||
{
|
||||
public class VaList : IDisposable
|
||||
{
|
||||
//protected byte[] buffer;
|
||||
protected readonly List<GCHandle> handles = new List<GCHandle>();
|
||||
|
||||
public VaList(params object[] args) : this(CharSet.Auto, args)
|
||||
{
|
||||
}
|
||||
|
||||
public VaList(CharSet charSet, params object[] args)
|
||||
{
|
||||
if (args == null) throw new ArgumentNullException(nameof(args));
|
||||
|
||||
var ptrs = new IntPtr[args.Length];
|
||||
handles.Add(GCHandle.Alloc(ptrs, GCHandleType.Pinned));
|
||||
|
||||
var enc = StringHelper.GetCharSize(charSet) == 1 ? Encoding.ASCII : Encoding.Unicode;
|
||||
for (var i = 0; i < args.Length; i++)
|
||||
{
|
||||
var arg = args[i];
|
||||
switch (arg)
|
||||
{
|
||||
case null:
|
||||
case DBNull n:
|
||||
break;
|
||||
case char c:
|
||||
ptrs[i] = (IntPtr) BitConverter.ToUInt16(enc.GetBytes(new[] {c}), 0);
|
||||
break;
|
||||
case string s:
|
||||
var bytes = s.GetBytesNullTerm(true, charSet);
|
||||
var handle = GCHandle.Alloc(bytes, GCHandleType.Pinned);
|
||||
handles.Add(handle);
|
||||
ptrs[i] = handle.AddrOfPinnedObject();
|
||||
break;
|
||||
case IntPtr p:
|
||||
ptrs[i] = p;
|
||||
break;
|
||||
case UIntPtr p:
|
||||
ptrs[i] = IntPtr.Size == 4 ? (IntPtr) Convert.ToInt32(p.ToUInt32()) : (IntPtr) Convert.ToInt64(p.ToUInt64());
|
||||
break;
|
||||
default:
|
||||
if (Marshal.SizeOf(arg) <= IntPtr.Size && arg.GetType().IsPrimitive)
|
||||
{
|
||||
ptrs[i] = IntPtr.Size == 4 ? (IntPtr) Convert.ToInt32(arg) : (IntPtr) Convert.ToInt64(arg);
|
||||
}
|
||||
else if (!arg.GetType().IsValueType)
|
||||
{
|
||||
var ohandle = GCHandle.Alloc(arg, GCHandleType.Pinned);
|
||||
handles.Add(ohandle);
|
||||
ptrs[i] = ohandle.AddrOfPinnedObject();
|
||||
}
|
||||
else
|
||||
throw new NotSupportedException();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*private void Test(CharSet charSet, params object[] args)
|
||||
{
|
||||
if (args == null) throw new ArgumentNullException(nameof(args));
|
||||
|
||||
// The first handle is for the bytes array
|
||||
handles.Add(default(GCHandle));
|
||||
|
||||
var bf = new BinaryFormatter();
|
||||
var enc = StringHelper.GetCharSize(charSet) == 1 ? Encoding.ASCII : Encoding.Unicode;
|
||||
using (var ms = new MemoryStream())
|
||||
using (var bw = new BinaryWriter(ms, enc, true))
|
||||
{
|
||||
foreach (var arg in args)
|
||||
{
|
||||
if (arg == null || arg == DBNull.Value)
|
||||
{
|
||||
WritePad(bw, 0);
|
||||
continue;
|
||||
}
|
||||
|
||||
var type = arg.GetType();
|
||||
var typeHandle = Type.GetTypeCode(type);
|
||||
switch (typeHandle)
|
||||
{
|
||||
case TypeCode.Boolean:
|
||||
bw.Write((bool)arg ? 1U : 0U);
|
||||
WritePad(bw, sizeof(int));
|
||||
break;
|
||||
|
||||
case TypeCode.SByte:
|
||||
bw.Write((sbyte)arg);
|
||||
WritePad(bw, Marshal.SizeOf(arg));
|
||||
break;
|
||||
|
||||
case TypeCode.Byte:
|
||||
bw.Write((byte)arg);
|
||||
WritePad(bw, Marshal.SizeOf(arg));
|
||||
break;
|
||||
|
||||
case TypeCode.Int16:
|
||||
bw.Write((short)arg);
|
||||
WritePad(bw, Marshal.SizeOf(arg));
|
||||
break;
|
||||
|
||||
case TypeCode.UInt16:
|
||||
bw.Write((ushort)arg);
|
||||
WritePad(bw, Marshal.SizeOf(arg));
|
||||
break;
|
||||
|
||||
case TypeCode.Int32:
|
||||
bw.Write((int)arg);
|
||||
WritePad(bw, Marshal.SizeOf(arg));
|
||||
break;
|
||||
|
||||
case TypeCode.UInt32:
|
||||
bw.Write((uint)arg);
|
||||
WritePad(bw, Marshal.SizeOf(arg));
|
||||
break;
|
||||
|
||||
case TypeCode.Int64:
|
||||
bw.Write((long)arg);
|
||||
WritePad(bw, Marshal.SizeOf(arg));
|
||||
break;
|
||||
|
||||
case TypeCode.UInt64:
|
||||
bw.Write((ulong)arg);
|
||||
WritePad(bw, Marshal.SizeOf(arg));
|
||||
break;
|
||||
|
||||
case TypeCode.Single:
|
||||
bw.Write((float)arg);
|
||||
WritePad(bw, Marshal.SizeOf(arg));
|
||||
break;
|
||||
|
||||
case TypeCode.Double:
|
||||
bw.Write((double)arg);
|
||||
WritePad(bw, Marshal.SizeOf(arg));
|
||||
break;
|
||||
|
||||
case TypeCode.Char:
|
||||
bw.Write((char)arg);
|
||||
WritePad(bw, enc.GetMaxCharCount(1));
|
||||
break;
|
||||
|
||||
case TypeCode.String:
|
||||
var str = (string)arg;
|
||||
var bytes = str.GetBytesNullTerm(true, charSet);
|
||||
var handle = GCHandle.Alloc(bytes, GCHandleType.Pinned);
|
||||
handles.Add(handle);
|
||||
WritePtr(bw, handle.AddrOfPinnedObject());
|
||||
break;
|
||||
|
||||
case TypeCode.Object:
|
||||
if (type == typeof(IntPtr))
|
||||
WritePtr(bw, (IntPtr)arg);
|
||||
else if (type == typeof(UIntPtr))
|
||||
{
|
||||
if (IntPtr.Size == 4)
|
||||
bw.Write(((UIntPtr)arg).ToUInt32());
|
||||
else
|
||||
bw.Write(((UIntPtr)arg).ToUInt64());
|
||||
}
|
||||
else if (!type.IsValueType)
|
||||
{
|
||||
var ohandle = GCHandle.Alloc(arg, GCHandleType.Pinned);
|
||||
handles.Add(ohandle);
|
||||
WritePtr(bw, ohandle.AddrOfPinnedObject());
|
||||
}
|
||||
else
|
||||
throw new NotSupportedException();
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
}
|
||||
buffer = ms.ToArray();
|
||||
}
|
||||
|
||||
handles[0] = GCHandle.Alloc(buffer, GCHandleType.Pinned);
|
||||
|
||||
void WritePad(BinaryWriter bw, int size)
|
||||
{
|
||||
var pad = IntPtr.Size - size;
|
||||
if (pad > 0)
|
||||
bw.Write(new byte[pad], 0, pad);
|
||||
}
|
||||
|
||||
void WritePtr(BinaryWriter bw, IntPtr p)
|
||||
{
|
||||
if (IntPtr.Size == 4)
|
||||
bw.Write(p.ToInt32());
|
||||
else
|
||||
bw.Write(p.ToInt64());
|
||||
}
|
||||
}*/
|
||||
|
||||
~VaList()
|
||||
{
|
||||
Dispose(false);
|
||||
}
|
||||
|
||||
public static implicit operator IntPtr(VaList vaList) => vaList.AddrOfPinnedObject();
|
||||
|
||||
public static implicit operator VaList(object[] args) => new VaList(args);
|
||||
|
||||
public IntPtr AddrOfPinnedObject()
|
||||
{
|
||||
if (handles.Count == 0)
|
||||
throw new ObjectDisposedException(GetType().Name);
|
||||
|
||||
return handles[0].AddrOfPinnedObject();
|
||||
}
|
||||
|
||||
void IDisposable.Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
}
|
||||
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
for (var i = 0; i < handles.Count; i++)
|
||||
if (handles[i].IsAllocated)
|
||||
handles[i].Free();
|
||||
|
||||
handles.Clear();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -67,16 +67,10 @@ CorrespondingAction, StringListPackMethod
|
|||
</PackageReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Remove="Collections\Hierarchy.cs" />
|
||||
<Compile Remove="Collections\Tree.cs" />
|
||||
<Compile Remove="Collections\VaList.cs" />
|
||||
<Compile Remove="InteropServices\SafeIDispatch.cs" />
|
||||
<Compile Remove="InteropServices\StructMarshaler.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="Collections\Hierarchy.cs" />
|
||||
<None Include="Collections\Tree.cs" />
|
||||
<None Include="Collections\VaList.cs" />
|
||||
<None Include="InteropServices\SafeIDispatch.cs" />
|
||||
<None Include="InteropServices\StructMarshaler.cs" />
|
||||
</ItemGroup>
|
||||
|
|
Loading…
Reference in New Issue