diff --git a/GeminiLab.Core2/Base64Extensions.cs b/GeminiLab.Core2/Base64Extensions.cs
new file mode 100644
index 0000000..a969ff0
--- /dev/null
+++ b/GeminiLab.Core2/Base64Extensions.cs
@@ -0,0 +1,101 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace GeminiLab.Core2 {
+ public static class Base64Extensions {
+ public static string Base64Chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
+ private static byte[] decodeTable = {
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3E, 0xFF, 0xFF, 0xFF, 0x3F,
+ 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xFF,
+ 0xFF, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E,
+ 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28,
+ 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32, 0x33, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ };
+
+ public static string ToBase64(this byte[] source) {
+ var tail = source.Length % 3;
+ var groups = source.Length / 3;
+ var outputLen = groups * 4 + (tail > 0 ? 4 : 0);
+
+ var sb = new StringBuilder(outputLen);
+
+ for (int i = 0; i < groups; ++i) {
+ int val = source[i * 3] << 16 | source[i * 3 + 1] << 8 | source[i * 3 + 2];
+
+ sb.Append(Base64Chars[(val >> 18)]);
+ sb.Append(Base64Chars[(val >> 12) & 0x3F]);
+ sb.Append(Base64Chars[(val >> 6) & 0x3F]);
+ sb.Append(Base64Chars[val & 0x3F]);
+ }
+
+ if (tail == 1) {
+ int val = source[source.Length - 1];
+ sb.Append(Base64Chars[val >> 2]);
+ sb.Append(Base64Chars[(val & 0x03) << 4]);
+ sb.Append("==");
+ } else if (tail == 2) {
+ int val = source[source.Length - 2] << 8 | source[source.Length - 1];
+ sb.Append(Base64Chars[val >> 10]);
+ sb.Append(Base64Chars[(val >> 4) & 0x3F]);
+ sb.Append(Base64Chars[(val & 0x0F) << 2]);
+ sb.Append("=");
+ }
+
+ return sb.ToString();
+ }
+
+ public static string ToBase64(this string source) => source.ToBase64(Encoding.UTF8);
+
+ public static string ToBase64(this string source, Encoding encoding) => encoding.GetBytes(source).ToBase64();
+
+ public static byte[] AsBase64(this string source) {
+ int len = source.Length;
+
+ if (len % 4 != 0) throw new ArgumentException(nameof(source));
+ if (len == 0) return new byte[0];
+
+ int sp = source[len - 1] == '=' ? (source[len - 2] == '=' ? 2 : 1) : 0;
+ int groups = len / 4;
+ int outputLen = groups * 3 - sp;
+
+ byte[] rv = new byte[outputLen];
+
+ for (int i = 0; i < groups; ++i) {
+ int val = 0;
+ for (int j = 0; j < 4; ++j) {
+ int chr;
+ if ((chr = source[i * 4 + j]) >= 0x80 || chr < 0 || decodeTable[chr] >= 0x40) throw new ArgumentException(nameof(source));
+
+ val = (val << 6) | decodeTable[chr];
+ }
+
+ if (i == groups - 1) {
+ byte[] v = { (byte)(val >> 16), (byte)((val >> 8) & 0xFF), (byte)(val & 0xFF) };
+
+ for (int j = 0; j < 3; ++j) {
+ if (j + sp >= 3) {
+ if (v[j] != 0) throw new ArgumentException(nameof(source));
+ } else {
+ rv[i * 3 + j] = v[j];
+ }
+ }
+ } else {
+ rv[i * 3] = (byte)(val >> 16);
+ rv[i * 3 + 1] = (byte)((val >> 8) & 0xFF);
+ rv[i * 3 + 2] = (byte)(val & 0xFF);
+ }
+ }
+
+ return rv;
+ }
+
+ public static string DecodeBase64EncodedString(this string source) => source.DecodeBase64EncodedString(Encoding.UTF8);
+
+ public static string DecodeBase64EncodedString(this string source, Encoding encoding) => encoding.GetString(source.AsBase64());
+ }
+}
diff --git a/GeminiLab.Core2/GeminiLab.Core2.csproj b/GeminiLab.Core2/GeminiLab.Core2.csproj
index 15ecf4b..ae22d54 100644
--- a/GeminiLab.Core2/GeminiLab.Core2.csproj
+++ b/GeminiLab.Core2/GeminiLab.Core2.csproj
@@ -8,9 +8,14 @@
Gemini Laboratory
Gemini Laboratory
GeminiLab.Core2
- 0.9.0.0
+ 0.9.2.0
Copyright © Gemini Laboratory 2017 - 2018
- 0.9.0.0
+ 0.9.2.0
+ true
+ true
+ 0.9.2
+ https://github.com/GeminiLab/GeminiLab.Core2/blob/master/LICENSE
+ https://github.com/GeminiLab/GeminiLab.Core2/
diff --git a/GeminiLab.Core2/InfiniteEnumerable.cs b/GeminiLab.Core2/InfiniteEnumerable.cs
index 6270585..5d36741 100644
--- a/GeminiLab.Core2/InfiniteEnumerable.cs
+++ b/GeminiLab.Core2/InfiniteEnumerable.cs
@@ -1,6 +1,5 @@
using System;
using System.Collections.Generic;
-using System.Diagnostics;
using System.Linq;
namespace GeminiLab.Core2 {
@@ -135,7 +134,7 @@ public T GetNext() {
public void Reset() {
_first = true;
- _accumulator = default(T);
+ _accumulator = default;
_en = _source.GetEnumerator();
}
diff --git a/GeminiLab.Core2/ML/Json/JsonObjects.cs b/GeminiLab.Core2/ML/Json/JsonObjects.cs
index 00b83b1..84093e5 100644
--- a/GeminiLab.Core2/ML/Json/JsonObjects.cs
+++ b/GeminiLab.Core2/ML/Json/JsonObjects.cs
@@ -1,3 +1,4 @@
+using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
@@ -7,7 +8,7 @@ public abstract class JsonValue {
internal abstract void Stringify(JsonStringifyConfig config, int indent, StringBuilder target);
internal static void MakeIndent(StringBuilder sb, int cnt) => sb.Append(' ', cnt * 4);
-
+
public sealed override string ToString() {
var sb = new StringBuilder();
@@ -39,11 +40,78 @@ public string ToStringForNetwork() {
}
public sealed class JsonObject : JsonValue {
- public IEnumerable Values { get; }
+ private struct JsonObjectKeyComparer : IComparer {
+ public JsonObject Father;
+
+ public int Compare(string x, string y) {
+ int xv = Father._keyOrder.ContainsKey(x) ? Father._keyOrder[x] : -1;
+ int yv = Father._keyOrder.ContainsKey(y) ? Father._keyOrder[y] : -1;
+
+ return xv.CompareTo(yv);
+ }
+ }
+
+ private readonly Dictionary _keyOrder;
+ private readonly SortedDictionary _values;
+
+ public IEnumerable Values {
+ get {
+ foreach (var i in _values) yield return new JsonObjectKeyValuePair(new JsonString(i.Key), i.Value);
+ }
+ }
+
+ public JsonValue this[JsonString str] {
+ get => this[str?.Value ?? throw new ArgumentNullException(nameof(str))];
+ set => this[str?.Value ?? throw new ArgumentNullException(nameof(str))] = value;
+ }
+
+ public JsonValue this[string str] {
+ get {
+ if (str == null) throw new ArgumentNullException(nameof(str));
+ if (!_values.ContainsKey(str)) throw new KeyNotFoundException();
+
+ return _values[str];
+ }
+ set {
+ if (str == null) throw new ArgumentNullException(nameof(str));
+ if (value == null) throw new ArgumentNullException(nameof(value));
+
+ if (!_values.ContainsKey(str)) {
+ _keyOrder[str] = _keyOrder.Count;
+ }
+
+ _values[str] = value;
+ }
+ }
+
+ public void Append(JsonString key, JsonValue value) {
+ if (key == null) throw new ArgumentNullException(nameof(key));
+ if (value == null) throw new ArgumentNullException(nameof(value));
+
+ if (_values.ContainsKey(key.Value)) throw new ArgumentOutOfRangeException(nameof(key));
+ this[key] = value;
+ }
+
+ public void Remove(JsonString key) {
+ if (key == null) throw new ArgumentNullException(nameof(key));
+
+ if (!_values.ContainsKey(key.Value)) throw new KeyNotFoundException();
+ _keyOrder[key.Value] = -1;
+ _values.Remove(key.Value);
+ }
+
+ public JsonObject() {
+ _keyOrder = new Dictionary();
+ _values = new SortedDictionary(new JsonObjectKeyComparer { Father = this });
+ }
- // some (and clr) don't like tuples, make them happy
public JsonObject(IEnumerable values) {
- Values = values;
+ _keyOrder = new Dictionary();
+ _values = new SortedDictionary(new JsonObjectKeyComparer { Father = this });
+
+ foreach (var i in values) {
+ Append(i.Key, i.Value);
+ }
}
internal override void Stringify(JsonStringifyConfig config, int indent, StringBuilder target) {
@@ -51,7 +119,7 @@ internal override void Stringify(JsonStringifyConfig config, int indent, StringB
target.Append("{}");
return;
}
-
+
bool compact = config.Contains(JsonStringifyConfig.Compact);
bool expandObjects = config.Contains(JsonStringifyConfig.ExpandObjects);
@@ -61,7 +129,7 @@ internal override void Stringify(JsonStringifyConfig config, int indent, StringB
string tail = compact ? "}" : " }";
target.Append(expandObjects ? "{\n" : head);
-
+
bool first = true;
foreach (var i in Values) {
if (!first) {
@@ -88,10 +156,14 @@ internal override void Stringify(JsonStringifyConfig config, int indent, StringB
}
public sealed class JsonArray : JsonValue {
- public IEnumerable Values { get; }
+ public List Values { get; }
+
+ public JsonArray() {
+ Values = new List();
+ }
public JsonArray(IEnumerable values) {
- Values = values;
+ Values = new List(values);
}
internal override void Stringify(JsonStringifyConfig config, int indent, StringBuilder target) {
@@ -162,9 +234,11 @@ internal JsonNumber(string value) {
if (int.TryParse(value, out int vint)) {
IsFloat = false;
ValueInt = vint;
- } else {
+ } else if (double.TryParse(value, out double vfloat)) {
IsFloat = true;
- ValueFloat = double.Parse(value);
+ ValueFloat = vfloat;
+ } else {
+ throw new ArgumentOutOfRangeException(nameof(value));
}
}
diff --git a/TestConsole/Program.cs b/TestConsole/Program.cs
index 51f4ce9..4cd1db3 100644
--- a/TestConsole/Program.cs
+++ b/TestConsole/Program.cs
@@ -1,16 +1,11 @@
using System;
+using GeminiLab.Core2;
using GeminiLab.Core2.ML.Json;
namespace TestConsole {
class Program {
public static void Main(string[] args) {
- var str = Console.In.ReadToEnd();
-
- var jsonValue = JsonParser.Parse(str);
- Console.WriteLine(jsonValue.ToString());
- Console.WriteLine(jsonValue.ToStringMinimized());
- Console.WriteLine(jsonValue.ToStringForNetwork());
- Console.WriteLine(jsonValue.ToStringPrettified());
+ Console.WriteLine("6Iuf5Yip5Zu95a6255Sf5q275Lul".DecodeBase64EncodedString());
}
}
}