mirror of
https://github.com/ICDSystems/ICD.Common.Utils.git
synced 2026-02-14 20:25:01 +00:00
feat: Splitting iterators from validation
This commit is contained in:
@@ -1,5 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
using ICD.Common.Properties;
|
using ICD.Common.Properties;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using Newtonsoft.Json.Linq;
|
using Newtonsoft.Json.Linq;
|
||||||
@@ -160,6 +161,7 @@ namespace ICD.Common.Utils.Extensions
|
|||||||
|
|
||||||
if (extends.TokenType == JsonToken.String)
|
if (extends.TokenType == JsonToken.String)
|
||||||
return EnumUtils.Parse<T>(extends.GetValueAsString(), true);
|
return EnumUtils.Parse<T>(extends.GetValueAsString(), true);
|
||||||
|
|
||||||
return (T)(object)extends.GetValueAsInt();
|
return (T)(object)extends.GetValueAsInt();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -252,17 +254,30 @@ namespace ICD.Common.Utils.Extensions
|
|||||||
throw new ArgumentNullException("read");
|
throw new ArgumentNullException("read");
|
||||||
|
|
||||||
if (reader.TokenType == JsonToken.Null)
|
if (reader.TokenType == JsonToken.Null)
|
||||||
yield break;
|
return Enumerable.Empty<TItem>();
|
||||||
|
|
||||||
if (reader.TokenType != JsonToken.StartArray)
|
if (reader.TokenType != JsonToken.StartArray)
|
||||||
throw new FormatException(string.Format("Expected token {0} got {1}", JsonToken.StartArray, reader.TokenType));
|
throw new FormatException(string.Format("Expected token {0} got {1}", JsonToken.StartArray, reader.TokenType));
|
||||||
|
|
||||||
|
return DeserializeArrayIterator(extends, reader, read);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Deserializes an array of items from the reader's current value.
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="TItem"></typeparam>
|
||||||
|
/// <param name="serializer"></param>
|
||||||
|
/// <param name="reader"></param>
|
||||||
|
/// <param name="read"></param>
|
||||||
|
private static IEnumerable<TItem> DeserializeArrayIterator<TItem>(JsonSerializer serializer, JsonReader reader,
|
||||||
|
Func<JsonSerializer, JsonReader, TItem> read)
|
||||||
|
{
|
||||||
// Step into the first value
|
// Step into the first value
|
||||||
reader.Read();
|
reader.Read();
|
||||||
|
|
||||||
while (reader.TokenType != JsonToken.EndArray)
|
while (reader.TokenType != JsonToken.EndArray)
|
||||||
{
|
{
|
||||||
TItem output = read(extends, reader);
|
TItem output = read(serializer, reader);
|
||||||
yield return output;
|
yield return output;
|
||||||
|
|
||||||
// Read out of the last value
|
// Read out of the last value
|
||||||
@@ -308,7 +323,8 @@ namespace ICD.Common.Utils.Extensions
|
|||||||
/// <typeparam name="TValue"></typeparam>
|
/// <typeparam name="TValue"></typeparam>
|
||||||
/// <param name="extends"></param>
|
/// <param name="extends"></param>
|
||||||
/// <param name="reader"></param>
|
/// <param name="reader"></param>
|
||||||
public static IEnumerable<KeyValuePair<TKey, TValue>> DeserializeDictionary<TKey, TValue>(this JsonSerializer extends, JsonReader reader)
|
public static IEnumerable<KeyValuePair<TKey, TValue>> DeserializeDictionary<TKey, TValue>(this JsonSerializer extends,
|
||||||
|
JsonReader reader)
|
||||||
{
|
{
|
||||||
if (extends == null)
|
if (extends == null)
|
||||||
throw new ArgumentNullException("extends");
|
throw new ArgumentNullException("extends");
|
||||||
@@ -317,11 +333,24 @@ namespace ICD.Common.Utils.Extensions
|
|||||||
throw new ArgumentNullException("reader");
|
throw new ArgumentNullException("reader");
|
||||||
|
|
||||||
if (reader.TokenType == JsonToken.Null)
|
if (reader.TokenType == JsonToken.Null)
|
||||||
yield break;
|
return Enumerable.Empty<KeyValuePair<TKey, TValue>>();
|
||||||
|
|
||||||
if (reader.TokenType != JsonToken.StartObject)
|
if (reader.TokenType != JsonToken.StartObject)
|
||||||
throw new FormatException(string.Format("Expected token {0} got {1}", JsonToken.StartObject, reader.TokenType));
|
throw new FormatException(string.Format("Expected token {0} got {1}", JsonToken.StartObject, reader.TokenType));
|
||||||
|
|
||||||
|
return DeserializeDictionaryIterator<TKey, TValue>(extends, reader);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Deserializes a dictionary of items from the reader's current value.
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="TKey"></typeparam>
|
||||||
|
/// <typeparam name="TValue"></typeparam>
|
||||||
|
/// <param name="serializer"></param>
|
||||||
|
/// <param name="reader"></param>
|
||||||
|
private static IEnumerable<KeyValuePair<TKey, TValue>> DeserializeDictionaryIterator<TKey, TValue>(
|
||||||
|
JsonSerializer serializer, JsonReader reader)
|
||||||
|
{
|
||||||
// Step into the first key
|
// Step into the first key
|
||||||
reader.Read();
|
reader.Read();
|
||||||
|
|
||||||
@@ -332,7 +361,7 @@ namespace ICD.Common.Utils.Extensions
|
|||||||
// Step into the value
|
// Step into the value
|
||||||
reader.Read();
|
reader.Read();
|
||||||
|
|
||||||
TValue value = extends.Deserialize<TValue>(reader);
|
TValue value = serializer.Deserialize<TValue>(reader);
|
||||||
|
|
||||||
yield return new KeyValuePair<TKey, TValue>(key, value);
|
yield return new KeyValuePair<TKey, TValue>(key, value);
|
||||||
|
|
||||||
|
|||||||
@@ -88,21 +88,34 @@ namespace ICD.Common.Utils.Extensions
|
|||||||
if (count < 1)
|
if (count < 1)
|
||||||
throw new ArgumentException("Value must be greater or equal to 1", "count");
|
throw new ArgumentException("Value must be greater or equal to 1", "count");
|
||||||
|
|
||||||
|
return SplitIterator(extends, delimeter, count);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Splits the string by the given delimiter, returning up to the given number of substrings.
|
||||||
|
/// E.g. "a:b:c".Split(':', 2) returns ["a", "b:c"]
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="value"></param>
|
||||||
|
/// <param name="delimeter"></param>
|
||||||
|
/// <param name="count"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
private static IEnumerable<string> SplitIterator(string value, char delimeter, int count)
|
||||||
|
{
|
||||||
if (count < 2)
|
if (count < 2)
|
||||||
{
|
{
|
||||||
yield return extends;
|
yield return value;
|
||||||
yield break;
|
yield break;
|
||||||
}
|
}
|
||||||
|
|
||||||
int index = extends.IndexOf(delimeter);
|
int index = value.IndexOf(delimeter);
|
||||||
if (index < 0)
|
if (index < 0)
|
||||||
{
|
{
|
||||||
yield return extends;
|
yield return value;
|
||||||
yield break;
|
yield break;
|
||||||
}
|
}
|
||||||
|
|
||||||
string first = extends.Substring(0, index);
|
string first = value.Substring(0, index);
|
||||||
string second = extends.Substring(index + 1);
|
string second = value.Substring(index + 1);
|
||||||
count--;
|
count--;
|
||||||
|
|
||||||
yield return first;
|
yield return first;
|
||||||
@@ -131,8 +144,6 @@ namespace ICD.Common.Utils.Extensions
|
|||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Splits a string by a given substring.
|
/// Splits a string by a given substring.
|
||||||
/// Taken from
|
|
||||||
/// https://social.msdn.microsoft.com/Forums/en-US/914a350f-e0e9-45e0-91a4-6b4b2168e780/string-split-function
|
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="extends"></param>
|
/// <param name="extends"></param>
|
||||||
/// <param name="delimeter"></param>
|
/// <param name="delimeter"></param>
|
||||||
@@ -146,19 +157,32 @@ namespace ICD.Common.Utils.Extensions
|
|||||||
if (delimeter == null)
|
if (delimeter == null)
|
||||||
throw new ArgumentNullException("delimeter");
|
throw new ArgumentNullException("delimeter");
|
||||||
|
|
||||||
|
return SplitIterator(extends, delimeter);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Splits a string by a given substring.
|
||||||
|
/// Taken from
|
||||||
|
/// https://social.msdn.microsoft.com/Forums/en-US/914a350f-e0e9-45e0-91a4-6b4b2168e780/string-split-function
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="value"></param>
|
||||||
|
/// <param name="delimeter"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
private static IEnumerable<string> SplitIterator(string value, string delimeter)
|
||||||
|
{
|
||||||
int dSum = 0;
|
int dSum = 0;
|
||||||
int sSum = 0;
|
int sSum = 0;
|
||||||
int length = extends.Length;
|
int length = value.Length;
|
||||||
int delimiterLength = delimeter.Length;
|
int delimiterLength = delimeter.Length;
|
||||||
|
|
||||||
if (delimiterLength == 0 || length == 0 || length < delimiterLength)
|
if (delimiterLength == 0 || length == 0 || length < delimiterLength)
|
||||||
{
|
{
|
||||||
yield return extends;
|
yield return value;
|
||||||
yield break;
|
yield break;
|
||||||
}
|
}
|
||||||
|
|
||||||
char[] cd = delimeter.ToCharArray();
|
char[] cd = delimeter.ToCharArray();
|
||||||
char[] cs = extends.ToCharArray();
|
char[] cs = value.ToCharArray();
|
||||||
|
|
||||||
for (int i = 0; i < delimiterLength; i++)
|
for (int i = 0; i < delimiterLength; i++)
|
||||||
{
|
{
|
||||||
@@ -169,22 +193,22 @@ namespace ICD.Common.Utils.Extensions
|
|||||||
int start = 0;
|
int start = 0;
|
||||||
for (int i = start; i < length - delimiterLength; i++)
|
for (int i = start; i < length - delimiterLength; i++)
|
||||||
{
|
{
|
||||||
if (i >= start && dSum == sSum && extends.Substring(i, delimiterLength) == delimeter)
|
if (i >= start && dSum == sSum && value.Substring(i, delimiterLength) == delimeter)
|
||||||
{
|
{
|
||||||
yield return extends.Substring(start, i - start);
|
yield return value.Substring(start, i - start);
|
||||||
start = i + delimiterLength;
|
start = i + delimiterLength;
|
||||||
}
|
}
|
||||||
|
|
||||||
sSum += cs[i + delimiterLength] - cs[i];
|
sSum += cs[i + delimiterLength] - cs[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dSum == sSum && extends.Substring(length - delimiterLength, delimiterLength) == delimeter)
|
if (dSum == sSum && value.Substring(length - delimiterLength, delimiterLength) == delimeter)
|
||||||
{
|
{
|
||||||
yield return extends.Substring(start, length - delimiterLength - start);
|
yield return value.Substring(start, length - delimiterLength - start);
|
||||||
yield return string.Empty;
|
yield return string.Empty;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
yield return extends.Substring(start, length - start);
|
yield return value.Substring(start, length - start);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -210,18 +210,15 @@ namespace ICD.Common.Utils.Extensions
|
|||||||
|
|
||||||
if (!s_TypeBaseTypes.ContainsKey(extends))
|
if (!s_TypeBaseTypes.ContainsKey(extends))
|
||||||
{
|
{
|
||||||
Type[] types = GetBaseTypesInternal(extends).ToArray();
|
Type[] types = GetBaseTypesIterator(extends).ToArray();
|
||||||
s_TypeBaseTypes.Add(extends, types);
|
s_TypeBaseTypes.Add(extends, types);
|
||||||
}
|
}
|
||||||
|
|
||||||
return s_TypeBaseTypes[extends];
|
return s_TypeBaseTypes[extends];
|
||||||
}
|
}
|
||||||
|
|
||||||
private static IEnumerable<Type> GetBaseTypesInternal(Type type)
|
private static IEnumerable<Type> GetBaseTypesIterator(Type type)
|
||||||
{
|
{
|
||||||
if (type == null)
|
|
||||||
throw new ArgumentNullException("type");
|
|
||||||
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
type = type
|
type = type
|
||||||
|
|||||||
@@ -172,18 +172,29 @@ namespace ICD.Common.Utils
|
|||||||
if (numbers == null)
|
if (numbers == null)
|
||||||
throw new ArgumentNullException("numbers");
|
throw new ArgumentNullException("numbers");
|
||||||
|
|
||||||
|
return GetRangesIterator(numbers);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Takes a sequence of numbers:
|
||||||
|
/// 1, 3, 5, 6, 7, 8, 9, 10, 12
|
||||||
|
/// And calculates the continuous ranges:
|
||||||
|
/// (1, 1), (3, 3), (5, 10), (12, 12)
|
||||||
|
/// </summary>
|
||||||
|
private static IEnumerable<int[]> GetRangesIterator(IEnumerable<int> numbers)
|
||||||
|
{
|
||||||
int[] currentRange = null;
|
int[] currentRange = null;
|
||||||
|
|
||||||
foreach (int number in numbers.Order())
|
foreach (int number in numbers.Order())
|
||||||
{
|
{
|
||||||
if (currentRange == null)
|
if (currentRange == null)
|
||||||
currentRange = new[] {number, number};
|
currentRange = new[] { number, number };
|
||||||
else if (currentRange[1] == number - 1)
|
else if (currentRange[1] == number - 1)
|
||||||
currentRange = new[] {currentRange[0], number};
|
currentRange = new[] { currentRange[0], number };
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
yield return currentRange;
|
yield return currentRange;
|
||||||
currentRange = new[] {number, number};
|
currentRange = new[] { number, number };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -71,6 +71,19 @@ namespace ICD.Common.Utils
|
|||||||
if (node == null)
|
if (node == null)
|
||||||
throw new ArgumentNullException("node");
|
throw new ArgumentNullException("node");
|
||||||
|
|
||||||
|
return GetCliqueIterator(map, visited, node);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the clique containing the node.
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T"></typeparam>
|
||||||
|
/// <param name="map"></param>
|
||||||
|
/// <param name="visited"></param>
|
||||||
|
/// <param name="node"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
private static IEnumerable<T> GetCliqueIterator<T>(IDictionary<T, IEnumerable<T>> map, IcdHashSet<T> visited, T node)
|
||||||
|
{
|
||||||
if (visited.Contains(node))
|
if (visited.Contains(node))
|
||||||
yield break;
|
yield break;
|
||||||
|
|
||||||
@@ -135,6 +148,18 @@ namespace ICD.Common.Utils
|
|||||||
if (getChildren == null)
|
if (getChildren == null)
|
||||||
throw new ArgumentNullException("getChildren");
|
throw new ArgumentNullException("getChildren");
|
||||||
|
|
||||||
|
return BreadthFirstSearchIterator(root, getChildren);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns all of the nodes in the tree via breadth-first search.
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T"></typeparam>
|
||||||
|
/// <param name="root"></param>
|
||||||
|
/// <param name="getChildren"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
private static IEnumerable<T> BreadthFirstSearchIterator<T>(T root, Func<T, IEnumerable<T>> getChildren)
|
||||||
|
{
|
||||||
Queue<T> process = new Queue<T>();
|
Queue<T> process = new Queue<T>();
|
||||||
process.Enqueue(root);
|
process.Enqueue(root);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user