diff --git a/ICD.Common.Utils/Extensions/JsonExtensions.cs b/ICD.Common.Utils/Extensions/JsonExtensions.cs index ac56fa2..0332c91 100644 --- a/ICD.Common.Utils/Extensions/JsonExtensions.cs +++ b/ICD.Common.Utils/Extensions/JsonExtensions.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Linq; using ICD.Common.Properties; using Newtonsoft.Json; using Newtonsoft.Json.Linq; @@ -160,6 +161,7 @@ namespace ICD.Common.Utils.Extensions if (extends.TokenType == JsonToken.String) return EnumUtils.Parse(extends.GetValueAsString(), true); + return (T)(object)extends.GetValueAsInt(); } @@ -252,17 +254,30 @@ namespace ICD.Common.Utils.Extensions throw new ArgumentNullException("read"); if (reader.TokenType == JsonToken.Null) - yield break; + return Enumerable.Empty(); if (reader.TokenType != JsonToken.StartArray) throw new FormatException(string.Format("Expected token {0} got {1}", JsonToken.StartArray, reader.TokenType)); + return DeserializeArrayIterator(extends, reader, read); + } + + /// + /// Deserializes an array of items from the reader's current value. + /// + /// + /// + /// + /// + private static IEnumerable DeserializeArrayIterator(JsonSerializer serializer, JsonReader reader, + Func read) + { // Step into the first value reader.Read(); while (reader.TokenType != JsonToken.EndArray) { - TItem output = read(extends, reader); + TItem output = read(serializer, reader); yield return output; // Read out of the last value @@ -308,7 +323,8 @@ namespace ICD.Common.Utils.Extensions /// /// /// - public static IEnumerable> DeserializeDictionary(this JsonSerializer extends, JsonReader reader) + public static IEnumerable> DeserializeDictionary(this JsonSerializer extends, + JsonReader reader) { if (extends == null) throw new ArgumentNullException("extends"); @@ -317,11 +333,24 @@ namespace ICD.Common.Utils.Extensions throw new ArgumentNullException("reader"); if (reader.TokenType == JsonToken.Null) - yield break; + return Enumerable.Empty>(); if (reader.TokenType != JsonToken.StartObject) throw new FormatException(string.Format("Expected token {0} got {1}", JsonToken.StartObject, reader.TokenType)); + return DeserializeDictionaryIterator(extends, reader); + } + + /// + /// Deserializes a dictionary of items from the reader's current value. + /// + /// + /// + /// + /// + private static IEnumerable> DeserializeDictionaryIterator( + JsonSerializer serializer, JsonReader reader) + { // Step into the first key reader.Read(); @@ -332,7 +361,7 @@ namespace ICD.Common.Utils.Extensions // Step into the value reader.Read(); - TValue value = extends.Deserialize(reader); + TValue value = serializer.Deserialize(reader); yield return new KeyValuePair(key, value); diff --git a/ICD.Common.Utils/Extensions/StringExtensions.cs b/ICD.Common.Utils/Extensions/StringExtensions.cs index 6708cef..219e42f 100644 --- a/ICD.Common.Utils/Extensions/StringExtensions.cs +++ b/ICD.Common.Utils/Extensions/StringExtensions.cs @@ -88,21 +88,34 @@ namespace ICD.Common.Utils.Extensions if (count < 1) throw new ArgumentException("Value must be greater or equal to 1", "count"); + return SplitIterator(extends, delimeter, count); + } + + /// + /// 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"] + /// + /// + /// + /// + /// + private static IEnumerable SplitIterator(string value, char delimeter, int count) + { if (count < 2) { - yield return extends; + yield return value; yield break; } - int index = extends.IndexOf(delimeter); + int index = value.IndexOf(delimeter); if (index < 0) { - yield return extends; + yield return value; yield break; } - string first = extends.Substring(0, index); - string second = extends.Substring(index + 1); + string first = value.Substring(0, index); + string second = value.Substring(index + 1); count--; yield return first; @@ -131,8 +144,6 @@ namespace ICD.Common.Utils.Extensions /// /// 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 /// /// /// @@ -146,19 +157,32 @@ namespace ICD.Common.Utils.Extensions if (delimeter == null) throw new ArgumentNullException("delimeter"); + return SplitIterator(extends, delimeter); + } + + /// + /// 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 + /// + /// + /// + /// + private static IEnumerable SplitIterator(string value, string delimeter) + { int dSum = 0; int sSum = 0; - int length = extends.Length; + int length = value.Length; int delimiterLength = delimeter.Length; if (delimiterLength == 0 || length == 0 || length < delimiterLength) { - yield return extends; + yield return value; yield break; } char[] cd = delimeter.ToCharArray(); - char[] cs = extends.ToCharArray(); + char[] cs = value.ToCharArray(); for (int i = 0; i < delimiterLength; i++) { @@ -169,22 +193,22 @@ namespace ICD.Common.Utils.Extensions int start = 0; 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; } 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; } else - yield return extends.Substring(start, length - start); + yield return value.Substring(start, length - start); } /// diff --git a/ICD.Common.Utils/Extensions/TypeExtensions.cs b/ICD.Common.Utils/Extensions/TypeExtensions.cs index 34829aa..8264d6d 100644 --- a/ICD.Common.Utils/Extensions/TypeExtensions.cs +++ b/ICD.Common.Utils/Extensions/TypeExtensions.cs @@ -210,18 +210,15 @@ namespace ICD.Common.Utils.Extensions if (!s_TypeBaseTypes.ContainsKey(extends)) { - Type[] types = GetBaseTypesInternal(extends).ToArray(); + Type[] types = GetBaseTypesIterator(extends).ToArray(); s_TypeBaseTypes.Add(extends, types); } return s_TypeBaseTypes[extends]; } - private static IEnumerable GetBaseTypesInternal(Type type) + private static IEnumerable GetBaseTypesIterator(Type type) { - if (type == null) - throw new ArgumentNullException("type"); - do { type = type diff --git a/ICD.Common.Utils/MathUtils.cs b/ICD.Common.Utils/MathUtils.cs index 7d718fd..c22c26f 100644 --- a/ICD.Common.Utils/MathUtils.cs +++ b/ICD.Common.Utils/MathUtils.cs @@ -172,18 +172,29 @@ namespace ICD.Common.Utils if (numbers == null) throw new ArgumentNullException("numbers"); + return GetRangesIterator(numbers); + } + + /// + /// 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) + /// + private static IEnumerable GetRangesIterator(IEnumerable numbers) + { int[] currentRange = null; foreach (int number in numbers.Order()) { if (currentRange == null) - currentRange = new[] {number, number}; + currentRange = new[] { number, number }; else if (currentRange[1] == number - 1) - currentRange = new[] {currentRange[0], number}; + currentRange = new[] { currentRange[0], number }; else { yield return currentRange; - currentRange = new[] {number, number}; + currentRange = new[] { number, number }; } } diff --git a/ICD.Common.Utils/RecursionUtils.cs b/ICD.Common.Utils/RecursionUtils.cs index 6cfec06..694c68a 100644 --- a/ICD.Common.Utils/RecursionUtils.cs +++ b/ICD.Common.Utils/RecursionUtils.cs @@ -71,6 +71,19 @@ namespace ICD.Common.Utils if (node == null) throw new ArgumentNullException("node"); + return GetCliqueIterator(map, visited, node); + } + + /// + /// Gets the clique containing the node. + /// + /// + /// + /// + /// + /// + private static IEnumerable GetCliqueIterator(IDictionary> map, IcdHashSet visited, T node) + { if (visited.Contains(node)) yield break; @@ -135,6 +148,18 @@ namespace ICD.Common.Utils if (getChildren == null) throw new ArgumentNullException("getChildren"); + return BreadthFirstSearchIterator(root, getChildren); + } + + /// + /// Returns all of the nodes in the tree via breadth-first search. + /// + /// + /// + /// + /// + private static IEnumerable BreadthFirstSearchIterator(T root, Func> getChildren) + { Queue process = new Queue(); process.Enqueue(root);