/Languages/CSV.cs |
@@ -0,0 +1,140 @@ |
/////////////////////////////////////////////////////////////////////////// |
// 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 |
{ |
public static class CSV |
{ |
/////////////////////////////////////////////////////////////////////////// |
// Copyright (C) 2015 Wizardry and Steamworks - License: GNU GPLv3 // |
/////////////////////////////////////////////////////////////////////////// |
/// <summary> |
/// Converts a list of strings to a comma-separated values string. |
/// </summary> |
/// <returns>a commma-separated list of values</returns> |
/// <remarks>compliant with RFC 4180</remarks> |
public static string FromEnumerable(IEnumerable<string> input) |
{ |
return string.Join(",", |
input |
.Select(o => o.Replace("\"", "\"\"")) |
.Select(o => o.IndexOfAny(new[] { '"', ' ', ',', '\r', '\n' }).Equals(-1) ? o : "\"" + o + "\"")); |
} |
|
/////////////////////////////////////////////////////////////////////////// |
// Copyright (C) 2016 Wizardry and Steamworks - License: GNU GPLv3 // |
/////////////////////////////////////////////////////////////////////////// |
/// <summary> |
/// Converts a dictionary of strings to a comma-separated values string. |
/// </summary> |
/// <returns>a commma-separated list of values</returns> |
/// <remarks>compliant with RFC 4180</remarks> |
public static string FromDictionary<K, V>(Dictionary<K, V> input) |
{ |
return string.Join(",", input.Keys.Select(o => o.ToString()).Zip(input.Values.Select(o => o.ToString()), |
(o, p) => |
string.Join(",", |
o.Replace("\"", "\"\"").IndexOfAny(new[] { '"', ' ', ',', '\r', '\n' }).Equals(-1) |
? o |
: "\"" + o + "\"", |
p.Replace("\"", "\"\"").IndexOfAny(new[] { '"', ' ', ',', '\r', '\n' }).Equals(-1) |
? p |
: "\"" + p + "\""))); |
} |
|
/////////////////////////////////////////////////////////////////////////// |
// Copyright (C) 2015 Wizardry and Steamworks - License: GNU GPLv3 // |
/////////////////////////////////////////////////////////////////////////// |
/// <summary> |
/// Converts successive comma-separated values to key-value pairs. |
/// </summary> |
/// <returns>key-value pairs of successive comma-separate values</returns> |
public static IEnumerable<KeyValuePair<string, string>> 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<string, string>(o[0], o[1])); |
} |
|
/////////////////////////////////////////////////////////////////////////// |
// Copyright (C) 2015 Wizardry and Steamworks - License: GNU GPLv3 // |
/////////////////////////////////////////////////////////////////////////// |
/// <summary> |
/// Converts a generic key value pair to a CSV. |
/// </summary> |
/// <returns>a commma-separated list of values</returns> |
/// <remarks>compliant with RFC 4180</remarks> |
public static string FromKeyValue<K, V>(KeyValuePair<K, V> input) |
{ |
var key = input.Key.ToString(); |
var value = input.Value.ToString(); |
|
return string.Join(",", key |
.Replace("\"", "\"\"").IndexOfAny(new[] { '"', ' ', ',', '\r', '\n' }).Equals(-1) |
? key |
: "\"" + key + "\"", value |
.Replace("\"", "\"\"") |
.IndexOfAny(new[] { '"', ' ', ',', '\r', '\n' }) |
.Equals(-1) |
? value |
: "\"" + value + "\""); |
} |
|
/////////////////////////////////////////////////////////////////////////// |
// Copyright (C) 2015 Wizardry and Steamworks - License: GNU GPLv3 // |
/////////////////////////////////////////////////////////////////////////// |
/// <summary> |
/// Converts a comma-separated list of values to a list of strings. |
/// </summary> |
/// <param name="csv">a comma-separated list of values</param> |
/// <returns>a list of strings</returns> |
/// <remarks>compliant with RFC 4180</remarks> |
public static IEnumerable<string> ToEnumerable(string csv) |
{ |
var s = new Stack<char>(); |
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(); |
} |
} |
} |
/Languages/KeyValue.cs |
@@ -0,0 +1,125 @@ |
/////////////////////////////////////////////////////////////////////////// |
// 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; |
using System.Collections.Generic; |
using System.Linq; |
|
namespace wasSharp |
{ |
public static class KeyValue |
{ |
/////////////////////////////////////////////////////////////////////////// |
// Copyright (C) 2014 Wizardry and Steamworks - License: GNU GPLv3 // |
/////////////////////////////////////////////////////////////////////////// |
/// <summary> |
/// Returns the value of a key from a key-value data string. |
/// </summary> |
/// <returns>true if the key was found in data</returns> |
public static string Get(string key, string data) |
{ |
return data.Split('&') |
.AsParallel() |
.Select(o => o.Split('=')) |
.Where(o => o.Length.Equals(2) && string.Equals(o[0], key, StringComparison.Ordinal)) |
.Select(o => o[1]) |
.FirstOrDefault(); |
} |
|
/////////////////////////////////////////////////////////////////////////// |
// Copyright (C) 2014 Wizardry and Steamworks - License: GNU GPLv3 // |
/////////////////////////////////////////////////////////////////////////// |
/// <summary> |
/// Returns a key-value data string with a key set to a given value. |
/// </summary> |
/// <returns> |
/// a key-value data string or the empty string if either key or |
/// value are empty |
/// </returns> |
public static string Set(string key, string value, string data) |
{ |
return string.Join("&", string.Join("&", data.Split('&') |
.AsParallel() |
.Select(o => o.Split('=')) |
.Where(o => o.Length.Equals(2) && !string.Equals(o[0], key, StringComparison.Ordinal)) |
.Select(o => string.Join("=", o[0], o[1]))), string.Join("=", key, value)); |
} |
|
/////////////////////////////////////////////////////////////////////////// |
// Copyright (C) 2014 Wizardry and Steamworks - License: GNU GPLv3 // |
/////////////////////////////////////////////////////////////////////////// |
/// <summary> |
/// Deletes a key-value pair from a string referenced by a key. |
/// </summary> |
/// <returns>a key-value pair string</returns> |
public static string Delete(string key, string data) |
{ |
return string.Join("&", data.Split('&') |
.AsParallel() |
.Select(o => o.Split('=')) |
.Where(o => o.Length.Equals(2) && !string.Equals(o[0], key, StringComparison.Ordinal)) |
.Select(o => string.Join("=", o[0], o[1]))); |
} |
|
/////////////////////////////////////////////////////////////////////////// |
// Copyright (C) 2014 Wizardry and Steamworks - License: GNU GPLv3 // |
/////////////////////////////////////////////////////////////////////////// |
/// <summary> |
/// Decodes key-value pair data to a dictionary. |
/// </summary> |
/// <returns>a dictionary containing the keys and values</returns> |
public static Dictionary<string, string> Decode(string data) |
{ |
return data.Split('&') |
.AsParallel() |
.Select(o => o.Split('=')) |
.Where(o => o.Length.Equals(2)) |
.Select(o => new |
{ |
k = o[0], |
v = o[1] |
}) |
.GroupBy(o => o.k) |
.ToDictionary(o => o.Key, p => p.FirstOrDefault()?.v); |
} |
|
/////////////////////////////////////////////////////////////////////////// |
// Copyright (C) 2014 Wizardry and Steamworks - License: GNU GPLv3 // |
/////////////////////////////////////////////////////////////////////////// |
/// <summary> |
/// Serialises a dictionary to key-value data. |
/// </summary> |
/// <returns>a key-value data encoded string</returns> |
public static string Encode(Dictionary<string, string> data) |
{ |
return string.Join("&", data.AsParallel().Select(o => string.Join("=", o.Key, o.Value))); |
} |
|
/////////////////////////////////////////////////////////////////////////// |
// Copyright (C) 2014 Wizardry and Steamworks - License: GNU GPLv3 // |
/////////////////////////////////////////////////////////////////////////// |
/// <summary> |
/// Serialises a dictionary to key-value data. |
/// </summary> |
/// <returns>a key-value data encoded string</returns> |
public static string Encode(IEnumerable<KeyValuePair<string, string>> data) |
{ |
return string.Join("&", data.AsParallel().Select(o => string.Join("=", o.Key, o.Value))); |
} |
|
/////////////////////////////////////////////////////////////////////////// |
// Copyright (C) 2014 Wizardry and Steamworks - License: GNU GPLv3 // |
/////////////////////////////////////////////////////////////////////////// |
/// <summary> |
/// Escapes a dictionary's keys and values for sending as POST data. |
/// </summary> |
public static IEnumerable<KeyValuePair<string, string>> Escape(IEnumerable<KeyValuePair<string, string>> data, |
Func<string, string> func) |
{ |
return data.AsParallel().ToDictionary(o => func(o.Key), p => func(p.Value)); |
} |
} |
} |
/Languages/XML.cs |
@@ -0,0 +1,189 @@ |
/////////////////////////////////////////////////////////////////////////// |
// 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; |
using System.Collections.Generic; |
using System.Linq; |
using System.Linq.Expressions; |
using System.Text; |
using System.Text.RegularExpressions; |
using System.Threading.Tasks; |
using System.Xml.Linq; |
|
namespace wasSharp |
{ |
public static class XML |
{ |
private static readonly Func<string, bool> directIsSafeXML = |
((Expression<Func<string, bool>>) |
(data => |
Regex.Replace(data, |
@"(" + string.Join(@"|", @"&", @"<", @">", @""", @"'") + @")", |
@"", RegexOptions.IgnoreCase | RegexOptions.Multiline) |
.IndexOfAny(new[] { '&', '<', '>', '"', '\'' }) |
.Equals(-1))).Compile(); |
|
/////////////////////////////////////////////////////////////////////////// |
// Copyright (C) 2015 Wizardry and Steamworks - License: GNU GPLv3 // |
/////////////////////////////////////////////////////////////////////////// |
/// <summary> |
/// Unescapes a string used in XML. |
/// </summary> |
/// <param name="s">the string to unescape</param> |
/// <returns>an XML unescaped string</returns> |
public static string UnescapeXML(string s) |
{ |
var t = new Queue<char>(); |
var m = new StringBuilder(); |
foreach (var c in s) |
{ |
switch (c) |
{ |
case '&': |
if (!t.Count.Equals(0)) |
{ |
m.Append(string.Join("", t.ToArray())); |
t.Clear(); |
} |
t.Enqueue(c); |
break; |
|
case ';': |
if (!t.Count.Equals(0)) |
{ |
t.Enqueue(c); |
var special = string.Join("", t.ToArray()); |
switch (special) |
{ |
case "'": |
m.Append('\''); |
break; |
|
case """: |
m.Append('"'); |
break; |
|
case ">": |
m.Append('>'); |
break; |
|
case "<": |
m.Append('<'); |
break; |
|
case "&": |
m.Append('&'); |
break; |
|
default: // Unrecognized escape sequence |
m.Append(special); |
break; |
} |
t.Clear(); |
break; |
} |
m.Append(c); |
break; |
|
default: |
if (!t.Count.Equals(0)) |
{ |
t.Enqueue(c); |
if (t.Count >= 6) |
{ |
m.Append(string.Join("", t.ToArray())); |
t.Clear(); |
} |
break; |
} |
m.Append(c); |
break; |
} |
} |
return m.ToString(); |
} |
|
/////////////////////////////////////////////////////////////////////////// |
// Copyright (C) 2015 Wizardry and Steamworks - License: GNU GPLv3 // |
/////////////////////////////////////////////////////////////////////////// |
/// <summary> |
/// Escapes a string to be used in XML. |
/// </summary> |
/// <param name="s">the string to escape</param> |
/// <returns>an XML escaped string</returns> |
public static string EscapeXML(string s) |
{ |
if (string.IsNullOrEmpty(s)) return s; |
|
var result = new string[s.Length]; |
Parallel.ForEach(Enumerable.Range(0, s.Length), o => |
{ |
switch (s[o]) |
{ |
case '&': |
result[o] = @"&"; |
break; |
|
case '<': |
result[o] = @"<"; |
break; |
|
case '>': |
result[o] = @">"; |
break; |
|
case '"': |
result[o] = @"""; |
break; |
|
case '\'': |
result[o] = @"'"; |
break; |
|
default: |
result[o] = s[o].ToString(); |
break; |
} |
}); |
return string.Join("", result); |
} |
|
/////////////////////////////////////////////////////////////////////////// |
// Copyright (C) 2015 Wizardry and Steamworks - License: GNU GPLv3 // |
/////////////////////////////////////////////////////////////////////////// |
/// <summary> |
/// Determines whether a string is safe to use in XML |
/// </summary> |
/// <param name="data">the string to check</param> |
/// <returns>true in case the string is safe</returns> |
public static bool IsSafeXML(string data) |
{ |
return directIsSafeXML(data); |
} |
|
/////////////////////////////////////////////////////////////////////////// |
// Copyright (C) 2015 Wizardry and Steamworks - License: GNU GPLv3 // |
/////////////////////////////////////////////////////////////////////////// |
/// <summary> |
/// Recursively rename a node by name. |
/// </summary> |
/// <param name="root">the root from where to start</param> |
/// <param name="name">the name to replace</param> |
/// <param name="rename">the name to replace with</param> |
public static void RenameNodes(XElement root, string name, string rename) |
{ |
if (string.Equals(root.Name.LocalName, name, StringComparison.Ordinal)) |
{ |
root.Name = rename; |
} |
|
foreach (var xElement in root.Elements()) |
{ |
RenameNodes(xElement, name, rename); |
} |
} |
} |
} |