static CalendarItem Parse(IEnumerator <string> lines) { if (!lines.Current.StartsWith("BEGIN:")) { throw new ArgumentException("not a calendar item text"); } var kind = lines.Current.Substring(6); var item = kind == CalendarDocument.Kind ? new CalendarDocument() : kind == CalendarEvent.Kind ? new CalendarEvent() : new CalendarItem(kind); while (lines.MoveNext()) { var i = lines.Current; var idx = i.IndexOfAny(new[] { ':', ';' }); var key = i.Substring(0, idx); var value = i.Substring(idx + 1); switch (key) { case "BEGIN": item.Items.Add(Parse(lines)); break; case "END": return(item); default: var values = i.StartsWith(key + ";") ? value.Split(new[] { ':' }, 2) : new[] { value }; var parameters = values.Take(values.Length - 1).Select(_ => _.Split(new[] { '=' }, 2)).SelectMany(_ => _.Last().Split(',').Select(v => new { Key = _.First(), Value = CalendarValue.UnescapeValueString(v), })).ToLookup(_ => _.Key, _ => _.Value); var parsed = item.ParseValue(key, values.Last().Split(',').Select(CalendarValue.UnescapeValueString).ToArray(), parameters); if (parsed != null) { item.Properties[key] = parsed; } break; } } throw new InvalidOperationException("calendar item not properly ended"); }
protected virtual CalendarValue ParseValue(string key, IReadOnlyList <string> value, ILookup <string, string> parameters) => CalendarValue.Parse(value, parameters);