From 79621dcfda019c3b1dfa2ca5885b18d8710ed1bf Mon Sep 17 00:00:00 2001 From: Chris Cameron Date: Thu, 20 Jul 2017 13:05:34 -0400 Subject: [PATCH 1/9] Better exception when an attribute does not exist --- ICD.Common.Utils/Xml/XmlUtils.cs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/ICD.Common.Utils/Xml/XmlUtils.cs b/ICD.Common.Utils/Xml/XmlUtils.cs index 5196045..bba7bdc 100644 --- a/ICD.Common.Utils/Xml/XmlUtils.cs +++ b/ICD.Common.Utils/Xml/XmlUtils.cs @@ -4,6 +4,7 @@ using System.Linq; using System.Text; using ICD.Common.EventArguments; using ICD.Common.Properties; +using ICD.Common.Utils.Extensions; using ICD.Common.Utils.IO; namespace ICD.Common.Utils.Xml @@ -67,7 +68,11 @@ namespace ICD.Common.Utils.Xml [PublicAPI] public static IcdXmlAttribute GetAttribute(string xml, string name) { - return GetAttributes(xml).First(a => a.Name == name); + IcdXmlAttribute output; + if (GetAttributes(xml).TryFirstOrDefault(a => a.Name == name, out output)) + return output; + + throw new KeyNotFoundException(string.Format("No attribute with name {0}", name)); } /// From 71b3c5ad2a577756bbcef3220effcb90c80f211b Mon Sep 17 00:00:00 2001 From: Chris Cameron Date: Thu, 20 Jul 2017 13:06:00 -0400 Subject: [PATCH 2/9] Better name for TryFirst extension method --- ICD.Common.Utils/Extensions/EnumerableExtensions.cs | 6 +++--- ICD.Common.Utils/Xml/XmlUtils.cs | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/ICD.Common.Utils/Extensions/EnumerableExtensions.cs b/ICD.Common.Utils/Extensions/EnumerableExtensions.cs index 80e23df..66cc2bd 100644 --- a/ICD.Common.Utils/Extensions/EnumerableExtensions.cs +++ b/ICD.Common.Utils/Extensions/EnumerableExtensions.cs @@ -53,12 +53,12 @@ namespace ICD.Common.Utils.Extensions /// /// Outputs the first item in the sequence. /// - public static bool TryFirstOrDefault(this IEnumerable extends, out T item) + public static bool TryFirst(this IEnumerable extends, out T item) { if (extends == null) throw new ArgumentNullException("extends"); - return extends.TryFirstOrDefault(i => true, out item); + return extends.TryFirst(i => true, out item); } /// @@ -69,7 +69,7 @@ namespace ICD.Common.Utils.Extensions /// /// Outputs the first item in the sequence. /// - public static bool TryFirstOrDefault(this IEnumerable extends, Func predicate, out T item) + public static bool TryFirst(this IEnumerable extends, Func predicate, out T item) { if (extends == null) throw new ArgumentNullException("extends"); diff --git a/ICD.Common.Utils/Xml/XmlUtils.cs b/ICD.Common.Utils/Xml/XmlUtils.cs index bba7bdc..4a224dd 100644 --- a/ICD.Common.Utils/Xml/XmlUtils.cs +++ b/ICD.Common.Utils/Xml/XmlUtils.cs @@ -69,7 +69,7 @@ namespace ICD.Common.Utils.Xml public static IcdXmlAttribute GetAttribute(string xml, string name) { IcdXmlAttribute output; - if (GetAttributes(xml).TryFirstOrDefault(a => a.Name == name, out output)) + if (GetAttributes(xml).TryFirst(a => a.Name == name, out output)) return output; throw new KeyNotFoundException(string.Format("No attribute with name {0}", name)); From 442bd20759fcdd305f4f27bc29f128c1f7937d87 Mon Sep 17 00:00:00 2001 From: Chris Cameron Date: Fri, 21 Jul 2017 09:52:46 -0400 Subject: [PATCH 3/9] Adding list extension methods for adding items to a sorted list --- .../Extensions/ListExtensionsTest.cs | 54 +++++++++++++++ ICD.Common.Utils/Extensions/ListExtensions.cs | 68 +++++++++++++++++++ .../ICD.Common.Utils_SimplSharp.csproj | 1 + 3 files changed, 123 insertions(+) create mode 100644 ICD.Common.Utils.Tests/Extensions/ListExtensionsTest.cs create mode 100644 ICD.Common.Utils/Extensions/ListExtensions.cs diff --git a/ICD.Common.Utils.Tests/Extensions/ListExtensionsTest.cs b/ICD.Common.Utils.Tests/Extensions/ListExtensionsTest.cs new file mode 100644 index 0000000..f05539c --- /dev/null +++ b/ICD.Common.Utils.Tests/Extensions/ListExtensionsTest.cs @@ -0,0 +1,54 @@ +using ICD.Common.Utils.Extensions; +using NUnit.Framework; +using System.Collections.Generic; +using System; + +namespace ICD.Common.Utils.Tests_NetStandard.Extensions +{ + [TestFixture] + public sealed class ListExtensionsTest + { + [Test] + public void AddSortedTest() + { + List testList = new List(); + + testList.AddSorted(2); + testList.AddSorted(3); + testList.AddSorted(1); + testList.AddSorted(2); + + Assert.AreEqual(4, testList.Count); + Assert.AreEqual(1, testList[0]); + Assert.AreEqual(2, testList[1]); + Assert.AreEqual(2, testList[2]); + Assert.AreEqual(3, testList[3]); + } + + [Test] + public void AddSortedComparerTest() + { + List testList = new List(); + IComparer comparer = new InverseComparer(); + + testList.AddSorted(2, comparer); + testList.AddSorted(3, comparer); + testList.AddSorted(1, comparer); + testList.AddSorted(2, comparer); + + Assert.AreEqual(4, testList.Count); + Assert.AreEqual(3, testList[0]); + Assert.AreEqual(2, testList[1]); + Assert.AreEqual(2, testList[2]); + Assert.AreEqual(1, testList[3]); + } + + internal class InverseComparer : IComparer + { + public int Compare(int x, int y) + { + return y.CompareTo(x); + } + } + } +} diff --git a/ICD.Common.Utils/Extensions/ListExtensions.cs b/ICD.Common.Utils/Extensions/ListExtensions.cs new file mode 100644 index 0000000..6cfe6ed --- /dev/null +++ b/ICD.Common.Utils/Extensions/ListExtensions.cs @@ -0,0 +1,68 @@ +using System; +using System.Collections.Generic; +using ICD.Common.Properties; + +namespace ICD.Common.Utils.Extensions +{ + /// + /// Extension methods for working with Lists. + /// + public static class ListExtensions + { + /// + /// Adds the item into a sorted list. + /// + /// + /// + /// + [PublicAPI] + public static void AddSorted(this List extends, T item) + { + if (extends == null) + throw new ArgumentNullException("extends"); + + extends.AddSorted(item, Comparer.Default); + } + + /// + /// Adds the item into a sorted list. + /// + /// + /// + /// + /// + [PublicAPI] + public static void AddSorted(this List extends, T item, IComparer comparer) + { + if (extends == null) + throw new ArgumentNullException("extends"); + + if (comparer == null) + throw new ArgumentNullException("comparer"); + + if (extends.Count == 0) + { + extends.Add(item); + return; + } + + if (comparer.Compare(extends[extends.Count - 1], item) <= 0) + { + extends.Add(item); + return; + } + + if (comparer.Compare(extends[0], item) >= 0) + { + extends.Insert(0, item); + return; + } + + int index = extends.BinarySearch(item); + if (index < 0) + index = ~index; + + extends.Insert(index, item); + } + } +} diff --git a/ICD.Common.Utils/ICD.Common.Utils_SimplSharp.csproj b/ICD.Common.Utils/ICD.Common.Utils_SimplSharp.csproj index c39b3ae..b6944e9 100644 --- a/ICD.Common.Utils/ICD.Common.Utils_SimplSharp.csproj +++ b/ICD.Common.Utils/ICD.Common.Utils_SimplSharp.csproj @@ -85,6 +85,7 @@ + From 323300f710401462bd7ac05587d4a064ed874a36 Mon Sep 17 00:00:00 2001 From: Chris Cameron Date: Fri, 21 Jul 2017 11:01:32 -0400 Subject: [PATCH 4/9] Rethrowing XmlExceptions as IcdXmlExceptions --- ICD.Common.Utils/Xml/IcdXmlDocument.cs | 2 +- ICD.Common.Utils/Xml/IcdXmlException.cs | 14 ++++ ICD.Common.Utils/Xml/IcdXmlReader.cs | 105 ++++++++++++++++++++---- ICD.Common.Utils/Xml/XmlUtils.cs | 9 ++ 4 files changed, 115 insertions(+), 15 deletions(-) diff --git a/ICD.Common.Utils/Xml/IcdXmlDocument.cs b/ICD.Common.Utils/Xml/IcdXmlDocument.cs index cd2973b..09a50f1 100644 --- a/ICD.Common.Utils/Xml/IcdXmlDocument.cs +++ b/ICD.Common.Utils/Xml/IcdXmlDocument.cs @@ -28,7 +28,7 @@ namespace ICD.Common.Utils.Xml } catch (XmlException e) { - throw new IcdXmlException(e.Message, e, e.LineNumber, e.LinePosition); + throw new IcdXmlException(e); } } diff --git a/ICD.Common.Utils/Xml/IcdXmlException.cs b/ICD.Common.Utils/Xml/IcdXmlException.cs index 708228f..984fbb4 100644 --- a/ICD.Common.Utils/Xml/IcdXmlException.cs +++ b/ICD.Common.Utils/Xml/IcdXmlException.cs @@ -1,4 +1,9 @@ using System; +#if SIMPLSHARP +using Crestron.SimplSharp; +#else +using System.Xml; +#endif namespace ICD.Common.Utils.Xml { @@ -20,5 +25,14 @@ namespace ICD.Common.Utils.Xml m_LineNumber = lineNumber; m_LinePosition = linePosition; } + + /// + /// Constructor. + /// + /// + public IcdXmlException(XmlException inner) + : this(inner.Message, inner, inner.LineNumber, inner.LinePosition) + { + } } } diff --git a/ICD.Common.Utils/Xml/IcdXmlReader.cs b/ICD.Common.Utils/Xml/IcdXmlReader.cs index 4103949..109c9db 100644 --- a/ICD.Common.Utils/Xml/IcdXmlReader.cs +++ b/ICD.Common.Utils/Xml/IcdXmlReader.cs @@ -50,26 +50,54 @@ namespace ICD.Common.Utils.Xml public bool MoveToNextAttribute() { - return m_Reader.MoveToNextAttribute(); + try + { + return m_Reader.MoveToNextAttribute(); + } + catch (XmlException e) + { + throw new IcdXmlException(e); + } } public void MoveToElement() { - m_Reader.MoveToElement(); + try + { + m_Reader.MoveToElement(); + } + catch (XmlException e) + { + throw new IcdXmlException(e); + } } public string GetAttribute(string name) { - return m_Reader.GetAttribute(name); + try + { + return m_Reader.GetAttribute(name); + } + catch (XmlException e) + { + throw new IcdXmlException(e); + } } public string ReadString() { + try + { #if SIMPLSHARP - return m_Reader.ReadString(); + return m_Reader.ReadString(); #else - return m_Reader.ReadElementContentAsString(); + return m_Reader.ReadElementContentAsString(); #endif + } + catch (XmlException e) + { + throw new IcdXmlException(e); + } } public bool Read() @@ -80,47 +108,96 @@ namespace ICD.Common.Utils.Xml } catch (XmlException e) { - throw new IcdXmlException(e.Message, e, e.LineNumber, e.LinePosition); + throw new IcdXmlException(e); } } public void Dispose() { + try + { #if SIMPLSHARP - m_Reader.Dispose(true); + m_Reader.Dispose(true); #else - m_Reader.Dispose(); + m_Reader.Dispose(); #endif + } + catch (XmlException e) + { + throw new IcdXmlException(e); + } } public void Skip() { - m_Reader.Skip(); + try + { + m_Reader.Skip(); + } + catch (XmlException e) + { + throw new IcdXmlException(e); + } } public string ReadElementContentAsString() { - return m_Reader.ReadElementContentAsString(); + try + { + return m_Reader.ReadElementContentAsString(); + } + catch (XmlException e) + { + throw new IcdXmlException(e); + } } public string ReadOuterXml() { - return m_Reader.ReadOuterXml(); + try + { + return m_Reader.ReadOuterXml(); + } + catch (XmlException e) + { + throw new IcdXmlException(e); + } } public string ReadInnerXml() { - return m_Reader.ReadInnerXml(); + try + { + return m_Reader.ReadInnerXml(); + } + catch (XmlException e) + { + throw new IcdXmlException(e); + } } public long ReadElementContentAsLong() { - return m_Reader.ReadElementContentAsLong(); + try + { + return m_Reader.ReadElementContentAsLong(); + } + catch (XmlException e) + { + throw new IcdXmlException(e); + } } public float ReadElementContentAsFloat() { - return m_Reader.ReadElementContentAsFloat(); + try + { + return m_Reader.ReadElementContentAsFloat(); + } + catch (XmlException e) + { + throw new IcdXmlException(e); + } } #endregion diff --git a/ICD.Common.Utils/Xml/XmlUtils.cs b/ICD.Common.Utils/Xml/XmlUtils.cs index 4a224dd..ee07697 100644 --- a/ICD.Common.Utils/Xml/XmlUtils.cs +++ b/ICD.Common.Utils/Xml/XmlUtils.cs @@ -135,6 +135,9 @@ namespace ICD.Common.Utils.Xml [PublicAPI] public static void Recurse(string xml, Action callback) { + if (callback == null) + throw new ArgumentNullException("callback"); + Recurse(xml, new Stack(), callback); } @@ -146,6 +149,12 @@ namespace ICD.Common.Utils.Xml /// private static void Recurse(string xml, Stack path, Action callback) { + if (path == null) + throw new ArgumentNullException("path"); + + if (callback == null) + throw new ArgumentNullException("callback"); + IcdXmlReader childReader; try From f1fe9420f210e51c63e34e381648bd9b8e9c8960 Mon Sep 17 00:00:00 2001 From: "jeffery.thompson" Date: Fri, 21 Jul 2017 12:08:37 -0400 Subject: [PATCH 5/9] IcdConsole does not call string.Format if there are no args --- ICD.Common.Utils/IcdConsole.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/ICD.Common.Utils/IcdConsole.cs b/ICD.Common.Utils/IcdConsole.cs index dc065ce..5505eb6 100644 --- a/ICD.Common.Utils/IcdConsole.cs +++ b/ICD.Common.Utils/IcdConsole.cs @@ -1,4 +1,5 @@ using System; +using System.Linq; using ICD.Common.Properties; #if SIMPLSHARP using Crestron.SimplSharp; @@ -34,7 +35,8 @@ namespace ICD.Common.Utils [PublicAPI] public static void ConsoleCommandResponse(string message, params object[] args) { - message = string.Format(message, args); + if(args != null && args.Any()) + message = string.Format(message, args); #if SIMPLSHARP try From 57d0b481f161214352bdf7c49e50df6c1349e105 Mon Sep 17 00:00:00 2001 From: Chris Cameron Date: Fri, 21 Jul 2017 12:18:23 -0400 Subject: [PATCH 6/9] Moving SettingsProperty attribute to Settings library --- .../Attributes/Properties/SettingsProperty.cs | 39 ------------------- .../ICD.Common.Utils_SimplSharp.csproj | 1 - 2 files changed, 40 deletions(-) delete mode 100644 ICD.Common.Utils/Attributes/Properties/SettingsProperty.cs diff --git a/ICD.Common.Utils/Attributes/Properties/SettingsProperty.cs b/ICD.Common.Utils/Attributes/Properties/SettingsProperty.cs deleted file mode 100644 index f50520e..0000000 --- a/ICD.Common.Utils/Attributes/Properties/SettingsProperty.cs +++ /dev/null @@ -1,39 +0,0 @@ -using System; -using ICD.Common.Properties; - -namespace ICD.Common.Attributes.Properties -{ - /// - /// Provides information on a settings property. - /// - [PublicAPI] - public sealed class SettingsProperty : Attribute - { - public enum ePropertyType - { - [PublicAPI] Default, - [PublicAPI] Hidden, - [PublicAPI] PortId, - [PublicAPI] DeviceId, - [PublicAPI] Ipid, - [PublicAPI] Enum - } - - private readonly ePropertyType m_PropertyType; - - /// - /// Gets the property type. - /// - [PublicAPI] - public ePropertyType PropertyType { get { return m_PropertyType; } } - - /// - /// Constructor. - /// - /// - public SettingsProperty(ePropertyType propertyType) - { - m_PropertyType = propertyType; - } - } -} diff --git a/ICD.Common.Utils/ICD.Common.Utils_SimplSharp.csproj b/ICD.Common.Utils/ICD.Common.Utils_SimplSharp.csproj index b6944e9..5c10690 100644 --- a/ICD.Common.Utils/ICD.Common.Utils_SimplSharp.csproj +++ b/ICD.Common.Utils/ICD.Common.Utils_SimplSharp.csproj @@ -71,7 +71,6 @@ - From 83902b61b66e264e810c7a45b12054726d8477d2 Mon Sep 17 00:00:00 2001 From: Chris Cameron Date: Tue, 25 Jul 2017 16:17:56 -0400 Subject: [PATCH 7/9] Shim for trimming a potentially null string --- ICD.Common.Utils/StringUtils.cs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/ICD.Common.Utils/StringUtils.cs b/ICD.Common.Utils/StringUtils.cs index 8a27161..325a55e 100644 --- a/ICD.Common.Utils/StringUtils.cs +++ b/ICD.Common.Utils/StringUtils.cs @@ -516,5 +516,17 @@ namespace ICD.Common.Utils return builder.ToString(); } + + /// + /// Shim of value.ToString() + /// Returns null if input value is null. + /// + /// + /// + [PublicAPI, CanBeNull] + public static string Trim(string value) + { + return value == null ? null : value.ToUpper(); + } } } From a552f84dabc41003000481f0ee6808cf364fce42 Mon Sep 17 00:00:00 2001 From: Chris Cameron Date: Wed, 26 Jul 2017 12:10:04 -0400 Subject: [PATCH 8/9] Fixing stupid mistake where the comparer was not being passed to the BinarySearch method --- ICD.Common.Utils/Extensions/ListExtensions.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ICD.Common.Utils/Extensions/ListExtensions.cs b/ICD.Common.Utils/Extensions/ListExtensions.cs index 6cfe6ed..2d842ba 100644 --- a/ICD.Common.Utils/Extensions/ListExtensions.cs +++ b/ICD.Common.Utils/Extensions/ListExtensions.cs @@ -58,7 +58,7 @@ namespace ICD.Common.Utils.Extensions return; } - int index = extends.BinarySearch(item); + int index = extends.BinarySearch(item, comparer); if (index < 0) index = ~index; From a4328096bdcf092f0363ce6ab5fdbf653c71cc89 Mon Sep 17 00:00:00 2001 From: Chris Cameron Date: Thu, 27 Jul 2017 14:50:08 -0400 Subject: [PATCH 9/9] Slightly safer parsing of prog comments --- ICD.Common.Utils/ProgramUtils.cs | 40 ++++++++++++++++---------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/ICD.Common.Utils/ProgramUtils.cs b/ICD.Common.Utils/ProgramUtils.cs index b065bd5..2d17aca 100644 --- a/ICD.Common.Utils/ProgramUtils.cs +++ b/ICD.Common.Utils/ProgramUtils.cs @@ -147,29 +147,29 @@ namespace ICD.Common.Utils { Dictionary output = new Dictionary(); - try + string progInfo = string.Empty; + string command = string.Format("progcomments:{0}", ProgramNumber); + + if (!IcdConsole.SendControlSystemCommand(command, ref progInfo)) { - string progInfo = string.Empty; - string command = string.Format("progcomments:{0}", ProgramNumber); - - if (!IcdConsole.SendControlSystemCommand(command, ref progInfo)) - { - ServiceProvider.TryGetService().AddEntry(eSeverity.Warning, "Failed to parse prog comments"); - return output; - } - - foreach (string line in progInfo.Split(new[] {"\n\r", "\r\n", "\n", "\r"})) - { - string[] pair = line.Split(':', 2).ToArray(); - string key = pair[0].Trim(); - string value = pair[1].Trim(); - output[key] = value; - } + ServiceProvider.GetService().AddEntry(eSeverity.Warning, "Failed to parse prog comments"); + return output; } - catch (Exception e) + + foreach (string line in progInfo.Split(new[] {"\n\r", "\r\n", "\n", "\r"})) { - ServiceProvider.TryGetService() - .AddEntry(eSeverity.Error, e, "Failed to parse prog comments - {0}", e.Message); + string[] pair = line.Split(':', 2).ToArray(); + + if (pair.Length < 2) + { + ServiceProvider.GetService() + .AddEntry(eSeverity.Warning, "Failed to parse prog comments line - {0}", line); + continue; + } + + string key = pair[0].Trim(); + string value = pair[1].Trim(); + output[key] = value; } return output;