up
This commit is contained in:
8
Assets/BestHTTP/PlatformSupport/Collections.meta
Normal file
8
Assets/BestHTTP/PlatformSupport/Collections.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7b962f9775c4f4861a0847627e1b9094
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0340683ab418d46789fd29788f193fc6
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,263 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.ComponentModel;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections;
|
||||
|
||||
#if NETFX_CORE
|
||||
using specialized = System.Collections.Specialized;
|
||||
#else
|
||||
using specialized = PlatformSupport.Collections.Specialized;
|
||||
#endif
|
||||
|
||||
namespace PlatformSupport.Collections.ObjectModel
|
||||
{
|
||||
public class ObservableDictionary<TKey, TValue> : IDictionary<TKey, TValue>, specialized.INotifyCollectionChanged, INotifyPropertyChanged
|
||||
{
|
||||
private const string CountString = "Count";
|
||||
private const string IndexerName = "Item[]";
|
||||
private const string KeysName = "Keys";
|
||||
private const string ValuesName = "Values";
|
||||
|
||||
private IDictionary<TKey, TValue> _Dictionary;
|
||||
protected IDictionary<TKey, TValue> Dictionary
|
||||
{
|
||||
get { return _Dictionary; }
|
||||
}
|
||||
|
||||
#region Constructors
|
||||
public ObservableDictionary()
|
||||
{
|
||||
_Dictionary = new Dictionary<TKey, TValue>();
|
||||
}
|
||||
public ObservableDictionary(IDictionary<TKey, TValue> dictionary)
|
||||
{
|
||||
_Dictionary = new Dictionary<TKey, TValue>(dictionary);
|
||||
}
|
||||
public ObservableDictionary(IEqualityComparer<TKey> comparer)
|
||||
{
|
||||
_Dictionary = new Dictionary<TKey, TValue>(comparer);
|
||||
}
|
||||
public ObservableDictionary(int capacity)
|
||||
{
|
||||
_Dictionary = new Dictionary<TKey, TValue>(capacity);
|
||||
}
|
||||
public ObservableDictionary(IDictionary<TKey, TValue> dictionary, IEqualityComparer<TKey> comparer)
|
||||
{
|
||||
_Dictionary = new Dictionary<TKey, TValue>(dictionary, comparer);
|
||||
}
|
||||
public ObservableDictionary(int capacity, IEqualityComparer<TKey> comparer)
|
||||
{
|
||||
_Dictionary = new Dictionary<TKey, TValue>(capacity, comparer);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region IDictionary<TKey,TValue> Members
|
||||
|
||||
public void Add(TKey key, TValue value)
|
||||
{
|
||||
Insert(key, value, true);
|
||||
}
|
||||
|
||||
public bool ContainsKey(TKey key)
|
||||
{
|
||||
return Dictionary.ContainsKey(key);
|
||||
}
|
||||
|
||||
public ICollection<TKey> Keys
|
||||
{
|
||||
get { return Dictionary.Keys; }
|
||||
}
|
||||
|
||||
public bool Remove(TKey key)
|
||||
{
|
||||
if (key == null) throw new ArgumentNullException("key");
|
||||
|
||||
TValue value;
|
||||
Dictionary.TryGetValue(key, out value);
|
||||
var removed = Dictionary.Remove(key);
|
||||
if (removed)
|
||||
|
||||
//OnCollectionChanged(NotifyCollectionChangedAction.Remove, new KeyValuePair<TKey, TValue>(key, value));
|
||||
OnCollectionChanged();
|
||||
|
||||
|
||||
return removed;
|
||||
}
|
||||
|
||||
public bool TryGetValue(TKey key, out TValue value)
|
||||
{
|
||||
return Dictionary.TryGetValue(key, out value);
|
||||
}
|
||||
|
||||
public ICollection<TValue> Values
|
||||
{
|
||||
get { return Dictionary.Values; }
|
||||
}
|
||||
|
||||
public TValue this[TKey key]
|
||||
{
|
||||
get
|
||||
{
|
||||
return Dictionary[key];
|
||||
}
|
||||
set
|
||||
{
|
||||
Insert(key, value, false);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region ICollection<KeyValuePair<TKey,TValue>> Members
|
||||
|
||||
public void Add(KeyValuePair<TKey, TValue> item)
|
||||
{
|
||||
Insert(item.Key, item.Value, true);
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
if (Dictionary.Count > 0)
|
||||
{
|
||||
Dictionary.Clear();
|
||||
OnCollectionChanged();
|
||||
}
|
||||
}
|
||||
|
||||
public bool Contains(KeyValuePair<TKey, TValue> item)
|
||||
{
|
||||
return Dictionary.Contains(item);
|
||||
}
|
||||
|
||||
public void CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex)
|
||||
{
|
||||
Dictionary.CopyTo(array, arrayIndex);
|
||||
}
|
||||
|
||||
public int Count
|
||||
{
|
||||
get { return Dictionary.Count; }
|
||||
}
|
||||
|
||||
public bool IsReadOnly
|
||||
{
|
||||
get { return Dictionary.IsReadOnly; }
|
||||
}
|
||||
|
||||
public bool Remove(KeyValuePair<TKey, TValue> item)
|
||||
{
|
||||
return Remove(item.Key);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region IEnumerable<KeyValuePair<TKey,TValue>> Members
|
||||
|
||||
public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
|
||||
{
|
||||
return Dictionary.GetEnumerator();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region IEnumerable Members
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
{
|
||||
return ((IEnumerable)Dictionary).GetEnumerator();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region INotifyCollectionChanged Members
|
||||
|
||||
public event specialized.NotifyCollectionChangedEventHandler CollectionChanged;
|
||||
|
||||
#endregion
|
||||
|
||||
#region INotifyPropertyChanged Members
|
||||
|
||||
public event PropertyChangedEventHandler PropertyChanged;
|
||||
|
||||
#endregion
|
||||
|
||||
public void AddRange(IDictionary<TKey, TValue> items)
|
||||
{
|
||||
if (items == null) throw new ArgumentNullException("items");
|
||||
|
||||
if (items.Count > 0)
|
||||
{
|
||||
if (Dictionary.Count > 0)
|
||||
{
|
||||
if (items.Keys.Any((k) => Dictionary.ContainsKey(k)))
|
||||
throw new ArgumentException("An item with the same key has already been added.");
|
||||
else
|
||||
foreach (var item in items) Dictionary.Add(item);
|
||||
}
|
||||
else
|
||||
_Dictionary = new Dictionary<TKey, TValue>(items);
|
||||
|
||||
OnCollectionChanged(specialized.NotifyCollectionChangedAction.Add, items.ToArray());
|
||||
}
|
||||
}
|
||||
|
||||
private void Insert(TKey key, TValue value, bool add)
|
||||
{
|
||||
if (key == null) throw new ArgumentNullException("key");
|
||||
|
||||
TValue item;
|
||||
if (Dictionary.TryGetValue(key, out item))
|
||||
{
|
||||
if (add) throw new ArgumentException("An item with the same key has already been added.");
|
||||
if (Equals(item, value)) return;
|
||||
Dictionary[key] = value;
|
||||
|
||||
OnCollectionChanged(specialized.NotifyCollectionChangedAction.Replace, new KeyValuePair<TKey, TValue>(key, value), new KeyValuePair<TKey, TValue>(key, item));
|
||||
}
|
||||
else
|
||||
{
|
||||
Dictionary[key] = value;
|
||||
|
||||
OnCollectionChanged(specialized.NotifyCollectionChangedAction.Add, new KeyValuePair<TKey, TValue>(key, value));
|
||||
}
|
||||
}
|
||||
|
||||
private void OnPropertyChanged()
|
||||
{
|
||||
OnPropertyChanged(CountString);
|
||||
OnPropertyChanged(IndexerName);
|
||||
OnPropertyChanged(KeysName);
|
||||
OnPropertyChanged(ValuesName);
|
||||
}
|
||||
|
||||
protected virtual void OnPropertyChanged(string propertyName)
|
||||
{
|
||||
if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
|
||||
}
|
||||
|
||||
private void OnCollectionChanged()
|
||||
{
|
||||
OnPropertyChanged();
|
||||
if (CollectionChanged != null) CollectionChanged(this, new specialized.NotifyCollectionChangedEventArgs(specialized.NotifyCollectionChangedAction.Reset));
|
||||
}
|
||||
|
||||
private void OnCollectionChanged(specialized.NotifyCollectionChangedAction action, KeyValuePair<TKey, TValue> changedItem)
|
||||
{
|
||||
OnPropertyChanged();
|
||||
if (CollectionChanged != null) CollectionChanged(this, new specialized.NotifyCollectionChangedEventArgs(action, changedItem));
|
||||
}
|
||||
|
||||
private void OnCollectionChanged(specialized.NotifyCollectionChangedAction action, KeyValuePair<TKey, TValue> newItem, KeyValuePair<TKey, TValue> oldItem)
|
||||
{
|
||||
OnPropertyChanged();
|
||||
if (CollectionChanged != null) CollectionChanged(this, new specialized.NotifyCollectionChangedEventArgs(action, newItem, oldItem));
|
||||
}
|
||||
|
||||
private void OnCollectionChanged(specialized.NotifyCollectionChangedAction action, IList newItems)
|
||||
{
|
||||
OnPropertyChanged();
|
||||
if (CollectionChanged != null) CollectionChanged(this, new specialized.NotifyCollectionChangedEventArgs(action, newItems));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3de08bc9233e94e0f9864fcc8d05a1e3
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 58fbbb653fb8d40a5bb47d4c657a3d86
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,467 @@
|
||||
#if !NETFX_CORE
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace PlatformSupport.Collections.Specialized
|
||||
{
|
||||
public delegate void NotifyCollectionChangedEventHandler(object sender, PlatformSupport.Collections.Specialized.NotifyCollectionChangedEventArgs e);
|
||||
|
||||
public interface INotifyCollectionChanged
|
||||
{
|
||||
event NotifyCollectionChangedEventHandler CollectionChanged;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This enum describes the action that caused a CollectionChanged event.
|
||||
/// </summary>
|
||||
public enum NotifyCollectionChangedAction
|
||||
{
|
||||
/// <summary> One or more items were added to the collection. </summary>
|
||||
Add,
|
||||
/// <summary> One or more items were removed from the collection. </summary>
|
||||
Remove,
|
||||
/// <summary> One or more items were replaced in the collection. </summary>
|
||||
Replace,
|
||||
/// <summary> One or more items were moved within the collection. </summary>
|
||||
Move,
|
||||
/// <summary> The contents of the collection changed dramatically. </summary>
|
||||
Reset,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Arguments for the CollectionChanged event.
|
||||
/// A collection that supports INotifyCollectionChangedThis raises this event
|
||||
/// whenever an item is added or removed, or when the contents of the collection
|
||||
/// changes dramatically.
|
||||
/// </summary>
|
||||
public class NotifyCollectionChangedEventArgs : EventArgs
|
||||
{
|
||||
//------------------------------------------------------
|
||||
//
|
||||
// Constructors
|
||||
//
|
||||
//------------------------------------------------------
|
||||
|
||||
/// <summary>
|
||||
/// Construct a NotifyCollectionChangedEventArgs that describes a reset change.
|
||||
/// </summary>
|
||||
/// <param name="action">The action that caused the event (must be Reset).</param>
|
||||
public NotifyCollectionChangedEventArgs(PlatformSupport.Collections.Specialized.NotifyCollectionChangedAction action)
|
||||
{
|
||||
if (action != PlatformSupport.Collections.Specialized.NotifyCollectionChangedAction.Reset)
|
||||
throw new ArgumentException("action");
|
||||
|
||||
InitializeAdd(action, null, -1);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Construct a NotifyCollectionChangedEventArgs that describes a one-item change.
|
||||
/// </summary>
|
||||
/// <param name="action">The action that caused the event; can only be Reset, Add or Remove action.</param>
|
||||
/// <param name="changedItem">The item affected by the change.</param>
|
||||
public NotifyCollectionChangedEventArgs(PlatformSupport.Collections.Specialized.NotifyCollectionChangedAction action, object changedItem)
|
||||
{
|
||||
if ((action != PlatformSupport.Collections.Specialized.NotifyCollectionChangedAction.Add) && (action != PlatformSupport.Collections.Specialized.NotifyCollectionChangedAction.Remove)
|
||||
&& (action != PlatformSupport.Collections.Specialized.NotifyCollectionChangedAction.Reset))
|
||||
throw new ArgumentException("action");
|
||||
|
||||
if (action == PlatformSupport.Collections.Specialized.NotifyCollectionChangedAction.Reset)
|
||||
{
|
||||
if (changedItem != null)
|
||||
throw new ArgumentException("action");
|
||||
|
||||
InitializeAdd(action, null, -1);
|
||||
}
|
||||
else
|
||||
{
|
||||
InitializeAddOrRemove(action, new object[] { changedItem }, -1);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Construct a NotifyCollectionChangedEventArgs that describes a one-item change.
|
||||
/// </summary>
|
||||
/// <param name="action">The action that caused the event.</param>
|
||||
/// <param name="changedItem">The item affected by the change.</param>
|
||||
/// <param name="index">The index where the change occurred.</param>
|
||||
public NotifyCollectionChangedEventArgs(PlatformSupport.Collections.Specialized.NotifyCollectionChangedAction action, object changedItem, int index)
|
||||
{
|
||||
if ((action != PlatformSupport.Collections.Specialized.NotifyCollectionChangedAction.Add) && (action != PlatformSupport.Collections.Specialized.NotifyCollectionChangedAction.Remove)
|
||||
&& (action != PlatformSupport.Collections.Specialized.NotifyCollectionChangedAction.Reset))
|
||||
throw new ArgumentException("action");
|
||||
|
||||
if (action == PlatformSupport.Collections.Specialized.NotifyCollectionChangedAction.Reset)
|
||||
{
|
||||
if (changedItem != null)
|
||||
throw new ArgumentException("action");
|
||||
if (index != -1)
|
||||
throw new ArgumentException("action");
|
||||
|
||||
InitializeAdd(action, null, -1);
|
||||
}
|
||||
else
|
||||
{
|
||||
InitializeAddOrRemove(action, new object[] { changedItem }, index);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Construct a NotifyCollectionChangedEventArgs that describes a multi-item change.
|
||||
/// </summary>
|
||||
/// <param name="action">The action that caused the event.</param>
|
||||
/// <param name="changedItems">The items affected by the change.</param>
|
||||
public NotifyCollectionChangedEventArgs(PlatformSupport.Collections.Specialized.NotifyCollectionChangedAction action, IList changedItems)
|
||||
{
|
||||
if ((action != PlatformSupport.Collections.Specialized.NotifyCollectionChangedAction.Add) && (action != PlatformSupport.Collections.Specialized.NotifyCollectionChangedAction.Remove)
|
||||
&& (action != PlatformSupport.Collections.Specialized.NotifyCollectionChangedAction.Reset))
|
||||
throw new ArgumentException("action");
|
||||
|
||||
if (action == PlatformSupport.Collections.Specialized.NotifyCollectionChangedAction.Reset)
|
||||
{
|
||||
if (changedItems != null)
|
||||
throw new ArgumentException("action");
|
||||
|
||||
InitializeAdd(action, null, -1);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (changedItems == null)
|
||||
throw new ArgumentNullException("changedItems");
|
||||
|
||||
InitializeAddOrRemove(action, changedItems, -1);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Construct a NotifyCollectionChangedEventArgs that describes a multi-item change (or a reset).
|
||||
/// </summary>
|
||||
/// <param name="action">The action that caused the event.</param>
|
||||
/// <param name="changedItems">The items affected by the change.</param>
|
||||
/// <param name="startingIndex">The index where the change occurred.</param>
|
||||
public NotifyCollectionChangedEventArgs(PlatformSupport.Collections.Specialized.NotifyCollectionChangedAction action, IList changedItems, int startingIndex)
|
||||
{
|
||||
if ((action != PlatformSupport.Collections.Specialized.NotifyCollectionChangedAction.Add) && (action != PlatformSupport.Collections.Specialized.NotifyCollectionChangedAction.Remove)
|
||||
&& (action != PlatformSupport.Collections.Specialized.NotifyCollectionChangedAction.Reset))
|
||||
throw new ArgumentException("action");
|
||||
|
||||
if (action == PlatformSupport.Collections.Specialized.NotifyCollectionChangedAction.Reset)
|
||||
{
|
||||
if (changedItems != null)
|
||||
throw new ArgumentException("action");
|
||||
if (startingIndex != -1)
|
||||
throw new ArgumentException("action");
|
||||
|
||||
InitializeAdd(action, null, -1);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (changedItems == null)
|
||||
throw new ArgumentNullException("changedItems");
|
||||
if (startingIndex < -1)
|
||||
throw new ArgumentException("startingIndex");
|
||||
|
||||
InitializeAddOrRemove(action, changedItems, startingIndex);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Construct a NotifyCollectionChangedEventArgs that describes a one-item Replace event.
|
||||
/// </summary>
|
||||
/// <param name="action">Can only be a Replace action.</param>
|
||||
/// <param name="newItem">The new item replacing the original item.</param>
|
||||
/// <param name="oldItem">The original item that is replaced.</param>
|
||||
public NotifyCollectionChangedEventArgs(PlatformSupport.Collections.Specialized.NotifyCollectionChangedAction action, object newItem, object oldItem)
|
||||
{
|
||||
if (action != PlatformSupport.Collections.Specialized.NotifyCollectionChangedAction.Replace)
|
||||
throw new ArgumentException("action");
|
||||
|
||||
InitializeMoveOrReplace(action, new object[] { newItem }, new object[] { oldItem }, -1, -1);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Construct a NotifyCollectionChangedEventArgs that describes a one-item Replace event.
|
||||
/// </summary>
|
||||
/// <param name="action">Can only be a Replace action.</param>
|
||||
/// <param name="newItem">The new item replacing the original item.</param>
|
||||
/// <param name="oldItem">The original item that is replaced.</param>
|
||||
/// <param name="index">The index of the item being replaced.</param>
|
||||
public NotifyCollectionChangedEventArgs(PlatformSupport.Collections.Specialized.NotifyCollectionChangedAction action, object newItem, object oldItem, int index)
|
||||
{
|
||||
if (action != PlatformSupport.Collections.Specialized.NotifyCollectionChangedAction.Replace)
|
||||
throw new ArgumentException("action");
|
||||
|
||||
InitializeMoveOrReplace(action, new object[] { newItem }, new object[] { oldItem }, index, index);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Construct a NotifyCollectionChangedEventArgs that describes a multi-item Replace event.
|
||||
/// </summary>
|
||||
/// <param name="action">Can only be a Replace action.</param>
|
||||
/// <param name="newItems">The new items replacing the original items.</param>
|
||||
/// <param name="oldItems">The original items that are replaced.</param>
|
||||
public NotifyCollectionChangedEventArgs(PlatformSupport.Collections.Specialized.NotifyCollectionChangedAction action, IList newItems, IList oldItems)
|
||||
{
|
||||
if (action != PlatformSupport.Collections.Specialized.NotifyCollectionChangedAction.Replace)
|
||||
throw new ArgumentException("action");
|
||||
if (newItems == null)
|
||||
throw new ArgumentNullException("newItems");
|
||||
if (oldItems == null)
|
||||
throw new ArgumentNullException("oldItems");
|
||||
|
||||
InitializeMoveOrReplace(action, newItems, oldItems, -1, -1);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Construct a NotifyCollectionChangedEventArgs that describes a multi-item Replace event.
|
||||
/// </summary>
|
||||
/// <param name="action">Can only be a Replace action.</param>
|
||||
/// <param name="newItems">The new items replacing the original items.</param>
|
||||
/// <param name="oldItems">The original items that are replaced.</param>
|
||||
/// <param name="startingIndex">The starting index of the items being replaced.</param>
|
||||
public NotifyCollectionChangedEventArgs(PlatformSupport.Collections.Specialized.NotifyCollectionChangedAction action, IList newItems, IList oldItems, int startingIndex)
|
||||
{
|
||||
if (action != PlatformSupport.Collections.Specialized.NotifyCollectionChangedAction.Replace)
|
||||
throw new ArgumentException("action");
|
||||
if (newItems == null)
|
||||
throw new ArgumentNullException("newItems");
|
||||
if (oldItems == null)
|
||||
throw new ArgumentNullException("oldItems");
|
||||
|
||||
InitializeMoveOrReplace(action, newItems, oldItems, startingIndex, startingIndex);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Construct a NotifyCollectionChangedEventArgs that describes a one-item Move event.
|
||||
/// </summary>
|
||||
/// <param name="action">Can only be a Move action.</param>
|
||||
/// <param name="changedItem">The item affected by the change.</param>
|
||||
/// <param name="index">The new index for the changed item.</param>
|
||||
/// <param name="oldIndex">The old index for the changed item.</param>
|
||||
public NotifyCollectionChangedEventArgs(PlatformSupport.Collections.Specialized.NotifyCollectionChangedAction action, object changedItem, int index, int oldIndex)
|
||||
{
|
||||
if (action != PlatformSupport.Collections.Specialized.NotifyCollectionChangedAction.Move)
|
||||
throw new ArgumentException("action");
|
||||
if (index < 0)
|
||||
throw new ArgumentException("index");
|
||||
|
||||
object[] changedItems = new object[] { changedItem };
|
||||
InitializeMoveOrReplace(action, changedItems, changedItems, index, oldIndex);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Construct a NotifyCollectionChangedEventArgs that describes a multi-item Move event.
|
||||
/// </summary>
|
||||
/// <param name="action">The action that caused the event.</param>
|
||||
/// <param name="changedItems">The items affected by the change.</param>
|
||||
/// <param name="index">The new index for the changed items.</param>
|
||||
/// <param name="oldIndex">The old index for the changed items.</param>
|
||||
public NotifyCollectionChangedEventArgs(PlatformSupport.Collections.Specialized.NotifyCollectionChangedAction action, IList changedItems, int index, int oldIndex)
|
||||
{
|
||||
if (action != PlatformSupport.Collections.Specialized.NotifyCollectionChangedAction.Move)
|
||||
throw new ArgumentException("action");
|
||||
if (index < 0)
|
||||
throw new ArgumentException("index");
|
||||
|
||||
InitializeMoveOrReplace(action, changedItems, changedItems, index, oldIndex);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Construct a NotifyCollectionChangedEventArgs with given fields (no validation). Used by WinRT marshaling.
|
||||
/// </summary>
|
||||
internal NotifyCollectionChangedEventArgs(PlatformSupport.Collections.Specialized.NotifyCollectionChangedAction action, IList newItems, IList oldItems, int newIndex, int oldIndex)
|
||||
{
|
||||
_action = action;
|
||||
_newItems = (newItems == null) ? null : new ReadOnlyList(newItems);
|
||||
_oldItems = (oldItems == null) ? null : new ReadOnlyList(oldItems);
|
||||
_newStartingIndex = newIndex;
|
||||
_oldStartingIndex = oldIndex;
|
||||
}
|
||||
|
||||
private void InitializeAddOrRemove(PlatformSupport.Collections.Specialized.NotifyCollectionChangedAction action, IList changedItems, int startingIndex)
|
||||
{
|
||||
if (action == PlatformSupport.Collections.Specialized.NotifyCollectionChangedAction.Add)
|
||||
InitializeAdd(action, changedItems, startingIndex);
|
||||
else if (action == PlatformSupport.Collections.Specialized.NotifyCollectionChangedAction.Remove)
|
||||
InitializeRemove(action, changedItems, startingIndex);
|
||||
else
|
||||
Debug.Assert(false, String.Format("Unsupported action: {0}", action.ToString()));
|
||||
}
|
||||
|
||||
private void InitializeAdd(PlatformSupport.Collections.Specialized.NotifyCollectionChangedAction action, IList newItems, int newStartingIndex)
|
||||
{
|
||||
_action = action;
|
||||
_newItems = (newItems == null) ? null : new ReadOnlyList(newItems);
|
||||
_newStartingIndex = newStartingIndex;
|
||||
}
|
||||
|
||||
private void InitializeRemove(PlatformSupport.Collections.Specialized.NotifyCollectionChangedAction action, IList oldItems, int oldStartingIndex)
|
||||
{
|
||||
_action = action;
|
||||
_oldItems = (oldItems == null) ? null : new ReadOnlyList(oldItems);
|
||||
_oldStartingIndex = oldStartingIndex;
|
||||
}
|
||||
|
||||
private void InitializeMoveOrReplace(PlatformSupport.Collections.Specialized.NotifyCollectionChangedAction action, IList newItems, IList oldItems, int startingIndex, int oldStartingIndex)
|
||||
{
|
||||
InitializeAdd(action, newItems, startingIndex);
|
||||
InitializeRemove(action, oldItems, oldStartingIndex);
|
||||
}
|
||||
|
||||
//------------------------------------------------------
|
||||
//
|
||||
// Public Properties
|
||||
//
|
||||
//------------------------------------------------------
|
||||
|
||||
/// <summary>
|
||||
/// The action that caused the event.
|
||||
/// </summary>
|
||||
public PlatformSupport.Collections.Specialized.NotifyCollectionChangedAction Action
|
||||
{
|
||||
get { return _action; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The items affected by the change.
|
||||
/// </summary>
|
||||
public IList NewItems
|
||||
{
|
||||
get { return _newItems; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The old items affected by the change (for Replace events).
|
||||
/// </summary>
|
||||
public IList OldItems
|
||||
{
|
||||
get { return _oldItems; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The index where the change occurred.
|
||||
/// </summary>
|
||||
public int NewStartingIndex
|
||||
{
|
||||
get { return _newStartingIndex; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The old index where the change occurred (for Move events).
|
||||
/// </summary>
|
||||
public int OldStartingIndex
|
||||
{
|
||||
get { return _oldStartingIndex; }
|
||||
}
|
||||
|
||||
//------------------------------------------------------
|
||||
//
|
||||
// Private Fields
|
||||
//
|
||||
//------------------------------------------------------
|
||||
|
||||
private PlatformSupport.Collections.Specialized.NotifyCollectionChangedAction _action;
|
||||
private IList _newItems, _oldItems;
|
||||
private int _newStartingIndex = -1;
|
||||
private int _oldStartingIndex = -1;
|
||||
}
|
||||
|
||||
internal sealed class ReadOnlyList : IList
|
||||
{
|
||||
private readonly IList _list;
|
||||
|
||||
internal ReadOnlyList(IList list)
|
||||
{
|
||||
Debug.Assert(list != null);
|
||||
|
||||
_list = list;
|
||||
}
|
||||
|
||||
public int Count
|
||||
{
|
||||
get { return _list.Count; }
|
||||
}
|
||||
|
||||
public bool IsReadOnly
|
||||
{
|
||||
get { return true; }
|
||||
}
|
||||
|
||||
public bool IsFixedSize
|
||||
{
|
||||
get { return true; }
|
||||
}
|
||||
|
||||
public bool IsSynchronized
|
||||
{
|
||||
get { return _list.IsSynchronized; }
|
||||
}
|
||||
|
||||
public object this[int index]
|
||||
{
|
||||
get
|
||||
{
|
||||
return _list[index];
|
||||
}
|
||||
set
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
}
|
||||
|
||||
public object SyncRoot
|
||||
{
|
||||
get { return _list.SyncRoot; }
|
||||
}
|
||||
|
||||
public int Add(object value)
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
public bool Contains(object value)
|
||||
{
|
||||
return _list.Contains(value);
|
||||
}
|
||||
|
||||
public void CopyTo(Array array, int index)
|
||||
{
|
||||
_list.CopyTo(array, index);
|
||||
}
|
||||
|
||||
public IEnumerator GetEnumerator()
|
||||
{
|
||||
return _list.GetEnumerator();
|
||||
}
|
||||
|
||||
public int IndexOf(object value)
|
||||
{
|
||||
return _list.IndexOf(value);
|
||||
}
|
||||
|
||||
public void Insert(int index, object value)
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
public void Remove(object value)
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
public void RemoveAt(int index)
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6c341e6fb73ee42268f3d07f5ced3268
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
8
Assets/BestHTTP/PlatformSupport/Cryptography.meta
Normal file
8
Assets/BestHTTP/PlatformSupport/Cryptography.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 274463c8a30844a4589308a296202ac7
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,510 @@
|
||||
#if UNITY_WP8
|
||||
//
|
||||
// System.Security.Cryptography.MD5CryptoServiceProvider.cs
|
||||
//
|
||||
// Authors:
|
||||
// Matthew S. Ford (Matthew.S.Ford@Rose-Hulman.Edu)
|
||||
// Sebastien Pouliot (sebastien@ximian.com)
|
||||
//
|
||||
// Copyright 2001 by Matthew S. Ford.
|
||||
// Copyright (C) 2004-2005 Novell, Inc (http://www.novell.com)
|
||||
//
|
||||
// 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.Runtime.InteropServices;
|
||||
|
||||
namespace BestHTTP.PlatformSupport.Cryptography
|
||||
{
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Security.Cryptography;
|
||||
|
||||
[ComVisible(true)]
|
||||
public abstract class MD5 : HashAlgorithm
|
||||
{
|
||||
|
||||
// Why is it protected when others abstract hash classes are public ?
|
||||
protected MD5()
|
||||
{
|
||||
HashSizeValue = 128;
|
||||
}
|
||||
|
||||
public static new MD5 Create()
|
||||
{
|
||||
return new BestHTTP.PlatformSupport.Cryptography.MD5CryptoServiceProvider();
|
||||
}
|
||||
}
|
||||
|
||||
[ComVisible (true)]
|
||||
public sealed class MD5CryptoServiceProvider : MD5 {
|
||||
private const int BLOCK_SIZE_BYTES = 64;
|
||||
private uint[] _H;
|
||||
private uint[] buff;
|
||||
private ulong count;
|
||||
private byte[] _ProcessingBuffer; // Used to start data when passed less than a block worth.
|
||||
private int _ProcessingBufferCount; // Counts how much data we have stored that still needs processed.
|
||||
|
||||
public MD5CryptoServiceProvider ()
|
||||
{
|
||||
_H = new uint[4];
|
||||
buff = new uint[16];
|
||||
_ProcessingBuffer = new byte [BLOCK_SIZE_BYTES];
|
||||
|
||||
Initialize();
|
||||
}
|
||||
|
||||
~MD5CryptoServiceProvider ()
|
||||
{
|
||||
Dispose (false);
|
||||
}
|
||||
|
||||
protected override void Dispose (bool disposing)
|
||||
{
|
||||
if (_ProcessingBuffer != null) {
|
||||
Array.Clear (_ProcessingBuffer, 0, _ProcessingBuffer.Length);
|
||||
_ProcessingBuffer = null;
|
||||
}
|
||||
if (_H != null) {
|
||||
Array.Clear (_H, 0, _H.Length);
|
||||
_H = null;
|
||||
}
|
||||
if (buff != null) {
|
||||
Array.Clear (buff, 0, buff.Length);
|
||||
buff = null;
|
||||
}
|
||||
}
|
||||
|
||||
protected override void HashCore (byte[] rgb, int ibStart, int cbSize)
|
||||
{
|
||||
int i;
|
||||
State = 1;
|
||||
|
||||
if (_ProcessingBufferCount != 0) {
|
||||
if (cbSize < (BLOCK_SIZE_BYTES - _ProcessingBufferCount)) {
|
||||
System.Buffer.BlockCopy (rgb, ibStart, _ProcessingBuffer, _ProcessingBufferCount, cbSize);
|
||||
_ProcessingBufferCount += cbSize;
|
||||
return;
|
||||
}
|
||||
else {
|
||||
i = (BLOCK_SIZE_BYTES - _ProcessingBufferCount);
|
||||
System.Buffer.BlockCopy (rgb, ibStart, _ProcessingBuffer, _ProcessingBufferCount, i);
|
||||
ProcessBlock (_ProcessingBuffer, 0);
|
||||
_ProcessingBufferCount = 0;
|
||||
ibStart += i;
|
||||
cbSize -= i;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < cbSize - cbSize % BLOCK_SIZE_BYTES; i += BLOCK_SIZE_BYTES) {
|
||||
ProcessBlock (rgb, ibStart + i);
|
||||
}
|
||||
|
||||
if (cbSize % BLOCK_SIZE_BYTES != 0) {
|
||||
System.Buffer.BlockCopy (rgb, cbSize - cbSize % BLOCK_SIZE_BYTES + ibStart, _ProcessingBuffer, 0, cbSize % BLOCK_SIZE_BYTES);
|
||||
_ProcessingBufferCount = cbSize % BLOCK_SIZE_BYTES;
|
||||
}
|
||||
}
|
||||
|
||||
protected override byte[] HashFinal ()
|
||||
{
|
||||
byte[] hash = new byte[16];
|
||||
int i, j;
|
||||
|
||||
ProcessFinalBlock (_ProcessingBuffer, 0, _ProcessingBufferCount);
|
||||
|
||||
for (i=0; i<4; i++) {
|
||||
for (j=0; j<4; j++) {
|
||||
hash[i*4+j] = (byte)(_H[i] >> j*8);
|
||||
}
|
||||
}
|
||||
|
||||
return hash;
|
||||
}
|
||||
|
||||
public override void Initialize ()
|
||||
{
|
||||
count = 0;
|
||||
_ProcessingBufferCount = 0;
|
||||
|
||||
_H[0] = 0x67452301;
|
||||
_H[1] = 0xefcdab89;
|
||||
_H[2] = 0x98badcfe;
|
||||
_H[3] = 0x10325476;
|
||||
}
|
||||
|
||||
private void ProcessBlock (byte[] inputBuffer, int inputOffset)
|
||||
{
|
||||
uint a, b, c, d;
|
||||
int i;
|
||||
|
||||
count += BLOCK_SIZE_BYTES;
|
||||
|
||||
for (i=0; i<16; i++) {
|
||||
buff[i] = (uint)(inputBuffer[inputOffset+4*i])
|
||||
| (((uint)(inputBuffer[inputOffset+4*i+1])) << 8)
|
||||
| (((uint)(inputBuffer[inputOffset+4*i+2])) << 16)
|
||||
| (((uint)(inputBuffer[inputOffset+4*i+3])) << 24);
|
||||
}
|
||||
|
||||
a = _H[0];
|
||||
b = _H[1];
|
||||
c = _H[2];
|
||||
d = _H[3];
|
||||
|
||||
// This function was unrolled because it seems to be doubling our performance with current compiler/VM.
|
||||
// Possibly roll up if this changes.
|
||||
|
||||
// ---- Round 1 --------
|
||||
|
||||
a += (((c ^ d) & b) ^ d) + (uint) K [0] + buff [0];
|
||||
a = (a << 7) | (a >> 25);
|
||||
a += b;
|
||||
|
||||
d += (((b ^ c) & a) ^ c) + (uint) K [1] + buff [1];
|
||||
d = (d << 12) | (d >> 20);
|
||||
d += a;
|
||||
|
||||
c += (((a ^ b) & d) ^ b) + (uint) K [2] + buff [2];
|
||||
c = (c << 17) | (c >> 15);
|
||||
c += d;
|
||||
|
||||
b += (((d ^ a) & c) ^ a) + (uint) K [3] + buff [3];
|
||||
b = (b << 22) | (b >> 10);
|
||||
b += c;
|
||||
|
||||
a += (((c ^ d) & b) ^ d) + (uint) K [4] + buff [4];
|
||||
a = (a << 7) | (a >> 25);
|
||||
a += b;
|
||||
|
||||
d += (((b ^ c) & a) ^ c) + (uint) K [5] + buff [5];
|
||||
d = (d << 12) | (d >> 20);
|
||||
d += a;
|
||||
|
||||
c += (((a ^ b) & d) ^ b) + (uint) K [6] + buff [6];
|
||||
c = (c << 17) | (c >> 15);
|
||||
c += d;
|
||||
|
||||
b += (((d ^ a) & c) ^ a) + (uint) K [7] + buff [7];
|
||||
b = (b << 22) | (b >> 10);
|
||||
b += c;
|
||||
|
||||
a += (((c ^ d) & b) ^ d) + (uint) K [8] + buff [8];
|
||||
a = (a << 7) | (a >> 25);
|
||||
a += b;
|
||||
|
||||
d += (((b ^ c) & a) ^ c) + (uint) K [9] + buff [9];
|
||||
d = (d << 12) | (d >> 20);
|
||||
d += a;
|
||||
|
||||
c += (((a ^ b) & d) ^ b) + (uint) K [10] + buff [10];
|
||||
c = (c << 17) | (c >> 15);
|
||||
c += d;
|
||||
|
||||
b += (((d ^ a) & c) ^ a) + (uint) K [11] + buff [11];
|
||||
b = (b << 22) | (b >> 10);
|
||||
b += c;
|
||||
|
||||
a += (((c ^ d) & b) ^ d) + (uint) K [12] + buff [12];
|
||||
a = (a << 7) | (a >> 25);
|
||||
a += b;
|
||||
|
||||
d += (((b ^ c) & a) ^ c) + (uint) K [13] + buff [13];
|
||||
d = (d << 12) | (d >> 20);
|
||||
d += a;
|
||||
|
||||
c += (((a ^ b) & d) ^ b) + (uint) K [14] + buff [14];
|
||||
c = (c << 17) | (c >> 15);
|
||||
c += d;
|
||||
|
||||
b += (((d ^ a) & c) ^ a) + (uint) K [15] + buff [15];
|
||||
b = (b << 22) | (b >> 10);
|
||||
b += c;
|
||||
|
||||
|
||||
// ---- Round 2 --------
|
||||
|
||||
a += (((b ^ c) & d) ^ c) + (uint) K [16] + buff [1];
|
||||
a = (a << 5) | (a >> 27);
|
||||
a += b;
|
||||
|
||||
d += (((a ^ b) & c) ^ b) + (uint) K [17] + buff [6];
|
||||
d = (d << 9) | (d >> 23);
|
||||
d += a;
|
||||
|
||||
c += (((d ^ a) & b) ^ a) + (uint) K [18] + buff [11];
|
||||
c = (c << 14) | (c >> 18);
|
||||
c += d;
|
||||
|
||||
b += (((c ^ d) & a) ^ d) + (uint) K [19] + buff [0];
|
||||
b = (b << 20) | (b >> 12);
|
||||
b += c;
|
||||
|
||||
a += (((b ^ c) & d) ^ c) + (uint) K [20] + buff [5];
|
||||
a = (a << 5) | (a >> 27);
|
||||
a += b;
|
||||
|
||||
d += (((a ^ b) & c) ^ b) + (uint) K [21] + buff [10];
|
||||
d = (d << 9) | (d >> 23);
|
||||
d += a;
|
||||
|
||||
c += (((d ^ a) & b) ^ a) + (uint) K [22] + buff [15];
|
||||
c = (c << 14) | (c >> 18);
|
||||
c += d;
|
||||
|
||||
b += (((c ^ d) & a) ^ d) + (uint) K [23] + buff [4];
|
||||
b = (b << 20) | (b >> 12);
|
||||
b += c;
|
||||
|
||||
a += (((b ^ c) & d) ^ c) + (uint) K [24] + buff [9];
|
||||
a = (a << 5) | (a >> 27);
|
||||
a += b;
|
||||
|
||||
d += (((a ^ b) & c) ^ b) + (uint) K [25] + buff [14];
|
||||
d = (d << 9) | (d >> 23);
|
||||
d += a;
|
||||
|
||||
c += (((d ^ a) & b) ^ a) + (uint) K [26] + buff [3];
|
||||
c = (c << 14) | (c >> 18);
|
||||
c += d;
|
||||
|
||||
b += (((c ^ d) & a) ^ d) + (uint) K [27] + buff [8];
|
||||
b = (b << 20) | (b >> 12);
|
||||
b += c;
|
||||
|
||||
a += (((b ^ c) & d) ^ c) + (uint) K [28] + buff [13];
|
||||
a = (a << 5) | (a >> 27);
|
||||
a += b;
|
||||
|
||||
d += (((a ^ b) & c) ^ b) + (uint) K [29] + buff [2];
|
||||
d = (d << 9) | (d >> 23);
|
||||
d += a;
|
||||
|
||||
c += (((d ^ a) & b) ^ a) + (uint) K [30] + buff [7];
|
||||
c = (c << 14) | (c >> 18);
|
||||
c += d;
|
||||
|
||||
b += (((c ^ d) & a) ^ d) + (uint) K [31] + buff [12];
|
||||
b = (b << 20) | (b >> 12);
|
||||
b += c;
|
||||
|
||||
|
||||
// ---- Round 3 --------
|
||||
|
||||
a += (b ^ c ^ d) + (uint) K [32] + buff [5];
|
||||
a = (a << 4) | (a >> 28);
|
||||
a += b;
|
||||
|
||||
d += (a ^ b ^ c) + (uint) K [33] + buff [8];
|
||||
d = (d << 11) | (d >> 21);
|
||||
d += a;
|
||||
|
||||
c += (d ^ a ^ b) + (uint) K [34] + buff [11];
|
||||
c = (c << 16) | (c >> 16);
|
||||
c += d;
|
||||
|
||||
b += (c ^ d ^ a) + (uint) K [35] + buff [14];
|
||||
b = (b << 23) | (b >> 9);
|
||||
b += c;
|
||||
|
||||
a += (b ^ c ^ d) + (uint) K [36] + buff [1];
|
||||
a = (a << 4) | (a >> 28);
|
||||
a += b;
|
||||
|
||||
d += (a ^ b ^ c) + (uint) K [37] + buff [4];
|
||||
d = (d << 11) | (d >> 21);
|
||||
d += a;
|
||||
|
||||
c += (d ^ a ^ b) + (uint) K [38] + buff [7];
|
||||
c = (c << 16) | (c >> 16);
|
||||
c += d;
|
||||
|
||||
b += (c ^ d ^ a) + (uint) K [39] + buff [10];
|
||||
b = (b << 23) | (b >> 9);
|
||||
b += c;
|
||||
|
||||
a += (b ^ c ^ d) + (uint) K [40] + buff [13];
|
||||
a = (a << 4) | (a >> 28);
|
||||
a += b;
|
||||
|
||||
d += (a ^ b ^ c) + (uint) K [41] + buff [0];
|
||||
d = (d << 11) | (d >> 21);
|
||||
d += a;
|
||||
|
||||
c += (d ^ a ^ b) + (uint) K [42] + buff [3];
|
||||
c = (c << 16) | (c >> 16);
|
||||
c += d;
|
||||
|
||||
b += (c ^ d ^ a) + (uint) K [43] + buff [6];
|
||||
b = (b << 23) | (b >> 9);
|
||||
b += c;
|
||||
|
||||
a += (b ^ c ^ d) + (uint) K [44] + buff [9];
|
||||
a = (a << 4) | (a >> 28);
|
||||
a += b;
|
||||
|
||||
d += (a ^ b ^ c) + (uint) K [45] + buff [12];
|
||||
d = (d << 11) | (d >> 21);
|
||||
d += a;
|
||||
|
||||
c += (d ^ a ^ b) + (uint) K [46] + buff [15];
|
||||
c = (c << 16) | (c >> 16);
|
||||
c += d;
|
||||
|
||||
b += (c ^ d ^ a) + (uint) K [47] + buff [2];
|
||||
b = (b << 23) | (b >> 9);
|
||||
b += c;
|
||||
|
||||
|
||||
// ---- Round 4 --------
|
||||
|
||||
a += (((~d) | b) ^ c) + (uint) K [48] + buff [0];
|
||||
a = (a << 6) | (a >> 26);
|
||||
a += b;
|
||||
|
||||
d += (((~c) | a) ^ b) + (uint) K [49] + buff [7];
|
||||
d = (d << 10) | (d >> 22);
|
||||
d += a;
|
||||
|
||||
c += (((~b) | d) ^ a) + (uint) K [50] + buff [14];
|
||||
c = (c << 15) | (c >> 17);
|
||||
c += d;
|
||||
|
||||
b += (((~a) | c) ^ d) + (uint) K [51] + buff [5];
|
||||
b = (b << 21) | (b >> 11);
|
||||
b += c;
|
||||
|
||||
a += (((~d) | b) ^ c) + (uint) K [52] + buff [12];
|
||||
a = (a << 6) | (a >> 26);
|
||||
a += b;
|
||||
|
||||
d += (((~c) | a) ^ b) + (uint) K [53] + buff [3];
|
||||
d = (d << 10) | (d >> 22);
|
||||
d += a;
|
||||
|
||||
c += (((~b) | d) ^ a) + (uint) K [54] + buff [10];
|
||||
c = (c << 15) | (c >> 17);
|
||||
c += d;
|
||||
|
||||
b += (((~a) | c) ^ d) + (uint) K [55] + buff [1];
|
||||
b = (b << 21) | (b >> 11);
|
||||
b += c;
|
||||
|
||||
a += (((~d) | b) ^ c) + (uint) K [56] + buff [8];
|
||||
a = (a << 6) | (a >> 26);
|
||||
a += b;
|
||||
|
||||
d += (((~c) | a) ^ b) + (uint) K [57] + buff [15];
|
||||
d = (d << 10) | (d >> 22);
|
||||
d += a;
|
||||
|
||||
c += (((~b) | d) ^ a) + (uint) K [58] + buff [6];
|
||||
c = (c << 15) | (c >> 17);
|
||||
c += d;
|
||||
|
||||
b += (((~a) | c) ^ d) + (uint) K [59] + buff [13];
|
||||
b = (b << 21) | (b >> 11);
|
||||
b += c;
|
||||
|
||||
a += (((~d) | b) ^ c) + (uint) K [60] + buff [4];
|
||||
a = (a << 6) | (a >> 26);
|
||||
a += b;
|
||||
|
||||
d += (((~c) | a) ^ b) + (uint) K [61] + buff [11];
|
||||
d = (d << 10) | (d >> 22);
|
||||
d += a;
|
||||
|
||||
c += (((~b) | d) ^ a) + (uint) K [62] + buff [2];
|
||||
c = (c << 15) | (c >> 17);
|
||||
c += d;
|
||||
|
||||
b += (((~a) | c) ^ d) + (uint) K [63] + buff [9];
|
||||
b = (b << 21) | (b >> 11);
|
||||
b += c;
|
||||
|
||||
_H [0] += a;
|
||||
_H [1] += b;
|
||||
_H [2] += c;
|
||||
_H [3] += d;
|
||||
}
|
||||
|
||||
private void ProcessFinalBlock (byte[] inputBuffer, int inputOffset, int inputCount)
|
||||
{
|
||||
ulong total = count + (ulong)inputCount;
|
||||
int paddingSize = (int)(56 - total % BLOCK_SIZE_BYTES);
|
||||
|
||||
if (paddingSize < 1)
|
||||
paddingSize += BLOCK_SIZE_BYTES;
|
||||
|
||||
byte[] fooBuffer = new byte [inputCount+paddingSize+8];
|
||||
|
||||
for (int i=0; i<inputCount; i++) {
|
||||
fooBuffer[i] = inputBuffer[i+inputOffset];
|
||||
}
|
||||
|
||||
fooBuffer[inputCount] = 0x80;
|
||||
for (int i=inputCount+1; i<inputCount+paddingSize; i++) {
|
||||
fooBuffer[i] = 0x00;
|
||||
}
|
||||
|
||||
// I deal in bytes. The algorithm deals in bits.
|
||||
ulong size = total << 3;
|
||||
AddLength (size, fooBuffer, inputCount+paddingSize);
|
||||
ProcessBlock (fooBuffer, 0);
|
||||
|
||||
if (inputCount+paddingSize+8 == 128) {
|
||||
ProcessBlock(fooBuffer, 64);
|
||||
}
|
||||
}
|
||||
|
||||
internal void AddLength (ulong length, byte[] buffer, int position)
|
||||
{
|
||||
buffer [position++] = (byte)(length);
|
||||
buffer [position++] = (byte)(length >> 8);
|
||||
buffer [position++] = (byte)(length >> 16);
|
||||
buffer [position++] = (byte)(length >> 24);
|
||||
buffer [position++] = (byte)(length >> 32);
|
||||
buffer [position++] = (byte)(length >> 40);
|
||||
buffer [position++] = (byte)(length >> 48);
|
||||
buffer [position] = (byte)(length >> 56);
|
||||
}
|
||||
|
||||
private readonly static uint[] K = {
|
||||
0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee,
|
||||
0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501,
|
||||
0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be,
|
||||
0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821,
|
||||
0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa,
|
||||
0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8,
|
||||
0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed,
|
||||
0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a,
|
||||
0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c,
|
||||
0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70,
|
||||
0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05,
|
||||
0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665,
|
||||
0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039,
|
||||
0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1,
|
||||
0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1,
|
||||
0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f10cd7507547a42b1a8f7139ca71f337
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
8
Assets/BestHTTP/PlatformSupport/IO.meta
Normal file
8
Assets/BestHTTP/PlatformSupport/IO.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7212d9252683941a0b7ac946cb343ab6
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
270
Assets/BestHTTP/PlatformSupport/IO/Directory.cs
Normal file
270
Assets/BestHTTP/PlatformSupport/IO/Directory.cs
Normal file
@@ -0,0 +1,270 @@
|
||||
#if NETFX_CORE
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Windows.Storage;
|
||||
using Windows.Storage.Streams;
|
||||
using Windows.Foundation;
|
||||
|
||||
namespace BestHTTP.PlatformSupport.IO
|
||||
{
|
||||
public static class Directory
|
||||
{
|
||||
private static StorageFolder GetDirectoryForPath(string path)
|
||||
{
|
||||
IAsyncOperation<StorageFolder> folderFromPathAsync = StorageFolder.GetFolderFromPathAsync(path);
|
||||
WindowsRuntimeSystemExtensions.AsTask<StorageFolder>(folderFromPathAsync).Wait();
|
||||
return folderFromPathAsync.GetResults();
|
||||
}
|
||||
|
||||
public static DirectoryInfo CreateDirectory(string path)
|
||||
{
|
||||
if (path == null)
|
||||
throw new ArgumentNullException();
|
||||
if (string.IsNullOrWhiteSpace(path))
|
||||
throw new ArgumentNullException("Path is empty");
|
||||
StorageFolder folder = (StorageFolder)null;
|
||||
path = path.Replace('/', '\\');
|
||||
string path1 = path;
|
||||
Stack<string> stack = new Stack<string>();
|
||||
do
|
||||
{
|
||||
try
|
||||
{
|
||||
folder = Directory.GetDirectoryForPath(path1);
|
||||
break;
|
||||
}
|
||||
catch
|
||||
{
|
||||
int length = path1.LastIndexOf('\\');
|
||||
if (length < 0)
|
||||
{
|
||||
path1 = (string)null;
|
||||
}
|
||||
else
|
||||
{
|
||||
stack.Push(path1.Substring(length + 1));
|
||||
path1 = path1.Substring(0, length);
|
||||
}
|
||||
}
|
||||
}
|
||||
while (path1 != null);
|
||||
if (path1 == null)
|
||||
{
|
||||
System.Diagnostics.Debug.WriteLine("Directory.CreateDirectory: Could not find any part of the path: " + path);
|
||||
throw new IOException("Could not find any part of the path: " + path);
|
||||
}
|
||||
try
|
||||
{
|
||||
while (stack.Count > 0)
|
||||
{
|
||||
string desiredName = stack.Pop();
|
||||
if (string.IsNullOrWhiteSpace(desiredName) && stack.Count > 0)
|
||||
throw new ArgumentNullException("Empty directory name in the path");
|
||||
IAsyncOperation<StorageFolder> folderAsync = folder.CreateFolderAsync(desiredName);
|
||||
WindowsRuntimeSystemExtensions.AsTask<StorageFolder>(folderAsync).Wait();
|
||||
folder = folderAsync.GetResults();
|
||||
}
|
||||
return new DirectoryInfo(path, folder);
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
System.Diagnostics.Debug.WriteLine("Directory.CreateDirectory: " + ex.Message + "\n" + ex.StackTrace);
|
||||
throw;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
System.Diagnostics.Debug.WriteLine("Directory.CreateDirectory: " + ex.Message + "\n" + ex.StackTrace);
|
||||
throw new IOException(ex.Message, ex);
|
||||
}
|
||||
}
|
||||
|
||||
public static void Delete(string path)
|
||||
{
|
||||
Directory.Delete(path, false);
|
||||
}
|
||||
|
||||
public static void Delete(string path, bool recursive)
|
||||
{
|
||||
if (path == null)
|
||||
throw new ArgumentNullException();
|
||||
if (string.IsNullOrWhiteSpace(path))
|
||||
throw new ArgumentException("Path is empty");
|
||||
try
|
||||
{
|
||||
StorageFolder directoryForPath = Directory.GetDirectoryForPath(path);
|
||||
if (!recursive)
|
||||
{
|
||||
IAsyncOperation<IReadOnlyList<StorageFolder>> foldersAsync = directoryForPath.GetFoldersAsync();
|
||||
WindowsRuntimeSystemExtensions.AsTask<IReadOnlyList<StorageFolder>>(foldersAsync).Wait();
|
||||
if (Enumerable.Count<StorageFolder>((IEnumerable<StorageFolder>)foldersAsync.GetResults()) > 0)
|
||||
{
|
||||
System.Diagnostics.Debug.WriteLine("Directory.Delete: Directory not empty");
|
||||
throw new IOException("Directory not empty");
|
||||
}
|
||||
IAsyncOperation<IReadOnlyList<StorageFile>> filesAsync = directoryForPath.GetFilesAsync();
|
||||
WindowsRuntimeSystemExtensions.AsTask<IReadOnlyList<StorageFile>>(filesAsync).Wait();
|
||||
if (Enumerable.Count<StorageFile>((IEnumerable<StorageFile>)filesAsync.GetResults()) > 0)
|
||||
{
|
||||
System.Diagnostics.Debug.WriteLine("Directory.Delete: Directory not empty");
|
||||
throw new IOException("Directory not empty");
|
||||
}
|
||||
}
|
||||
WindowsRuntimeSystemExtensions.AsTask(directoryForPath.DeleteAsync()).Wait();
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
System.Diagnostics.Debug.WriteLine("Directory.Delete: " + ex.Message + "\n" + ex.StackTrace);
|
||||
throw;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
System.Diagnostics.Debug.WriteLine("Directory.Delete: " + ex.Message + "\n" + ex.StackTrace);
|
||||
throw new IOException(ex.Message, ex);
|
||||
}
|
||||
}
|
||||
|
||||
public static IEnumerable<string> EnumerateDirectories(string path)
|
||||
{
|
||||
if (path == null)
|
||||
throw new ArgumentNullException();
|
||||
if (string.IsNullOrWhiteSpace(path))
|
||||
throw new ArgumentException("Path is empty");
|
||||
try
|
||||
{
|
||||
IAsyncOperation<IReadOnlyList<StorageFolder>> foldersAsync = Directory.GetDirectoryForPath(path).GetFoldersAsync();
|
||||
WindowsRuntimeSystemExtensions.AsTask<IReadOnlyList<StorageFolder>>(foldersAsync).Wait();
|
||||
IReadOnlyList<StorageFolder> results = foldersAsync.GetResults();
|
||||
List<string> list = new List<string>(Enumerable.Count<StorageFolder>((IEnumerable<StorageFolder>)results));
|
||||
foreach (StorageFolder storageFolder in (IEnumerable<StorageFolder>)results)
|
||||
list.Add(storageFolder.Path);
|
||||
return (IEnumerable<string>)list;
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
System.Diagnostics.Debug.WriteLine("Directory.EnumerateDirectories: " + ex.Message + "\n" + ex.StackTrace);
|
||||
throw;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
System.Diagnostics.Debug.WriteLine("Directory.EnumerateDirectories: " + ex.Message + "\n" + ex.StackTrace);
|
||||
throw new IOException(ex.Message, ex);
|
||||
}
|
||||
}
|
||||
|
||||
public static IEnumerable<string> EnumerateFiles(string path)
|
||||
{
|
||||
if (path == null)
|
||||
throw new ArgumentNullException();
|
||||
if (string.IsNullOrWhiteSpace(path))
|
||||
throw new ArgumentException("Path is empty");
|
||||
try
|
||||
{
|
||||
IAsyncOperation<IReadOnlyList<StorageFile>> filesAsync = Directory.GetDirectoryForPath(path).GetFilesAsync();
|
||||
WindowsRuntimeSystemExtensions.AsTask<IReadOnlyList<StorageFile>>(filesAsync).Wait();
|
||||
IReadOnlyList<StorageFile> results = filesAsync.GetResults();
|
||||
List<string> list = new List<string>(Enumerable.Count<StorageFile>((IEnumerable<StorageFile>)results));
|
||||
foreach (StorageFile storageFile in (IEnumerable<StorageFile>)results)
|
||||
list.Add(storageFile.Path);
|
||||
return (IEnumerable<string>)list;
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
System.Diagnostics.Debug.WriteLine("Directory.EnumerateFiles: " + ex.Message + "\n" + ex.StackTrace);
|
||||
throw;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
System.Diagnostics.Debug.WriteLine("Directory.EnumerateFiles: " + ex.Message + "\n" + ex.StackTrace);
|
||||
throw new IOException(ex.Message, ex);
|
||||
}
|
||||
}
|
||||
|
||||
public static IEnumerable<string> EnumerateFileSystemEntries(string path)
|
||||
{
|
||||
if (path == null)
|
||||
throw new ArgumentNullException();
|
||||
if (string.IsNullOrWhiteSpace(path))
|
||||
throw new ArgumentException("Path is empty");
|
||||
try
|
||||
{
|
||||
List<string> list = (List<string>)Directory.EnumerateDirectories(path);
|
||||
list.AddRange(Directory.EnumerateFiles(path));
|
||||
return (IEnumerable<string>)list;
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
System.Diagnostics.Debug.WriteLine("Directory.EnumerateFileSystemEntries: " + ex.Message + "\n" + ex.StackTrace);
|
||||
throw;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
System.Diagnostics.Debug.WriteLine("Directory.EnumerateFileSystemEntries: " + ex.Message + "\n" + ex.StackTrace);
|
||||
throw new IOException(ex.Message, ex);
|
||||
}
|
||||
}
|
||||
|
||||
public static bool Exists(string path)
|
||||
{
|
||||
try
|
||||
{
|
||||
return Directory.GetDirectoryForPath(path) != null;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private static DateTimeOffset GetFolderCreationTime(string path)
|
||||
{
|
||||
if (path == null)
|
||||
throw new ArgumentNullException();
|
||||
if (string.IsNullOrWhiteSpace(path))
|
||||
throw new ArgumentException("Path is empty");
|
||||
try
|
||||
{
|
||||
return Directory.GetDirectoryForPath(path).DateCreated;
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
System.Diagnostics.Debug.WriteLine("Directory.GetFolderCreationTime: " + ex.Message + "\n" + ex.StackTrace);
|
||||
throw;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
System.Diagnostics.Debug.WriteLine("Directory.GetFolderCreationTime: " + ex.Message + "\n" + ex.StackTrace);
|
||||
throw new IOException(ex.Message, ex);
|
||||
}
|
||||
}
|
||||
|
||||
public static System.DateTime GetCreationTime(string path)
|
||||
{
|
||||
return Directory.GetFolderCreationTime(path).DateTime;
|
||||
}
|
||||
|
||||
public static System.DateTime GetCreationTimeUtc(string path)
|
||||
{
|
||||
return Directory.GetFolderCreationTime(path).ToUniversalTime().DateTime;
|
||||
}
|
||||
|
||||
public static string[] GetDirectories(string path)
|
||||
{
|
||||
return Enumerable.ToArray<string>(Directory.EnumerateDirectories(path));
|
||||
}
|
||||
|
||||
public static string[] GetFiles(string path)
|
||||
{
|
||||
return Enumerable.ToArray<string>(Directory.EnumerateFiles(path));
|
||||
}
|
||||
|
||||
public static string[] GetFileSystemEntries(string path)
|
||||
{
|
||||
return Enumerable.ToArray<string>(Directory.EnumerateFileSystemEntries(path));
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
11
Assets/BestHTTP/PlatformSupport/IO/Directory.cs.meta
Normal file
11
Assets/BestHTTP/PlatformSupport/IO/Directory.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 74f6f31c369d846db92707a1582237f2
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
491
Assets/BestHTTP/PlatformSupport/IO/File.cs
Normal file
491
Assets/BestHTTP/PlatformSupport/IO/File.cs
Normal file
@@ -0,0 +1,491 @@
|
||||
#if NETFX_CORE
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Windows.Storage;
|
||||
using Windows.Storage.Streams;
|
||||
using Windows.Foundation;
|
||||
|
||||
namespace BestHTTP.PlatformSupport.IO
|
||||
{
|
||||
public static class File
|
||||
{
|
||||
public static void AppendAllLines(string path, IEnumerable<string> contents)
|
||||
{
|
||||
File.AppendAllLines(path, contents, (Encoding)null);
|
||||
}
|
||||
|
||||
public static void AppendAllLines(string path, IEnumerable<string> contents, Encoding encoding)
|
||||
{
|
||||
try
|
||||
{
|
||||
IEnumerator<string> enumerator = contents.GetEnumerator();
|
||||
if (!enumerator.MoveNext())
|
||||
return;
|
||||
using (StreamWriter streamWriter = File.AppendText(path, encoding))
|
||||
{
|
||||
string current = enumerator.Current;
|
||||
while (enumerator.MoveNext())
|
||||
{
|
||||
streamWriter.WriteLine(current);
|
||||
current = enumerator.Current;
|
||||
}
|
||||
streamWriter.Write(current);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw File.GetRethrowException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
public static void AppendAllText(string path, string contents)
|
||||
{
|
||||
File.AppendAllText(path, contents, (Encoding)null);
|
||||
}
|
||||
|
||||
public static void AppendAllText(string path, string contents, Encoding encoding)
|
||||
{
|
||||
try
|
||||
{
|
||||
using (StreamWriter streamWriter = File.AppendText(path, encoding))
|
||||
streamWriter.Write(contents);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw File.GetRethrowException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
public static StreamWriter AppendText(string path, Encoding encoding)
|
||||
{
|
||||
try
|
||||
{
|
||||
IAsyncOperation<StorageFile> fileAsync = FileHelper.GetFolderForPathOrURI(path).CreateFileAsync(Path.GetFileName(path), CreationCollisionOption.OpenIfExists);
|
||||
WindowsRuntimeSystemExtensions.AsTask<StorageFile>(fileAsync).Wait();
|
||||
IAsyncOperation<IRandomAccessStream> source = fileAsync.GetResults().OpenAsync(FileAccessMode.ReadWrite);
|
||||
WindowsRuntimeSystemExtensions.AsTask<IRandomAccessStream>(source).Wait();
|
||||
FileRandomAccessStream randomAccessStream = (FileRandomAccessStream)source.GetResults();
|
||||
randomAccessStream.Seek(randomAccessStream.Size);
|
||||
return encoding == null ? new StreamWriter(WindowsRuntimeStreamExtensions.AsStream((IRandomAccessStream)randomAccessStream)) : new StreamWriter(WindowsRuntimeStreamExtensions.AsStream((IRandomAccessStream)randomAccessStream), encoding);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw File.GetRethrowException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
private static Exception GetRethrowException(Exception ex)
|
||||
{
|
||||
System.Diagnostics.Debug.WriteLine("File.GetRethrowException: " + ex.Message + "\n" + ex.StackTrace);
|
||||
if (ex.GetType() == typeof(IOException))
|
||||
return ex;
|
||||
else
|
||||
return (Exception)new IOException(ex.Message, ex);
|
||||
}
|
||||
|
||||
public static void Copy(string sourceFileName, string destFileName)
|
||||
{
|
||||
File.Copy(sourceFileName, destFileName, false);
|
||||
}
|
||||
|
||||
public static void Copy(string sourceFileName, string destFileName, bool overwrite)
|
||||
{
|
||||
try
|
||||
{
|
||||
StorageFile fileForPathOrUri = FileHelper.GetFileForPathOrURI(sourceFileName);
|
||||
if (overwrite)
|
||||
{
|
||||
StorageFile storageFile = (StorageFile)null;
|
||||
try
|
||||
{
|
||||
storageFile = FileHelper.GetFileForPathOrURI(destFileName);
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
if (storageFile != null)
|
||||
{
|
||||
WindowsRuntimeSystemExtensions.AsTask(fileForPathOrUri.CopyAndReplaceAsync((IStorageFile)storageFile)).Wait();
|
||||
return;
|
||||
}
|
||||
}
|
||||
WindowsRuntimeSystemExtensions.AsTask<StorageFile>(fileForPathOrUri.CopyAsync((IStorageFolder)FileHelper.GetFolderForPathOrURI(destFileName), Path.GetFileName(destFileName))).Wait();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw File.GetRethrowException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
public static FileStream Create(string path)
|
||||
{
|
||||
return new FileStream(path, FileMode.Create, FileAccess.ReadWrite);
|
||||
}
|
||||
|
||||
public static FileStream Create(string path, int bufferSize)
|
||||
{
|
||||
return new FileStream(path, FileMode.Create, FileAccess.ReadWrite, FileShare.None, bufferSize);
|
||||
}
|
||||
|
||||
public static StreamWriter CreateText(string path)
|
||||
{
|
||||
return new StreamWriter((Stream)File.Create(path));
|
||||
}
|
||||
|
||||
public static void Delete(string path)
|
||||
{
|
||||
if (path == null)
|
||||
throw new ArgumentNullException();
|
||||
if (path.Trim() == "")
|
||||
throw new ArgumentException();
|
||||
try
|
||||
{
|
||||
WindowsRuntimeSystemExtensions.AsTask(FileHelper.GetFileForPathOrURI(path).DeleteAsync()).Wait();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw File.GetRethrowException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
public static bool Exists(string path)
|
||||
{
|
||||
try
|
||||
{
|
||||
return FileHelper.GetFileForPathOrURI(path) != null;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static FileAttributes GetAttributes(string path)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(path))
|
||||
throw new ArgumentException();
|
||||
try
|
||||
{
|
||||
return File.WinAttributesToSysAttributes(FileHelper.GetFileForPathOrURI(path).Attributes);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new FileNotFoundException(ex.Message, ex);
|
||||
}
|
||||
}
|
||||
|
||||
internal static FileAttributes WinAttributesToSysAttributes(Windows.Storage.FileAttributes atts)
|
||||
{
|
||||
FileAttributes fileAttributes = (FileAttributes)0;
|
||||
if ((Windows.Storage.FileAttributes.ReadOnly & atts) != Windows.Storage.FileAttributes.Normal)
|
||||
fileAttributes |= FileAttributes.ReadOnly;
|
||||
if ((Windows.Storage.FileAttributes.Directory & atts) != Windows.Storage.FileAttributes.Normal)
|
||||
fileAttributes |= FileAttributes.Directory;
|
||||
if ((Windows.Storage.FileAttributes.Archive & atts) != Windows.Storage.FileAttributes.Normal)
|
||||
fileAttributes |= FileAttributes.Archive;
|
||||
if ((Windows.Storage.FileAttributes.Temporary & atts) != Windows.Storage.FileAttributes.Normal)
|
||||
fileAttributes |= FileAttributes.Temporary;
|
||||
if (fileAttributes == (FileAttributes)0)
|
||||
fileAttributes = FileAttributes.Normal;
|
||||
return fileAttributes;
|
||||
}
|
||||
|
||||
public static System.DateTime GetCreationTime(string path)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(path))
|
||||
throw new ArgumentException();
|
||||
try
|
||||
{
|
||||
return FileHelper.GetFileForPathOrURI(path).DateCreated.DateTime;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new FileNotFoundException(ex.Message, ex);
|
||||
}
|
||||
}
|
||||
|
||||
public static System.DateTime GetCreationTimeUtc(string path)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(path))
|
||||
throw new ArgumentException();
|
||||
try
|
||||
{
|
||||
return FileHelper.GetFileForPathOrURI(path).DateCreated.ToUniversalTime().DateTime;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new FileNotFoundException(ex.Message, ex);
|
||||
}
|
||||
}
|
||||
|
||||
public static void Move(string sourceFileName, string destFileName)
|
||||
{
|
||||
try
|
||||
{
|
||||
WindowsRuntimeSystemExtensions.AsTask(FileHelper.GetFileForPathOrURI(sourceFileName).MoveAsync((IStorageFolder)FileHelper.GetFolderForPathOrURI(destFileName), Path.GetFileName(destFileName))).Wait();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw File.GetRethrowException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
public static FileStream Open(string path, FileMode mode)
|
||||
{
|
||||
return new FileStream(path, mode);
|
||||
}
|
||||
|
||||
public static FileStream Open(string path, FileMode mode, FileAccess access)
|
||||
{
|
||||
return new FileStream(path, mode, access);
|
||||
}
|
||||
|
||||
public static FileStream Open(string path, FileMode mode, FileAccess access, FileShare share)
|
||||
{
|
||||
return new FileStream(path, mode, access, share);
|
||||
}
|
||||
|
||||
public static FileStream OpenRead(string path)
|
||||
{
|
||||
return File.Open(path, FileMode.Open, FileAccess.Read);
|
||||
}
|
||||
|
||||
public static StreamReader OpenText(string path)
|
||||
{
|
||||
return new StreamReader((Stream)File.OpenRead(path));
|
||||
}
|
||||
|
||||
public static FileStream OpenWrite(string path)
|
||||
{
|
||||
return File.Open(path, FileMode.Create, FileAccess.Write);
|
||||
}
|
||||
|
||||
public static byte[] ReadAllBytes(string path)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(path))
|
||||
throw new ArgumentException();
|
||||
try
|
||||
{
|
||||
return FileHelper.ReadEntireFile(FileHelper.GetFileForPathOrURI(path));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw File.GetRethrowException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
public static string[] ReadAllLines(string path)
|
||||
{
|
||||
return Enumerable.ToArray<string>(File.ReadLines(path));
|
||||
}
|
||||
|
||||
public static string[] ReadAllLines(string path, Encoding encoding)
|
||||
{
|
||||
return File.ReadAllLines(path);
|
||||
}
|
||||
|
||||
public static string ReadAllText(string path)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(path))
|
||||
throw new ArgumentException();
|
||||
try
|
||||
{
|
||||
IAsyncOperation<IRandomAccessStream> source = FileHelper.GetFileForPathOrURI(path).OpenAsync(FileAccessMode.Read);
|
||||
WindowsRuntimeSystemExtensions.AsTask<IRandomAccessStream>(source).Wait();
|
||||
using (FileRandomAccessStream randomAccessStream = (FileRandomAccessStream)source.GetResults())
|
||||
return new StreamReader(WindowsRuntimeStreamExtensions.AsStreamForRead((IInputStream)randomAccessStream)).ReadToEnd();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw File.GetRethrowException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
public static string ReadAllText(string path, Encoding encoding)
|
||||
{
|
||||
return File.ReadAllText(path);
|
||||
}
|
||||
|
||||
public static IEnumerable<string> ReadLines(string path)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(path))
|
||||
throw new ArgumentException();
|
||||
try
|
||||
{
|
||||
IAsyncOperation<IRandomAccessStream> source = FileHelper.GetFileForPathOrURI(path).OpenAsync(FileAccessMode.Read);
|
||||
WindowsRuntimeSystemExtensions.AsTask<IRandomAccessStream>(source).Wait();
|
||||
using (FileRandomAccessStream randomAccessStream = (FileRandomAccessStream)source.GetResults())
|
||||
{
|
||||
StreamReader streamReader = new StreamReader(WindowsRuntimeStreamExtensions.AsStreamForRead((IInputStream)randomAccessStream));
|
||||
List<string> list = new List<string>();
|
||||
while (true)
|
||||
{
|
||||
string str = streamReader.ReadLine();
|
||||
if (str != null)
|
||||
list.Add(str);
|
||||
else
|
||||
break;
|
||||
}
|
||||
return (IEnumerable<string>)list;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw File.GetRethrowException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
public static IEnumerable<string> ReadLines(string path, Encoding encoding)
|
||||
{
|
||||
return File.ReadLines(path);
|
||||
}
|
||||
|
||||
public static void Replace(string sourceFileName, string destinationFileName, string destinationBackupFileName)
|
||||
{
|
||||
if (destinationFileName == null)
|
||||
throw new ArgumentNullException();
|
||||
if (!string.IsNullOrWhiteSpace(sourceFileName) && !string.IsNullOrWhiteSpace(destinationFileName))
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(destinationBackupFileName))
|
||||
{
|
||||
try
|
||||
{
|
||||
StorageFile fileForPathOrUri1 = FileHelper.GetFileForPathOrURI(sourceFileName);
|
||||
string fileName1 = Path.GetFileName(destinationFileName);
|
||||
StorageFile fileForPathOrUri2;
|
||||
if (fileName1.ToLower() == destinationFileName.ToLower())
|
||||
{
|
||||
if (Path.GetFileName(sourceFileName).ToLower() == fileName1.ToLower())
|
||||
{
|
||||
System.Diagnostics.Debug.WriteLine("File.Replace: Source and destination is the same file");
|
||||
throw new IOException("Source and destination is the same file");
|
||||
}
|
||||
fileForPathOrUri2 = FileHelper.GetFileForPathOrURI(Path.Combine(Path.GetDirectoryName(fileForPathOrUri1.Path), fileName1));
|
||||
}
|
||||
else
|
||||
{
|
||||
fileForPathOrUri2 = FileHelper.GetFileForPathOrURI(destinationFileName);
|
||||
if (fileForPathOrUri1.Equals((object)fileForPathOrUri2))
|
||||
{
|
||||
System.Diagnostics.Debug.WriteLine("File.Replace: Source and destination is the same file");
|
||||
throw new IOException("Source and destination is the same file");
|
||||
}
|
||||
}
|
||||
string fileName2 = Path.GetFileName(destinationBackupFileName);
|
||||
if (fileName2.ToLower() == destinationBackupFileName.ToLower())
|
||||
{
|
||||
WindowsRuntimeSystemExtensions.AsTask(fileForPathOrUri2.RenameAsync(destinationBackupFileName)).Wait();
|
||||
}
|
||||
else
|
||||
{
|
||||
StorageFolder folderForPathOrUri = FileHelper.GetFolderForPathOrURI(destinationBackupFileName);
|
||||
WindowsRuntimeSystemExtensions.AsTask(fileForPathOrUri2.MoveAsync((IStorageFolder)folderForPathOrUri, fileName2)).Wait();
|
||||
}
|
||||
if (fileName1.ToLower() == destinationFileName.ToLower())
|
||||
{
|
||||
WindowsRuntimeSystemExtensions.AsTask(fileForPathOrUri1.RenameAsync(destinationFileName)).Wait();
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
StorageFolder folderForPathOrUri = FileHelper.GetFolderForPathOrURI(destinationFileName);
|
||||
WindowsRuntimeSystemExtensions.AsTask(fileForPathOrUri1.MoveAsync((IStorageFolder)folderForPathOrUri, fileName1)).Wait();
|
||||
return;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw File.GetRethrowException(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
throw new ArgumentException();
|
||||
}
|
||||
|
||||
public static void Replace(string sourceFileName, string destinationFileName, string destinationBackupFileName, bool ignoreMetadataErrors)
|
||||
{
|
||||
File.Replace(sourceFileName, destinationFileName, destinationBackupFileName);
|
||||
}
|
||||
|
||||
private static StorageFile CreateOrReplaceFile(string path)
|
||||
{
|
||||
IAsyncOperation<StorageFile> fileAsync = FileHelper.GetFolderForPathOrURI(path).CreateFileAsync(Path.GetFileName(path), CreationCollisionOption.ReplaceExisting);
|
||||
WindowsRuntimeSystemExtensions.AsTask<StorageFile>(fileAsync).Wait();
|
||||
return fileAsync.GetResults();
|
||||
}
|
||||
|
||||
public static void WriteAllBytes(string path, byte[] bytes)
|
||||
{
|
||||
if (path == null || bytes == null || bytes.Length == 0)
|
||||
throw new ArgumentNullException();
|
||||
if (string.IsNullOrWhiteSpace(path))
|
||||
throw new ArgumentException();
|
||||
try
|
||||
{
|
||||
WindowsRuntimeSystemExtensions.AsTask(FileIO.WriteBytesAsync((IStorageFile)File.CreateOrReplaceFile(path), bytes)).Wait();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw File.GetRethrowException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
public static void WriteAllLines(string path, IEnumerable<string> contents)
|
||||
{
|
||||
if (path == null || contents == null)
|
||||
throw new ArgumentNullException();
|
||||
if (string.IsNullOrWhiteSpace(path))
|
||||
throw new ArgumentException();
|
||||
try
|
||||
{
|
||||
WindowsRuntimeSystemExtensions.AsTask(FileIO.WriteLinesAsync((IStorageFile)File.CreateOrReplaceFile(path), contents)).Wait();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw File.GetRethrowException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
public static void WriteAllLines(string path, string[] contents)
|
||||
{
|
||||
IEnumerable<string> contents1 = (IEnumerable<string>)contents;
|
||||
File.WriteAllLines(path, contents1);
|
||||
}
|
||||
|
||||
public static void WriteAllLines(string path, IEnumerable<string> contents, Encoding encoding)
|
||||
{
|
||||
File.WriteAllLines(path, contents);
|
||||
}
|
||||
|
||||
public static void WriteAllLines(string path, string[] contents, Encoding encoding)
|
||||
{
|
||||
File.WriteAllLines(path, contents);
|
||||
}
|
||||
|
||||
public static void WriteAllText(string path, string contents)
|
||||
{
|
||||
if (path == null || string.IsNullOrEmpty(contents))
|
||||
throw new ArgumentNullException();
|
||||
if (string.IsNullOrWhiteSpace(path))
|
||||
throw new ArgumentException();
|
||||
try
|
||||
{
|
||||
WindowsRuntimeSystemExtensions.AsTask(FileIO.WriteTextAsync((IStorageFile)File.CreateOrReplaceFile(path), contents)).Wait();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw File.GetRethrowException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
public static void WriteAllText(string path, string contents, Encoding encoding)
|
||||
{
|
||||
File.WriteAllText(path, contents);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
11
Assets/BestHTTP/PlatformSupport/IO/File.cs.meta
Normal file
11
Assets/BestHTTP/PlatformSupport/IO/File.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 57d397f0564a244aaa7be36a21e9b300
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
69
Assets/BestHTTP/PlatformSupport/IO/FileEnums.cs
Normal file
69
Assets/BestHTTP/PlatformSupport/IO/FileEnums.cs
Normal file
@@ -0,0 +1,69 @@
|
||||
#if NETFX_CORE
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace BestHTTP.PlatformSupport.IO
|
||||
{
|
||||
[Flags]
|
||||
public enum FileAccess
|
||||
{
|
||||
Read = 1,
|
||||
Write = 2,
|
||||
ReadWrite = Write | Read,
|
||||
}
|
||||
|
||||
[Flags]
|
||||
public enum FileAttributes
|
||||
{
|
||||
Archive = 32,
|
||||
Compressed = 2048,
|
||||
Device = 64,
|
||||
Directory = 16,
|
||||
Encrypted = 16384,
|
||||
Hidden = 2,
|
||||
Normal = 128,
|
||||
NotContentIndexed = 8192,
|
||||
Offline = 4096,
|
||||
ReadOnly = 1,
|
||||
ReparsePoint = 1024,
|
||||
SparseFile = 512,
|
||||
System = 4,
|
||||
Temporary = 256,
|
||||
}
|
||||
|
||||
public enum FileMode
|
||||
{
|
||||
CreateNew = 1,
|
||||
Create = 2,
|
||||
Open = 3,
|
||||
OpenOrCreate = 4,
|
||||
Truncate = 5,
|
||||
Append = 6,
|
||||
}
|
||||
|
||||
[Flags]
|
||||
public enum FileOptions
|
||||
{
|
||||
None = 0,
|
||||
Encrypted = 16384,
|
||||
DeleteOnClose = 67108864,
|
||||
SequentialScan = 134217728,
|
||||
RandomAccess = 268435456,
|
||||
Asynchronous = 1073741824,
|
||||
WriteThrough = -2147483648,
|
||||
}
|
||||
|
||||
[Flags]
|
||||
public enum FileShare
|
||||
{
|
||||
None = 0,
|
||||
Read = 1,
|
||||
Write = 2,
|
||||
ReadWrite = Write | Read,
|
||||
Delete = 4,
|
||||
Inheritable = 16,
|
||||
}
|
||||
}
|
||||
#endif
|
||||
11
Assets/BestHTTP/PlatformSupport/IO/FileEnums.cs.meta
Normal file
11
Assets/BestHTTP/PlatformSupport/IO/FileEnums.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 37e07c62de7114e0698c1a747fd51442
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
140
Assets/BestHTTP/PlatformSupport/IO/FileHelper.cs
Normal file
140
Assets/BestHTTP/PlatformSupport/IO/FileHelper.cs
Normal file
@@ -0,0 +1,140 @@
|
||||
#if NETFX_CORE
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Windows.Storage;
|
||||
using Windows.Storage.Streams;
|
||||
using Windows.Foundation;
|
||||
|
||||
namespace BestHTTP.PlatformSupport.IO
|
||||
{
|
||||
public static class FileHelper
|
||||
{
|
||||
internal const string LOCAL_FOLDER = "ms-appdata:///local/";
|
||||
internal const string ROAMING_FOLDER = "ms-appdata:///roaming/";
|
||||
internal const string TEMP_FOLDER = "ms-appdata:///temp/";
|
||||
internal const string STORE_FOLDER = "isostore:/";
|
||||
|
||||
public static Stream OpenFileForReading(string uri)
|
||||
{
|
||||
return FileHelper.OpenFileForReading(FileHelper.GetFileForPathOrURI(uri));
|
||||
}
|
||||
|
||||
public static Stream OpenFileForReading(System.Uri uri)
|
||||
{
|
||||
Task<StorageFile> task = WindowsRuntimeSystemExtensions.AsTask<StorageFile>(StorageFile.GetFileFromApplicationUriAsync(uri));
|
||||
task.Wait();
|
||||
if (task.Status != TaskStatus.RanToCompletion)
|
||||
throw new Exception("Filed to open file " + uri.ToString());
|
||||
else
|
||||
return FileHelper.OpenFileForReading(task.Result);
|
||||
}
|
||||
|
||||
public static Stream OpenFileForWriting(string uri)
|
||||
{
|
||||
string fileName = Path.GetFileName(uri);
|
||||
Task<StorageFile> task1 = WindowsRuntimeSystemExtensions.AsTask<StorageFile>(FileHelper.GetFolderForPathOrURI(uri).CreateFileAsync(fileName, CreationCollisionOption.ReplaceExisting));
|
||||
task1.Wait();
|
||||
if (task1.Status != TaskStatus.RanToCompletion)
|
||||
throw new Exception("Failed to open the file");
|
||||
Task<IRandomAccessStream> task2 = WindowsRuntimeSystemExtensions.AsTask<IRandomAccessStream>(task1.Result.OpenAsync(FileAccessMode.ReadWrite));
|
||||
task2.Wait();
|
||||
if (task2.Status != TaskStatus.RanToCompletion)
|
||||
throw new Exception("Failed to open the file");
|
||||
else
|
||||
return WindowsRuntimeStreamExtensions.AsStreamForWrite((IOutputStream)task2.Result);
|
||||
}
|
||||
|
||||
internal static StorageFolder GetFolderForURI(string uri)
|
||||
{
|
||||
uri = uri.ToLower();
|
||||
StorageFolder storageFolder1;
|
||||
if (uri.StartsWith("ms-appdata:///local/"))
|
||||
{
|
||||
storageFolder1 = ApplicationData.Current.LocalFolder;
|
||||
uri = uri.Replace("ms-appdata:///local/", "");
|
||||
}
|
||||
else if (uri.StartsWith("ms-appdata:///roaming/"))
|
||||
{
|
||||
storageFolder1 = ApplicationData.Current.RoamingFolder;
|
||||
uri = uri.Replace("ms-appdata:///roaming/", "");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!uri.StartsWith("ms-appdata:///temp/"))
|
||||
throw new Exception("Unsupported URI: " + uri);
|
||||
storageFolder1 = ApplicationData.Current.TemporaryFolder;
|
||||
uri = uri.Replace("ms-appdata:///temp/", "");
|
||||
}
|
||||
string[] strArray = uri.Split(new char[1]
|
||||
{
|
||||
'/'
|
||||
});
|
||||
for (int index = 0; index < strArray.Length - 1; ++index)
|
||||
{
|
||||
Task<IReadOnlyList<StorageFolder>> task = WindowsRuntimeSystemExtensions.AsTask<IReadOnlyList<StorageFolder>>(storageFolder1.CreateFolderQuery().GetFoldersAsync());
|
||||
task.Wait();
|
||||
if (task.Status != TaskStatus.RanToCompletion)
|
||||
throw new Exception("Failed to find folder: " + strArray[index]);
|
||||
IReadOnlyList<StorageFolder> result = task.Result;
|
||||
bool flag = false;
|
||||
foreach (StorageFolder storageFolder2 in (IEnumerable<StorageFolder>)result)
|
||||
{
|
||||
if (storageFolder2.Name == strArray[index])
|
||||
{
|
||||
storageFolder1 = storageFolder2;
|
||||
flag = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!flag)
|
||||
throw new Exception("Folder not found: " + strArray[index]);
|
||||
}
|
||||
return storageFolder1;
|
||||
}
|
||||
|
||||
internal static StorageFolder GetFolderForPathOrURI(string path)
|
||||
{
|
||||
if (System.Uri.IsWellFormedUriString(path, UriKind.RelativeOrAbsolute))
|
||||
return FileHelper.GetFolderForURI(path);
|
||||
IAsyncOperation<StorageFolder> folderFromPathAsync = StorageFolder.GetFolderFromPathAsync(Path.GetDirectoryName(path));
|
||||
WindowsRuntimeSystemExtensions.AsTask<StorageFolder>(folderFromPathAsync).Wait();
|
||||
return folderFromPathAsync.GetResults();
|
||||
}
|
||||
|
||||
internal static StorageFile GetFileForPathOrURI(string path)
|
||||
{
|
||||
IAsyncOperation<StorageFile> source = !System.Uri.IsWellFormedUriString(path, UriKind.RelativeOrAbsolute) ? StorageFile.GetFileFromPathAsync(path) : StorageFile.GetFileFromApplicationUriAsync(new System.Uri(path));
|
||||
WindowsRuntimeSystemExtensions.AsTask<StorageFile>(source).Wait();
|
||||
return source.GetResults();
|
||||
}
|
||||
|
||||
internal static Stream OpenFileForReading(StorageFile file)
|
||||
{
|
||||
Task<IRandomAccessStream> task = WindowsRuntimeSystemExtensions.AsTask<IRandomAccessStream>(file.OpenAsync(FileAccessMode.Read));
|
||||
task.Wait();
|
||||
if (task.Status != TaskStatus.RanToCompletion)
|
||||
throw new Exception("Failed to open file!");
|
||||
else
|
||||
return WindowsRuntimeStreamExtensions.AsStreamForRead((IInputStream)task.Result);
|
||||
}
|
||||
|
||||
internal static byte[] ReadEntireFile(StorageFile file)
|
||||
{
|
||||
Task<IBuffer> task = WindowsRuntimeSystemExtensions.AsTask<IBuffer>(FileIO.ReadBufferAsync((IStorageFile)file));
|
||||
task.Wait();
|
||||
if (task.Status != TaskStatus.RanToCompletion)
|
||||
throw new Exception("Failed to read file");
|
||||
IBuffer result = task.Result;
|
||||
DataReader dataReader = DataReader.FromBuffer(result);
|
||||
byte[] numArray = new byte[result.Length];
|
||||
dataReader.ReadBytes(numArray);
|
||||
return numArray;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
11
Assets/BestHTTP/PlatformSupport/IO/FileHelper.cs.meta
Normal file
11
Assets/BestHTTP/PlatformSupport/IO/FileHelper.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8eba5212cad144a2ba80168674807963
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
338
Assets/BestHTTP/PlatformSupport/IO/FileStream.cs
Normal file
338
Assets/BestHTTP/PlatformSupport/IO/FileStream.cs
Normal file
@@ -0,0 +1,338 @@
|
||||
#if NETFX_CORE
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
using Windows.Storage;
|
||||
using Windows.Storage.Streams;
|
||||
using Windows.Foundation;
|
||||
|
||||
namespace BestHTTP.PlatformSupport.IO
|
||||
{
|
||||
public class FileStream : Stream
|
||||
{
|
||||
private int readTimeout = -1;
|
||||
private int writeTimeout = 1000;
|
||||
internal const int DefaultBufferSize = 8192;
|
||||
private FileRandomAccessStream backend;
|
||||
private FileOptions fileOptions;
|
||||
private string name;
|
||||
|
||||
public override bool CanRead { get { return this.backend.CanRead; } }
|
||||
public override bool CanSeek { get { return true; } }
|
||||
public override bool CanWrite { get { return this.backend.CanWrite; } }
|
||||
public virtual bool IsAsync { get { return (this.fileOptions & FileOptions.Asynchronous) > FileOptions.None; } }
|
||||
public override long Length { get { return (long)this.backend.Size; } }
|
||||
public override int ReadTimeout { get { return this.readTimeout; } set { this.readTimeout = value; } }
|
||||
public override int WriteTimeout { get { return this.writeTimeout; } set { this.writeTimeout = value; } }
|
||||
|
||||
public string Name { get { return this.name; } }
|
||||
|
||||
public override long Position
|
||||
{
|
||||
get { return (long)this.backend.Position; }
|
||||
set
|
||||
{
|
||||
try
|
||||
{
|
||||
this.backend.Seek((ulong)value);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw FileStream.RethrowException(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public FileStream(string file, FileMode mode)
|
||||
: this(file, mode, mode == FileMode.Append ? FileAccess.Write : FileAccess.ReadWrite, FileShare.Read, 8192, FileOptions.None)
|
||||
{
|
||||
}
|
||||
|
||||
public FileStream(string file, FileMode mode, FileAccess access)
|
||||
: this(file, mode, access, FileShare.Read, 8192, FileOptions.None)
|
||||
{
|
||||
}
|
||||
|
||||
public FileStream(string file, FileMode mode, FileAccess access, FileShare share)
|
||||
: this(file, mode, access, share, 8192, FileOptions.None)
|
||||
{
|
||||
}
|
||||
|
||||
public FileStream(string file, FileMode mode, FileAccess access, FileShare share, int bufferSize)
|
||||
: this(file, mode, access, share, bufferSize, FileOptions.None)
|
||||
{
|
||||
}
|
||||
|
||||
public FileStream(string file, FileMode mode, FileAccess access, FileShare share, int bufferSize, bool useAsync)
|
||||
: this(file, mode, access, share, bufferSize, useAsync ? FileOptions.Asynchronous : FileOptions.None)
|
||||
{
|
||||
}
|
||||
|
||||
public FileStream(string file, FileMode mode, FileAccess access, FileShare share, int bufferSize, FileOptions options)
|
||||
{
|
||||
try
|
||||
{
|
||||
this.fileOptions = options;
|
||||
this.name = file;
|
||||
this.CheckAccess(mode, access);
|
||||
StorageFile storageFile;
|
||||
switch (mode)
|
||||
{
|
||||
case FileMode.CreateNew:
|
||||
case FileMode.Create:
|
||||
case FileMode.OpenOrCreate:
|
||||
case FileMode.Append:
|
||||
storageFile = FileStream.CreateFile(file, mode, access);
|
||||
break;
|
||||
case FileMode.Open:
|
||||
case FileMode.Truncate:
|
||||
storageFile = FileStream.OpenFile(file, mode, access);
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentException("Unknown file mode");
|
||||
}
|
||||
IAsyncOperation<IRandomAccessStream> source = storageFile.OpenAsync(FileStream.GetAccessMode(access));
|
||||
WindowsRuntimeSystemExtensions.AsTask<IRandomAccessStream>(source).Wait();
|
||||
this.backend = (FileRandomAccessStream)source.GetResults();
|
||||
if (mode == FileMode.Truncate)
|
||||
{
|
||||
this.backend.Size = 0UL;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (mode != FileMode.Append)
|
||||
return;
|
||||
this.backend.Seek(this.backend.Size);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw FileStream.RethrowException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
private void CheckAccess(FileMode mode, FileAccess access)
|
||||
{
|
||||
switch (mode)
|
||||
{
|
||||
case FileMode.CreateNew:
|
||||
break;
|
||||
case FileMode.Create:
|
||||
break;
|
||||
case FileMode.Open:
|
||||
break;
|
||||
case FileMode.OpenOrCreate:
|
||||
break;
|
||||
case FileMode.Truncate:
|
||||
break;
|
||||
case FileMode.Append:
|
||||
if (access == FileAccess.Write)
|
||||
break;
|
||||
else
|
||||
{
|
||||
System.Diagnostics.Debug.WriteLine("FileStream.CheckAccess: Bad access mode for Append");
|
||||
throw new IOException("Bad access mode for Append");
|
||||
}
|
||||
default:
|
||||
throw new ArgumentException("Unknown file mode");
|
||||
}
|
||||
}
|
||||
|
||||
private static StorageFile OpenFile(string file, FileMode mode, FileAccess access)
|
||||
{
|
||||
return FileHelper.GetFileForPathOrURI(file);
|
||||
}
|
||||
|
||||
private static StorageFile CreateFile(string file, FileMode mode, FileAccess access)
|
||||
{
|
||||
IAsyncOperation<StorageFile> fileAsync = FileHelper.GetFolderForPathOrURI(file).CreateFileAsync(Path.GetFileName(file), FileStream.GetCollisionOption(mode, access));
|
||||
WindowsRuntimeSystemExtensions.AsTask<StorageFile>(fileAsync).Wait();
|
||||
if (fileAsync.Status != AsyncStatus.Completed)
|
||||
{
|
||||
System.Diagnostics.Debug.WriteLine("FileStream.CheckAccess: Failed to create file " + file);
|
||||
throw new IOException("Failed to create file " + file);
|
||||
}
|
||||
else
|
||||
return fileAsync.GetResults();
|
||||
}
|
||||
|
||||
public override void Flush()
|
||||
{
|
||||
try
|
||||
{
|
||||
WindowsRuntimeSystemExtensions.AsTask<bool>(this.backend.FlushAsync()).Wait();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw FileStream.RethrowException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
public void Flush(bool flushToDisc)
|
||||
{
|
||||
Flush();
|
||||
}
|
||||
|
||||
public override int Read(byte[] buffer, int offset, int count)
|
||||
{
|
||||
try
|
||||
{
|
||||
Windows.Storage.Streams.Buffer buffer1 = new Windows.Storage.Streams.Buffer((uint)count);
|
||||
WindowsRuntimeSystemExtensions.AsTask<IBuffer, uint>(this.backend.ReadAsync((IBuffer)buffer1, (uint)count, InputStreamOptions.ReadAhead)).Wait(this.readTimeout);
|
||||
int length = (int)buffer1.Length;
|
||||
DataReader dataReader = DataReader.FromBuffer((IBuffer)buffer1);
|
||||
bool flag = offset == 0 && buffer.Length == count && length == count;
|
||||
byte[] numArray = flag ? buffer : new byte[length];
|
||||
dataReader.ReadBytes(numArray);
|
||||
if (!flag)
|
||||
Array.Copy((Array)numArray, 0, (Array)buffer, offset, numArray.Length);
|
||||
return length;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw FileStream.RethrowException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
public override long Seek(long offset, SeekOrigin origin)
|
||||
{
|
||||
try
|
||||
{
|
||||
switch (origin)
|
||||
{
|
||||
case SeekOrigin.Begin:
|
||||
if (offset > (long)this.backend.Size)
|
||||
{
|
||||
offset = (long)this.backend.Size;
|
||||
break;
|
||||
}
|
||||
else
|
||||
break;
|
||||
case SeekOrigin.Current:
|
||||
if ((long)this.backend.Position + offset > (long)this.backend.Size)
|
||||
{
|
||||
offset = (long)this.backend.Position + offset;
|
||||
break;
|
||||
}
|
||||
else
|
||||
break;
|
||||
case SeekOrigin.End:
|
||||
if (offset >= 0L)
|
||||
{
|
||||
offset = (long)this.backend.Size;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
offset += (long)this.backend.Size;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (offset < 0L)
|
||||
offset = 0L;
|
||||
this.backend.Seek((ulong)offset);
|
||||
return offset;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw FileStream.RethrowException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
public override void SetLength(long value)
|
||||
{
|
||||
try
|
||||
{
|
||||
this.backend.Size = (ulong)value;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw FileStream.RethrowException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
public override void Write(byte[] buffer, int offset, int count)
|
||||
{
|
||||
try
|
||||
{
|
||||
Windows.Storage.Streams.Buffer buffer1 = new Windows.Storage.Streams.Buffer((uint)count);
|
||||
byte[] numArray;
|
||||
if (offset == 0 && count == buffer.Length)
|
||||
{
|
||||
numArray = buffer;
|
||||
}
|
||||
else
|
||||
{
|
||||
numArray = new byte[count];
|
||||
Array.Copy((Array)buffer, offset, (Array)numArray, 0, count);
|
||||
}
|
||||
DataWriter dataWriter = new DataWriter();
|
||||
dataWriter.WriteBytes(numArray);
|
||||
WindowsRuntimeSystemExtensions.AsTask<uint, uint>(this.backend.WriteAsync(dataWriter.DetachBuffer())).Wait(this.writeTimeout);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw FileStream.RethrowException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
base.Dispose(disposing);
|
||||
this.backend.Dispose();
|
||||
}
|
||||
|
||||
public void Close()
|
||||
{
|
||||
base.Dispose();
|
||||
}
|
||||
|
||||
private static Exception RethrowException(Exception e)
|
||||
{
|
||||
System.Diagnostics.Debug.WriteLine("FileStream.RethrowException: " + e.Message + "\n" + e.StackTrace);
|
||||
if (e.GetType() == typeof(IOException))
|
||||
return e;
|
||||
else
|
||||
return (Exception)new IOException(e.Message, e);
|
||||
}
|
||||
|
||||
private static CreationCollisionOption GetCollisionOption(FileMode mode, FileAccess access)
|
||||
{
|
||||
CreationCollisionOption creationCollisionOption = CreationCollisionOption.GenerateUniqueName;
|
||||
switch (mode)
|
||||
{
|
||||
case FileMode.CreateNew:
|
||||
creationCollisionOption = CreationCollisionOption.FailIfExists;
|
||||
break;
|
||||
case FileMode.Create:
|
||||
case FileMode.Truncate:
|
||||
creationCollisionOption = CreationCollisionOption.ReplaceExisting;
|
||||
break;
|
||||
case FileMode.Open:
|
||||
case FileMode.OpenOrCreate:
|
||||
case FileMode.Append:
|
||||
creationCollisionOption = CreationCollisionOption.OpenIfExists;
|
||||
break;
|
||||
}
|
||||
return creationCollisionOption;
|
||||
}
|
||||
|
||||
private static FileAccessMode GetAccessMode(FileAccess access)
|
||||
{
|
||||
switch (access)
|
||||
{
|
||||
case FileAccess.Read:
|
||||
return FileAccessMode.Read;
|
||||
default:
|
||||
return FileAccessMode.ReadWrite;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
11
Assets/BestHTTP/PlatformSupport/IO/FileStream.cs.meta
Normal file
11
Assets/BestHTTP/PlatformSupport/IO/FileStream.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b4119d4304fce48a89dfa6d57fb3d68a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
217
Assets/BestHTTP/PlatformSupport/IO/Infos.cs
Normal file
217
Assets/BestHTTP/PlatformSupport/IO/Infos.cs
Normal file
@@ -0,0 +1,217 @@
|
||||
#if NETFX_CORE
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Windows.Storage;
|
||||
using Windows.Storage.Streams;
|
||||
using Windows.Foundation;
|
||||
|
||||
namespace BestHTTP.PlatformSupport.IO
|
||||
{
|
||||
public abstract class FileSystemInfo
|
||||
{
|
||||
public FileAttributes Attributes
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.GetAttributes();
|
||||
}
|
||||
}
|
||||
|
||||
public DateTime CreationTime
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.GetCreationTime().DateTime;
|
||||
}
|
||||
}
|
||||
|
||||
public DateTime CreationTimeUtc
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.GetCreationTime().ToUniversalTime().DateTime;
|
||||
}
|
||||
}
|
||||
|
||||
public abstract bool Exists { get; }
|
||||
|
||||
public string Extention
|
||||
{
|
||||
get
|
||||
{
|
||||
return Path.GetExtension(this.FullName);
|
||||
}
|
||||
}
|
||||
|
||||
public abstract string FullName { get; }
|
||||
|
||||
public abstract string Name { get; }
|
||||
|
||||
internal abstract FileAttributes GetAttributes();
|
||||
|
||||
internal abstract DateTimeOffset GetCreationTime();
|
||||
|
||||
public abstract void Delete();
|
||||
|
||||
public void Refresh()
|
||||
{
|
||||
this.RefreshInternal();
|
||||
}
|
||||
|
||||
internal abstract void RefreshInternal();
|
||||
}
|
||||
|
||||
public sealed class DirectoryInfo : FileSystemInfo
|
||||
{
|
||||
private string path;
|
||||
private StorageFolder folder;
|
||||
|
||||
public override bool Exists
|
||||
{
|
||||
get
|
||||
{
|
||||
try
|
||||
{
|
||||
this.RefreshInternal();
|
||||
return true;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override string FullName
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.folder.Path;
|
||||
}
|
||||
}
|
||||
|
||||
public override string Name
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.folder.Name;
|
||||
}
|
||||
}
|
||||
|
||||
public DirectoryInfo(string path)
|
||||
{
|
||||
if (path == null)
|
||||
throw new ArgumentNullException();
|
||||
if (string.IsNullOrWhiteSpace(path))
|
||||
throw new ArgumentException();
|
||||
try
|
||||
{
|
||||
this.path = path;
|
||||
this.folder = FileHelper.GetFolderForPathOrURI(path);
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
System.Diagnostics.Debug.WriteLine("DirectoryInfo: " + ex.Message + "\n" + ex.StackTrace);
|
||||
throw;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
System.Diagnostics.Debug.WriteLine("DirectoryInfo: " + ex.Message + "\n" + ex.StackTrace);
|
||||
throw new IOException(ex.Message, ex);
|
||||
}
|
||||
}
|
||||
|
||||
internal DirectoryInfo(string path, StorageFolder folder)
|
||||
{
|
||||
this.path = path;
|
||||
this.folder = folder;
|
||||
}
|
||||
|
||||
internal override FileAttributes GetAttributes()
|
||||
{
|
||||
try
|
||||
{
|
||||
return File.WinAttributesToSysAttributes(this.folder.Attributes);
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
System.Diagnostics.Debug.WriteLine("DirectoryInfo.GetAttributes: " + ex.Message + "\n" + ex.StackTrace);
|
||||
throw;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
System.Diagnostics.Debug.WriteLine("DirectoryInfo.GetAttributes: " + ex.Message + "\n" + ex.StackTrace);
|
||||
throw new IOException(ex.Message, ex);
|
||||
}
|
||||
}
|
||||
|
||||
internal override DateTimeOffset GetCreationTime()
|
||||
{
|
||||
try
|
||||
{
|
||||
return this.folder.DateCreated;
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
System.Diagnostics.Debug.WriteLine("DirectoryInfo.GetCreationTime: " + ex.Message + "\n" + ex.StackTrace);
|
||||
throw;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
System.Diagnostics.Debug.WriteLine("DirectoryInfo.GetCreationTime: " + ex.Message + "\n" + ex.StackTrace);
|
||||
throw new IOException(ex.Message, ex);
|
||||
}
|
||||
}
|
||||
|
||||
public override void Delete()
|
||||
{
|
||||
try
|
||||
{
|
||||
WindowsRuntimeSystemExtensions.AsTask(this.folder.DeleteAsync()).Wait();
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
System.Diagnostics.Debug.WriteLine("DirectoryInfo.Delete: " + ex.Message + "\n" + ex.StackTrace);
|
||||
throw;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
System.Diagnostics.Debug.WriteLine("DirectoryInfo.Delete: " + ex.Message + "\n" + ex.StackTrace);
|
||||
throw new IOException(ex.Message, ex);
|
||||
}
|
||||
}
|
||||
|
||||
internal override void RefreshInternal()
|
||||
{
|
||||
try
|
||||
{
|
||||
this.folder = FileHelper.GetFolderForPathOrURI(this.path);
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
System.Diagnostics.Debug.WriteLine("DirectoryInfo.RefreshInternal: " + ex.Message + "\n" + ex.StackTrace);
|
||||
throw;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
System.Diagnostics.Debug.WriteLine("DirectoryInfo.RefreshInternal: " + ex.Message + "\n" + ex.StackTrace);
|
||||
throw new IOException(ex.Message, ex);
|
||||
}
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return this.path;
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return this.path.GetHashCode();
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
11
Assets/BestHTTP/PlatformSupport/IO/Infos.cs.meta
Normal file
11
Assets/BestHTTP/PlatformSupport/IO/Infos.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 68c9ba41295844c5ea47bc094fbed3e5
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
8
Assets/BestHTTP/PlatformSupport/TcpClient.meta
Normal file
8
Assets/BestHTTP/PlatformSupport/TcpClient.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 039d40848a0ce410a97dd190afc87f3a
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
609
Assets/BestHTTP/PlatformSupport/TcpClient/TcpClient.cs
Normal file
609
Assets/BestHTTP/PlatformSupport/TcpClient/TcpClient.cs
Normal file
@@ -0,0 +1,609 @@
|
||||
#if (!NETFX_CORE && !UNITY_WP8) || UNITY_EDITOR
|
||||
|
||||
// TcpClient.cs
|
||||
//
|
||||
// Author:
|
||||
// Phillip Pearson (pp@myelin.co.nz)
|
||||
// Gonzalo Paniagua Javier (gonzalo@novell.com)
|
||||
// Sridhar Kulkarni (sridharkulkarni@gmail.com)
|
||||
// Marek Safar (marek.safar@gmail.com)
|
||||
//
|
||||
// Copyright (C) 2001, Phillip Pearson http://www.myelin.co.nz
|
||||
// Copyright (c) 2006 Novell, Inc. (http://www.novell.com)
|
||||
// Copyright 2011 Xamarin Inc.
|
||||
//
|
||||
|
||||
//
|
||||
// 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.IO;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
|
||||
namespace BestHTTP.PlatformSupport.TcpClient.General
|
||||
{
|
||||
// This is a little modified TcpClient class from the Mono src tree.
|
||||
public class TcpClient : IDisposable
|
||||
{
|
||||
enum Properties : uint
|
||||
{
|
||||
LingerState = 1,
|
||||
NoDelay = 2,
|
||||
ReceiveBufferSize = 4,
|
||||
ReceiveTimeout = 8,
|
||||
SendBufferSize = 16,
|
||||
SendTimeout = 32
|
||||
}
|
||||
|
||||
// private data
|
||||
NetworkStream stream;
|
||||
bool active;
|
||||
Socket client;
|
||||
bool disposed;
|
||||
Properties values;
|
||||
int recv_timeout, send_timeout;
|
||||
int recv_buffer_size, send_buffer_size;
|
||||
LingerOption linger_state;
|
||||
bool no_delay;
|
||||
|
||||
private void Init(AddressFamily family)
|
||||
{
|
||||
active = false;
|
||||
|
||||
if (client != null)
|
||||
{
|
||||
client.Close();
|
||||
client = null;
|
||||
}
|
||||
|
||||
client = new Socket(family, SocketType.Stream, ProtocolType.Tcp);
|
||||
}
|
||||
|
||||
public TcpClient()
|
||||
{
|
||||
Init(AddressFamily.InterNetwork);
|
||||
client.Bind(new IPEndPoint(IPAddress.Any, 0));
|
||||
|
||||
ConnectTimeout = TimeSpan.FromSeconds(2);
|
||||
}
|
||||
|
||||
public TcpClient(AddressFamily family)
|
||||
{
|
||||
if (family != AddressFamily.InterNetwork &&
|
||||
family != AddressFamily.InterNetworkV6)
|
||||
{
|
||||
throw new ArgumentException("Family must be InterNetwork or InterNetworkV6", "family");
|
||||
}
|
||||
|
||||
Init(family);
|
||||
IPAddress any = IPAddress.Any;
|
||||
if (family == AddressFamily.InterNetworkV6)
|
||||
any = IPAddress.IPv6Any;
|
||||
client.Bind(new IPEndPoint(any, 0));
|
||||
|
||||
ConnectTimeout = TimeSpan.FromSeconds(2);
|
||||
}
|
||||
|
||||
public TcpClient(IPEndPoint localEP)
|
||||
{
|
||||
Init(localEP.AddressFamily);
|
||||
client.Bind(localEP);
|
||||
|
||||
ConnectTimeout = TimeSpan.FromSeconds(2);
|
||||
}
|
||||
|
||||
public TcpClient(string hostname, int port)
|
||||
{
|
||||
ConnectTimeout = TimeSpan.FromSeconds(2);
|
||||
|
||||
Connect(hostname, port);
|
||||
}
|
||||
|
||||
protected bool Active
|
||||
{
|
||||
get { return active; }
|
||||
set { active = value; }
|
||||
}
|
||||
|
||||
public Socket Client
|
||||
{
|
||||
get { return client; }
|
||||
set
|
||||
{
|
||||
client = value;
|
||||
stream = null;
|
||||
}
|
||||
}
|
||||
|
||||
public int Available
|
||||
{
|
||||
get { return client.Available; }
|
||||
}
|
||||
|
||||
public bool Connected
|
||||
{
|
||||
get { return client.Connected; }
|
||||
}
|
||||
|
||||
|
||||
public bool IsConnected()
|
||||
{
|
||||
try
|
||||
{
|
||||
return !(Client.Poll(1, SelectMode.SelectRead) && Client.Available == 0);
|
||||
}
|
||||
catch (Exception) { return false; }
|
||||
}
|
||||
|
||||
public bool ExclusiveAddressUse
|
||||
{
|
||||
get
|
||||
{
|
||||
return (client.ExclusiveAddressUse);
|
||||
}
|
||||
set
|
||||
{
|
||||
client.ExclusiveAddressUse = value;
|
||||
}
|
||||
}
|
||||
|
||||
internal void SetTcpClient(Socket s)
|
||||
{
|
||||
Client = s;
|
||||
}
|
||||
|
||||
public LingerOption LingerState
|
||||
{
|
||||
get
|
||||
{
|
||||
if ((values & Properties.LingerState) != 0)
|
||||
return linger_state;
|
||||
|
||||
return (LingerOption)client.GetSocketOption(SocketOptionLevel.Socket,
|
||||
SocketOptionName.Linger);
|
||||
}
|
||||
set
|
||||
{
|
||||
if (!client.Connected)
|
||||
{
|
||||
linger_state = value;
|
||||
values |= Properties.LingerState;
|
||||
return;
|
||||
}
|
||||
client.SetSocketOption(
|
||||
SocketOptionLevel.Socket,
|
||||
SocketOptionName.Linger, value);
|
||||
}
|
||||
}
|
||||
|
||||
public bool NoDelay
|
||||
{
|
||||
get
|
||||
{
|
||||
if ((values & Properties.NoDelay) != 0)
|
||||
return no_delay;
|
||||
|
||||
return (bool)client.GetSocketOption(
|
||||
SocketOptionLevel.Tcp,
|
||||
SocketOptionName.NoDelay);
|
||||
}
|
||||
set
|
||||
{
|
||||
if (!client.Connected)
|
||||
{
|
||||
no_delay = value;
|
||||
values |= Properties.NoDelay;
|
||||
return;
|
||||
}
|
||||
client.SetSocketOption(
|
||||
SocketOptionLevel.Tcp,
|
||||
SocketOptionName.NoDelay, value ? 1 : 0);
|
||||
}
|
||||
}
|
||||
|
||||
public int ReceiveBufferSize
|
||||
{
|
||||
get
|
||||
{
|
||||
if ((values & Properties.ReceiveBufferSize) != 0)
|
||||
return recv_buffer_size;
|
||||
|
||||
return (int)client.GetSocketOption(
|
||||
SocketOptionLevel.Socket,
|
||||
SocketOptionName.ReceiveBuffer);
|
||||
}
|
||||
set
|
||||
{
|
||||
if (!client.Connected)
|
||||
{
|
||||
recv_buffer_size = value;
|
||||
values |= Properties.ReceiveBufferSize;
|
||||
return;
|
||||
}
|
||||
client.SetSocketOption(
|
||||
SocketOptionLevel.Socket,
|
||||
SocketOptionName.ReceiveBuffer, value);
|
||||
}
|
||||
}
|
||||
|
||||
public int ReceiveTimeout
|
||||
{
|
||||
get
|
||||
{
|
||||
if ((values & Properties.ReceiveTimeout) != 0)
|
||||
return recv_timeout;
|
||||
|
||||
return (int)client.GetSocketOption(
|
||||
SocketOptionLevel.Socket,
|
||||
SocketOptionName.ReceiveTimeout);
|
||||
}
|
||||
set
|
||||
{
|
||||
if (!client.Connected)
|
||||
{
|
||||
recv_timeout = value;
|
||||
values |= Properties.ReceiveTimeout;
|
||||
return;
|
||||
}
|
||||
client.SetSocketOption(
|
||||
SocketOptionLevel.Socket,
|
||||
SocketOptionName.ReceiveTimeout, value);
|
||||
}
|
||||
}
|
||||
|
||||
public int SendBufferSize
|
||||
{
|
||||
get
|
||||
{
|
||||
if ((values & Properties.SendBufferSize) != 0)
|
||||
return send_buffer_size;
|
||||
|
||||
return (int)client.GetSocketOption(
|
||||
SocketOptionLevel.Socket,
|
||||
SocketOptionName.SendBuffer);
|
||||
}
|
||||
set
|
||||
{
|
||||
if (!client.Connected)
|
||||
{
|
||||
send_buffer_size = value;
|
||||
values |= Properties.SendBufferSize;
|
||||
return;
|
||||
}
|
||||
client.SetSocketOption(
|
||||
SocketOptionLevel.Socket,
|
||||
SocketOptionName.SendBuffer, value);
|
||||
}
|
||||
}
|
||||
|
||||
public int SendTimeout
|
||||
{
|
||||
get
|
||||
{
|
||||
if ((values & Properties.SendTimeout) != 0)
|
||||
return send_timeout;
|
||||
|
||||
return (int)client.GetSocketOption(
|
||||
SocketOptionLevel.Socket,
|
||||
SocketOptionName.SendTimeout);
|
||||
}
|
||||
set
|
||||
{
|
||||
if (!client.Connected)
|
||||
{
|
||||
send_timeout = value;
|
||||
values |= Properties.SendTimeout;
|
||||
return;
|
||||
}
|
||||
client.SetSocketOption(
|
||||
SocketOptionLevel.Socket,
|
||||
SocketOptionName.SendTimeout, value);
|
||||
}
|
||||
}
|
||||
|
||||
public TimeSpan ConnectTimeout { get; set; }
|
||||
|
||||
// methods
|
||||
|
||||
public void Close()
|
||||
{
|
||||
((IDisposable)this).Dispose();
|
||||
}
|
||||
|
||||
public void Connect(IPEndPoint remoteEP)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (ConnectTimeout > TimeSpan.Zero)
|
||||
{
|
||||
// Third version, works in WebPlayer
|
||||
System.Threading.ManualResetEvent mre = new System.Threading.ManualResetEvent(false);
|
||||
IAsyncResult result = client.BeginConnect(remoteEP, (res) => mre.Set(), null);
|
||||
active = mre.WaitOne(ConnectTimeout);
|
||||
if (active)
|
||||
client.EndConnect(result);
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
client.Close();
|
||||
}
|
||||
catch
|
||||
{ }
|
||||
|
||||
throw new TimeoutException("Connection timed out!");
|
||||
}
|
||||
|
||||
// Second version with timeout, in WebPlayer can't connect:
|
||||
// Attempt to access a private/protected method failed. at System.Security.SecurityManager.ThrowException (System.Exception ex) [0x00000] in <filename unknown>:0
|
||||
/*IAsyncResult result = client.BeginConnect(remoteEP, null, null);
|
||||
Active = result.AsyncWaitHandle.WaitOne(ConnectTimeout, true);
|
||||
if (active)
|
||||
{
|
||||
client.EndConnect(result);
|
||||
}
|
||||
else
|
||||
{
|
||||
client.Close();
|
||||
//throw new SocketException(10060);
|
||||
throw new TimeoutException("Connection timed out!");
|
||||
}*/
|
||||
}
|
||||
else
|
||||
{
|
||||
// First(old) version, no timeout
|
||||
client.Connect(remoteEP);
|
||||
active = true;
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
CheckDisposed();
|
||||
}
|
||||
}
|
||||
|
||||
public void Connect(IPAddress address, int port)
|
||||
{
|
||||
Connect(new IPEndPoint(address, port));
|
||||
}
|
||||
|
||||
void SetOptions()
|
||||
{
|
||||
Properties props = values;
|
||||
values = 0;
|
||||
|
||||
if ((props & Properties.LingerState) != 0)
|
||||
LingerState = linger_state;
|
||||
if ((props & Properties.NoDelay) != 0)
|
||||
NoDelay = no_delay;
|
||||
if ((props & Properties.ReceiveBufferSize) != 0)
|
||||
ReceiveBufferSize = recv_buffer_size;
|
||||
if ((props & Properties.ReceiveTimeout) != 0)
|
||||
ReceiveTimeout = recv_timeout;
|
||||
if ((props & Properties.SendBufferSize) != 0)
|
||||
SendBufferSize = send_buffer_size;
|
||||
if ((props & Properties.SendTimeout) != 0)
|
||||
SendTimeout = send_timeout;
|
||||
}
|
||||
|
||||
public void Connect(string hostname, int port)
|
||||
{
|
||||
IPAddress[] addresses = Dns.GetHostAddresses(hostname);
|
||||
Connect(addresses, port);
|
||||
}
|
||||
|
||||
public void Connect(IPAddress[] ipAddresses, int port)
|
||||
{
|
||||
CheckDisposed();
|
||||
|
||||
if (ipAddresses == null)
|
||||
{
|
||||
throw new ArgumentNullException("ipAddresses");
|
||||
}
|
||||
|
||||
for (int i = 0; i < ipAddresses.Length; i++)
|
||||
{
|
||||
try
|
||||
{
|
||||
IPAddress address = ipAddresses[i];
|
||||
|
||||
if (address.Equals(IPAddress.Any) ||
|
||||
address.Equals(IPAddress.IPv6Any))
|
||||
{
|
||||
throw new SocketException((int)SocketError.AddressNotAvailable);
|
||||
}
|
||||
|
||||
Init(address.AddressFamily);
|
||||
|
||||
if (address.AddressFamily == AddressFamily.InterNetwork)
|
||||
{
|
||||
client.Bind(new IPEndPoint(IPAddress.Any, 0));
|
||||
}
|
||||
else if (address.AddressFamily == AddressFamily.InterNetworkV6)
|
||||
{
|
||||
client.Bind(new IPEndPoint(IPAddress.IPv6Any, 0));
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new NotSupportedException("This method is only valid for sockets in the InterNetwork and InterNetworkV6 families");
|
||||
}
|
||||
|
||||
Connect(new IPEndPoint(address, port));
|
||||
|
||||
if (values != 0)
|
||||
{
|
||||
SetOptions();
|
||||
}
|
||||
|
||||
// Enable Keep-Alive packets
|
||||
client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.KeepAlive, true);
|
||||
|
||||
try
|
||||
{
|
||||
/*
|
||||
TCP_KEEPIDLE 4 // Start keeplives after this period
|
||||
TCP_KEEPINTVL 5 // Interval between keepalives
|
||||
TCP_KEEPCNT 6 // Number of keepalives before death
|
||||
*/
|
||||
|
||||
//client.SetSocketOption(SocketOptionLevel.Tcp, (SocketOptionName)4, 30);
|
||||
//client.SetSocketOption(SocketOptionLevel.Tcp, (SocketOptionName)5, 10);
|
||||
}
|
||||
catch { }
|
||||
|
||||
|
||||
#if UNITY_WINDOWS || UNITY_EDITOR
|
||||
// Set the keep-alive time and interval on windows
|
||||
|
||||
// https://msdn.microsoft.com/en-us/library/windows/desktop/dd877220%28v=vs.85%29.aspx
|
||||
// https://msdn.microsoft.com/en-us/library/windows/desktop/ee470551%28v=vs.85%29.aspx
|
||||
try
|
||||
{
|
||||
//SetKeepAlive(true, 30000, 1000);
|
||||
}
|
||||
catch{ }
|
||||
#endif
|
||||
|
||||
break;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
/* Reinitialise the socket so
|
||||
* other properties still work
|
||||
* (see no-arg constructor)
|
||||
*/
|
||||
Init(AddressFamily.InterNetwork);
|
||||
|
||||
/* This is the last known
|
||||
* address, so re-throw the
|
||||
* exception
|
||||
*/
|
||||
if (i == ipAddresses.Length - 1)
|
||||
{
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void EndConnect(IAsyncResult asyncResult)
|
||||
{
|
||||
client.EndConnect(asyncResult);
|
||||
}
|
||||
|
||||
public IAsyncResult BeginConnect(IPAddress address, int port, AsyncCallback requestCallback, object state)
|
||||
{
|
||||
return client.BeginConnect(address, port, requestCallback, state);
|
||||
}
|
||||
|
||||
public IAsyncResult BeginConnect(IPAddress[] addresses, int port, AsyncCallback requestCallback, object state)
|
||||
{
|
||||
return client.BeginConnect(addresses, port, requestCallback, state);
|
||||
}
|
||||
|
||||
public IAsyncResult BeginConnect(string host, int port, AsyncCallback requestCallback, object state)
|
||||
{
|
||||
return client.BeginConnect(host, port, requestCallback, state);
|
||||
}
|
||||
|
||||
void IDisposable.Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
if (disposed)
|
||||
return;
|
||||
disposed = true;
|
||||
|
||||
if (disposing)
|
||||
{
|
||||
// release managed resources
|
||||
NetworkStream s = stream;
|
||||
stream = null;
|
||||
if (s != null)
|
||||
{
|
||||
// This closes the socket as well, as the NetworkStream
|
||||
// owns the socket.
|
||||
s.Close();
|
||||
active = false;
|
||||
s = null;
|
||||
}
|
||||
else if (client != null)
|
||||
{
|
||||
client.Close();
|
||||
client = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
~TcpClient()
|
||||
{
|
||||
Dispose(false);
|
||||
}
|
||||
|
||||
public Stream GetStream()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (stream == null)
|
||||
stream = new NetworkStream(client, true);
|
||||
return stream;
|
||||
}
|
||||
finally { CheckDisposed(); }
|
||||
}
|
||||
|
||||
private void CheckDisposed()
|
||||
{
|
||||
if (disposed)
|
||||
throw new ObjectDisposedException(GetType().FullName);
|
||||
}
|
||||
|
||||
#if UNITY_WINDOWS || UNITY_EDITOR
|
||||
public void SetKeepAlive(bool on, uint keepAliveTime, uint keepAliveInterval)
|
||||
{
|
||||
int size = System.Runtime.InteropServices.Marshal.SizeOf(new uint());
|
||||
|
||||
var inOptionValues = new byte[size * 3];
|
||||
|
||||
BitConverter.GetBytes((uint)(on ? 1 : 0)).CopyTo(inOptionValues, 0);
|
||||
BitConverter.GetBytes((uint)keepAliveTime).CopyTo(inOptionValues, size);
|
||||
BitConverter.GetBytes((uint)keepAliveInterval).CopyTo(inOptionValues, size * 2);
|
||||
|
||||
//client.IOControl(IOControlCode.KeepAliveValues, inOptionValues, null);
|
||||
int dwBytesRet = 0;
|
||||
WSAIoctl(client.Handle, /*SIO_KEEPALIVE_VALS*/ System.Net.Sockets.IOControlCode.KeepAliveValues, inOptionValues, inOptionValues.Length, /*NULL*/IntPtr.Zero, 0, ref dwBytesRet, /*NULL*/IntPtr.Zero, /*NULL*/IntPtr.Zero);
|
||||
}
|
||||
|
||||
[System.Runtime.InteropServices.DllImport("Ws2_32.dll")]
|
||||
public static extern int WSAIoctl(
|
||||
/* Socket, Mode */ IntPtr s, System.Net.Sockets.IOControlCode dwIoControlCode,
|
||||
/* Optional Or IntPtr.Zero, 0 */ byte[] lpvInBuffer, int cbInBuffer,
|
||||
/* Optional Or IntPtr.Zero, 0 */ IntPtr lpvOutBuffer, int cbOutBuffer,
|
||||
/* reference to receive Size */ ref int lpcbBytesReturned,
|
||||
/* IntPtr.Zero, IntPtr.Zero */ IntPtr lpOverlapped, IntPtr lpCompletionRoutine);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
11
Assets/BestHTTP/PlatformSupport/TcpClient/TcpClient.cs.meta
Normal file
11
Assets/BestHTTP/PlatformSupport/TcpClient/TcpClient.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3ebe4d6e9f7ad40afab9cba5deffcb9a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
8
Assets/BestHTTP/PlatformSupport/TcpClient/WinRT.meta
Normal file
8
Assets/BestHTTP/PlatformSupport/TcpClient/WinRT.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3cefc2cb2b33a4a788457894e7fd4d7b
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,148 @@
|
||||
#if (UNITY_WSA || BUILD_FOR_WP8) && !UNITY_EDITOR && !ENABLE_IL2CPP
|
||||
|
||||
using System;
|
||||
|
||||
using Windows.Storage.Streams;
|
||||
|
||||
namespace BestHTTP.PlatformSupport.TcpClient.WinRT
|
||||
{
|
||||
public sealed class DataReaderWriterStream : System.IO.Stream
|
||||
{
|
||||
private TcpClient Client { get; set; }
|
||||
private DataReader Reader { get; set; }
|
||||
private DataWriter Writer { get; set; }
|
||||
|
||||
public DataReaderWriterStream(TcpClient socket)
|
||||
{
|
||||
this.Client = socket;
|
||||
this.Reader = new DataReader(Client.Socket.InputStream);
|
||||
this.Writer = new DataWriter(Client.Socket.OutputStream);
|
||||
}
|
||||
|
||||
#region Stream interface
|
||||
|
||||
public override bool CanRead
|
||||
{
|
||||
get { return true; }
|
||||
}
|
||||
|
||||
public override bool CanSeek
|
||||
{
|
||||
get { return false; }
|
||||
}
|
||||
|
||||
public override bool CanWrite
|
||||
{
|
||||
get { return true; }
|
||||
}
|
||||
|
||||
public override void Flush()
|
||||
{
|
||||
Writer.StoreAsync().AsTask().Wait();
|
||||
}
|
||||
|
||||
public override long Length
|
||||
{
|
||||
get { throw new NotImplementedException(); }
|
||||
}
|
||||
|
||||
public override long Position
|
||||
{
|
||||
get
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
set
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
||||
public bool DataAvailable
|
||||
{
|
||||
get
|
||||
{
|
||||
return Reader.UnconsumedBufferLength > 0;
|
||||
}
|
||||
}
|
||||
|
||||
public override int Read(byte[] buffer, int offset, int count)
|
||||
{
|
||||
Windows.Storage.Streams.Buffer tmpBuffer = new Windows.Storage.Streams.Buffer((uint)count);
|
||||
|
||||
try
|
||||
{
|
||||
var task = Client.Socket.InputStream.ReadAsync(tmpBuffer, (uint)count, InputStreamOptions.None);
|
||||
task.AsTask().Wait();
|
||||
}
|
||||
catch(AggregateException ex)
|
||||
{
|
||||
if (ex.InnerException != null)
|
||||
throw ex.InnerException;
|
||||
else
|
||||
throw ex;
|
||||
}
|
||||
|
||||
/*byte[] tmpBuff = tmpBuffer.ToArray();
|
||||
int length = Math.Min(tmpBuff.Length, count);
|
||||
|
||||
Array.Copy(tmpBuff, 0, buffer, offset, length);
|
||||
|
||||
return length;*/
|
||||
|
||||
DataReader buf = DataReader.FromBuffer(tmpBuffer);
|
||||
int length = (int)buf.UnconsumedBufferLength;
|
||||
for (int i = 0; i < length; ++i)
|
||||
buffer[offset + i] = buf.ReadByte();
|
||||
return length;
|
||||
}
|
||||
|
||||
public override void Write(byte[] buffer, int offset, int count)
|
||||
{
|
||||
for (int i = 0; i < count; ++i)
|
||||
Writer.WriteByte(buffer[offset + i]);
|
||||
}
|
||||
|
||||
public override long Seek(long offset, System.IO.SeekOrigin origin)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public override void SetLength(long value)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Dispose
|
||||
|
||||
private bool disposed = false;
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (!disposed)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
if (Reader != null)
|
||||
{
|
||||
Reader.Dispose();
|
||||
Reader = null;
|
||||
}
|
||||
|
||||
if (Writer != null)
|
||||
{
|
||||
Writer.Dispose();
|
||||
Writer = null;
|
||||
}
|
||||
}
|
||||
disposed = true;
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1b92cbaa1cac44ba8983949c6df04130
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
127
Assets/BestHTTP/PlatformSupport/TcpClient/WinRT/TcpClient.cs
Normal file
127
Assets/BestHTTP/PlatformSupport/TcpClient/WinRT/TcpClient.cs
Normal file
@@ -0,0 +1,127 @@
|
||||
#if (NETFX_CORE || BUILD_FOR_WP8) && !UNITY_EDITOR && !ENABLE_IL2CPP
|
||||
|
||||
using System;
|
||||
using Windows.Networking;
|
||||
using Windows.Networking.Sockets;
|
||||
|
||||
namespace BestHTTP.PlatformSupport.TcpClient.WinRT
|
||||
{
|
||||
public sealed class TcpClient : IDisposable
|
||||
{
|
||||
#region Public Properties
|
||||
|
||||
public bool Connected { get; private set; }
|
||||
public TimeSpan ConnectTimeout { get; set; }
|
||||
|
||||
public bool UseHTTPSProtocol { get; set; }
|
||||
|
||||
#endregion
|
||||
|
||||
#region Private Properties
|
||||
|
||||
internal StreamSocket Socket { get; set; }
|
||||
private System.IO.Stream Stream { get; set; }
|
||||
|
||||
#endregion
|
||||
|
||||
public TcpClient()
|
||||
{
|
||||
ConnectTimeout = TimeSpan.FromSeconds(2);
|
||||
}
|
||||
|
||||
public void Connect(string hostName, int port)
|
||||
{
|
||||
//How to secure socket connections with TLS/SSL:
|
||||
//http://msdn.microsoft.com/en-us/library/windows/apps/jj150597.aspx
|
||||
|
||||
//Networking in Windows 8 Apps - Using StreamSocket for TCP Communication
|
||||
//http://blogs.msdn.com/b/metulev/archive/2012/10/22/networking-in-windows-8-apps-using-streamsocket-for-tcp-communication.aspx
|
||||
|
||||
Socket = new StreamSocket();
|
||||
Socket.Control.KeepAlive = true;
|
||||
|
||||
var host = new HostName(hostName);
|
||||
|
||||
SocketProtectionLevel spl = SocketProtectionLevel.PlainSocket;
|
||||
if (UseHTTPSProtocol)
|
||||
spl = SocketProtectionLevel.
|
||||
#if UNITY_WSA_8_0 || BUILD_FOR_WP8
|
||||
Ssl;
|
||||
#else
|
||||
Tls12;
|
||||
#endif
|
||||
|
||||
// https://msdn.microsoft.com/en-us/library/windows/apps/xaml/jj710176.aspx#content
|
||||
try
|
||||
{
|
||||
var result = Socket.ConnectAsync(host, UseHTTPSProtocol ? "https" : port.ToString(), spl);
|
||||
|
||||
if (ConnectTimeout > TimeSpan.Zero)
|
||||
Connected = result.AsTask().Wait(ConnectTimeout);
|
||||
else
|
||||
Connected = result.AsTask().Wait(TimeSpan.FromMilliseconds(-1));
|
||||
}
|
||||
catch(AggregateException ex)
|
||||
{
|
||||
if (ex.InnerException != null)
|
||||
throw ex.InnerException;
|
||||
else
|
||||
throw ex;
|
||||
}
|
||||
|
||||
if (!Connected)
|
||||
throw new TimeoutException("Connection timed out!");
|
||||
}
|
||||
|
||||
public bool IsConnected()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public System.IO.Stream GetStream()
|
||||
{
|
||||
if (Stream == null)
|
||||
Stream = new DataReaderWriterStream(this);
|
||||
return Stream;
|
||||
}
|
||||
|
||||
public void Close()
|
||||
{
|
||||
Dispose();
|
||||
}
|
||||
|
||||
#region IDisposeble
|
||||
|
||||
private bool disposed = false;
|
||||
|
||||
private void Dispose(bool disposing)
|
||||
{
|
||||
if (!disposed)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
if (Stream != null)
|
||||
Stream.Dispose();
|
||||
Stream = null;
|
||||
Connected = false;
|
||||
}
|
||||
disposed = true;
|
||||
}
|
||||
}
|
||||
|
||||
~TcpClient()
|
||||
{
|
||||
Dispose(false);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: aa3c009b2f9c64da0877ac1b940c4b6c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user