/////////////////////////////////////////////////////////////////////////// // Copyright (C) Wizardry and Steamworks 2013 - License: GNU GPLv3 // // Please see: http://www.gnu.org/licenses/gpl.html for legal details, // // rights of fair usage, the disclaimer and warranty conditions. // /////////////////////////////////////////////////////////////////////////// using System.Collections.Generic; using System.Linq; using System.Text; namespace wasSharp.Languages { public static class CSV { public static readonly char[] CSVEscapeCharacters = {'"', ' ', ',', '\r', '\n'}; /////////////////////////////////////////////////////////////////////////// // Copyright (C) 2015 Wizardry and Steamworks - License: GNU GPLv3 // /////////////////////////////////////////////////////////////////////////// /// /// Converts a list of strings to a comma-separated values string. /// /// a commma-separated list of values /// compliant with RFC 4180 public static string FromEnumerable(IEnumerable input) { return string.Join(",", input .Select(o => o.Replace("\"", "\"\"")) .Select(o => o.IndexOfAny(CSVEscapeCharacters) == -1 ? o : $"\"{o}\"")); } /////////////////////////////////////////////////////////////////////////// // Copyright (C) 2016 Wizardry and Steamworks - License: GNU GPLv3 // /////////////////////////////////////////////////////////////////////////// /// /// Converts a dictionary of strings to a comma-separated values string. /// /// a commma-separated list of values /// compliant with RFC 4180 public static string FromDictionary(Dictionary input) { return string.Join(",", input.Keys.Select(o => o.ToString()).Zip(input.Values.Select(o => o.ToString()), (o, p) => string.Join(",", o.Replace("\"", "\"\"").IndexOfAny(CSVEscapeCharacters) == -1 ? o : $"\"{o}\"", p.Replace("\"", "\"\"").IndexOfAny(CSVEscapeCharacters) == -1 ? p : $"\"{p}\""))); } /////////////////////////////////////////////////////////////////////////// // Copyright (C) 2015 Wizardry and Steamworks - License: GNU GPLv3 // /////////////////////////////////////////////////////////////////////////// /// /// Converts successive comma-separated values to key-value pairs. /// /// key-value pairs of successive comma-separate values public static IEnumerable> ToKeyValue(string input) { return ToEnumerable(input).AsParallel().Select((o, p) => new {o, p}) .GroupBy(q => q.p / 2, q => q.o) .Select(o => o.ToArray()) .TakeWhile(o => o.Length % 2 == 0) .Where(o => !string.IsNullOrEmpty(o[0])) .Select(o => new KeyValuePair(o[0], o[1])); } /////////////////////////////////////////////////////////////////////////// // Copyright (C) 2015 Wizardry and Steamworks - License: GNU GPLv3 // /////////////////////////////////////////////////////////////////////////// /// /// Converts a generic key value pair to a CSV. /// /// a commma-separated list of values /// compliant with RFC 4180 public static string FromKeyValue(KeyValuePair input) { var key = input.Key.ToString(); var value = input.Value.ToString(); return string.Join(",", key .Replace("\"", "\"\"").IndexOfAny(CSVEscapeCharacters) == -1 ? key : $"\"{key}\"", value .Replace("\"", "\"\"") .IndexOfAny(CSVEscapeCharacters) == -1 ? value : $"\"{value}\""); } /////////////////////////////////////////////////////////////////////////// // Copyright (C) 2015 Wizardry and Steamworks - License: GNU GPLv3 // /////////////////////////////////////////////////////////////////////////// /// /// Converts a comma-separated list of values to a list of strings. /// /// a comma-separated list of values /// a list of strings /// compliant with RFC 4180 public static IEnumerable ToEnumerable(string csv) { if (string.IsNullOrEmpty(csv)) yield break; var s = new Stack(); var m = new StringBuilder(); for (var i = 0; i < csv.Length; ++i) { switch (csv[i]) { case ',': if (!s.Any() || !s.Peek().Equals('"')) { yield return m.ToString(); m = new StringBuilder(); continue; } m.Append(csv[i]); continue; case '"': if (i + 1 < csv.Length && csv[i].Equals(csv[i + 1])) { m.Append(csv[i]); ++i; continue; } if (!s.Any() || !s.Peek().Equals(csv[i])) { s.Push(csv[i]); continue; } s.Pop(); continue; } m.Append(csv[i]); } yield return m.ToString(); } } }