private static CipElement ParseElement(string eString) { var attrs = SplitByTokenPreserveQuoted(eString); int intValue; var attributesList = attrs as IList <string> ?? attrs.ToList(); var hasIdData = int.TryParse(attributesList.FirstOrDefault(), out intValue); Func <string, CipAttribute> extractAttribute = str => { var sections = str.Split(new[] { '=' }, 2); if (sections.Length < 2) { return(new CipAttribute { Name = sections[0].EndsWith("=") ? sections[0].Substring(0, sections[0].Length - 1) : sections[0] }); } int numericValue; return(new CipAttribute { Name = sections[0], Value = int.TryParse(sections[1], out numericValue) ? (IConvertible)numericValue : sections[1] }); }; var element = new CipElement(hasIdData ? intValue : -1) { Attributes = attributesList.Skip(hasIdData ? 1 : 0).Select(a => extractAttribute(a)).ToList() }; return(element); }
public static IEnumerable <CipElement> Parse(string inputStr) { if (string.IsNullOrWhiteSpace(inputStr)) { return(null); } var enclosingChars = new Dictionary <char, char> { { CloseCurly, OpenCurly }, { CloseParenthesis, OpenParenthesis } }; inputStr = inputStr.Trim(' '); // remove extra leading and trailing spaces. inputStr = TrimEnclosures(inputStr, enclosingChars); var enclosures = GetEnclosedButPreserveQuoted(inputStr, enclosingChars); var root = new CipElement(-1); root.Attributes.Add(new CipAttribute()); var pendingContent = new Stack <CipAttribute>(); // root is guaranteed to have at least one attribute. pendingContent.Push(root.Attributes.First()); while (enclosures.Count > 0) { // comma separate but watch for strings in quotes (""). var elements = SplitByTokenPreserveQuoted(enclosures.Pop(), ',').Select(ParseElement).ToList(); var currentAttribute = pendingContent.Pop(); foreach (var element in elements) { foreach (var attr in element.Attributes.Where(a => a.Name.Equals("Content"))) { pendingContent.Push(attr); } } currentAttribute.Value = elements; } return(root.Attributes.First().Value as IEnumerable <CipElement>); }