wasSharp

Subversion Repositories:
Compare Path: Rev
With Path: Rev
?path1? @ 51  →  ?path2? @ 52
/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(@"|", @"&amp;", @"&lt;", @"&gt;", @"&quot;", @"&apos;") + @")",
@"", 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 "&apos;":
m.Append('\'');
break;
 
case "&quot;":
m.Append('"');
break;
 
case "&gt;":
m.Append('>');
break;
 
case "&lt;":
m.Append('<');
break;
 
case "&amp;":
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] = @"&amp;";
break;
 
case '<':
result[o] = @"&lt;";
break;
 
case '>':
result[o] = @"&gt;";
break;
 
case '"':
result[o] = @"&quot;";
break;
 
case '\'':
result[o] = @"&apos;";
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);
}
}
}
}