mirror of
https://github.com/ICDSystems/ICD.Common.Utils.git
synced 2026-01-25 02:14:59 +00:00
Compare commits
306 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9bf0a9b8a5 | ||
|
|
f7b35e64ec | ||
|
|
bfab3c77b0 | ||
|
|
4a68c0caad | ||
|
|
07ee6ce586 | ||
|
|
6f5deaf1ea | ||
|
|
3da9b23e12 | ||
|
|
9deafaec9b | ||
|
|
28ea05e2f6 | ||
|
|
f53d05936c | ||
|
|
4339f02698 | ||
|
|
25fb5a0ad8 | ||
|
|
6240d3fccf | ||
|
|
88ff67b356 | ||
|
|
1d0ba453e3 | ||
|
|
121d267aad | ||
|
|
f23b051c3a | ||
|
|
b5ec51d9a4 | ||
|
|
62f54f1213 | ||
|
|
dd3c0f530b | ||
|
|
fc74865c5b | ||
|
|
4de7944286 | ||
|
|
dbad18925f | ||
|
|
1a027bcea0 | ||
|
|
7053faede1 | ||
|
|
582cbe9157 | ||
|
|
00803fcd66 | ||
|
|
9912097a33 | ||
|
|
cad3cf60cf | ||
|
|
0431b5afe4 | ||
|
|
d1c21ae7b4 | ||
|
|
f34e307a93 | ||
|
|
2ad9adf86c | ||
|
|
bbb09666dd | ||
|
|
dd3c6b13fd | ||
|
|
f9dccd30e5 | ||
|
|
db0029bbc1 | ||
|
|
a5289e01f7 | ||
|
|
9de5acfbe7 | ||
|
|
a22c3626ab | ||
|
|
d90c60126e | ||
|
|
49d12d454f | ||
|
|
760ab259fa | ||
|
|
40e00e0ab7 | ||
|
|
64405a1cd6 | ||
|
|
ffb217839c | ||
|
|
0d8dbf4a30 | ||
|
|
79344a3667 | ||
|
|
5e61098e71 | ||
|
|
e0663bdbfd | ||
|
|
96946d6323 | ||
|
|
5067f5fdb3 | ||
|
|
d002dda568 | ||
|
|
08aeba756a | ||
|
|
b29ae4c8c8 | ||
|
|
c1418ae4e2 | ||
|
|
5978d492cf | ||
|
|
a1775b281f | ||
|
|
75ddc37cf1 | ||
|
|
d07373b69e | ||
|
|
3ebfa76970 | ||
|
|
ac5da50e98 | ||
|
|
6c6d272511 | ||
|
|
022e625143 | ||
|
|
b496594cd6 | ||
|
|
e99a7f313f | ||
|
|
ed2cf84a7e | ||
|
|
91684f25f2 | ||
|
|
be5024271f | ||
|
|
dd90227ca1 | ||
|
|
2fa6ff3de6 | ||
|
|
311d63204f | ||
|
|
82d0598352 | ||
|
|
4229a6a73f | ||
|
|
f5c6b64ab7 | ||
|
|
3f62e7e929 | ||
|
|
a82645e902 | ||
|
|
985578985a | ||
|
|
c453717998 | ||
|
|
fde3106389 | ||
|
|
94265b1915 | ||
|
|
9b3294382f | ||
|
|
d59eb00d6b | ||
|
|
d051ddb098 | ||
|
|
a53ad74811 | ||
|
|
69eb4b3d34 | ||
|
|
8e5486e1ef | ||
|
|
ecf7e626f3 | ||
|
|
3b5c9ed51b | ||
|
|
e2646194b8 | ||
|
|
0adad154c6 | ||
|
|
0b8eb82e3b | ||
|
|
13d1072d10 | ||
|
|
8d2321c350 | ||
|
|
55f494e2f5 | ||
|
|
859a2b0830 | ||
|
|
9d5dfb3b64 | ||
|
|
c60acf52ba | ||
|
|
311bf683e0 | ||
|
|
d025946948 | ||
|
|
b74d2c9d60 | ||
|
|
ac4c0eccc9 | ||
|
|
0cae292899 | ||
|
|
9cdc8b26a2 | ||
|
|
80786dd84c | ||
|
|
bf8061046b | ||
|
|
201639b30b | ||
|
|
89f0214cce | ||
|
|
49f8f116fd | ||
|
|
7598a451cc | ||
|
|
f03f49b376 | ||
|
|
da4415a11c | ||
|
|
67c07b8833 | ||
|
|
11c4d10a51 | ||
|
|
d1ec8a45d1 | ||
|
|
352121e25c | ||
|
|
0d5ee31d61 | ||
|
|
ec7004e053 | ||
|
|
ea0bcec2c3 | ||
|
|
55bf458a2b | ||
|
|
7562dddeff | ||
|
|
f66ddc7e03 | ||
|
|
b5fc25de7c | ||
|
|
d4ef4c3e1a | ||
|
|
2a8a936b6f | ||
|
|
bbe596c116 | ||
|
|
7689ffc3c8 | ||
|
|
1ab247f204 | ||
|
|
5b5ee258ca | ||
|
|
4695a80575 | ||
|
|
79a98d8c10 | ||
|
|
b68c5f1c97 | ||
|
|
3deec98f44 | ||
|
|
eb52b164bf | ||
|
|
fb8abe2aa4 | ||
|
|
f61305856f | ||
|
|
de00acbf79 | ||
|
|
5ffca5e7a3 | ||
|
|
2037c990b2 | ||
|
|
13a2493f4c | ||
|
|
09e0a20443 | ||
|
|
7870d2c375 | ||
|
|
7cf3d18127 | ||
|
|
f39b3897fc | ||
|
|
ab2fab0b3a | ||
|
|
9b69b2a712 | ||
|
|
0a1f637b45 | ||
|
|
e0ace12ef9 | ||
|
|
9f1541f843 | ||
|
|
b9f5349055 | ||
|
|
0c7f82835c | ||
|
|
41755cb472 | ||
|
|
238d6518ab | ||
|
|
89cde5c9a0 | ||
|
|
38204314e7 | ||
|
|
9e8cedfbfa | ||
|
|
52229c1472 | ||
|
|
38c24d42a7 | ||
|
|
cff1ec8d7e | ||
|
|
5a64a6c269 | ||
|
|
68d98021a5 | ||
|
|
0e16606d75 | ||
|
|
602f170091 | ||
|
|
aae8bc5323 | ||
|
|
11004085c5 | ||
|
|
6ca015a561 | ||
|
|
73b1c4819c | ||
|
|
f913af6efe | ||
|
|
099517df7d | ||
|
|
6a7b58f50f | ||
|
|
2273d5b3a1 | ||
|
|
aa17f29305 | ||
|
|
e65578584a | ||
|
|
96d2df8871 | ||
|
|
b4d82a855e | ||
|
|
83bc344ab3 | ||
|
|
0821dcb3ca | ||
|
|
b6f64bb9b2 | ||
|
|
6ae110a997 | ||
|
|
efdb48f2c3 | ||
|
|
9d02ee0022 | ||
|
|
8c0416f70e | ||
|
|
0f27d68edf | ||
|
|
f8fc68e08f | ||
|
|
fc4ae67e40 | ||
|
|
0f618198b5 | ||
|
|
9a6f197aa0 | ||
|
|
45ee3e70b0 | ||
|
|
b09f614ef5 | ||
|
|
027c9ffe82 | ||
|
|
dc1b60e629 | ||
|
|
091ad10068 | ||
|
|
71bb320057 | ||
|
|
e6b0fd5f7b | ||
|
|
2a2bff2e92 | ||
|
|
9c07b3da04 | ||
|
|
438b3d48e4 | ||
|
|
629ceec84e | ||
|
|
bb41d59a4b | ||
|
|
c23d81e023 | ||
|
|
18abe78550 | ||
|
|
f33218f7a6 | ||
|
|
4938dad882 | ||
|
|
5900f5974b | ||
|
|
81f7eb9c66 | ||
|
|
440c1c62f1 | ||
|
|
63b590a9ea | ||
|
|
f8c88630fc | ||
|
|
3f1f9611ec | ||
|
|
47c611a0b4 | ||
|
|
e388f35efb | ||
|
|
89061b5cbf | ||
|
|
ff6f15d3ef | ||
|
|
02e6fe9f8c | ||
|
|
edb5534b9d | ||
|
|
6af3e5b2ff | ||
|
|
65f76402cc | ||
|
|
5700cf4ce2 | ||
|
|
7c238b9fef | ||
|
|
6eda848410 | ||
|
|
7b44867f34 | ||
|
|
149f480add | ||
|
|
0f5632ced8 | ||
|
|
9df5f7ae37 | ||
|
|
6e056c9dcc | ||
|
|
7add461a1a | ||
|
|
cb3677bd72 | ||
|
|
69ad4bb240 | ||
|
|
1a868d5a7d | ||
|
|
bb6110931a | ||
|
|
909ebfbc97 | ||
|
|
3d068aeb68 | ||
|
|
1f6915a825 | ||
|
|
00e7fd6a6b | ||
|
|
e3f356a5db | ||
|
|
2d401959b6 | ||
|
|
7cc5a47d6a | ||
|
|
8c160c77c4 | ||
|
|
65c50e8e90 | ||
|
|
3a2fc0eef7 | ||
|
|
1be852685d | ||
|
|
6201184fab | ||
|
|
e8acb42bb9 | ||
|
|
d3d812265e | ||
|
|
b915401109 | ||
|
|
3e3a4e33cb | ||
|
|
b680bab67a | ||
|
|
7666021925 | ||
|
|
7b6092c291 | ||
|
|
f7740aaea2 | ||
|
|
c31b2b556b | ||
|
|
8866a3e1e6 | ||
|
|
e3273934a7 | ||
|
|
0152259a25 | ||
|
|
98c3f17602 | ||
|
|
bb3fba100d | ||
|
|
9adad373f6 | ||
|
|
844f8b7b46 | ||
|
|
43d7ea944e | ||
|
|
6526b2b811 | ||
|
|
ead365e251 | ||
|
|
f24e6d2597 | ||
|
|
311f2dfaf4 | ||
|
|
1c38d9f04a | ||
|
|
02c18d152f | ||
|
|
fc482ec685 | ||
|
|
d649fb9dc4 | ||
|
|
4d76abe046 | ||
|
|
d6d3bfa9e0 | ||
|
|
536742a1c6 | ||
|
|
dc824b2034 | ||
|
|
0cc588ce15 | ||
|
|
b996a295f6 | ||
|
|
4312ad1a61 | ||
|
|
7792b01629 | ||
|
|
4953e40f9e | ||
|
|
69f872ced1 | ||
|
|
7e3aef4cb3 | ||
|
|
a6fbd5a6d2 | ||
|
|
6f67064d34 | ||
|
|
723759f805 | ||
|
|
59f4411620 | ||
|
|
243e285948 | ||
|
|
198bf8dac0 | ||
|
|
78f5c4a7b6 | ||
|
|
c0ed7f9b26 | ||
|
|
6d08ee3bef | ||
|
|
2b376bff47 | ||
|
|
9f0e66e4a1 | ||
|
|
4c93515f83 | ||
|
|
9ad49540d2 | ||
|
|
dc0e65125a | ||
|
|
294afd1834 | ||
|
|
475f381991 | ||
|
|
0931d6f1ec | ||
|
|
24859aaa31 | ||
|
|
f4693df048 | ||
|
|
40342e2d9e | ||
|
|
c054a9d752 | ||
|
|
ef19e20d67 | ||
|
|
3fd344a308 | ||
|
|
17e7f4d3c9 | ||
|
|
87d1f4da16 | ||
|
|
88a4801f8e | ||
|
|
c55e35ac6e | ||
|
|
7557e01c9f |
217
CHANGELOG.md
217
CHANGELOG.md
@@ -6,6 +6,160 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
## [12.0.0] - 2020-06-18
|
||||
### Added
|
||||
- Added ToCollection extension method for copying an enumerable to a new collection
|
||||
- TableBuilder supports multi-line content
|
||||
- Added eIcdFileMode for IO platform agnosticism
|
||||
- Extension method for determining if a Type is anonymous
|
||||
- Extension method for getting inner generic Types
|
||||
- Added extension method for dynamically converting a sequence to a generic list of the given item type
|
||||
- Added methods for getting UserData paths
|
||||
- Added methods for reading GUIDs from XML
|
||||
- Added methods for reading DateTimes from XML
|
||||
- Added method for combining GUIDs
|
||||
- Added method for getting the EventArgs type for an EventHandler
|
||||
- Added methods for getting a JSON value as a float or double
|
||||
- Added dictionary Remove method for outputting the removed value
|
||||
- Added IGenericEventArgs interface
|
||||
- Added MinimalTypeConverter for serializing Types to JSON
|
||||
- Added common JSON serializer settings for common, platform agnostic DateTime and Type conversion
|
||||
|
||||
### Changed
|
||||
- Rewrote JsonItemWrapper serialization for JsonConvert friendliness
|
||||
- Reflection optimizations
|
||||
- Fixed NullParameterException in TableBuilder
|
||||
- Improvements to EnumUtils, less reliance on casting to/from int
|
||||
- Cleaned up TimeSpan.ToReadableString() output
|
||||
- Fixed a bug where System.Reflection exceptions can't be caught in S#
|
||||
- TableBuilder no longer draws redundant separators
|
||||
- Fixed a bug where CompiledOn date was not being parsed correctly due to culture
|
||||
- S# DateTimes are serialized to JSON in ISO-8601 format
|
||||
- Deadlock detection works better for false positives
|
||||
- Improved LogItem JSON serialization
|
||||
- Improved NiceName method to better handle syntax, whitespace and punctuation
|
||||
- Fixed a bug where IcdCultureInfo would fail to load on Crestron 4-series processors
|
||||
- Clarifying which culture failed to load when IcdCultureInfo throws an exception
|
||||
|
||||
## [11.1.0] - 2020-05-19
|
||||
### Added
|
||||
- ScrollQueue - Added OnItemTrimmed event
|
||||
- Added DateTimeNullableEventArgs
|
||||
|
||||
## [11.0.0] - 2020-03-20
|
||||
### Added
|
||||
- Added Not null tag for ICDUriBuilder Constructor that takes a URI as an argument.
|
||||
- Added MathUtils methods for converting to and from percentages
|
||||
- Added enum extensions for finding the inclusion and exclusion of enum flags
|
||||
- Added DateTime extensions for adding years, months, days, hours, minutes and wrapping without modifying other values
|
||||
- Added shims for deserializing an XML array using a callback for each item
|
||||
- Added methods for serializing an XML array
|
||||
- Added WriteAllByte method on IcdFile.
|
||||
- Added PathUtils for building paths in the HTML directory
|
||||
- Added public access to GetValues enumeration extension
|
||||
- Added extensions for getting JsonReader values as long or ulong
|
||||
- Added DateTimeUtils methods for creating DateTimes from epoch seconds or milliseconds
|
||||
- Added utils for splitting ANSI into spans for conversion to XAML, HTML, etc
|
||||
|
||||
### Changed
|
||||
- Fixed exception trying to get DHCP status of network interfaces on Linux
|
||||
- Fixed a bug where color formatted console output on Net Standard was not raising the OnConsolePrint event
|
||||
- Simplifying ANSI color methods, better cross-platform color support
|
||||
- Console uses unicode for table drawing on Net Standard
|
||||
- Using UTC for tracking scheduled events, fixes issues with DST
|
||||
- Using UTC for tracking durations
|
||||
- Fixed a bug where table width calculations were not considering unprintable characters
|
||||
|
||||
## [10.3.0] - 2020-01-20
|
||||
### Changed
|
||||
- Network/MAC/DNS address utils are now enumerating all adapter types
|
||||
- Ignoring Crestron ethernet parameters that say "Invalid Value"
|
||||
- Skipping network interfaces with an invalid adapter id
|
||||
|
||||
## [10.2.0] - 2019-12-04
|
||||
### Added
|
||||
- Added shim methods for finding closest DateTimes from a sequence
|
||||
|
||||
## [10.1.0] - 2019-11-18
|
||||
### Added
|
||||
- Added PathUtils methods for getting ProgramData paths
|
||||
- Added a method for determining if a URI is defaults
|
||||
- Added MaxOrDefault extension method for enumerables
|
||||
- Added a method for finding an item in a sorted list by a given predicate
|
||||
|
||||
### Changed
|
||||
- NullObject implements IComparable, fixes issues with null keys in ordered dictionaries
|
||||
- IcdSqliteConnection CreateFile method will create directories recursively
|
||||
|
||||
## [10.0.0] - 2019-10-07
|
||||
### Added
|
||||
- IcdEnvironment.GetUtcTime() to get UTC representaiton of current time.
|
||||
- Extension methods for determining if a sequence is in order
|
||||
- Overload for calculating the modulus of longs
|
||||
- Default implementation for AbstractGenericXmlConverter Instantiate method
|
||||
- Additional binary search extensions, now working for all ILists
|
||||
- Added NullObject as a means of having null keys in hash tables
|
||||
|
||||
### Changed
|
||||
- Potential fix for unhelpful exception messages coming from SafeCriticalSection.Execute
|
||||
- Small performance improvement when copying arrays
|
||||
|
||||
## [9.9.0] - 2019-09-16
|
||||
### Added
|
||||
- Added a method for converting 24 hour to 12 hour format
|
||||
- Added a method for determining if a culture uses 24 hour format
|
||||
- Added math util method for modulus
|
||||
- Added TimeSpan extension methods for cycling hours and minutes without modifying the day
|
||||
- Added a dictionary extension method for getting or adding a new value via func
|
||||
- Added CultureInfo extensions for converting between 12 hour and 24 hour time formatting
|
||||
- Added environment methods for setting the current date and time
|
||||
- Added BinarySearch extension method for all IList types
|
||||
- Added PathUtils methods to get ProgramData directory
|
||||
|
||||
### Changed
|
||||
- The Root Config path in Net Standard will now be the ICD.Connect folder in the current environments ProgramData directory
|
||||
- Fixed a bug where CultureInfo was not being cloned correctly
|
||||
- List AddSorted extensions now work for all IList types
|
||||
|
||||
## [9.8.0] - 2019-09-03
|
||||
### Added
|
||||
- Added Public API Properties to get the program install date based on the creation date of core dll file for NetStandard and SimplSharp
|
||||
- Implemented processor utils for NetStandard to get the system uptime and the program uptime
|
||||
- Added methods for deserializing an XML array
|
||||
|
||||
### Changed
|
||||
- Fixed a bug where ANSI color encoded strings with percentages were being scrambled
|
||||
- Improvements to JSON DateTime parsing, particularly in Net Standard
|
||||
|
||||
## [9.7.0] - 2019-08-15
|
||||
### Added
|
||||
- Added logger timestamps to non simplsharp programs
|
||||
- Added Net Standard Support for JSON DateTime formats
|
||||
- Added EmailValidation class
|
||||
|
||||
### Changed
|
||||
- JSON dict serialization serializes keys instead of converting to property name
|
||||
|
||||
## [9.6.0] - 2019-07-03
|
||||
### Added
|
||||
- Added RecursionUtils method to get a single clique given a starting node
|
||||
- Breadth First Search can now search graphs in addition to trees
|
||||
- Added StartOfDay and EndOfDay DateTime extension methods
|
||||
|
||||
### Changed
|
||||
- Fixed bug in IcdUriBuilder where Query property behaved differently to UriBuilder
|
||||
- Throwing an exception when attempting to read a non-primitive JSON token as a string
|
||||
|
||||
## [9.5.0] - 2019-06-10
|
||||
### Added
|
||||
- Added Shim to read a list from xml with no root element
|
||||
- Added a URI query builder
|
||||
|
||||
### Changed
|
||||
- Fixed JSON DateTime parsing in .Net Standard
|
||||
- Fixed threading exception in TypeExtensions
|
||||
- Fixes for platform-agnostic culture handling
|
||||
|
||||
## [9.4.0] - 2019-05-10
|
||||
### Added
|
||||
- Added extension method for peeking queues
|
||||
@@ -59,6 +213,64 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
|
||||
- Better VC-4 support for IcdConsole
|
||||
- JSON refactoring for simpler deserialization
|
||||
|
||||
## [8.9.1] - 2020-05-27
|
||||
### Changed
|
||||
- Changed ProcessorUtils to use CrestronEnvironment to retrive serial number - this fixes issues with new serial numbers that aren't deciaml TSIDs
|
||||
|
||||
## [8.9.0] - 2020-04-30
|
||||
### Changed
|
||||
- ProgramUtils and ProcessorUtils return dates instead of strings for date properties
|
||||
|
||||
## [8.8.1] - 2020-02-18
|
||||
### Changed
|
||||
- IcdTimer - fixed issue that prevented OnElapsed event from firing when Length is less than (or close to) Heartbeat Interval
|
||||
|
||||
## [8.8.0] - 2020-01-23
|
||||
### Added
|
||||
- Added an overload to PriorityQueue for determing the de-duplication behaviour
|
||||
|
||||
## [8.7.2] - 2019-10-29
|
||||
### Changed
|
||||
- Fixed a bug with PriorityQueue de-duplication where a new command would be inserted in the wrong position
|
||||
|
||||
## [8.7.1] - 2019-08-22
|
||||
### Changed
|
||||
- Fixed a bug with the IcdOrderedDict index setter that was creating additional values
|
||||
|
||||
## [8.7.0] - 2019-06-24
|
||||
### Added
|
||||
- IcdXmlException exposes line number and position properties
|
||||
|
||||
## [8.6.1] - 2019-06-14
|
||||
### Changed
|
||||
- Fixed a bug where stopped timers on NetStandard would still have a periodic callback duration
|
||||
|
||||
## [8.6.0] - 2019-06-14
|
||||
### Changed
|
||||
- Overhaul of RangeAttribute remap methods to better avoid overflows
|
||||
|
||||
## [8.5.0] - 2019-06-06
|
||||
### Added
|
||||
- Adding features to IcdEnvironment for tracking program initialization state
|
||||
|
||||
## [8.4.1] - 2019-06-05
|
||||
### Changed
|
||||
- Caching the program/processor start time and calculating the uptime from those values instead of polling the crestron processor
|
||||
|
||||
## [8.4.0] - 2019-05-15
|
||||
### Added
|
||||
- Added GUID utils for generating seeded GUIDs
|
||||
- Added extension method for getting stable hashcodes from strings
|
||||
- Added environment and processor utilities for determining DNS status and hostname
|
||||
|
||||
### Changed
|
||||
- RangeAttribute improvements for better type safety
|
||||
- PathUtils breaking out ProgramConfigDirectory and CommonConfigDirectory from the full paths
|
||||
|
||||
## [8.3.3] - 2019-05-24
|
||||
### Added
|
||||
- Added empty, placeholder interface for ICD Attributes
|
||||
|
||||
## [8.3.2] - 2019-05-02
|
||||
### Changed
|
||||
- Fixed PriorityQueue IndexOutOfRange exception when an inner queue becomes depleted
|
||||
@@ -127,7 +339,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
|
||||
- New XML conversion framework for performance improvements
|
||||
|
||||
### Changed
|
||||
- XmlUtils is now using the improved XML conversion framework
|
||||
- XmlUtils is now using the improved XML conversion framework
|
||||
- Better implementation of DictionaryExtensions.ToInverse
|
||||
|
||||
## [5.0.0] - 2018-09-14
|
||||
@@ -200,8 +412,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
|
||||
- Adding extension method for getting Informational Version from an Assembly
|
||||
- Adding WeakKeyDictionary for caching
|
||||
- Reflection util methods
|
||||
|
||||
|
||||
### Changed
|
||||
- JSON serialization/deserialization features moved into base converter
|
||||
- Removed suffix from assembly name
|
||||
|
||||
27
ICD.Common.Utils.Tests/AnsiUtilsTest.cs
Normal file
27
ICD.Common.Utils.Tests/AnsiUtilsTest.cs
Normal file
@@ -0,0 +1,27 @@
|
||||
using System.Linq;
|
||||
using NUnit.Framework;
|
||||
|
||||
namespace ICD.Common.Utils.Tests
|
||||
{
|
||||
[TestFixture]
|
||||
public sealed class AnsiUtilsTest
|
||||
{
|
||||
[Test]
|
||||
public void ToSpansTest()
|
||||
{
|
||||
string ansi = "\x1b[30mblack\x1b[37mwhite\x1b[0mdefault";
|
||||
AnsiSpan[] spans = AnsiUtils.ToSpans(ansi).ToArray();
|
||||
|
||||
Assert.AreEqual(3, spans.Length);
|
||||
|
||||
Assert.AreEqual("black", spans[0].Text);
|
||||
Assert.AreEqual("30", spans[0].Code);
|
||||
|
||||
Assert.AreEqual("white", spans[1].Text);
|
||||
Assert.AreEqual("37", spans[1].Code);
|
||||
|
||||
Assert.AreEqual("default", spans[2].Text);
|
||||
Assert.AreEqual("0", spans[2].Code);
|
||||
}
|
||||
}
|
||||
}
|
||||
86
ICD.Common.Utils.Tests/Attributes/RangeAttributeTest.cs
Normal file
86
ICD.Common.Utils.Tests/Attributes/RangeAttributeTest.cs
Normal file
@@ -0,0 +1,86 @@
|
||||
using System;
|
||||
using NUnit.Framework;
|
||||
using RangeAttribute = ICD.Common.Utils.Attributes.RangeAttribute;
|
||||
|
||||
namespace ICD.Common.Utils.Tests.Attributes
|
||||
{
|
||||
[TestFixture]
|
||||
public sealed class RangeAttributeTest : AbstractIcdAttributeTest<RangeAttribute>
|
||||
{
|
||||
#region Properties
|
||||
|
||||
[TestCase(1)]
|
||||
[TestCase(1.0f)]
|
||||
[TestCase(1.0)]
|
||||
public void MinTest(object min)
|
||||
{
|
||||
Assert.AreEqual(min, new RangeAttribute(min, min).Min);
|
||||
}
|
||||
|
||||
[TestCase(1)]
|
||||
[TestCase(1.0f)]
|
||||
[TestCase(1.0)]
|
||||
public void MaxTest(object max)
|
||||
{
|
||||
Assert.AreEqual(max, new RangeAttribute(max, max).Max);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
|
||||
[TestCase((double)0, (double)0)]
|
||||
[TestCase((double)1, (double)1)]
|
||||
[TestCase(ushort.MaxValue, double.MaxValue)]
|
||||
[TestCase(short.MinValue, double.MinValue)]
|
||||
public void RemapToDoubleTest(object value, double expected)
|
||||
{
|
||||
Assert.AreEqual(expected, RangeAttribute.RemapToDouble(value));
|
||||
}
|
||||
|
||||
[TestCase((double)0, typeof(ushort), (ushort)32767)]
|
||||
[TestCase(double.MinValue, typeof(ushort), ushort.MinValue)]
|
||||
[TestCase(double.MaxValue, typeof(ushort), ushort.MaxValue)]
|
||||
public void RemapFromDoubleTest(double value, Type type, object expected)
|
||||
{
|
||||
Assert.AreEqual(expected, RangeAttribute.RemapFromDouble(value, type));
|
||||
}
|
||||
|
||||
[TestCase(short.MinValue, typeof(ushort), ushort.MinValue)]
|
||||
[TestCase(short.MaxValue, typeof(ushort), short.MaxValue)]
|
||||
public static void Clamp(object value, Type type, object expected)
|
||||
{
|
||||
Assert.AreEqual(expected, RangeAttribute.Clamp(value, type));
|
||||
}
|
||||
|
||||
[TestCase(double.MinValue, typeof(ushort), ushort.MinValue)]
|
||||
[TestCase(double.MaxValue, typeof(ushort), ushort.MaxValue)]
|
||||
public void Clamp(double value, Type type, double expected)
|
||||
{
|
||||
Assert.AreEqual(expected, RangeAttribute.Clamp(value, type));
|
||||
}
|
||||
|
||||
[TestCase(short.MinValue, typeof(ushort), ushort.MinValue)]
|
||||
[TestCase(short.MaxValue, typeof(ushort), ushort.MaxValue)]
|
||||
public void RemapTest(object value, Type type, object expected)
|
||||
{
|
||||
Assert.AreEqual(expected, RangeAttribute.Remap(value, type));
|
||||
}
|
||||
|
||||
[TestCase(0, 100, ushort.MaxValue, typeof(ushort), ushort.MaxValue)]
|
||||
[TestCase(0, 100, ushort.MaxValue, typeof(short), short.MaxValue)]
|
||||
public void ClampMinMaxThenRemapTest(object min, object max, object value, Type type, object expected)
|
||||
{
|
||||
Assert.AreEqual(expected, new RangeAttribute(min, max).ClampMinMaxThenRemap(value, type));
|
||||
}
|
||||
|
||||
[TestCase(0, 100, ushort.MaxValue, 100)]
|
||||
[TestCase(0, 100, ushort.MinValue, 0)]
|
||||
public void RemapMinMaxTest(object min, object max, object value, object expected)
|
||||
{
|
||||
Assert.AreEqual(expected, new RangeAttribute(min, max).RemapMinMax(value));
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -69,16 +69,26 @@ namespace ICD.Common.Utils.Tests.Collections
|
||||
[Test]
|
||||
public void IndexerTest()
|
||||
{
|
||||
IcdOrderedDictionary<int, int> dict = new IcdOrderedDictionary<int, int>
|
||||
{
|
||||
{0, 0},
|
||||
{1, 10},
|
||||
{-1, -10}
|
||||
};
|
||||
// ReSharper disable UseObjectOrCollectionInitializer
|
||||
IcdOrderedDictionary<int, int> dict = new IcdOrderedDictionary<int, int>();
|
||||
// ReSharper restore UseObjectOrCollectionInitializer
|
||||
|
||||
dict[0] = 0;
|
||||
dict[1] = 10;
|
||||
dict[-1] = -10;
|
||||
dict[-1] = -11;
|
||||
|
||||
Assert.AreEqual(0, dict[0]);
|
||||
Assert.AreEqual(10, dict[1]);
|
||||
Assert.AreEqual(-10, dict[-1]);
|
||||
Assert.AreEqual(-11, dict[-1]);
|
||||
|
||||
Assert.AreEqual(3, dict.Count);
|
||||
|
||||
int[] expectedKeys = {-1, 0, 1 };
|
||||
int[] expectedValues = {-11, 0, 10};
|
||||
|
||||
Assert.AreEqual(expectedKeys, dict.Keys.ToArray());
|
||||
Assert.AreEqual(expectedValues, dict.Values.ToArray());
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -133,8 +133,8 @@ namespace ICD.Common.Utils.Tests.Collections
|
||||
};
|
||||
|
||||
Assert.AreEqual(1, dequeue[0]);
|
||||
Assert.AreEqual(4, dequeue[1]);
|
||||
Assert.AreEqual(3, dequeue[2]);
|
||||
Assert.AreEqual(3, dequeue[1]);
|
||||
Assert.AreEqual(4, dequeue[2]);
|
||||
}
|
||||
|
||||
[Test]
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
using ICD.Common.Properties;
|
||||
using NUnit.Framework;
|
||||
using ICD.Common.Utils.Collections;
|
||||
using ICD.Common.Utils.EventArguments;
|
||||
|
||||
namespace ICD.Common.Utils.Tests.Collections
|
||||
{
|
||||
@@ -76,5 +77,43 @@ namespace ICD.Common.Utils.Tests.Collections
|
||||
|
||||
Assert.AreEqual(0, test.Peek());
|
||||
}
|
||||
|
||||
[Test, UsedImplicitly]
|
||||
public void OnItemTrimmedTest()
|
||||
{
|
||||
ScrollQueue<int> test = new ScrollQueue<int>(3);
|
||||
|
||||
int? removedItem = null;
|
||||
|
||||
test.OnItemTrimmed += (sender, args) => removedItem = args.Data;
|
||||
|
||||
test.Enqueue(1);
|
||||
test.Enqueue(2);
|
||||
test.Enqueue(3);
|
||||
|
||||
Assert.IsNull(removedItem, "Raised Early");
|
||||
|
||||
test.Enqueue(4);
|
||||
|
||||
Assert.True(removedItem.HasValue, "Not Raised");
|
||||
if (removedItem.HasValue)
|
||||
Assert.AreEqual(1, removedItem.Value, "Incorrect Value");
|
||||
|
||||
removedItem = null;
|
||||
|
||||
test.Enqueue(5);
|
||||
|
||||
Assert.True(removedItem.HasValue, "Not Raised");
|
||||
if (removedItem.HasValue)
|
||||
Assert.AreEqual(2, removedItem.Value, "Incorrect Value");
|
||||
|
||||
removedItem = null;
|
||||
|
||||
test.MaxSize = 4;
|
||||
|
||||
test.Enqueue(6);
|
||||
|
||||
Assert.False(removedItem.HasValue, "Raised Early");
|
||||
}
|
||||
}
|
||||
}
|
||||
17
ICD.Common.Utils.Tests/DateTimeUtilsTest.cs
Normal file
17
ICD.Common.Utils.Tests/DateTimeUtilsTest.cs
Normal file
@@ -0,0 +1,17 @@
|
||||
using NUnit.Framework;
|
||||
|
||||
namespace ICD.Common.Utils.Tests
|
||||
{
|
||||
[TestFixture]
|
||||
public sealed class DateTimeUtilsTest
|
||||
{
|
||||
[TestCase(1, 1)]
|
||||
[TestCase(0, 12)]
|
||||
[TestCase(12, 12)]
|
||||
[TestCase(23, 11)]
|
||||
public void To12HourTest(int hour, int expected)
|
||||
{
|
||||
Assert.AreEqual(expected, DateTimeUtils.To12Hour(hour));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,12 +5,12 @@ using System.Linq;
|
||||
namespace ICD.Common.Utils.Tests
|
||||
{
|
||||
[TestFixture]
|
||||
public sealed class EnumUtilsTest
|
||||
{
|
||||
public sealed class EnumUtilsTest
|
||||
{
|
||||
public enum eTestEnum
|
||||
{
|
||||
None = 0,
|
||||
A = 1,
|
||||
A = 1,
|
||||
B = 2,
|
||||
C = 3,
|
||||
}
|
||||
@@ -24,7 +24,7 @@ namespace ICD.Common.Utils.Tests
|
||||
C = 4,
|
||||
D = 32
|
||||
}
|
||||
|
||||
|
||||
[Test]
|
||||
public void GetValuesTest()
|
||||
{
|
||||
@@ -36,7 +36,7 @@ namespace ICD.Common.Utils.Tests
|
||||
Assert.AreEqual(eTestEnum.B, values[2]);
|
||||
Assert.AreEqual(eTestEnum.C, values[3]);
|
||||
}
|
||||
|
||||
|
||||
[Test]
|
||||
public void IsEnumTypeGenericTest()
|
||||
{
|
||||
@@ -57,17 +57,29 @@ namespace ICD.Common.Utils.Tests
|
||||
Assert.IsFalse(EnumUtils.IsEnum(""));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void IsDefinedTest()
|
||||
{
|
||||
Assert.IsFalse(EnumUtils.IsDefined((eTestEnum)20));
|
||||
Assert.IsTrue(EnumUtils.IsDefined((eTestEnum)2));
|
||||
[Test]
|
||||
public void IsDefinedTest()
|
||||
{
|
||||
Assert.IsFalse(EnumUtils.IsDefined((eTestEnum)20));
|
||||
Assert.IsTrue(EnumUtils.IsDefined((eTestEnum)2));
|
||||
|
||||
Assert.IsFalse(EnumUtils.IsDefined((eTestFlagsEnum)8));
|
||||
Assert.IsTrue(EnumUtils.IsDefined((eTestFlagsEnum)3));
|
||||
}
|
||||
Assert.IsFalse(EnumUtils.IsDefined((eTestFlagsEnum)8));
|
||||
Assert.IsTrue(EnumUtils.IsDefined((eTestFlagsEnum)3));
|
||||
}
|
||||
|
||||
#region Values
|
||||
#region Values
|
||||
|
||||
[Test]
|
||||
public void GetNamesTest()
|
||||
{
|
||||
string[] names = EnumUtils.GetNames<eTestEnum>().ToArray();
|
||||
|
||||
Assert.AreEqual(4, names.Length);
|
||||
Assert.IsTrue(names.Contains("None"));
|
||||
Assert.IsTrue(names.Contains("A"));
|
||||
Assert.IsTrue(names.Contains("B"));
|
||||
Assert.IsTrue(names.Contains("C"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GetValuesGenericTest()
|
||||
@@ -107,7 +119,9 @@ namespace ICD.Common.Utils.Tests
|
||||
[Test]
|
||||
public void GetFlagsIntersectionGenericTest()
|
||||
{
|
||||
Assert.AreEqual(eTestFlagsEnum.B, EnumUtils.GetFlagsIntersection(eTestFlagsEnum.A | eTestFlagsEnum.B, eTestFlagsEnum.B | eTestFlagsEnum.C));
|
||||
Assert.AreEqual(eTestFlagsEnum.B,
|
||||
EnumUtils.GetFlagsIntersection(eTestFlagsEnum.A | eTestFlagsEnum.B,
|
||||
eTestFlagsEnum.B | eTestFlagsEnum.C));
|
||||
}
|
||||
|
||||
[Test]
|
||||
@@ -138,11 +152,11 @@ namespace ICD.Common.Utils.Tests
|
||||
Assert.IsTrue(aValues.Contains(eTestFlagsEnum.D));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GetAllFlagCombinationsExceptNoneGenericTest()
|
||||
{
|
||||
eTestFlagsEnum a = eTestFlagsEnum.A | eTestFlagsEnum.B | eTestFlagsEnum.C | eTestFlagsEnum.D;
|
||||
eTestFlagsEnum[] aValues = EnumUtils.GetAllFlagCombinationsExceptNone(a).ToArray();
|
||||
[Test]
|
||||
public void GetAllFlagCombinationsExceptNoneGenericTest()
|
||||
{
|
||||
eTestFlagsEnum a = eTestFlagsEnum.A | eTestFlagsEnum.B | eTestFlagsEnum.C | eTestFlagsEnum.D;
|
||||
eTestFlagsEnum[] aValues = EnumUtils.GetAllFlagCombinationsExceptNone(a).ToArray();
|
||||
|
||||
Assert.AreEqual(15, aValues.Length);
|
||||
Assert.IsFalse(aValues.Contains(eTestFlagsEnum.None));
|
||||
@@ -167,7 +181,8 @@ namespace ICD.Common.Utils.Tests
|
||||
public void GetFlagsAllValueGenericTest()
|
||||
{
|
||||
eTestFlagsEnum value = EnumUtils.GetFlagsAllValue<eTestFlagsEnum>();
|
||||
Assert.AreEqual(eTestFlagsEnum.None | eTestFlagsEnum.A | eTestFlagsEnum.B | eTestFlagsEnum.C | eTestFlagsEnum.D, value);
|
||||
Assert.AreEqual(eTestFlagsEnum.None | eTestFlagsEnum.A | eTestFlagsEnum.B | eTestFlagsEnum.C | eTestFlagsEnum.D,
|
||||
value);
|
||||
}
|
||||
|
||||
[Test]
|
||||
@@ -181,7 +196,8 @@ namespace ICD.Common.Utils.Tests
|
||||
public void HasFlagsGenericTest()
|
||||
{
|
||||
Assert.IsTrue(EnumUtils.HasFlags(eTestFlagsEnum.A | eTestFlagsEnum.B, eTestFlagsEnum.A | eTestFlagsEnum.B));
|
||||
Assert.IsFalse(EnumUtils.HasFlags(eTestFlagsEnum.A | eTestFlagsEnum.B, eTestFlagsEnum.A | eTestFlagsEnum.C));
|
||||
Assert.IsFalse(EnumUtils.HasFlags(eTestFlagsEnum.A | eTestFlagsEnum.B,
|
||||
eTestFlagsEnum.A | eTestFlagsEnum.C));
|
||||
}
|
||||
|
||||
[Test]
|
||||
@@ -200,28 +216,28 @@ namespace ICD.Common.Utils.Tests
|
||||
Assert.IsTrue(EnumUtils.HasMultipleFlags(eTestFlagsEnum.A | eTestFlagsEnum.B));
|
||||
}
|
||||
|
||||
[TestCase(false, eTestFlagsEnum.None)]
|
||||
[TestCase(true, eTestFlagsEnum.B)]
|
||||
[TestCase(true, eTestFlagsEnum.B | eTestFlagsEnum.C)]
|
||||
public void HasAnyFlagsTest(bool expected, eTestFlagsEnum value)
|
||||
{
|
||||
Assert.AreEqual(expected, EnumUtils.HasAnyFlags(value));
|
||||
}
|
||||
[TestCase(false, eTestFlagsEnum.None)]
|
||||
[TestCase(true, eTestFlagsEnum.B)]
|
||||
[TestCase(true, eTestFlagsEnum.B | eTestFlagsEnum.C)]
|
||||
public void HasAnyFlagsTest(bool expected, eTestFlagsEnum value)
|
||||
{
|
||||
Assert.AreEqual(expected, EnumUtils.HasAnyFlags(value));
|
||||
}
|
||||
|
||||
[TestCase(false, eTestFlagsEnum.None, eTestFlagsEnum.None)]
|
||||
[TestCase(false, eTestFlagsEnum.None, eTestFlagsEnum.B)]
|
||||
[TestCase(true, eTestFlagsEnum.B, eTestFlagsEnum.B)]
|
||||
[TestCase(false, eTestFlagsEnum.None | eTestFlagsEnum.A, eTestFlagsEnum.B | eTestFlagsEnum.C)]
|
||||
public void HasAnyFlagsValueTest(bool expected, eTestFlagsEnum value, eTestFlagsEnum other)
|
||||
{
|
||||
Assert.AreEqual(expected, EnumUtils.HasAnyFlags(value, other));
|
||||
}
|
||||
[TestCase(false, eTestFlagsEnum.None, eTestFlagsEnum.None)]
|
||||
[TestCase(false, eTestFlagsEnum.None, eTestFlagsEnum.B)]
|
||||
[TestCase(true, eTestFlagsEnum.B, eTestFlagsEnum.B)]
|
||||
[TestCase(false, eTestFlagsEnum.None | eTestFlagsEnum.A, eTestFlagsEnum.B | eTestFlagsEnum.C)]
|
||||
public void HasAnyFlagsValueTest(bool expected, eTestFlagsEnum value, eTestFlagsEnum other)
|
||||
{
|
||||
Assert.AreEqual(expected, EnumUtils.HasAnyFlags(value, other));
|
||||
}
|
||||
|
||||
#endregion
|
||||
#endregion
|
||||
|
||||
#region Conversion
|
||||
#region Conversion
|
||||
|
||||
[Test]
|
||||
[Test]
|
||||
public void ParseGenericTest()
|
||||
{
|
||||
Assert.AreEqual(eTestEnum.A, EnumUtils.Parse<eTestEnum>("A", false));
|
||||
@@ -243,35 +259,35 @@ namespace ICD.Common.Utils.Tests
|
||||
Assert.AreEqual(default(eTestEnum), output);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ParseStrictGenericTest()
|
||||
{
|
||||
Assert.AreEqual(eTestEnum.A, EnumUtils.ParseStrict<eTestEnum>("1", false));
|
||||
Assert.Throws<ArgumentOutOfRangeException>(() => EnumUtils.ParseStrict<eTestEnum>("4", false));
|
||||
[Test]
|
||||
public void ParseStrictGenericTest()
|
||||
{
|
||||
Assert.AreEqual(eTestEnum.A, EnumUtils.ParseStrict<eTestEnum>("1", false));
|
||||
Assert.Throws<ArgumentOutOfRangeException>(() => EnumUtils.ParseStrict<eTestEnum>("4", false));
|
||||
|
||||
Assert.AreEqual(eTestFlagsEnum.A | eTestFlagsEnum.B, EnumUtils.ParseStrict<eTestFlagsEnum>("3", false));
|
||||
Assert.Throws<ArgumentOutOfRangeException>(() => EnumUtils.ParseStrict<eTestFlagsEnum>("8", false));
|
||||
}
|
||||
Assert.AreEqual(eTestFlagsEnum.A | eTestFlagsEnum.B, EnumUtils.ParseStrict<eTestFlagsEnum>("3", false));
|
||||
Assert.Throws<ArgumentOutOfRangeException>(() => EnumUtils.ParseStrict<eTestFlagsEnum>("8", false));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TryParseStrictGenericTest()
|
||||
{
|
||||
eTestEnum outputA;
|
||||
[Test]
|
||||
public void TryParseStrictGenericTest()
|
||||
{
|
||||
eTestEnum outputA;
|
||||
|
||||
Assert.AreEqual(true, EnumUtils.TryParseStrict("1", false, out outputA));
|
||||
Assert.AreEqual(eTestEnum.A, outputA);
|
||||
Assert.AreEqual(true, EnumUtils.TryParseStrict("1", false, out outputA));
|
||||
Assert.AreEqual(eTestEnum.A, outputA);
|
||||
|
||||
Assert.AreEqual(false, EnumUtils.TryParseStrict("4", false, out outputA));
|
||||
Assert.AreEqual(eTestEnum.None, outputA);
|
||||
Assert.AreEqual(false, EnumUtils.TryParseStrict("4", false, out outputA));
|
||||
Assert.AreEqual(eTestEnum.None, outputA);
|
||||
|
||||
eTestFlagsEnum outputB;
|
||||
eTestFlagsEnum outputB;
|
||||
|
||||
Assert.AreEqual(true, EnumUtils.TryParseStrict("3", false, out outputB));
|
||||
Assert.AreEqual(eTestFlagsEnum.A | eTestFlagsEnum.B, outputB);
|
||||
Assert.AreEqual(true, EnumUtils.TryParseStrict("3", false, out outputB));
|
||||
Assert.AreEqual(eTestFlagsEnum.A | eTestFlagsEnum.B, outputB);
|
||||
|
||||
Assert.AreEqual(false, EnumUtils.TryParseStrict("8", false, out outputB));
|
||||
Assert.AreEqual(eTestFlagsEnum.None, outputB);
|
||||
}
|
||||
Assert.AreEqual(false, EnumUtils.TryParseStrict("8", false, out outputB));
|
||||
Assert.AreEqual(eTestFlagsEnum.None, outputB);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
@@ -3,16 +3,16 @@
|
||||
namespace ICD.Common.Utils.Tests.Extensions
|
||||
{
|
||||
[TestFixture]
|
||||
public sealed class DateTimeExtensionsTest
|
||||
{
|
||||
[Test]
|
||||
public static void ToShortTimeStringTest()
|
||||
{
|
||||
Assert.Inconclusive();
|
||||
}
|
||||
public sealed class DateTimeExtensionsTest
|
||||
{
|
||||
[Test]
|
||||
public void ToShortTimeStringTest()
|
||||
{
|
||||
Assert.Inconclusive();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public static void ToLongTimeStringWithMillisecondsTest()
|
||||
public void ToLongTimeStringWithMillisecondsTest()
|
||||
{
|
||||
Assert.Inconclusive();
|
||||
}
|
||||
|
||||
@@ -284,6 +284,15 @@ namespace ICD.Common.Utils.Tests.Extensions
|
||||
Assert.AreEqual(5, items.Length);
|
||||
}
|
||||
|
||||
[TestCase(true)]
|
||||
[TestCase(true, 1, 2, 3, 4)]
|
||||
[TestCase(true, 1, 2, 2, 3, 4)]
|
||||
[TestCase(false, 4, 3, 2, 1)]
|
||||
public void AreOrderedTest(bool expected, params int[] items)
|
||||
{
|
||||
Assert.AreEqual(expected, items.AreOrdered());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void OrderTest()
|
||||
{
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using ICD.Common.Utils.Extensions;
|
||||
using NUnit.Framework;
|
||||
|
||||
@@ -9,14 +8,14 @@ namespace ICD.Common.Utils.Tests.Extensions
|
||||
public sealed class ListExtensionsTest
|
||||
{
|
||||
[Test]
|
||||
public void AddSortedTest()
|
||||
public void InsertSortedTest()
|
||||
{
|
||||
List<int> testList = new List<int>();
|
||||
|
||||
Assert.AreEqual(0, testList.AddSorted(2));
|
||||
Assert.AreEqual(1, testList.AddSorted(3));
|
||||
Assert.AreEqual(0, testList.AddSorted(1));
|
||||
Assert.AreEqual(1, testList.AddSorted(2));
|
||||
Assert.AreEqual(0, testList.InsertSorted(2));
|
||||
Assert.AreEqual(1, testList.InsertSorted(3));
|
||||
Assert.AreEqual(0, testList.InsertSorted(1));
|
||||
Assert.AreEqual(1, testList.InsertSorted(2));
|
||||
|
||||
Assert.AreEqual(4, testList.Count);
|
||||
Assert.AreEqual(1, testList[0]);
|
||||
@@ -26,15 +25,15 @@ namespace ICD.Common.Utils.Tests.Extensions
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void AddSortedComparerTest()
|
||||
public void InsertSortedComparerTest()
|
||||
{
|
||||
List<int> testList = new List<int>();
|
||||
IComparer<int> comparer = new InverseComparer();
|
||||
|
||||
Assert.AreEqual(0, testList.AddSorted(2, comparer));
|
||||
Assert.AreEqual(0, testList.AddSorted(3, comparer));
|
||||
Assert.AreEqual(2, testList.AddSorted(1, comparer));
|
||||
Assert.AreEqual(1, testList.AddSorted(2, comparer));
|
||||
Assert.AreEqual(0, testList.InsertSorted(2, comparer));
|
||||
Assert.AreEqual(0, testList.InsertSorted(3, comparer));
|
||||
Assert.AreEqual(2, testList.InsertSorted(1, comparer));
|
||||
Assert.AreEqual(1, testList.InsertSorted(2, comparer));
|
||||
|
||||
Assert.AreEqual(4, testList.Count);
|
||||
Assert.AreEqual(3, testList[0]);
|
||||
@@ -43,82 +42,6 @@ namespace ICD.Common.Utils.Tests.Extensions
|
||||
Assert.AreEqual(1, testList[3]);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void PadRightTest()
|
||||
{
|
||||
List<int> testList = new List<int>();
|
||||
testList.PadRight(10);
|
||||
|
||||
Assert.AreEqual(10, testList.Count);
|
||||
Assert.AreEqual(0, testList.Sum());
|
||||
|
||||
testList = new List<int>
|
||||
{
|
||||
1,
|
||||
2,
|
||||
3,
|
||||
4,
|
||||
5
|
||||
};
|
||||
|
||||
testList.PadRight(10);
|
||||
|
||||
Assert.AreEqual(10, testList.Count);
|
||||
Assert.AreEqual(15, testList.Sum());
|
||||
|
||||
testList = new List<int>
|
||||
{
|
||||
1,
|
||||
2,
|
||||
3,
|
||||
4,
|
||||
5
|
||||
};
|
||||
|
||||
testList.PadRight(1);
|
||||
|
||||
Assert.AreEqual(5, testList.Count);
|
||||
Assert.AreEqual(15, testList.Sum());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void PadRightDefaultTest()
|
||||
{
|
||||
List<int> testList = new List<int>();
|
||||
testList.PadRight(10, 1);
|
||||
|
||||
Assert.AreEqual(10, testList.Count);
|
||||
Assert.AreEqual(10, testList.Sum());
|
||||
|
||||
testList = new List<int>
|
||||
{
|
||||
1,
|
||||
2,
|
||||
3,
|
||||
4,
|
||||
5
|
||||
};
|
||||
|
||||
testList.PadRight(10, 1);
|
||||
|
||||
Assert.AreEqual(10, testList.Count);
|
||||
Assert.AreEqual(20, testList.Sum());
|
||||
|
||||
testList = new List<int>
|
||||
{
|
||||
1,
|
||||
2,
|
||||
3,
|
||||
4,
|
||||
5
|
||||
};
|
||||
|
||||
testList.PadRight(1, 1);
|
||||
|
||||
Assert.AreEqual(5, testList.Count);
|
||||
Assert.AreEqual(15, testList.Sum());
|
||||
}
|
||||
|
||||
private sealed class InverseComparer : IComparer<int>
|
||||
{
|
||||
public int Compare(int x, int y)
|
||||
|
||||
43
ICD.Common.Utils.Tests/Extensions/TimeSpanExtensionsTest.cs
Normal file
43
ICD.Common.Utils.Tests/Extensions/TimeSpanExtensionsTest.cs
Normal file
@@ -0,0 +1,43 @@
|
||||
using System;
|
||||
using ICD.Common.Utils.Extensions;
|
||||
using NUnit.Framework;
|
||||
|
||||
namespace ICD.Common.Utils.Tests.Extensions
|
||||
{
|
||||
[TestFixture]
|
||||
public sealed class TimeSpanExtensionsTest
|
||||
{
|
||||
[Test]
|
||||
public void ToReadableStringTest()
|
||||
{
|
||||
Assert.Inconclusive();
|
||||
}
|
||||
|
||||
[TestCase(0, 0, 0)]
|
||||
[TestCase(12, 1, 13)]
|
||||
[TestCase(23, 1, 0)]
|
||||
[TestCase(6, -12, 18)]
|
||||
public void AddHoursAndWrapTest(int hours, int addHours, int expectedHours)
|
||||
{
|
||||
Assert.AreEqual(expectedHours, new TimeSpan(hours, 0, 0).AddHoursAndWrap(addHours).Hours);
|
||||
}
|
||||
|
||||
[TestCase(0, 0, 0)]
|
||||
[TestCase(12, 1, 13)]
|
||||
[TestCase(23, 1, 12)]
|
||||
[TestCase(6, -12, 6)]
|
||||
public void AddHoursAndWrap12Hour(int hours, int addHours, int expectedHours)
|
||||
{
|
||||
Assert.AreEqual(expectedHours, new TimeSpan(hours, 0, 0).AddHoursAndWrap12Hour(addHours).Hours);
|
||||
}
|
||||
|
||||
[TestCase(0, 0, 0)]
|
||||
[TestCase(30, 1, 31)]
|
||||
[TestCase(59, 1, 0)]
|
||||
[TestCase(30, -60, 30)]
|
||||
public void AddMinutesAndWrap(int minutes, int addMinutes, int expectedMinutes)
|
||||
{
|
||||
Assert.AreEqual(expectedMinutes, new TimeSpan(0, minutes, 0).AddMinutesAndWrap(addMinutes).Minutes);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -20,9 +20,15 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.0.1" />
|
||||
<PackageReference Include="NUnit" Version="3.11.0" />
|
||||
<PackageReference Include="NUnit3TestAdapter" Version="3.13.0" />
|
||||
<Compile Remove="binNetCoreApp\**" />
|
||||
<EmbeddedResource Remove="binNetCoreApp\**" />
|
||||
<None Remove="binNetCoreApp\**" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.2.0" />
|
||||
<PackageReference Include="NUnit" Version="3.12.0" />
|
||||
<PackageReference Include="NUnit3TestAdapter" Version="3.15.1" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@@ -37,10 +37,11 @@ namespace ICD.Common.Utils.Tests
|
||||
Assert.AreEqual(port, new IcdUriBuilder {Port = port}.Port);
|
||||
}
|
||||
|
||||
[TestCase("test")]
|
||||
public void QueryTest(string query)
|
||||
[TestCase("?test", "test")]
|
||||
[TestCase("??test", "?test")]
|
||||
public void QueryTest(string expected, string query)
|
||||
{
|
||||
Assert.AreEqual(query, new IcdUriBuilder {Query = query}.Query);
|
||||
Assert.AreEqual(expected, new IcdUriBuilder {Query = query}.Query);
|
||||
}
|
||||
|
||||
[TestCase("test")]
|
||||
@@ -72,6 +73,8 @@ namespace ICD.Common.Utils.Tests
|
||||
[TestCase("http://localhost/test", null, "localhost", null, "test", (ushort)0, null, "http", null)]
|
||||
[TestCase("http://localhost/test", null, "localhost", null, "/test", (ushort)0, null, "http", null)]
|
||||
[TestCase("http://localhost//test", null, "localhost", null, "//test", (ushort)0, null, "http", null)]
|
||||
[TestCase("http://localhost/test?a=b", null, "localhost", null, "/test", (ushort)0, "a=b", "http", null)]
|
||||
[TestCase("http://localhost/test??a=b", null, "localhost", null, "/test", (ushort)0, "?a=b", "http", null)]
|
||||
public void ToStringTest(string expected, string fragment, string address, string password, string path, ushort port,
|
||||
string query, string scheme, string userName)
|
||||
{
|
||||
|
||||
41
ICD.Common.Utils.Tests/Json/DateTimeIsoConverterTest.cs
Normal file
41
ICD.Common.Utils.Tests/Json/DateTimeIsoConverterTest.cs
Normal file
@@ -0,0 +1,41 @@
|
||||
using System;
|
||||
using ICD.Common.Utils.Json;
|
||||
using Newtonsoft.Json;
|
||||
using NUnit.Framework;
|
||||
|
||||
namespace ICD.Common.Utils.Tests.Json
|
||||
{
|
||||
[TestFixture]
|
||||
public sealed class DateTimeIsoConverterTest : AbstractGenericJsonConverterTest
|
||||
{
|
||||
[Test]
|
||||
public override void WriteJsonTest()
|
||||
{
|
||||
JsonSerializerSettings settings = new JsonSerializerSettings
|
||||
{
|
||||
DateParseHandling = DateParseHandling.None
|
||||
};
|
||||
settings.Converters.Add(new DateTimeIsoConverter());
|
||||
|
||||
DateTime dateTime = new DateTime(2020, 1, 2, 3, 4, 5, DateTimeKind.Utc);
|
||||
string serial = JsonConvert.SerializeObject(dateTime, settings);
|
||||
|
||||
Assert.AreEqual("\"2020-01-02T03:04:05Z\"", serial);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public override void ReadJsonTest()
|
||||
{
|
||||
JsonSerializerSettings settings = new JsonSerializerSettings
|
||||
{
|
||||
DateParseHandling = DateParseHandling.None
|
||||
};
|
||||
settings.Converters.Add(new DateTimeIsoConverter());
|
||||
|
||||
string serial = "\"2020-01-02T03:04:05Z\"";
|
||||
DateTime dateTime = JsonConvert.DeserializeObject<DateTime>(serial, settings);
|
||||
|
||||
Assert.AreEqual(new DateTime(2020, 1, 2, 3, 4, 5, DateTimeKind.Utc), dateTime);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using ICD.Common.Utils.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using Newtonsoft.Json;
|
||||
using NUnit.Framework;
|
||||
|
||||
namespace ICD.Common.Utils.Tests.Json
|
||||
@@ -14,7 +14,7 @@ namespace ICD.Common.Utils.Tests.Json
|
||||
[TestCase(1, typeof(int))]
|
||||
public void ItemTypeTest(object item, Type expected)
|
||||
{
|
||||
Assert.AreEqual(expected, new JsonItemWrapper(item).ItemType);
|
||||
Assert.AreEqual(expected, new JsonItemWrapper(item).Type);
|
||||
}
|
||||
|
||||
[TestCase("")]
|
||||
@@ -27,19 +27,21 @@ namespace ICD.Common.Utils.Tests.Json
|
||||
[Test]
|
||||
public void WriteTest()
|
||||
{
|
||||
JsonItemWrapper wrapper = new JsonItemWrapper(new List<int> {1, 2, 3});
|
||||
string json = JsonUtils.Serialize(wrapper.Write);
|
||||
const string expected = @"{""t"":""System.Collections.Generic.List`1[[System.Int32]]"",""i"":[1,2,3]}";
|
||||
|
||||
Assert.Inconclusive();
|
||||
JsonItemWrapper wrapper = new JsonItemWrapper(new List<int> {1, 2, 3});
|
||||
string json = JsonConvert.SerializeObject(wrapper);
|
||||
|
||||
Assert.AreEqual(expected, json);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ReadTest()
|
||||
{
|
||||
const string json = "{\"t\":\"System.Collections.Generic.List`1[[System.Int32, System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]]\",\"i\":\"[1,2,3]\"}";
|
||||
const string json = @"{""t"":""System.Collections.Generic.List`1[[System.Int32]]"",""i"":[1,2,3]}";
|
||||
|
||||
JObject jObject = JObject.Parse(json);
|
||||
List<int> wrappedObject = JsonItemWrapper.ReadToObject(jObject) as List<int>;
|
||||
JsonItemWrapper wrapper = JsonConvert.DeserializeObject<JsonItemWrapper>(json);
|
||||
List<int> wrappedObject = wrapper.Item as List<int>;
|
||||
|
||||
Assert.NotNull(wrappedObject);
|
||||
Assert.AreEqual(3, wrappedObject.Count);
|
||||
|
||||
@@ -10,29 +10,7 @@ namespace ICD.Common.Utils.Tests.Json
|
||||
public sealed class JsonUtilsTest
|
||||
{
|
||||
[Test]
|
||||
public void CacheTypeTest()
|
||||
{
|
||||
Assert.Inconclusive();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ParseDateTimeTest()
|
||||
{
|
||||
const string dataA = "2016-02-26T19:24:59";
|
||||
const string dataB = "2019-04-01T12:41:15-04:00";
|
||||
|
||||
Assert.DoesNotThrow(() => JsonUtils.ParseDateTime(dataA));
|
||||
Assert.DoesNotThrow(() => JsonUtils.ParseDateTime(dataB));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TryParseDateTimeTest()
|
||||
{
|
||||
Assert.Inconclusive();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void PrintTest()
|
||||
public void FormatTest()
|
||||
{
|
||||
Assert.Inconclusive();
|
||||
}
|
||||
|
||||
@@ -1,14 +1,13 @@
|
||||
using NUnit.Framework;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using ICD.Common.Properties;
|
||||
|
||||
namespace ICD.Common.Utils.Tests
|
||||
{
|
||||
[TestFixture, UsedImplicitly]
|
||||
[TestFixture]
|
||||
public sealed class MathUtilsTest
|
||||
{
|
||||
[Test, UsedImplicitly]
|
||||
[Test]
|
||||
public void ClampTest()
|
||||
{
|
||||
Assert.AreEqual(MathUtils.Clamp(-10, 0, 0), 0);
|
||||
@@ -24,9 +23,13 @@ namespace ICD.Common.Utils.Tests
|
||||
Assert.AreEqual(MathUtils.Clamp(20, 10, 10), 10);
|
||||
}
|
||||
|
||||
[Test, UsedImplicitly]
|
||||
[Test]
|
||||
public void MapRangeTest()
|
||||
{
|
||||
Assert.AreEqual(5, MathUtils.MapRange(-100, 100, 0, 10, 0));
|
||||
Assert.AreEqual(7, MathUtils.MapRange(-100, 100, 0, 10, 50));
|
||||
Assert.AreEqual(10, MathUtils.MapRange(-100, 100, 0, 10, 100));
|
||||
|
||||
Assert.AreEqual(0, MathUtils.MapRange(0, 100, 0, 10, 0));
|
||||
Assert.AreEqual(5, MathUtils.MapRange(0, 100, 0, 10, 50));
|
||||
Assert.AreEqual(10, MathUtils.MapRange(0, 100, 0, 10, 100));
|
||||
@@ -36,7 +39,7 @@ namespace ICD.Common.Utils.Tests
|
||||
Assert.AreEqual(100, MathUtils.MapRange(0, 10, 0, 100, 10));
|
||||
}
|
||||
|
||||
[Test, UsedImplicitly]
|
||||
[Test]
|
||||
public void GetRangesTest()
|
||||
{
|
||||
IEnumerable<int> values = new [] { 1, 3, 5, 6, 7, 8, 9, 10, 12 };
|
||||
@@ -57,11 +60,21 @@ namespace ICD.Common.Utils.Tests
|
||||
Assert.AreEqual(12, ranges[3][1]);
|
||||
}
|
||||
|
||||
[Test, UsedImplicitly]
|
||||
[Test]
|
||||
public void RoundToNearestTest()
|
||||
{
|
||||
IEnumerable<int> values = new [] { 0, 15, 30, 45 };
|
||||
Assert.AreEqual(15, MathUtils.RoundToNearest(21, values));
|
||||
}
|
||||
|
||||
[TestCase(10, 10, 0)]
|
||||
[TestCase(-10, 10, 0)]
|
||||
[TestCase(9, 3, 0)]
|
||||
[TestCase(3, 2, 1)]
|
||||
[TestCase(-3, 2, 1)]
|
||||
public void ModulusTest(int value, int mod, int expected)
|
||||
{
|
||||
Assert.AreEqual(expected, MathUtils.Modulus(value, mod));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -127,6 +127,24 @@ namespace ICD.Common.Utils.Tests
|
||||
Assert.IsTrue(clique.Contains(6));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GetCliqueSingleNodeTest()
|
||||
{
|
||||
int[] clique = RecursionUtils.GetClique(1, n => s_CliqueGraph[n]).ToArray();
|
||||
|
||||
Assert.AreEqual(4, clique.Length);
|
||||
Assert.IsTrue(clique.Contains(1));
|
||||
Assert.IsTrue(clique.Contains(2));
|
||||
Assert.IsTrue(clique.Contains(3));
|
||||
Assert.IsTrue(clique.Contains(4));
|
||||
|
||||
clique = RecursionUtils.GetClique(5, n => s_CliqueGraph[n]).ToArray();
|
||||
|
||||
Assert.AreEqual(2, clique.Length);
|
||||
Assert.IsTrue(clique.Contains(5));
|
||||
Assert.IsTrue(clique.Contains(6));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void BreadthFirstSearchTest()
|
||||
{
|
||||
|
||||
@@ -12,7 +12,7 @@ namespace ICD.Common.Utils.Tests.Services.Logging
|
||||
public void TimestampTest()
|
||||
{
|
||||
LogItem item = new LogItem(eSeverity.Critical, null);
|
||||
DateTime time = IcdEnvironment.GetLocalTime();
|
||||
DateTime time = IcdEnvironment.GetUtcTime();
|
||||
|
||||
Assert.IsTrue((time - item.Timestamp).TotalSeconds <= 1);
|
||||
}
|
||||
|
||||
@@ -24,11 +24,18 @@ namespace ICD.Common.Utils.Tests
|
||||
Assert.AreEqual("\x08\x22\x00\x00\x00\x02", output);
|
||||
}
|
||||
|
||||
[Test, UsedImplicitly]
|
||||
public void NiceNameTest()
|
||||
[TestCase("Test", "Test")]
|
||||
[TestCase("test", "Test")]
|
||||
[TestCase("TodayILiveInTheUSAWithSimon", "Today I Live In The USA With Simon")]
|
||||
[TestCase("CONST_VALUE", "CONST VALUE")]
|
||||
[TestCase("m_PrivateMember", "Private Member")]
|
||||
[TestCase("variableName", "Variable Name")]
|
||||
[TestCase("Comma, Delimited", "Comma, Delimited")]
|
||||
[TestCase("Comma,Delimited", "Comma, Delimited")]
|
||||
public void NiceNameTest(string input, string expected)
|
||||
{
|
||||
string output = StringUtils.NiceName("TodayILiveInTheUSAWithSimon");
|
||||
Assert.AreEqual("Today I Live In The USA With Simon", output);
|
||||
string output = StringUtils.NiceName(input);
|
||||
Assert.AreEqual(expected, output);
|
||||
}
|
||||
|
||||
[Test, UsedImplicitly]
|
||||
|
||||
@@ -13,7 +13,7 @@ namespace ICD.Common.Utils.Tests
|
||||
Assert.IsTrue(ThreadingUtils.Wait(() => true, 100));
|
||||
|
||||
bool complete = false;
|
||||
DateTime time = IcdEnvironment.GetLocalTime();
|
||||
DateTime time = IcdEnvironment.GetUtcTime();
|
||||
|
||||
ThreadingUtils.SafeInvoke(() =>
|
||||
{
|
||||
@@ -22,15 +22,15 @@ namespace ICD.Common.Utils.Tests
|
||||
});
|
||||
|
||||
Assert.IsTrue(ThreadingUtils.Wait(() => complete, 200));
|
||||
Assert.AreEqual(100, (IcdEnvironment.GetLocalTime() - time).TotalMilliseconds, 20);
|
||||
Assert.AreEqual(100, (IcdEnvironment.GetUtcTime() - time).TotalMilliseconds, 20);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Sleep()
|
||||
{
|
||||
DateTime now = IcdEnvironment.GetLocalTime();
|
||||
DateTime now = IcdEnvironment.GetUtcTime();
|
||||
ThreadingUtils.Sleep(1000);
|
||||
DateTime now2 = IcdEnvironment.GetLocalTime();
|
||||
DateTime now2 = IcdEnvironment.GetUtcTime();
|
||||
|
||||
Assert.AreEqual(1000, (now2 - now).TotalMilliseconds, 100);
|
||||
}
|
||||
|
||||
17
ICD.Common.Utils.Tests/Timers/IcdStopwatchTest.cs
Normal file
17
ICD.Common.Utils.Tests/Timers/IcdStopwatchTest.cs
Normal file
@@ -0,0 +1,17 @@
|
||||
using ICD.Common.Utils.Timers;
|
||||
using NUnit.Framework;
|
||||
|
||||
namespace ICD.Common.Utils.Tests.Timers
|
||||
{
|
||||
[TestFixture]
|
||||
public sealed class IcdStopwatchTest
|
||||
{
|
||||
[Test]
|
||||
public void ConstructorTest()
|
||||
{
|
||||
var stopwatch = new IcdStopwatch();
|
||||
ThreadingUtils.Sleep(100);
|
||||
Assert.AreEqual(0, stopwatch.ElapsedMilliseconds);
|
||||
}
|
||||
}
|
||||
}
|
||||
35
ICD.Common.Utils.Tests/Xml/IcdXmlConvertTest.cs
Normal file
35
ICD.Common.Utils.Tests/Xml/IcdXmlConvertTest.cs
Normal file
@@ -0,0 +1,35 @@
|
||||
using System.Linq;
|
||||
using ICD.Common.Utils.Xml;
|
||||
using NUnit.Framework;
|
||||
|
||||
namespace ICD.Common.Utils.Tests.Xml
|
||||
{
|
||||
[TestFixture]
|
||||
public sealed class IcdXmlConvertTest
|
||||
{
|
||||
[Test]
|
||||
public void DeserializeArrayGenericTest()
|
||||
{
|
||||
const string xml = @"<A>
|
||||
<B>1</B>
|
||||
<B>2</B>
|
||||
</A>";
|
||||
|
||||
using (IcdXmlReader reader = new IcdXmlReader(xml))
|
||||
{
|
||||
// Read to the first element
|
||||
reader.Read();
|
||||
|
||||
int[] values = IcdXmlConvert.DeserializeArray<int>(reader).ToArray();
|
||||
|
||||
Assert.AreEqual(new[] {1, 2}, values);
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void DeserializeArrayTest()
|
||||
{
|
||||
Assert.Inconclusive();
|
||||
}
|
||||
}
|
||||
}
|
||||
183
ICD.Common.Utils/AnsiUtils.cs
Normal file
183
ICD.Common.Utils/AnsiUtils.cs
Normal file
@@ -0,0 +1,183 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace ICD.Common.Utils
|
||||
{
|
||||
public static class AnsiUtils
|
||||
{
|
||||
public const string COLOR_RED = "\x1b[31;1m";
|
||||
public const string COLOR_GREEN = "\x1b[32;1m";
|
||||
public const string COLOR_YELLOW = "\x1b[33;1m";
|
||||
public const string COLOR_BLUE = "\x1b[34;1m";
|
||||
public const string COLOR_MAGENTA = "\x1b[35;1m";
|
||||
public const string COLOR_CYAN = "\x1b[36;1m";
|
||||
public const string COLOR_WHITE = "\x1b[37;1m";
|
||||
public const string COLOR_YELLOW_ON_RED_BACKGROUND = "\x1b[93;41m";
|
||||
public const string ANSI_RESET = "\x1b[0m";
|
||||
|
||||
public const string CODE_BLACK = "30";
|
||||
public const string CODE_RED = "31";
|
||||
public const string CODE_GREEN = "32";
|
||||
public const string CODE_YELLOW = "33";
|
||||
public const string CODE_BLUE = "34";
|
||||
public const string CODE_MAGENTA = "35";
|
||||
public const string CODE_CYAN = "36";
|
||||
public const string CODE_WHITE = "37";
|
||||
|
||||
public const string CODE_BRIGHT_BLACK = "30;1";
|
||||
public const string CODE_BRIGHT_RED = "31;1";
|
||||
public const string CODE_BRIGHT_GREEN = "32;1";
|
||||
public const string CODE_BRIGHT_YELLOW = "33;1";
|
||||
public const string CODE_BRIGHT_BLUE = "34;1";
|
||||
public const string CODE_BRIGHT_MAGENTA = "35;1";
|
||||
public const string CODE_BRIGHT_CYAN = "36;1";
|
||||
public const string CODE_BRIGHT_WHITE = "37;1";
|
||||
|
||||
/// <summary>
|
||||
/// Matches ANSI escape codes, e.g. \x1b[31m and \x1b[30;1m
|
||||
/// </summary>
|
||||
public const string ANSI_REGEX = "(?'match'\x01b\\[(?'code'[\\d;]+)m)";
|
||||
|
||||
/// <summary>
|
||||
/// Matches ANSI escape codes to HTML styles.
|
||||
/// Color values are taken from PuTTY.
|
||||
/// </summary>
|
||||
private static readonly Dictionary<string, string> s_PuttyColors =
|
||||
new Dictionary<string, string>
|
||||
{
|
||||
{CODE_BLACK, "#000000"},
|
||||
{CODE_RED, "#BB0000"},
|
||||
{CODE_GREEN, "#00BB00"},
|
||||
{CODE_YELLOW, "#BBBB00"},
|
||||
{CODE_BLUE, "#0000BB"},
|
||||
{CODE_MAGENTA, "#BB00BB"},
|
||||
{CODE_CYAN, "#00BBBB"},
|
||||
{CODE_WHITE, "#BBBBBB"},
|
||||
|
||||
{CODE_BRIGHT_BLACK, "#555555"},
|
||||
{CODE_BRIGHT_RED, "#FF5555"},
|
||||
{CODE_BRIGHT_GREEN, "#55FF55"},
|
||||
{CODE_BRIGHT_YELLOW, "#FFFF55"},
|
||||
{CODE_BRIGHT_BLUE, "#5555FF"},
|
||||
{CODE_BRIGHT_MAGENTA, "#FF55FF"},
|
||||
{CODE_BRIGHT_CYAN, "#55FFFF"},
|
||||
{CODE_BRIGHT_WHITE, "#FFFFFF"}
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Gets the color map matching PuTTY.
|
||||
/// </summary>
|
||||
public static IDictionary<string, string> PuttyColors { get { return s_PuttyColors; } }
|
||||
|
||||
/// <summary>
|
||||
/// Constructor.
|
||||
/// </summary>
|
||||
static AnsiUtils()
|
||||
{
|
||||
#if !SIMPLSHARP
|
||||
// Enables ANSI color output in windows/linux console
|
||||
Pastel.ConsoleExtensions.Enable();
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Prefixes the given data with an ANSI control sequence and suffixes with a reset sequence.
|
||||
/// </summary>
|
||||
/// <param name="data"></param>
|
||||
/// <param name="ansiSequence"></param>
|
||||
/// <returns></returns>
|
||||
public static string Format(string data, string ansiSequence)
|
||||
{
|
||||
// % needs to be escaped or weird things happen
|
||||
data = string.IsNullOrEmpty(data) ? data : data.Replace("%", "%%");
|
||||
|
||||
return string.Format("{0}{1}{2}", ansiSequence, data, ANSI_RESET);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Splits the given ANSI string into spans.
|
||||
/// </summary>
|
||||
/// <param name="data"></param>
|
||||
/// <returns></returns>
|
||||
public static IEnumerable<AnsiSpan> ToSpans(string data)
|
||||
{
|
||||
if (string.IsNullOrEmpty(data))
|
||||
yield break;
|
||||
|
||||
Regex regex = new Regex(ANSI_REGEX);
|
||||
Match match = regex.Match(data);
|
||||
|
||||
// No matches
|
||||
if (!match.Success)
|
||||
yield return new AnsiSpan {Text = data};
|
||||
|
||||
// Find the spans
|
||||
while (match.Success)
|
||||
{
|
||||
// Get the code
|
||||
string code = match.Groups["code"].Value;
|
||||
|
||||
// Get the text
|
||||
Match next = match.NextMatch();
|
||||
int startIndex = match.Index + match.Length;
|
||||
int endIndex = next.Success ? next.Index : data.Length;
|
||||
string text = data.Substring(startIndex, endIndex - startIndex);
|
||||
|
||||
// Build the span
|
||||
if (text.Length > 0)
|
||||
yield return new AnsiSpan { Code = code, Text = text };
|
||||
|
||||
// Loop
|
||||
match = next;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes the bright suffix from the code if present, otherwise appends a bright suffix.
|
||||
/// </summary>
|
||||
/// <param name="code"></param>
|
||||
/// <returns></returns>
|
||||
public static string InvertBright(string code)
|
||||
{
|
||||
return code.EndsWith(";1")
|
||||
? code.Substring(0, code.Length - 2)
|
||||
: code + ";1";
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class AnsiSpan
|
||||
{
|
||||
public string Code { get; set; }
|
||||
public string Text { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the color value for the code.
|
||||
/// </summary>
|
||||
/// <param name="colors"></param>
|
||||
/// <param name="invertBright"></param>
|
||||
/// <returns></returns>
|
||||
public string GetColor(IDictionary<string, string> colors, bool invertBright)
|
||||
{
|
||||
if (colors == null)
|
||||
throw new ArgumentNullException("colors");
|
||||
|
||||
return GetColor<string>(colors, invertBright);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the color value for the code.
|
||||
/// </summary>
|
||||
/// <param name="colors"></param>
|
||||
/// <param name="invertBright"></param>
|
||||
/// <returns></returns>
|
||||
public T GetColor<T>(IDictionary<string, T> colors, bool invertBright)
|
||||
{
|
||||
if (colors == null)
|
||||
throw new ArgumentNullException("colors");
|
||||
|
||||
string code = invertBright ? AnsiUtils.InvertBright(Code) : Code;
|
||||
return colors[code];
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -42,13 +42,42 @@ namespace ICD.Common.Utils
|
||||
if (type == null)
|
||||
throw new ArgumentNullException("type");
|
||||
|
||||
// ReSharper disable InvokeAsExtensionMethod
|
||||
return GetClassAttributes<T>(type, inherit).FirstOrDefault();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the attributes on the given class type matching the generic type.
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="type"></param>
|
||||
/// <returns></returns>
|
||||
public static IEnumerable<T> GetClassAttributes<T>(Type type)
|
||||
{
|
||||
if (type == null)
|
||||
throw new ArgumentNullException("type");
|
||||
|
||||
return GetClassAttributes<T>(type, false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the attributes on the given class type matching the generic type.
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="type"></param>
|
||||
/// <param name="inherit"></param>
|
||||
/// <returns></returns>
|
||||
public static IEnumerable<T> GetClassAttributes<T>(Type type, bool inherit)
|
||||
{
|
||||
if (type == null)
|
||||
throw new ArgumentNullException("type");
|
||||
|
||||
// ReSharper disable InvokeAsExtensionMethod
|
||||
return ReflectionExtensions.GetCustomAttributes<T>(
|
||||
#if SIMPLSHARP
|
||||
(CType)
|
||||
(CType)
|
||||
#endif
|
||||
type, inherit).FirstOrDefault();
|
||||
// ReSharper restore InvokeAsExtensionMethod
|
||||
type, inherit);
|
||||
// ReSharper restore InvokeAsExtensionMethod
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -5,7 +5,7 @@ namespace ICD.Common.Utils.Attributes
|
||||
/// <summary>
|
||||
/// AbstractIcdAttribute is the base class for all ICD attributes.
|
||||
/// </summary>
|
||||
public abstract class AbstractIcdAttribute : Attribute
|
||||
public abstract class AbstractIcdAttribute : Attribute, IIcdAttribute
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
6
ICD.Common.Utils/Attributes/IIcdAttribute.cs
Normal file
6
ICD.Common.Utils/Attributes/IIcdAttribute.cs
Normal file
@@ -0,0 +1,6 @@
|
||||
namespace ICD.Common.Utils.Attributes
|
||||
{
|
||||
public interface IIcdAttribute
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,8 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using ICD.Common.Properties;
|
||||
using ICD.Common.Utils.Extensions;
|
||||
|
||||
namespace ICD.Common.Utils.Attributes
|
||||
{
|
||||
@@ -9,90 +12,274 @@ namespace ICD.Common.Utils.Attributes
|
||||
[AttributeUsage(AttributeTargets.Property |
|
||||
AttributeTargets.Field |
|
||||
AttributeTargets.Parameter |
|
||||
AttributeTargets.ReturnValue,
|
||||
AllowMultiple = false,
|
||||
Inherited = true)]
|
||||
AttributeTargets.ReturnValue)]
|
||||
public sealed class RangeAttribute : AbstractIcdAttribute
|
||||
{
|
||||
/// <summary>
|
||||
/// Remaps from the source numeric min/max to double min/max.
|
||||
/// </summary>
|
||||
private static readonly Dictionary<Type, Func<double, double>> s_Clamp =
|
||||
new Dictionary<Type, Func<double, double>>
|
||||
{
|
||||
// Duh
|
||||
{typeof(double), o => o},
|
||||
|
||||
// Signed
|
||||
{typeof(short), o => o < short.MinValue ? short.MinValue : o > short.MaxValue ? short.MaxValue : o},
|
||||
{typeof(int), o => o < int.MinValue ? int.MinValue : o > int.MaxValue ? int.MaxValue : o},
|
||||
{typeof(long), o => o < long.MinValue ? long.MinValue : o > long.MaxValue ? long.MaxValue : o},
|
||||
{typeof(float),o => o < float.MinValue ? float.MinValue : o > float.MaxValue ? float.MaxValue : o},
|
||||
{typeof(decimal), o => o < (double)decimal.MinValue ? (double)decimal.MinValue : o > (double)decimal.MaxValue ? (double)decimal.MaxValue : o},
|
||||
|
||||
// Unsigned
|
||||
{typeof(ushort), o => o < ushort.MinValue ? ushort.MinValue : o > ushort.MaxValue ? ushort.MaxValue : o},
|
||||
{typeof(uint), o => o < uint.MinValue ? uint.MinValue : o > uint.MaxValue ? uint.MaxValue : o},
|
||||
{typeof(ulong), o => o < ulong.MinValue ? ulong.MinValue : o > ulong.MaxValue ? ulong.MaxValue : o},
|
||||
{typeof(byte), o => o < byte.MinValue ? byte.MinValue : o > byte.MaxValue ? byte.MaxValue : o}
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Remaps from the source numeric min/max to double min/max.
|
||||
/// </summary>
|
||||
private static readonly Dictionary<Type, Func<object, double>> s_RemapToDouble =
|
||||
new Dictionary<Type, Func<object, double>>
|
||||
{
|
||||
// Duh
|
||||
{ typeof(double), o => (double)o},
|
||||
|
||||
// Signed - Clamping prevents an overflow due to loss of precision
|
||||
{ typeof(short), o => MathUtils.Clamp(Convert.ToDouble(o) / short.MaxValue, -1, 1) * double.MaxValue},
|
||||
{ typeof(int), o => MathUtils.Clamp(Convert.ToDouble(o) / int.MaxValue, -1, 1) * double.MaxValue},
|
||||
{ typeof(long), o => MathUtils.Clamp(Convert.ToDouble(o) / long.MaxValue, -1, 1) * double.MaxValue},
|
||||
{ typeof(float), o => MathUtils.Clamp(Convert.ToDouble(o) / float.MaxValue, -1, 1) * double.MaxValue},
|
||||
{ typeof(decimal), o => MathUtils.Clamp(Convert.ToDouble(o) / (double)decimal.MaxValue, -1, 1) * double.MaxValue},
|
||||
|
||||
// Unsigned
|
||||
{ typeof(ushort), o => MathUtils.Clamp((Convert.ToDouble(o) / ushort.MaxValue - 0.5) * 2, -1, 1) * double.MaxValue},
|
||||
{ typeof(uint), o => MathUtils.Clamp((Convert.ToDouble(o) / uint.MaxValue - 0.5) * 2, -1, 1) * double.MaxValue},
|
||||
{ typeof(ulong), o => MathUtils.Clamp((Convert.ToDouble(o) / ulong.MaxValue - 0.5) * 2, -1, 1) * double.MaxValue},
|
||||
{ typeof(byte), o => MathUtils.Clamp((Convert.ToDouble(o) / byte.MaxValue - 0.5) * 2, -1, 1) * double.MaxValue}
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Remaps from the double min/max to target numeric min/max.
|
||||
/// </summary>
|
||||
private static readonly Dictionary<Type, Func<double, object>> s_RemapFromDouble =
|
||||
new Dictionary<Type, Func<double, object>>
|
||||
{
|
||||
// Duh
|
||||
{typeof(double), v => v},
|
||||
|
||||
// Signed
|
||||
{typeof(short), v => (short)(v / double.MaxValue * short.MaxValue)},
|
||||
{typeof(int), v => (int)(v / double.MaxValue * int.MaxValue)},
|
||||
{typeof(long), v => (long)(v / double.MaxValue * long.MaxValue)},
|
||||
{typeof(float), v => (float)(v / double.MaxValue * float.MaxValue)},
|
||||
{typeof(decimal), v => (decimal)(v / double.MaxValue) * decimal.MaxValue},
|
||||
|
||||
// Unsigned
|
||||
{typeof(ushort), v => (ushort)((v / double.MaxValue + 1) / 2 * ushort.MaxValue)},
|
||||
{typeof(uint), v => (uint)((v / double.MaxValue + 1) / 2 * uint.MaxValue)},
|
||||
{typeof(ulong), v => (ulong)((v / double.MaxValue + 1) / 2 * ulong.MaxValue)},
|
||||
{typeof(byte), v => (byte)((v / double.MaxValue + 1) / 2 * byte.MaxValue)}
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Gets the min value of a given numeric type as a double.
|
||||
/// </summary>
|
||||
private static readonly Dictionary<Type, double> s_MinAsDouble =
|
||||
new Dictionary<Type, double>
|
||||
{
|
||||
// Duh
|
||||
{typeof(double), double.MinValue},
|
||||
|
||||
// Signed
|
||||
{typeof(short), Convert.ToDouble(short.MinValue)},
|
||||
{typeof(int), Convert.ToDouble(int.MinValue)},
|
||||
{typeof(long), Convert.ToDouble(long.MinValue)},
|
||||
{typeof(float), Convert.ToDouble(float.MinValue)},
|
||||
{typeof(decimal), Convert.ToDouble(decimal.MinValue)},
|
||||
|
||||
// Unsigned
|
||||
{typeof(ushort), Convert.ToDouble(ushort.MinValue)},
|
||||
{typeof(uint), Convert.ToDouble(uint.MinValue)},
|
||||
{typeof(ulong), Convert.ToDouble(ulong.MinValue)},
|
||||
{typeof(byte), Convert.ToDouble(byte.MinValue)}
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Gets the min value of a given numeric type as a double.
|
||||
/// </summary>
|
||||
private static readonly Dictionary<Type, double> s_MaxAsDouble =
|
||||
new Dictionary<Type, double>
|
||||
{
|
||||
// Duh
|
||||
{typeof(double), double.MaxValue},
|
||||
|
||||
// Signed
|
||||
{typeof(short), Convert.ToDouble(short.MaxValue)},
|
||||
{typeof(int), Convert.ToDouble(int.MaxValue)},
|
||||
{typeof(long), Convert.ToDouble(long.MaxValue)},
|
||||
{typeof(float), Convert.ToDouble(float.MaxValue)},
|
||||
{typeof(decimal), Convert.ToDouble(decimal.MaxValue)},
|
||||
|
||||
// Unsigned
|
||||
{typeof(ushort), Convert.ToDouble(ushort.MaxValue)},
|
||||
{typeof(uint), Convert.ToDouble(uint.MaxValue)},
|
||||
{typeof(ulong), Convert.ToDouble(ulong.MaxValue)},
|
||||
{typeof(byte), Convert.ToDouble(byte.MaxValue)}
|
||||
};
|
||||
|
||||
private readonly object m_Min;
|
||||
private readonly object m_Max;
|
||||
|
||||
#region Properties
|
||||
|
||||
[NotNull]
|
||||
public object Min { get; private set; }
|
||||
/// <summary>
|
||||
/// Gets the min value for this range.
|
||||
/// </summary>
|
||||
public object Min { get { return m_Min; } }
|
||||
|
||||
[NotNull]
|
||||
public object Max { get; private set; }
|
||||
|
||||
[NotNull]
|
||||
private Type Type { get { return Min.GetType(); } }
|
||||
/// <summary>
|
||||
/// Gets the max value for this range.
|
||||
/// </summary>
|
||||
public object Max { get { return m_Max; } }
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
|
||||
/// <summary>
|
||||
/// Constructor.
|
||||
/// </summary>
|
||||
/// <param name="min"></param>
|
||||
/// <param name="max"></param>
|
||||
public RangeAttribute(ushort min, ushort max)
|
||||
: this((object)min, (object)max)
|
||||
{
|
||||
Min = min;
|
||||
Max = max;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructor.
|
||||
/// </summary>
|
||||
/// <param name="min"></param>
|
||||
/// <param name="max"></param>
|
||||
public RangeAttribute(short min, short max)
|
||||
: this((object)min, (object)max)
|
||||
{
|
||||
Min = min;
|
||||
Max = max;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructor.
|
||||
/// </summary>
|
||||
/// <param name="min"></param>
|
||||
/// <param name="max"></param>
|
||||
public RangeAttribute(uint min, uint max)
|
||||
: this((object)min, (object)max)
|
||||
{
|
||||
Min = min;
|
||||
Max = max;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructor.
|
||||
/// </summary>
|
||||
/// <param name="min"></param>
|
||||
/// <param name="max"></param>
|
||||
public RangeAttribute(int min, int max)
|
||||
: this((object)min, (object)max)
|
||||
{
|
||||
Min = min;
|
||||
Max = max;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructor.
|
||||
/// </summary>
|
||||
/// <param name="min"></param>
|
||||
/// <param name="max"></param>
|
||||
public RangeAttribute(ulong min, ulong max)
|
||||
: this((object)min, (object)max)
|
||||
{
|
||||
Min = min;
|
||||
Max = max;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructor.
|
||||
/// </summary>
|
||||
/// <param name="min"></param>
|
||||
/// <param name="max"></param>
|
||||
public RangeAttribute(long min, long max)
|
||||
: this((object)min, (object)max)
|
||||
{
|
||||
Min = min;
|
||||
Max = max;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructor.
|
||||
/// </summary>
|
||||
/// <param name="min"></param>
|
||||
/// <param name="max"></param>
|
||||
public RangeAttribute(float min, float max)
|
||||
: this((object)min, (object)max)
|
||||
{
|
||||
Min = min;
|
||||
Max = max;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructor.
|
||||
/// </summary>
|
||||
/// <param name="min"></param>
|
||||
/// <param name="max"></param>
|
||||
public RangeAttribute(double min, double max)
|
||||
: this((object)min, (object)max)
|
||||
{
|
||||
Min = min;
|
||||
Max = max;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructor.
|
||||
/// </summary>
|
||||
/// <param name="min"></param>
|
||||
/// <param name="max"></param>
|
||||
public RangeAttribute(byte min, byte max)
|
||||
: this((object)min, (object)max)
|
||||
{
|
||||
Min = min;
|
||||
Max = max;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructor.
|
||||
/// </summary>
|
||||
/// <param name="min"></param>
|
||||
/// <param name="max"></param>
|
||||
public RangeAttribute(sbyte min, sbyte max)
|
||||
: this((object)min, (object)max)
|
||||
{
|
||||
Min = min;
|
||||
Max = max;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructor.
|
||||
/// </summary>
|
||||
/// <param name="min"></param>
|
||||
/// <param name="max"></param>
|
||||
public RangeAttribute(decimal min, decimal max)
|
||||
: this((object)min, (object)max)
|
||||
{
|
||||
Min = min;
|
||||
Max = max;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructor.
|
||||
/// </summary>
|
||||
/// <param name="min"></param>
|
||||
/// <param name="max"></param>
|
||||
public RangeAttribute(object min, object max)
|
||||
{
|
||||
if (min == null)
|
||||
throw new ArgumentNullException("min");
|
||||
|
||||
if (max == null)
|
||||
throw new ArgumentNullException("max");
|
||||
|
||||
if (min.GetType() != max.GetType())
|
||||
throw new ArgumentException("Min and Max types do not match");
|
||||
|
||||
if (!min.GetType().IsNumeric())
|
||||
throw new ArgumentException("Given types are not numeric");
|
||||
|
||||
m_Min = min;
|
||||
m_Max = max;
|
||||
}
|
||||
|
||||
#endregion
|
||||
@@ -100,127 +287,239 @@ namespace ICD.Common.Utils.Attributes
|
||||
#region Methods
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if the given value is within the range of Min to Max.
|
||||
/// Remaps the numeric value into the min-max range of the target numeric type.
|
||||
/// </summary>
|
||||
/// <param name="value"></param>
|
||||
/// <param name="type"></param>
|
||||
/// <returns></returns>
|
||||
public bool IsInRange(object value)
|
||||
[NotNull]
|
||||
public static object Remap([NotNull] object value, [NotNull] Type type)
|
||||
{
|
||||
if (value == null)
|
||||
throw new ArgumentNullException("value");
|
||||
|
||||
if (value.GetType() != Type)
|
||||
throw new ArgumentException("the type of value does not match the type of min / max");
|
||||
if (type == null)
|
||||
throw new ArgumentNullException("type");
|
||||
|
||||
if (value is ushort)
|
||||
{
|
||||
var castMin = (ushort)Min;
|
||||
var castMax = (ushort)Max;
|
||||
var castVal = (ushort)value;
|
||||
return (castVal >= castMin && castVal <= castMax);
|
||||
}
|
||||
if (!type.IsNumeric())
|
||||
throw new ArgumentException("Target type is not numeric");
|
||||
|
||||
if (value is short)
|
||||
{
|
||||
var castMin = (short)Min;
|
||||
var castMax = (short)Max;
|
||||
var castVal = (short)value;
|
||||
return (castVal >= castMin && castVal <= castMax);
|
||||
}
|
||||
if (!value.GetType().IsNumeric())
|
||||
throw new ArgumentException("Source value is not numeric");
|
||||
|
||||
if (value is uint)
|
||||
{
|
||||
var castMin = (uint)Min;
|
||||
var castMax = (uint)Max;
|
||||
var castVal = (uint)value;
|
||||
return (castVal >= castMin && castVal <= castMax);
|
||||
}
|
||||
|
||||
if (value is int)
|
||||
{
|
||||
var castMin = (int)Min;
|
||||
var castMax = (int)Max;
|
||||
var castVal = (int)value;
|
||||
return (castVal >= castMin && castVal <= castMax);
|
||||
}
|
||||
|
||||
if (value is ulong)
|
||||
{
|
||||
var castMin = (ulong)Min;
|
||||
var castMax = (ulong)Max;
|
||||
var castVal = (ulong)value;
|
||||
return (castVal >= castMin && castVal <= castMax);
|
||||
}
|
||||
|
||||
if (value is long)
|
||||
{
|
||||
var castMin = (long)Min;
|
||||
var castMax = (long)Max;
|
||||
var castVal = (long)value;
|
||||
return (castVal >= castMin && castVal <= castMax);
|
||||
}
|
||||
|
||||
if (value is float)
|
||||
{
|
||||
var castMin = (float)Min;
|
||||
var castMax = (float)Max;
|
||||
var castVal = (float)value;
|
||||
return (castVal >= castMin && castVal <= castMax);
|
||||
}
|
||||
|
||||
if (value is double)
|
||||
{
|
||||
var castMin = (double)Min;
|
||||
var castMax = (double)Max;
|
||||
var castVal = (double)value;
|
||||
return (castVal >= castMin && castVal <= castMax);
|
||||
}
|
||||
|
||||
if (value is decimal)
|
||||
{
|
||||
var castMin = (decimal)Min;
|
||||
var castMax = (decimal)Max;
|
||||
var castVal = (decimal)value;
|
||||
return (castVal >= castMin && castVal <= castMax);
|
||||
}
|
||||
|
||||
if (value is byte)
|
||||
{
|
||||
var castMin = (byte)Min;
|
||||
var castMax = (byte)Max;
|
||||
var castVal = (byte)value;
|
||||
return (castVal >= castMin && castVal <= castMax);
|
||||
}
|
||||
|
||||
if (value is sbyte)
|
||||
{
|
||||
var castMin = (sbyte)Min;
|
||||
var castMax = (sbyte)Max;
|
||||
var castVal = (sbyte)value;
|
||||
return (castVal >= castMin && castVal <= castMax);
|
||||
}
|
||||
|
||||
throw new ArgumentException("the type of value is not a numeric type.");
|
||||
double intermediate = RemapToDouble(value);
|
||||
return RemapFromDouble(intermediate, type);
|
||||
}
|
||||
|
||||
public ushort RemapRangeToUShort(double value)
|
||||
/// <summary>
|
||||
/// Remaps the given numeric value from its min/max range into double min/max range.
|
||||
/// </summary>
|
||||
/// <param name="value"></param>
|
||||
/// <returns></returns>
|
||||
public static double RemapToDouble([NotNull] object value)
|
||||
{
|
||||
return (ushort)MathUtils.MapRange((double)Min, (double)Max, ushort.MinValue, ushort.MaxValue, value);
|
||||
if (value == null)
|
||||
throw new ArgumentNullException("value");
|
||||
|
||||
Func<object, double> remap;
|
||||
if (!s_RemapToDouble.TryGetValue(value.GetType(), out remap))
|
||||
throw new NotSupportedException("Value type is not supported.");
|
||||
|
||||
return remap(value);
|
||||
}
|
||||
|
||||
public ushort RemapRangeToUShort(float value)
|
||||
/// <summary>
|
||||
/// Remaps the given double value from its min/max range into the target type min/max range.
|
||||
/// </summary>
|
||||
/// <param name="value"></param>
|
||||
/// <param name="type"></param>
|
||||
/// <returns></returns>
|
||||
[NotNull]
|
||||
public static object RemapFromDouble(double value, [NotNull] Type type)
|
||||
{
|
||||
return (ushort)MathUtils.MapRange((float)Min, (float)Max, ushort.MinValue, ushort.MaxValue, value);
|
||||
if (type == null)
|
||||
throw new ArgumentNullException("type");
|
||||
|
||||
Func<double, object> remap;
|
||||
if (!s_RemapFromDouble.TryGetValue(type, out remap))
|
||||
throw new NotSupportedException("Value type is not supported.");
|
||||
|
||||
return remap(value);
|
||||
}
|
||||
|
||||
public ushort RemapRangeToUShort(int value)
|
||||
/// <summary>
|
||||
/// Remaps the given numeric value to the defined min/max.
|
||||
/// </summary>
|
||||
/// <param name="value"></param>
|
||||
/// <returns></returns>
|
||||
[NotNull]
|
||||
public object RemapMinMax([NotNull] object value)
|
||||
{
|
||||
return (ushort)MathUtils.MapRange((int)Min, (int)Max, ushort.MinValue, ushort.MaxValue, value);
|
||||
if (value == null)
|
||||
throw new ArgumentNullException("value");
|
||||
|
||||
if (!value.GetType().IsNumeric())
|
||||
throw new ArgumentException("Source value is not numeric");
|
||||
|
||||
double sourceMin = GetMinAsDouble(value.GetType());
|
||||
double sourceMax = GetMaxAsDouble(value.GetType());
|
||||
|
||||
double targetMin = Convert.ToDouble(Min);
|
||||
double targetMax = Convert.ToDouble(Max);
|
||||
|
||||
double doubleValue = Convert.ToDouble(value);
|
||||
|
||||
double remapped = MathUtils.MapRange(sourceMin, sourceMax, targetMin, targetMax, doubleValue);
|
||||
|
||||
return Convert.ChangeType(remapped, value.GetType(), CultureInfo.InvariantCulture);
|
||||
}
|
||||
|
||||
public ushort RemapRangeToUShort(ushort value)
|
||||
/// <summary>
|
||||
/// Clamps the given numeric value into the valid ranges of the target numeric type.
|
||||
/// </summary>
|
||||
/// <param name="value"></param>
|
||||
/// <param name="type"></param>
|
||||
/// <returns></returns>
|
||||
[NotNull]
|
||||
public static object Clamp([NotNull] object value, [NotNull] Type type)
|
||||
{
|
||||
return MathUtils.MapRange((ushort)Min, (ushort)Max, ushort.MinValue, ushort.MaxValue, value);
|
||||
if (value == null)
|
||||
throw new ArgumentNullException("value");
|
||||
|
||||
if (type == null)
|
||||
throw new ArgumentNullException("type");
|
||||
|
||||
if (!type.IsNumeric())
|
||||
throw new ArgumentException("Target type is not numeric");
|
||||
|
||||
if (!value.GetType().IsNumeric())
|
||||
throw new ArgumentException("Source value is not numeric");
|
||||
|
||||
double doubleValue = Convert.ToDouble(value);
|
||||
double clamped = Clamp(doubleValue, type);
|
||||
|
||||
return Convert.ChangeType(clamped, value.GetType(), CultureInfo.InvariantCulture);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clamps the given double value into the valid ranges of the target numeric type.
|
||||
/// </summary>
|
||||
/// <param name="value"></param>
|
||||
/// <param name="type"></param>
|
||||
/// <returns></returns>
|
||||
public static double Clamp(double value, [NotNull] Type type)
|
||||
{
|
||||
if (type == null)
|
||||
throw new ArgumentNullException("type");
|
||||
|
||||
Func<double, double> clamp;
|
||||
if (!s_Clamp.TryGetValue(type, out clamp))
|
||||
throw new NotSupportedException("Value type is not supported.");
|
||||
|
||||
return clamp(value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clamps the given numeric value to the defined min/max then remaps to the target numeric type.
|
||||
/// </summary>
|
||||
/// <param name="value"></param>
|
||||
/// <param name="type"></param>
|
||||
/// <returns></returns>
|
||||
[NotNull]
|
||||
public object ClampMinMaxThenRemap([NotNull] object value, [NotNull] Type type)
|
||||
{
|
||||
if (value == null)
|
||||
throw new ArgumentNullException("value");
|
||||
|
||||
if (type == null)
|
||||
throw new ArgumentNullException("type");
|
||||
|
||||
if (!type.IsNumeric())
|
||||
throw new ArgumentException("Target type is not numeric");
|
||||
|
||||
if (!value.GetType().IsNumeric())
|
||||
throw new ArgumentException("Source value is not numeric");
|
||||
|
||||
double min = Convert.ToDouble(Min);
|
||||
double max = Convert.ToDouble(Max);
|
||||
double doubleValue = Convert.ToDouble(value);
|
||||
|
||||
double clamped = MathUtils.Clamp(doubleValue, min, max);
|
||||
object remapped = RemapMinMax(clamped, type);
|
||||
|
||||
return Convert.ChangeType(remapped, value.GetType(), CultureInfo.InvariantCulture);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Private Methods
|
||||
|
||||
[NotNull]
|
||||
private object RemapMinMax([NotNull] object value, [NotNull] Type type)
|
||||
{
|
||||
if (value == null)
|
||||
throw new ArgumentNullException("value");
|
||||
|
||||
if (type == null)
|
||||
throw new ArgumentNullException("type");
|
||||
|
||||
if (!type.IsNumeric())
|
||||
throw new ArgumentException("Target type is not numeric");
|
||||
|
||||
if (!value.GetType().IsNumeric())
|
||||
throw new ArgumentException("Source value is not numeric");
|
||||
|
||||
double sourceMin = Convert.ToDouble(Min);
|
||||
double sourceMax = Convert.ToDouble(Max);
|
||||
|
||||
double targetMin = GetMinAsDouble(type);
|
||||
double targetMax = GetMaxAsDouble(type);
|
||||
|
||||
double doubleValue = Convert.ToDouble(value);
|
||||
|
||||
double remapped = MathUtils.MapRange(sourceMin, sourceMax, targetMin, targetMax, doubleValue);
|
||||
|
||||
return Convert.ChangeType(remapped, type, CultureInfo.InvariantCulture);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the min value for the given numeric type as a double.
|
||||
/// </summary>
|
||||
/// <param name="type"></param>
|
||||
/// <returns></returns>
|
||||
private static double GetMinAsDouble([NotNull] Type type)
|
||||
{
|
||||
if (type == null)
|
||||
throw new ArgumentNullException("type");
|
||||
|
||||
if (!type.IsNumeric())
|
||||
throw new ArgumentException("Target type is not numeric");
|
||||
|
||||
double min;
|
||||
if (!s_MinAsDouble.TryGetValue(type, out min))
|
||||
throw new NotSupportedException("Type is not supported.");
|
||||
|
||||
return min;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the max value for the given numeric type as a double.
|
||||
/// </summary>
|
||||
/// <param name="type"></param>
|
||||
/// <returns></returns>
|
||||
private static double GetMaxAsDouble([NotNull] Type type)
|
||||
{
|
||||
if (type == null)
|
||||
throw new ArgumentNullException("type");
|
||||
|
||||
if (!type.IsNumeric())
|
||||
throw new ArgumentException("Target type is not numeric");
|
||||
|
||||
double max;
|
||||
if (!s_MaxAsDouble.TryGetValue(type, out max))
|
||||
throw new NotSupportedException("Type is not supported.");
|
||||
|
||||
return max;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using ICD.Common.Properties;
|
||||
|
||||
namespace ICD.Common.Utils.Collections
|
||||
{
|
||||
@@ -20,8 +21,10 @@ namespace ICD.Common.Utils.Collections
|
||||
|
||||
public bool IsReadOnly { get { return false; } }
|
||||
|
||||
[NotNull]
|
||||
public ICollection<TKey> Keys { get { return m_KeyToValue.Keys; } }
|
||||
|
||||
[NotNull]
|
||||
public ICollection<TValue> Values { get { return m_ValueToKey.Keys; } }
|
||||
|
||||
#endregion
|
||||
@@ -30,21 +33,20 @@ namespace ICD.Common.Utils.Collections
|
||||
/// Constructor.
|
||||
/// </summary>
|
||||
public BiDictionary()
|
||||
: this(null)
|
||||
{
|
||||
m_KeyToValue = new Dictionary<TKey, TValue>();
|
||||
m_ValueToKey = new Dictionary<TValue, TKey>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructor.
|
||||
/// </summary>
|
||||
/// <param name="dict"></param>
|
||||
public BiDictionary(Dictionary<TKey, TValue> dict)
|
||||
public BiDictionary([NotNull] Dictionary<TKey, TValue> dict)
|
||||
: this()
|
||||
{
|
||||
m_KeyToValue = new Dictionary<TKey, TValue>();
|
||||
m_ValueToKey = new Dictionary<TValue, TKey>();
|
||||
|
||||
if (dict == null)
|
||||
return;
|
||||
throw new ArgumentNullException("dict");
|
||||
|
||||
foreach (KeyValuePair<TKey, TValue> kvp in dict)
|
||||
Add(kvp.Key, kvp.Value);
|
||||
@@ -58,24 +60,31 @@ namespace ICD.Common.Utils.Collections
|
||||
m_ValueToKey.Clear();
|
||||
}
|
||||
|
||||
public bool ContainsKey(TKey key)
|
||||
public bool ContainsKey([NotNull] TKey key)
|
||||
{
|
||||
// ReSharper disable CompareNonConstrainedGenericWithNull
|
||||
if (key == null)
|
||||
// ReSharper restore CompareNonConstrainedGenericWithNull
|
||||
throw new ArgumentNullException("key");
|
||||
|
||||
return m_KeyToValue.ContainsKey(key);
|
||||
}
|
||||
|
||||
public bool ContainsValue(TValue value)
|
||||
public bool ContainsValue([NotNull] TValue value)
|
||||
{
|
||||
return m_ValueToKey.ContainsKey(value);
|
||||
}
|
||||
|
||||
public void Add(TKey key, TValue value)
|
||||
public void Add([NotNull] TKey key, [NotNull] TValue value)
|
||||
{
|
||||
// ReSharper disable once CompareNonConstrainedGenericWithNull
|
||||
// ReSharper disable CompareNonConstrainedGenericWithNull
|
||||
if (key == null)
|
||||
// ReSharper restore CompareNonConstrainedGenericWithNull
|
||||
throw new ArgumentNullException("key");
|
||||
|
||||
// ReSharper disable once CompareNonConstrainedGenericWithNull
|
||||
// ReSharper disable CompareNonConstrainedGenericWithNull
|
||||
if (value == null)
|
||||
// ReSharper restore CompareNonConstrainedGenericWithNull
|
||||
throw new ArgumentNullException("value");
|
||||
|
||||
if (ContainsKey(key))
|
||||
@@ -88,14 +97,16 @@ namespace ICD.Common.Utils.Collections
|
||||
m_ValueToKey.Add(value, key);
|
||||
}
|
||||
|
||||
public void Set(TKey key, TValue value)
|
||||
public void Set([NotNull] TKey key, [NotNull] TValue value)
|
||||
{
|
||||
// ReSharper disable once CompareNonConstrainedGenericWithNull
|
||||
// ReSharper disable CompareNonConstrainedGenericWithNull
|
||||
if (key == null)
|
||||
// ReSharper restore CompareNonConstrainedGenericWithNull
|
||||
throw new ArgumentNullException("key");
|
||||
|
||||
// ReSharper disable once CompareNonConstrainedGenericWithNull
|
||||
// ReSharper disable CompareNonConstrainedGenericWithNull
|
||||
if (value == null)
|
||||
// ReSharper restore CompareNonConstrainedGenericWithNull
|
||||
throw new ArgumentNullException("value");
|
||||
|
||||
RemoveKey(key);
|
||||
@@ -104,18 +115,35 @@ namespace ICD.Common.Utils.Collections
|
||||
Add(key, value);
|
||||
}
|
||||
|
||||
public TKey GetKey(TValue value)
|
||||
[NotNull]
|
||||
public TKey GetKey([NotNull] TValue value)
|
||||
{
|
||||
// ReSharper disable CompareNonConstrainedGenericWithNull
|
||||
if (value == null)
|
||||
// ReSharper restore CompareNonConstrainedGenericWithNull
|
||||
throw new ArgumentNullException("value");
|
||||
|
||||
return m_ValueToKey[value];
|
||||
}
|
||||
|
||||
public TValue GetValue(TKey key)
|
||||
[NotNull]
|
||||
public TValue GetValue([NotNull] TKey key)
|
||||
{
|
||||
// ReSharper disable CompareNonConstrainedGenericWithNull
|
||||
if (key == null)
|
||||
// ReSharper restore CompareNonConstrainedGenericWithNull
|
||||
throw new ArgumentNullException("key");
|
||||
|
||||
return m_KeyToValue[key];
|
||||
}
|
||||
|
||||
public bool RemoveKey(TKey key)
|
||||
public bool RemoveKey([NotNull] TKey key)
|
||||
{
|
||||
// ReSharper disable CompareNonConstrainedGenericWithNull
|
||||
if (key == null)
|
||||
// ReSharper restore CompareNonConstrainedGenericWithNull
|
||||
throw new ArgumentNullException("key");
|
||||
|
||||
if (!ContainsKey(key))
|
||||
return false;
|
||||
|
||||
@@ -127,8 +155,13 @@ namespace ICD.Common.Utils.Collections
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool RemoveValue(TValue value)
|
||||
public bool RemoveValue([NotNull] TValue value)
|
||||
{
|
||||
// ReSharper disable CompareNonConstrainedGenericWithNull
|
||||
if (value == null)
|
||||
// ReSharper restore CompareNonConstrainedGenericWithNull
|
||||
throw new ArgumentNullException("value");
|
||||
|
||||
if (!ContainsValue(value))
|
||||
return false;
|
||||
|
||||
@@ -137,13 +170,23 @@ namespace ICD.Common.Utils.Collections
|
||||
return RemoveKey(key);
|
||||
}
|
||||
|
||||
public bool TryGetValue(TKey key, out TValue value)
|
||||
public bool TryGetValue([NotNull] TKey key, out TValue value)
|
||||
{
|
||||
// ReSharper disable CompareNonConstrainedGenericWithNull
|
||||
if (key == null)
|
||||
// ReSharper restore CompareNonConstrainedGenericWithNull
|
||||
throw new ArgumentNullException("key");
|
||||
|
||||
return m_KeyToValue.TryGetValue(key, out value);
|
||||
}
|
||||
|
||||
public bool TryGetKey(TValue value, out TKey key)
|
||||
public bool TryGetKey([NotNull] TValue value, out TKey key)
|
||||
{
|
||||
// ReSharper disable CompareNonConstrainedGenericWithNull
|
||||
if (value == null)
|
||||
// ReSharper restore CompareNonConstrainedGenericWithNull
|
||||
throw new ArgumentNullException("value");
|
||||
|
||||
return m_ValueToKey.TryGetValue(value, out key);
|
||||
}
|
||||
|
||||
@@ -151,9 +194,10 @@ namespace ICD.Common.Utils.Collections
|
||||
|
||||
#region IDictionary
|
||||
|
||||
TValue IDictionary<TKey, TValue>.this[TKey key] { get { return GetValue(key); } set { Set(key, value); } }
|
||||
[NotNull]
|
||||
TValue IDictionary<TKey, TValue>.this[[NotNull] TKey key] { get { return GetValue(key); } set { Set(key, value); } }
|
||||
|
||||
bool IDictionary<TKey, TValue>.Remove(TKey key)
|
||||
bool IDictionary<TKey, TValue>.Remove([NotNull] TKey key)
|
||||
{
|
||||
return RemoveKey(key);
|
||||
}
|
||||
@@ -177,7 +221,7 @@ namespace ICD.Common.Utils.Collections
|
||||
return RemoveKey(item.Key);
|
||||
}
|
||||
|
||||
void ICollection<KeyValuePair<TKey, TValue>>.CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex)
|
||||
void ICollection<KeyValuePair<TKey, TValue>>.CopyTo([NotNull] KeyValuePair<TKey, TValue>[] array, int arrayIndex)
|
||||
{
|
||||
(m_KeyToValue as IDictionary<TKey, TValue>).CopyTo(array, arrayIndex);
|
||||
}
|
||||
@@ -186,11 +230,13 @@ namespace ICD.Common.Utils.Collections
|
||||
|
||||
#region IEnumerable
|
||||
|
||||
[NotNull]
|
||||
public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
|
||||
{
|
||||
return m_KeyToValue.GetEnumerator();
|
||||
}
|
||||
|
||||
[NotNull]
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
{
|
||||
return GetEnumerator();
|
||||
|
||||
@@ -49,7 +49,7 @@ namespace ICD.Common.Utils.Collections
|
||||
/// Constructor.
|
||||
/// </summary>
|
||||
/// <param name="items"></param>
|
||||
public IcdHashSet(IEnumerable<T> items)
|
||||
public IcdHashSet([NotNull] IEnumerable<T> items)
|
||||
: this(EqualityComparer<T>.Default, items)
|
||||
{
|
||||
}
|
||||
@@ -58,7 +58,7 @@ namespace ICD.Common.Utils.Collections
|
||||
/// Constructor.
|
||||
/// </summary>
|
||||
/// <param name="comparer"></param>
|
||||
public IcdHashSet(IEqualityComparer<T> comparer)
|
||||
public IcdHashSet([NotNull] IEqualityComparer<T> comparer)
|
||||
: this(comparer, Enumerable.Empty<T>())
|
||||
{
|
||||
}
|
||||
@@ -68,7 +68,7 @@ namespace ICD.Common.Utils.Collections
|
||||
/// </summary>
|
||||
/// <param name="comparer"></param>
|
||||
/// <param name="items"></param>
|
||||
public IcdHashSet(IEqualityComparer<T> comparer, IEnumerable<T> items)
|
||||
public IcdHashSet([NotNull] IEqualityComparer<T> comparer, [NotNull] IEnumerable<T> items)
|
||||
{
|
||||
if (comparer == null)
|
||||
throw new ArgumentNullException("comparer");
|
||||
@@ -91,7 +91,8 @@ namespace ICD.Common.Utils.Collections
|
||||
/// <param name="set"></param>
|
||||
/// <returns></returns>
|
||||
[PublicAPI]
|
||||
public IcdHashSet<T> Union(IEnumerable<T> set)
|
||||
[NotNull]
|
||||
public IcdHashSet<T> Union([NotNull] IEnumerable<T> set)
|
||||
{
|
||||
if (set == null)
|
||||
throw new ArgumentNullException("set");
|
||||
@@ -108,7 +109,8 @@ namespace ICD.Common.Utils.Collections
|
||||
/// <param name="set"></param>
|
||||
/// <returns></returns>
|
||||
[PublicAPI]
|
||||
public IcdHashSet<T> Subtract(IEnumerable<T> set)
|
||||
[NotNull]
|
||||
public IcdHashSet<T> Subtract([NotNull] IEnumerable<T> set)
|
||||
{
|
||||
if (set == null)
|
||||
throw new ArgumentNullException("set");
|
||||
@@ -127,7 +129,8 @@ namespace ICD.Common.Utils.Collections
|
||||
/// <param name="set"></param>
|
||||
/// <returns></returns>
|
||||
[PublicAPI]
|
||||
public IcdHashSet<T> Intersection(IEnumerable<T> set)
|
||||
[NotNull]
|
||||
public IcdHashSet<T> Intersection([NotNull] IEnumerable<T> set)
|
||||
{
|
||||
if (set == null)
|
||||
throw new ArgumentNullException("set");
|
||||
@@ -146,7 +149,8 @@ namespace ICD.Common.Utils.Collections
|
||||
/// <param name="set"></param>
|
||||
/// <returns></returns>
|
||||
[PublicAPI]
|
||||
public IcdHashSet<T> NonIntersection(IEnumerable<T> set)
|
||||
[NotNull]
|
||||
public IcdHashSet<T> NonIntersection([NotNull] IEnumerable<T> set)
|
||||
{
|
||||
if (set == null)
|
||||
throw new ArgumentNullException("set");
|
||||
@@ -170,7 +174,7 @@ namespace ICD.Common.Utils.Collections
|
||||
/// <param name="set"></param>
|
||||
/// <returns></returns>
|
||||
[PublicAPI]
|
||||
public bool IsSubsetOf(IcdHashSet<T> set)
|
||||
public bool IsSubsetOf([NotNull] IcdHashSet<T> set)
|
||||
{
|
||||
if (set == null)
|
||||
throw new ArgumentNullException("set");
|
||||
@@ -184,7 +188,7 @@ namespace ICD.Common.Utils.Collections
|
||||
/// <param name="set"></param>
|
||||
/// <returns></returns>
|
||||
[PublicAPI]
|
||||
public bool IsProperSubsetOf(IcdHashSet<T> set)
|
||||
public bool IsProperSubsetOf([NotNull] IcdHashSet<T> set)
|
||||
{
|
||||
if (set == null)
|
||||
throw new ArgumentNullException("set");
|
||||
@@ -198,7 +202,7 @@ namespace ICD.Common.Utils.Collections
|
||||
/// <param name="set"></param>
|
||||
/// <returns></returns>
|
||||
[PublicAPI]
|
||||
public bool IsSupersetOf(IcdHashSet<T> set)
|
||||
public bool IsSupersetOf([NotNull] IcdHashSet<T> set)
|
||||
{
|
||||
if (set == null)
|
||||
throw new ArgumentNullException("set");
|
||||
@@ -212,7 +216,7 @@ namespace ICD.Common.Utils.Collections
|
||||
/// <param name="set"></param>
|
||||
/// <returns></returns>
|
||||
[PublicAPI]
|
||||
public bool IsProperSupersetOf(IcdHashSet<T> set)
|
||||
public bool IsProperSupersetOf([NotNull] IcdHashSet<T> set)
|
||||
{
|
||||
if (set == null)
|
||||
throw new ArgumentNullException("set");
|
||||
@@ -226,7 +230,7 @@ namespace ICD.Common.Utils.Collections
|
||||
/// <param name="set"></param>
|
||||
/// <returns></returns>
|
||||
[PublicAPI]
|
||||
public bool SetEquals(IcdHashSet<T> set)
|
||||
public bool SetEquals([NotNull] IcdHashSet<T> set)
|
||||
{
|
||||
if (set == null)
|
||||
throw new ArgumentNullException("set");
|
||||
@@ -243,7 +247,7 @@ namespace ICD.Common.Utils.Collections
|
||||
/// </summary>
|
||||
/// <param name="item"></param>
|
||||
/// <returns></returns>
|
||||
public bool Add(T item)
|
||||
public bool Add([NotNull] T item)
|
||||
{
|
||||
// ReSharper disable CompareNonConstrainedGenericWithNull
|
||||
if (item == null)
|
||||
@@ -261,7 +265,7 @@ namespace ICD.Common.Utils.Collections
|
||||
/// Adds the item to the collection.
|
||||
/// </summary>
|
||||
/// <param name="item"></param>
|
||||
void ICollection<T>.Add(T item)
|
||||
void ICollection<T>.Add([NotNull] T item)
|
||||
{
|
||||
Add(item);
|
||||
}
|
||||
@@ -270,7 +274,7 @@ namespace ICD.Common.Utils.Collections
|
||||
/// Adds each of the items in the sequence to the collection.
|
||||
/// </summary>
|
||||
/// <param name="items"></param>
|
||||
public void AddRange(IEnumerable<T> items)
|
||||
public void AddRange([NotNull] IEnumerable<T> items)
|
||||
{
|
||||
if (items == null)
|
||||
throw new ArgumentNullException("items");
|
||||
@@ -293,7 +297,7 @@ namespace ICD.Common.Utils.Collections
|
||||
/// </summary>
|
||||
/// <param name="item"></param>
|
||||
/// <returns></returns>
|
||||
public bool Contains(T item)
|
||||
public bool Contains([NotNull] T item)
|
||||
{
|
||||
// ReSharper disable CompareNonConstrainedGenericWithNull
|
||||
if (item == null)
|
||||
@@ -307,8 +311,11 @@ namespace ICD.Common.Utils.Collections
|
||||
/// Copies the items of the <see cref="T:System.Collections.Generic.ICollection`1"/> to an <see cref="T:System.Array"/>, starting at a particular <see cref="T:System.Array"/> index.
|
||||
/// </summary>
|
||||
/// <param name="array">The one-dimensional <see cref="T:System.Array"/> that is the destination of the items copied from <see cref="T:System.Collections.Generic.ICollection`1"/>. The <see cref="T:System.Array"/> must have zero-based indexing.</param><param name="arrayIndex">The zero-based index in <paramref name="array"/> at which copying begins.</param><exception cref="T:System.ArgumentNullException"><paramref name="array"/> is null.</exception><exception cref="T:System.ArgumentOutOfRangeException"><paramref name="arrayIndex"/> is less than 0.</exception><exception cref="T:System.ArgumentException"><paramref name="array"/> is multidimensional.-or-<paramref name="arrayIndex"/> is equal to or greater than the length of <paramref name="array"/>.-or-The number of items in the source <see cref="T:System.Collections.Generic.ICollection`1"/> is greater than the available space from <paramref name="arrayIndex"/> to the end of the destination <paramref name="array"/>.-or-Type T cannot be cast automatically to the type of the destination <paramref name="array"/>.</exception>
|
||||
public void CopyTo(T[] array, int arrayIndex)
|
||||
public void CopyTo([NotNull] T[] array, int arrayIndex)
|
||||
{
|
||||
if (array == null)
|
||||
throw new ArgumentNullException("array");
|
||||
|
||||
m_Dict.Keys.CopyTo(array, arrayIndex);
|
||||
}
|
||||
|
||||
@@ -319,7 +326,7 @@ namespace ICD.Common.Utils.Collections
|
||||
/// true if <paramref name="item"/> was successfully removed from the <see cref="T:System.Collections.Generic.ICollection`1"/>; otherwise, false. This method also returns false if <paramref name="item"/> is not found in the original <see cref="T:System.Collections.Generic.ICollection`1"/>.
|
||||
/// </returns>
|
||||
/// <param name="item">The object to remove from the <see cref="T:System.Collections.Generic.ICollection`1"/>.</param><exception cref="T:System.NotSupportedException">The <see cref="T:System.Collections.Generic.ICollection`1"/> is read-only.</exception>
|
||||
public bool Remove(T item)
|
||||
public bool Remove([NotNull] T item)
|
||||
{
|
||||
// ReSharper disable CompareNonConstrainedGenericWithNull
|
||||
if (item == null)
|
||||
@@ -333,7 +340,7 @@ namespace ICD.Common.Utils.Collections
|
||||
/// Removes each of the items in the sequence from the collection.
|
||||
/// </summary>
|
||||
/// <param name="items"></param>
|
||||
public void RemoveRange(IEnumerable<T> items)
|
||||
public void RemoveRange([NotNull] IEnumerable<T> items)
|
||||
{
|
||||
if (items == null)
|
||||
throw new ArgumentNullException("items");
|
||||
@@ -352,6 +359,7 @@ namespace ICD.Common.Utils.Collections
|
||||
/// A <see cref="T:System.Collections.Generic.IEnumerator`1"/> that can be used to iterate through the collection.
|
||||
/// </returns>
|
||||
/// <filterpriority>1</filterpriority>
|
||||
[NotNull]
|
||||
public IEnumerator<T> GetEnumerator()
|
||||
{
|
||||
return m_Dict.Keys.GetEnumerator();
|
||||
@@ -364,6 +372,7 @@ namespace ICD.Common.Utils.Collections
|
||||
/// An <see cref="T:System.Collections.IEnumerator"/> object that can be used to iterate through the collection.
|
||||
/// </returns>
|
||||
/// <filterpriority>2</filterpriority>
|
||||
[NotNull]
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
{
|
||||
return GetEnumerator();
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using ICD.Common.Properties;
|
||||
using ICD.Common.Utils.Extensions;
|
||||
|
||||
namespace ICD.Common.Utils.Collections
|
||||
@@ -19,11 +20,14 @@ namespace ICD.Common.Utils.Collections
|
||||
|
||||
public bool IsReadOnly { get { return false; } }
|
||||
|
||||
[NotNull]
|
||||
public ICollection<TKey> Keys { get { return m_OrderedKeys; } }
|
||||
|
||||
[NotNull]
|
||||
public ICollection<TValue> Values { get { return m_ValuesOrderedByKey; } }
|
||||
|
||||
public TValue this[TKey key]
|
||||
[CanBeNull]
|
||||
public TValue this[[NotNull] TKey key]
|
||||
{
|
||||
get { return m_Dictionary[key]; }
|
||||
set
|
||||
@@ -32,13 +36,8 @@ namespace ICD.Common.Utils.Collections
|
||||
if (key == null)
|
||||
throw new ArgumentNullException("key");
|
||||
|
||||
if (!ContainsKey(key))
|
||||
{
|
||||
int index = m_OrderedKeys.AddSorted(key, m_Comparer);
|
||||
m_ValuesOrderedByKey.Insert(index, value);
|
||||
}
|
||||
|
||||
m_Dictionary[key] = value;
|
||||
Remove(key);
|
||||
Add(key, value);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -56,7 +55,7 @@ namespace ICD.Common.Utils.Collections
|
||||
/// Constructor.
|
||||
/// </summary>
|
||||
/// <param name="comparer"></param>
|
||||
public IcdOrderedDictionary(IComparer<TKey> comparer)
|
||||
public IcdOrderedDictionary([NotNull] IComparer<TKey> comparer)
|
||||
: this(comparer, EqualityComparer<TKey>.Default)
|
||||
{
|
||||
}
|
||||
@@ -66,7 +65,7 @@ namespace ICD.Common.Utils.Collections
|
||||
/// </summary>
|
||||
/// <param name="comparer"></param>
|
||||
/// <param name="equalityComparer"></param>
|
||||
public IcdOrderedDictionary(IComparer<TKey> comparer, IEqualityComparer<TKey> equalityComparer)
|
||||
public IcdOrderedDictionary([NotNull] IComparer<TKey> comparer, [NotNull] IEqualityComparer<TKey> equalityComparer)
|
||||
{
|
||||
if (comparer == null)
|
||||
throw new ArgumentNullException("comparer");
|
||||
@@ -84,7 +83,7 @@ namespace ICD.Common.Utils.Collections
|
||||
/// Constructor.
|
||||
/// </summary>
|
||||
/// <param name="dictionary"></param>
|
||||
public IcdOrderedDictionary(IEnumerable<KeyValuePair<TKey, TValue>> dictionary)
|
||||
public IcdOrderedDictionary([NotNull] IEnumerable<KeyValuePair<TKey, TValue>> dictionary)
|
||||
: this()
|
||||
{
|
||||
if (dictionary == null)
|
||||
@@ -96,22 +95,27 @@ namespace ICD.Common.Utils.Collections
|
||||
|
||||
#region Methods
|
||||
|
||||
[NotNull]
|
||||
public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
|
||||
{
|
||||
return m_OrderedKeys.Select(k => new KeyValuePair<TKey, TValue>(k, m_Dictionary[k]))
|
||||
.GetEnumerator();
|
||||
}
|
||||
|
||||
public void Add(TKey key, TValue value)
|
||||
public void Add([NotNull] TKey key, [CanBeNull] TValue value)
|
||||
{
|
||||
// ReSharper disable once CompareNonConstrainedGenericWithNull
|
||||
// ReSharper disable CompareNonConstrainedGenericWithNull
|
||||
if (key == null)
|
||||
// ReSharper restore CompareNonConstrainedGenericWithNull
|
||||
throw new ArgumentNullException("key");
|
||||
|
||||
if (m_Dictionary.ContainsKey(key))
|
||||
throw new ArgumentException("An item with the same key has already been added.", "key");
|
||||
throw new ArgumentOutOfRangeException("key", "An item with the same key has already been added.");
|
||||
|
||||
this[key] = value;
|
||||
int index = m_OrderedKeys.InsertSorted(key, m_Comparer);
|
||||
m_ValuesOrderedByKey.Insert(index, value);
|
||||
|
||||
m_Dictionary[key] = value;
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
@@ -121,15 +125,21 @@ namespace ICD.Common.Utils.Collections
|
||||
m_Dictionary.Clear();
|
||||
}
|
||||
|
||||
public bool ContainsKey(TKey key)
|
||||
public bool ContainsKey([NotNull] TKey key)
|
||||
{
|
||||
// ReSharper disable CompareNonConstrainedGenericWithNull
|
||||
if (key == null)
|
||||
// ReSharper restore CompareNonConstrainedGenericWithNull
|
||||
throw new ArgumentNullException("key");
|
||||
|
||||
return m_Dictionary.ContainsKey(key);
|
||||
}
|
||||
|
||||
public bool Remove(TKey key)
|
||||
public bool Remove([NotNull] TKey key)
|
||||
{
|
||||
// ReSharper disable once CompareNonConstrainedGenericWithNull
|
||||
// ReSharper disable CompareNonConstrainedGenericWithNull
|
||||
if (key == null)
|
||||
// ReSharper restore CompareNonConstrainedGenericWithNull
|
||||
throw new ArgumentNullException("key");
|
||||
|
||||
if (!m_Dictionary.Remove(key))
|
||||
@@ -143,8 +153,13 @@ namespace ICD.Common.Utils.Collections
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool TryGetValue(TKey key, out TValue value)
|
||||
public bool TryGetValue([NotNull] TKey key, out TValue value)
|
||||
{
|
||||
// ReSharper disable CompareNonConstrainedGenericWithNull
|
||||
if (key == null)
|
||||
// ReSharper restore CompareNonConstrainedGenericWithNull
|
||||
throw new ArgumentNullException("key");
|
||||
|
||||
return m_Dictionary.TryGetValue(key, out value);
|
||||
}
|
||||
|
||||
@@ -152,6 +167,7 @@ namespace ICD.Common.Utils.Collections
|
||||
|
||||
#region Private Methods
|
||||
|
||||
[NotNull]
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
{
|
||||
return GetEnumerator();
|
||||
@@ -169,8 +185,11 @@ namespace ICD.Common.Utils.Collections
|
||||
EqualityComparer<TValue>.Default.Equals(value, item.Value);
|
||||
}
|
||||
|
||||
void ICollection<KeyValuePair<TKey, TValue>>.CopyTo(KeyValuePair<TKey, TValue>[] array, int index)
|
||||
void ICollection<KeyValuePair<TKey, TValue>>.CopyTo([NotNull] KeyValuePair<TKey, TValue>[] array, int index)
|
||||
{
|
||||
if (array == null)
|
||||
throw new ArgumentNullException("array");
|
||||
|
||||
foreach (KeyValuePair<TKey, TValue> kvp in this)
|
||||
{
|
||||
array.SetValue(kvp, index);
|
||||
|
||||
@@ -30,6 +30,7 @@ namespace ICD.Common.Utils.Collections
|
||||
/// <summary>
|
||||
/// Gets a reference for locking.
|
||||
/// </summary>
|
||||
[NotNull]
|
||||
public object SyncRoot { get { return this; } }
|
||||
|
||||
#endregion
|
||||
@@ -59,7 +60,7 @@ namespace ICD.Common.Utils.Collections
|
||||
/// </summary>
|
||||
/// <param name="item"></param>
|
||||
[PublicAPI]
|
||||
public void Enqueue(T item)
|
||||
public void Enqueue([CanBeNull] T item)
|
||||
{
|
||||
Enqueue(item, int.MaxValue);
|
||||
}
|
||||
@@ -71,16 +72,24 @@ namespace ICD.Common.Utils.Collections
|
||||
/// <param name="item"></param>
|
||||
/// <param name="priority"></param>
|
||||
[PublicAPI]
|
||||
public void Enqueue(T item, int priority)
|
||||
public void Enqueue([CanBeNull] T item, int priority)
|
||||
{
|
||||
List<T> queue;
|
||||
if (!m_PriorityToQueue.TryGetValue(priority, out queue))
|
||||
{
|
||||
queue = new List<T>();
|
||||
m_PriorityToQueue.Add(priority, queue);
|
||||
}
|
||||
m_PriorityToQueue.GetOrAddNew(priority, () => new List<T>())
|
||||
.Add(item);
|
||||
m_Count++;
|
||||
}
|
||||
|
||||
queue.Add(item);
|
||||
/// <summary>
|
||||
/// Adds the item to the queue with the given priority at the given index.
|
||||
/// </summary>
|
||||
/// <param name="item"></param>
|
||||
/// <param name="priority"></param>
|
||||
/// <param name="position"></param>
|
||||
[PublicAPI]
|
||||
public void Enqueue([CanBeNull] T item, int priority, int position)
|
||||
{
|
||||
m_PriorityToQueue.GetOrAddNew(priority, ()=> new List<T>())
|
||||
.Insert(position, item);
|
||||
m_Count++;
|
||||
}
|
||||
|
||||
@@ -89,30 +98,22 @@ namespace ICD.Common.Utils.Collections
|
||||
/// </summary>
|
||||
/// <param name="item"></param>
|
||||
[PublicAPI]
|
||||
public void EnqueueFirst(T item)
|
||||
public void EnqueueFirst([CanBeNull] T item)
|
||||
{
|
||||
const int priority = int.MinValue;
|
||||
|
||||
List<T> queue;
|
||||
if (!m_PriorityToQueue.TryGetValue(priority, out queue))
|
||||
{
|
||||
queue = new List<T>();
|
||||
m_PriorityToQueue.Add(priority, queue);
|
||||
}
|
||||
|
||||
queue.Insert(0, item);
|
||||
m_PriorityToQueue.GetOrAddNew(int.MinValue, () => new List<T>())
|
||||
.Insert(0, item);
|
||||
m_Count++;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes any items in the queue matching the predicate.
|
||||
/// Inserts the given item in the position of the first removed item, or at the end of the queue.
|
||||
/// This is useful for reducing duplication, or replacing items with something more pertinant.
|
||||
/// Appends the given item at the end of the given priority level.
|
||||
/// This is useful for reducing duplication, or replacing items with something more pertinent.
|
||||
/// </summary>
|
||||
/// <param name="item"></param>
|
||||
/// <param name="remove"></param>
|
||||
[PublicAPI]
|
||||
public void EnqueueRemove(T item, Func<T, bool> remove)
|
||||
public void EnqueueRemove([CanBeNull] T item, [NotNull] Func<T, bool> remove)
|
||||
{
|
||||
if (remove == null)
|
||||
throw new ArgumentNullException("remove");
|
||||
@@ -122,19 +123,38 @@ namespace ICD.Common.Utils.Collections
|
||||
|
||||
/// <summary>
|
||||
/// Removes any items in the queue matching the predicate.
|
||||
/// Inserts the given item in the position of the first removed item, or at the end of the queue.
|
||||
/// This is useful for reducing duplication, or replacing items with something more pertinant.
|
||||
/// Appends the given item at the end of the given priority level.
|
||||
/// This is useful for reducing duplication, or replacing items with something more pertinent.
|
||||
/// </summary>
|
||||
/// <param name="item"></param>
|
||||
/// <param name="remove"></param>
|
||||
/// <param name="priority"></param>
|
||||
[PublicAPI]
|
||||
public void EnqueueRemove(T item, Func<T, bool> remove, int priority)
|
||||
public void EnqueueRemove([CanBeNull] T item, [NotNull] Func<T, bool> remove, int priority)
|
||||
{
|
||||
if (remove == null)
|
||||
throw new ArgumentNullException("remove");
|
||||
|
||||
bool inserted = false;
|
||||
EnqueueRemove(item, remove, priority, false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes any items in the queue matching the predicate.
|
||||
/// Appends the given item at the end of the given priority level.
|
||||
/// This is useful for reducing duplication, or replacing items with something more pertinent.
|
||||
/// </summary>
|
||||
/// <param name="item"></param>
|
||||
/// <param name="remove"></param>
|
||||
/// <param name="priority"></param>
|
||||
/// <param name="deDuplicateToEndOfQueue"></param>
|
||||
[PublicAPI]
|
||||
public void EnqueueRemove([CanBeNull] T item, [NotNull] Func<T, bool> remove, int priority, bool deDuplicateToEndOfQueue)
|
||||
{
|
||||
if (remove == null)
|
||||
throw new ArgumentNullException("remove");
|
||||
|
||||
int lowestMatchingPriority = int.MaxValue;
|
||||
int? firstMatchingIndex = null;
|
||||
|
||||
foreach (KeyValuePair<int, List<T>> kvp in m_PriorityToQueue.ToArray())
|
||||
{
|
||||
@@ -144,8 +164,11 @@ namespace ICD.Common.Utils.Collections
|
||||
.Reverse()
|
||||
.ToArray();
|
||||
|
||||
if (removeIndices.Length == 0)
|
||||
continue;
|
||||
if (removeIndices.Any() && kvp.Key < lowestMatchingPriority )
|
||||
{
|
||||
lowestMatchingPriority = kvp.Key;
|
||||
firstMatchingIndex = removeIndices.Last();
|
||||
}
|
||||
|
||||
foreach (int removeIndex in removeIndices)
|
||||
{
|
||||
@@ -153,26 +176,20 @@ namespace ICD.Common.Utils.Collections
|
||||
m_Count--;
|
||||
}
|
||||
|
||||
if (!inserted)
|
||||
{
|
||||
int insertIndex = removeIndices[0];
|
||||
|
||||
if (insertIndex >= kvp.Value.Count)
|
||||
kvp.Value.Add(item);
|
||||
else
|
||||
kvp.Value.Insert(insertIndex, item);
|
||||
|
||||
m_Count++;
|
||||
|
||||
inserted = true;
|
||||
}
|
||||
|
||||
if (kvp.Value.Count == 0)
|
||||
m_PriorityToQueue.Remove(kvp.Key);
|
||||
}
|
||||
|
||||
if (!inserted)
|
||||
|
||||
if(deDuplicateToEndOfQueue)
|
||||
Enqueue(item, priority);
|
||||
else
|
||||
{
|
||||
if(firstMatchingIndex == null)
|
||||
Enqueue(item, lowestMatchingPriority);
|
||||
else
|
||||
Enqueue(item, lowestMatchingPriority, firstMatchingIndex.Value);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -180,6 +197,7 @@ namespace ICD.Common.Utils.Collections
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[PublicAPI]
|
||||
[CanBeNull]
|
||||
public T Dequeue()
|
||||
{
|
||||
T output;
|
||||
@@ -227,6 +245,7 @@ namespace ICD.Common.Utils.Collections
|
||||
/// Gets an enumerator for the items.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[NotNull]
|
||||
public IEnumerator<T> GetEnumerator()
|
||||
{
|
||||
return m_PriorityToQueue.Values
|
||||
@@ -239,8 +258,11 @@ namespace ICD.Common.Utils.Collections
|
||||
/// </summary>
|
||||
/// <param name="array"></param>
|
||||
/// <param name="index"></param>
|
||||
public void CopyTo(Array array, int index)
|
||||
public void CopyTo([NotNull] Array array, int index)
|
||||
{
|
||||
if (array == null)
|
||||
throw new ArgumentNullException("array");
|
||||
|
||||
foreach (T item in this)
|
||||
array.SetValue(item, index++);
|
||||
}
|
||||
@@ -253,6 +275,7 @@ namespace ICD.Common.Utils.Collections
|
||||
/// Gets an enumerator for the items.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[NotNull]
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
{
|
||||
return GetEnumerator();
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using ICD.Common.Properties;
|
||||
using ICD.Common.Utils.EventArguments;
|
||||
using ICD.Common.Utils.Extensions;
|
||||
using ICD.Common.Utils.Timers;
|
||||
@@ -32,6 +33,7 @@ namespace ICD.Common.Utils.Collections
|
||||
|
||||
bool ICollection.IsSynchronized { get { return true; } }
|
||||
|
||||
[NotNull]
|
||||
object ICollection.SyncRoot { get { return this; } }
|
||||
|
||||
#endregion
|
||||
@@ -72,7 +74,7 @@ namespace ICD.Common.Utils.Collections
|
||||
/// Enqueues the given item.
|
||||
/// </summary>
|
||||
/// <param name="item"></param>
|
||||
public void Enqueue(T item)
|
||||
public void Enqueue([CanBeNull] T item)
|
||||
{
|
||||
m_QueueSection.Enter();
|
||||
|
||||
@@ -158,18 +160,23 @@ namespace ICD.Common.Utils.Collections
|
||||
|
||||
#region IEnumerable/ICollection
|
||||
|
||||
[NotNull]
|
||||
public IEnumerator<T> GetEnumerator()
|
||||
{
|
||||
return m_QueueSection.Execute(() => m_Queue.ToList(m_Queue.Count).GetEnumerator());
|
||||
}
|
||||
|
||||
[NotNull]
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
{
|
||||
return GetEnumerator();
|
||||
}
|
||||
|
||||
void ICollection.CopyTo(Array array, int index)
|
||||
void ICollection.CopyTo([NotNull] Array array, int index)
|
||||
{
|
||||
if (array == null)
|
||||
throw new ArgumentNullException("array");
|
||||
|
||||
m_QueueSection.Enter();
|
||||
|
||||
try
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using ICD.Common.Properties;
|
||||
using ICD.Common.Utils.EventArguments;
|
||||
using ICD.Common.Utils.Extensions;
|
||||
|
||||
namespace ICD.Common.Utils.Collections
|
||||
{
|
||||
@@ -15,6 +17,11 @@ namespace ICD.Common.Utils.Collections
|
||||
private readonly LinkedList<TContents> m_Collection;
|
||||
private int m_MaxSize;
|
||||
|
||||
/// <summary>
|
||||
/// Raised when an item is trimmed from the end of the queue.
|
||||
/// </summary>
|
||||
public event EventHandler<GenericEventArgs<TContents>> OnItemTrimmed;
|
||||
|
||||
#region Properties
|
||||
|
||||
/// <summary>
|
||||
@@ -141,7 +148,11 @@ namespace ICD.Common.Utils.Collections
|
||||
private void Trim()
|
||||
{
|
||||
while (Count > MaxSize)
|
||||
{
|
||||
TContents removed = m_Collection.First.Value;
|
||||
m_Collection.RemoveFirst();
|
||||
OnItemTrimmed.Raise(this, new GenericEventArgs<TContents>(removed));
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -1,108 +0,0 @@
|
||||
using System;
|
||||
|
||||
namespace ICD.Common.Utils
|
||||
{
|
||||
public enum eConsoleColor
|
||||
{
|
||||
Red,
|
||||
Green,
|
||||
Yellow,
|
||||
Blue,
|
||||
Magenta,
|
||||
Cyan,
|
||||
White,
|
||||
YellowOnRed
|
||||
}
|
||||
|
||||
public static class ConsoleColorExtensions
|
||||
{
|
||||
public const string CONSOLE_RED = "\x1B[31;1m";
|
||||
public const string CONSOLE_GREEN = "\x1B[32;1m";
|
||||
public const string CONSOLE_YELLOW = "\x1B[33;1m";
|
||||
public const string CONSOLE_BLUE = "\x1B[34;1m";
|
||||
public const string CONSOLE_MAGENTA = "\x1B[35;1m";
|
||||
public const string CONSOLE_CYAN = "\x1B[36;1m";
|
||||
public const string CONSOLE_WHITE = "\x1B[37;1m";
|
||||
public const string CONSOLE_YELLOW_ON_RED_BACKGROUND = "\x1B[93;41m";
|
||||
public const string CONSOLE_RESET = "\x1B[0m";
|
||||
|
||||
public static string FormatAnsi(this eConsoleColor extends, string data)
|
||||
{
|
||||
return string.Format("{0}{1}{2}", extends.ToAnsiPrefix(), data, CONSOLE_RESET);
|
||||
}
|
||||
|
||||
public static string ToAnsiPrefix(this eConsoleColor extends)
|
||||
{
|
||||
switch (extends)
|
||||
{
|
||||
case eConsoleColor.Red:
|
||||
return CONSOLE_RED;
|
||||
case eConsoleColor.Green:
|
||||
return CONSOLE_GREEN;
|
||||
case eConsoleColor.Yellow:
|
||||
return CONSOLE_YELLOW;
|
||||
case eConsoleColor.Blue:
|
||||
return CONSOLE_BLUE;
|
||||
case eConsoleColor.Magenta:
|
||||
return CONSOLE_MAGENTA;
|
||||
case eConsoleColor.Cyan:
|
||||
return CONSOLE_CYAN;
|
||||
case eConsoleColor.White:
|
||||
return CONSOLE_WHITE;
|
||||
case eConsoleColor.YellowOnRed:
|
||||
return CONSOLE_YELLOW_ON_RED_BACKGROUND;
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException("extends");
|
||||
}
|
||||
}
|
||||
|
||||
#if STANDARD
|
||||
|
||||
public static ConsoleColor ToForegroundConsoleColor(this eConsoleColor extends)
|
||||
{
|
||||
switch (extends)
|
||||
{
|
||||
case eConsoleColor.Red:
|
||||
return ConsoleColor.Red;
|
||||
case eConsoleColor.Green:
|
||||
return ConsoleColor.Green;
|
||||
case eConsoleColor.Yellow:
|
||||
case eConsoleColor.YellowOnRed:
|
||||
return ConsoleColor.Yellow;
|
||||
case eConsoleColor.Blue:
|
||||
return ConsoleColor.Blue;
|
||||
case eConsoleColor.Magenta:
|
||||
return ConsoleColor.Magenta;
|
||||
case eConsoleColor.Cyan:
|
||||
return ConsoleColor.Cyan;
|
||||
case eConsoleColor.White:
|
||||
return ConsoleColor.White;
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException("extends");
|
||||
}
|
||||
}
|
||||
|
||||
public static ConsoleColor ToBackgroundConsoleColor(this eConsoleColor extends)
|
||||
{
|
||||
switch (extends)
|
||||
{
|
||||
case eConsoleColor.Red:
|
||||
case eConsoleColor.Green:
|
||||
case eConsoleColor.Yellow:
|
||||
case eConsoleColor.Blue:
|
||||
case eConsoleColor.Magenta:
|
||||
case eConsoleColor.Cyan:
|
||||
case eConsoleColor.White:
|
||||
return ConsoleColor.Black;
|
||||
|
||||
case eConsoleColor.YellowOnRed:
|
||||
return ConsoleColor.Red;
|
||||
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException("extends");
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@@ -11,33 +11,81 @@ namespace ICD.Common.Utils.Csv
|
||||
private const string DOUBLE_QUOTE_MARK = "\"\"";
|
||||
|
||||
private readonly IcdTextWriter m_Writer;
|
||||
|
||||
private readonly string m_Seperator;
|
||||
private readonly string m_LineTerminator;
|
||||
private readonly bool m_AlwaysEscape;
|
||||
|
||||
private readonly CsvWriterSettings m_Settings;
|
||||
private bool m_NewLine;
|
||||
|
||||
#region Properties
|
||||
|
||||
private string Separator { get { return m_Settings.InsertSpaceAfterComma ? ", " : ","; } }
|
||||
|
||||
private string LineTerminator { get { return m_Settings.NewLineSequence; } }
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
|
||||
/// <summary>
|
||||
/// Constructor.
|
||||
/// </summary>
|
||||
public CsvWriter(IcdTextWriter writer, bool spaceAfterComma, bool alwaysEscape, string newline, params string[] header)
|
||||
public CsvWriter([NotNull] IcdTextWriter writer, [NotNull] CsvWriterSettings settings, [NotNull] params string[] header)
|
||||
{
|
||||
if (writer == null)
|
||||
throw new ArgumentNullException("writer");
|
||||
|
||||
if (settings == null)
|
||||
throw new ArgumentNullException("settings");
|
||||
|
||||
if (header == null)
|
||||
throw new ArgumentNullException("header");
|
||||
|
||||
m_NewLine = true;
|
||||
m_Writer = writer;
|
||||
m_Seperator = spaceAfterComma ? ", " : ",";
|
||||
m_AlwaysEscape = alwaysEscape;
|
||||
m_LineTerminator = newline;
|
||||
m_Settings = settings;
|
||||
|
||||
if(header.Any())
|
||||
if (header.Any())
|
||||
AppendRow(header);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Deconstructor.
|
||||
/// </summary>
|
||||
~CsvWriter()
|
||||
{
|
||||
Dispose();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Instantiates a new CsvWriter with the properties given in the CsvWriterSettings.
|
||||
/// </summary>
|
||||
/// <param name="writer"></param>
|
||||
/// <param name="settings"></param>
|
||||
/// <param name="header"></param>
|
||||
/// <returns></returns>
|
||||
[PublicAPI]
|
||||
public static CsvWriter Create([NotNull] IcdTextWriter writer, [NotNull] CsvWriterSettings settings,
|
||||
[NotNull] params string[] header)
|
||||
{
|
||||
if (writer == null)
|
||||
throw new ArgumentNullException("writer");
|
||||
|
||||
if (settings == null)
|
||||
throw new ArgumentNullException("settings");
|
||||
|
||||
if (header == null)
|
||||
throw new ArgumentNullException("header");
|
||||
|
||||
return new CsvWriter(writer, settings, header);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
m_Writer.Dispose();
|
||||
}
|
||||
|
||||
#region Methods
|
||||
|
||||
/// <summary>
|
||||
/// Calls ToString() for each item and adds the row to the builder.
|
||||
/// </summary>
|
||||
@@ -82,9 +130,9 @@ namespace ICD.Common.Utils.Csv
|
||||
value = value ?? string.Empty;
|
||||
|
||||
if (!m_NewLine)
|
||||
m_Writer.WrappedTextWriter.Write(m_Seperator);
|
||||
m_Writer.WrappedTextWriter.Write(Separator);
|
||||
|
||||
if (m_AlwaysEscape || value.Contains(","))
|
||||
if (m_Settings.AlwaysEscapeEveryValue || value.Contains(","))
|
||||
{
|
||||
value = value.Replace(QUOTATION_MARK, DOUBLE_QUOTE_MARK);
|
||||
|
||||
@@ -107,31 +155,11 @@ namespace ICD.Common.Utils.Csv
|
||||
[PublicAPI]
|
||||
public void AppendNewline()
|
||||
{
|
||||
m_Writer.WrappedTextWriter.Write(m_LineTerminator);
|
||||
m_Writer.WrappedTextWriter.Write(LineTerminator);
|
||||
|
||||
m_NewLine = true;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
m_Writer.Dispose();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Instantiates a new CsvWriter with the properties given in the CsvWriterSettings.
|
||||
/// </summary>
|
||||
/// <param name="writer"></param>
|
||||
/// <param name="settings"></param>
|
||||
/// <param name="header"></param>
|
||||
/// <returns></returns>
|
||||
[PublicAPI]
|
||||
public static CsvWriter Create(IcdTextWriter writer, CsvWriterSettings settings, params string[] header)
|
||||
{
|
||||
return new CsvWriter(writer,
|
||||
settings.InsertSpaceAfterComma,
|
||||
settings.AlwaysEscapeEveryValue,
|
||||
settings.NewLineSequence,
|
||||
header);
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
48
ICD.Common.Utils/DateTimeUtils.cs
Normal file
48
ICD.Common.Utils/DateTimeUtils.cs
Normal file
@@ -0,0 +1,48 @@
|
||||
using System;
|
||||
using System.Globalization;
|
||||
|
||||
namespace ICD.Common.Utils
|
||||
{
|
||||
public static class DateTimeUtils
|
||||
{
|
||||
/// <summary>
|
||||
/// Converts the hour in 24 hour format to 12 hour format (1 through 12).
|
||||
/// </summary>
|
||||
/// <param name="hour"></param>
|
||||
/// <returns></returns>
|
||||
public static int To12Hour(int hour)
|
||||
{
|
||||
return MathUtils.Modulus(hour + 11, 12) + 1;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a DateTime from the given number of milliseconds since the epoch (1970-01-01T00:00:00Z)
|
||||
/// </summary>
|
||||
/// <param name="milliseconds">milliseconds since the epoch</param>
|
||||
/// <returns></returns>
|
||||
public static DateTime FromEpochMilliseconds(long milliseconds)
|
||||
{
|
||||
return new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).AddMilliseconds(milliseconds);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a DateTime from the given number of seconds since the epoch (1970-01-01T00:00:00Z)
|
||||
/// </summary>
|
||||
/// <param name="seconds">seconds since the epoch</param>
|
||||
/// <returns></returns>
|
||||
public static DateTime FromEpochSeconds(long seconds)
|
||||
{
|
||||
return FromEpochMilliseconds(seconds * 1000);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a DateTime for the given ISO-8601 string.
|
||||
/// </summary>
|
||||
/// <param name="iso"></param>
|
||||
/// <returns></returns>
|
||||
public static DateTime FromIso8601(string iso)
|
||||
{
|
||||
return DateTime.Parse(iso, null, DateTimeStyles.RoundtripKind);
|
||||
}
|
||||
}
|
||||
}
|
||||
14
ICD.Common.Utils/Email/EmailValidation.cs
Normal file
14
ICD.Common.Utils/Email/EmailValidation.cs
Normal file
@@ -0,0 +1,14 @@
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace ICD.Common.Utils.Email
|
||||
{
|
||||
public static class EmailValidation
|
||||
{
|
||||
private const string EMAIL_REGEX = @"(?:[a-z0-9!#$%&'*+\/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+\/=?^_`{|}~-]+)*|""(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*"")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\[(?:(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9]))\.){3}(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9])|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\])";
|
||||
|
||||
public static bool IsValidEmailAddress(string emailAddress)
|
||||
{
|
||||
return emailAddress != null && Regex.IsMatch(emailAddress, EMAIL_REGEX);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -13,16 +13,16 @@ namespace ICD.Common.Utils
|
||||
{
|
||||
public static class EnumUtils
|
||||
{
|
||||
private static readonly Dictionary<Type, object> s_EnumValuesCache;
|
||||
private static readonly Dictionary<Type, Dictionary<int, object>> s_EnumFlagsCache;
|
||||
private static readonly Dictionary<Type, object[]> s_EnumValuesCache;
|
||||
private static readonly Dictionary<Type, Dictionary<object, object[]>> s_EnumFlagsCache;
|
||||
|
||||
/// <summary>
|
||||
/// Static constructor.
|
||||
/// </summary>
|
||||
static EnumUtils()
|
||||
{
|
||||
s_EnumValuesCache = new Dictionary<Type, object>();
|
||||
s_EnumFlagsCache = new Dictionary<Type, Dictionary<int, object>>();
|
||||
s_EnumValuesCache = new Dictionary<Type, object[]>();
|
||||
s_EnumFlagsCache = new Dictionary<Type, Dictionary<object, object[]>>();
|
||||
}
|
||||
|
||||
#region Validation
|
||||
@@ -58,7 +58,6 @@ namespace ICD.Common.Utils
|
||||
/// <returns></returns>
|
||||
public static bool IsEnum<T>(T value)
|
||||
{
|
||||
// ReSharper disable once CompareNonConstrainedGenericWithNull
|
||||
return value != null && IsEnumType(value.GetType());
|
||||
}
|
||||
|
||||
@@ -123,6 +122,30 @@ namespace ICD.Common.Utils
|
||||
|
||||
#region Values
|
||||
|
||||
/// <summary>
|
||||
/// Gets the names of the values in the enumeration.
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <returns></returns>
|
||||
public static IEnumerable<string> GetNames<T>()
|
||||
where T : struct, IConvertible
|
||||
{
|
||||
return GetNames(typeof(T));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the names of the values in the enumeration.
|
||||
/// </summary>
|
||||
/// <param name="type"></param>
|
||||
/// <returns></returns>
|
||||
public static IEnumerable<string> GetNames([NotNull] Type type)
|
||||
{
|
||||
if (type == null)
|
||||
throw new ArgumentNullException("type");
|
||||
|
||||
return GetValues(type).Select(v => v.ToString());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the values from an enumeration.
|
||||
/// </summary>
|
||||
@@ -131,46 +154,51 @@ namespace ICD.Common.Utils
|
||||
public static IEnumerable<T> GetValues<T>()
|
||||
where T : struct, IConvertible
|
||||
{
|
||||
Type type = typeof(T);
|
||||
|
||||
// Reflection is slow and this method is called a lot, so we cache the results.
|
||||
object cache;
|
||||
if (!s_EnumValuesCache.TryGetValue(type, out cache))
|
||||
{
|
||||
cache = GetValuesUncached<T>().ToArray();
|
||||
s_EnumValuesCache[type] = cache;
|
||||
}
|
||||
|
||||
return cache as T[];
|
||||
return GetValues(typeof(T)).Cast<T>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the values from an enumeration without performing any caching. This is slow because of reflection.
|
||||
/// Gets the values from an enumeration.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public static IEnumerable<int> GetValues(Type type)
|
||||
public static IEnumerable<object> GetValues(Type type)
|
||||
{
|
||||
if (type == null)
|
||||
throw new ArgumentNullException("type");
|
||||
|
||||
return GetValuesUncached(type);
|
||||
// Reflection is slow and this method is called a lot, so we cache the results.
|
||||
return s_EnumValuesCache.GetOrAddNew(type, () => GetValuesUncached(type).ToArray());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the values from an enumeration without performing any caching. This is slow because of reflection.
|
||||
/// Gets the values from an enumeration except the 0 value.
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <returns></returns>
|
||||
private static IEnumerable<T> GetValuesUncached<T>()
|
||||
public static IEnumerable<T> GetValuesExceptNone<T>()
|
||||
where T : struct, IConvertible
|
||||
{
|
||||
return GetValuesUncached(typeof(T)).Select(i => (T)(object)i);
|
||||
return GetValuesExceptNone(typeof(T)).Cast<T>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the values from an enumeration except the 0 value.
|
||||
/// </summary>
|
||||
/// <param name="type"></param>
|
||||
/// <returns></returns>
|
||||
public static IEnumerable<object> GetValuesExceptNone([NotNull] Type type)
|
||||
{
|
||||
if (type == null)
|
||||
throw new ArgumentNullException("type");
|
||||
|
||||
return GetFlagsExceptNone(type);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the values from an enumeration without performing any caching. This is slow because of reflection.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
private static IEnumerable<int> GetValuesUncached(Type type)
|
||||
private static IEnumerable<object> GetValuesUncached(Type type)
|
||||
{
|
||||
if (type == null)
|
||||
throw new ArgumentNullException("type");
|
||||
@@ -182,34 +210,10 @@ namespace ICD.Common.Utils
|
||||
#if SIMPLSHARP
|
||||
.GetCType()
|
||||
#else
|
||||
.GetTypeInfo()
|
||||
.GetTypeInfo()
|
||||
#endif
|
||||
.GetFields(BindingFlags.Static | BindingFlags.Public)
|
||||
.Select(x => x.GetValue(null))
|
||||
.Cast<int>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the values from an enumeration except the 0 value.
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <returns></returns>
|
||||
public static IEnumerable<T> GetValuesExceptNone<T>()
|
||||
where T : struct, IConvertible
|
||||
{
|
||||
return GetFlagsExceptNone<T>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the values from an enumeration except the 0 value without performing any caching. This is slow because of reflection.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public static IEnumerable<int> GetValuesExceptNone(Type type)
|
||||
{
|
||||
if (type == null)
|
||||
throw new ArgumentNullException("type");
|
||||
|
||||
return GetValues(type).Except(0);
|
||||
.GetFields(BindingFlags.Static | BindingFlags.Public)
|
||||
.Select(x => x.GetValue(null));
|
||||
}
|
||||
|
||||
#endregion
|
||||
@@ -330,24 +334,21 @@ namespace ICD.Common.Utils
|
||||
public static IEnumerable<T> GetFlags<T>(T value)
|
||||
where T : struct, IConvertible
|
||||
{
|
||||
Type type = typeof(T);
|
||||
int valueInt = (int)(object)value;
|
||||
return GetFlags(typeof(T), value).Cast<T>();
|
||||
}
|
||||
|
||||
Dictionary<int, object> cache;
|
||||
if (!s_EnumFlagsCache.TryGetValue(type, out cache))
|
||||
{
|
||||
cache = new Dictionary<int, object>();
|
||||
s_EnumFlagsCache[type] = cache;
|
||||
}
|
||||
|
||||
object flags;
|
||||
if (!cache.TryGetValue(valueInt, out flags))
|
||||
{
|
||||
flags = GetValues<T>().Where(e => HasFlag(value, e)).ToArray();
|
||||
cache[valueInt] = flags;
|
||||
}
|
||||
|
||||
return flags as T[];
|
||||
/// <summary>
|
||||
/// Gets all of the set flags on the given enum.
|
||||
/// </summary>
|
||||
/// <param name="type"></param>
|
||||
/// <param name="value"></param>
|
||||
/// <returns></returns>
|
||||
public static IEnumerable<object> GetFlags(Type type, object value)
|
||||
{
|
||||
return s_EnumFlagsCache.GetOrAddNew(type, () => new Dictionary<object, object[]>())
|
||||
.GetOrAddNew(value, () => GetValues(type)
|
||||
.Where(f => HasFlag(value, f))
|
||||
.ToArray());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -358,8 +359,7 @@ namespace ICD.Common.Utils
|
||||
public static IEnumerable<T> GetFlagsExceptNone<T>()
|
||||
where T : struct, IConvertible
|
||||
{
|
||||
T allValue = GetFlagsAllValue<T>();
|
||||
return GetFlagsExceptNone(allValue);
|
||||
return GetFlagsExceptNone(typeof(T)).Cast<T>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -371,7 +371,35 @@ namespace ICD.Common.Utils
|
||||
public static IEnumerable<T> GetFlagsExceptNone<T>(T value)
|
||||
where T : struct, IConvertible
|
||||
{
|
||||
return GetFlags(value).Except(default(T));
|
||||
return GetFlagsExceptNone(typeof(T), value).Cast<T>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets all of the set flags on the given enum type except 0.
|
||||
/// </summary>
|
||||
/// <param name="type"></param>
|
||||
/// <returns></returns>
|
||||
public static IEnumerable<object> GetFlagsExceptNone([NotNull] Type type)
|
||||
{
|
||||
if (type == null)
|
||||
throw new ArgumentNullException("type");
|
||||
|
||||
object allValue = GetFlagsAllValue(type);
|
||||
return GetFlagsExceptNone(type, allValue);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets all of the set flags on the given enum except 0.
|
||||
/// </summary>
|
||||
/// <param name="type"></param>
|
||||
/// <param name="value"></param>
|
||||
/// <returns></returns>
|
||||
public static IEnumerable<object> GetFlagsExceptNone([NotNull] Type type, object value)
|
||||
{
|
||||
if (type == null)
|
||||
throw new ArgumentNullException("type");
|
||||
|
||||
return GetFlags(type, value).Where(f => (int)f != 0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -412,7 +440,7 @@ namespace ICD.Common.Utils
|
||||
if (type == null)
|
||||
throw new ArgumentNullException("type");
|
||||
|
||||
return GetValuesUncached(type).Aggregate(0, (current, value) => current | value);
|
||||
return GetValuesUncached(type).Aggregate(0, (current, value) => current | (int)value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -428,6 +456,17 @@ namespace ICD.Common.Utils
|
||||
return HasFlags(value, flag);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if the enum contains the given flag.
|
||||
/// </summary>
|
||||
/// <param name="value"></param>
|
||||
/// <param name="flag"></param>
|
||||
/// <returns></returns>
|
||||
public static bool HasFlag(object value, object flag)
|
||||
{
|
||||
return HasFlag((int)value, (int)flag);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if the enum contains the given flag.
|
||||
/// </summary>
|
||||
|
||||
15
ICD.Common.Utils/EventArguments/DateTimeNullableEventArgs.cs
Normal file
15
ICD.Common.Utils/EventArguments/DateTimeNullableEventArgs.cs
Normal file
@@ -0,0 +1,15 @@
|
||||
using System;
|
||||
|
||||
namespace ICD.Common.Utils.EventArguments
|
||||
{
|
||||
public sealed class DateTimeNullableEventArgs : GenericEventArgs<DateTime?>
|
||||
{
|
||||
/// <summary>
|
||||
/// Constructor.
|
||||
/// </summary>
|
||||
/// <param name="data"></param>
|
||||
public DateTimeNullableEventArgs(DateTime? data) : base(data)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,10 +4,17 @@ namespace ICD.Common.Utils.EventArguments
|
||||
{
|
||||
public class GenericEventArgs<T> : EventArgs, IGenericEventArgs<T>
|
||||
{
|
||||
private readonly T m_Data;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the wrapped data associated with the event.
|
||||
/// </summary>
|
||||
public T Data { get; private set; }
|
||||
object IGenericEventArgs.Data { get { return Data; } }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the wrapped data associated with the event.
|
||||
/// </summary>
|
||||
public T Data { get { return m_Data; } }
|
||||
|
||||
/// <summary>
|
||||
/// Constructor.
|
||||
@@ -15,7 +22,7 @@ namespace ICD.Common.Utils.EventArguments
|
||||
/// <param name="data"></param>
|
||||
public GenericEventArgs(T data)
|
||||
{
|
||||
Data = data;
|
||||
m_Data = data;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,18 @@
|
||||
namespace ICD.Common.Utils.EventArguments
|
||||
{
|
||||
public interface IGenericEventArgs<T>
|
||||
public interface IGenericEventArgs
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the wrapped data associated with the event.
|
||||
/// </summary>
|
||||
T Data { get; }
|
||||
object Data { get; }
|
||||
}
|
||||
|
||||
public interface IGenericEventArgs<T> : IGenericEventArgs
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the wrapped data associated with the event.
|
||||
/// </summary>
|
||||
new T Data { get; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@ namespace ICD.Common.Utils.Extensions
|
||||
/// <param name="extends"></param>
|
||||
/// <returns></returns>
|
||||
[CanBeNull]
|
||||
public static string GetPath(this Assembly extends)
|
||||
public static string GetPath([NotNull]this Assembly extends)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
@@ -29,7 +29,7 @@ namespace ICD.Common.Utils.Extensions
|
||||
#endif
|
||||
.CodeBase;
|
||||
|
||||
if (path == null)
|
||||
if (string.IsNullOrEmpty(path))
|
||||
{
|
||||
#if STANDARD
|
||||
path = extends.Location;
|
||||
@@ -51,7 +51,7 @@ namespace ICD.Common.Utils.Extensions
|
||||
/// <param name="extends"></param>
|
||||
/// <returns></returns>
|
||||
[PublicAPI]
|
||||
public static DateTime GetCreationTime(this Assembly extends)
|
||||
public static DateTime GetCreationTime([NotNull]this Assembly extends)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
@@ -66,7 +66,7 @@ namespace ICD.Common.Utils.Extensions
|
||||
/// <param name="extends"></param>
|
||||
/// <returns></returns>
|
||||
[PublicAPI]
|
||||
public static string GetInformationalVersion(this Assembly extends)
|
||||
public static string GetInformationalVersion([NotNull]this Assembly extends)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
@@ -85,7 +85,7 @@ namespace ICD.Common.Utils.Extensions
|
||||
/// <param name="version"></param>
|
||||
/// <returns></returns>
|
||||
[PublicAPI]
|
||||
public static bool TryGetInformationalVersion(this Assembly extends, out string version)
|
||||
public static bool TryGetInformationalVersion([NotNull]this Assembly extends, out string version)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
|
||||
91
ICD.Common.Utils/Extensions/CultureInfoExtensions.cs
Normal file
91
ICD.Common.Utils/Extensions/CultureInfoExtensions.cs
Normal file
@@ -0,0 +1,91 @@
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using ICD.Common.Properties;
|
||||
|
||||
namespace ICD.Common.Utils.Extensions
|
||||
{
|
||||
public static class CultureInfoExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Returns true if the given culture uses a 24 hour time format.
|
||||
/// </summary>
|
||||
/// <param name="extends"></param>
|
||||
/// <returns></returns>
|
||||
public static bool Uses24HourFormat([NotNull]this CultureInfo extends)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
|
||||
return extends.DateTimeFormat.ShortTimePattern.Contains("H");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates the time patterns for the given culture to use 12 hour time.
|
||||
/// </summary>
|
||||
/// <param name="extends"></param>
|
||||
public static void ConvertTo12HourCulture([NotNull]this CultureInfo extends)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
|
||||
if (extends.IsReadOnly)
|
||||
throw new InvalidOperationException("Culture is readonly");
|
||||
|
||||
DateTimeFormatInfo dateTimeFormat = extends.DateTimeFormat;
|
||||
|
||||
dateTimeFormat.FullDateTimePattern = To12HourPattern(dateTimeFormat.FullDateTimePattern);
|
||||
dateTimeFormat.LongTimePattern = To12HourPattern(dateTimeFormat.LongTimePattern);
|
||||
dateTimeFormat.ShortTimePattern = To12HourPattern(dateTimeFormat.ShortTimePattern);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates the time patterns for the given culture to use 24 hour time.
|
||||
/// </summary>
|
||||
/// <param name="extends"></param>
|
||||
public static void ConvertTo24HourCulture([NotNull]this CultureInfo extends)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
|
||||
if (extends.IsReadOnly)
|
||||
throw new InvalidOperationException("Culture is readonly");
|
||||
|
||||
DateTimeFormatInfo dateTimeFormat = extends.DateTimeFormat;
|
||||
|
||||
dateTimeFormat.FullDateTimePattern = To24HourPattern(dateTimeFormat.FullDateTimePattern);
|
||||
dateTimeFormat.LongTimePattern = To24HourPattern(dateTimeFormat.LongTimePattern);
|
||||
dateTimeFormat.ShortTimePattern = To24HourPattern(dateTimeFormat.ShortTimePattern);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts the given format pattern to use 24 hour time.
|
||||
/// </summary>
|
||||
/// <param name="pattern"></param>
|
||||
/// <returns></returns>
|
||||
private static string To24HourPattern(string pattern)
|
||||
{
|
||||
if (pattern == null)
|
||||
return null;
|
||||
|
||||
pattern = pattern.Replace(" tt", "");
|
||||
|
||||
return pattern.Replace("h", "H");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts the given format pattern to use 12 hour time.
|
||||
/// </summary>
|
||||
/// <param name="pattern"></param>
|
||||
/// <returns></returns>
|
||||
private static string To12HourPattern(string pattern)
|
||||
{
|
||||
if (pattern == null)
|
||||
return null;
|
||||
|
||||
if (!pattern.Contains("t"))
|
||||
pattern = pattern + " tt";
|
||||
|
||||
return pattern.Replace("H", "h");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,8 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using ICD.Common.Properties;
|
||||
|
||||
namespace ICD.Common.Utils.Extensions
|
||||
{
|
||||
@@ -37,14 +39,29 @@ namespace ICD.Common.Utils.Extensions
|
||||
/// <param name="inclusive">Whether or not to include times equal to the target time</param>
|
||||
/// <param name="times"></param>
|
||||
/// <returns></returns>
|
||||
public static DateTime? NextEarliestTime(this DateTime target, bool inclusive, params DateTime[] times)
|
||||
public static DateTime? NextEarliestTime(this DateTime target, bool inclusive, [NotNull] params DateTime[] times)
|
||||
{
|
||||
if (times == null)
|
||||
throw new ArgumentNullException("times");
|
||||
|
||||
return target.NextEarliestTime(inclusive, (IEnumerable<DateTime>)times);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the closest DateTime to the target time that is greater than the target time
|
||||
/// </summary>
|
||||
/// <param name="target"></param>
|
||||
/// <param name="inclusive">Whether or not to include times equal to the target time</param>
|
||||
/// <param name="times"></param>
|
||||
/// <returns></returns>
|
||||
public static DateTime? NextEarliestTime(this DateTime target, bool inclusive, [NotNull] IEnumerable<DateTime> times)
|
||||
{
|
||||
if (times == null)
|
||||
throw new ArgumentNullException("times");
|
||||
|
||||
DateTime earliestTime;
|
||||
bool success = times.OrderBy(dt => dt).TryFirst(dt => inclusive ? target <= dt : target < dt, out earliestTime);
|
||||
return success ? earliestTime : (DateTime?) null;
|
||||
return success ? earliestTime : (DateTime?)null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -54,14 +71,159 @@ namespace ICD.Common.Utils.Extensions
|
||||
/// <param name="inclusive">Whether or not to include times equal to the target time</param>
|
||||
/// <param name="times"></param>
|
||||
/// <returns></returns>
|
||||
public static DateTime? PreviousLatestTime(this DateTime target, bool inclusive, params DateTime[] times)
|
||||
public static DateTime? PreviousLatestTime(this DateTime target, bool inclusive, [NotNull] params DateTime[] times)
|
||||
{
|
||||
if (times == null)
|
||||
throw new ArgumentNullException("null");
|
||||
throw new ArgumentNullException("times");
|
||||
|
||||
return target.PreviousLatestTime(inclusive, (IEnumerable<DateTime>)times);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the closest DateTime to the target time that is less than the target time
|
||||
/// </summary>
|
||||
/// <param name="target"></param>
|
||||
/// <param name="inclusive">Whether or not to include times equal to the target time</param>
|
||||
/// <param name="times"></param>
|
||||
/// <returns></returns>
|
||||
public static DateTime? PreviousLatestTime(this DateTime target, bool inclusive, [NotNull] IEnumerable<DateTime> times)
|
||||
{
|
||||
if (times == null)
|
||||
throw new ArgumentNullException("times");
|
||||
|
||||
DateTime latestTime;
|
||||
bool success = times.OrderByDescending(dt => dt).TryFirst(dt => inclusive ? target >= dt : target > dt, out latestTime);
|
||||
return success ? latestTime : (DateTime?) null;
|
||||
return success ? latestTime : (DateTime?)null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the DateTime representing the very start of the current day.
|
||||
/// </summary>
|
||||
/// <param name="extends"></param>
|
||||
/// <returns></returns>
|
||||
public static DateTime StartOfDay(this DateTime extends)
|
||||
{
|
||||
return new DateTime(extends.Year, extends.Month, extends.Day, 0, 0, 0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the DateTime representing the very end of the current day.
|
||||
/// </summary>
|
||||
/// <param name="extends"></param>
|
||||
/// <returns></returns>
|
||||
public static DateTime EndOfDay(this DateTime extends)
|
||||
{
|
||||
return extends.StartOfDay() + new TimeSpan(24, 0, 0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the give date in ISO-8601 format.
|
||||
/// </summary>
|
||||
/// <param name="extends"></param>
|
||||
/// <returns></returns>
|
||||
public static string ToIso(this DateTime extends)
|
||||
{
|
||||
return extends.ToString("o");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the given date in unix timestamp format.
|
||||
/// </summary>
|
||||
/// <param name="extends"></param>
|
||||
/// <returns></returns>
|
||||
[PublicAPI]
|
||||
public static double ToUnixTimestamp(this DateTime extends)
|
||||
{
|
||||
DateTime origin = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc);
|
||||
TimeSpan diff = extends.ToUniversalTime() - origin;
|
||||
return Math.Floor(diff.TotalSeconds);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds the given number of years to the date, and checks if the day is still valid (basically only for leap days).
|
||||
/// </summary>
|
||||
/// <param name="extends"></param>
|
||||
/// <param name="years"></param>
|
||||
/// <returns></returns>
|
||||
public static DateTime AddYearsAndWrap(this DateTime extends, int years)
|
||||
{
|
||||
years += extends.Year;
|
||||
|
||||
// need to check days in month due to leap year
|
||||
int daysInMonth = DateTime.DaysInMonth(years, extends.Month);
|
||||
int day = daysInMonth < extends.Day ? daysInMonth : extends.Day;
|
||||
return new DateTime(years, extends.Month, day, extends.Hour, extends.Minute, extends.Second, extends.Millisecond);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds the given number of months to the date, wrapping every 12 months, and lowering the day in the month is not valid.
|
||||
/// </summary>
|
||||
/// <param name="extends"></param>
|
||||
/// <param name="months"></param>
|
||||
/// <returns></returns>
|
||||
public static DateTime AddMonthsAndWrap(this DateTime extends, int months)
|
||||
{
|
||||
months = MathUtils.Modulus(months + extends.Month - 1, 12) + 1;
|
||||
int daysInMonth = DateTime.DaysInMonth(extends.Year, months);
|
||||
int day = daysInMonth < extends.Day ? daysInMonth : extends.Day;
|
||||
|
||||
return new DateTime(extends.Year, months, day, extends.Hour, extends.Minute, extends.Second, extends.Millisecond);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds the given number of days to the date, wrapping when the number of days exceeds the days in a month.
|
||||
/// </summary>
|
||||
/// <param name="extends"></param>
|
||||
/// <param name="days"></param>
|
||||
/// <returns></returns>
|
||||
public static DateTime AddDaysAndWrap(this DateTime extends, int days)
|
||||
{
|
||||
days = MathUtils.Modulus(days + extends.Day - 1, DateTime.DaysInMonth(extends.Year, extends.Month)) + 1;
|
||||
return new DateTime(extends.Year, extends.Month, days, extends.Hour, extends.Minute, extends.Second, extends.Millisecond);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds the given number of hours to the time, wrapping every 24 hours without modifying the day.
|
||||
/// </summary>
|
||||
/// <param name="extends"></param>
|
||||
/// <param name="hours"></param>
|
||||
/// <returns></returns>
|
||||
public static DateTime AddHoursAndWrap(this DateTime extends, int hours)
|
||||
{
|
||||
hours = MathUtils.Modulus(hours + extends.Hour, 24);
|
||||
return new DateTime(extends.Year, extends.Month, extends.Day, hours, extends.Minute, extends.Second, extends.Millisecond);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds the given number of hours to the time, wrapping within the current 12 hour span, without modifying the day.
|
||||
/// </summary>
|
||||
/// <param name="extends"></param>
|
||||
/// <param name="hours"></param>
|
||||
/// <returns></returns>
|
||||
public static DateTime AddHoursAndWrap12Hour(this DateTime extends, int hours)
|
||||
{
|
||||
int currentHour = extends.Hour;
|
||||
bool am = extends.Hour < 12;
|
||||
|
||||
int current12Hour = MathUtils.Modulus(currentHour, 12);
|
||||
int new12Hour = MathUtils.Modulus(current12Hour + hours, 12);
|
||||
|
||||
return am
|
||||
? new DateTime(extends.Year, extends.Month, extends.Day, new12Hour, extends.Minute, extends.Second, extends.Millisecond)
|
||||
: new DateTime(extends.Year, extends.Month, extends.Day, new12Hour + 12, extends.Minute, extends.Second, extends.Millisecond);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds the given number of minutes to the time, wrapping every 60 minutes without modifying the hour.
|
||||
/// </summary>
|
||||
/// <param name="extends"></param>
|
||||
/// <param name="minutes"></param>
|
||||
/// <returns></returns>
|
||||
public static DateTime AddMinutesAndWrap(this DateTime extends, int minutes)
|
||||
{
|
||||
minutes = MathUtils.Modulus(minutes + extends.Minute, 60);
|
||||
return new DateTime(extends.Year, extends.Month, extends.Day, extends.Hour, minutes, extends.Second, extends.Millisecond);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,29 @@ namespace ICD.Common.Utils.Extensions
|
||||
{
|
||||
public static class DictionaryExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Removes the key from the dictionary, outputting the value.
|
||||
/// </summary>
|
||||
/// <typeparam name="TKey"></typeparam>
|
||||
/// <typeparam name="TValue"></typeparam>
|
||||
/// <param name="extends"></param>
|
||||
/// <param name="key"></param>
|
||||
/// <param name="value"></param>
|
||||
/// <returns></returns>
|
||||
public static bool Remove<TKey, TValue>([NotNull] this IDictionary<TKey, TValue> extends,
|
||||
[NotNull] TKey key, out TValue value)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
|
||||
// ReSharper disable CompareNonConstrainedGenericWithNull
|
||||
if (key == null)
|
||||
// ReSharper restore CompareNonConstrainedGenericWithNull
|
||||
throw new ArgumentNullException("key");
|
||||
|
||||
return extends.TryGetValue(key, out value) && extends.Remove(key);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes all of the given keys from the dictionary.
|
||||
/// </summary>
|
||||
@@ -14,7 +37,8 @@ namespace ICD.Common.Utils.Extensions
|
||||
/// <typeparam name="TValue"></typeparam>
|
||||
/// <param name="extends"></param>
|
||||
/// <param name="keys"></param>
|
||||
public static void RemoveAll<TKey, TValue>(this IDictionary<TKey, TValue> extends, IEnumerable<TKey> keys)
|
||||
public static void RemoveAll<TKey, TValue>([NotNull] this IDictionary<TKey, TValue> extends,
|
||||
[NotNull] IEnumerable<TKey> keys)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
@@ -35,7 +59,7 @@ namespace ICD.Common.Utils.Extensions
|
||||
/// <param name="value"></param>
|
||||
/// <returns>False if value is not found in the dictionary.</returns>
|
||||
[PublicAPI]
|
||||
public static bool RemoveValue<TKey, TValue>(this IDictionary<TKey, TValue> extends, TValue value)
|
||||
public static bool RemoveValue<TKey, TValue>([NotNull] this IDictionary<TKey, TValue> extends, TValue value)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
@@ -52,7 +76,7 @@ namespace ICD.Common.Utils.Extensions
|
||||
/// <param name="extends"></param>
|
||||
/// <param name="value"></param>
|
||||
[PublicAPI]
|
||||
public static void RemoveAllValues<TKey, TValue>(this IDictionary<TKey, TValue> extends, TValue value)
|
||||
public static void RemoveAllValues<TKey, TValue>([NotNull] this IDictionary<TKey, TValue> extends, TValue value)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
@@ -71,13 +95,15 @@ namespace ICD.Common.Utils.Extensions
|
||||
/// <returns></returns>
|
||||
[CanBeNull]
|
||||
[PublicAPI]
|
||||
public static TValue GetDefault<TKey, TValue>(this IDictionary<TKey, TValue> extends, TKey key)
|
||||
public static TValue GetDefault<TKey, TValue>([NotNull] this IDictionary<TKey, TValue> extends,
|
||||
[NotNull] TKey key)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
|
||||
// ReSharper disable once CompareNonConstrainedGenericWithNull
|
||||
// ReSharper disable CompareNonConstrainedGenericWithNull
|
||||
if (key == null)
|
||||
// ReSharper restore CompareNonConstrainedGenericWithNull
|
||||
throw new ArgumentNullException("key");
|
||||
|
||||
return extends.GetDefault(key, default(TValue));
|
||||
@@ -93,13 +119,16 @@ namespace ICD.Common.Utils.Extensions
|
||||
/// <param name="defaultValue"></param>
|
||||
/// <returns></returns>
|
||||
[PublicAPI]
|
||||
public static TValue GetDefault<TKey, TValue>(this IDictionary<TKey, TValue> extends, TKey key, TValue defaultValue)
|
||||
public static TValue GetDefault<TKey, TValue>([NotNull] this IDictionary<TKey, TValue> extends,
|
||||
[NotNull] TKey key,
|
||||
TValue defaultValue)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
|
||||
// ReSharper disable once CompareNonConstrainedGenericWithNull
|
||||
// ReSharper disable CompareNonConstrainedGenericWithNull
|
||||
if (key == null)
|
||||
// ReSharper restore CompareNonConstrainedGenericWithNull
|
||||
throw new ArgumentNullException("key");
|
||||
|
||||
TValue value;
|
||||
@@ -116,14 +145,15 @@ namespace ICD.Common.Utils.Extensions
|
||||
/// <param name="defaultValue"></param>
|
||||
/// <returns></returns>
|
||||
[PublicAPI]
|
||||
public static TValue GetOrAddDefault<TKey, TValue>(this IDictionary<TKey, TValue> extends, TKey key,
|
||||
TValue defaultValue)
|
||||
public static TValue GetOrAddDefault<TKey, TValue>([NotNull] this IDictionary<TKey, TValue> extends,
|
||||
[NotNull] TKey key, TValue defaultValue)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
|
||||
// ReSharper disable once CompareNonConstrainedGenericWithNull
|
||||
// ReSharper disable CompareNonConstrainedGenericWithNull
|
||||
if (key == null)
|
||||
// ReSharper restore CompareNonConstrainedGenericWithNull
|
||||
throw new ArgumentNullException("key");
|
||||
|
||||
TValue value = extends.GetDefault(key, defaultValue);
|
||||
@@ -141,20 +171,50 @@ namespace ICD.Common.Utils.Extensions
|
||||
/// <param name="key"></param>
|
||||
/// <returns></returns>
|
||||
[PublicAPI]
|
||||
public static TValue GetOrAddNew<TKey, TValue>(this IDictionary<TKey, TValue> extends, TKey key)
|
||||
public static TValue GetOrAddNew<TKey, TValue>([NotNull] this IDictionary<TKey, TValue> extends,
|
||||
[NotNull] TKey key)
|
||||
where TValue : new()
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
|
||||
// ReSharper disable once CompareNonConstrainedGenericWithNull
|
||||
// ReSharper disable CompareNonConstrainedGenericWithNull
|
||||
if (key == null)
|
||||
// ReSharper restore CompareNonConstrainedGenericWithNull
|
||||
throw new ArgumentNullException("key");
|
||||
|
||||
return extends.GetOrAddNew(key, () => ReflectionUtils.CreateInstance<TValue>());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// If the key is present in the dictionary return the value, otherwise add a new value to the dictionary and return it.
|
||||
/// </summary>
|
||||
/// <typeparam name="TKey"></typeparam>
|
||||
/// <typeparam name="TValue"></typeparam>
|
||||
/// <param name="extends"></param>
|
||||
/// <param name="key"></param>
|
||||
/// <param name="valueFunc"></param>
|
||||
/// <returns></returns>
|
||||
[PublicAPI]
|
||||
public static TValue GetOrAddNew<TKey, TValue>([NotNull] this IDictionary<TKey, TValue> extends,
|
||||
[NotNull] TKey key,
|
||||
[NotNull] Func<TValue> valueFunc)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
|
||||
// ReSharper disable CompareNonConstrainedGenericWithNull
|
||||
if (key == null)
|
||||
// ReSharper restore CompareNonConstrainedGenericWithNull
|
||||
throw new ArgumentNullException("key");
|
||||
|
||||
if (valueFunc == null)
|
||||
throw new ArgumentNullException("valueFunc");
|
||||
|
||||
TValue value;
|
||||
if (!extends.TryGetValue(key, out value))
|
||||
{
|
||||
value = ReflectionUtils.CreateInstance<TValue>();
|
||||
value = valueFunc();
|
||||
extends.Add(key, value);
|
||||
}
|
||||
|
||||
@@ -171,7 +231,7 @@ namespace ICD.Common.Utils.Extensions
|
||||
/// <returns></returns>
|
||||
/// <exception cref="ArgumentOutOfRangeException">The value does not exist in the dictionary.</exception>
|
||||
[PublicAPI]
|
||||
public static TKey GetKey<TKey, TValue>(this IDictionary<TKey, TValue> extends, TValue value)
|
||||
public static TKey GetKey<TKey, TValue>([NotNull] this IDictionary<TKey, TValue> extends, TValue value)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
@@ -194,7 +254,8 @@ namespace ICD.Common.Utils.Extensions
|
||||
/// <param name="key"></param>
|
||||
/// <returns></returns>
|
||||
[PublicAPI]
|
||||
public static bool TryGetKey<TKey, TValue>(this IDictionary<TKey, TValue> extends, TValue value, out TKey key)
|
||||
public static bool TryGetKey<TKey, TValue>([NotNull] this IDictionary<TKey, TValue> extends, TValue value,
|
||||
out TKey key)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
@@ -211,7 +272,8 @@ namespace ICD.Common.Utils.Extensions
|
||||
/// <param name="value"></param>
|
||||
/// <returns></returns>
|
||||
[PublicAPI]
|
||||
public static IEnumerable<TKey> GetKeys<TKey, TValue>(this IDictionary<TKey, TValue> extends, TValue value)
|
||||
public static IEnumerable<TKey> GetKeys<TKey, TValue>([NotNull] this IDictionary<TKey, TValue> extends,
|
||||
TValue value)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
@@ -229,8 +291,8 @@ namespace ICD.Common.Utils.Extensions
|
||||
/// <param name="other"></param>
|
||||
/// <returns></returns>
|
||||
[PublicAPI]
|
||||
public static bool Update<TKey, TValue>(this IDictionary<TKey, TValue> extends,
|
||||
IEnumerable<KeyValuePair<TKey, TValue>> other)
|
||||
public static bool Update<TKey, TValue>([NotNull] this IDictionary<TKey, TValue> extends,
|
||||
[NotNull] IEnumerable<KeyValuePair<TKey, TValue>> other)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
@@ -251,9 +313,9 @@ namespace ICD.Common.Utils.Extensions
|
||||
/// <param name="comparer"></param>
|
||||
/// <returns></returns>
|
||||
[PublicAPI]
|
||||
public static bool Update<TKey, TValue>(this IDictionary<TKey, TValue> extends,
|
||||
IEnumerable<KeyValuePair<TKey, TValue>> other,
|
||||
IEqualityComparer<TValue> comparer)
|
||||
public static bool Update<TKey, TValue>([NotNull] this IDictionary<TKey, TValue> extends,
|
||||
[NotNull] IEnumerable<KeyValuePair<TKey, TValue>> other,
|
||||
[NotNull] IEqualityComparer<TValue> comparer)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
@@ -261,6 +323,9 @@ namespace ICD.Common.Utils.Extensions
|
||||
if (other == null)
|
||||
throw new ArgumentNullException("other");
|
||||
|
||||
if (comparer == null)
|
||||
throw new ArgumentNullException("comparer");
|
||||
|
||||
bool change = false;
|
||||
|
||||
foreach (KeyValuePair<TKey, TValue> pair in other)
|
||||
@@ -284,7 +349,8 @@ namespace ICD.Common.Utils.Extensions
|
||||
/// <param name="extends"></param>
|
||||
/// <param name="items"></param>
|
||||
[PublicAPI]
|
||||
public static void AddRange<TKey, TValue>(this IDictionary<TKey, TValue> extends, IEnumerable<KeyValuePair<TKey, TValue>> items)
|
||||
public static void AddRange<TKey, TValue>([NotNull] this IDictionary<TKey, TValue> extends,
|
||||
[NotNull] IEnumerable<KeyValuePair<TKey, TValue>> items)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
@@ -305,8 +371,9 @@ namespace ICD.Common.Utils.Extensions
|
||||
/// <param name="items"></param>
|
||||
/// <param name="getKey"></param>
|
||||
[PublicAPI]
|
||||
public static void AddRange<TKey, TValue>(this IDictionary<TKey, TValue> extends, IEnumerable<TValue> items,
|
||||
Func<TValue, TKey> getKey)
|
||||
public static void AddRange<TKey, TValue>([NotNull] this IDictionary<TKey, TValue> extends,
|
||||
[NotNull] IEnumerable<TValue> items,
|
||||
[NotNull] Func<TValue, TKey> getKey)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
@@ -330,8 +397,9 @@ namespace ICD.Common.Utils.Extensions
|
||||
/// <param name="items"></param>
|
||||
/// <param name="getValue"></param>
|
||||
[PublicAPI]
|
||||
public static void AddRange<TKey, TValue>(this IDictionary<TKey, TValue> extends, IEnumerable<TKey> items,
|
||||
Func<TKey, TValue> getValue)
|
||||
public static void AddRange<TKey, TValue>([NotNull] this IDictionary<TKey, TValue> extends,
|
||||
[NotNull] IEnumerable<TKey> items,
|
||||
[NotNull] Func<TKey, TValue> getValue)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
@@ -354,8 +422,8 @@ namespace ICD.Common.Utils.Extensions
|
||||
/// <param name="extends"></param>
|
||||
/// <param name="items"></param>
|
||||
[PublicAPI]
|
||||
public static void AddRange<TKey, TValue>(this Dictionary<TKey, TValue> extends,
|
||||
IEnumerable<KeyValuePair<TKey, TValue>> items)
|
||||
public static void AddRange<TKey, TValue>([NotNull] this Dictionary<TKey, TValue> extends,
|
||||
[NotNull] IEnumerable<KeyValuePair<TKey, TValue>> items)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
@@ -376,12 +444,15 @@ namespace ICD.Common.Utils.Extensions
|
||||
/// <param name="other"></param>
|
||||
/// <returns></returns>
|
||||
[PublicAPI]
|
||||
public static bool DictionaryEqual<TKey, TValue>(this IDictionary<TKey, TValue> extends,
|
||||
IDictionary<TKey, TValue> other)
|
||||
public static bool DictionaryEqual<TKey, TValue>([NotNull] this IDictionary<TKey, TValue> extends,
|
||||
[NotNull] IDictionary<TKey, TValue> other)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
|
||||
if (other == null)
|
||||
throw new ArgumentNullException("other");
|
||||
|
||||
return extends.DictionaryEqual(other, EqualityComparer<TValue>.Default);
|
||||
}
|
||||
|
||||
@@ -395,13 +466,16 @@ namespace ICD.Common.Utils.Extensions
|
||||
/// <param name="valueComparer"></param>
|
||||
/// <returns></returns>
|
||||
[PublicAPI]
|
||||
public static bool DictionaryEqual<TKey, TValue>(this IDictionary<TKey, TValue> extends,
|
||||
IDictionary<TKey, TValue> other,
|
||||
IEqualityComparer<TValue> valueComparer)
|
||||
public static bool DictionaryEqual<TKey, TValue>([NotNull] this IDictionary<TKey, TValue> extends,
|
||||
[NotNull] IDictionary<TKey, TValue> other,
|
||||
[NotNull] IEqualityComparer<TValue> valueComparer)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
|
||||
if (other == null)
|
||||
throw new ArgumentNullException("other");
|
||||
|
||||
if (valueComparer == null)
|
||||
throw new ArgumentNullException("valueComparer");
|
||||
|
||||
@@ -418,20 +492,21 @@ namespace ICD.Common.Utils.Extensions
|
||||
/// <param name="valueComparer"></param>
|
||||
/// <returns></returns>
|
||||
[PublicAPI]
|
||||
public static bool DictionaryEqual<TKey, TValue>(this IDictionary<TKey, TValue> extends,
|
||||
IDictionary<TKey, TValue> other,
|
||||
Func<TValue, TValue, bool> valueComparer)
|
||||
public static bool DictionaryEqual<TKey, TValue>([NotNull] this IDictionary<TKey, TValue> extends,
|
||||
[NotNull] IDictionary<TKey, TValue> other,
|
||||
[NotNull] Func<TValue, TValue, bool> valueComparer)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
|
||||
if (other == null)
|
||||
throw new ArgumentNullException("other");
|
||||
|
||||
if (valueComparer == null)
|
||||
throw new ArgumentNullException("valueComparer");
|
||||
|
||||
if (extends == other)
|
||||
return true;
|
||||
if (other == null)
|
||||
return false;
|
||||
if (extends.Count != other.Count)
|
||||
return false;
|
||||
|
||||
@@ -443,6 +518,7 @@ namespace ICD.Common.Utils.Extensions
|
||||
if (!valueComparer(kvp.Value, secondValue))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -455,7 +531,7 @@ namespace ICD.Common.Utils.Extensions
|
||||
/// <returns></returns>
|
||||
[PublicAPI]
|
||||
public static IEnumerable<KeyValuePair<TKey, TValue>> OrderByKey<TKey, TValue>(
|
||||
this IEnumerable<KeyValuePair<TKey, TValue>> extends)
|
||||
[NotNull] this IEnumerable<KeyValuePair<TKey, TValue>> extends)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
@@ -471,7 +547,8 @@ namespace ICD.Common.Utils.Extensions
|
||||
/// <param name="extends"></param>
|
||||
/// <returns></returns>
|
||||
[PublicAPI]
|
||||
public static IEnumerable<TValue> OrderValuesByKey<TKey, TValue>(this IEnumerable<KeyValuePair<TKey, TValue>> extends)
|
||||
public static IEnumerable<TValue> OrderValuesByKey<TKey, TValue>(
|
||||
[NotNull] this IEnumerable<KeyValuePair<TKey, TValue>> extends)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
@@ -487,7 +564,8 @@ namespace ICD.Common.Utils.Extensions
|
||||
/// <param name="extends"></param>
|
||||
/// <returns></returns>
|
||||
[PublicAPI]
|
||||
public static Dictionary<TValue, List<TKey>> ToInverse<TKey, TValue>(this IEnumerable<KeyValuePair<TKey, TValue>> extends)
|
||||
public static Dictionary<TValue, List<TKey>> ToInverse<TKey, TValue>(
|
||||
[NotNull] this IEnumerable<KeyValuePair<TKey, TValue>> extends)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
@@ -508,5 +586,22 @@ namespace ICD.Common.Utils.Extensions
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Turns an enumerable of KeyValuePairs back into a dictionary
|
||||
/// </summary>
|
||||
/// <typeparam name="TKey"></typeparam>
|
||||
/// <typeparam name="TValue"></typeparam>
|
||||
/// <param name="extends"></param>
|
||||
/// <returns></returns>
|
||||
[PublicAPI]
|
||||
public static Dictionary<TKey, TValue> ToDictionary<TKey, TValue>(
|
||||
[NotNull] this IEnumerable<KeyValuePair<TKey, TValue>> extends)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
|
||||
return extends.ToDictionary(x => x.Key, x => x.Value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,6 +31,34 @@ namespace ICD.Common.Utils.Extensions
|
||||
return EnumUtils.HasFlags(extends, values);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns these enum flags, excluding the other enum flags.
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="extends"></param>
|
||||
/// <param name="other"></param>
|
||||
/// <returns></returns>
|
||||
[PublicAPI]
|
||||
public static T ExcludeFlags<T>(this T extends, T other)
|
||||
where T : struct, IConvertible
|
||||
{
|
||||
return EnumUtils.ExcludeFlags(extends, other);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns these enum flags, including the other enum flags.
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="extends"></param>
|
||||
/// <param name="other"></param>
|
||||
/// <returns></returns>
|
||||
[PublicAPI]
|
||||
public static T IncludeFlags<T>(this T extends, T other)
|
||||
where T : struct, IConvertible
|
||||
{
|
||||
return EnumUtils.IncludeFlags(extends, other);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the enum value as a
|
||||
/// </summary>
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using ICD.Common.Properties;
|
||||
@@ -17,7 +18,7 @@ namespace ICD.Common.Utils.Extensions
|
||||
/// <param name="extends"></param>
|
||||
/// <param name="defaultItem"></param>
|
||||
/// <returns></returns>
|
||||
public static T FirstOrDefault<T>(this IEnumerable<T> extends, T defaultItem)
|
||||
public static T FirstOrDefault<T>([NotNull] this IEnumerable<T> extends, T defaultItem)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
@@ -34,7 +35,8 @@ namespace ICD.Common.Utils.Extensions
|
||||
/// <param name="predicate"></param>
|
||||
/// <param name="defaultItem"></param>
|
||||
/// <returns></returns>
|
||||
public static T FirstOrDefault<T>(this IEnumerable<T> extends, Func<T, bool> predicate, T defaultItem)
|
||||
public static T FirstOrDefault<T>([NotNull] this IEnumerable<T> extends, [NotNull] Func<T, bool> predicate,
|
||||
T defaultItem)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
@@ -53,7 +55,7 @@ namespace ICD.Common.Utils.Extensions
|
||||
/// <param name="extends"></param>
|
||||
/// <param name="item">Outputs the first item in the sequence.</param>
|
||||
/// <returns></returns>
|
||||
public static bool TryFirst<T>(this IEnumerable<T> extends, out T item)
|
||||
public static bool TryFirst<T>([NotNull] this IEnumerable<T> extends, out T item)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
@@ -80,7 +82,8 @@ namespace ICD.Common.Utils.Extensions
|
||||
/// <param name="predicate"></param>
|
||||
/// <param name="item">Outputs the first item in the sequence.</param>
|
||||
/// <returns></returns>
|
||||
public static bool TryFirst<T>(this IEnumerable<T> extends, Func<T, bool> predicate, out T item)
|
||||
public static bool TryFirst<T>([NotNull] this IEnumerable<T> extends, [NotNull] Func<T, bool> predicate,
|
||||
out T item)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
@@ -112,7 +115,7 @@ namespace ICD.Common.Utils.Extensions
|
||||
/// <param name="extends"></param>
|
||||
/// <param name="item">Outputs the last item in the sequence.</param>
|
||||
/// <returns></returns>
|
||||
public static bool TryLast<T>(this IEnumerable<T> extends, out T item)
|
||||
public static bool TryLast<T>([NotNull] this IEnumerable<T> extends, out T item)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
@@ -139,7 +142,8 @@ namespace ICD.Common.Utils.Extensions
|
||||
/// <param name="predicate"></param>
|
||||
/// <param name="item">Outputs the last item in the sequence.</param>
|
||||
/// <returns></returns>
|
||||
public static bool TryLast<T>(this IEnumerable<T> extends, Func<T, bool> predicate, out T item)
|
||||
public static bool TryLast<T>([NotNull] this IEnumerable<T> extends, [NotNull] Func<T, bool> predicate,
|
||||
out T item)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
@@ -173,7 +177,7 @@ namespace ICD.Common.Utils.Extensions
|
||||
/// <param name="index"></param>
|
||||
/// <param name="item"></param>
|
||||
/// <returns></returns>
|
||||
public static bool TryElementAt<T>(this IEnumerable<T> extends, int index, out T item)
|
||||
public static bool TryElementAt<T>([NotNull] this IEnumerable<T> extends, int index, out T item)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
@@ -200,6 +204,7 @@ namespace ICD.Common.Utils.Extensions
|
||||
item = value;
|
||||
return true;
|
||||
}
|
||||
|
||||
current++;
|
||||
}
|
||||
|
||||
@@ -214,7 +219,7 @@ namespace ICD.Common.Utils.Extensions
|
||||
/// <param name="index"></param>
|
||||
/// <param name="defaultValue"></param>
|
||||
/// <returns></returns>
|
||||
public static T ElementAtOrDefault<T>(this IEnumerable<T> extends, int index, T defaultValue)
|
||||
public static T ElementAtOrDefault<T>([NotNull] this IEnumerable<T> extends, int index, T defaultValue)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
@@ -231,7 +236,8 @@ namespace ICD.Common.Utils.Extensions
|
||||
/// <param name="other"></param>
|
||||
/// <param name="comparer"></param>
|
||||
/// <returns></returns>
|
||||
public static bool SequenceEqual<T>(this IEnumerable<T> extends, IEnumerable<T> other, IEqualityComparer<T> comparer)
|
||||
public static bool SequenceEqual<T>([NotNull] this IEnumerable<T> extends, [NotNull] IEnumerable<T> other,
|
||||
[NotNull] IEqualityComparer<T> comparer)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
@@ -253,7 +259,8 @@ namespace ICD.Common.Utils.Extensions
|
||||
/// <param name="other"></param>
|
||||
/// <param name="comparer"></param>
|
||||
/// <returns></returns>
|
||||
public static bool SequenceEqual<T>(this IEnumerable<T> extends, IEnumerable<T> other, Func<T, T, bool> comparer)
|
||||
public static bool SequenceEqual<T>([NotNull] this IEnumerable<T> extends, [NotNull] IEnumerable<T> other,
|
||||
[NotNull] Func<T, T, bool> comparer)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
@@ -298,7 +305,7 @@ namespace ICD.Common.Utils.Extensions
|
||||
/// <param name="extends"></param>
|
||||
/// <param name="other"></param>
|
||||
/// <returns></returns>
|
||||
public static bool ScrambledEquals<T>(this IEnumerable<T> extends, IEnumerable<T> other)
|
||||
public static bool ScrambledEquals<T>([NotNull] this IEnumerable<T> extends, [NotNull] IEnumerable<T> other)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
@@ -317,7 +324,8 @@ namespace ICD.Common.Utils.Extensions
|
||||
/// <param name="other"></param>
|
||||
/// <param name="comparer"></param>
|
||||
/// <returns></returns>
|
||||
public static bool ScrambledEquals<T>(this IEnumerable<T> extends, IEnumerable<T> other, IEqualityComparer<T> comparer)
|
||||
public static bool ScrambledEquals<T>([NotNull] this IEnumerable<T> extends, [NotNull] IEnumerable<T> other,
|
||||
[NotNull] IEqualityComparer<T> comparer)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
@@ -352,7 +360,7 @@ namespace ICD.Common.Utils.Extensions
|
||||
/// <param name="extends"></param>
|
||||
/// <param name="match"></param>
|
||||
/// <returns></returns>
|
||||
public static int FindIndex<T>(this IEnumerable<T> extends, Predicate<T> match)
|
||||
public static int FindIndex<T>([NotNull] this IEnumerable<T> extends, [NotNull] Predicate<T> match)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
@@ -370,7 +378,8 @@ namespace ICD.Common.Utils.Extensions
|
||||
/// <param name="extends"></param>
|
||||
/// <param name="match"></param>
|
||||
/// <returns></returns>
|
||||
public static IEnumerable<int> FindIndices<T>(this IEnumerable<T> extends, Predicate<T> match)
|
||||
public static IEnumerable<int> FindIndices<T>([NotNull] this IEnumerable<T> extends,
|
||||
[NotNull] Predicate<T> match)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
@@ -388,7 +397,8 @@ namespace ICD.Common.Utils.Extensions
|
||||
/// <param name="sequence"></param>
|
||||
/// <param name="match"></param>
|
||||
/// <returns></returns>
|
||||
private static IEnumerable<int> FindIndicesIterator<T>(IEnumerable<T> sequence, Predicate<T> match)
|
||||
private static IEnumerable<int> FindIndicesIterator<T>([NotNull] IEnumerable<T> sequence,
|
||||
[NotNull] Predicate<T> match)
|
||||
{
|
||||
int index = 0;
|
||||
|
||||
@@ -408,7 +418,8 @@ namespace ICD.Common.Utils.Extensions
|
||||
/// <param name="extends"></param>
|
||||
/// <param name="selectors"></param>
|
||||
/// <returns></returns>
|
||||
public static IEnumerable<TResult> SelectMulti<TSource, TResult>(this IEnumerable<TSource> extends,
|
||||
public static IEnumerable<TResult> SelectMulti<TSource, TResult>([NotNull] this IEnumerable<TSource> extends,
|
||||
[NotNull]
|
||||
params Func<TSource, TResult>[] selectors)
|
||||
{
|
||||
if (extends == null)
|
||||
@@ -427,7 +438,7 @@ namespace ICD.Common.Utils.Extensions
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="extends"></param>
|
||||
[PublicAPI]
|
||||
public static void Execute<T>(this IEnumerable<T> extends)
|
||||
public static void Execute<T>([NotNull] this IEnumerable<T> extends)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
@@ -446,7 +457,7 @@ namespace ICD.Common.Utils.Extensions
|
||||
/// <param name="extends"></param>
|
||||
/// <param name="action"></param>
|
||||
[PublicAPI]
|
||||
public static void ForEach<T>(this IEnumerable<T> extends, Action<T> action)
|
||||
public static void ForEach<T>([NotNull] this IEnumerable<T> extends, [NotNull] Action<T> action)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
@@ -464,7 +475,7 @@ namespace ICD.Common.Utils.Extensions
|
||||
/// <param name="extends"></param>
|
||||
/// <param name="action"></param>
|
||||
[PublicAPI]
|
||||
public static void ForEach<T>(this IEnumerable<T> extends, Action<T, int> action)
|
||||
public static void ForEach<T>([NotNull] this IEnumerable<T> extends, [NotNull] Action<T, int> action)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
@@ -485,7 +496,7 @@ namespace ICD.Common.Utils.Extensions
|
||||
/// <param name="extends"></param>
|
||||
/// <param name="item"></param>
|
||||
/// <returns></returns>
|
||||
public static IEnumerable<T> Prepend<T>(this IEnumerable<T> extends, T item)
|
||||
public static IEnumerable<T> Prepend<T>([NotNull]this IEnumerable<T> extends, T item)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
@@ -500,7 +511,7 @@ namespace ICD.Common.Utils.Extensions
|
||||
/// <param name="sequence"></param>
|
||||
/// <param name="item"></param>
|
||||
/// <returns></returns>
|
||||
private static IEnumerable<T> PrependIterator<T>(IEnumerable<T> sequence, T item)
|
||||
private static IEnumerable<T> PrependIterator<T>([NotNull]IEnumerable<T> sequence, T item)
|
||||
{
|
||||
yield return item;
|
||||
|
||||
@@ -517,7 +528,7 @@ namespace ICD.Common.Utils.Extensions
|
||||
/// <param name="items"></param>
|
||||
/// <returns></returns>
|
||||
[PublicAPI]
|
||||
public static IEnumerable<T> PrependMany<T>(this IEnumerable<T> extends, params T[] items)
|
||||
public static IEnumerable<T> PrependMany<T>([NotNull] this IEnumerable<T> extends, [NotNull] params T[] items)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
@@ -535,7 +546,8 @@ namespace ICD.Common.Utils.Extensions
|
||||
/// <param name="sequence"></param>
|
||||
/// <param name="items"></param>
|
||||
/// <returns></returns>
|
||||
private static IEnumerable<T> PrependManyIterator<T>(IEnumerable<T> sequence, params T[] items)
|
||||
private static IEnumerable<T> PrependManyIterator<T>([NotNull] IEnumerable<T> sequence,
|
||||
[NotNull] params T[] items)
|
||||
{
|
||||
foreach (T item in items)
|
||||
yield return item;
|
||||
@@ -552,7 +564,7 @@ namespace ICD.Common.Utils.Extensions
|
||||
/// <param name="extends"></param>
|
||||
/// <param name="item"></param>
|
||||
/// <returns></returns>
|
||||
public static IEnumerable<T> Append<T>(this IEnumerable<T> extends, T item)
|
||||
public static IEnumerable<T> Append<T>([NotNull]this IEnumerable<T> extends, T item)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
@@ -567,7 +579,7 @@ namespace ICD.Common.Utils.Extensions
|
||||
/// <param name="sequence"></param>
|
||||
/// <param name="item"></param>
|
||||
/// <returns></returns>
|
||||
private static IEnumerable<T> AppendIterator<T>(IEnumerable<T> sequence, T item)
|
||||
private static IEnumerable<T> AppendIterator<T>([NotNull]IEnumerable<T> sequence, T item)
|
||||
{
|
||||
foreach (T first in sequence)
|
||||
yield return first;
|
||||
@@ -584,7 +596,7 @@ namespace ICD.Common.Utils.Extensions
|
||||
/// <param name="items"></param>
|
||||
/// <returns></returns>
|
||||
[PublicAPI]
|
||||
public static IEnumerable<T> AppendMany<T>(this IEnumerable<T> extends, params T[] items)
|
||||
public static IEnumerable<T> AppendMany<T>([NotNull] this IEnumerable<T> extends, [NotNull] params T[] items)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
@@ -602,7 +614,8 @@ namespace ICD.Common.Utils.Extensions
|
||||
/// <param name="sequence"></param>
|
||||
/// <param name="items"></param>
|
||||
/// <returns></returns>
|
||||
private static IEnumerable<T> AppendManyIterator<T>(IEnumerable<T> sequence, params T[] items)
|
||||
private static IEnumerable<T> AppendManyIterator<T>([NotNull] IEnumerable<T> sequence,
|
||||
[NotNull] params T[] items)
|
||||
{
|
||||
foreach (T each in sequence)
|
||||
yield return each;
|
||||
@@ -619,7 +632,7 @@ namespace ICD.Common.Utils.Extensions
|
||||
/// <param name="count"></param>
|
||||
/// <returns></returns>
|
||||
[PublicAPI]
|
||||
public static IEnumerable<T> PadRight<T>(this IEnumerable<T> extends, int count)
|
||||
public static IEnumerable<T> PadRight<T>([NotNull] this IEnumerable<T> extends, int count)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
@@ -634,7 +647,7 @@ namespace ICD.Common.Utils.Extensions
|
||||
/// <param name="sequence"></param>
|
||||
/// <param name="count"></param>
|
||||
/// <returns></returns>
|
||||
private static IEnumerable<T> PadRightIterator<T>(IEnumerable<T> sequence, int count)
|
||||
private static IEnumerable<T> PadRightIterator<T>([NotNull] IEnumerable<T> sequence, int count)
|
||||
{
|
||||
int index = 0;
|
||||
|
||||
@@ -648,13 +661,57 @@ namespace ICD.Common.Utils.Extensions
|
||||
yield return default(T);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if the given sequence is ordered.
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="extends"></param>
|
||||
/// <returns></returns>
|
||||
public static bool AreOrdered<T>([NotNull] this IEnumerable<T> extends)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
|
||||
return extends.AreOrdered(Comparer<T>.Default);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if the given sequence is ordered.
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="extends"></param>
|
||||
/// <param name="comparer"></param>
|
||||
/// <returns></returns>
|
||||
public static bool AreOrdered<T>([NotNull] this IEnumerable<T> extends, [NotNull] IComparer<T> comparer)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
|
||||
if (comparer == null)
|
||||
throw new ArgumentNullException("comparer");
|
||||
|
||||
bool first = true;
|
||||
T previous = default(T);
|
||||
|
||||
foreach (T item in extends)
|
||||
{
|
||||
if (!first && comparer.Compare(item, previous) < 0)
|
||||
return false;
|
||||
|
||||
first = false;
|
||||
previous = item;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Default ordering for the items in the sequence.
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="extends"></param>
|
||||
/// <returns></returns>
|
||||
public static IOrderedEnumerable<T> Order<T>(this IEnumerable<T> extends)
|
||||
public static IOrderedEnumerable<T> Order<T>([NotNull] this IEnumerable<T> extends)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
@@ -669,7 +726,8 @@ namespace ICD.Common.Utils.Extensions
|
||||
/// <param name="extends"></param>
|
||||
/// <param name="comparer"></param>
|
||||
/// <returns></returns>
|
||||
public static IOrderedEnumerable<T> Order<T>(this IEnumerable<T> extends, IComparer<T> comparer)
|
||||
public static IOrderedEnumerable<T> Order<T>([NotNull] this IEnumerable<T> extends,
|
||||
[NotNull] IComparer<T> comparer)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
@@ -687,7 +745,8 @@ namespace ICD.Common.Utils.Extensions
|
||||
/// <param name="extends"></param>
|
||||
/// <param name="comparer"></param>
|
||||
/// <returns></returns>
|
||||
public static IOrderedEnumerable<T> OrderDescending<T>(this IEnumerable<T> extends, IComparer<T> comparer)
|
||||
public static IOrderedEnumerable<T> OrderDescending<T>([NotNull] this IEnumerable<T> extends,
|
||||
[NotNull] IComparer<T> comparer)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
@@ -705,7 +764,7 @@ namespace ICD.Common.Utils.Extensions
|
||||
/// <param name="extends"></param>
|
||||
/// <param name="item"></param>
|
||||
/// <returns></returns>
|
||||
public static IEnumerable<T> Except<T>(this IEnumerable<T> extends, T item)
|
||||
public static IEnumerable<T> Except<T>([NotNull] this IEnumerable<T> extends, T item)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
@@ -721,7 +780,8 @@ namespace ICD.Common.Utils.Extensions
|
||||
/// <param name="item"></param>
|
||||
/// <param name="comparer"></param>
|
||||
/// <returns></returns>
|
||||
public static IEnumerable<T> Except<T>(this IEnumerable<T> extends, T item, IEqualityComparer<T> comparer)
|
||||
public static IEnumerable<T> Except<T>([NotNull] this IEnumerable<T> extends, T item,
|
||||
[NotNull] IEqualityComparer<T> comparer)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
@@ -732,6 +792,22 @@ namespace ICD.Common.Utils.Extensions
|
||||
return extends.Where(i => !comparer.Equals(item, i));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes any null elements from an enumerable of nullable value types
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="extends"></param>
|
||||
/// <returns></returns>
|
||||
[PublicAPI]
|
||||
public static IEnumerable<T> ExceptNulls<T>([NotNull] this IEnumerable<T?> extends)
|
||||
where T : struct
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
|
||||
return extends.OfType<T>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Copies all the elements of the current one-dimensional array to the specified one-dimensional array
|
||||
/// starting at the specified destination array index. The index is specified as a 32-bit integer.
|
||||
@@ -740,7 +816,7 @@ namespace ICD.Common.Utils.Extensions
|
||||
/// <param name="extends"></param>
|
||||
/// <param name="array"></param>
|
||||
/// <param name="index"></param>
|
||||
public static void CopyTo<T>(this IEnumerable<T> extends, T[] array, int index)
|
||||
public static void CopyTo<T>([NotNull] this IEnumerable<T> extends, [NotNull] T[] array, int index)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
@@ -763,13 +839,33 @@ namespace ICD.Common.Utils.Extensions
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new collection and fills it with the items of the enumerable.
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <typeparam name="TCollection"></typeparam>
|
||||
/// <param name="extends"></param>
|
||||
/// <returns></returns>
|
||||
public static TCollection ToCollection<T, TCollection>([NotNull] this IEnumerable<T> extends)
|
||||
where TCollection : ICollection<T>
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
|
||||
TCollection collection = ReflectionUtils.CreateInstance<TCollection>();
|
||||
foreach (T item in extends)
|
||||
collection.Add(item);
|
||||
|
||||
return collection;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the sequence as a IcdHashSet.
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="extends"></param>
|
||||
/// <returns></returns>
|
||||
public static IcdHashSet<T> ToIcdHashSet<T>(this IEnumerable<T> extends)
|
||||
public static IcdHashSet<T> ToIcdHashSet<T>([NotNull] this IEnumerable<T> extends)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
@@ -784,7 +880,8 @@ namespace ICD.Common.Utils.Extensions
|
||||
/// <param name="extends"></param>
|
||||
/// <param name="comparer"></param>
|
||||
/// <returns></returns>
|
||||
public static IcdHashSet<T> ToIcdHashSet<T>(this IEnumerable<T> extends, IEqualityComparer<T> comparer)
|
||||
public static IcdHashSet<T> ToIcdHashSet<T>([NotNull] this IEnumerable<T> extends,
|
||||
[NotNull] IEqualityComparer<T> comparer)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
@@ -802,7 +899,7 @@ namespace ICD.Common.Utils.Extensions
|
||||
/// <param name="extends"></param>
|
||||
/// <param name="count"></param>
|
||||
/// <returns></returns>
|
||||
public static T[] ToArray<T>(this IEnumerable<T> extends, int count)
|
||||
public static T[] ToArray<T>([NotNull] this IEnumerable<T> extends, int count)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
@@ -810,14 +907,56 @@ namespace ICD.Common.Utils.Extensions
|
||||
if (count < 0)
|
||||
throw new ArgumentOutOfRangeException("count");
|
||||
|
||||
T[] array = new T[count];
|
||||
int i = 0;
|
||||
// Source is already an array
|
||||
T[] arrayCast = extends as T[];
|
||||
if (arrayCast != null)
|
||||
{
|
||||
T[] output = new T[count];
|
||||
Array.Copy(arrayCast, output, count);
|
||||
return output;
|
||||
}
|
||||
|
||||
// Dumb sequence case
|
||||
T[] array = new T[count];
|
||||
|
||||
int i = 0;
|
||||
foreach (T item in extends)
|
||||
{
|
||||
array[i++] = item;
|
||||
if (i >= count)
|
||||
break;
|
||||
}
|
||||
|
||||
if (i != count)
|
||||
throw new ArgumentOutOfRangeException("count");
|
||||
|
||||
return array;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a generic List of the given item type.
|
||||
/// </summary>
|
||||
/// <param name="extends"></param>
|
||||
/// <param name="itemType"></param>
|
||||
/// <returns></returns>
|
||||
public static IList ToList<T>([NotNull] this IEnumerable<T> extends, [NotNull] Type itemType)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
|
||||
if (itemType == null)
|
||||
throw new ArgumentNullException("itemType");
|
||||
|
||||
Type genericListType = typeof(List<>);
|
||||
Type specificListType = genericListType.MakeGenericType(itemType);
|
||||
IList list = (IList)ReflectionUtils.CreateInstance(specificListType);
|
||||
|
||||
foreach (object item in extends)
|
||||
list.Add(item);
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Optimized ToList implementation with fewer allocations.
|
||||
/// </summary>
|
||||
@@ -825,7 +964,7 @@ namespace ICD.Common.Utils.Extensions
|
||||
/// <param name="extends"></param>
|
||||
/// <param name="count"></param>
|
||||
/// <returns></returns>
|
||||
public static List<T> ToList<T>(this IEnumerable<T> extends, int count)
|
||||
public static List<T> ToList<T>([NotNull] this IEnumerable<T> extends, int count)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
@@ -845,7 +984,7 @@ namespace ICD.Common.Utils.Extensions
|
||||
/// <param name="extends"></param>
|
||||
/// <returns></returns>
|
||||
[PublicAPI]
|
||||
public static Dictionary<int, T> ToIndexedDictionary<T>(this IEnumerable<T> extends)
|
||||
public static Dictionary<int, T> ToIndexedDictionary<T>([NotNull] this IEnumerable<T> extends)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
@@ -862,7 +1001,7 @@ namespace ICD.Common.Utils.Extensions
|
||||
/// <param name="extends"></param>
|
||||
/// <returns></returns>
|
||||
[PublicAPI]
|
||||
public static Dictionary<uint, T> ToIndexedDictionaryUInt<T>(this IEnumerable<T> extends)
|
||||
public static Dictionary<uint, T> ToIndexedDictionaryUInt<T>([NotNull] this IEnumerable<T> extends)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
@@ -873,19 +1012,49 @@ namespace ICD.Common.Utils.Extensions
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Turns an enumerable of KeyValuePairs back into a dictionary
|
||||
/// Returns true if all of the items in the sequence are equal, or the sequence is empty.
|
||||
/// </summary>
|
||||
/// <typeparam name="TKey"></typeparam>
|
||||
/// <typeparam name="TValue"></typeparam>
|
||||
/// <typeparam name="TItem"></typeparam>
|
||||
/// <param name="extends"></param>
|
||||
/// <returns></returns>
|
||||
[PublicAPI]
|
||||
public static Dictionary<TKey, TValue> ToDictionary<TKey, TValue>(this IEnumerable<KeyValuePair<TKey, TValue>> extends)
|
||||
public static bool IsDistinct<TItem>([NotNull] this IEnumerable<TItem> extends)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
|
||||
return extends.ToDictionary(x => x.Key, x => x.Value);
|
||||
IEqualityComparer<TItem> comparer = EqualityComparer<TItem>.Default;
|
||||
return extends.IsDistinct(comparer);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if all of the items in the sequence are equal, or the sequence is empty.
|
||||
/// </summary>
|
||||
/// <typeparam name="TItem"></typeparam>
|
||||
/// <param name="extends"></param>
|
||||
/// <param name="comparer"></param>
|
||||
/// <returns></returns>
|
||||
public static bool IsDistinct<TItem>([NotNull] this IEnumerable<TItem> extends, [NotNull] IEqualityComparer<TItem> comparer)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
|
||||
TItem other = default(TItem);
|
||||
bool first = true;
|
||||
|
||||
foreach (TItem item in extends)
|
||||
{
|
||||
if (first)
|
||||
{
|
||||
other = item;
|
||||
first = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!comparer.Equals(item, other))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -897,8 +1066,8 @@ namespace ICD.Common.Utils.Extensions
|
||||
/// <param name="getProperty"></param>
|
||||
/// <returns></returns>
|
||||
[PublicAPI]
|
||||
public static IEnumerable<TItem> Distinct<TItem, TProperty>(this IEnumerable<TItem> extends,
|
||||
Func<TItem, TProperty> getProperty)
|
||||
public static IEnumerable<TItem> Distinct<TItem, TProperty>([NotNull] this IEnumerable<TItem> extends,
|
||||
[NotNull] Func<TItem, TProperty> getProperty)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
@@ -920,8 +1089,9 @@ namespace ICD.Common.Utils.Extensions
|
||||
/// <param name="propertyComparer"></param>
|
||||
/// <returns></returns>
|
||||
[PublicAPI]
|
||||
public static IEnumerable<TItem> Distinct<TItem, TProperty>(this IEnumerable<TItem> extends,
|
||||
public static IEnumerable<TItem> Distinct<TItem, TProperty>([NotNull] this IEnumerable<TItem> extends,
|
||||
Func<TItem, TProperty> getProperty,
|
||||
[NotNull]
|
||||
IEqualityComparer<TProperty> propertyComparer)
|
||||
{
|
||||
if (extends == null)
|
||||
@@ -942,7 +1112,7 @@ namespace ICD.Common.Utils.Extensions
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="extends"></param>
|
||||
/// <returns></returns>
|
||||
public static T Random<T>(this IEnumerable<T> extends)
|
||||
public static T Random<T>([NotNull] this IEnumerable<T> extends)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
@@ -967,7 +1137,7 @@ namespace ICD.Common.Utils.Extensions
|
||||
/// <param name="other"></param>
|
||||
/// <returns></returns>
|
||||
[PublicAPI]
|
||||
public static T Unanimous<T>(this IEnumerable<T> extends, T other)
|
||||
public static T Unanimous<T>([NotNull] this IEnumerable<T> extends, T other)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
@@ -985,7 +1155,7 @@ namespace ICD.Common.Utils.Extensions
|
||||
/// <param name="result"></param>
|
||||
/// <returns></returns>
|
||||
[PublicAPI]
|
||||
public static bool Unanimous<T>(this IEnumerable<T> extends, out T result)
|
||||
public static bool Unanimous<T>([NotNull] this IEnumerable<T> extends, out T result)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
@@ -1003,7 +1173,8 @@ namespace ICD.Common.Utils.Extensions
|
||||
/// <param name="result"></param>
|
||||
/// <returns></returns>
|
||||
[PublicAPI]
|
||||
public static bool Unanimous<T>(this IEnumerable<T> extends, IEqualityComparer<T> comparer, out T result)
|
||||
public static bool Unanimous<T>([NotNull] this IEnumerable<T> extends, [NotNull] IEqualityComparer<T> comparer,
|
||||
out T result)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
@@ -1042,7 +1213,7 @@ namespace ICD.Common.Utils.Extensions
|
||||
/// <param name="partitionSize"></param>
|
||||
/// <returns></returns>
|
||||
[PublicAPI]
|
||||
public static IEnumerable<IEnumerable<T>> Partition<T>(this IEnumerable<T> extends, int partitionSize)
|
||||
public static IEnumerable<IEnumerable<T>> Partition<T>([NotNull] this IEnumerable<T> extends, int partitionSize)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
@@ -1056,7 +1227,8 @@ namespace ICD.Common.Utils.Extensions
|
||||
/// <param name="sequence"></param>
|
||||
/// <param name="partitionSize"></param>
|
||||
/// <returns></returns>
|
||||
private static IEnumerable<IEnumerable<T>> PartitionIterator<T>(IEnumerable<T> sequence, int partitionSize)
|
||||
private static IEnumerable<IEnumerable<T>> PartitionIterator<T>([NotNull] IEnumerable<T> sequence,
|
||||
int partitionSize)
|
||||
{
|
||||
using (IEnumerator<T> enumerator = sequence.GetEnumerator())
|
||||
{
|
||||
@@ -1065,7 +1237,7 @@ namespace ICD.Common.Utils.Extensions
|
||||
}
|
||||
}
|
||||
|
||||
private static IEnumerable<T> YieldBatchElements<T>(IEnumerator<T> source, int partitionSize)
|
||||
private static IEnumerable<T> YieldBatchElements<T>([NotNull] IEnumerator<T> source, int partitionSize)
|
||||
{
|
||||
if (source == null)
|
||||
throw new ArgumentNullException("source");
|
||||
@@ -1086,7 +1258,7 @@ namespace ICD.Common.Utils.Extensions
|
||||
/// <typeparam name="T">Type of the object.</typeparam>
|
||||
/// <param name="item">The instance that will be wrapped.</param>
|
||||
/// <returns>An IEnumerable<T> consisting of a single item.</returns>
|
||||
public static IEnumerable<T> Yield<T>(this T item)
|
||||
public static IEnumerable<T> Yield<T>([CanBeNull] this T item)
|
||||
{
|
||||
yield return item;
|
||||
}
|
||||
@@ -1097,7 +1269,7 @@ namespace ICD.Common.Utils.Extensions
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="extends"></param>
|
||||
/// <returns></returns>
|
||||
public static IEnumerable<T[]> GetAdjacentPairs<T>(this IEnumerable<T> extends)
|
||||
public static IEnumerable<T[]> GetAdjacentPairs<T>([NotNull] this IEnumerable<T> extends)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
@@ -1111,7 +1283,7 @@ namespace ICD.Common.Utils.Extensions
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="extends"></param>
|
||||
/// <returns></returns>
|
||||
private static IEnumerable<T[]> GetAdjacentPairsIterator<T>(IEnumerable<T> extends)
|
||||
private static IEnumerable<T[]> GetAdjacentPairsIterator<T>([NotNull] IEnumerable<T> extends)
|
||||
{
|
||||
T previous = default(T);
|
||||
bool first = true;
|
||||
@@ -1119,7 +1291,7 @@ namespace ICD.Common.Utils.Extensions
|
||||
foreach (T item in extends)
|
||||
{
|
||||
if (!first)
|
||||
yield return new[] { previous, item };
|
||||
yield return new[] {previous, item};
|
||||
|
||||
first = false;
|
||||
previous = item;
|
||||
@@ -1133,7 +1305,7 @@ namespace ICD.Common.Utils.Extensions
|
||||
/// <param name="extends"></param>
|
||||
/// <param name="getDelta"></param>
|
||||
/// <returns></returns>
|
||||
public static T GetClosest<T>(this IEnumerable<T> extends, Func<T, int> getDelta)
|
||||
public static T GetClosest<T>([NotNull] this IEnumerable<T> extends, [NotNull] Func<T, int> getDelta)
|
||||
{
|
||||
return extends.MinBy(n => Math.Abs(getDelta(n)));
|
||||
}
|
||||
@@ -1156,8 +1328,8 @@ namespace ICD.Common.Utils.Extensions
|
||||
/// <exception cref="ArgumentNullException"><paramref name="source"/> or <paramref name="selector"/> is null</exception>
|
||||
/// <exception cref="InvalidOperationException"><paramref name="source"/> is empty</exception>
|
||||
[PublicAPI]
|
||||
public static TSource MinBy<TSource, TKey>(this IEnumerable<TSource> source,
|
||||
Func<TSource, TKey> selector)
|
||||
public static TSource MinBy<TSource, TKey>([NotNull] this IEnumerable<TSource> source,
|
||||
[NotNull] Func<TSource, TKey> selector)
|
||||
{
|
||||
if (source == null)
|
||||
throw new ArgumentNullException("source");
|
||||
@@ -1187,8 +1359,9 @@ namespace ICD.Common.Utils.Extensions
|
||||
/// or <paramref name="comparer"/> is null</exception>
|
||||
/// <exception cref="InvalidOperationException"><paramref name="source"/> is empty</exception>
|
||||
[PublicAPI]
|
||||
public static TSource MinBy<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> selector,
|
||||
IComparer<TKey> comparer)
|
||||
public static TSource MinBy<TSource, TKey>([NotNull] this IEnumerable<TSource> source,
|
||||
[NotNull] Func<TSource, TKey> selector,
|
||||
[NotNull] IComparer<TKey> comparer)
|
||||
{
|
||||
if (source == null)
|
||||
throw new ArgumentNullException("source");
|
||||
@@ -1224,19 +1397,57 @@ namespace ICD.Common.Utils.Extensions
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes any null elements from an enumerable of nullable value types
|
||||
/// Returns the minimum value from the sequence, otherwise the default value.
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="extends"></param>
|
||||
/// <returns></returns>
|
||||
[PublicAPI]
|
||||
public static IEnumerable<T> ExceptNulls<T>(this IEnumerable<T?> extends)
|
||||
where T : struct
|
||||
public static T MinOrDefault<T>([NotNull] this IEnumerable<T> extends)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
|
||||
return extends.OfType<T>();
|
||||
Comparer<T> comparer = Comparer<T>.Default;
|
||||
T value = default(T);
|
||||
bool first = true;
|
||||
|
||||
foreach (T x in extends)
|
||||
{
|
||||
if (first)
|
||||
{
|
||||
first = false;
|
||||
value = x;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (comparer.Compare(x, value) < 0)
|
||||
value = x;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the maximum value from the sequence, otherwise the default value.
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="extends"></param>
|
||||
/// <returns></returns>
|
||||
public static T MaxOrDefault<T>([NotNull] this IEnumerable<T> extends)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
|
||||
Comparer<T> comparer = Comparer<T>.Default;
|
||||
T value = default(T);
|
||||
|
||||
foreach (T x in extends)
|
||||
{
|
||||
if (comparer.Compare(x, value) > 0)
|
||||
value = x;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -1245,7 +1456,7 @@ namespace ICD.Common.Utils.Extensions
|
||||
/// <param name="extends"></param>
|
||||
/// <returns></returns>
|
||||
[PublicAPI]
|
||||
public static byte Sum(this IEnumerable<byte> extends)
|
||||
public static byte Sum([NotNull] this IEnumerable<byte> extends)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
@@ -1264,7 +1475,7 @@ namespace ICD.Common.Utils.Extensions
|
||||
/// <param name="extends"></param>
|
||||
/// <returns></returns>
|
||||
[PublicAPI]
|
||||
public static IEnumerable<T> Consolidate<T>(this IEnumerable<T> extends)
|
||||
public static IEnumerable<T> Consolidate<T>([NotNull] this IEnumerable<T> extends)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
@@ -1284,7 +1495,8 @@ namespace ICD.Common.Utils.Extensions
|
||||
/// <param name="comparer"></param>
|
||||
/// <returns></returns>
|
||||
[PublicAPI]
|
||||
public static IEnumerable<T> Consolidate<T>(this IEnumerable<T> extends, IComparer<T> comparer)
|
||||
public static IEnumerable<T> Consolidate<T>([NotNull] this IEnumerable<T> extends,
|
||||
[NotNull] IComparer<T> comparer)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
@@ -1306,7 +1518,8 @@ namespace ICD.Common.Utils.Extensions
|
||||
/// <param name="sequence"></param>
|
||||
/// <param name="comparer"></param>
|
||||
/// <returns></returns>
|
||||
private static IEnumerable<T> ConsolidateIterator<T>(IEnumerable<T> sequence, IComparer<T> comparer)
|
||||
private static IEnumerable<T> ConsolidateIterator<T>([NotNull] IEnumerable<T> sequence,
|
||||
[NotNull] IComparer<T> comparer)
|
||||
{
|
||||
bool first = true;
|
||||
T last = default(T);
|
||||
@@ -1332,7 +1545,7 @@ namespace ICD.Common.Utils.Extensions
|
||||
/// <param name="predicate"></param>
|
||||
/// <returns></returns>
|
||||
[PublicAPI]
|
||||
public static bool AnyAndAll<T>(this IEnumerable<T> extends, Func<T, bool> predicate)
|
||||
public static bool AnyAndAll<T>([NotNull] this IEnumerable<T> extends, [NotNull] Func<T, bool> predicate)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
@@ -1351,19 +1564,40 @@ namespace ICD.Common.Utils.Extensions
|
||||
return any;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Combines the corresponding elements of two sequences, producing a sequence of KeyValuePairs.
|
||||
/// </summary>
|
||||
/// <typeparam name="TFirst"></typeparam>
|
||||
/// <typeparam name="TSecond"></typeparam>
|
||||
/// <param name="extends"></param>
|
||||
/// <param name="second"></param>
|
||||
public static IEnumerable<KeyValuePair<TFirst, TSecond>> Zip<TFirst, TSecond>(
|
||||
[NotNull] this IEnumerable<TFirst> extends,
|
||||
[NotNull] IEnumerable<TSecond> second)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
|
||||
if (second == null)
|
||||
throw new ArgumentNullException("second");
|
||||
|
||||
return extends.Zip(second, (f, s) => new KeyValuePair<TFirst, TSecond>(f, s));
|
||||
}
|
||||
|
||||
#if SIMPLSHARP
|
||||
/// <summary>
|
||||
/// Applies a specified function to the corresponding elements of two sequences, producing a sequence of the results.
|
||||
/// </summary>
|
||||
/// <typeparam name="TFirst"></typeparam>
|
||||
/// <typeparam name="TSecond"></typeparam>
|
||||
/// <param name="first"></param>
|
||||
/// <param name="extends"></param>
|
||||
/// <param name="second"></param>
|
||||
/// <param name="callback"></param>
|
||||
public static void Zip<TFirst, TSecond>(this IEnumerable<TFirst> first,
|
||||
IEnumerable<TSecond> second,
|
||||
Action<TFirst, TSecond> callback)
|
||||
public static void Zip<TFirst, TSecond>([NotNull]this IEnumerable<TFirst> extends,
|
||||
[NotNull]IEnumerable<TSecond> second,
|
||||
[NotNull]Action<TFirst, TSecond> callback)
|
||||
{
|
||||
if (first == null)
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("first");
|
||||
|
||||
if (second == null)
|
||||
@@ -1372,7 +1606,7 @@ namespace ICD.Common.Utils.Extensions
|
||||
if (callback == null)
|
||||
throw new ArgumentNullException("callback");
|
||||
|
||||
using (IEnumerator<TFirst> enumerator1 = first.GetEnumerator())
|
||||
using (IEnumerator<TFirst> enumerator1 = extends.GetEnumerator())
|
||||
{
|
||||
using (IEnumerator<TSecond> enumerator2 = second.GetEnumerator())
|
||||
{
|
||||
@@ -1382,51 +1616,6 @@ namespace ICD.Common.Utils.Extensions
|
||||
}
|
||||
}
|
||||
|
||||
// since S# can't do anonymous types
|
||||
private struct TryParseStruct<T>
|
||||
{
|
||||
public readonly T value;
|
||||
public readonly bool isParsed;
|
||||
|
||||
public TryParseStruct(T value, bool isParsed)
|
||||
{
|
||||
this.value = value;
|
||||
this.isParsed = isParsed;
|
||||
}
|
||||
}
|
||||
|
||||
// since Func<...,T> can't specify `out` parameters
|
||||
public delegate bool TryParseDelegate<T>(string input, out T output);
|
||||
|
||||
/// <summary>
|
||||
/// Attempts to parse each value of the enumerable,
|
||||
/// throwing away the values that don't parse correctly.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">type to parse to</typeparam>
|
||||
/// <param name="extends">enumerable of strings to parse</param>
|
||||
/// <param name="tryParseFunc">TryParse function for given type</param>
|
||||
/// <returns>enumerable of successfully parsed values</returns>
|
||||
public static IEnumerable<T> TryParseSkipFailures<T>(this IEnumerable<string> extends,
|
||||
TryParseDelegate<T> tryParseFunc)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
|
||||
if (tryParseFunc == null)
|
||||
throw new ArgumentNullException("tryParseFunc");
|
||||
|
||||
return extends.Select(str =>
|
||||
{
|
||||
T value;
|
||||
bool isParsed = tryParseFunc(str, out value);
|
||||
return new TryParseStruct<T>(value, isParsed);
|
||||
})
|
||||
.Where(v => v.isParsed)
|
||||
.Select(v => v.value);
|
||||
}
|
||||
|
||||
#if SIMPLSHARP
|
||||
|
||||
/// <summary>
|
||||
/// Applies a specified function to the corresponding elements of two sequences, producing a sequence of the results.
|
||||
/// </summary>
|
||||
@@ -1437,9 +1626,9 @@ namespace ICD.Common.Utils.Extensions
|
||||
/// <param name="other"></param>
|
||||
/// <param name="callback"></param>
|
||||
/// <returns></returns>
|
||||
public static IEnumerable<TResult> Zip<TFirst, TSecond, TResult>(this IEnumerable<TFirst> extends,
|
||||
IEnumerable<TSecond> other,
|
||||
Func<TFirst, TSecond, TResult> callback)
|
||||
public static IEnumerable<TResult> Zip<TFirst, TSecond, TResult>([NotNull]this IEnumerable<TFirst> extends,
|
||||
[NotNull]IEnumerable<TSecond> other,
|
||||
[NotNull]Func<TFirst, TSecond, TResult> callback)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
@@ -1463,9 +1652,9 @@ namespace ICD.Common.Utils.Extensions
|
||||
/// <param name="second"></param>
|
||||
/// <param name="callback"></param>
|
||||
/// <returns></returns>
|
||||
private static IEnumerable<TResult> ZipIterator<TFirst, TSecond, TResult>(IEnumerable<TFirst> first,
|
||||
IEnumerable<TSecond> second,
|
||||
Func<TFirst, TSecond, TResult> callback)
|
||||
private static IEnumerable<TResult> ZipIterator<TFirst, TSecond, TResult>([NotNull]IEnumerable<TFirst> first,
|
||||
[NotNull]IEnumerable<TSecond> second,
|
||||
[NotNull]Func<TFirst, TSecond, TResult> callback)
|
||||
{
|
||||
using (IEnumerator<TFirst> enumerator1 = first.GetEnumerator())
|
||||
{
|
||||
@@ -1476,7 +1665,6 @@ namespace ICD.Common.Utils.Extensions
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,5 @@
|
||||
using System;
|
||||
#if SIMPLSHARP
|
||||
using Crestron.SimplSharp.Reflection;
|
||||
#else
|
||||
using System.Reflection;
|
||||
#endif
|
||||
using ICD.Common.Properties;
|
||||
|
||||
namespace ICD.Common.Utils.Extensions
|
||||
{
|
||||
@@ -17,7 +13,7 @@ namespace ICD.Common.Utils.Extensions
|
||||
/// </summary>
|
||||
/// <param name="extends"></param>
|
||||
/// <param name="sender"></param>
|
||||
public static void Raise(this EventHandler extends, object sender)
|
||||
public static void Raise([CanBeNull] this EventHandler extends, object sender)
|
||||
{
|
||||
if (extends != null)
|
||||
extends(sender, EventArgs.Empty);
|
||||
@@ -30,7 +26,7 @@ namespace ICD.Common.Utils.Extensions
|
||||
/// <param name="extends"></param>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="args"></param>
|
||||
public static void Raise<T>(this EventHandler<T> extends, object sender, T args)
|
||||
public static void Raise<T>([CanBeNull]this EventHandler<T> extends, object sender, [NotNull]T args)
|
||||
where T : EventArgs
|
||||
{
|
||||
if (args == null)
|
||||
@@ -39,22 +35,5 @@ namespace ICD.Common.Utils.Extensions
|
||||
if (extends != null)
|
||||
extends(sender, args);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Cross-platform shim for getting MethodInfo for the delegate.
|
||||
/// </summary>
|
||||
/// <param name="extends"></param>
|
||||
/// <returns></returns>
|
||||
public static MethodInfo GetMethodInfo(this Delegate extends)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
|
||||
#if SIMPLSHARP
|
||||
return extends.GetMethod();
|
||||
#else
|
||||
return extends.Method;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
using System;
|
||||
using System.Text.RegularExpressions;
|
||||
using ICD.Common.Properties;
|
||||
using ICD.Common.Utils.Json;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace ICD.Common.Utils.Extensions
|
||||
@@ -16,12 +16,17 @@ namespace ICD.Common.Utils.Extensions
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="extends"></param>
|
||||
/// <returns></returns>
|
||||
public static T ReadAsObject<T>(this JsonReader extends)
|
||||
public static T ReadAsObject<T>([NotNull] this JsonReader extends)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
|
||||
JsonSerializer serializer = new JsonSerializer();
|
||||
JsonSerializer serializer =
|
||||
#if SIMPLSHARP
|
||||
new JsonSerializer();
|
||||
#else
|
||||
JsonSerializer.CreateDefault();
|
||||
#endif
|
||||
return extends.ReadAsObject<T>(serializer);
|
||||
}
|
||||
|
||||
@@ -32,7 +37,7 @@ namespace ICD.Common.Utils.Extensions
|
||||
/// <param name="extends"></param>
|
||||
/// <param name="serializer"></param>
|
||||
/// <returns></returns>
|
||||
public static T ReadAsObject<T>(this JsonReader extends, JsonSerializer serializer)
|
||||
public static T ReadAsObject<T>([NotNull] this JsonReader extends, [NotNull] JsonSerializer serializer)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
@@ -49,8 +54,8 @@ namespace ICD.Common.Utils.Extensions
|
||||
/// <param name="extends"></param>
|
||||
/// <param name="serializer"></param>
|
||||
/// <param name="readPropertyValue"></param>
|
||||
public static void ReadObject(this JsonReader extends, JsonSerializer serializer,
|
||||
Action<string, JsonReader, JsonSerializer> readPropertyValue)
|
||||
public static void ReadObject([NotNull] this JsonReader extends, [NotNull] JsonSerializer serializer,
|
||||
[NotNull] Action<string, JsonReader, JsonSerializer> readPropertyValue)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
@@ -65,7 +70,8 @@ namespace ICD.Common.Utils.Extensions
|
||||
return;
|
||||
|
||||
if (extends.TokenType != JsonToken.StartObject)
|
||||
throw new FormatException(string.Format("Expected {0} got {1}", JsonToken.StartObject, extends.TokenType));
|
||||
throw new FormatException(string.Format("Expected {0} got {1}", JsonToken.StartObject,
|
||||
extends.TokenType));
|
||||
|
||||
while (extends.Read())
|
||||
{
|
||||
@@ -90,11 +96,15 @@ namespace ICD.Common.Utils.Extensions
|
||||
/// <param name="extends"></param>
|
||||
/// <returns></returns>
|
||||
[PublicAPI]
|
||||
public static Type GetValueAsType(this JsonReader extends)
|
||||
[CanBeNull]
|
||||
public static Type GetValueAsType([NotNull] this JsonReader extends)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
|
||||
if (extends.TokenType == JsonToken.Null)
|
||||
return null;
|
||||
|
||||
string value = extends.GetValueAsString();
|
||||
return Type.GetType(value);
|
||||
}
|
||||
@@ -105,7 +115,7 @@ namespace ICD.Common.Utils.Extensions
|
||||
/// <param name="extends"></param>
|
||||
/// <returns></returns>
|
||||
[PublicAPI]
|
||||
public static uint GetValueAsUInt(this JsonReader extends)
|
||||
public static uint GetValueAsUInt([NotNull] this JsonReader extends)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
@@ -113,7 +123,8 @@ namespace ICD.Common.Utils.Extensions
|
||||
if (extends.TokenType == JsonToken.Integer)
|
||||
return (uint)(long)extends.Value;
|
||||
|
||||
string message = string.Format("Token {0} {1} is not {2}", extends.TokenType, extends.Value, JsonToken.Integer);
|
||||
string message = string.Format("Token {0} {1} is not {2}", extends.TokenType, extends.Value,
|
||||
JsonToken.Integer);
|
||||
throw new InvalidCastException(message);
|
||||
}
|
||||
|
||||
@@ -123,7 +134,7 @@ namespace ICD.Common.Utils.Extensions
|
||||
/// <param name="extends"></param>
|
||||
/// <returns></returns>
|
||||
[PublicAPI]
|
||||
public static int GetValueAsInt(this JsonReader extends)
|
||||
public static int GetValueAsInt([NotNull] this JsonReader extends)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
@@ -131,7 +142,84 @@ namespace ICD.Common.Utils.Extensions
|
||||
if (extends.TokenType == JsonToken.Integer)
|
||||
return (int)(long)extends.Value;
|
||||
|
||||
string message = string.Format("Token {0} {1} is not {2}", extends.TokenType, extends.Value, JsonToken.Integer);
|
||||
string message = string.Format("Token {0} {1} is not {2}", extends.TokenType, extends.Value,
|
||||
JsonToken.Integer);
|
||||
throw new InvalidCastException(message);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the current value as a long.
|
||||
/// </summary>
|
||||
/// <param name="extends"></param>
|
||||
/// <returns></returns>
|
||||
[PublicAPI]
|
||||
public static long GetValueAsLong([NotNull] this JsonReader extends)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
|
||||
if (extends.TokenType == JsonToken.Integer)
|
||||
return (long)extends.Value;
|
||||
|
||||
string message = string.Format("Token {0} {1} is not {2}", extends.TokenType, extends.Value,
|
||||
JsonToken.Integer);
|
||||
throw new InvalidCastException(message);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the current value as an unsigned long.
|
||||
/// </summary>
|
||||
/// <param name="extends"></param>
|
||||
/// <returns></returns>
|
||||
[PublicAPI]
|
||||
public static ulong GetValueAsULong([NotNull] this JsonReader extends)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
|
||||
if (extends.TokenType == JsonToken.Integer)
|
||||
return (ulong)extends.Value;
|
||||
|
||||
string message = string.Format("Token {0} {1} is not {2}", extends.TokenType, extends.Value,
|
||||
JsonToken.Integer);
|
||||
throw new InvalidCastException(message);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the current value as a float.
|
||||
/// </summary>
|
||||
/// <param name="extends"></param>
|
||||
/// <returns></returns>
|
||||
[PublicAPI]
|
||||
public static float GetValueAsFloat([NotNull] this JsonReader extends)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
|
||||
if (extends.TokenType == JsonToken.Float || extends.TokenType == JsonToken.Integer)
|
||||
return (float)extends.Value;
|
||||
|
||||
string message = string.Format("Token {0} {1} is not {2}", extends.TokenType, extends.Value,
|
||||
JsonToken.Integer);
|
||||
throw new InvalidCastException(message);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the current value as a double.
|
||||
/// </summary>
|
||||
/// <param name="extends"></param>
|
||||
/// <returns></returns>
|
||||
[PublicAPI]
|
||||
public static double GetValueAsDouble([NotNull] this JsonReader extends)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
|
||||
if (extends.TokenType == JsonToken.Float || extends.TokenType == JsonToken.Integer)
|
||||
return (double)extends.Value;
|
||||
|
||||
string message = string.Format("Token {0} {1} is not {2}", extends.TokenType, extends.Value,
|
||||
JsonToken.Integer);
|
||||
throw new InvalidCastException(message);
|
||||
}
|
||||
|
||||
@@ -141,12 +229,21 @@ namespace ICD.Common.Utils.Extensions
|
||||
/// <param name="extends"></param>
|
||||
/// <returns></returns>
|
||||
[PublicAPI]
|
||||
public static string GetValueAsString(this JsonReader extends)
|
||||
public static string GetValueAsString([NotNull] this JsonReader extends)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
|
||||
return extends.Value as string;
|
||||
#if !SIMPLSHARP
|
||||
// Newer versions of NewtonSoft try to be helpful and interpret strings as DateTimes without any consideration for different DateTime formats.
|
||||
if (extends.TokenType == JsonToken.Date && extends.DateParseHandling != DateParseHandling.None)
|
||||
throw new InvalidOperationException("DateParseHandling needs to be set to None");
|
||||
#endif
|
||||
|
||||
if (!extends.TokenType.IsPrimitive())
|
||||
throw new FormatException("Expected primitive token type but got " + extends.TokenType);
|
||||
|
||||
return extends.Value == null ? null : extends.Value.ToString();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -155,7 +252,7 @@ namespace ICD.Common.Utils.Extensions
|
||||
/// <param name="extends"></param>
|
||||
/// <returns></returns>
|
||||
[PublicAPI]
|
||||
public static bool GetValueAsBool(this JsonReader extends)
|
||||
public static bool GetValueAsBool([NotNull] this JsonReader extends)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
@@ -163,7 +260,8 @@ namespace ICD.Common.Utils.Extensions
|
||||
if (extends.TokenType == JsonToken.Boolean)
|
||||
return (bool)extends.Value;
|
||||
|
||||
string message = string.Format("Token {0} {1} is not {2}", extends.TokenType, extends.Value, JsonToken.Boolean);
|
||||
string message = string.Format("Token {0} {1} is not {2}", extends.TokenType, extends.Value,
|
||||
JsonToken.Boolean);
|
||||
throw new InvalidCastException(message);
|
||||
}
|
||||
|
||||
@@ -173,7 +271,7 @@ namespace ICD.Common.Utils.Extensions
|
||||
/// <param name="extends"></param>
|
||||
/// <returns></returns>
|
||||
[PublicAPI]
|
||||
public static T GetValueAsEnum<T>(this JsonReader extends)
|
||||
public static T GetValueAsEnum<T>([NotNull] this JsonReader extends)
|
||||
where T : struct, IConvertible
|
||||
{
|
||||
if (extends == null)
|
||||
@@ -191,7 +289,7 @@ namespace ICD.Common.Utils.Extensions
|
||||
/// <param name="extends"></param>
|
||||
/// <returns></returns>
|
||||
[PublicAPI]
|
||||
public static Guid GetValueAsGuid(this JsonReader extends)
|
||||
public static Guid GetValueAsGuid([NotNull] this JsonReader extends)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
@@ -205,13 +303,39 @@ namespace ICD.Common.Utils.Extensions
|
||||
/// </summary>
|
||||
/// <param name="extends"></param>
|
||||
/// <returns></returns>
|
||||
public static DateTime GetValueAsDateTime(this JsonReader extends)
|
||||
public static DateTime GetValueAsDateTime([NotNull] this JsonReader extends)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
|
||||
string stringValue = extends.GetValueAsString();
|
||||
return JsonUtils.ParseDateTime(stringValue);
|
||||
#if !SIMPLSHARP
|
||||
// Newer NewtonSoft tries to be helpful by assuming that anything that looks like a DateTime must be a date.
|
||||
if (extends.DateParseHandling != DateParseHandling.None)
|
||||
return (DateTime)extends.Value;
|
||||
#endif
|
||||
/*
|
||||
"\"\\/Date(1335205592410)\\/\"" .NET JavaScriptSerializer
|
||||
"\"\\/Date(1335205592410-0500)\\/\"" .NET DataContractJsonSerializer
|
||||
"2012-04-23T18:25:43.511Z" JavaScript built-in JSON object
|
||||
"2012-04-21T18:25:43-05:00" ISO 8601
|
||||
*/
|
||||
|
||||
string serial = extends.GetValueAsString();
|
||||
|
||||
Match match;
|
||||
if (RegexUtils.Matches(serial, @"Date\((?'date'\d+)(?'zone'(-|\+)\d+)?\)", out match))
|
||||
{
|
||||
long ms = long.Parse(match.Groups["date"].Value);
|
||||
DateTime dateTime = DateTimeUtils.FromEpochMilliseconds(ms);
|
||||
if (!match.Groups["zone"].Success)
|
||||
return dateTime;
|
||||
|
||||
// No TimeZoneInfo in CF, so now things get gross
|
||||
dateTime = DateTime.SpecifyKind(dateTime, DateTimeKind.Unspecified);
|
||||
serial = dateTime.ToIso() + match.Groups["zone"].Value;
|
||||
}
|
||||
|
||||
return DateTimeUtils.FromIso8601(serial);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,21 +1,32 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using ICD.Common.Properties;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace ICD.Common.Utils.Extensions
|
||||
{
|
||||
public static class JsonSerializerExtensions
|
||||
{
|
||||
private const string PROPERTY_KEY = "k";
|
||||
private const string PROPERTY_VALUE = "v";
|
||||
|
||||
/// <summary>
|
||||
/// Deserializes an array of items from the reader's current value.
|
||||
/// </summary>
|
||||
/// <typeparam name="TItem"></typeparam>
|
||||
/// <param name="extends"></param>
|
||||
/// <param name="reader"></param>
|
||||
public static IEnumerable<TItem> DeserializeArray<TItem>(this JsonSerializer extends, JsonReader reader)
|
||||
[CanBeNull]
|
||||
public static IEnumerable<TItem> DeserializeArray<TItem>([NotNull] this JsonSerializer extends,
|
||||
[NotNull] JsonReader reader)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
|
||||
if (reader == null)
|
||||
throw new ArgumentNullException("reader");
|
||||
|
||||
return extends.DeserializeArray(reader, (s, r) => extends.Deserialize<TItem>(reader));
|
||||
}
|
||||
|
||||
@@ -26,8 +37,10 @@ namespace ICD.Common.Utils.Extensions
|
||||
/// <param name="extends"></param>
|
||||
/// <param name="reader"></param>
|
||||
/// <param name="read"></param>
|
||||
public static IEnumerable<TItem> DeserializeArray<TItem>(this JsonSerializer extends, JsonReader reader,
|
||||
Func<JsonSerializer, JsonReader, TItem> read)
|
||||
[CanBeNull]
|
||||
public static IEnumerable<TItem> DeserializeArray<TItem>([NotNull] this JsonSerializer extends,
|
||||
[NotNull] JsonReader reader,
|
||||
[NotNull] Func<JsonSerializer, JsonReader, TItem> read)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
@@ -39,10 +52,11 @@ namespace ICD.Common.Utils.Extensions
|
||||
throw new ArgumentNullException("read");
|
||||
|
||||
if (reader.TokenType == JsonToken.Null)
|
||||
return Enumerable.Empty<TItem>();
|
||||
return null;
|
||||
|
||||
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));
|
||||
|
||||
// ToArray to ensure everything gets read before moving onto the next token
|
||||
return DeserializeArrayIterator(extends, reader, read).ToArray();
|
||||
@@ -55,8 +69,10 @@ namespace ICD.Common.Utils.Extensions
|
||||
/// <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)
|
||||
[NotNull]
|
||||
private static IEnumerable<TItem> DeserializeArrayIterator<TItem>(
|
||||
[NotNull] JsonSerializer serializer, [NotNull] JsonReader reader,
|
||||
[NotNull] Func<JsonSerializer, JsonReader, TItem> read)
|
||||
{
|
||||
// Step into the first value
|
||||
reader.Read();
|
||||
@@ -78,41 +94,10 @@ namespace ICD.Common.Utils.Extensions
|
||||
/// <typeparam name="TValue"></typeparam>
|
||||
/// <param name="extends"></param>
|
||||
/// <param name="reader"></param>
|
||||
public static IEnumerable<KeyValuePair<TKey, TValue>> DeserializeDict<TKey, TValue>(this JsonSerializer extends,
|
||||
JsonReader reader)
|
||||
{
|
||||
return extends.DeserializeDict<TKey, TValue>(reader, p => (TKey)Convert.ChangeType(p, typeof(TKey), CultureInfo.InvariantCulture));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Deserializes a dictionary of items from the reader's current value.
|
||||
/// </summary>
|
||||
/// <typeparam name="TKey"></typeparam>
|
||||
/// <typeparam name="TValue"></typeparam>
|
||||
/// <param name="extends"></param>
|
||||
/// <param name="reader"></param>
|
||||
/// <param name="getKey"></param>
|
||||
public static IEnumerable<KeyValuePair<TKey, TValue>> DeserializeDict<TKey, TValue>(this JsonSerializer extends,
|
||||
JsonReader reader,
|
||||
Func<string, TKey> getKey)
|
||||
{
|
||||
return extends.DeserializeDict(reader, getKey, (s, r) => extends.Deserialize<TValue>(reader));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Deserializes a dictionary of items from the reader's current value.
|
||||
/// </summary>
|
||||
/// <typeparam name="TKey"></typeparam>
|
||||
/// <typeparam name="TValue"></typeparam>
|
||||
/// <param name="extends"></param>
|
||||
/// <param name="reader"></param>
|
||||
/// <param name="getKey"></param>
|
||||
/// <param name="readValue"></param>
|
||||
public static IEnumerable<KeyValuePair<TKey, TValue>> DeserializeDict<TKey, TValue>(this JsonSerializer extends,
|
||||
JsonReader reader,
|
||||
Func<string, TKey> getKey,
|
||||
Func<JsonSerializer, JsonReader,
|
||||
TValue> readValue)
|
||||
[CanBeNull]
|
||||
public static IEnumerable<KeyValuePair<TKey, TValue>> DeserializeDict<TKey, TValue>(
|
||||
[NotNull] this JsonSerializer extends,
|
||||
[NotNull] JsonReader reader)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
@@ -120,20 +105,9 @@ namespace ICD.Common.Utils.Extensions
|
||||
if (reader == null)
|
||||
throw new ArgumentNullException("reader");
|
||||
|
||||
if (getKey == null)
|
||||
throw new ArgumentNullException("getKey");
|
||||
|
||||
if (readValue == null)
|
||||
throw new ArgumentNullException("readValue");
|
||||
|
||||
if (reader.TokenType == JsonToken.Null)
|
||||
return Enumerable.Empty<KeyValuePair<TKey, TValue>>();
|
||||
|
||||
if (reader.TokenType != JsonToken.StartObject)
|
||||
throw new FormatException(string.Format("Expected token {0} got {1}", JsonToken.StartObject, reader.TokenType));
|
||||
|
||||
// ToArray to ensure everything gets read before moving onto the next token
|
||||
return DeserializeDictIterator(extends, reader, getKey, readValue).ToArray();
|
||||
return extends.DeserializeDict(reader,
|
||||
(s, r) => s.Deserialize<TKey>(r),
|
||||
(s, r) => s.Deserialize<TValue>(r));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -141,34 +115,90 @@ namespace ICD.Common.Utils.Extensions
|
||||
/// </summary>
|
||||
/// <typeparam name="TKey"></typeparam>
|
||||
/// <typeparam name="TValue"></typeparam>
|
||||
/// <param name="serializer"></param>
|
||||
/// <param name="extends"></param>
|
||||
/// <param name="reader"></param>
|
||||
/// <param name="getKey"></param>
|
||||
/// <param name="readKey"></param>
|
||||
/// <param name="readValue"></param>
|
||||
private static IEnumerable<KeyValuePair<TKey, TValue>> DeserializeDictIterator<TKey, TValue>(
|
||||
JsonSerializer serializer, JsonReader reader,
|
||||
Func<string, TKey> getKey,
|
||||
Func<JsonSerializer, JsonReader, TValue> readValue)
|
||||
[CanBeNull]
|
||||
public static IEnumerable<KeyValuePair<TKey, TValue>> DeserializeDict<TKey, TValue>(
|
||||
[NotNull] this JsonSerializer extends,
|
||||
[NotNull] JsonReader reader,
|
||||
[NotNull] Func<JsonSerializer, JsonReader, TKey> readKey,
|
||||
[NotNull] Func<JsonSerializer, JsonReader, TValue> readValue)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
|
||||
if (reader == null)
|
||||
throw new ArgumentNullException("reader");
|
||||
|
||||
if (readKey == null)
|
||||
throw new ArgumentNullException("readKey");
|
||||
|
||||
if (readValue == null)
|
||||
throw new ArgumentNullException("readValue");
|
||||
|
||||
return extends.DeserializeArray(reader, (s, r) => s.DeserializeKeyValuePair(r, readKey, readValue));
|
||||
}
|
||||
|
||||
public static KeyValuePair<TKey, TValue> DeserializeKeyValuePair<TKey, TValue>(
|
||||
[NotNull] this JsonSerializer extends,
|
||||
[NotNull] JsonReader reader,
|
||||
[NotNull] Func<JsonSerializer, JsonReader, TKey> readKey,
|
||||
[NotNull] Func<JsonSerializer, JsonReader, TValue> readValue)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
|
||||
if (reader == null)
|
||||
throw new ArgumentNullException("reader");
|
||||
|
||||
if (readKey == null)
|
||||
throw new ArgumentNullException("readKey");
|
||||
|
||||
if (readValue == null)
|
||||
throw new ArgumentNullException("readValue");
|
||||
|
||||
if (reader.TokenType != JsonToken.StartObject)
|
||||
throw new FormatException(string.Format("Expected token {0} got {1}", JsonToken.StartObject,
|
||||
reader.TokenType));
|
||||
|
||||
TKey key = default(TKey);
|
||||
TValue value = default(TValue);
|
||||
|
||||
// Step into the first property
|
||||
reader.Read();
|
||||
|
||||
while (reader.TokenType != JsonToken.EndObject)
|
||||
{
|
||||
if (reader.TokenType != JsonToken.PropertyName)
|
||||
throw new FormatException();
|
||||
throw new FormatException(string.Format("Expected token {0} got {1}", JsonToken.PropertyName,
|
||||
reader.TokenType));
|
||||
|
||||
TKey key = getKey((string)reader.Value);
|
||||
string propertyName = (string)reader.Value;
|
||||
|
||||
// Step into the value
|
||||
reader.Read();
|
||||
|
||||
TValue value = readValue(serializer, reader);
|
||||
yield return new KeyValuePair<TKey, TValue>(key, value);
|
||||
switch (propertyName)
|
||||
{
|
||||
case PROPERTY_KEY:
|
||||
key = readKey(extends, reader);
|
||||
break;
|
||||
|
||||
case PROPERTY_VALUE:
|
||||
value = readValue(extends, reader);
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new FormatException(string.Format("Unexpected property {0}", reader.Value));
|
||||
}
|
||||
|
||||
// Step out of the value
|
||||
reader.Read();
|
||||
}
|
||||
|
||||
return new KeyValuePair<TKey, TValue>(key, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -178,8 +208,15 @@ namespace ICD.Common.Utils.Extensions
|
||||
/// <param name="extends"></param>
|
||||
/// <param name="writer"></param>
|
||||
/// <param name="items"></param>
|
||||
public static void SerializeArray<TItem>(this JsonSerializer extends, JsonWriter writer, IEnumerable<TItem> items)
|
||||
public static void SerializeArray<TItem>([NotNull] this JsonSerializer extends, [NotNull] JsonWriter writer,
|
||||
[CanBeNull] IEnumerable<TItem> items)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
|
||||
if (writer == null)
|
||||
throw new ArgumentNullException("writer");
|
||||
|
||||
extends.SerializeArray(writer, items, (s, w, item) => s.Serialize(w, item));
|
||||
}
|
||||
|
||||
@@ -191,8 +228,9 @@ namespace ICD.Common.Utils.Extensions
|
||||
/// <param name="writer"></param>
|
||||
/// <param name="items"></param>
|
||||
/// <param name="write"></param>
|
||||
public static void SerializeArray<TItem>(this JsonSerializer extends, JsonWriter writer, IEnumerable<TItem> items,
|
||||
Action<JsonSerializer, JsonWriter, TItem> write)
|
||||
public static void SerializeArray<TItem>([NotNull] this JsonSerializer extends, [NotNull] JsonWriter writer,
|
||||
[CanBeNull] IEnumerable<TItem> items,
|
||||
[NotNull] Action<JsonSerializer, JsonWriter, TItem> write)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
@@ -225,10 +263,13 @@ namespace ICD.Common.Utils.Extensions
|
||||
/// <param name="extends"></param>
|
||||
/// <param name="writer"></param>
|
||||
/// <param name="items"></param>
|
||||
public static void SerializeDict<TKey, TValue>(this JsonSerializer extends, JsonWriter writer,
|
||||
IEnumerable<KeyValuePair<TKey, TValue>> items)
|
||||
public static void SerializeDict<TKey, TValue>([NotNull] this JsonSerializer extends,
|
||||
[NotNull] JsonWriter writer,
|
||||
[CanBeNull] IEnumerable<KeyValuePair<TKey, TValue>> items)
|
||||
{
|
||||
extends.SerializeDict(writer, items, k => k.ToString());
|
||||
extends.SerializeDict(writer, items,
|
||||
(s, w, k) => s.Serialize(w, k),
|
||||
(s, w, v) => s.Serialize(w, v));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -239,28 +280,13 @@ namespace ICD.Common.Utils.Extensions
|
||||
/// <param name="extends"></param>
|
||||
/// <param name="writer"></param>
|
||||
/// <param name="items"></param>
|
||||
/// <param name="getPropertyName"></param>
|
||||
public static void SerializeDict<TKey, TValue>(this JsonSerializer extends, JsonWriter writer,
|
||||
IEnumerable<KeyValuePair<TKey, TValue>> items,
|
||||
Func<TKey, string> getPropertyName)
|
||||
{
|
||||
extends.SerializeDict(writer, items, getPropertyName, (s, w, v) => s.Serialize(w, v));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Serializes the given sequence of items to the writer.
|
||||
/// </summary>
|
||||
/// <typeparam name="TKey"></typeparam>
|
||||
/// <typeparam name="TValue"></typeparam>
|
||||
/// <param name="extends"></param>
|
||||
/// <param name="writer"></param>
|
||||
/// <param name="items"></param>
|
||||
/// <param name="getPropertyName"></param>
|
||||
/// <param name="writeKey"></param>
|
||||
/// <param name="writeValue"></param>
|
||||
public static void SerializeDict<TKey, TValue>(this JsonSerializer extends, JsonWriter writer,
|
||||
IEnumerable<KeyValuePair<TKey, TValue>> items,
|
||||
Func<TKey, string> getPropertyName,
|
||||
Action<JsonSerializer, JsonWriter, TValue> writeValue)
|
||||
public static void SerializeDict<TKey, TValue>([NotNull] this JsonSerializer extends,
|
||||
[NotNull] JsonWriter writer,
|
||||
[CanBeNull] IEnumerable<KeyValuePair<TKey, TValue>> items,
|
||||
[NotNull] Action<JsonSerializer, JsonWriter, TKey> writeKey,
|
||||
[NotNull] Action<JsonSerializer, JsonWriter, TValue> writeValue)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
@@ -268,28 +294,42 @@ namespace ICD.Common.Utils.Extensions
|
||||
if (writer == null)
|
||||
throw new ArgumentNullException("writer");
|
||||
|
||||
if (getPropertyName == null)
|
||||
throw new ArgumentNullException("getPropertyName");
|
||||
if (writeKey == null)
|
||||
throw new ArgumentNullException("writeKey");
|
||||
|
||||
if (writeValue == null)
|
||||
throw new ArgumentNullException("writeValue");
|
||||
|
||||
if (items == null)
|
||||
{
|
||||
writer.WriteNull();
|
||||
return;
|
||||
}
|
||||
extends.SerializeArray(writer, items, (s, w, kvp) => s.SerializeKeyValuePair(w, kvp, writeKey, writeValue));
|
||||
}
|
||||
|
||||
public static void SerializeKeyValuePair<TKey, TValue>(
|
||||
[NotNull] this JsonSerializer extends,
|
||||
[NotNull] JsonWriter writer, KeyValuePair<TKey, TValue> kvp,
|
||||
[NotNull] Action<JsonSerializer, JsonWriter, TKey> writeKey,
|
||||
[NotNull] Action<JsonSerializer, JsonWriter, TValue> writeValue)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
|
||||
if (writer == null)
|
||||
throw new ArgumentNullException("writer");
|
||||
|
||||
if (writeKey == null)
|
||||
throw new ArgumentNullException("writeKey");
|
||||
|
||||
if (writeValue == null)
|
||||
throw new ArgumentNullException("writeValue");
|
||||
|
||||
writer.WriteStartObject();
|
||||
{
|
||||
foreach (KeyValuePair<TKey, TValue> kvp in items)
|
||||
{
|
||||
string propertyName = getPropertyName(kvp.Key);
|
||||
writer.WritePropertyName(propertyName);
|
||||
writeValue(extends, writer, kvp.Value);
|
||||
}
|
||||
writer.WritePropertyName(PROPERTY_KEY);
|
||||
writeKey(extends, writer, kvp.Key);
|
||||
|
||||
writer.WritePropertyName(PROPERTY_VALUE);
|
||||
writeValue(extends, writer, kvp.Value);
|
||||
}
|
||||
writer.WriteEndObject();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
45
ICD.Common.Utils/Extensions/JsonTokenExtensions.cs
Normal file
45
ICD.Common.Utils/Extensions/JsonTokenExtensions.cs
Normal file
@@ -0,0 +1,45 @@
|
||||
using System;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace ICD.Common.Utils.Extensions
|
||||
{
|
||||
public static class JsonTokenExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Returns true if the JsonToken respresents a single data value
|
||||
/// rather than a complex type such as an object or an array.
|
||||
/// </summary>
|
||||
/// <param name="extends"></param>
|
||||
/// <returns></returns>
|
||||
public static bool IsPrimitive(this JsonToken extends)
|
||||
{
|
||||
switch (extends)
|
||||
{
|
||||
case JsonToken.None:
|
||||
case JsonToken.StartObject:
|
||||
case JsonToken.StartArray:
|
||||
case JsonToken.StartConstructor:
|
||||
case JsonToken.EndObject:
|
||||
case JsonToken.EndArray:
|
||||
case JsonToken.EndConstructor:
|
||||
case JsonToken.Undefined:
|
||||
return false;
|
||||
|
||||
case JsonToken.PropertyName:
|
||||
case JsonToken.Comment:
|
||||
case JsonToken.Raw:
|
||||
case JsonToken.Integer:
|
||||
case JsonToken.Float:
|
||||
case JsonToken.String:
|
||||
case JsonToken.Boolean:
|
||||
case JsonToken.Null:
|
||||
case JsonToken.Date:
|
||||
case JsonToken.Bytes:
|
||||
return true;
|
||||
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException("extends");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6,13 +6,31 @@ namespace ICD.Common.Utils.Extensions
|
||||
{
|
||||
public static class JsonWriterExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Writes the DateTime as an ISO-8601 string.
|
||||
/// </summary>
|
||||
/// <param name="extends"></param>
|
||||
/// <param name="dateTime"></param>
|
||||
public static void WriteDateTime([NotNull] this JsonWriter extends, DateTime dateTime)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
|
||||
string iso = dateTime.ToIso();
|
||||
|
||||
// Remove redundant ms
|
||||
iso = iso.Replace(".0000000", "");
|
||||
|
||||
extends.WriteValue(iso);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes the type value.
|
||||
/// </summary>
|
||||
/// <param name="extends"></param>
|
||||
/// <param name="type"></param>
|
||||
[PublicAPI]
|
||||
public static void WriteType(this JsonWriter extends, Type type)
|
||||
public static void WriteType([NotNull] this JsonWriter extends, [CanBeNull] Type type)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
@@ -33,7 +51,7 @@ namespace ICD.Common.Utils.Extensions
|
||||
/// <param name="extends"></param>
|
||||
/// <param name="propertyName"></param>
|
||||
/// <param name="value"></param>
|
||||
public static void WriteProperty(this JsonWriter extends, string propertyName, object value)
|
||||
public static void WriteProperty([NotNull]this JsonWriter extends, string propertyName, object value)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
@@ -48,7 +66,7 @@ namespace ICD.Common.Utils.Extensions
|
||||
/// <param name="extends"></param>
|
||||
/// <param name="propertyName"></param>
|
||||
/// <param name="value"></param>
|
||||
public static void WriteProperty(this JsonWriter extends, string propertyName, string value)
|
||||
public static void WriteProperty([NotNull]this JsonWriter extends, string propertyName, string value)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
@@ -63,7 +81,22 @@ namespace ICD.Common.Utils.Extensions
|
||||
/// <param name="extends"></param>
|
||||
/// <param name="propertyName"></param>
|
||||
/// <param name="value"></param>
|
||||
public static void WriteProperty(this JsonWriter extends, string propertyName, DateTime value)
|
||||
public static void WriteProperty([NotNull]this JsonWriter extends, string propertyName, DateTime value)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
|
||||
extends.WritePropertyName(propertyName);
|
||||
extends.WriteDateTime(value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes the property name and value to the writer.
|
||||
/// </summary>
|
||||
/// <param name="extends"></param>
|
||||
/// <param name="propertyName"></param>
|
||||
/// <param name="value"></param>
|
||||
public static void WriteProperty([NotNull]this JsonWriter extends, string propertyName, bool value)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
@@ -78,7 +111,7 @@ namespace ICD.Common.Utils.Extensions
|
||||
/// <param name="extends"></param>
|
||||
/// <param name="propertyName"></param>
|
||||
/// <param name="value"></param>
|
||||
public static void WriteProperty(this JsonWriter extends, string propertyName, bool value)
|
||||
public static void WriteProperty([NotNull]this JsonWriter extends, string propertyName, int value)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
@@ -93,7 +126,7 @@ namespace ICD.Common.Utils.Extensions
|
||||
/// <param name="extends"></param>
|
||||
/// <param name="propertyName"></param>
|
||||
/// <param name="value"></param>
|
||||
public static void WriteProperty(this JsonWriter extends, string propertyName, int value)
|
||||
public static void WriteProperty([NotNull]this JsonWriter extends, string propertyName, Guid value)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
@@ -108,22 +141,7 @@ namespace ICD.Common.Utils.Extensions
|
||||
/// <param name="extends"></param>
|
||||
/// <param name="propertyName"></param>
|
||||
/// <param name="value"></param>
|
||||
public static void WriteProperty(this JsonWriter extends, string propertyName, Guid value)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
|
||||
extends.WritePropertyName(propertyName);
|
||||
extends.WriteValue(value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes the property name and value to the writer.
|
||||
/// </summary>
|
||||
/// <param name="extends"></param>
|
||||
/// <param name="propertyName"></param>
|
||||
/// <param name="value"></param>
|
||||
public static void WriteProperty(this JsonWriter extends, string propertyName, Type value)
|
||||
public static void WriteProperty([NotNull]this JsonWriter extends, string propertyName, Type value)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using ICD.Common.Properties;
|
||||
using ICD.Common.Utils.Comparers;
|
||||
|
||||
@@ -11,14 +10,159 @@ namespace ICD.Common.Utils.Extensions
|
||||
/// </summary>
|
||||
public static class ListExtensions
|
||||
{
|
||||
#region Add Sorted
|
||||
|
||||
/// <summary>
|
||||
/// Adds the items into a sorted list.
|
||||
/// Attempts to add the item to the sorted list.
|
||||
/// Returns false if the item already exists in the list.
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="extends"></param>
|
||||
/// <param name="item"></param>
|
||||
/// <returns></returns>
|
||||
[PublicAPI]
|
||||
public static bool AddSorted<T>([NotNull] this IList<T> extends, T item)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
|
||||
return extends.AddSorted(item, Comparer<T>.Default);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Attempts to add the item to the sorted list.
|
||||
/// Returns false if the item already exists in the list.
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <typeparam name="TProp"></typeparam>
|
||||
/// <param name="extends"></param>
|
||||
/// <param name="item"></param>
|
||||
/// <param name="predicate"></param>
|
||||
[PublicAPI]
|
||||
public static bool AddSorted<T, TProp>([NotNull] this IList<T> extends, T item,
|
||||
[NotNull] Func<T, TProp> predicate)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
|
||||
if (predicate == null)
|
||||
throw new ArgumentNullException("predicate");
|
||||
|
||||
PredicateComparer<T, TProp> comparer = new PredicateComparer<T, TProp>(predicate);
|
||||
return extends.AddSorted(item, comparer);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Attempts to add the item to the sorted list.
|
||||
/// Returns false if the item already exists in the list.
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="extends"></param>
|
||||
/// <param name="item"></param>
|
||||
/// <param name="comparer"></param>
|
||||
/// <returns></returns>
|
||||
[PublicAPI]
|
||||
public static bool AddSorted<T>([NotNull] this IList<T> extends, T item, [NotNull] IComparer<T> comparer)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
|
||||
if (comparer == null)
|
||||
throw new ArgumentNullException("comparer");
|
||||
|
||||
int index = extends.BinarySearch(item, comparer);
|
||||
if (index >= 0)
|
||||
return false;
|
||||
|
||||
index = ~index;
|
||||
extends.Insert(index, item);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Remove Sorted
|
||||
|
||||
/// <summary>
|
||||
/// Attempts to remove the item from the sorted list.
|
||||
/// Returns false if the item does not exist in the list.
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="extends"></param>
|
||||
/// <param name="item"></param>
|
||||
/// <returns></returns>
|
||||
[PublicAPI]
|
||||
public static bool RemoveSorted<T>([NotNull] this IList<T> extends, T item)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
|
||||
return extends.RemoveSorted(item, Comparer<T>.Default);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Attempts to remove the item from the sorted list.
|
||||
/// Returns false if the item does not exist in the list.
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <typeparam name="TProp"></typeparam>
|
||||
/// <param name="extends"></param>
|
||||
/// <param name="item"></param>
|
||||
/// <param name="predicate"></param>
|
||||
[PublicAPI]
|
||||
public static bool RemoveSorted<T, TProp>([NotNull] this IList<T> extends, T item,
|
||||
[NotNull] Func<T, TProp> predicate)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
|
||||
if (predicate == null)
|
||||
throw new ArgumentNullException("predicate");
|
||||
|
||||
PredicateComparer<T, TProp> comparer = new PredicateComparer<T, TProp>(predicate);
|
||||
return extends.RemoveSorted(item, comparer);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Attempts to remove the item from the sorted list.
|
||||
/// Returns false if the item does not exist in the list.
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="extends"></param>
|
||||
/// <param name="item"></param>
|
||||
/// <param name="comparer"></param>
|
||||
/// <returns></returns>
|
||||
[PublicAPI]
|
||||
public static bool RemoveSorted<T>([NotNull] this IList<T> extends, T item, [NotNull] IComparer<T> comparer)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
|
||||
if (comparer == null)
|
||||
throw new ArgumentNullException("comparer");
|
||||
|
||||
int index = extends.BinarySearch(item, comparer);
|
||||
if (index < 0)
|
||||
return false;
|
||||
|
||||
extends.RemoveAt(index);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Insert Sorted
|
||||
|
||||
/// <summary>
|
||||
/// Inserts the items into a sorted list.
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="extends"></param>
|
||||
/// <param name="items"></param>
|
||||
[PublicAPI]
|
||||
public static void AddSorted<T>(this List<T> extends, IEnumerable<T> items)
|
||||
public static void InsertSorted<T>([NotNull] this IList<T> extends, [NotNull] IEnumerable<T> items)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
@@ -26,18 +170,19 @@ namespace ICD.Common.Utils.Extensions
|
||||
if (items == null)
|
||||
throw new ArgumentNullException("items");
|
||||
|
||||
extends.AddSorted(items, Comparer<T>.Default);
|
||||
extends.InsertSorted(items, Comparer<T>.Default);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds the items into a sorted list.
|
||||
/// Inserts the items into a sorted list.
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="extends"></param>
|
||||
/// <param name="items"></param>
|
||||
/// <param name="comparer"></param>
|
||||
[PublicAPI]
|
||||
public static void AddSorted<T>(this List<T> extends, IEnumerable<T> items, IComparer<T> comparer)
|
||||
public static void InsertSorted<T>([NotNull] this IList<T> extends, [NotNull] IEnumerable<T> items,
|
||||
[NotNull] IComparer<T> comparer)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
@@ -48,11 +193,11 @@ namespace ICD.Common.Utils.Extensions
|
||||
if (comparer == null)
|
||||
throw new ArgumentNullException("comparer");
|
||||
|
||||
items.ForEach(i => extends.AddSorted(i, comparer));
|
||||
items.ForEach(i => extends.InsertSorted(i, comparer));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds the items into a sorted list.
|
||||
/// Inserts the items into a sorted list.
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <typeparam name="TProp"></typeparam>
|
||||
@@ -60,7 +205,8 @@ namespace ICD.Common.Utils.Extensions
|
||||
/// <param name="items"></param>
|
||||
/// <param name="predicate"></param>
|
||||
[PublicAPI]
|
||||
public static void AddSorted<T, TProp>(this List<T> extends, IEnumerable<T> items, Func<T, TProp> predicate)
|
||||
public static void InsertSorted<T, TProp>([NotNull] this IList<T> extends, [NotNull] IEnumerable<T> items,
|
||||
[NotNull] Func<T, TProp> predicate)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
@@ -72,33 +218,55 @@ namespace ICD.Common.Utils.Extensions
|
||||
throw new ArgumentNullException("predicate");
|
||||
|
||||
PredicateComparer<T, TProp> comparer = new PredicateComparer<T, TProp>(predicate);
|
||||
extends.AddSorted(items, comparer);
|
||||
extends.InsertSorted(items, comparer);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds the item into a sorted list.
|
||||
/// Inserts the item into a sorted list.
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="extends"></param>
|
||||
/// <param name="item"></param>
|
||||
[PublicAPI]
|
||||
public static int AddSorted<T>(this List<T> extends, T item)
|
||||
public static int InsertSorted<T>([NotNull] this IList<T> extends, T item)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
|
||||
return extends.AddSorted(item, Comparer<T>.Default);
|
||||
return extends.InsertSorted(item, Comparer<T>.Default);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds the item into a sorted list.
|
||||
/// Inserts the item into a sorted list.
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <typeparam name="TProp"></typeparam>
|
||||
/// <param name="extends"></param>
|
||||
/// <param name="item"></param>
|
||||
/// <param name="predicate"></param>
|
||||
[PublicAPI]
|
||||
public static int InsertSorted<T, TProp>([NotNull] this IList<T> extends, T item,
|
||||
[NotNull] Func<T, TProp> predicate)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
|
||||
if (predicate == null)
|
||||
throw new ArgumentNullException("predicate");
|
||||
|
||||
PredicateComparer<T, TProp> comparer = new PredicateComparer<T, TProp>(predicate);
|
||||
return extends.InsertSorted(item, comparer);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Inserts the item into a sorted list.
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="extends"></param>
|
||||
/// <param name="item"></param>
|
||||
/// <param name="comparer"></param>
|
||||
[PublicAPI]
|
||||
public static int AddSorted<T>(this List<T> extends, T item, IComparer<T> comparer)
|
||||
public static int InsertSorted<T>([NotNull] this IList<T> extends, T item, [NotNull] IComparer<T> comparer)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
@@ -115,8 +283,48 @@ namespace ICD.Common.Utils.Extensions
|
||||
return index;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Contains Sorted
|
||||
|
||||
/// <summary>
|
||||
/// Adds the item into a sorted list.
|
||||
/// Returns true if the sorted list contains the given item.
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="extends"></param>
|
||||
/// <param name="item"></param>
|
||||
/// <returns></returns>
|
||||
[PublicAPI]
|
||||
public static bool ContainsSorted<T>([NotNull] this IList<T> extends, T item)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
|
||||
return extends.ContainsSorted(item, Comparer<T>.Default);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if the sorted list contains the given item.
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="extends"></param>
|
||||
/// <param name="item"></param>
|
||||
/// <param name="comparer"></param>
|
||||
/// <returns></returns>
|
||||
[PublicAPI]
|
||||
public static bool ContainsSorted<T>([NotNull] this IList<T> extends, T item, [NotNull] IComparer<T> comparer)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
|
||||
if (comparer == null)
|
||||
throw new ArgumentNullException("comparer");
|
||||
|
||||
return extends.BinarySearch(item, comparer) >= 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if the sorted list contains the given item.
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <typeparam name="TProp"></typeparam>
|
||||
@@ -124,7 +332,8 @@ namespace ICD.Common.Utils.Extensions
|
||||
/// <param name="item"></param>
|
||||
/// <param name="predicate"></param>
|
||||
[PublicAPI]
|
||||
public static int AddSorted<T, TProp>(this List<T> extends, T item, Func<T, TProp> predicate)
|
||||
public static bool ContainsSorted<T, TProp>([NotNull] this IList<T> extends, T item,
|
||||
[NotNull] Func<T, TProp> predicate)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
@@ -133,48 +342,61 @@ namespace ICD.Common.Utils.Extensions
|
||||
throw new ArgumentNullException("predicate");
|
||||
|
||||
PredicateComparer<T, TProp> comparer = new PredicateComparer<T, TProp>(predicate);
|
||||
return extends.AddSorted(item, comparer);
|
||||
return extends.ContainsSorted(item, comparer);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Binary Search
|
||||
|
||||
/// <summary>
|
||||
/// Pads the list to the given total length.
|
||||
/// Returns the index of the item in the list.
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="extends"></param>
|
||||
/// <param name="totalLength"></param>
|
||||
[PublicAPI]
|
||||
public static void PadRight<T>(this List<T> extends, int totalLength)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
|
||||
if (totalLength < 0)
|
||||
throw new ArgumentOutOfRangeException("totalLength", "totalLength must be greater or equal to 0");
|
||||
|
||||
extends.PadRight(totalLength, default(T));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Pads the list to the given total length with the given item.
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="extends"></param>
|
||||
/// <param name="totalLength"></param>
|
||||
/// <param name="item"></param>
|
||||
/// <param name="comparer"></param>
|
||||
/// <returns></returns>
|
||||
[PublicAPI]
|
||||
public static void PadRight<T>(this List<T> extends, int totalLength, T item)
|
||||
public static int BinarySearch<T>([NotNull] this IList<T> extends, T item, [NotNull] IComparer<T> comparer)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
|
||||
if (totalLength < 0)
|
||||
throw new ArgumentOutOfRangeException("totalLength", "totalLength must be greater or equal to 0");
|
||||
if (comparer == null)
|
||||
throw new ArgumentNullException("comparer");
|
||||
|
||||
int pad = totalLength - extends.Count;
|
||||
if (pad <= 0)
|
||||
return;
|
||||
// Array
|
||||
T[] array = extends as T[];
|
||||
if (array != null)
|
||||
return Array.BinarySearch(array, 0, array.Length, item, comparer);
|
||||
|
||||
extends.AddRange(Enumerable.Repeat(item, pad));
|
||||
// List
|
||||
List<T> list = extends as List<T>;
|
||||
if (list != null)
|
||||
return list.BinarySearch(item, comparer);
|
||||
|
||||
// IList
|
||||
int lo = 0;
|
||||
int hi = extends.Count - 1;
|
||||
|
||||
while (lo <= hi)
|
||||
{
|
||||
int i = lo + ((hi - lo) >> 1);
|
||||
int order = comparer.Compare(extends[i], item);
|
||||
|
||||
if (order == 0)
|
||||
return i;
|
||||
|
||||
if (order < 0)
|
||||
lo = i + 1;
|
||||
else
|
||||
hi = i - 1;
|
||||
}
|
||||
|
||||
return ~lo;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Text;
|
||||
using ICD.Common.Properties;
|
||||
#if SIMPLSHARP
|
||||
using Crestron.SimplSharp.Reflection;
|
||||
#else
|
||||
@@ -15,8 +16,11 @@ namespace ICD.Common.Utils.Extensions
|
||||
/// </summary>
|
||||
/// <param name="method">The Method</param>
|
||||
/// <returns>Method signature</returns>
|
||||
public static string GetSignature(this MethodInfo method)
|
||||
public static string GetSignature([NotNull]this MethodInfo method)
|
||||
{
|
||||
if (method == null)
|
||||
throw new ArgumentNullException("method");
|
||||
|
||||
return method.GetSignature(false);
|
||||
}
|
||||
|
||||
@@ -26,8 +30,11 @@ namespace ICD.Common.Utils.Extensions
|
||||
/// <param name="method">The Method</param>
|
||||
/// <param name="callable">Return as a callable string(public void a(string b) would return a(b))</param>
|
||||
/// <returns>Method signature</returns>
|
||||
public static string GetSignature(this MethodInfo method, bool callable)
|
||||
public static string GetSignature([NotNull]this MethodInfo method, bool callable)
|
||||
{
|
||||
if (method == null)
|
||||
throw new ArgumentNullException("method");
|
||||
|
||||
bool firstParam = true;
|
||||
StringBuilder sigBuilder = new StringBuilder();
|
||||
|
||||
@@ -123,5 +130,22 @@ namespace ICD.Common.Utils.Extensions
|
||||
|
||||
return sigBuilder.ToString();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Cross-platform shim for getting MethodInfo for the delegate.
|
||||
/// </summary>
|
||||
/// <param name="extends"></param>
|
||||
/// <returns></returns>
|
||||
public static MethodInfo GetMethodInfo([NotNull]this Delegate extends)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
|
||||
#if SIMPLSHARP
|
||||
return extends.GetMethod();
|
||||
#else
|
||||
return extends.Method;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using ICD.Common.Properties;
|
||||
#if SIMPLSHARP
|
||||
using Crestron.SimplSharp.Reflection;
|
||||
#else
|
||||
@@ -14,7 +15,7 @@ namespace ICD.Common.Utils.Extensions
|
||||
/// </summary>
|
||||
/// <param name="extends"></param>
|
||||
/// <returns></returns>
|
||||
public static bool GetIsOut(this ParameterInfo extends)
|
||||
public static bool GetIsOut([NotNull] this ParameterInfo extends)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using ICD.Common.Properties;
|
||||
|
||||
namespace ICD.Common.Utils.Extensions
|
||||
{
|
||||
@@ -11,7 +12,7 @@ namespace ICD.Common.Utils.Extensions
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="extends"></param>
|
||||
/// <param name="items"></param>
|
||||
public static void EnqueueRange<T>(this Queue<T> extends, IEnumerable<T> items)
|
||||
public static void EnqueueRange<T>([NotNull] this Queue<T> extends, [NotNull] IEnumerable<T> items)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
@@ -30,7 +31,7 @@ namespace ICD.Common.Utils.Extensions
|
||||
/// <param name="extends"></param>
|
||||
/// <param name="item"></param>
|
||||
/// <returns></returns>
|
||||
public static bool Dequeue<T>(this Queue<T> extends, out T item)
|
||||
public static bool Dequeue<T>([NotNull] this Queue<T> extends, out T item)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
@@ -51,7 +52,7 @@ namespace ICD.Common.Utils.Extensions
|
||||
/// <param name="extends"></param>
|
||||
/// <param name="item"></param>
|
||||
/// <returns></returns>
|
||||
public static bool Peek<T>(this Queue<T> extends, out T item)
|
||||
public static bool Peek<T>([NotNull] this Queue<T> extends, out T item)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using ICD.Common.Properties;
|
||||
#if SIMPLSHARP
|
||||
using Crestron.SimplSharp.Reflection;
|
||||
#else
|
||||
@@ -20,7 +21,7 @@ namespace ICD.Common.Utils.Extensions
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="extends"></param>
|
||||
/// <returns></returns>
|
||||
public static IEnumerable<T> GetCustomAttributes<T>(this ICustomAttributeProvider extends)
|
||||
public static IEnumerable<T> GetCustomAttributes<T>([NotNull] this ICustomAttributeProvider extends)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
@@ -35,7 +36,8 @@ namespace ICD.Common.Utils.Extensions
|
||||
/// <param name="extends"></param>
|
||||
/// <param name="inherits"></param>
|
||||
/// <returns></returns>
|
||||
public static IEnumerable<T> GetCustomAttributes<T>(this ICustomAttributeProvider extends, bool inherits)
|
||||
public static IEnumerable<T> GetCustomAttributes<T>([NotNull] this ICustomAttributeProvider extends,
|
||||
bool inherits)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
@@ -57,7 +59,7 @@ namespace ICD.Common.Utils.Extensions
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="extends"></param>
|
||||
/// <returns></returns>
|
||||
public static T GetCustomAttribute<T>(this ICustomAttributeProvider extends)
|
||||
public static T GetCustomAttribute<T>([NotNull] this ICustomAttributeProvider extends)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
@@ -72,7 +74,7 @@ namespace ICD.Common.Utils.Extensions
|
||||
/// <param name="extends"></param>
|
||||
/// <param name="inherits"></param>
|
||||
/// <returns></returns>
|
||||
public static T GetCustomAttribute<T>(this ICustomAttributeProvider extends, bool inherits)
|
||||
public static T GetCustomAttribute<T>([NotNull] this ICustomAttributeProvider extends, bool inherits)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
@@ -86,16 +88,18 @@ namespace ICD.Common.Utils.Extensions
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="extends"></param>
|
||||
/// <param name="inherits"></param>
|
||||
/// <returns></returns>
|
||||
public static IEnumerable<T> GetCustomAttributesIncludingBaseInterfaces<T>(this Type extends)
|
||||
public static IEnumerable<T> GetCustomAttributesIncludingBaseInterfaces<T>([NotNull] this Type extends)
|
||||
where T : Attribute
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
|
||||
return extends.GetCustomAttributes<T>(true)
|
||||
.Union(extends.GetInterfaces()
|
||||
.SelectMany(interfaceType => interfaceType
|
||||
.GetCustomAttributes<T>(true)))
|
||||
.Distinct();
|
||||
.Union(extends.GetInterfaces()
|
||||
.SelectMany(interfaceType => interfaceType
|
||||
.GetCustomAttributes<T>(true)))
|
||||
.Distinct();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -103,24 +107,43 @@ namespace ICD.Common.Utils.Extensions
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="extends"></param>
|
||||
/// <param name="inherits"></param>
|
||||
/// <returns></returns>
|
||||
public static IEnumerable<T> GetCustomAttributesIncludingBaseInterfaces<T>(this MemberInfo extends)
|
||||
public static IEnumerable<T> GetCustomAttributesIncludingBaseInterfaces<T>([NotNull] this MemberInfo extends)
|
||||
where T : Attribute
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
|
||||
return extends.GetCustomAttributes<T>(true)
|
||||
.Union(extends.DeclaringType?
|
||||
.GetInterfaces()
|
||||
.SelectMany(interfaceType => interfaceType
|
||||
.GetMember(
|
||||
extends.Name,
|
||||
extends.MemberType,
|
||||
BindingFlags.Instance)
|
||||
.FirstOrDefault()?
|
||||
.GetCustomAttributes<T>(true) ?? Enumerable.Empty<T>())?
|
||||
.Except(null) ?? Enumerable.Empty<T>())
|
||||
.Distinct();
|
||||
.Union(extends.DeclaringType?
|
||||
.GetInterfaces()
|
||||
.SelectMany(interfaceType => interfaceType
|
||||
.GetMember(extends.Name,
|
||||
extends.MemberType,
|
||||
BindingFlags.Instance)
|
||||
.FirstOrDefault()?
|
||||
.GetCustomAttributes<T>(true) ??
|
||||
Enumerable.Empty<T>())?
|
||||
.Except(null) ?? Enumerable.Empty<T>())
|
||||
.Distinct();
|
||||
}
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Gets the EventArgs Type for the given event.
|
||||
/// </summary>
|
||||
/// <param name="extends"></param>
|
||||
/// <returns></returns>
|
||||
public static Type GetEventArgsType([NotNull] this EventInfo extends)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
|
||||
Type eventHandlerType = extends.EventHandlerType;
|
||||
return eventHandlerType == typeof(EventHandler)
|
||||
? typeof(EventArgs)
|
||||
: eventHandlerType.GetInnerGenericTypes(typeof(EventHandler<>))
|
||||
.First();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Text;
|
||||
using ICD.Common.Properties;
|
||||
|
||||
namespace ICD.Common.Utils.Extensions
|
||||
{
|
||||
@@ -9,7 +10,7 @@ namespace ICD.Common.Utils.Extensions
|
||||
/// Empties the StringBuilder.
|
||||
/// </summary>
|
||||
/// <param name="extends"></param>
|
||||
public static void Clear(this StringBuilder extends)
|
||||
public static void Clear([NotNull] this StringBuilder extends)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
@@ -23,7 +24,7 @@ namespace ICD.Common.Utils.Extensions
|
||||
/// </summary>
|
||||
/// <param name="extends"></param>
|
||||
/// <returns></returns>
|
||||
public static string Pop(this StringBuilder extends)
|
||||
public static string Pop([NotNull] this StringBuilder extends)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
using ICD.Common.Properties;
|
||||
|
||||
namespace ICD.Common.Utils.Extensions
|
||||
@@ -15,7 +16,7 @@ namespace ICD.Common.Utils.Extensions
|
||||
/// <param name="first"></param>
|
||||
/// <returns></returns>
|
||||
[PublicAPI]
|
||||
public static int IndexOf(this string extends, IEnumerable<string> items, out string first)
|
||||
public static int IndexOf([NotNull] this string extends, [NotNull] IEnumerable<string> items, out string first)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
@@ -52,7 +53,7 @@ namespace ICD.Common.Utils.Extensions
|
||||
/// <param name="character"></param>
|
||||
/// <returns></returns>
|
||||
[PublicAPI]
|
||||
public static bool StartsWith(this string extends, char character)
|
||||
public static bool StartsWith([NotNull] this string extends, char character)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
@@ -67,7 +68,7 @@ namespace ICD.Common.Utils.Extensions
|
||||
/// <param name="character"></param>
|
||||
/// <returns></returns>
|
||||
[PublicAPI]
|
||||
public static bool EndsWith(this string extends, char character)
|
||||
public static bool EndsWith([NotNull] this string extends, char character)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
@@ -83,7 +84,8 @@ namespace ICD.Common.Utils.Extensions
|
||||
/// <param name="delimeter"></param>
|
||||
/// <param name="count"></param>
|
||||
/// <returns></returns>
|
||||
public static IEnumerable<string> Split(this string extends, char delimeter, int count)
|
||||
[NotNull]
|
||||
public static IEnumerable<string> Split([NotNull] this string extends, char delimeter, int count)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
@@ -102,7 +104,8 @@ namespace ICD.Common.Utils.Extensions
|
||||
/// <param name="delimeter"></param>
|
||||
/// <param name="count"></param>
|
||||
/// <returns></returns>
|
||||
private static IEnumerable<string> SplitIterator(string value, char delimeter, int count)
|
||||
[NotNull]
|
||||
private static IEnumerable<string> SplitIterator([NotNull] string value, char delimeter, int count)
|
||||
{
|
||||
while (count > 1)
|
||||
{
|
||||
@@ -125,7 +128,8 @@ namespace ICD.Common.Utils.Extensions
|
||||
/// <param name="chunkSize"></param>
|
||||
/// <returns></returns>
|
||||
[PublicAPI]
|
||||
public static IEnumerable<string> Split(this string extends, int chunkSize)
|
||||
[NotNull]
|
||||
public static IEnumerable<string> Split([NotNull] this string extends, int chunkSize)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
@@ -134,7 +138,8 @@ namespace ICD.Common.Utils.Extensions
|
||||
throw new InvalidOperationException("chunkSize must be greater than 0");
|
||||
|
||||
return Enumerable.Range(0, (int)Math.Ceiling(extends.Length / (double)chunkSize))
|
||||
.Select(i => extends.Substring(i * chunkSize, Math.Min(chunkSize, extends.Length - (i * chunkSize))));
|
||||
.Select(i => extends.Substring(i * chunkSize,
|
||||
Math.Min(chunkSize, extends.Length - (i * chunkSize))));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -143,7 +148,8 @@ namespace ICD.Common.Utils.Extensions
|
||||
/// <param name="extends"></param>
|
||||
/// <returns></returns>
|
||||
[PublicAPI]
|
||||
public static string RemoveWhitespace(this string extends)
|
||||
[NotNull]
|
||||
public static string RemoveWhitespace([NotNull] this string extends)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
@@ -152,12 +158,13 @@ namespace ICD.Common.Utils.Extensions
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes all occurances of the given string.
|
||||
/// Removes all occurrences of the given string.
|
||||
/// </summary>
|
||||
/// <param name="extends"></param>
|
||||
/// <param name="other"></param>
|
||||
/// <returns></returns>
|
||||
public static string Remove(this string extends, string other)
|
||||
[NotNull]
|
||||
public static string Remove([NotNull] this string extends, [NotNull] string other)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
@@ -176,19 +183,21 @@ namespace ICD.Common.Utils.Extensions
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes all occurances the given characters from the string.
|
||||
/// Removes all occurrences the given characters from the string.
|
||||
/// </summary>
|
||||
/// <param name="extends"></param>
|
||||
/// <param name="characters"></param>
|
||||
/// <returns></returns>
|
||||
[PublicAPI]
|
||||
public static string Remove(this string extends, IEnumerable<char> characters)
|
||||
[NotNull]
|
||||
public static string Remove([NotNull] this string extends, IEnumerable<char> characters)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
|
||||
if (characters == null)
|
||||
throw new ArgumentNullException("characters");
|
||||
|
||||
var cSet = characters.ToIcdHashSet();
|
||||
|
||||
return new string(extends.Where(c => !cSet.Contains(c)).ToArray());
|
||||
@@ -200,7 +209,7 @@ namespace ICD.Common.Utils.Extensions
|
||||
/// <param name="extends"></param>
|
||||
/// <returns></returns>
|
||||
[PublicAPI]
|
||||
public static bool IsNumeric(this string extends)
|
||||
public static bool IsNumeric([NotNull] this string extends)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
@@ -214,12 +223,89 @@ namespace ICD.Common.Utils.Extensions
|
||||
/// <param name="extends"></param>
|
||||
/// <param name="character"></param>
|
||||
/// <returns></returns>
|
||||
public static bool Contains(this string extends, char character)
|
||||
public static bool Contains([NotNull] this string extends, char character)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
|
||||
return extends.Contains(character.ToString());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Generates a hashcode that is consistent between program executions.
|
||||
/// </summary>
|
||||
/// <param name="extends"></param>
|
||||
/// <returns></returns>
|
||||
public static int GetStableHashCode([NotNull] this string extends)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
|
||||
unchecked
|
||||
{
|
||||
int hash1 = 5381;
|
||||
int hash2 = hash1;
|
||||
|
||||
for (int i = 0; i < extends.Length && extends[i] != '\0'; i += 2)
|
||||
{
|
||||
hash1 = ((hash1 << 5) + hash1) ^ extends[i];
|
||||
if (i == extends.Length - 1 || extends[i + 1] == '\0')
|
||||
break;
|
||||
hash2 = ((hash2 << 5) + hash2) ^ extends[i + 1];
|
||||
}
|
||||
|
||||
return hash1 + (hash2 * 1566083941);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Strips all of the non-printable characters and control codes from the string.
|
||||
/// </summary>
|
||||
/// <param name="extends"></param>
|
||||
/// <returns></returns>
|
||||
public static string ToPrintableCharacters([NotNull] this string extends)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
|
||||
// Strip ANSI escape sequences
|
||||
extends = Regex.Replace(extends, AnsiUtils.ANSI_REGEX, string.Empty);
|
||||
|
||||
// Strip control characters
|
||||
extends = Regex.Replace(extends, @"\p{C}+", string.Empty);
|
||||
|
||||
return extends;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the printable length of the string.
|
||||
/// </summary>
|
||||
/// <param name="extends"></param>
|
||||
/// <returns></returns>
|
||||
public static int GetPrintableLength([NotNull] this string extends)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
|
||||
return extends.ToPrintableCharacters().Length;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Pads the string to the number of printable characters.
|
||||
/// </summary>
|
||||
/// <param name="extends"></param>
|
||||
/// <param name="length"></param>
|
||||
/// <returns></returns>
|
||||
public static string PadRightPrintable([NotNull] this string extends, int length)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
|
||||
int printableLength = extends.GetPrintableLength();
|
||||
int actualLength = extends.Length;
|
||||
int delta = actualLength - printableLength;
|
||||
|
||||
return extends.PadRight(length + delta);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,25 +5,83 @@ namespace ICD.Common.Utils.Extensions
|
||||
{
|
||||
public static class TimeSpanExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Writes the TimeSpan to a string in the format "A day/s, B hour/s, C minute/s, D second/s, E ms"
|
||||
/// Omits any items that are 0.
|
||||
/// </summary>
|
||||
/// <param name="extends"></param>
|
||||
/// <returns></returns>
|
||||
public static string ToReadableString(this TimeSpan extends)
|
||||
{
|
||||
StringBuilder builder = new StringBuilder();
|
||||
|
||||
if (extends.Days > 0)
|
||||
if (extends.Days == 1)
|
||||
builder.AppendFormat("{0} day, ", extends.Days);
|
||||
else if (extends.Days > 1)
|
||||
builder.AppendFormat("{0} days, ", extends.Days);
|
||||
if (extends.Hours > 0)
|
||||
builder.AppendFormat("{0} hours, ", extends.Hours);
|
||||
if (extends.Minutes > 0)
|
||||
builder.AppendFormat("{0} minutes, ", extends.Minutes);
|
||||
if (extends.Seconds > 0)
|
||||
builder.AppendFormat("{0} seconds, ", extends.Seconds);
|
||||
if (extends.Milliseconds > 0)
|
||||
{
|
||||
builder.AppendFormat("{0}.{1} ms", extends.Milliseconds,
|
||||
((double)extends.Ticks / TimeSpan.TicksPerMillisecond) - extends.TotalMilliseconds);
|
||||
}
|
||||
|
||||
return builder.ToString();
|
||||
if (extends.Hours == 1)
|
||||
builder.AppendFormat("{0} hour, ", extends.Hours);
|
||||
else if (extends.Hours > 1)
|
||||
builder.AppendFormat("{0} hours, ", extends.Hours);
|
||||
|
||||
if (extends.Minutes == 1)
|
||||
builder.AppendFormat("{0} minute, ", extends.Minutes);
|
||||
else if (extends.Minutes > 1)
|
||||
builder.AppendFormat("{0} minutes, ", extends.Minutes);
|
||||
|
||||
if (extends.Seconds == 1)
|
||||
builder.AppendFormat("{0} second, ", extends.Seconds);
|
||||
else if (extends.Seconds > 1)
|
||||
builder.AppendFormat("{0} seconds, ", extends.Seconds);
|
||||
|
||||
if (extends.Milliseconds > 0)
|
||||
builder.AppendFormat("{0} ms", extends.Milliseconds);
|
||||
|
||||
return builder.ToString().TrimEnd(',', ' ');
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds the given number of hours to the time, wrapping every 24 hours without modifying the day.
|
||||
/// </summary>
|
||||
/// <param name="extends"></param>
|
||||
/// <param name="hours"></param>
|
||||
/// <returns></returns>
|
||||
public static TimeSpan AddHoursAndWrap(this TimeSpan extends, int hours)
|
||||
{
|
||||
hours = MathUtils.Modulus(hours + extends.Hours, 24);
|
||||
return new TimeSpan(extends.Days, hours, extends.Minutes, extends.Seconds, extends.Milliseconds);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds the given number of hours to the time, wrapping within the current 12 hour span, without modifying the day.
|
||||
/// </summary>
|
||||
/// <param name="extends"></param>
|
||||
/// <param name="hours"></param>
|
||||
/// <returns></returns>
|
||||
public static TimeSpan AddHoursAndWrap12Hour(this TimeSpan extends, int hours)
|
||||
{
|
||||
int currentHour = extends.Hours;
|
||||
bool am = extends.Hours < 12;
|
||||
|
||||
int current12Hour = MathUtils.Modulus(currentHour, 12);
|
||||
int new12Hour = MathUtils.Modulus(current12Hour + hours, 12);
|
||||
|
||||
return am
|
||||
? new TimeSpan(extends.Days, new12Hour, extends.Minutes, extends.Seconds, extends.Milliseconds)
|
||||
: new TimeSpan(extends.Days, new12Hour + 12, extends.Minutes, extends.Seconds, extends.Milliseconds);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds the given number of minutes to the time, wrapping every 60 minutes without modifying the hour.
|
||||
/// </summary>
|
||||
/// <param name="extends"></param>
|
||||
/// <param name="minutes"></param>
|
||||
/// <returns></returns>
|
||||
public static TimeSpan AddMinutesAndWrap(this TimeSpan extends, int minutes)
|
||||
{
|
||||
minutes = MathUtils.Modulus(minutes + extends.Minutes, 60);
|
||||
return new TimeSpan(extends.Days, extends.Hours, minutes, extends.Seconds, extends.Milliseconds);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using ICD.Common.Properties;
|
||||
using ICD.Common.Utils.Collections;
|
||||
#if SIMPLSHARP
|
||||
using Crestron.SimplSharp.Reflection;
|
||||
@@ -83,7 +84,7 @@ namespace ICD.Common.Utils.Extensions
|
||||
/// </summary>
|
||||
/// <param name="extends"></param>
|
||||
/// <returns></returns>
|
||||
public static bool CanBeNull(this Type extends)
|
||||
public static bool CanBeNull([NotNull]this Type extends)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentException("extends");
|
||||
@@ -91,12 +92,26 @@ namespace ICD.Common.Utils.Extensions
|
||||
return !extends.IsValueType || Nullable.GetUnderlyingType(extends) != null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if the type is anonymous.
|
||||
/// </summary>
|
||||
/// <param name="type"></param>
|
||||
/// <returns></returns>
|
||||
public static bool IsAnonymous([NotNull] this Type type)
|
||||
{
|
||||
if (type == null)
|
||||
throw new ArgumentNullException("type");
|
||||
|
||||
return (type.Name.Contains("AnonymousType") || type.Name.Contains("AnonType")) &&
|
||||
(type.Name.StartsWith("<>") || type.Name.StartsWith("VB$"));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if the given type is a numeric type.
|
||||
/// </summary>
|
||||
/// <param name="extends"></param>
|
||||
/// <returns></returns>
|
||||
public static bool IsNumeric(this Type extends)
|
||||
public static bool IsNumeric([NotNull]this Type extends)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentException("extends");
|
||||
@@ -109,7 +124,7 @@ namespace ICD.Common.Utils.Extensions
|
||||
/// </summary>
|
||||
/// <param name="extends"></param>
|
||||
/// <returns></returns>
|
||||
public static bool IsSignedNumeric(this Type extends)
|
||||
public static bool IsSignedNumeric([NotNull]this Type extends)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentException("extends");
|
||||
@@ -122,7 +137,7 @@ namespace ICD.Common.Utils.Extensions
|
||||
/// </summary>
|
||||
/// <param name="extends"></param>
|
||||
/// <returns></returns>
|
||||
public static bool IsDecimalNumeric(this Type extends)
|
||||
public static bool IsDecimalNumeric([NotNull]this Type extends)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentException("extends");
|
||||
@@ -135,7 +150,7 @@ namespace ICD.Common.Utils.Extensions
|
||||
/// </summary>
|
||||
/// <param name="extends"></param>
|
||||
/// <returns></returns>
|
||||
public static bool IsIntegerNumeric(this Type extends)
|
||||
public static bool IsIntegerNumeric([NotNull]this Type extends)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentException("extends");
|
||||
@@ -148,7 +163,8 @@ namespace ICD.Common.Utils.Extensions
|
||||
/// </summary>
|
||||
/// <param name="extends"></param>
|
||||
/// <returns></returns>
|
||||
public static Assembly GetAssembly(this Type extends)
|
||||
[NotNull]
|
||||
public static Assembly GetAssembly([NotNull]this Type extends)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
@@ -167,7 +183,7 @@ namespace ICD.Common.Utils.Extensions
|
||||
/// </summary>
|
||||
/// <param name="from"></param>
|
||||
/// <returns></returns>
|
||||
public static bool IsAssignableTo<T>(this Type from)
|
||||
public static bool IsAssignableTo<T>([NotNull]this Type from)
|
||||
{
|
||||
if (from == null)
|
||||
throw new ArgumentNullException("from");
|
||||
@@ -181,7 +197,7 @@ namespace ICD.Common.Utils.Extensions
|
||||
/// <param name="from"></param>
|
||||
/// <param name="to"></param>
|
||||
/// <returns></returns>
|
||||
public static bool IsAssignableTo(this Type from, Type to)
|
||||
public static bool IsAssignableTo([NotNull]this Type from, [NotNull]Type to)
|
||||
{
|
||||
if (from == null)
|
||||
throw new ArgumentNullException("from");
|
||||
@@ -192,12 +208,39 @@ namespace ICD.Common.Utils.Extensions
|
||||
return to.IsAssignableFrom(from);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Extracts the inner Types from this current Type inheriting/implementing the given generic Type.
|
||||
/// E.g.
|
||||
/// typeof(List<int>).GetInnerGenericTypes(typeof(IEnumerable<>));
|
||||
/// Returns
|
||||
/// [ typeof(int) ]
|
||||
/// </summary>
|
||||
/// <param name="extends"></param>
|
||||
/// <param name="genericType"></param>
|
||||
/// <returns></returns>
|
||||
[NotNull]
|
||||
public static IEnumerable<Type> GetInnerGenericTypes([NotNull] this Type extends, Type genericType)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
|
||||
if (genericType == null)
|
||||
throw new ArgumentNullException("genericType");
|
||||
|
||||
return extends
|
||||
.GetAllTypes()
|
||||
.First(t => t.IsGenericType &&
|
||||
t.GetGenericTypeDefinition() == genericType)
|
||||
.GetGenericArguments();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the given type, all base types, and all implemented interfaces.
|
||||
/// </summary>
|
||||
/// <param name="extends"></param>
|
||||
/// <returns></returns>
|
||||
public static IEnumerable<Type> GetAllTypes(this Type extends)
|
||||
[NotNull]
|
||||
public static IEnumerable<Type> GetAllTypes([NotNull] this Type extends)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
@@ -221,7 +264,8 @@ namespace ICD.Common.Utils.Extensions
|
||||
/// </summary>
|
||||
/// <param name="extends"></param>
|
||||
/// <returns></returns>
|
||||
public static IEnumerable<Type> GetBaseTypes(this Type extends)
|
||||
[NotNull]
|
||||
public static IEnumerable<Type> GetBaseTypes([NotNull]this Type extends)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
@@ -236,7 +280,8 @@ namespace ICD.Common.Utils.Extensions
|
||||
return types;
|
||||
}
|
||||
|
||||
private static IEnumerable<Type> GetBaseTypesIterator(Type type)
|
||||
[NotNull]
|
||||
private static IEnumerable<Type> GetBaseTypesIterator([NotNull] Type type)
|
||||
{
|
||||
do
|
||||
{
|
||||
@@ -257,7 +302,8 @@ namespace ICD.Common.Utils.Extensions
|
||||
/// </summary>
|
||||
/// <param name="extends"></param>
|
||||
/// <returns></returns>
|
||||
public static IEnumerable<Type> GetImmediateInterfaces(this Type extends)
|
||||
[NotNull]
|
||||
public static IEnumerable<Type> GetImmediateInterfaces([NotNull]this Type extends)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
@@ -286,7 +332,8 @@ namespace ICD.Common.Utils.Extensions
|
||||
/// </summary>
|
||||
/// <param name="extends"></param>
|
||||
/// <returns></returns>
|
||||
public static IEnumerable<Type> GetMinimalInterfaces(this Type extends)
|
||||
[NotNull]
|
||||
public static IEnumerable<Type> GetMinimalInterfaces([NotNull]this Type extends)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
@@ -314,7 +361,8 @@ namespace ICD.Common.Utils.Extensions
|
||||
/// </summary>
|
||||
/// <param name="extends"></param>
|
||||
/// <returns></returns>
|
||||
public static string GetNameWithoutGenericArity(this Type extends)
|
||||
[NotNull]
|
||||
public static string GetNameWithoutGenericArity([NotNull]this Type extends)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
@@ -330,7 +378,8 @@ namespace ICD.Common.Utils.Extensions
|
||||
/// </summary>
|
||||
/// <param name="extends"></param>
|
||||
/// <returns></returns>
|
||||
public static string GetMinimalName(this Type extends)
|
||||
[NotNull]
|
||||
public static string GetMinimalName([NotNull]this Type extends)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
@@ -369,7 +418,7 @@ namespace ICD.Common.Utils.Extensions
|
||||
: extends.FullName;
|
||||
}
|
||||
|
||||
s_TypeToMinimalName.Add(extends, name);
|
||||
s_TypeToMinimalName[extends] = name;
|
||||
}
|
||||
|
||||
return name;
|
||||
@@ -380,7 +429,8 @@ namespace ICD.Common.Utils.Extensions
|
||||
/// </summary>
|
||||
/// <param name="extends"></param>
|
||||
/// <returns></returns>
|
||||
public static string GetNameWithoutAssemblyDetails(this Type extends)
|
||||
[NotNull]
|
||||
public static string GetNameWithoutAssemblyDetails([NotNull]this Type extends)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
@@ -389,7 +439,7 @@ namespace ICD.Common.Utils.Extensions
|
||||
if (!s_TypeToNameWithoutAssemblyDetails.TryGetValue(extends, out name))
|
||||
{
|
||||
name = RemoveAssemblyDetails(extends.AssemblyQualifiedName);
|
||||
s_TypeToNameWithoutAssemblyDetails.Add(extends, name);
|
||||
s_TypeToNameWithoutAssemblyDetails[extends] = name;
|
||||
}
|
||||
|
||||
return name;
|
||||
@@ -401,7 +451,8 @@ namespace ICD.Common.Utils.Extensions
|
||||
/// </summary>
|
||||
/// <param name="fullyQualifiedTypeName"></param>
|
||||
/// <returns></returns>
|
||||
private static string RemoveAssemblyDetails(string fullyQualifiedTypeName)
|
||||
[NotNull]
|
||||
private static string RemoveAssemblyDetails([NotNull] string fullyQualifiedTypeName)
|
||||
{
|
||||
StringBuilder builder = new StringBuilder();
|
||||
|
||||
@@ -450,7 +501,8 @@ namespace ICD.Common.Utils.Extensions
|
||||
/// </summary>
|
||||
/// <param name="extends">Type. May be generic or nullable</param>
|
||||
/// <returns>Full type name, fully qualified namespaces</returns>
|
||||
public static string GetSyntaxName(this Type extends)
|
||||
[NotNull]
|
||||
public static string GetSyntaxName([NotNull]this Type extends)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using ICD.Common.Properties;
|
||||
|
||||
namespace ICD.Common.Utils.Extensions
|
||||
{
|
||||
@@ -10,7 +11,8 @@ namespace ICD.Common.Utils.Extensions
|
||||
/// </summary>
|
||||
/// <param name="extends"></param>
|
||||
/// <returns></returns>
|
||||
public static string GetUserName(this Uri extends)
|
||||
[NotNull]
|
||||
public static string GetUserName([NotNull] this Uri extends)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
@@ -23,12 +25,42 @@ namespace ICD.Common.Utils.Extensions
|
||||
/// </summary>
|
||||
/// <param name="extends"></param>
|
||||
/// <returns></returns>
|
||||
public static string GetPassword(this Uri extends)
|
||||
[NotNull]
|
||||
public static string GetPassword([NotNull] this Uri extends)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
|
||||
return extends.UserInfo.Split(':').Skip(1).FirstOrDefault(string.Empty);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if the URI matches the default http://localhost/
|
||||
/// </summary>
|
||||
/// <param name="extends"></param>
|
||||
/// <returns></returns>
|
||||
public static bool GetIsDefault([NotNull] this Uri extends)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
|
||||
return extends.ToString() == "http://localhost/";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the string representation of the given URI, replacing the password with asterixes.
|
||||
/// </summary>
|
||||
/// <param name="extends"></param>
|
||||
/// <returns></returns>
|
||||
public static string ToPrivateString([NotNull] this Uri extends)
|
||||
{
|
||||
if (extends == null)
|
||||
throw new ArgumentNullException("extends");
|
||||
|
||||
IcdUriBuilder builder = new IcdUriBuilder(extends);
|
||||
builder.Password = builder.Password == null ? null : StringUtils.PasswordFormat(builder.Password);
|
||||
|
||||
return builder.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -95,7 +95,12 @@ namespace ICD.Common.Utils.Globalization
|
||||
public sealed class IcdCultureInfo : CultureInfo
|
||||
{
|
||||
private const string SQL_LOCAL_DATABASE_FILE = "CultureInfo.sqlite";
|
||||
private const string SQL_CONNECTION_STRING_FORMAT = "Data Source = {0}; Version = 3; ReadOnly = True";
|
||||
private const string SQL_CONNECTION_STRING_FORMAT =
|
||||
#if SIMPLSHARP
|
||||
"Data Source = {0}; Version = 3; ReadOnly = True";
|
||||
#else
|
||||
"Data Source = {0}";
|
||||
#endif
|
||||
private const string SQL_CMD_SELECT_BY_NAME = "select * from cultureinfo where name = @name collate nocase";
|
||||
private const string SQL_CMD_SELECT_BY_LCID = "select * from cultureinfo where lcid = @lcid";
|
||||
private const string SQL_CMD_SELECT_BY_ID = "select * from cultureinfo where id = @id";
|
||||
@@ -181,13 +186,13 @@ namespace ICD.Common.Utils.Globalization
|
||||
if ((calendar = m_Calendar) == null)
|
||||
{
|
||||
calendar =
|
||||
(m_Calendar =
|
||||
((m_CalendarType == typeof(GregorianCalendar) && m_GregorianCalendarType.HasValue)
|
||||
? (ReflectionUtils.CreateInstance<Calendar>(m_CalendarType, new object[]
|
||||
{
|
||||
m_GregorianCalendarType
|
||||
}))
|
||||
: ReflectionUtils.CreateInstance<Calendar>(m_CalendarType)));
|
||||
m_Calendar =
|
||||
m_CalendarType == typeof(GregorianCalendar) && m_GregorianCalendarType.HasValue
|
||||
? ReflectionUtils.CreateInstance<Calendar>(m_CalendarType, new object[]
|
||||
{
|
||||
m_GregorianCalendarType
|
||||
})
|
||||
: ReflectionUtils.CreateInstance<Calendar>(m_CalendarType);
|
||||
}
|
||||
return calendar;
|
||||
}
|
||||
@@ -199,14 +204,17 @@ namespace ICD.Common.Utils.Globalization
|
||||
{
|
||||
get
|
||||
{
|
||||
if (m_IsResident)
|
||||
return base.DateTimeFormat;
|
||||
CheckNeutral(this);
|
||||
if (m_DatetimeFormat == null)
|
||||
{
|
||||
if (m_IsResident)
|
||||
return base.DateTimeFormat;
|
||||
|
||||
ThrowIfNeutralCulture(this);
|
||||
|
||||
DateTimeFormatInfo dateTimeFormatInfo = GetDateTimeFormat(m_DatetimeFormatId);
|
||||
if (IsReadOnly)
|
||||
dateTimeFormatInfo = DateTimeFormatInfo.ReadOnly(dateTimeFormatInfo);
|
||||
|
||||
m_DatetimeFormat = dateTimeFormatInfo;
|
||||
}
|
||||
return m_DatetimeFormat;
|
||||
@@ -214,13 +222,13 @@ namespace ICD.Common.Utils.Globalization
|
||||
set
|
||||
{
|
||||
if (m_IsResident)
|
||||
{
|
||||
base.DateTimeFormat = value;
|
||||
return;
|
||||
}
|
||||
VerifyWritable();
|
||||
|
||||
ThrowIfReadOnly();
|
||||
|
||||
if (value == null)
|
||||
throw new ArgumentException("value");
|
||||
|
||||
m_DatetimeFormat = value;
|
||||
}
|
||||
}
|
||||
@@ -239,14 +247,17 @@ namespace ICD.Common.Utils.Globalization
|
||||
{
|
||||
get
|
||||
{
|
||||
if (m_IsResident)
|
||||
return base.NumberFormat;
|
||||
CheckNeutral(this);
|
||||
if (m_NumberFormat == null)
|
||||
{
|
||||
if (m_IsResident)
|
||||
return base.NumberFormat;
|
||||
|
||||
ThrowIfNeutralCulture(this);
|
||||
|
||||
NumberFormatInfo numberFormatInfo = GetNumberFormat(m_NumberFormatId);
|
||||
if (IsReadOnly)
|
||||
numberFormatInfo = NumberFormatInfo.ReadOnly(numberFormatInfo);
|
||||
|
||||
m_NumberFormat = numberFormatInfo;
|
||||
}
|
||||
return m_NumberFormat;
|
||||
@@ -254,13 +265,13 @@ namespace ICD.Common.Utils.Globalization
|
||||
set
|
||||
{
|
||||
if (m_IsResident)
|
||||
{
|
||||
base.NumberFormat = value;
|
||||
return;
|
||||
}
|
||||
VerifyWritable();
|
||||
|
||||
ThrowIfReadOnly();
|
||||
|
||||
if (value == null)
|
||||
throw new ArgumentException("value");
|
||||
|
||||
m_NumberFormat = value;
|
||||
}
|
||||
}
|
||||
@@ -298,7 +309,7 @@ namespace ICD.Common.Utils.Globalization
|
||||
{
|
||||
CultureInfo cultureInfo;
|
||||
if ((cultureInfo = m_Parent) == null)
|
||||
cultureInfo = (m_Parent = new IcdCultureInfo(m_ParentId, 0));
|
||||
cultureInfo = m_Parent = new IcdCultureInfo(m_ParentId, 0);
|
||||
return cultureInfo;
|
||||
}
|
||||
}
|
||||
@@ -326,7 +337,9 @@ namespace ICD.Common.Utils.Globalization
|
||||
s_LockCacheByLcid = new SafeCriticalSection();
|
||||
s_DictNumberFormatInfos = new Dictionary<int, NumberFormatInfo>();
|
||||
s_DictDatetimeFormatInfos = new Dictionary<int, DateTimeFormatInfo>();
|
||||
|
||||
string[] builtinCultures =
|
||||
#if SIMPLSHARP
|
||||
{
|
||||
"",
|
||||
"af",
|
||||
@@ -401,6 +414,11 @@ namespace ICD.Common.Utils.Globalization
|
||||
"zh-CHS",
|
||||
"zh-CHT"
|
||||
};
|
||||
#else
|
||||
CultureInfo.GetCultures(CultureTypes.AllCultures)
|
||||
.Select(c => c.Name)
|
||||
.ToArray();
|
||||
#endif
|
||||
|
||||
string databasePath = IcdPath.Combine(PathUtils.ProgramPath, SQL_LOCAL_DATABASE_FILE);
|
||||
if (!IcdFile.Exists(databasePath))
|
||||
@@ -410,62 +428,65 @@ namespace ICD.Common.Utils.Globalization
|
||||
}
|
||||
|
||||
s_SqlConnectionString = string.Format(SQL_CONNECTION_STRING_FORMAT, databasePath);
|
||||
using (IcdSqliteConnection sQLiteConnection = new IcdSqliteConnection(s_SqlConnectionString))
|
||||
try
|
||||
{
|
||||
try
|
||||
using (IcdSqliteConnection sQLiteConnection = new IcdSqliteConnection(s_SqlConnectionString))
|
||||
{
|
||||
sQLiteConnection.Open();
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
s_IsDatabasePresent = false;
|
||||
return;
|
||||
}
|
||||
s_IsDatabasePresent = true;
|
||||
IcdSqliteCommand sQLiteCommand = new IcdSqliteCommand("select count(*) from cultureinfo", sQLiteConnection);
|
||||
int num = Convert.ToInt32(sQLiteCommand.ExecuteScalar());
|
||||
s_AvailableCultureNames = new string[num + 1];
|
||||
IcdSqliteCommand sQLiteCommand2 = new IcdSqliteCommand("select id, name, lcid, isneutralculture from cultureinfo",
|
||||
sQLiteConnection);
|
||||
using (IcdSqliteDataReader sQLiteDataReader = sQLiteCommand2.ExecuteReader())
|
||||
{
|
||||
while (sQLiteDataReader.Read())
|
||||
s_IsDatabasePresent = true;
|
||||
|
||||
IcdSqliteCommand sQLiteCommand = new IcdSqliteCommand("select count(*) from cultureinfo", sQLiteConnection);
|
||||
int num = Convert.ToInt32(sQLiteCommand.ExecuteScalar());
|
||||
s_AvailableCultureNames = new string[num + 1];
|
||||
IcdSqliteCommand sQLiteCommand2 = new IcdSqliteCommand("select id, name, lcid, isneutralculture from cultureinfo",
|
||||
sQLiteConnection);
|
||||
using (IcdSqliteDataReader sQLiteDataReader = sQLiteCommand2.ExecuteReader())
|
||||
{
|
||||
int @int = sQLiteDataReader.GetInt32(0);
|
||||
bool boolean = sQLiteDataReader.GetBoolean(3);
|
||||
string @string = sQLiteDataReader.GetString(1);
|
||||
s_DictAvailableCulturesByName[@string] = (boolean ? CultureTypes.NeutralCultures : CultureTypes.SpecificCultures);
|
||||
int int2 = sQLiteDataReader.GetInt32(2);
|
||||
s_DictAvailableCulturesByLcid[int2] = (boolean ? CultureTypes.NeutralCultures : CultureTypes.SpecificCultures);
|
||||
s_AvailableCultureNames[@int] = @string;
|
||||
while (sQLiteDataReader.Read())
|
||||
{
|
||||
int @int = sQLiteDataReader.GetInt32(0);
|
||||
bool boolean = sQLiteDataReader.GetBoolean(3);
|
||||
string @string = sQLiteDataReader.GetString(1);
|
||||
s_DictAvailableCulturesByName[@string] = boolean ? CultureTypes.NeutralCultures : CultureTypes.SpecificCultures;
|
||||
int int2 = sQLiteDataReader.GetInt32(2);
|
||||
s_DictAvailableCulturesByLcid[int2] = boolean ? CultureTypes.NeutralCultures : CultureTypes.SpecificCultures;
|
||||
s_AvailableCultureNames[@int] = @string;
|
||||
}
|
||||
}
|
||||
}
|
||||
sQLiteCommand2 = new IcdSqliteCommand("select id, specificculture from specificcultureinfo", sQLiteConnection);
|
||||
using (IcdSqliteDataReader sQLiteDataReader2 = sQLiteCommand2.ExecuteReader())
|
||||
{
|
||||
while (sQLiteDataReader2.Read())
|
||||
|
||||
sQLiteCommand2 = new IcdSqliteCommand("select id, specificculture from specificcultureinfo", sQLiteConnection);
|
||||
using (IcdSqliteDataReader sQLiteDataReader2 = sQLiteCommand2.ExecuteReader())
|
||||
{
|
||||
int int3 = sQLiteDataReader2.GetInt32(0);
|
||||
string string2 = sQLiteDataReader2.GetString(1);
|
||||
s_DictSpecificCulture[s_AvailableCultureNames[int3]] = string2;
|
||||
while (sQLiteDataReader2.Read())
|
||||
{
|
||||
int int3 = sQLiteDataReader2.GetInt32(0);
|
||||
string string2 = sQLiteDataReader2.GetString(1);
|
||||
s_DictSpecificCulture[s_AvailableCultureNames[int3]] = string2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
string[] array = builtinCultures;
|
||||
for (int i = 0; i < array.Length; i++)
|
||||
catch (Exception)
|
||||
{
|
||||
s_IsDatabasePresent = false;
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (string name in builtinCultures)
|
||||
{
|
||||
string name = array[i];
|
||||
try
|
||||
{
|
||||
CultureInfo cultureInfo = CultureInfo.GetCultureInfo(name);
|
||||
|
||||
Dictionary<string, CultureTypes> dictAvailableCulturesByName;
|
||||
string name2;
|
||||
(dictAvailableCulturesByName = s_DictAvailableCulturesByName)[name2 = cultureInfo.Name] =
|
||||
(dictAvailableCulturesByName[name2] | CultureTypes.InstalledWin32Cultures);
|
||||
dictAvailableCulturesByName[name2] | CultureTypes.InstalledWin32Cultures;
|
||||
|
||||
Dictionary<int, CultureTypes> dictAvailableCulturesByLcid;
|
||||
int lCid;
|
||||
(dictAvailableCulturesByLcid = s_DictAvailableCulturesByLcid)[lCid = cultureInfo.LCID] =
|
||||
(dictAvailableCulturesByLcid[lCid] | CultureTypes.InstalledWin32Cultures);
|
||||
dictAvailableCulturesByLcid[lCid] | CultureTypes.InstalledWin32Cultures;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
@@ -483,14 +504,17 @@ namespace ICD.Common.Utils.Globalization
|
||||
{
|
||||
if (culture < 0)
|
||||
throw new ArgumentOutOfRangeException("culture", "must be >= 0");
|
||||
|
||||
CultureTypes cultureTypes;
|
||||
if (!s_DictAvailableCulturesByLcid.TryGetValue(culture, out cultureTypes))
|
||||
throw new ArgumentException("not supported");
|
||||
throw new ArgumentException(string.Format("Culture {0} not supported", culture));
|
||||
|
||||
if (!s_IsDatabasePresent || (cultureTypes & CultureTypes.InstalledWin32Cultures) != 0)
|
||||
{
|
||||
BuildCultureInfoEx(CultureInfo.GetCultureInfo(culture));
|
||||
return;
|
||||
}
|
||||
|
||||
CultureInfo ci;
|
||||
bool flag;
|
||||
s_LockCacheByLcid.Enter();
|
||||
@@ -498,11 +522,13 @@ namespace ICD.Common.Utils.Globalization
|
||||
flag = s_DictCacheByLcid.TryGetValue(culture, out ci);
|
||||
}
|
||||
s_LockCacheByLcid.Leave();
|
||||
|
||||
if (flag)
|
||||
{
|
||||
BuildCultureInfoEx(ci);
|
||||
return;
|
||||
}
|
||||
|
||||
using (IcdSqliteConnection sQLiteConnection = new IcdSqliteConnection(s_SqlConnectionString))
|
||||
{
|
||||
sQLiteConnection.Open();
|
||||
@@ -523,14 +549,17 @@ namespace ICD.Common.Utils.Globalization
|
||||
{
|
||||
if (name == null)
|
||||
throw new ArgumentNullException("name");
|
||||
|
||||
CultureTypes cultureTypes;
|
||||
if (!s_DictAvailableCulturesByName.TryGetValue(name, out cultureTypes))
|
||||
throw new ArgumentException("not supported");
|
||||
throw new ArgumentException(string.Format("Culture {0} not supported", name));
|
||||
|
||||
if (!s_IsDatabasePresent || (cultureTypes & CultureTypes.InstalledWin32Cultures) != 0)
|
||||
{
|
||||
BuildCultureInfoEx(CultureInfo.GetCultureInfo(name));
|
||||
return;
|
||||
}
|
||||
|
||||
CultureInfo ci;
|
||||
bool flag;
|
||||
s_LockCacheByName.Enter();
|
||||
@@ -590,6 +619,7 @@ namespace ICD.Common.Utils.Globalization
|
||||
{
|
||||
if (!rdr.Read())
|
||||
throw new InvalidOperationException("failure reading database");
|
||||
|
||||
int ordinal = rdr.GetOrdinal("calendar");
|
||||
string text = rdr.GetString(ordinal);
|
||||
if (text.EndsWith(")"))
|
||||
@@ -599,6 +629,7 @@ namespace ICD.Common.Utils.Globalization
|
||||
text = text.Substring(0, num);
|
||||
m_GregorianCalendarType = (GregorianCalendarTypes)Enum.Parse(typeof(GregorianCalendarTypes), value, true);
|
||||
}
|
||||
|
||||
m_CalendarType = Type.GetType("System.Globalization." + text);
|
||||
ordinal = rdr.GetOrdinal("englishname");
|
||||
m_EnglishName = rdr.GetString(ordinal);
|
||||
@@ -611,10 +642,7 @@ namespace ICD.Common.Utils.Globalization
|
||||
ordinal = rdr.GetOrdinal("nativename");
|
||||
m_NativeName = rdr.GetString(ordinal);
|
||||
ordinal = rdr.GetOrdinal("optionalcalendars");
|
||||
string[] array = rdr.GetString(ordinal).Split(new[]
|
||||
{
|
||||
'|'
|
||||
});
|
||||
string[] array = rdr.GetString(ordinal).Split('|');
|
||||
m_OptionalGregorianCalendarTypes = new GregorianCalendarTypes?[array.Length];
|
||||
m_OptionalCalendarTypes = new Type[array.Length];
|
||||
for (int i = 0; i < array.Length; i++)
|
||||
@@ -701,15 +729,15 @@ namespace ICD.Common.Utils.Globalization
|
||||
CurrencyDecimalDigits = sQLiteDataReader.GetInt32(ordinal),
|
||||
CurrencyDecimalSeparator = sQLiteDataReader.GetString(ordinal2),
|
||||
CurrencyGroupSizes = sQLiteDataReader.GetString(ordinal3)
|
||||
.Split(new[] {','})
|
||||
.Split(',')
|
||||
.Select(s => int.Parse(s))
|
||||
.ToArray(),
|
||||
NumberGroupSizes = sQLiteDataReader.GetString(ordinal4)
|
||||
.Split(new[] {','})
|
||||
.Split(',')
|
||||
.Select(s => int.Parse(s))
|
||||
.ToArray(),
|
||||
PercentGroupSizes = sQLiteDataReader.GetString(ordinal5)
|
||||
.Split(new[] {','})
|
||||
.Split(',')
|
||||
.Select(s => int.Parse(s))
|
||||
.ToArray(),
|
||||
CurrencyGroupSeparator = sQLiteDataReader.GetString(ordinal6),
|
||||
@@ -798,34 +826,13 @@ namespace ICD.Common.Utils.Globalization
|
||||
ShortTimePattern = sQLiteDataReader.GetString(ordinal11),
|
||||
TimeSeparator = sQLiteDataReader.GetString(ordinal12),
|
||||
YearMonthPattern = sQLiteDataReader.GetString(ordinal13),
|
||||
AbbreviatedDayNames = sQLiteDataReader.GetString(ordinal14).Split(new[]
|
||||
{
|
||||
'|'
|
||||
}),
|
||||
ShortestDayNames = sQLiteDataReader.GetString(ordinal15).Split(new[]
|
||||
{
|
||||
'|'
|
||||
}),
|
||||
DayNames = sQLiteDataReader.GetString(ordinal16).Split(new[]
|
||||
{
|
||||
'|'
|
||||
}),
|
||||
AbbreviatedMonthNames = sQLiteDataReader.GetString(ordinal17).Split(new[]
|
||||
{
|
||||
'|'
|
||||
}),
|
||||
MonthNames = sQLiteDataReader.GetString(ordinal18).Split(new[]
|
||||
{
|
||||
'|'
|
||||
}),
|
||||
AbbreviatedMonthGenitiveNames = sQLiteDataReader.GetString(ordinal19).Split(new[]
|
||||
{
|
||||
'|'
|
||||
}),
|
||||
MonthGenitiveNames = sQLiteDataReader.GetString(ordinal20).Split(new[]
|
||||
{
|
||||
'|'
|
||||
})
|
||||
AbbreviatedDayNames = sQLiteDataReader.GetString(ordinal14).Split('|'),
|
||||
ShortestDayNames = sQLiteDataReader.GetString(ordinal15).Split('|'),
|
||||
DayNames = sQLiteDataReader.GetString(ordinal16).Split('|'),
|
||||
AbbreviatedMonthNames = sQLiteDataReader.GetString(ordinal17).Split('|'),
|
||||
MonthNames = sQLiteDataReader.GetString(ordinal18).Split('|'),
|
||||
AbbreviatedMonthGenitiveNames = sQLiteDataReader.GetString(ordinal19).Split('|'),
|
||||
MonthGenitiveNames = sQLiteDataReader.GetString(ordinal20).Split('|')
|
||||
};
|
||||
}
|
||||
s_DictDatetimeFormatInfos[id] = dateTimeFormatInfo;
|
||||
@@ -845,24 +852,25 @@ namespace ICD.Common.Utils.Globalization
|
||||
try
|
||||
{
|
||||
m_CompareInfo = ci.CompareInfo;
|
||||
goto IL_CE;
|
||||
}
|
||||
catch (PlatformNotSupportedException)
|
||||
{
|
||||
m_CompareInfo = CultureInfo.InvariantCulture.CompareInfo;
|
||||
goto IL_CE;
|
||||
}
|
||||
}
|
||||
m_Calendar = icdCultureInfo.m_Calendar;
|
||||
m_CalendarType = icdCultureInfo.m_CalendarType;
|
||||
m_GregorianCalendarType = icdCultureInfo.m_GregorianCalendarType;
|
||||
m_OptionalCalendars = icdCultureInfo.m_OptionalCalendars;
|
||||
m_OptionalCalendarTypes = icdCultureInfo.m_OptionalCalendarTypes;
|
||||
m_OptionalGregorianCalendarTypes = icdCultureInfo.m_OptionalGregorianCalendarTypes;
|
||||
m_Parent = icdCultureInfo.m_Parent;
|
||||
m_TextInfo = icdCultureInfo.m_TextInfo;
|
||||
m_CompareInfo = icdCultureInfo.m_CompareInfo;
|
||||
IL_CE:
|
||||
else
|
||||
{
|
||||
m_Calendar = icdCultureInfo.m_Calendar;
|
||||
m_CalendarType = icdCultureInfo.m_CalendarType;
|
||||
m_GregorianCalendarType = icdCultureInfo.m_GregorianCalendarType;
|
||||
m_OptionalCalendars = icdCultureInfo.m_OptionalCalendars;
|
||||
m_OptionalCalendarTypes = icdCultureInfo.m_OptionalCalendarTypes;
|
||||
m_OptionalGregorianCalendarTypes = icdCultureInfo.m_OptionalGregorianCalendarTypes;
|
||||
m_Parent = icdCultureInfo.m_Parent;
|
||||
m_TextInfo = icdCultureInfo.m_TextInfo;
|
||||
m_CompareInfo = icdCultureInfo.m_CompareInfo;
|
||||
}
|
||||
|
||||
m_EnglishName = ci.EnglishName;
|
||||
m_IsNeutralCulture = ci.IsNeutralCulture;
|
||||
m_Lcid = ci.LCID;
|
||||
@@ -871,19 +879,21 @@ namespace ICD.Common.Utils.Globalization
|
||||
m_ThreeLetterIsoLanguageName = ci.ThreeLetterISOLanguageName;
|
||||
m_ThreeLetterWindowsLanguageName = ci.ThreeLetterWindowsLanguageName;
|
||||
m_TwoLetterIsoLanguageName = ci.TwoLetterISOLanguageName;
|
||||
if (!m_IsNeutralCulture)
|
||||
|
||||
if (m_IsNeutralCulture)
|
||||
return;
|
||||
|
||||
if (icdCultureInfo == null)
|
||||
{
|
||||
if (icdCultureInfo == null)
|
||||
{
|
||||
m_DatetimeFormat = ci.DateTimeFormat;
|
||||
m_NumberFormat = ci.NumberFormat;
|
||||
return;
|
||||
}
|
||||
m_DatetimeFormatId = icdCultureInfo.m_DatetimeFormatId;
|
||||
m_DatetimeFormat = icdCultureInfo.m_DatetimeFormat;
|
||||
m_NumberFormatId = icdCultureInfo.m_NumberFormatId;
|
||||
m_NumberFormat = icdCultureInfo.m_NumberFormat;
|
||||
m_DatetimeFormat = ci.DateTimeFormat.Clone() as DateTimeFormatInfo;
|
||||
m_NumberFormat = ci.NumberFormat.Clone() as NumberFormatInfo;
|
||||
return;
|
||||
}
|
||||
|
||||
m_DatetimeFormatId = icdCultureInfo.m_DatetimeFormatId;
|
||||
m_DatetimeFormat = icdCultureInfo.m_DatetimeFormat.Clone() as DateTimeFormatInfo;
|
||||
m_NumberFormatId = icdCultureInfo.m_NumberFormatId;
|
||||
m_NumberFormat = icdCultureInfo.m_NumberFormat.Clone() as NumberFormatInfo;
|
||||
}
|
||||
|
||||
#region Methods
|
||||
@@ -932,7 +942,7 @@ namespace ICD.Common.Utils.Globalization
|
||||
|
||||
public static CultureInfo[] GetCultures(CultureTypes types)
|
||||
{
|
||||
return s_DictAvailableCulturesByName.Where(de => (de.Value & types) != (CultureTypes)0)
|
||||
return s_DictAvailableCulturesByName.Where(de => (de.Value & types) != 0)
|
||||
.Select(de => new IcdCultureInfo(de.Key))
|
||||
.Cast<CultureInfo>()
|
||||
.ToArray();
|
||||
@@ -985,16 +995,16 @@ namespace ICD.Common.Utils.Globalization
|
||||
|
||||
#endregion
|
||||
|
||||
private void VerifyWritable()
|
||||
private void ThrowIfReadOnly()
|
||||
{
|
||||
if (IsReadOnly)
|
||||
throw new InvalidOperationException();
|
||||
}
|
||||
|
||||
private static void CheckNeutral(CultureInfo culture)
|
||||
private static void ThrowIfNeutralCulture(CultureInfo culture)
|
||||
{
|
||||
if (culture.IsNeutralCulture)
|
||||
throw new NotSupportedException();
|
||||
throw new NotSupportedException("A neutral culture does not provide enough information to display the correct numeric format");
|
||||
}
|
||||
|
||||
private static bool IsResident(string name)
|
||||
|
||||
34
ICD.Common.Utils/GuidUtils.cs
Normal file
34
ICD.Common.Utils/GuidUtils.cs
Normal file
@@ -0,0 +1,34 @@
|
||||
using System;
|
||||
|
||||
namespace ICD.Common.Utils
|
||||
{
|
||||
public static class GuidUtils
|
||||
{
|
||||
/// <summary>
|
||||
/// Generates a pseudo-random guid from the given seed.
|
||||
/// </summary>
|
||||
public static Guid GenerateSeeded(int seed)
|
||||
{
|
||||
Random seeded = new Random(seed);
|
||||
byte[] bytes = new byte[16];
|
||||
|
||||
seeded.NextBytes(bytes);
|
||||
|
||||
return new Guid(bytes);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Combines the two guids to make a new, deterministic guid.
|
||||
/// </summary>
|
||||
public static Guid Combine(Guid a, Guid b)
|
||||
{
|
||||
byte[] aBytes = a.ToByteArray();
|
||||
byte[] bBytes = b.ToByteArray();
|
||||
|
||||
for (int index = 0; index < aBytes.Length; index++)
|
||||
aBytes[index] = (byte)(aBytes[index] ^ bBytes[index]);
|
||||
|
||||
return new Guid(aBytes);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -39,9 +39,10 @@
|
||||
<None Remove="Properties\ControlSystem.cfg" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Data.SQLite" Version="2.2.3" />
|
||||
<PackageReference Include="Microsoft.Data.SQLite" Version="2.2.6" />
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyModel" Version="2.1.0" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="12.0.1" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="12.0.2" />
|
||||
<PackageReference Include="Pastel" Version="1.3.1" />
|
||||
<PackageReference Include="System.Net.NetworkInformation" Version="4.3.0" />
|
||||
<PackageReference Include="System.Runtime.Loader" Version="4.3.0" />
|
||||
</ItemGroup>
|
||||
|
||||
@@ -74,7 +74,9 @@
|
||||
<Reference Include="System.Data" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="AnsiUtils.cs" />
|
||||
<Compile Include="Attributes\AbstractIcdAttribute.cs" />
|
||||
<Compile Include="Attributes\IIcdAttribute.cs" />
|
||||
<Compile Include="Attributes\RangeAttribute.cs" />
|
||||
<Compile Include="Collections\BiDictionary.cs" />
|
||||
<Compile Include="Collections\IcdOrderedDictionary.cs" />
|
||||
@@ -84,16 +86,19 @@
|
||||
<Compile Include="Comparers\FileNameEqualityComparer.cs" />
|
||||
<Compile Include="Comparers\PredicateComparer.cs" />
|
||||
<Compile Include="Comparers\SequenceComparer.cs" />
|
||||
<Compile Include="ConsoleColor.cs" />
|
||||
<Compile Include="eConsoleColor.cs" />
|
||||
<Compile Include="DateTimeUtils.cs" />
|
||||
<Compile Include="Email\EmailClient.cs" />
|
||||
<Compile Include="Email\eMailErrorCode.cs" />
|
||||
<Compile Include="Email\EmailStringCollection.cs" />
|
||||
<Compile Include="Email\EmailValidation.cs" />
|
||||
<Compile Include="EncodingUtils.cs" />
|
||||
<Compile Include="Csv\CsvWriter.cs" />
|
||||
<Compile Include="Csv\CsvWriterSettings.cs" />
|
||||
<Compile Include="EventArguments\BoolEventArgs.cs" />
|
||||
<Compile Include="EventArguments\CharEventArgs.cs" />
|
||||
<Compile Include="EventArguments\DateTimeEventArgs.cs" />
|
||||
<Compile Include="EventArguments\DateTimeNullableEventArgs.cs" />
|
||||
<Compile Include="EventArguments\FloatEventArgs.cs" />
|
||||
<Compile Include="EventArguments\GenericEventArgs.cs" />
|
||||
<Compile Include="EventArguments\IGenericEventArgs.cs" />
|
||||
@@ -107,8 +112,10 @@
|
||||
<None Include="ObfuscationSettings.cs" />
|
||||
<Compile Include="Extensions\BoolExtensions.cs" />
|
||||
<Compile Include="Extensions\ByteExtensions.cs" />
|
||||
<Compile Include="Extensions\CultureInfoExtensions.cs" />
|
||||
<Compile Include="Extensions\DayOfWeekExtensions.cs" />
|
||||
<Compile Include="Extensions\JsonSerializerExtensions.cs" />
|
||||
<Compile Include="Extensions\JsonTokenExtensions.cs" />
|
||||
<Compile Include="Extensions\JsonWriterExtensions.cs" />
|
||||
<Compile Include="Extensions\ListExtensions.cs" />
|
||||
<Compile Include="Comparers\PredicateEqualityComparer.cs" />
|
||||
@@ -117,12 +124,17 @@
|
||||
<Compile Include="Extensions\UriExtensions.cs" />
|
||||
<Compile Include="Extensions\UShortExtensions.cs" />
|
||||
<Compile Include="Globalization\IcdCultureInfo.cs" />
|
||||
<Compile Include="GuidUtils.cs" />
|
||||
<Compile Include="IcdUriBuilder.cs" />
|
||||
<Compile Include="IO\Compression\IcdZipEntry.cs" />
|
||||
<Compile Include="IO\eIcdFileMode.cs" />
|
||||
<Compile Include="IO\IcdBinaryReader.cs" />
|
||||
<Compile Include="IO\eSeekOrigin.cs" />
|
||||
<Compile Include="IO\IcdStreamWriter.cs" />
|
||||
<Compile Include="Json\DateTimeIsoConverter.cs" />
|
||||
<Compile Include="Json\MinimalTypeConverter.cs" />
|
||||
<Compile Include="Json\ToStringJsonConverter.cs" />
|
||||
<Compile Include="NullObject.cs" />
|
||||
<Compile Include="ProcessorUtils.SimplSharp.cs" />
|
||||
<Compile Include="ProcessorUtils.Standard.cs" />
|
||||
<Compile Include="ProgramUtils.SimplSharp.cs" />
|
||||
@@ -209,6 +221,7 @@
|
||||
<Compile Include="Timers\Repeater.cs" />
|
||||
<Compile Include="Timers\SafeTimer.cs" />
|
||||
<Compile Include="TryUtils.cs" />
|
||||
<Compile Include="UriQueryBuilder.cs" />
|
||||
<Compile Include="UriUtils.cs" />
|
||||
<Compile Include="Xml\AbstractGenericXmlConverter.cs" />
|
||||
<Compile Include="Xml\AbstractXmlConverter.cs" />
|
||||
|
||||
@@ -78,9 +78,9 @@ namespace ICD.Common.Utils.IO
|
||||
}
|
||||
|
||||
[PublicAPI]
|
||||
public static IcdFileStream Open(string path, FileMode mode)
|
||||
public static IcdFileStream Open(string path, eIcdFileMode mode)
|
||||
{
|
||||
return new IcdFileStream(File.Open(path, mode));
|
||||
return new IcdFileStream(File.Open(path, mode.ToFileMode()));
|
||||
}
|
||||
|
||||
[PublicAPI]
|
||||
@@ -100,5 +100,16 @@ namespace ICD.Common.Utils.IO
|
||||
{
|
||||
return new IcdStreamWriter(File.AppendText(path));
|
||||
}
|
||||
|
||||
public static void WriteAllBytes(string path, byte[] bytes)
|
||||
{
|
||||
using (FileStream stream = File.OpenWrite(path))
|
||||
stream.Write(bytes, 0, bytes.Length);
|
||||
}
|
||||
|
||||
public static void Move([NotNull] string sourceFileName, [NotNull] string destFileName)
|
||||
{
|
||||
File.Move(sourceFileName, destFileName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
46
ICD.Common.Utils/IO/eIcdFileMode.cs
Normal file
46
ICD.Common.Utils/IO/eIcdFileMode.cs
Normal file
@@ -0,0 +1,46 @@
|
||||
using System;
|
||||
#if SIMPLSHARP
|
||||
using Crestron.SimplSharp.CrestronIO;
|
||||
#else
|
||||
using System.IO;
|
||||
#endif
|
||||
|
||||
namespace ICD.Common.Utils.IO
|
||||
{
|
||||
/// <summary>
|
||||
/// Specifies how the operating system should open a file.
|
||||
/// </summary>
|
||||
public enum eIcdFileMode
|
||||
{
|
||||
CreateNew = 1,
|
||||
Create = 2,
|
||||
Open = 3,
|
||||
OpenOrCreate = 4,
|
||||
Truncate = 5,
|
||||
Append = 6,
|
||||
}
|
||||
|
||||
public static class IcdFileModeExtensions
|
||||
{
|
||||
public static FileMode ToFileMode(this eIcdFileMode extends)
|
||||
{
|
||||
switch (extends)
|
||||
{
|
||||
case eIcdFileMode.CreateNew:
|
||||
return FileMode.CreateNew;
|
||||
case eIcdFileMode.Create:
|
||||
return FileMode.Create;
|
||||
case eIcdFileMode.Open:
|
||||
return FileMode.Open;
|
||||
case eIcdFileMode.OpenOrCreate:
|
||||
return FileMode.OpenOrCreate;
|
||||
case eIcdFileMode.Truncate:
|
||||
return FileMode.Truncate;
|
||||
case eIcdFileMode.Append:
|
||||
return FileMode.Append;
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException("extends");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -49,9 +49,7 @@ namespace ICD.Common.Utils
|
||||
{
|
||||
try
|
||||
{
|
||||
|
||||
CrestronConsole.ConsoleCommandResponse(message);
|
||||
|
||||
}
|
||||
catch (NotSupportedException)
|
||||
{
|
||||
@@ -83,14 +81,8 @@ namespace ICD.Common.Utils
|
||||
|
||||
public static void PrintLine(eConsoleColor color, string message)
|
||||
{
|
||||
#if SIMPLSHARP
|
||||
PrintLine(color.FormatAnsi(message));
|
||||
#else
|
||||
System.Console.ForegroundColor = color.ToForegroundConsoleColor();
|
||||
System.Console.BackgroundColor = color.ToBackgroundConsoleColor();
|
||||
System.Console.WriteLine(message);
|
||||
System.Console.ResetColor();
|
||||
#endif
|
||||
string ansi = color.FormatAnsi(message);
|
||||
PrintLine(ansi);
|
||||
}
|
||||
|
||||
public static void PrintLine(eConsoleColor color, string message, params object[] args)
|
||||
@@ -118,14 +110,8 @@ namespace ICD.Common.Utils
|
||||
|
||||
public static void Print(eConsoleColor color, string message)
|
||||
{
|
||||
#if SIMPLSHARP
|
||||
Print(color.FormatAnsi(message));
|
||||
#else
|
||||
System.Console.ForegroundColor = color.ToForegroundConsoleColor();
|
||||
System.Console.BackgroundColor = color.ToBackgroundConsoleColor();
|
||||
System.Console.Write(message);
|
||||
System.Console.ResetColor();
|
||||
#endif
|
||||
string ansi = color.FormatAnsi(message);
|
||||
Print(ansi);
|
||||
}
|
||||
|
||||
public static void Print(eConsoleColor color, string message, params object[] args)
|
||||
|
||||
@@ -3,11 +3,19 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using Crestron.SimplSharp;
|
||||
using ICD.Common.Properties;
|
||||
using ICD.Common.Utils.Extensions;
|
||||
|
||||
namespace ICD.Common.Utils
|
||||
{
|
||||
public static partial class IcdEnvironment
|
||||
{
|
||||
/// <summary>
|
||||
/// For some reason crestron returns "Invalid Value" for ethernet parameters sometimes :/
|
||||
/// </summary>
|
||||
private const string INVALID_VALUE = "Invalid Value";
|
||||
|
||||
#region Properties
|
||||
|
||||
public static string NewLine { get { return CrestronEnvironment.NewLine; } }
|
||||
|
||||
public static eRuntimeEnvironment RuntimeEnvironment
|
||||
@@ -30,9 +38,27 @@ namespace ICD.Common.Utils
|
||||
{
|
||||
const CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET param =
|
||||
CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_CURRENT_IP_ADDRESS;
|
||||
const EthernetAdapterType type = EthernetAdapterType.EthernetLANAdapter;
|
||||
short id = CrestronEthernetHelper.GetAdapterdIdForSpecifiedAdapterType(type);
|
||||
yield return CrestronEthernetHelper.GetEthernetParameter(param, id);
|
||||
|
||||
foreach (EthernetAdapterType type in EnumUtils.GetValuesExceptNone<EthernetAdapterType>())
|
||||
{
|
||||
string address;
|
||||
|
||||
try
|
||||
{
|
||||
short id = CrestronEthernetHelper.GetAdapterdIdForSpecifiedAdapterType(type);
|
||||
if (id >= InitialParametersClass.NumberOfEthernetInterfaces)
|
||||
continue;
|
||||
|
||||
address = CrestronEthernetHelper.GetEthernetParameter(param, id);
|
||||
}
|
||||
catch (ArgumentException)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(address) && !address.Equals(INVALID_VALUE))
|
||||
yield return address;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,12 +72,98 @@ namespace ICD.Common.Utils
|
||||
{
|
||||
const CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET param =
|
||||
CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_MAC_ADDRESS;
|
||||
const EthernetAdapterType type = EthernetAdapterType.EthernetLANAdapter;
|
||||
short id = CrestronEthernetHelper.GetAdapterdIdForSpecifiedAdapterType(type);
|
||||
yield return CrestronEthernetHelper.GetEthernetParameter(param, id);
|
||||
|
||||
foreach (EthernetAdapterType type in EnumUtils.GetValuesExceptNone<EthernetAdapterType>())
|
||||
{
|
||||
string macAddress;
|
||||
|
||||
try
|
||||
{
|
||||
short id = CrestronEthernetHelper.GetAdapterdIdForSpecifiedAdapterType(type);
|
||||
if (id >= InitialParametersClass.NumberOfEthernetInterfaces)
|
||||
continue;
|
||||
|
||||
macAddress = CrestronEthernetHelper.GetEthernetParameter(param, id);
|
||||
}
|
||||
catch (ArgumentException)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(macAddress) && !macAddress.Equals(INVALID_VALUE))
|
||||
yield return macAddress;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the dhcp status of the processor.
|
||||
/// </summary>
|
||||
[PublicAPI]
|
||||
public static string DhcpStatus
|
||||
{
|
||||
get
|
||||
{
|
||||
const CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET param =
|
||||
CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_CURRENT_DHCP_STATE;
|
||||
const EthernetAdapterType type = EthernetAdapterType.EthernetLANAdapter;
|
||||
|
||||
try
|
||||
{
|
||||
short id = CrestronEthernetHelper.GetAdapterdIdForSpecifiedAdapterType(type);
|
||||
if (id >= InitialParametersClass.NumberOfEthernetInterfaces)
|
||||
return null;
|
||||
|
||||
string status = CrestronEthernetHelper.GetEthernetParameter(param, id);
|
||||
|
||||
if (!string.IsNullOrEmpty(status) && !status.Equals(INVALID_VALUE))
|
||||
return status;
|
||||
|
||||
return null;
|
||||
}
|
||||
catch (ArgumentException)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the hostname of the processor.
|
||||
/// </summary>
|
||||
[PublicAPI]
|
||||
public static IEnumerable<string> Hostname
|
||||
{
|
||||
get
|
||||
{
|
||||
const CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET param =
|
||||
CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_HOSTNAME;
|
||||
|
||||
foreach (EthernetAdapterType type in EnumUtils.GetValuesExceptNone<EthernetAdapterType>())
|
||||
{
|
||||
string hostname;
|
||||
|
||||
try
|
||||
{
|
||||
short id = CrestronEthernetHelper.GetAdapterdIdForSpecifiedAdapterType(type);
|
||||
if (id >= InitialParametersClass.NumberOfEthernetInterfaces)
|
||||
continue;
|
||||
|
||||
hostname = CrestronEthernetHelper.GetEthernetParameter(param, id);
|
||||
}
|
||||
catch (ArgumentException)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(hostname) && !hostname.Equals(INVALID_VALUE))
|
||||
yield return hostname;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Static constructor.
|
||||
/// </summary>
|
||||
@@ -68,6 +180,18 @@ namespace ICD.Common.Utils
|
||||
return CrestronEnvironment.GetLocalTime();
|
||||
}
|
||||
|
||||
public static void SetLocalTime(DateTime localTime)
|
||||
{
|
||||
CrestronEnvironment.SetTimeAndDate((ushort)localTime.Hour,
|
||||
(ushort)localTime.Minute,
|
||||
(ushort)localTime.Second,
|
||||
(ushort)localTime.Month,
|
||||
(ushort)localTime.Day,
|
||||
(ushort)localTime.Year);
|
||||
|
||||
OnSystemDateTimeChanged.Raise(null);
|
||||
}
|
||||
|
||||
public static eEthernetEventType GetEthernetEventType(Crestron.SimplSharp.eEthernetEventType type)
|
||||
{
|
||||
switch (type)
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.NetworkInformation;
|
||||
using System.Net.Sockets;
|
||||
using System.Text.RegularExpressions;
|
||||
@@ -13,11 +14,6 @@ namespace ICD.Common.Utils
|
||||
{
|
||||
public static string NewLine { get { return Environment.NewLine; } }
|
||||
|
||||
public static DateTime GetLocalTime()
|
||||
{
|
||||
return DateTime.Now;
|
||||
}
|
||||
|
||||
public static eRuntimeEnvironment RuntimeEnvironment { get { return eRuntimeEnvironment.Standard; } }
|
||||
|
||||
/// <summary>
|
||||
@@ -53,6 +49,53 @@ namespace ICD.Common.Utils
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the dhcp status of the processor.
|
||||
/// </summary>
|
||||
[PublicAPI]
|
||||
public static string DhcpStatus
|
||||
{
|
||||
get
|
||||
{
|
||||
try
|
||||
{
|
||||
bool enabled =
|
||||
NetworkInterface.GetAllNetworkInterfaces()
|
||||
.Where(ni => ni.NetworkInterfaceType == NetworkInterfaceType.Wireless80211 ||
|
||||
ni.NetworkInterfaceType == NetworkInterfaceType.Ethernet)
|
||||
.Select(ni => ni.GetIPProperties().GetIPv4Properties().IsDhcpEnabled)
|
||||
.FirstOrDefault();
|
||||
|
||||
return enabled.ToString();
|
||||
}
|
||||
catch(PlatformNotSupportedException)
|
||||
{
|
||||
return false.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the hostname of the processor.
|
||||
/// </summary>
|
||||
[PublicAPI]
|
||||
public static IEnumerable<string> Hostname { get { yield return Dns.GetHostName(); } }
|
||||
|
||||
public static DateTime GetLocalTime()
|
||||
{
|
||||
return DateTime.Now;
|
||||
}
|
||||
|
||||
public static void SetLocalTime(DateTime localTime)
|
||||
{
|
||||
#if DEBUG
|
||||
IcdConsole.PrintLine(eConsoleColor.Magenta, "Debug Build - Skipped setting local time to {0}",
|
||||
localTime.ToString("s"));
|
||||
#else
|
||||
throw new NotSupportedException();
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts 12 digit address to XX:XX:XX... format
|
||||
/// </summary>
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
using System;
|
||||
using ICD.Common.Properties;
|
||||
using ICD.Common.Utils.Extensions;
|
||||
|
||||
namespace ICD.Common.Utils
|
||||
{
|
||||
@@ -54,5 +56,56 @@ namespace ICD.Common.Utils
|
||||
public static event ProgramStatusCallback OnProgramStatusEvent;
|
||||
|
||||
public static event EthernetEventCallback OnEthernetEvent;
|
||||
|
||||
/// <summary>
|
||||
/// Raised when the program has completed initialization.
|
||||
/// </summary>
|
||||
public static event EventHandler OnProgramInitializationComplete;
|
||||
|
||||
/// <summary>
|
||||
/// Raised when the system date/time has been set.
|
||||
/// </summary>
|
||||
public static event EventHandler OnSystemDateTimeChanged;
|
||||
|
||||
private static readonly SafeCriticalSection s_ProgramInitializationSection = new SafeCriticalSection();
|
||||
private static bool s_ProgramInitializationComplete;
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if the program has been flagged as completely initialized.
|
||||
/// </summary>
|
||||
public static bool ProgramIsInitialized { get { return s_ProgramInitializationSection.Execute(() => s_ProgramInitializationComplete); } }
|
||||
|
||||
/// <summary>
|
||||
/// Called by the program entry point to signify that the program initialization is complete.
|
||||
/// </summary>
|
||||
[PublicAPI]
|
||||
public static void SetProgramInitializationComplete()
|
||||
{
|
||||
s_ProgramInitializationSection.Enter();
|
||||
|
||||
try
|
||||
{
|
||||
if (s_ProgramInitializationComplete)
|
||||
return;
|
||||
|
||||
s_ProgramInitializationComplete = true;
|
||||
}
|
||||
finally
|
||||
{
|
||||
s_ProgramInitializationSection.Leave();
|
||||
}
|
||||
|
||||
OnProgramInitializationComplete.Raise(null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets UTC time
|
||||
/// Uses GetLocalTime so Crestron Env will have ms percision
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public static DateTime GetUtcTime()
|
||||
{
|
||||
return GetLocalTime().ToUniversalTime();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,13 +25,12 @@ namespace ICD.Common.Utils
|
||||
|
||||
try
|
||||
{
|
||||
message = eConsoleColor.Red.FormatAnsi(message);
|
||||
|
||||
#if SIMPLSHARP
|
||||
message = FormatConsoleColor(message, ConsoleColorExtensions.CONSOLE_RED);
|
||||
ErrorLog.Error(message);
|
||||
#else
|
||||
System.Console.ForegroundColor = ConsoleColor.Red;
|
||||
System.Console.Error.WriteLine(message);
|
||||
System.Console.ResetColor();
|
||||
Console.Error.WriteLine("Error - {0} - {1}", IcdEnvironment.GetLocalTime(), message);
|
||||
#endif
|
||||
}
|
||||
finally
|
||||
@@ -53,13 +52,13 @@ namespace ICD.Common.Utils
|
||||
|
||||
try
|
||||
{
|
||||
message = eConsoleColor.Yellow.FormatAnsi(message);
|
||||
|
||||
#if SIMPLSHARP
|
||||
message = FormatConsoleColor(message, ConsoleColorExtensions.CONSOLE_YELLOW);
|
||||
|
||||
ErrorLog.Warn(message);
|
||||
#else
|
||||
System.Console.ForegroundColor = ConsoleColor.Yellow;
|
||||
System.Console.Error.WriteLine(message);
|
||||
System.Console.ResetColor();
|
||||
Console.Error.WriteLine("Warn - {0} - {1}", IcdEnvironment.GetLocalTime(), message);
|
||||
#endif
|
||||
}
|
||||
finally
|
||||
@@ -81,13 +80,12 @@ namespace ICD.Common.Utils
|
||||
|
||||
try
|
||||
{
|
||||
message = eConsoleColor.Blue.FormatAnsi(message);
|
||||
|
||||
#if SIMPLSHARP
|
||||
message = FormatConsoleColor(message, ConsoleColorExtensions.CONSOLE_BLUE);
|
||||
ErrorLog.Notice(message);
|
||||
#else
|
||||
System.Console.ForegroundColor = ConsoleColor.Blue;
|
||||
System.Console.Error.WriteLine(message);
|
||||
System.Console.ResetColor();
|
||||
Console.Error.WriteLine("Notice - {0} - {1}", IcdEnvironment.GetLocalTime(), message);
|
||||
#endif
|
||||
}
|
||||
finally
|
||||
@@ -109,13 +107,12 @@ namespace ICD.Common.Utils
|
||||
|
||||
try
|
||||
{
|
||||
message = eConsoleColor.Green.FormatAnsi(message);
|
||||
|
||||
#if SIMPLSHARP
|
||||
message = FormatConsoleColor(message, ConsoleColorExtensions.CONSOLE_GREEN);
|
||||
ErrorLog.Ok(message);
|
||||
#else
|
||||
System.Console.ForegroundColor = ConsoleColor.Green;
|
||||
System.Console.Error.WriteLine(message);
|
||||
System.Console.ResetColor();
|
||||
Console.Error.WriteLine("OK - {0} - {1}", IcdEnvironment.GetLocalTime(), message);
|
||||
#endif
|
||||
}
|
||||
finally
|
||||
@@ -137,15 +134,17 @@ namespace ICD.Common.Utils
|
||||
|
||||
try
|
||||
{
|
||||
#if !SIMPLSHARP
|
||||
message = string.Format("{0}: {1}", ex.GetType().Name, message);
|
||||
#endif
|
||||
|
||||
message = eConsoleColor.YellowOnRed.FormatAnsi(message);
|
||||
|
||||
#if SIMPLSHARP
|
||||
message = FormatConsoleColor(message, ConsoleColorExtensions.CONSOLE_YELLOW_ON_RED_BACKGROUND);
|
||||
ErrorLog.Exception(message, ex);
|
||||
#else
|
||||
System.Console.ForegroundColor = ConsoleColor.Yellow;
|
||||
System.Console.BackgroundColor = ConsoleColor.Red;
|
||||
System.Console.Error.WriteLine("{0}: {1}", ex.GetType().Name, message);
|
||||
System.Console.ResetColor();
|
||||
System.Console.Error.WriteLine(ex.StackTrace);
|
||||
Console.Error.WriteLine("Except - {0} - {1}", IcdEnvironment.GetLocalTime(), message);
|
||||
Console.Error.WriteLine(ex.StackTrace);
|
||||
#endif
|
||||
}
|
||||
finally
|
||||
@@ -168,13 +167,12 @@ namespace ICD.Common.Utils
|
||||
|
||||
try
|
||||
{
|
||||
message = eConsoleColor.Cyan.FormatAnsi(message);
|
||||
|
||||
#if SIMPLSHARP
|
||||
message = FormatConsoleColor(message, ConsoleColorExtensions.CONSOLE_CYAN);
|
||||
ErrorLog.Info(message);
|
||||
#else
|
||||
System.Console.ForegroundColor = ConsoleColor.Cyan;
|
||||
System.Console.Error.WriteLine(message);
|
||||
System.Console.ResetColor();
|
||||
Console.Error.WriteLine("Info - {0} - {1}", IcdEnvironment.GetLocalTime(), message);
|
||||
#endif
|
||||
}
|
||||
finally
|
||||
@@ -188,16 +186,5 @@ namespace ICD.Common.Utils
|
||||
{
|
||||
Info(string.Format(message, args));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Formats the text with the given console color.
|
||||
/// </summary>
|
||||
/// <param name="text"></param>
|
||||
/// <param name="color"></param>
|
||||
/// <returns></returns>
|
||||
private static string FormatConsoleColor(string text, string color)
|
||||
{
|
||||
return string.Format("{0}{1}{2}", color, text, ConsoleColorExtensions.CONSOLE_RESET);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ using System.Linq;
|
||||
#endif
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using ICD.Common.Properties;
|
||||
using ICD.Common.Utils.Extensions;
|
||||
|
||||
namespace ICD.Common.Utils
|
||||
@@ -13,6 +14,8 @@ namespace ICD.Common.Utils
|
||||
/// </summary>
|
||||
public sealed class IcdUriBuilder
|
||||
{
|
||||
private string m_Query;
|
||||
|
||||
#region Properties
|
||||
|
||||
/// <summary>
|
||||
@@ -43,7 +46,7 @@ namespace ICD.Common.Utils
|
||||
/// <summary>
|
||||
/// Gets or sets any query information included in the URI.
|
||||
/// </summary>
|
||||
public string Query { get; set; }
|
||||
public string Query { get { return string.IsNullOrEmpty(m_Query) ? string.Empty : "?" + m_Query; } set { m_Query = value; } }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the scheme name of the URI.
|
||||
@@ -83,7 +86,7 @@ namespace ICD.Common.Utils
|
||||
/// Constructor.
|
||||
/// </summary>
|
||||
/// <param name="uri"></param>
|
||||
public IcdUriBuilder(Uri uri)
|
||||
public IcdUriBuilder([NotNull] Uri uri)
|
||||
{
|
||||
if (uri == null)
|
||||
throw new ArgumentNullException("uri");
|
||||
@@ -96,7 +99,7 @@ namespace ICD.Common.Utils
|
||||
Password = uri.GetPassword();
|
||||
Path = uri.AbsolutePath;
|
||||
Port = (ushort)uri.Port;
|
||||
Query = uri.Query;
|
||||
Query = uri.Query.TrimStart('?');
|
||||
Scheme = uri.Scheme;
|
||||
UserName = uri.GetUserName();
|
||||
}
|
||||
@@ -149,10 +152,7 @@ namespace ICD.Common.Utils
|
||||
|
||||
// Query
|
||||
if (!string.IsNullOrEmpty(Query))
|
||||
{
|
||||
builder.Append('?');
|
||||
builder.Append(Query);
|
||||
}
|
||||
|
||||
// Fragment
|
||||
if (!string.IsNullOrEmpty(Fragment))
|
||||
|
||||
@@ -103,7 +103,10 @@ namespace ICD.Common.Utils.Json
|
||||
if (serializer == null)
|
||||
throw new ArgumentNullException("serializer");
|
||||
|
||||
return ReadJson(reader, (T)existingValue, serializer);
|
||||
// Casting null blows up struct casts
|
||||
T cast = (T)(existingValue ?? default(T));
|
||||
|
||||
return ReadJson(reader, cast, serializer);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
34
ICD.Common.Utils/Json/DateTimeIsoConverter.cs
Normal file
34
ICD.Common.Utils/Json/DateTimeIsoConverter.cs
Normal file
@@ -0,0 +1,34 @@
|
||||
using System;
|
||||
using ICD.Common.Utils.Extensions;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace ICD.Common.Utils.Json
|
||||
{
|
||||
public sealed class DateTimeIsoConverter : AbstractGenericJsonConverter<DateTime>
|
||||
{
|
||||
/// <summary>
|
||||
/// Writes the JSON representation of the object.
|
||||
/// </summary>
|
||||
/// <param name="writer">The <see cref="T:Newtonsoft.Json.JsonWriter"/> to write to.</param>
|
||||
/// <param name="value">The value.</param>
|
||||
/// <param name="serializer">The calling serializer.</param>
|
||||
public override void WriteJson(JsonWriter writer, DateTime value, JsonSerializer serializer)
|
||||
{
|
||||
writer.WriteDateTime(value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads the JSON representation of the object.
|
||||
/// </summary>
|
||||
/// <param name="reader">The <see cref="T:Newtonsoft.Json.JsonReader"/> to read from.</param>
|
||||
/// <param name="existingValue">The existing value of object being read.</param>
|
||||
/// <param name="serializer">The calling serializer.</param>
|
||||
/// <returns>
|
||||
/// The object value.
|
||||
/// </returns>
|
||||
public override DateTime ReadJson(JsonReader reader, DateTime existingValue, JsonSerializer serializer)
|
||||
{
|
||||
return reader.GetValueAsDateTime();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,97 +1,97 @@
|
||||
using System;
|
||||
using System.Text.RegularExpressions;
|
||||
using ICD.Common.Properties;
|
||||
using ICD.Common.Utils.Extensions;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
namespace ICD.Common.Utils.Json
|
||||
{
|
||||
/// <summary>
|
||||
/// Simple wrapper for serialization of an object and its type.
|
||||
/// </summary>
|
||||
[JsonConverter(typeof(JsonItemWrapperConverter))]
|
||||
public sealed class JsonItemWrapper
|
||||
{
|
||||
private const string TYPE_TOKEN = "t";
|
||||
private const string ITEM_TOKEN = "i";
|
||||
|
||||
private readonly object m_Item;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Type of the item. Returns null if the item is null.
|
||||
/// </summary>
|
||||
public Type ItemType { get { return m_Item == null ? null : m_Item.GetType(); } }
|
||||
[CanBeNull]
|
||||
public Type Type { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the wrapped item.
|
||||
/// </summary>
|
||||
public object Item { get { return m_Item; } }
|
||||
[CanBeNull]
|
||||
public object Item { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Constructor.
|
||||
/// </summary>
|
||||
public JsonItemWrapper()
|
||||
: this(null)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructor.
|
||||
/// </summary>
|
||||
/// <param name="item"></param>
|
||||
public JsonItemWrapper(object item)
|
||||
public JsonItemWrapper([CanBeNull] object item)
|
||||
{
|
||||
m_Item = item;
|
||||
Item = item;
|
||||
Type = item == null ? null : item.GetType();
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class JsonItemWrapperConverter : AbstractGenericJsonConverter<JsonItemWrapper>
|
||||
{
|
||||
private const string TYPE_TOKEN = "t";
|
||||
private const string ITEM_TOKEN = "i";
|
||||
|
||||
/// <summary>
|
||||
/// Writes the JsonItemWrapper as a JObject.
|
||||
/// Override to write properties to the writer.
|
||||
/// </summary>
|
||||
/// <param name="writer"></param>
|
||||
public void Write(JsonWriter writer)
|
||||
/// <param name="value"></param>
|
||||
/// <param name="serializer"></param>
|
||||
protected override void WriteProperties(JsonWriter writer, JsonItemWrapper value, JsonSerializer serializer)
|
||||
{
|
||||
if (writer == null)
|
||||
throw new ArgumentNullException("writer");
|
||||
base.WriteProperties(writer, value, serializer);
|
||||
|
||||
writer.WriteStartObject();
|
||||
if (value.Type != null)
|
||||
writer.WriteProperty(TYPE_TOKEN, value.Type.GetMinimalName());
|
||||
|
||||
if (value.Item != null)
|
||||
{
|
||||
writer.WritePropertyName(TYPE_TOKEN);
|
||||
writer.WriteType(ItemType);
|
||||
|
||||
writer.WritePropertyName(ITEM_TOKEN);
|
||||
writer.WriteValue(JsonConvert.SerializeObject(m_Item));
|
||||
serializer.Serialize(writer, value.Item);
|
||||
}
|
||||
writer.WriteEndObject();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads the JToken back to the wrapped object.
|
||||
/// Override to handle the current property value with the given name.
|
||||
/// </summary>
|
||||
/// <param name="token"></param>
|
||||
/// <returns></returns>
|
||||
public static object ReadToObject(JToken token)
|
||||
/// <param name="property"></param>
|
||||
/// <param name="reader"></param>
|
||||
/// <param name="instance"></param>
|
||||
/// <param name="serializer"></param>
|
||||
protected override void ReadProperty(string property, JsonReader reader, JsonItemWrapper instance, JsonSerializer serializer)
|
||||
{
|
||||
if (token == null)
|
||||
throw new ArgumentNullException("token");
|
||||
|
||||
string typeString = (string)token.SelectToken(TYPE_TOKEN);
|
||||
if (string.IsNullOrEmpty(typeString))
|
||||
return null;
|
||||
|
||||
string itemString = (string)token.SelectToken(ITEM_TOKEN);
|
||||
Type type = Type.GetType(typeString);
|
||||
|
||||
if (type == null)
|
||||
switch (property)
|
||||
{
|
||||
typeString = typeString.Replace("_SimplSharp", "").Replace("_NetStandard", "");
|
||||
type = Type.GetType(typeString);
|
||||
case TYPE_TOKEN:
|
||||
instance.Type = reader.TokenType == JsonToken.Null ? null : reader.GetValueAsType();
|
||||
break;
|
||||
|
||||
case ITEM_TOKEN:
|
||||
if (instance.Type == null && reader.TokenType != JsonToken.Null)
|
||||
throw new FormatException("No Type for associated Item");
|
||||
instance.Item = serializer.Deserialize(reader, instance.Type);
|
||||
break;
|
||||
|
||||
default:
|
||||
base.ReadProperty(property, reader, instance, serializer);
|
||||
break;
|
||||
}
|
||||
|
||||
if (type == null)
|
||||
{
|
||||
typeString = AddSimplSharpSuffix(typeString);
|
||||
type = Type.GetType(typeString);
|
||||
}
|
||||
|
||||
return JsonConvert.DeserializeObject(itemString, type);
|
||||
}
|
||||
|
||||
private static string AddSimplSharpSuffix(string typeString)
|
||||
{
|
||||
return Regex.Replace(typeString,
|
||||
"(?'prefix'[^,]+, )(?'assembly'[^,]*)(?'suffix', .*)",
|
||||
"${prefix}${assembly}_SimplSharp${suffix}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,6 @@ using ICD.Common.Properties;
|
||||
using ICD.Common.Utils.Extensions;
|
||||
using ICD.Common.Utils.IO;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
namespace ICD.Common.Utils.Json
|
||||
{
|
||||
@@ -18,56 +17,33 @@ namespace ICD.Common.Utils.Json
|
||||
private const string MESSAGE_NAME_PROPERTY = "m";
|
||||
private const string MESSAGE_DATA_PROPERTY = "d";
|
||||
|
||||
/// <summary>
|
||||
/// Gets the data as a DateTime value.
|
||||
/// </summary>
|
||||
/// <param name="data"></param>
|
||||
/// <returns></returns>
|
||||
public static DateTime ParseDateTime(string data)
|
||||
{
|
||||
return DateTime.Parse(data);
|
||||
}
|
||||
private static JsonSerializerSettings s_CommonSettings;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the token as a DateTime value.
|
||||
/// Gets the common JSON serializer settings for cross-platform support.
|
||||
/// </summary>
|
||||
/// <param name="token"></param>
|
||||
/// <returns></returns>
|
||||
[PublicAPI]
|
||||
public static DateTime ParseDateTime(JToken token)
|
||||
public static JsonSerializerSettings CommonSettings
|
||||
{
|
||||
if (token == null)
|
||||
throw new ArgumentNullException("token");
|
||||
|
||||
return ParseDateTime((string)token);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the token as a DateTime value.
|
||||
/// </summary>
|
||||
/// <param name="token"></param>
|
||||
/// <param name="output"></param>
|
||||
/// <returns></returns>
|
||||
[PublicAPI]
|
||||
public static bool TryParseDateTime(JToken token, out DateTime output)
|
||||
{
|
||||
if (token == null)
|
||||
throw new ArgumentNullException("token");
|
||||
|
||||
output = default(DateTime);
|
||||
|
||||
try
|
||||
get
|
||||
{
|
||||
output = ParseDateTime(token);
|
||||
return true;
|
||||
}
|
||||
catch (FormatException)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
catch (InvalidCastException)
|
||||
{
|
||||
return false;
|
||||
if (s_CommonSettings != null)
|
||||
return s_CommonSettings;
|
||||
|
||||
s_CommonSettings = new JsonSerializerSettings
|
||||
{
|
||||
#if !SIMPLSHARP
|
||||
// Turn off the ridiculous new behaviour of DateTiming anything vaguely resembling a date
|
||||
DateParseHandling = DateParseHandling.None,
|
||||
#endif
|
||||
};
|
||||
|
||||
// Serialize DateTimes to ISO
|
||||
s_CommonSettings.Converters.Add(new DateTimeIsoConverter());
|
||||
|
||||
// Minify Type serialization
|
||||
s_CommonSettings.Converters.Add(new MinimalTypeConverter());
|
||||
|
||||
return s_CommonSettings;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -79,7 +55,7 @@ namespace ICD.Common.Utils.Json
|
||||
[PublicAPI]
|
||||
public static string Format(object value)
|
||||
{
|
||||
string serial = JsonConvert.SerializeObject(value);
|
||||
string serial = JsonConvert.SerializeObject(value, Formatting.None, CommonSettings);
|
||||
return Format(serial);
|
||||
}
|
||||
|
||||
|
||||
34
ICD.Common.Utils/Json/MinimalTypeConverter.cs
Normal file
34
ICD.Common.Utils/Json/MinimalTypeConverter.cs
Normal file
@@ -0,0 +1,34 @@
|
||||
using System;
|
||||
using ICD.Common.Utils.Extensions;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace ICD.Common.Utils.Json
|
||||
{
|
||||
public sealed class MinimalTypeConverter : AbstractGenericJsonConverter<Type>
|
||||
{
|
||||
/// <summary>
|
||||
/// Writes the JSON representation of the object.
|
||||
/// </summary>
|
||||
/// <param name="writer">The <see cref="T:Newtonsoft.Json.JsonWriter"/> to write to.</param>
|
||||
/// <param name="value">The value.</param>
|
||||
/// <param name="serializer">The calling serializer.</param>
|
||||
public override void WriteJson(JsonWriter writer, Type value, JsonSerializer serializer)
|
||||
{
|
||||
writer.WriteType(value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads the JSON representation of the object.
|
||||
/// </summary>
|
||||
/// <param name="reader">The <see cref="T:Newtonsoft.Json.JsonReader"/> to read from.</param>
|
||||
/// <param name="existingValue">The existing value of object being read.</param>
|
||||
/// <param name="serializer">The calling serializer.</param>
|
||||
/// <returns>
|
||||
/// The object value.
|
||||
/// </returns>
|
||||
public override Type ReadJson(JsonReader reader, Type existingValue, JsonSerializer serializer)
|
||||
{
|
||||
return reader.GetValueAsType();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -43,12 +43,19 @@ namespace ICD.Common.Utils.Json
|
||||
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
|
||||
{
|
||||
MethodInfo parse = GetParseMethod(objectType);
|
||||
if (parse != null)
|
||||
return parse.Invoke(null, new[] {reader.Value});
|
||||
|
||||
throw new ArgumentException(
|
||||
if (parse == null)
|
||||
throw new ArgumentException(
|
||||
string.Format("{0} does not have a 'static {0} Parse(string)' method.", objectType.Name),
|
||||
"objectType");
|
||||
|
||||
try
|
||||
{
|
||||
return parse.Invoke(null, new[] { reader.Value });
|
||||
}
|
||||
catch (TargetInvocationException e)
|
||||
{
|
||||
throw e.InnerException;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -10,6 +10,18 @@ namespace ICD.Common.Utils
|
||||
/// </summary>
|
||||
public static class MathUtils
|
||||
{
|
||||
/// <summary>
|
||||
/// Clamps the number between the two values.
|
||||
/// </summary>
|
||||
/// <param name="number"></param>
|
||||
/// <param name="min"></param>
|
||||
/// <param name="max"></param>
|
||||
/// <returns></returns>
|
||||
public static byte Clamp(byte number, byte min, byte max)
|
||||
{
|
||||
return (byte)Clamp((double)number, min, max);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clamps the number between the two values.
|
||||
/// </summary>
|
||||
@@ -72,12 +84,30 @@ namespace ICD.Common.Utils
|
||||
public static double MapRange(double inputStart, double inputEnd, double outputStart, double outputEnd, double value)
|
||||
{
|
||||
if (inputStart.Equals(inputEnd))
|
||||
throw new DivideByZeroException();
|
||||
return outputStart;
|
||||
|
||||
double slope = (outputEnd - outputStart) / (inputEnd - inputStart);
|
||||
return outputStart + slope * (value - inputStart);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the value after the input range has been mapped to a new range
|
||||
/// </summary>
|
||||
/// <param name="inputStart">Input start.</param>
|
||||
/// <param name="inputEnd">Input end.</param>
|
||||
/// <param name="outputStart">Output start.</param>
|
||||
/// <param name="outputEnd">Output end.</param>
|
||||
/// <param name="value">Value.</param>
|
||||
/// <returns>The newly mapped value</returns>
|
||||
public static decimal MapRange(decimal inputStart, decimal inputEnd, decimal outputStart, decimal outputEnd, decimal value)
|
||||
{
|
||||
if (inputStart.Equals(inputEnd))
|
||||
return outputStart;
|
||||
|
||||
decimal slope = (outputEnd - outputStart) / (inputEnd - inputStart);
|
||||
return outputStart + slope * (value - inputStart);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the value after the input range has been mapped to a new range
|
||||
/// </summary>
|
||||
@@ -191,5 +221,55 @@ namespace ICD.Common.Utils
|
||||
|
||||
return nearest.Aggregate((x, y) => Math.Abs(x - number) < Math.Abs(y - number) ? x : y);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calculates the modulus of the given number.
|
||||
/// </summary>
|
||||
/// <param name="number"></param>
|
||||
/// <param name="mod"></param>
|
||||
/// <returns></returns>
|
||||
/// <remarks>Method name can't be "Mod", due to S+ compatibility issues</remarks>
|
||||
public static int Modulus(int number, int mod)
|
||||
{
|
||||
int remainder = number % mod;
|
||||
return remainder < 0 ? remainder + mod : remainder;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calculates the modulus of the given number.
|
||||
/// </summary>
|
||||
/// <param name="number"></param>
|
||||
/// <param name="mod"></param>
|
||||
/// <returns></returns>
|
||||
/// <remarks>Method name can't be "Mod", due to S+ compatibility issues</remarks>
|
||||
public static long Modulus(long number, long mod)
|
||||
{
|
||||
long remainder = number % mod;
|
||||
return remainder < 0 ? remainder + mod : remainder;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts the value to a percentage.
|
||||
/// </summary>
|
||||
/// <param name="min"></param>
|
||||
/// <param name="max"></param>
|
||||
/// <param name="value"></param>
|
||||
/// <returns></returns>
|
||||
public static float ToPercent(float min, float max, float value)
|
||||
{
|
||||
return MapRange(min, max, 0.0f, 1.0f, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts the value from a percentage.
|
||||
/// </summary>
|
||||
/// <param name="min"></param>
|
||||
/// <param name="max"></param>
|
||||
/// <param name="percent"></param>
|
||||
/// <returns></returns>
|
||||
public static float FromPercent(float min, float max, float percent)
|
||||
{
|
||||
return MapRange(0.0f, 1.0f, min, max, percent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
121
ICD.Common.Utils/NullObject.cs
Normal file
121
ICD.Common.Utils/NullObject.cs
Normal file
@@ -0,0 +1,121 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace ICD.Common.Utils
|
||||
{
|
||||
/// <summary>
|
||||
/// Convenience wrapper for supporting null keys in hash tables.
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
public struct NullObject<T> : IEquatable<NullObject<T>>, IComparable<NullObject<T>>
|
||||
{
|
||||
#region Properties
|
||||
|
||||
public T Item { get; private set; }
|
||||
|
||||
public bool IsNull { get; private set; }
|
||||
|
||||
public static NullObject<T> Null { get { return new NullObject<T>(); } }
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
|
||||
/// <summary>
|
||||
/// Constructor.
|
||||
/// </summary>
|
||||
/// <param name="item"></param>
|
||||
public NullObject(T item)
|
||||
// ReSharper disable CompareNonConstrainedGenericWithNull
|
||||
: this(item, item == null)
|
||||
// ReSharper restore CompareNonConstrainedGenericWithNull
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructor.
|
||||
/// </summary>
|
||||
/// <param name="item"></param>
|
||||
/// <param name="isnull"></param>
|
||||
private NullObject(T item, bool isnull)
|
||||
: this()
|
||||
{
|
||||
IsNull = isnull;
|
||||
Item = item;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
// ReSharper disable CompareNonConstrainedGenericWithNull
|
||||
return Item == null ? "NULL" : Item.ToString();
|
||||
// ReSharper restore CompareNonConstrainedGenericWithNull
|
||||
}
|
||||
|
||||
#region Casting
|
||||
|
||||
public static implicit operator T(NullObject<T> nullObject)
|
||||
{
|
||||
return nullObject.Item;
|
||||
}
|
||||
|
||||
public static implicit operator NullObject<T>(T item)
|
||||
{
|
||||
return new NullObject<T>(item);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Equality
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
if (obj == null)
|
||||
return IsNull;
|
||||
|
||||
if (!(obj is NullObject<T>))
|
||||
return false;
|
||||
|
||||
return Equals((NullObject<T>)obj);
|
||||
}
|
||||
|
||||
public bool Equals(NullObject<T> other)
|
||||
{
|
||||
if (IsNull)
|
||||
return other.IsNull;
|
||||
|
||||
return !other.IsNull && Item.Equals(other.Item);
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
if (IsNull)
|
||||
return 0;
|
||||
|
||||
var result = Item.GetHashCode();
|
||||
|
||||
if (result >= 0)
|
||||
result++;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Comparable
|
||||
|
||||
public int CompareTo(NullObject<T> other)
|
||||
{
|
||||
if (IsNull && other.IsNull)
|
||||
return 0;
|
||||
|
||||
if (IsNull)
|
||||
return -1;
|
||||
|
||||
return Comparer<T>.Default.Compare(Item, other.Item);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -48,7 +48,7 @@ namespace ICD.Common.Utils
|
||||
#elif LINUX
|
||||
return Join(RootPath, "opt", "ICD.Connect");
|
||||
#else
|
||||
return Join(RootPath, "ProgramData", "ICD.Connect");
|
||||
return Join(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData), "ICD.Connect");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@@ -58,29 +58,60 @@ namespace ICD.Common.Utils
|
||||
/// </summary>
|
||||
/// <value></value>
|
||||
[PublicAPI]
|
||||
public static string ProgramConfigPath
|
||||
public static string ProgramConfigPath { get { return Join(RootConfigPath, ProgramConfigDirectory); } }
|
||||
|
||||
/// <summary>
|
||||
/// Returns the name of the program config directory.
|
||||
/// </summary>
|
||||
[PublicAPI]
|
||||
public static string ProgramConfigDirectory
|
||||
{
|
||||
get
|
||||
{
|
||||
string directoryName;
|
||||
|
||||
switch (IcdEnvironment.RuntimeEnvironment)
|
||||
{
|
||||
case IcdEnvironment.eRuntimeEnvironment.SimplSharp:
|
||||
case IcdEnvironment.eRuntimeEnvironment.SimplSharpPro:
|
||||
case IcdEnvironment.eRuntimeEnvironment.Standard:
|
||||
directoryName = string.Format("Program{0:D2}Config", ProgramUtils.ProgramNumber);
|
||||
break;
|
||||
return string.Format("Program{0:D2}Config", ProgramUtils.ProgramNumber);
|
||||
|
||||
case IcdEnvironment.eRuntimeEnvironment.SimplSharpProMono:
|
||||
directoryName = "ProgramConfig";
|
||||
break;
|
||||
return "ProgramConfig";
|
||||
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Join(RootConfigPath, directoryName);
|
||||
/// <summary>
|
||||
/// Returns the absolute path to the program data directory.
|
||||
/// </summary>
|
||||
/// <value></value>
|
||||
[PublicAPI]
|
||||
public static string ProgramDataPath { get { return Join(RootConfigPath, ProgramDataDirectory); } }
|
||||
|
||||
/// <summary>
|
||||
/// Returns the name of the program data directory.
|
||||
/// This directory contains runtime program data that should be retained through deployments.
|
||||
/// </summary>
|
||||
public static string ProgramDataDirectory
|
||||
{
|
||||
get
|
||||
{
|
||||
switch (IcdEnvironment.RuntimeEnvironment)
|
||||
{
|
||||
case IcdEnvironment.eRuntimeEnvironment.SimplSharp:
|
||||
case IcdEnvironment.eRuntimeEnvironment.SimplSharpPro:
|
||||
case IcdEnvironment.eRuntimeEnvironment.Standard:
|
||||
return string.Format("Program{0:D2}Data", ProgramUtils.ProgramNumber);
|
||||
|
||||
case IcdEnvironment.eRuntimeEnvironment.SimplSharpProMono:
|
||||
return "ProgramData";
|
||||
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -88,7 +119,10 @@ namespace ICD.Common.Utils
|
||||
/// Returns the absolute path to the common configuration directory.
|
||||
/// </summary>
|
||||
[PublicAPI]
|
||||
public static string CommonConfigPath { get { return Join(RootConfigPath, "CommonConfig"); } }
|
||||
public static string CommonConfigPath { get { return Join(RootConfigPath, CommonConfigDirectory); } }
|
||||
|
||||
[PublicAPI]
|
||||
public static string CommonConfigDirectory { get { return "CommonConfig"; }}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the absolute path to the common config library directory.
|
||||
@@ -133,6 +167,37 @@ namespace ICD.Common.Utils
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the absolute path to the control system web server directory.
|
||||
/// </summary>
|
||||
/// <value></value>
|
||||
[PublicAPI]
|
||||
public static string WebServerPath
|
||||
{
|
||||
get
|
||||
{
|
||||
switch (IcdEnvironment.RuntimeEnvironment)
|
||||
{
|
||||
case IcdEnvironment.eRuntimeEnvironment.SimplSharp:
|
||||
case IcdEnvironment.eRuntimeEnvironment.SimplSharpPro:
|
||||
return Join(RootPath, "HTML");
|
||||
|
||||
case IcdEnvironment.eRuntimeEnvironment.SimplSharpProMono:
|
||||
return Join(RootPath, "Html");
|
||||
|
||||
case IcdEnvironment.eRuntimeEnvironment.Standard:
|
||||
#if LINUX
|
||||
return Join(RootPath, "var", "www", "html");
|
||||
#else
|
||||
return "C:\\INetPub";
|
||||
#endif
|
||||
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
@@ -144,6 +209,9 @@ namespace ICD.Common.Utils
|
||||
/// <returns></returns>
|
||||
public static string Join(params string[] items)
|
||||
{
|
||||
if (items == null)
|
||||
throw new ArgumentNullException("items");
|
||||
|
||||
return items.Length > 1
|
||||
? items.Skip(1).Aggregate(items.First(), IcdPath.Combine)
|
||||
: items.FirstOrDefault(string.Empty);
|
||||
@@ -209,6 +277,9 @@ namespace ICD.Common.Utils
|
||||
[PublicAPI]
|
||||
public static string GetDefaultConfigPath(params string[] localPath)
|
||||
{
|
||||
if (localPath == null)
|
||||
throw new ArgumentNullException("localPath");
|
||||
|
||||
string local = Join(localPath);
|
||||
|
||||
// Program slot configuration
|
||||
@@ -230,6 +301,9 @@ namespace ICD.Common.Utils
|
||||
/// <returns></returns>
|
||||
public static string GetCommonConfigPath(params string[] localPath)
|
||||
{
|
||||
if (localPath == null)
|
||||
throw new ArgumentNullException("localPath");
|
||||
|
||||
string local = Join(localPath);
|
||||
return Join(CommonConfigPath, local);
|
||||
}
|
||||
@@ -240,10 +314,109 @@ namespace ICD.Common.Utils
|
||||
/// <returns></returns>
|
||||
public static string GetProgramConfigPath(params string[] localPath)
|
||||
{
|
||||
if (localPath == null)
|
||||
throw new ArgumentNullException("localPath");
|
||||
|
||||
string local = Join(localPath);
|
||||
return Join(ProgramConfigPath, local);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Appends the local path to the program data path.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public static string GetProgramDataPath(params string[] localPath)
|
||||
{
|
||||
if (localPath == null)
|
||||
throw new ArgumentNullException("localPath");
|
||||
|
||||
string local = Join(localPath);
|
||||
return Join(ProgramDataPath, local);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Appends the local path to the room data path.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public static string GetRoomDataPath(int roomId, params string[] localPath)
|
||||
{
|
||||
if (localPath == null)
|
||||
throw new ArgumentNullException("localPath");
|
||||
|
||||
string local = Join(localPath);
|
||||
string roomDataDirectory = GetRoomDataDirectory(roomId);
|
||||
return Join(ProgramDataPath, roomDataDirectory, local);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the directory name of the room data directory for the room with the given id.
|
||||
/// </summary>
|
||||
/// <param name="roomId"></param>
|
||||
/// <returns></returns>
|
||||
public static string GetRoomDataDirectory(int roomId)
|
||||
{
|
||||
return string.Format("Room{0}Data", roomId);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Appends the local path to the user data path.
|
||||
/// </summary>
|
||||
/// <param name="userName"></param>
|
||||
/// <param name="localPath"></param>
|
||||
/// <returns></returns>
|
||||
public static string GetUserDataPath(string userName, params string[] localPath)
|
||||
{
|
||||
if (localPath == null)
|
||||
throw new ArgumentNullException("localPath");
|
||||
|
||||
string local = Join(localPath);
|
||||
string userDataDirectory = GetUserDataDirectory(userName);
|
||||
return Join(ProgramDataPath, userDataDirectory, local);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the directory name of the user data directory for the user with the given name.
|
||||
/// </summary>
|
||||
/// <param name="userName"></param>
|
||||
/// <returns></returns>
|
||||
public static string GetUserDataDirectory(string userName)
|
||||
{
|
||||
return string.Format("User{0}Data", StringUtils.RemoveWhitespace(userName));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Appends the local path to the web server path.
|
||||
/// </summary>
|
||||
/// <param name="localPath"></param>
|
||||
/// <returns></returns>
|
||||
public static string GetWebServerPath(params string[] localPath)
|
||||
{
|
||||
if (localPath == null)
|
||||
throw new ArgumentNullException("localPath");
|
||||
|
||||
string local = Join(localPath);
|
||||
return Join(WebServerPath, local);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the URL to the resource at the given web server path.
|
||||
/// </summary>
|
||||
/// <param name="webServerPath"></param>
|
||||
/// <returns></returns>
|
||||
public static string GetUrl(string webServerPath)
|
||||
{
|
||||
if (webServerPath == null)
|
||||
throw new ArgumentNullException("webServerPath");
|
||||
|
||||
if (!webServerPath.StartsWith(WebServerPath))
|
||||
throw new ArgumentException("Path is not in the web server directory");
|
||||
|
||||
string local = webServerPath.Substring(WebServerPath.Length + 1)
|
||||
.Replace('\\', '/');
|
||||
|
||||
return string.Format("{0}/{1}", IcdEnvironment.NetworkAddresses.First(), local);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if the given path exists.
|
||||
/// </summary>
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using ICD.Common.Properties;
|
||||
using ICD.Common.Properties;
|
||||
using ICD.Common.Utils.Json;
|
||||
|
||||
namespace ICD.Common.Utils
|
||||
{
|
||||
@@ -13,72 +11,16 @@ namespace ICD.Common.Utils
|
||||
#region Methods
|
||||
|
||||
[PublicAPI]
|
||||
public static void PrintLine<TKey, TValue>(IDictionary<TKey, TValue> dictionary)
|
||||
public static void PrintLine([CanBeNull] object value)
|
||||
{
|
||||
if (dictionary == null)
|
||||
throw new ArgumentNullException("dictionary");
|
||||
|
||||
IcdConsole.PrintLine(ToString(dictionary));
|
||||
string serial = ToString(value);
|
||||
IcdConsole.PrintLine(serial);
|
||||
}
|
||||
|
||||
[PublicAPI]
|
||||
public static void PrintLine<T>(IEnumerable<T> sequence)
|
||||
public static string ToString([CanBeNull] object value)
|
||||
{
|
||||
if (sequence == null)
|
||||
throw new ArgumentNullException("sequence");
|
||||
|
||||
IcdConsole.PrintLine(ToString(sequence));
|
||||
}
|
||||
|
||||
[PublicAPI]
|
||||
public static string ToString<TKey, TValue>(IDictionary<TKey, TValue> dictionary)
|
||||
{
|
||||
if (dictionary == null)
|
||||
throw new ArgumentNullException("dictionary");
|
||||
|
||||
StringBuilder builder = new StringBuilder();
|
||||
builder.AppendLine("{");
|
||||
|
||||
foreach (KeyValuePair<TKey, TValue> kvp in dictionary)
|
||||
{
|
||||
builder.Append('\t');
|
||||
builder.Append(ToString(kvp.Key));
|
||||
builder.Append(" : ");
|
||||
builder.Append(ToString(kvp.Value));
|
||||
builder.Append(',');
|
||||
builder.AppendLine();
|
||||
}
|
||||
|
||||
builder.Append("}");
|
||||
return builder.ToString();
|
||||
}
|
||||
|
||||
[PublicAPI]
|
||||
public static string ToString<T>(IEnumerable<T> sequence)
|
||||
{
|
||||
if (sequence == null)
|
||||
throw new ArgumentNullException("sequence");
|
||||
|
||||
StringBuilder builder = new StringBuilder();
|
||||
builder.AppendLine("[");
|
||||
|
||||
foreach (T item in sequence)
|
||||
{
|
||||
builder.Append('\t');
|
||||
builder.Append(ToString(item));
|
||||
builder.Append(',');
|
||||
builder.AppendLine();
|
||||
}
|
||||
|
||||
builder.Append("]");
|
||||
return builder.ToString();
|
||||
}
|
||||
|
||||
[PublicAPI]
|
||||
public static string ToString<T>(T value)
|
||||
{
|
||||
// ReSharper disable once CompareNonConstrainedGenericWithNull
|
||||
return StringUtils.ToRepresentation(value == null ? null : value.ToString());
|
||||
return JsonUtils.Format(value);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
using ICD.Common.Utils.Services;
|
||||
#if SIMPLSHARP
|
||||
using System.Globalization;
|
||||
using Crestron.SimplSharp;
|
||||
using ICD.Common.Utils.Services;
|
||||
using ICD.Common.Utils.Services.Logging;
|
||||
#if SIMPLSHARP
|
||||
using System;
|
||||
using System.Text.RegularExpressions;
|
||||
using ICD.Common.Properties;
|
||||
@@ -9,14 +11,21 @@ namespace ICD.Common.Utils
|
||||
{
|
||||
public static partial class ProcessorUtils
|
||||
{
|
||||
private const string MODEL_NAME_REGEX = @"^(\S*)";
|
||||
private const string MODEL_VERSION_REGEX = @" [[]v(\S*)";
|
||||
private const string VER_REGEX =
|
||||
@"(?'model'\S+) (?'type'\S+) (?'lang'\S+) \[v(?'version'\d+.\d+.\d+.\d+) \((?'date'\S+ \d+ \d+)\), #(?'serial'[A-F0-9]+)\] @E-(?'mac'[a-z0-9]+)";
|
||||
|
||||
private const string UPTIME_COMMAND = "uptime";
|
||||
private const string PROGUPTIME_COMMAND_ROOT = "proguptime:{0}";
|
||||
private const string UPTIME_REGEX = @".*(?'uptime'(?'days'\d+) days (?'hours'\d{2}):(?'minutes'\d{2}):(?'seconds'\d{2})\.(?'milliseconds'\d+))";
|
||||
|
||||
private const string RAMFREE_COMMAND = "ramfree";
|
||||
private const string RAMFREE_DIGITS_REGEX = @"^(\d*)";
|
||||
|
||||
private static string s_VersionResult;
|
||||
|
||||
private static DateTime? s_SystemUptimeStartTimeUtc;
|
||||
private static DateTime? s_ProgramUptimeStartTimeUtc;
|
||||
|
||||
#region Properties
|
||||
|
||||
/// <summary>
|
||||
@@ -51,11 +60,11 @@ namespace ICD.Common.Utils
|
||||
string versionResult = VersionResult;
|
||||
if (!String.IsNullOrEmpty(versionResult))
|
||||
{
|
||||
Regex regex = new Regex(MODEL_NAME_REGEX);
|
||||
Regex regex = new Regex(VER_REGEX);
|
||||
Match match = regex.Match(versionResult);
|
||||
|
||||
if (match.Success)
|
||||
return match.Groups[1].Value;
|
||||
return match.Groups["model"].Value;
|
||||
}
|
||||
|
||||
ServiceProvider.TryGetService<ILoggerService>()
|
||||
@@ -75,11 +84,11 @@ namespace ICD.Common.Utils
|
||||
string versionResult = VersionResult;
|
||||
if (!String.IsNullOrEmpty(versionResult))
|
||||
{
|
||||
Regex regex = new Regex(MODEL_VERSION_REGEX);
|
||||
Regex regex = new Regex(VER_REGEX);
|
||||
Match match = regex.Match(VersionResult);
|
||||
|
||||
if (match.Success)
|
||||
return new Version(match.Groups[1].Value);
|
||||
return new Version(match.Groups["version"].Value);
|
||||
}
|
||||
|
||||
ServiceProvider.TryGetService<ILoggerService>()
|
||||
@@ -88,6 +97,39 @@ namespace ICD.Common.Utils
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the date that the firmware was updated.
|
||||
/// </summary>
|
||||
[PublicAPI]
|
||||
public static DateTime ModelVersionDate
|
||||
{
|
||||
get
|
||||
{
|
||||
Regex regex = new Regex(VER_REGEX);
|
||||
Match match = regex.Match(VersionResult);
|
||||
|
||||
if (match.Success)
|
||||
return DateTime.ParseExact(match.Groups["date"].Value, "MMM dd yyyy", CultureInfo.InvariantCulture).ToUniversalTime();
|
||||
|
||||
ServiceProvider.TryGetService<ILoggerService>()
|
||||
.AddEntry(eSeverity.Warning, "Unable to get model version date from \"{0}\"", VersionResult);
|
||||
|
||||
return DateTime.MinValue;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the serial number of the processor
|
||||
/// </summary>
|
||||
[PublicAPI]
|
||||
public static string ProcessorSerialNumber
|
||||
{
|
||||
get
|
||||
{
|
||||
return CrestronEnvironment.SystemInfo.SerialNumber;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the ram usage in the range 0 - 1.
|
||||
/// </summary>
|
||||
@@ -178,6 +220,60 @@ namespace ICD.Common.Utils
|
||||
IcdConsole.SendControlSystemCommand("reboot", ref consoleResult);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the uptime for the system
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[PublicAPI]
|
||||
public static TimeSpan GetSystemUptime()
|
||||
{
|
||||
if (s_SystemUptimeStartTimeUtc == null)
|
||||
{
|
||||
string uptime = GetSystemUptimeFeedback();
|
||||
Match match = Regex.Match(uptime, UPTIME_REGEX);
|
||||
if (!match.Success)
|
||||
return default(TimeSpan);
|
||||
|
||||
int days = int.Parse(match.Groups["days"].Value);
|
||||
int hours = int.Parse(match.Groups["hours"].Value);
|
||||
int minutes = int.Parse(match.Groups["minutes"].Value);
|
||||
int seconds = int.Parse(match.Groups["seconds"].Value);
|
||||
int milliseconds = int.Parse(match.Groups["milliseconds"].Value);
|
||||
|
||||
TimeSpan span = new TimeSpan(days, hours, minutes, seconds, milliseconds);
|
||||
s_SystemUptimeStartTimeUtc = IcdEnvironment.GetUtcTime() - span;
|
||||
}
|
||||
|
||||
return IcdEnvironment.GetUtcTime() - s_SystemUptimeStartTimeUtc.Value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the uptime of the current program.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[PublicAPI]
|
||||
public static TimeSpan GetProgramUptime()
|
||||
{
|
||||
if (s_ProgramUptimeStartTimeUtc == null)
|
||||
{
|
||||
string uptime = GetProgramUptimeFeedback((int)ProgramUtils.ProgramNumber);
|
||||
Match match = Regex.Match(uptime, UPTIME_REGEX);
|
||||
if (!match.Success)
|
||||
return default(TimeSpan);
|
||||
|
||||
int days = int.Parse(match.Groups["days"].Value);
|
||||
int hours = int.Parse(match.Groups["hours"].Value);
|
||||
int minutes = int.Parse(match.Groups["minutes"].Value);
|
||||
int seconds = int.Parse(match.Groups["seconds"].Value);
|
||||
int milliseconds = int.Parse(match.Groups["milliseconds"].Value);
|
||||
|
||||
TimeSpan span = new TimeSpan(days, hours, minutes, seconds, milliseconds);
|
||||
s_ProgramUptimeStartTimeUtc = IcdEnvironment.GetUtcTime() - span;
|
||||
}
|
||||
|
||||
return IcdEnvironment.GetUtcTime() - s_ProgramUptimeStartTimeUtc.Value;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
@@ -195,6 +291,30 @@ namespace ICD.Common.Utils
|
||||
}
|
||||
return ramfree;
|
||||
}
|
||||
|
||||
private static string GetSystemUptimeFeedback()
|
||||
{
|
||||
string uptime = null;
|
||||
if (!IcdConsole.SendControlSystemCommand(UPTIME_COMMAND, ref uptime))
|
||||
{
|
||||
ServiceProvider.TryGetService<ILoggerService>()
|
||||
.AddEntry(eSeverity.Warning, "{0} - Failed to send console command \"{1}\"",
|
||||
typeof(ProcessorUtils).Name, UPTIME_COMMAND);
|
||||
}
|
||||
return uptime;
|
||||
}
|
||||
|
||||
private static string GetProgramUptimeFeedback(int programSlot)
|
||||
{
|
||||
string uptime = null;
|
||||
if (!IcdConsole.SendControlSystemCommand(string.Format(PROGUPTIME_COMMAND_ROOT, programSlot), ref uptime))
|
||||
{
|
||||
ServiceProvider.TryGetService<ILoggerService>()
|
||||
.AddEntry(eSeverity.Warning, "{0} - Failed to send console command \"{1}\"",
|
||||
typeof(ProcessorUtils).Name, UPTIME_COMMAND);
|
||||
}
|
||||
return uptime;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -27,6 +27,32 @@ namespace ICD.Common.Utils
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the date that the firmware was updated.
|
||||
/// </summary>
|
||||
[PublicAPI]
|
||||
public static DateTime ModelVersionDate
|
||||
{
|
||||
get
|
||||
{
|
||||
// TODO
|
||||
return DateTime.MinValue;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the serial number of the processor
|
||||
/// </summary>
|
||||
[PublicAPI]
|
||||
public static string ProcessorSerialNumber
|
||||
{
|
||||
get
|
||||
{
|
||||
// TODO
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the ram usage in the range 0 - 1.
|
||||
/// </summary>
|
||||
@@ -109,6 +135,27 @@ namespace ICD.Common.Utils
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the uptime for the system
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[PublicAPI]
|
||||
public static TimeSpan GetSystemUptime()
|
||||
{
|
||||
return TimeSpan.FromMilliseconds(Environment.TickCount);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the uptime
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[PublicAPI]
|
||||
public static TimeSpan GetProgramUptime()
|
||||
{
|
||||
var current = System.Diagnostics.Process.GetCurrentProcess();
|
||||
return IcdEnvironment.GetLocalTime() - current.StartTime;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
using ICD.Common.Utils.Services;
|
||||
using System.Globalization;
|
||||
using ICD.Common.Utils.IO;
|
||||
using ICD.Common.Utils.Services;
|
||||
using ICD.Common.Utils.Services.Logging;
|
||||
#if SIMPLSHARP
|
||||
using Crestron.SimplSharp;
|
||||
@@ -40,7 +42,35 @@ namespace ICD.Common.Utils
|
||||
/// Gets the compile date of the program.
|
||||
/// </summary>
|
||||
[PublicAPI]
|
||||
public static string CompiledDate { get { return ProgComments.GetDefault(COMPILED_ON_KEY, null); } }
|
||||
public static DateTime CompiledDate
|
||||
{
|
||||
get
|
||||
{
|
||||
string dateString;
|
||||
if (!ProgComments.TryGetValue(COMPILED_ON_KEY, out dateString))
|
||||
return DateTime.MinValue;
|
||||
|
||||
// Crestron writes compile time in system local time with no sense of localization...
|
||||
try
|
||||
{
|
||||
return DateTime.Parse(dateString).ToUniversalTime();
|
||||
}
|
||||
catch (FormatException)
|
||||
{
|
||||
}
|
||||
|
||||
// Try again with dd/mm/yyyy
|
||||
try
|
||||
{
|
||||
return DateTime.ParseExact(dateString, "dd/MM/yyyy hh:mm:ss", CultureInfo.InvariantCulture).ToUniversalTime();
|
||||
}
|
||||
catch (FormatException)
|
||||
{
|
||||
}
|
||||
|
||||
return DateTime.MinValue;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the compiler revision version.
|
||||
@@ -86,6 +116,16 @@ namespace ICD.Common.Utils
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the date and time the program was installed.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[PublicAPI]
|
||||
public static DateTime ProgramInstallDate
|
||||
{
|
||||
get { return IcdFile.GetCreationTime(PathUtils.Join(PathUtils.ProgramPath, ProgramFile)).ToUniversalTime(); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parses the prog comments and pulls program information.
|
||||
/// </summary>
|
||||
|
||||
@@ -18,11 +18,11 @@ namespace ICD.Common.Utils
|
||||
/// Gets the compile date of the program.
|
||||
/// </summary>
|
||||
[PublicAPI]
|
||||
public static string CompiledDate
|
||||
public static DateTime CompiledDate
|
||||
{
|
||||
get
|
||||
{
|
||||
return IcdFile.GetLastWriteTime(Assembly.GetEntryAssembly().Location).ToString();
|
||||
return IcdFile.GetLastWriteTime(Assembly.GetEntryAssembly().Location);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,6 +55,15 @@ namespace ICD.Common.Utils
|
||||
return Assembly.GetEntryAssembly().GetName().Name;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the date and time the program was installed.
|
||||
/// </summary>
|
||||
[PublicAPI]
|
||||
public static DateTime ProgramInstallDate
|
||||
{
|
||||
get { return IcdFile.GetCreationTime(PathUtils.Join(PathUtils.ProgramPath, ProgramFile)); }
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -3,5 +3,5 @@ using System.Reflection;
|
||||
[assembly: AssemblyTitle("ICD.Common.Utils")]
|
||||
[assembly: AssemblyCompany("ICD Systems")]
|
||||
[assembly: AssemblyProduct("ICD.Common.Utils")]
|
||||
[assembly: AssemblyCopyright("Copyright © ICD Systems 2019")]
|
||||
[assembly: AssemblyVersion("9.4.0.0")]
|
||||
[assembly: AssemblyCopyright("Copyright © ICD Systems 2020")]
|
||||
[assembly: AssemblyVersion("12.0.0.0")]
|
||||
|
||||
@@ -32,6 +32,24 @@ namespace ICD.Common.Utils
|
||||
.Select(node => GetClique(map, visited, node));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the clique containing the given node.
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="node"></param>
|
||||
/// <param name="getAdjacent"></param>
|
||||
/// <returns></returns>
|
||||
public static IEnumerable<T> GetClique<T>(T node, Func<T, IEnumerable<T>> getAdjacent)
|
||||
{
|
||||
if (node == null)
|
||||
throw new ArgumentNullException("node");
|
||||
|
||||
if (getAdjacent == null)
|
||||
throw new ArgumentNullException("getAdjacent");
|
||||
|
||||
return BreadthFirstSearch(node, getAdjacent);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the clique containing the given node.
|
||||
/// </summary>
|
||||
@@ -149,7 +167,7 @@ namespace ICD.Common.Utils
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns all of the nodes in the tree via breadth-first search.
|
||||
/// Returns all of the nodes in the graph via breadth-first search.
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="root"></param>
|
||||
@@ -157,6 +175,7 @@ namespace ICD.Common.Utils
|
||||
/// <returns></returns>
|
||||
private static IEnumerable<T> BreadthFirstSearchIterator<T>(T root, Func<T, IEnumerable<T>> getChildren)
|
||||
{
|
||||
IcdHashSet<T> visited = new IcdHashSet<T> {root};
|
||||
Queue<T> process = new Queue<T>();
|
||||
process.Enqueue(root);
|
||||
|
||||
@@ -165,8 +184,11 @@ namespace ICD.Common.Utils
|
||||
{
|
||||
yield return current;
|
||||
|
||||
foreach (T child in getChildren(current))
|
||||
foreach (T child in getChildren(current).Where(c => !visited.Contains(c)))
|
||||
{
|
||||
visited.Add(child);
|
||||
process.Enqueue(child);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ using System.Linq;
|
||||
using ICD.Common.Properties;
|
||||
using ICD.Common.Utils.Extensions;
|
||||
using ICD.Common.Utils.IO;
|
||||
using MethodInfoExtensions = ICD.Common.Utils.Extensions.MethodInfoExtensions;
|
||||
#if SIMPLSHARP
|
||||
using Crestron.SimplSharp.CrestronIO;
|
||||
using Crestron.SimplSharp.Reflection;
|
||||
@@ -50,13 +51,15 @@ namespace ICD.Common.Utils
|
||||
if (parameters == null)
|
||||
throw new ArgumentNullException("parameters");
|
||||
|
||||
#if SIMPLSHARP
|
||||
IEnumerable<CType>
|
||||
#else
|
||||
IEnumerable<Type>
|
||||
#endif
|
||||
parameterTypes = method.GetParameters().Select(p => p.ParameterType);
|
||||
ParameterInfo[] methodParameters = method.GetParameters();
|
||||
|
||||
// Bail early if the counts don't match
|
||||
ICollection<object> parametersCollection = parameters as ICollection<object>;
|
||||
if (parametersCollection != null && parametersCollection.Count != methodParameters.Length)
|
||||
return false;
|
||||
|
||||
// Compare the parameters to the objects
|
||||
IEnumerable<Type> parameterTypes = methodParameters.Select(p => (Type)p.ParameterType);
|
||||
return ParametersMatchTypes(parameterTypes, parameters);
|
||||
}
|
||||
|
||||
@@ -80,13 +83,7 @@ namespace ICD.Common.Utils
|
||||
/// <param name="types"></param>
|
||||
/// <param name="parameters"></param>
|
||||
/// <returns></returns>
|
||||
private static bool ParametersMatchTypes(
|
||||
#if SIMPLSHARP
|
||||
IEnumerable<CType>
|
||||
#else
|
||||
IEnumerable<Type>
|
||||
#endif
|
||||
types, IEnumerable<object> parameters)
|
||||
private static bool ParametersMatchTypes(IEnumerable<Type> types, IEnumerable<object> parameters)
|
||||
{
|
||||
if (types == null)
|
||||
throw new ArgumentNullException("types");
|
||||
@@ -94,27 +91,11 @@ namespace ICD.Common.Utils
|
||||
if (parameters == null)
|
||||
throw new ArgumentNullException("parameters");
|
||||
|
||||
return types
|
||||
#if SIMPLSHARP
|
||||
IList<CType>
|
||||
#else
|
||||
IList<Type>
|
||||
.Cast<object>()
|
||||
#endif
|
||||
typesArray = types as
|
||||
#if SIMPLSHARP
|
||||
IList<CType>
|
||||
#else
|
||||
IList<Type>
|
||||
#endif
|
||||
?? types.ToArray();
|
||||
|
||||
IList<object> parametersArray = parameters as IList<object> ?? parameters.ToArray();
|
||||
|
||||
if (parametersArray.Count != typesArray.Count)
|
||||
return false;
|
||||
|
||||
// Compares each pair of items in the two arrays.
|
||||
return !parametersArray.Where((t, index) => !ParameterMatchesType(typesArray[index], t))
|
||||
.Any();
|
||||
.SequenceEqual(parameters, (a, b) => ParameterMatchesType((Type)a, b));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -147,6 +128,7 @@ namespace ICD.Common.Utils
|
||||
/// </summary>
|
||||
/// <param name="type"></param>
|
||||
/// <returns></returns>
|
||||
[CanBeNull]
|
||||
public static object GetDefaultValue(Type type)
|
||||
{
|
||||
if (type == null)
|
||||
@@ -162,7 +144,7 @@ namespace ICD.Common.Utils
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Platform independant delegate instantiation.
|
||||
/// Platform independent delegate instantiation.
|
||||
/// </summary>
|
||||
/// <param name="type"></param>
|
||||
/// <param name="firstArgument"></param>
|
||||
@@ -219,23 +201,25 @@ namespace ICD.Common.Utils
|
||||
|
||||
if (parameters == null)
|
||||
throw new ArgumentNullException("parameters");
|
||||
|
||||
if (parameters.Length == 0)
|
||||
return Activator.CreateInstance(type);
|
||||
|
||||
ConstructorInfo constructor = GetConstructor(type, parameters);
|
||||
|
||||
try
|
||||
{
|
||||
if (parameters.Length == 0)
|
||||
return Activator.CreateInstance(type);
|
||||
|
||||
ConstructorInfo constructor = GetConstructor(type, parameters);
|
||||
return constructor.Invoke(parameters);
|
||||
}
|
||||
catch (TypeLoadException e)
|
||||
catch (Exception e)
|
||||
{
|
||||
throw e.GetBaseException();
|
||||
}
|
||||
catch (TargetInvocationException e)
|
||||
{
|
||||
throw e.GetBaseException();
|
||||
// Crestron sandbox doesn't let us reference System.Reflection types...
|
||||
switch (e.GetType().Name)
|
||||
{
|
||||
case "TypeLoadException":
|
||||
case "TargetInvocationException":
|
||||
throw e.GetBaseException();
|
||||
}
|
||||
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -314,6 +298,7 @@ namespace ICD.Common.Utils
|
||||
/// <param name="value"></param>
|
||||
/// <param name="type"></param>
|
||||
/// <returns></returns>
|
||||
[CanBeNull]
|
||||
public static object ChangeType(object value, Type type)
|
||||
{
|
||||
if (type == null)
|
||||
@@ -372,7 +357,9 @@ namespace ICD.Common.Utils
|
||||
throw new ArgumentNullException("eventHandler");
|
||||
|
||||
object handler = eventHandler.Target;
|
||||
MethodInfo callback = EventHandlerExtensions.GetMethodInfo(eventHandler);
|
||||
// ReSharper disable InvokeAsExtensionMethod
|
||||
MethodInfo callback = MethodInfoExtensions.GetMethodInfo(eventHandler);
|
||||
// ReSharper restore InvokeAsExtensionMethod
|
||||
|
||||
return SubscribeEvent(instance, eventInfo, handler, callback);
|
||||
}
|
||||
@@ -394,7 +381,9 @@ namespace ICD.Common.Utils
|
||||
throw new ArgumentNullException("eventHandler");
|
||||
|
||||
object handler = eventHandler.Target;
|
||||
MethodInfo callback = EventHandlerExtensions.GetMethodInfo(eventHandler);
|
||||
// ReSharper disable InvokeAsExtensionMethod
|
||||
MethodInfo callback = MethodInfoExtensions.GetMethodInfo(eventHandler);
|
||||
// ReSharper restore InvokeAsExtensionMethod
|
||||
|
||||
return SubscribeEvent(instance, eventInfo, handler, callback);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
using System;
|
||||
using ICD.Common.Utils.Services;
|
||||
using ICD.Common.Utils.Services.Logging;
|
||||
#if SIMPLSHARP
|
||||
using Crestron.SimplSharp;
|
||||
|
||||
@@ -44,8 +46,20 @@ namespace ICD.Common.Utils
|
||||
try
|
||||
{
|
||||
#if DEBUG
|
||||
if (!m_CriticalSection.WaitForMutex(TIMEOUT))
|
||||
throw new InvalidProgramException("Deadlock detected in program");
|
||||
int attempt = 1;
|
||||
while (!m_CriticalSection.WaitForMutex(TIMEOUT))
|
||||
{
|
||||
// Poor-man's stack trace
|
||||
try
|
||||
{
|
||||
throw new InvalidProgramException("Failed to aquire mutex in expected timeframe - Attempt " + attempt++);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
ServiceProvider.GetService<ILoggerService>()
|
||||
.AddEntry(eSeverity.Error, e, "Deadlock detected in program");
|
||||
}
|
||||
}
|
||||
#else
|
||||
m_CriticalSection.Enter();
|
||||
#endif
|
||||
|
||||
@@ -13,9 +13,10 @@ namespace ICD.Common.Utils
|
||||
if (callback == null)
|
||||
throw new ArgumentNullException("callback");
|
||||
|
||||
Enter();
|
||||
|
||||
try
|
||||
{
|
||||
Enter();
|
||||
callback();
|
||||
}
|
||||
finally
|
||||
@@ -35,9 +36,10 @@ namespace ICD.Common.Utils
|
||||
if (callback == null)
|
||||
throw new ArgumentNullException("callback");
|
||||
|
||||
Enter();
|
||||
|
||||
try
|
||||
{
|
||||
Enter();
|
||||
return callback();
|
||||
}
|
||||
finally
|
||||
|
||||
@@ -21,14 +21,20 @@ namespace ICD.Common.Utils.Services.Logging
|
||||
|
||||
public interface ILoggerService
|
||||
{
|
||||
/// <summary>
|
||||
/// Raised when an item is logged against the logger service.
|
||||
/// </summary>
|
||||
[PublicAPI]
|
||||
event EventHandler<LogItemEventArgs> OnEntryAdded;
|
||||
|
||||
/// <summary>
|
||||
/// Raised when the severity level changes.
|
||||
/// </summary>
|
||||
[PublicAPI]
|
||||
event EventHandler<SeverityEventArgs> OnSeverityLevelChanged;
|
||||
|
||||
/// <summary>
|
||||
/// Gets and sets the severity level.
|
||||
/// Gets and sets the minimum severity threshold for log items to be logged.
|
||||
/// </summary>
|
||||
[PublicAPI]
|
||||
eSeverity SeverityLevel { get; set; }
|
||||
@@ -45,7 +51,8 @@ namespace ICD.Common.Utils.Services.Logging
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[PublicAPI]
|
||||
KeyValuePair<int, LogItem>[] GetHistory();
|
||||
[NotNull]
|
||||
IEnumerable<KeyValuePair<int, LogItem>> GetHistory();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using ICD.Common.Properties;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Converters;
|
||||
|
||||
namespace ICD.Common.Utils.Services.Logging
|
||||
{
|
||||
@@ -17,12 +18,12 @@ namespace ICD.Common.Utils.Services.Logging
|
||||
/// <summary>
|
||||
/// Gets the log time in UTC.
|
||||
/// </summary>
|
||||
[PublicAPI]
|
||||
public DateTime Timestamp { get { return m_Timestamp; } }
|
||||
|
||||
/// <summary>
|
||||
/// Get/Set for severity level.
|
||||
/// </summary>
|
||||
[JsonConverter(typeof(StringEnumConverter))]
|
||||
public eSeverity Severity { get { return m_Severity; } }
|
||||
|
||||
/// <summary>
|
||||
@@ -40,10 +41,22 @@ namespace ICD.Common.Utils.Services.Logging
|
||||
/// <param name="severity">Severity Level, between 0 and 7</param>
|
||||
/// <param name="message">Error message text</param>
|
||||
public LogItem(eSeverity severity, string message)
|
||||
: this(IcdEnvironment.GetUtcTime(), severity, message)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new LogItem object with the specified values.
|
||||
/// </summary>
|
||||
/// <param name="timestamp"></param>
|
||||
/// <param name="severity">Severity Level, between 0 and 7</param>
|
||||
/// <param name="message">Error message text</param>
|
||||
[JsonConstructor]
|
||||
public LogItem(DateTime timestamp, eSeverity severity, string message)
|
||||
{
|
||||
m_Severity = severity;
|
||||
m_Message = message;
|
||||
m_Timestamp = IcdEnvironment.GetLocalTime().ToUniversalTime();
|
||||
m_Timestamp = timestamp;
|
||||
}
|
||||
|
||||
#endregion
|
||||
@@ -72,6 +85,11 @@ namespace ICD.Common.Utils.Services.Logging
|
||||
return !a1.Equals(a2);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if this instance is equal to the given object.
|
||||
/// </summary>
|
||||
/// <param name="other"></param>
|
||||
/// <returns></returns>
|
||||
public bool Equals(LogItem other)
|
||||
{
|
||||
return m_Severity == other.m_Severity &&
|
||||
|
||||
@@ -7,17 +7,17 @@ namespace ICD.Common.Utils.Services.Scheduler
|
||||
{
|
||||
public event EventHandler OnScheduledRunTimeChanged;
|
||||
|
||||
private DateTime? m_NextRunTime;
|
||||
private DateTime? m_NextRunTimeUtc;
|
||||
|
||||
public DateTime? NextRunTime
|
||||
public DateTime? NextRunTimeUtc
|
||||
{
|
||||
get { return m_NextRunTime; }
|
||||
get { return m_NextRunTimeUtc; }
|
||||
private set
|
||||
{
|
||||
if (m_NextRunTime == value)
|
||||
if (m_NextRunTimeUtc == value)
|
||||
return;
|
||||
|
||||
m_NextRunTime = value;
|
||||
m_NextRunTimeUtc = value;
|
||||
|
||||
OnScheduledRunTimeChanged.Raise(this);
|
||||
}
|
||||
@@ -26,12 +26,12 @@ namespace ICD.Common.Utils.Services.Scheduler
|
||||
public void Run()
|
||||
{
|
||||
RunFinal();
|
||||
NextRunTime = GetNextRunTime();
|
||||
NextRunTimeUtc = GetNextRunTimeUtc();
|
||||
}
|
||||
|
||||
public void UpdateNextRunTime()
|
||||
{
|
||||
NextRunTime = GetNextRunTime();
|
||||
NextRunTimeUtc = GetNextRunTimeUtc();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -42,6 +42,6 @@ namespace ICD.Common.Utils.Services.Scheduler
|
||||
/// <summary>
|
||||
/// Runs after RunFinal in order to set the next run time of this action
|
||||
/// </summary>
|
||||
public abstract DateTime? GetNextRunTime();
|
||||
public abstract DateTime? GetNextRunTimeUtc();
|
||||
}
|
||||
}
|
||||
@@ -39,7 +39,7 @@ namespace ICD.Common.Utils.Services.Scheduler
|
||||
try
|
||||
{
|
||||
Subscribe(action);
|
||||
m_Actions.AddSorted(action, a => a.NextRunTime);
|
||||
m_Actions.InsertSorted(action, a => a.NextRunTimeUtc);
|
||||
}
|
||||
finally
|
||||
{
|
||||
@@ -96,15 +96,15 @@ namespace ICD.Common.Utils.Services.Scheduler
|
||||
|
||||
private void TimerCallback()
|
||||
{
|
||||
DateTime currentTime = IcdEnvironment.GetLocalTime();
|
||||
DateTime currentTime = IcdEnvironment.GetUtcTime();
|
||||
IScheduledAction[] actionsToRun;
|
||||
|
||||
m_CriticalSection.Enter();
|
||||
try
|
||||
{
|
||||
actionsToRun = m_Actions
|
||||
.Where(a => a.NextRunTime <= currentTime && a.NextRunTime > m_LastRunTime)
|
||||
.OrderBy(a => a.NextRunTime)
|
||||
.Where(a => a.NextRunTimeUtc <= currentTime && a.NextRunTimeUtc > m_LastRunTime)
|
||||
.OrderBy(a => a.NextRunTimeUtc)
|
||||
.ToArray();
|
||||
}
|
||||
finally
|
||||
@@ -135,14 +135,14 @@ namespace ICD.Common.Utils.Services.Scheduler
|
||||
m_CriticalSection.Enter();
|
||||
try
|
||||
{
|
||||
var action = m_Actions.FirstOrDefault(a => a.NextRunTime != null && a.NextRunTime > m_LastRunTime);
|
||||
if (action == null || action.NextRunTime == null)
|
||||
var action = m_Actions.FirstOrDefault(a => a.NextRunTimeUtc != null && a.NextRunTimeUtc > m_LastRunTime);
|
||||
if (action == null || action.NextRunTimeUtc == null)
|
||||
{
|
||||
m_Timer.Stop();
|
||||
return;
|
||||
}
|
||||
|
||||
long msToNextAction = (long)(action.NextRunTime.Value - IcdEnvironment.GetLocalTime()).TotalMilliseconds;
|
||||
long msToNextAction = (long)(action.NextRunTimeUtc.Value - IcdEnvironment.GetUtcTime()).TotalMilliseconds;
|
||||
if (msToNextAction < 0)
|
||||
msToNextAction = 0;
|
||||
m_Timer.Reset(msToNextAction);
|
||||
@@ -195,7 +195,7 @@ namespace ICD.Common.Utils.Services.Scheduler
|
||||
try
|
||||
{
|
||||
m_Actions.Remove(action);
|
||||
m_Actions.AddSorted(action, a => a.NextRunTime);
|
||||
m_Actions.InsertSorted(action, a => a.NextRunTimeUtc);
|
||||
}
|
||||
finally
|
||||
{
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user