UniVRM/Assets/VRM/UniJSON/Scripts/Json/JsonString.cs

373 lines
11 KiB
C#

using System;
using System.Linq;
using System.Text;
namespace UniJSON
{
public static class JsonString
{
#region Quote
public static void Escape(String s, IStore w)
{
if (String.IsNullOrEmpty(s))
{
return;
}
var it = s.ToCharArray().Cast<char>().GetEnumerator();
while (it.MoveNext())
{
switch (it.Current)
{
case '"':
case '\\':
case '/':
// \\ prefix
w.Write('\\');
w.Write(it.Current);
break;
case '\b':
w.Write('\\');
w.Write('b');
break;
case '\f':
w.Write('\\');
w.Write('f');
break;
case '\n':
w.Write('\\');
w.Write('n');
break;
case '\r':
w.Write('\\');
w.Write('r');
break;
case '\t':
w.Write('\\');
w.Write('t');
break;
default:
w.Write(it.Current);
break;
}
}
}
public static void Escape(Utf8String s, IStore w)
{
if (s.IsEmpty)
{
return;
}
var it = s.GetIterator();
while(it.MoveNext())
{
var l = it.CurrentByteLength;
if (l == 1)
{
var b = it.Current;
switch (b)
{
case (Byte)'"':
case (Byte)'\\':
case (Byte)'/':
// \\ prefix
w.Write((Byte)'\\');
w.Write(b);
break;
case (Byte)'\b':
w.Write((Byte)'\\');
w.Write((Byte)'b');
break;
case (Byte)'\f':
w.Write((Byte)'\\');
w.Write((Byte)'f');
break;
case (Byte)'\n':
w.Write((Byte)'\\');
w.Write((Byte)'n');
break;
case (Byte)'\r':
w.Write((Byte)'\\');
w.Write((Byte)'r');
break;
case (Byte)'\t':
w.Write((Byte)'\\');
w.Write((Byte)'t');
break;
default:
w.Write(b);
break;
}
// ascii
}
else if (l == 2)
{
w.Write(it.Current);
w.Write(it.Second);
}
else if (l == 3)
{
w.Write(it.Current);
w.Write(it.Second);
w.Write(it.Third);
}
else if (l == 4)
{
w.Write(it.Current);
w.Write(it.Second);
w.Write(it.Third);
w.Write(it.Fourth);
}
else
{
throw new ParserException("invalid utf8");
}
}
}
public static string Escape(String s)
{
var sb = new StringBuilder();
Escape(s, new StringBuilderStore(sb));
return sb.ToString();
}
public static void Quote(String s, IStore w)
{
w.Write('"');
Escape(s, w);
w.Write('"');
}
public static void Quote(Utf8String s, IStore w)
{
w.Write((Byte)'"');
Escape(s, w);
w.Write((Byte)'"');
}
/// <summary>
/// Added " and Escape
/// </summary>
/// <param name="s"></param>
/// <param name="w"></param>
public static string Quote(string s)
{
var sb = new StringBuilder();
Quote(s, new StringBuilderStore(sb));
return sb.ToString();
}
public static Utf8String Quote(Utf8String s)
{
var sb = new BytesStore(s.ByteLength);
Quote(s, sb);
return new Utf8String(sb.Bytes);
}
#endregion
#region Unquote
public static int Unescape(string src, IStore w)
{
int writeCount = 0;
Action<Char> Write = c =>
{
if (w != null)
{
w.Write(c);
}
++writeCount;
};
int i = 0;
int length = src.Length - 1;
while (i < length)
{
if (src[i] == '\\')
{
var c = src[i + 1];
switch (c)
{
case '\\':
case '/':
case '"':
// remove prefix
Write(c);
i += 2;
continue;
case 'b':
Write('\b');
i += 2;
continue;
case 'f':
Write('\f');
i += 2;
continue;
case 'n':
Write('\n');
i += 2;
continue;
case 'r':
Write('\r');
i += 2;
continue;
case 't':
Write('\t');
i += 2;
continue;
}
}
Write(src[i]);
i += 1;
}
while (i <= length)
{
Write(src[i++]);
}
return writeCount;
}
public static int Unescape(Utf8String s, IStore w)
{
int writeCount = 0;
Action<Byte> Write = c =>
{
if (w != null)
{
w.Write(c);
}
++writeCount;
};
var it = s.GetIterator();
while(it.MoveNext())
{
var l = it.CurrentByteLength;
if (l == 1)
{
if (it.Current == (Byte)'\\')
{
var c = it.Second;
switch (c)
{
case (Byte)'\\':
case (Byte)'/':
case (Byte)'"':
// remove prefix
Write(c);
it.MoveNext();
continue;
case (Byte)'b':
Write((Byte)'\b');
it.MoveNext();
continue;
case (Byte)'f':
Write((Byte)'\f');
it.MoveNext();
continue;
case (Byte)'n':
Write((Byte)'\n');
it.MoveNext();
continue;
case (Byte)'r':
Write((Byte)'\r');
it.MoveNext();
continue;
case (Byte)'t':
Write((Byte)'\t');
it.MoveNext();
continue;
}
}
Write(it.Current);
}
else if (l == 2)
{
Write(it.Current);
Write(it.Second);
}
else if (l == 3)
{
Write(it.Current);
Write(it.Second);
Write(it.Third);
}
else if (l == 4)
{
Write(it.Current);
Write(it.Second);
Write(it.Third);
Write(it.Fourth);
}
else
{
throw new ParserException("invalid utf8");
}
}
return writeCount;
}
public static string Unescape(string src)
{
var sb = new StringBuilder();
Unescape(src, new StringBuilderStore(sb));
return sb.ToString();
}
public static int Unquote(string src, IStore w)
{
return Unescape(src.Substring(1, src.Length - 2), w);
}
public static int Unquote(Utf8String src, IStore w)
{
return Unescape(src.Subbytes(1, src.ByteLength - 2), w);
}
public static string Unquote(string src)
{
var count = Unquote(src, null);
if (count == src.Length - 2)
{
return src.Substring(1, src.Length - 2);
}
else
{
var sb = new StringBuilder(count);
Unquote(src, new StringBuilderStore(sb));
var str = sb.ToString();
return str;
}
}
public static Utf8String Unquote(Utf8String src)
{
var count = Unquote(src, null);
if (count == src.ByteLength - 2)
{
return src.Subbytes(1, src.ByteLength - 2);
}
else
{
var sb = new BytesStore(count);
Unquote(src, sb);
return new Utf8String(sb.Bytes);
}
}
#endregion
}
}