/// <summary> /// Creates an instance of a <see cref="List"/>. /// </summary> /// <param name="prefix">A value that determines whether the instrument references in <paramref name="instrumentReferences"/> should be concatenated to a current value, removed from a current value or replace a current value.</param> /// <param name="instrumentReferences">A sequence of instrument references that belongs to the <see cref="List"/>.</param> public List(ListPrefix prefix, IEnumerable <InsRef> instrumentReferences) { _instrumentReferences = instrumentReferences ?? throw new ArgumentNullException(nameof(instrumentReferences)); Prefix = prefix; PrefixCharacter = prefix switch { ListPrefix.Add => AddPrefix, ListPrefix.Remove => RemovePrefix, ListPrefix.Replace => ReplacePrefix, _ => default(char?), }; if (instrumentReferences is ICollection <InsRef> collection) { Count = collection.Count; } else { int count = 0; using (IEnumerator <InsRef> enumerator = instrumentReferences.GetEnumerator()) while (enumerator?.MoveNext() == true) { count++; } Count = count; } }
private static void ParseListTest(string s, ListPrefix prefix, params InsRef[] insRefs) { Assert.IsFalse(string.IsNullOrEmpty(s)); Assert.IsNotNull(insRefs); void Verify(List list) { Assert.AreEqual(insRefs.Length, list.Count); Assert.AreEqual(prefix, list.Prefix); if (prefix != ListPrefix.Undefined) { Assert.AreEqual(s[0], list.PrefixCharacter); } Assert.IsNotNull(list.GetEnumerator()); for (int i = 0; i < insRefs.Length; ++i) { InsRef insRef = insRefs[i]; Assert.IsTrue(list.Contains(insRef)); Assert.AreEqual(list[i], insRef); } int index = 0; foreach (InsRef insRef in list) { Assert.AreEqual(insRefs[index++], insRef); } Assert.AreEqual(s.Trim(), list.ToString()); } Assert.IsTrue(List.TryParse(s, out List list)); Verify(list); Assert.IsTrue(List.TryParse(s.GetBytes(), out list)); Verify(list); }
/// <summary> /// Tries to convert a memory span that contains the bytes of a UTF-8 string representation of a space separated list of instrument references to its <see cref="List"/> equivalent and returns a value that indicates whether the conversion succeeded. /// </summary> /// <param name="value">The memory span that contains the UTF-8 string value to parse.</param> /// <param name="list">The converted <see cref="List"/> value or default depending on whether the conversion succeeded or failed.</param> /// <returns>true if value was converted successfully; otherwise, false.</returns> public static bool TryParse(ReadOnlySpan <byte> value, out List @list) { //trim leading spaces while (value.Length > 0 && value[0] == SpacePrefix) { value = value.Slice(1); } ListPrefix prefix = ListPrefix.Undefined; if (value.Length > 0) { switch (value[0]) { case (byte)AddPrefix: prefix = ListPrefix.Add; value = value.Slice(1); break; case (byte)RemovePrefix: prefix = ListPrefix.Remove; value = value.Slice(1); break; case (byte)ReplacePrefix: prefix = ListPrefix.Replace; value = value.Slice(1); break; } } @list = default; List <InsRef> instrumentReferences = new List <InsRef>(); int index; const byte ByteSpace = (byte)SpacePrefix; while ((index = value.IndexOf(ByteSpace)) != -1 && index < value.Length - 1) { ReadOnlySpan <byte> longUtf8Bytes = value.Slice(0, index); if (!InsRef.TryParse(longUtf8Bytes, out InsRef insRef)) { return(false); } instrumentReferences.Add(insRef); value = value.Slice(index + 1); } if (value.Length > 0) { if (!InsRef.TryParse(value, out InsRef insRef)) { return(false); } instrumentReferences.Add(insRef); } if (instrumentReferences.Count == 0) { return(false); } @list = new List(prefix, instrumentReferences); return(true); }