diff --git a/Packages/UniGLTF/Runtime/UniGLTF/IO/GltfData.cs b/Packages/UniGLTF/Runtime/UniGLTF/IO/GltfData.cs index 2841754fd..7b5af2972 100644 --- a/Packages/UniGLTF/Runtime/UniGLTF/IO/GltfData.cs +++ b/Packages/UniGLTF/Runtime/UniGLTF/IO/GltfData.cs @@ -2,6 +2,7 @@ using System; using System.Collections.Generic; using System.Linq; using System.Runtime.InteropServices; +using UniJSON; using Unity.Collections; namespace UniGLTF @@ -32,7 +33,7 @@ namespace UniGLTF /// JSON chunk ToString /// > This chunk MUST be the very first chunk of Binary glTF asset /// - public string Json { get; } + public string Json => _jsonString ??= _utf8JsonString.ToString(); /// /// GLTF parsed from JSON chunk @@ -72,10 +73,39 @@ namespace UniGLTF /// Dictionary> _UriCache = new Dictionary>(); + /// + /// json string in utf8 + /// + Utf8String _utf8JsonString; + + /// + /// json string cache + /// + string _jsonString; + public GltfData(string targetPath, string json, glTF gltf, IReadOnlyList chunks, IStorage storage, MigrationFlags migrationFlags) { TargetPath = targetPath; - Json = json; + _jsonString = json; + GLTF = gltf; + Chunks = chunks; + _storage = storage; + MigrationFlags = migrationFlags; + + // init + if (Chunks != null) + { + if (Chunks.Count >= 2) + { + Bin = NativeArrayManager.CreateNativeArray(Chunks[1].Bytes); + } + } + } + + internal GltfData(string targetPath, Utf8String jsonString, glTF gltf, IReadOnlyList chunks, IStorage storage, MigrationFlags migrationFlags) + { + TargetPath = targetPath; + _utf8JsonString = jsonString; GLTF = gltf; Chunks = chunks; _storage = storage; @@ -441,4 +471,4 @@ namespace UniGLTF return false; } } -} +} \ No newline at end of file diff --git a/Packages/UniGLTF/Runtime/UniGLTF/IO/Parser/GlbLowLevelParser.cs b/Packages/UniGLTF/Runtime/UniGLTF/IO/Parser/GlbLowLevelParser.cs index 2207bc6cd..4aa2739d3 100644 --- a/Packages/UniGLTF/Runtime/UniGLTF/IO/Parser/GlbLowLevelParser.cs +++ b/Packages/UniGLTF/Runtime/UniGLTF/IO/Parser/GlbLowLevelParser.cs @@ -1,7 +1,6 @@ using System; using System.Collections.Generic; using System.IO; -using System.Text; using System.Text.RegularExpressions; using UniJSON; @@ -33,7 +32,7 @@ namespace UniGLTF var jsonBytes = chunks[0].Bytes; return ParseGltf( _path, - Encoding.UTF8.GetString(jsonBytes.Array, jsonBytes.Offset, jsonBytes.Count), + new Utf8String(new ArraySegment(jsonBytes.Array, jsonBytes.Offset, jsonBytes.Count)), chunks, default, new MigrationFlags() @@ -73,14 +72,20 @@ namespace UniGLTF public static GltfData ParseGltf(string path, string json, IReadOnlyList chunks, IStorage storage, MigrationFlags migrationFlags) { - var GLTF = GltfDeserializer.Deserialize(json.ParseAsJson()); + return ParseGltf(path, Utf8String.From(json), chunks, storage, migrationFlags); + } + + internal static GltfData ParseGltf(string path, Utf8String json, IReadOnlyList chunks, IStorage storage, MigrationFlags migrationFlags) + { + var parsedJson = json.ParseAsJson(); + var GLTF = GltfDeserializer.Deserialize(parsedJson); if (GLTF.asset.version != "2.0") { throw new UniGLTFException("unknown gltf version {0}", GLTF.asset.version); } // Version Compatibility - RestoreOlderVersionValues(json, GLTF); + RestoreOlderVersionValues(parsedJson, GLTF); FixMeshNameUnique(GLTF); FixBlendShapeNameUnique(GLTF); @@ -298,9 +303,8 @@ namespace UniGLTF } } - private static void RestoreOlderVersionValues(string Json, glTF GLTF) + private static void RestoreOlderVersionValues(JsonNode parsed, glTF GLTF) { - var parsed = UniJSON.JsonParser.Parse(Json); for (int i = 0; i < GLTF.images.Count; ++i) { if (string.IsNullOrEmpty(GLTF.images[i].name)) diff --git a/Packages/UniGLTF/Runtime/UniJSON/Json/JsonString.cs b/Packages/UniGLTF/Runtime/UniJSON/Json/JsonString.cs index ed145f272..712593d78 100644 --- a/Packages/UniGLTF/Runtime/UniJSON/Json/JsonString.cs +++ b/Packages/UniGLTF/Runtime/UniJSON/Json/JsonString.cs @@ -395,6 +395,28 @@ namespace UniJSON return writeCount; } + private static Utf8String Unescape(Utf8String s) + { + var span = s.AsSpan(); + var escapeIndex = span.IndexOf((byte)'\\'); + + // escape not found + if (escapeIndex == -1) + { + return s; + } + + var sb = new BytesStore(s.ByteLength); + foreach (var b in span[..escapeIndex]) + { + sb.Write(b); + } + + Unescape(s.Subbytes(escapeIndex), sb); + return new Utf8String(sb.Bytes); + } + + public static string Unescape(string src) { var sb = new StringBuilder(); @@ -430,18 +452,9 @@ namespace UniJSON 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); - } + return Unescape(src.Subbytes(1, src.ByteLength - 2)); } + #endregion } -} +} \ No newline at end of file diff --git a/Packages/UniGLTF/Runtime/UniJSON/Json/JsonValue.cs b/Packages/UniGLTF/Runtime/UniJSON/Json/JsonValue.cs index 450308540..1e0d6545f 100644 --- a/Packages/UniGLTF/Runtime/UniJSON/Json/JsonValue.cs +++ b/Packages/UniGLTF/Runtime/UniJSON/Json/JsonValue.cs @@ -101,7 +101,7 @@ namespace UniJSON public UInt64 GetUInt64() { return Segment.ToUInt64(); } public Single GetSingle() { return Segment.ToSingle(); } public Double GetDouble() { return Segment.ToDouble(); } - public String GetString() { return JsonString.Unquote(Segment.ToString()); } + public String GetString() { return JsonString.Unquote(Segment).ToString(); } public Utf8String GetUtf8String() { return JsonString.Unquote(Segment); } } -} +} \ No newline at end of file diff --git a/Packages/UniGLTF/Runtime/UniJSON/Utf8String/Utf8String.cs b/Packages/UniGLTF/Runtime/UniJSON/Utf8String/Utf8String.cs index 020f127f8..734132be4 100644 --- a/Packages/UniGLTF/Runtime/UniJSON/Utf8String/Utf8String.cs +++ b/Packages/UniGLTF/Runtime/UniJSON/Utf8String/Utf8String.cs @@ -110,6 +110,8 @@ namespace UniJSON return new Utf8String(bytes); } + public ReadOnlySpan AsSpan() => Bytes.AsSpan(); + public override string ToString() { if (ByteLength == 0) return ""; @@ -324,4 +326,4 @@ namespace UniJSON } } } -} +} \ No newline at end of file diff --git a/Packages/UniGLTF/Runtime/UniJSON/Utf8String/Utf8StringExtensions.cs b/Packages/UniGLTF/Runtime/UniJSON/Utf8String/Utf8StringExtensions.cs index e0df03db3..8222a258a 100644 --- a/Packages/UniGLTF/Runtime/UniJSON/Utf8String/Utf8StringExtensions.cs +++ b/Packages/UniGLTF/Runtime/UniJSON/Utf8String/Utf8StringExtensions.cs @@ -1,5 +1,7 @@ using System; +using System.Buffers; using System.Collections.Generic; +using System.Globalization; using System.IO; @@ -320,11 +322,46 @@ namespace UniJSON public static float ToSingle(this Utf8String src) { - return Single.Parse(src.ToAscii(), System.Globalization.CultureInfo.InvariantCulture); + char[] arrayToReturn = null; + try + { + var srcBytes = src.AsSpan(); + Span chars = srcBytes.Length < 64 + ? stackalloc char[srcBytes.Length] + : arrayToReturn = ArrayPool.Shared.Rent(srcBytes.Length); + var count = System.Text.Encoding.ASCII.GetChars(srcBytes, chars); + return Single.Parse(chars[..count], NumberStyles.Float | NumberStyles.AllowThousands, + System.Globalization.CultureInfo.InvariantCulture); + } + finally + { + if (arrayToReturn != null) + { + ArrayPool.Shared.Return(arrayToReturn); + } + } } + public static double ToDouble(this Utf8String src) { - return Double.Parse(src.ToAscii(), System.Globalization.CultureInfo.InvariantCulture); + char[] arrayToReturn = null; + try + { + var srcBytes = src.AsSpan(); + Span chars = srcBytes.Length < 64 + ? stackalloc char[srcBytes.Length] + : arrayToReturn = ArrayPool.Shared.Rent(srcBytes.Length); + var count = System.Text.Encoding.ASCII.GetChars(srcBytes, chars); + return Double.Parse(chars[..count], NumberStyles.Float | NumberStyles.AllowThousands, + System.Globalization.CultureInfo.InvariantCulture); + } + finally + { + if (arrayToReturn != null) + { + ArrayPool.Shared.Return(arrayToReturn); + } + } } public static Utf8String GetLine(this Utf8String src)