<commit_before>﻿using System;
using System.Collections.Generic;
using GLTF.JsonExtensions;
using Newtonsoft.Json;

namespace GLTF
{
    public class GLTFProperty
    {
        private static Dictionary<string, GLTFExtensionFactory> _extensionRegistry = new Dictionary<string, GLTFExtensionFactory>();

        public static void RegisterExtension(GLTFExtensionFactory extensionFactory)
        {
            _extensionRegistry.Add(extensionFactory.ExtensionName, extensionFactory);
        }

        public Dictionary<string, GLTFExtension> Extensions;
        public Dictionary<string, object> Extras;

        public void DefaultPropertyDeserializer(GLTFRoot root, JsonTextReader reader)
        {
            switch (reader.Value.ToString())
            {
                case "extensions":
                    Extensions = DeserializeExtensions(root, reader);
                    break;
                case "extras":
                    Extras = reader.ReadAsObjectDictionary();
                    break;
                default:
                    throw new Exception(string.Format("Unexpected property: {0} at: {1}", reader.Value, reader.Path));
            }
        }

        private Dictionary<string, GLTFExtension> DeserializeExtensions(GLTFRoot root, JsonTextReader reader)
        {
            if (reader.Read() && reader.TokenType != JsonToken.StartObject)
            {
                throw new Exception("GLTF extensions must be an object");
            }

            var extensions = new Dictionary<string, GLTFExtension>();

            while (reader.Read() && reader.TokenType == JsonToken.PropertyName)
            {
                var extensionName = reader.Value.ToString();
                GLTFExtensionFactory extensionFactory;

                if (_extensionRegistry.TryGetValue(extensionName, out extensionFactory))
                {
                    extensions.Add(extensionName, extensionFactory.Deserialize(root, reader));
                }
                else
                {
                    reader.ReadAsObjectDictionary();
                }
            }

            return extensions;
        }

        public virtual void Serialize(JsonWriter writer)
        {
            if (Extensions != null && Extensions.Count > 0)
            {
                writer.WritePropertyName("extensions");
                writer.WriteStartArray();
                foreach (var extension in Extensions)
                {
                    writer.WritePropertyName(extension.Key);
                    extension.Value.Serialize(writer);
                }<commit_msg>Support additional properties. Skip unregistered extensions.<commit_after>﻿using System;
using System.Collections.Generic;
using GLTF.JsonExtensions;
using Newtonsoft.Json;

namespace GLTF
{
    public class GLTFProperty
    {
        private static Dictionary<string, GLTFExtensionFactory> _extensionRegistry = new Dictionary<string, GLTFExtensionFactory>();

        public static void RegisterExtension(GLTFExtensionFactory extensionFactory)
        {
            _extensionRegistry.Add(extensionFactory.ExtensionName, extensionFactory);
        }

        public Dictionary<string, GLTFExtension> Extensions;
        public Dictionary<string, object> Extras;

        public void DefaultPropertyDeserializer(GLTFRoot root, JsonTextReader reader)
        {
            switch (reader.Value.ToString())
            {
                case "extensions":
                    Extensions = DeserializeExtensions(root, reader);
                    break;
                case "extras":
                    Extras = reader.ReadAsObjectDictionary();
                    break;
                default:
                    SkipValue(reader);
                    break;
            }
        }

        private void SkipValue(JsonReader reader)
        {
            if (!reader.Read())
            {
                throw new Exception("No value found.");
            }

            if (reader.TokenType == JsonToken.StartObject)
            {
                SkipObject(reader);
            }
            else if (reader.TokenType == JsonToken.StartArray)
            {
                SkipArray(reader);
            }
        }

        private void SkipObject(JsonReader reader)
        {
            while (reader.Read() && reader.TokenType != JsonToken.EndObject) {
                if (reader.TokenType == JsonToken.StartArray)
                {
                    SkipArray(reader);
                }
                else if (reader.TokenType == JsonToken.StartObject)
                {
                    SkipObject(reader);
                }
            }
        }

        private void SkipArray(JsonReader reader)
        {
            while (reader.Read() && reader.TokenType != JsonToken.EndArray) {
                if (reader.TokenType == JsonToken.StartArray)
                {
                    SkipArray(reader);
                }
                else if (reader.TokenType == JsonToken.StartObject)
                {
                    SkipObject(reader);
                }
            }
        }

        private Dictionary<string, GLTFExtension> DeserializeExtensions(GLTFRoot root, JsonTextReader reader)
        {
            if (reader.Read() && reader.TokenType != JsonToken.StartObject)
            {
                throw new Exception("GLTF extensions must be an object");
            }

            var extensions = new Dictionary<string, GLTFExtension>();

            while (reader.Read() && reader.TokenType == JsonToken.PropertyName)
            {
                var extensionName = reader.Value.ToString();
                GLTFExtensionFactory extensionFactory;

                if (_extensionRegistry.TryGetValue(extensionName, out extensionFactory))
                {
                    extensions.Add(extensionName, extensionFactory.Deserialize(root, reader));
                }
                else
                {
                    SkipValue(reader);
                }
            }

            return extensions;
        }

        public virtual void Serialize(JsonWriter writer)
        {
            if (Extensions != null && Extensions.Count > 0)
            {
                writer.WritePropertyName("extensions");
                writer.WriteStartArray();
                foreach (var extension in Extensions)
                {
                    writer.WritePropertyName(extension.Key);
                    extension.Value.Serialize(writer);
                }
{'fraction_non_alphanumeric': 0.07902409083934325, 'fraction_numerical': 0.0006137793463249962, 'mean_word_length': 1.5450995704802812, 'pattern_counts': {'":': 4, '<': 15, '<?xml version=': 0, '>': 17, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3301260', 'n_tokens_mistral': 1481, 'n_tokens_neox': 1386, 'n_words': 308}