Может ли кто-нибудь из t-sql создавать сопутствующие функции, связанные с таблицами, с этими массивами массивов С# и распаковывать утилиты, которые выходят из разделителей и сохраняют нули, нулевые массивы, пустые массивы с помощью кодирования с округлением до конца?
Упаковывая любое множество строковых массивов в строку, вы можете передавать такие (малые) массивы в SQL в качестве параметров, что полезно в некоторых сценариях.
static class ArrayUtil
{
public static string Pack(string[] original)
{
return Pack(original, '|', '0', '~');
}
public static string[] Unpack(string original)
{
return Unpack(original, '|', '0', '~');
}
public static string Pack(string[] original, char delimiter, char zed, char escape)
{
if (delimiter == escape ||
zed == escape ||
delimiter == zed) throw new ArgumentException("special characters must be distinct");
// Null array returns a null string
if (original == null) return null;
// Empty array returns an empty string
if (original.Length == 0) return string.Empty;
// Arrays with a single empty element are represented as just the escape character
// to differentiate from an empty array
if (original.Length == 1 && original[0] == string.Empty) return escape.ToString();
// Otherwise
StringBuilder sb = new StringBuilder();
for (int i = 0, ol = original.Length; i < ol; i++)
{
string s = original[i];
if (s == null)
{
sb.Append(zed); // zed == null
}
else
{
for (int j = 0, sl = s.Length; j < sl; j++)
{
char c = s[j];
// escape literal delimiters, escapes, and leading zeds
if (c == delimiter ||
c == escape ||
(c == zed && j == 0)) sb.Append(escape);
sb.Append(c);
}
}
if (i != ol - 1) sb.Append(delimiter); // no trailing delimiter
}
return sb.ToString();
}
public static string[] Unpack(string original, char delimiter, char zed, char escape)
{
if (delimiter == escape ||
zed == escape ||
delimiter == zed) throw new ArgumentException("special characters must be distinct");
// Null string returns a null array
if (original == null) return null;
// Empty string returns an empty array
if (original == string.Empty) return new string[] { };
// A single escape character represents an array with a single empty element
// to differentiate from an empty array
if (original == escape.ToString()) return new string[] { string.Empty };
// Otherwise
StringBuilder sb = new StringBuilder(); // A place to store the current element
StringReader sr = new StringReader(original); // A stream of the original string
List<string> unpacked = new List<string>(); // The finished elements
int next;
while ((next = sr.Read()) >= 0)
{
char c = (char)next;
if (c == zed && sb.Length == 0)
{
unpacked.Add(null);
if ((next = sr.Peek()) >= 0 && (char)next != delimiter)
throw new ArgumentException("An element leading zed character must be escaped or must alone be the element", "original");
sb = null;
}
else if (c == delimiter)
{
if (sb != null) unpacked.Add(sb.ToString());
sb = new StringBuilder();
}
else if (c == escape)
{
if ((next = sr.Read()) >= 0)
{
sb.Append((char)next);
}
else
throw new ArgumentException("Escapee expected", "original");
}
else
{
sb.Append(c);
}
}
// A final zed character will make sb = null, but otherwise we have an additional element
if (sb != null) unpacked.Add(sb.ToString());
return unpacked.ToArray();
}
}
Пример упаковки с Pack(original, '|', '0', '~')
, основной случай:
["hello", "world"] -> "hello|world"
Некоторые частные случаи (обнаруженные PEX)
null -> null
[null] -> "0"
[null, null] -> "0|0"
[] -> ""
[""] -> "~"
["", ""] -> "|"
["|", "|"] -> "~||~|"