Update rapidjson-amalgamation to include error/en.h and cursorstreamwrapper.h.
Now schema validation is getting to work.
diff --git a/README.md b/README.md
index e085c02..7ac0e2b 100644
--- a/README.md
+++ b/README.md
@@ -70,6 +70,7 @@
 ## For developer
 
 Generate single rapidjson file using this node.js script: https://github.com/Tencent/rapidjson/issues/863
+Add `cursorstreamwrapper.h` and `error/en.h` inclusion in `rapidjson-all.h` before running merge script.
 
 ## TODOs
 
diff --git a/loader_example.cc b/loader_example.cc
index c0eec95..6bcff91 100644
--- a/loader_example.cc
+++ b/loader_example.cc
@@ -2,6 +2,7 @@
 // TODO(syoyo): Print extensions and extras for each glTF object.
 //
 #define TINYGLTF_IMPLEMENTATION
+#define TINYGLTF_ENABLE_SCHEMA_VALIDATOR
 #define STB_IMAGE_IMPLEMENTATION
 #define STB_IMAGE_WRITE_IMPLEMENTATION
 #include "tiny_gltf.h"
@@ -640,8 +641,13 @@
   } else {
     std::cout << "Reading ASCII glTF" << std::endl;
     // assume ascii glTF.
+#if defined(TINYGLTF_ENABLE_SCHEMA_VALIDATOR)
+    ret =
+        gltf_ctx.LoadASCIIFromFileWithValidation(&model, &err, &warn, input_filename.c_str());
+#else
     ret =
         gltf_ctx.LoadASCIIFromFile(&model, &err, &warn, input_filename.c_str());
+#endif
   }
 
   if (!warn.empty()) {
diff --git a/rapidjson-amalgamation.h b/rapidjson-amalgamation.h
index 2578092..0d15082 100644
--- a/rapidjson-amalgamation.h
+++ b/rapidjson-amalgamation.h
@@ -1581,7 +1581,7 @@
 // End file:allocators.h

 

 

-// Begin file: document.h

+// Begin file: error/en.h

 // Tencent is pleased to support the open source community by making RapidJSON available.

 // 

 // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.

@@ -1596,13 +1596,240 @@
 // CONDITIONS OF ANY KIND, either express or implied. See the License for the 

 // specific language governing permissions and limitations under the License.

 

-#ifndef RAPIDJSON_DOCUMENT_H_

-#define RAPIDJSON_DOCUMENT_H_

-

-/*! \file document.h */

+#ifndef RAPIDJSON_ERROR_EN_H_

+#define RAPIDJSON_ERROR_EN_H_

 

 

-// Begin file: reader.h

+// Begin file: error.h

+// Tencent is pleased to support the open source community by making RapidJSON available.

+// 

+// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.

+//

+// Licensed under the MIT License (the "License"); you may not use this file except

+// in compliance with the License. You may obtain a copy of the License at

+//

+// http://opensource.org/licenses/MIT

+//

+// Unless required by applicable law or agreed to in writing, software distributed 

+// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 

+// CONDITIONS OF ANY KIND, either express or implied. See the License for the 

+// specific language governing permissions and limitations under the License.

+

+#ifndef RAPIDJSON_ERROR_ERROR_H_

+#define RAPIDJSON_ERROR_ERROR_H_

+

+

+// Begin file: ../rapidjson.h

+// already included

+// End file:../rapidjson.h

+

+

+#ifdef __clang__

+RAPIDJSON_DIAG_PUSH

+RAPIDJSON_DIAG_OFF(padded)

+#endif

+

+/*! \file error.h */

+

+/*! \defgroup RAPIDJSON_ERRORS RapidJSON error handling */

+

+///////////////////////////////////////////////////////////////////////////////

+// RAPIDJSON_ERROR_CHARTYPE

+

+//! Character type of error messages.

+/*! \ingroup RAPIDJSON_ERRORS

+    The default character type is \c char.

+    On Windows, user can define this macro as \c TCHAR for supporting both

+    unicode/non-unicode settings.

+*/

+#ifndef RAPIDJSON_ERROR_CHARTYPE

+#define RAPIDJSON_ERROR_CHARTYPE char

+#endif

+

+///////////////////////////////////////////////////////////////////////////////

+// RAPIDJSON_ERROR_STRING

+

+//! Macro for converting string literial to \ref RAPIDJSON_ERROR_CHARTYPE[].

+/*! \ingroup RAPIDJSON_ERRORS

+    By default this conversion macro does nothing.

+    On Windows, user can define this macro as \c _T(x) for supporting both

+    unicode/non-unicode settings.

+*/

+#ifndef RAPIDJSON_ERROR_STRING

+#define RAPIDJSON_ERROR_STRING(x) x

+#endif

+

+RAPIDJSON_NAMESPACE_BEGIN

+

+///////////////////////////////////////////////////////////////////////////////

+// ParseErrorCode

+

+//! Error code of parsing.

+/*! \ingroup RAPIDJSON_ERRORS

+    \see GenericReader::Parse, GenericReader::GetParseErrorCode

+*/

+enum ParseErrorCode {

+    kParseErrorNone = 0,                        //!< No error.

+

+    kParseErrorDocumentEmpty,                   //!< The document is empty.

+    kParseErrorDocumentRootNotSingular,         //!< The document root must not follow by other values.

+

+    kParseErrorValueInvalid,                    //!< Invalid value.

+

+    kParseErrorObjectMissName,                  //!< Missing a name for object member.

+    kParseErrorObjectMissColon,                 //!< Missing a colon after a name of object member.

+    kParseErrorObjectMissCommaOrCurlyBracket,   //!< Missing a comma or '}' after an object member.

+

+    kParseErrorArrayMissCommaOrSquareBracket,   //!< Missing a comma or ']' after an array element.

+

+    kParseErrorStringUnicodeEscapeInvalidHex,   //!< Incorrect hex digit after \\u escape in string.

+    kParseErrorStringUnicodeSurrogateInvalid,   //!< The surrogate pair in string is invalid.

+    kParseErrorStringEscapeInvalid,             //!< Invalid escape character in string.

+    kParseErrorStringMissQuotationMark,         //!< Missing a closing quotation mark in string.

+    kParseErrorStringInvalidEncoding,           //!< Invalid encoding in string.

+

+    kParseErrorNumberTooBig,                    //!< Number too big to be stored in double.

+    kParseErrorNumberMissFraction,              //!< Miss fraction part in number.

+    kParseErrorNumberMissExponent,              //!< Miss exponent in number.

+

+    kParseErrorTermination,                     //!< Parsing was terminated.

+    kParseErrorUnspecificSyntaxError            //!< Unspecific syntax error.

+};

+

+//! Result of parsing (wraps ParseErrorCode)

+/*!

+    \ingroup RAPIDJSON_ERRORS

+    \code

+        Document doc;

+        ParseResult ok = doc.Parse("[42]");

+        if (!ok) {

+            fprintf(stderr, "JSON parse error: %s (%u)",

+                    GetParseError_En(ok.Code()), ok.Offset());

+            exit(EXIT_FAILURE);

+        }

+    \endcode

+    \see GenericReader::Parse, GenericDocument::Parse

+*/

+struct ParseResult {

+    //!! Unspecified boolean type

+    typedef bool (ParseResult::*BooleanType)() const;

+public:

+    //! Default constructor, no error.

+    ParseResult() : code_(kParseErrorNone), offset_(0) {}

+    //! Constructor to set an error.

+    ParseResult(ParseErrorCode code, size_t offset) : code_(code), offset_(offset) {}

+

+    //! Get the error code.

+    ParseErrorCode Code() const { return code_; }

+    //! Get the error offset, if \ref IsError(), 0 otherwise.

+    size_t Offset() const { return offset_; }

+

+    //! Explicit conversion to \c bool, returns \c true, iff !\ref IsError().

+    operator BooleanType() const { return !IsError() ? &ParseResult::IsError : NULL; }

+    //! Whether the result is an error.

+    bool IsError() const { return code_ != kParseErrorNone; }

+

+    bool operator==(const ParseResult& that) const { return code_ == that.code_; }

+    bool operator==(ParseErrorCode code) const { return code_ == code; }

+    friend bool operator==(ParseErrorCode code, const ParseResult & err) { return code == err.code_; }

+

+    bool operator!=(const ParseResult& that) const { return !(*this == that); }

+    bool operator!=(ParseErrorCode code) const { return !(*this == code); }

+    friend bool operator!=(ParseErrorCode code, const ParseResult & err) { return err != code; }

+

+    //! Reset error code.

+    void Clear() { Set(kParseErrorNone); }

+    //! Update error code and offset.

+    void Set(ParseErrorCode code, size_t offset = 0) { code_ = code; offset_ = offset; }

+

+private:

+    ParseErrorCode code_;

+    size_t offset_;

+};

+

+//! Function pointer type of GetParseError().

+/*! \ingroup RAPIDJSON_ERRORS

+

+    This is the prototype for \c GetParseError_X(), where \c X is a locale.

+    User can dynamically change locale in runtime, e.g.:

+\code

+    GetParseErrorFunc GetParseError = GetParseError_En; // or whatever

+    const RAPIDJSON_ERROR_CHARTYPE* s = GetParseError(document.GetParseErrorCode());

+\endcode

+*/

+typedef const RAPIDJSON_ERROR_CHARTYPE* (*GetParseErrorFunc)(ParseErrorCode);

+

+RAPIDJSON_NAMESPACE_END

+

+#ifdef __clang__

+RAPIDJSON_DIAG_POP

+#endif

+

+#endif // RAPIDJSON_ERROR_ERROR_H_

+

+// End file:error.h

+

+

+#ifdef __clang__

+RAPIDJSON_DIAG_PUSH

+RAPIDJSON_DIAG_OFF(switch-enum)

+RAPIDJSON_DIAG_OFF(covered-switch-default)

+#endif

+

+RAPIDJSON_NAMESPACE_BEGIN

+

+//! Maps error code of parsing into error message.

+/*!

+    \ingroup RAPIDJSON_ERRORS

+    \param parseErrorCode Error code obtained in parsing.

+    \return the error message.

+    \note User can make a copy of this function for localization.

+        Using switch-case is safer for future modification of error codes.

+*/

+inline const RAPIDJSON_ERROR_CHARTYPE* GetParseError_En(ParseErrorCode parseErrorCode) {

+    switch (parseErrorCode) {

+        case kParseErrorNone:                           return RAPIDJSON_ERROR_STRING("No error.");

+

+        case kParseErrorDocumentEmpty:                  return RAPIDJSON_ERROR_STRING("The document is empty.");

+        case kParseErrorDocumentRootNotSingular:        return RAPIDJSON_ERROR_STRING("The document root must not be followed by other values.");

+    

+        case kParseErrorValueInvalid:                   return RAPIDJSON_ERROR_STRING("Invalid value.");

+    

+        case kParseErrorObjectMissName:                 return RAPIDJSON_ERROR_STRING("Missing a name for object member.");

+        case kParseErrorObjectMissColon:                return RAPIDJSON_ERROR_STRING("Missing a colon after a name of object member.");

+        case kParseErrorObjectMissCommaOrCurlyBracket:  return RAPIDJSON_ERROR_STRING("Missing a comma or '}' after an object member.");

+    

+        case kParseErrorArrayMissCommaOrSquareBracket:  return RAPIDJSON_ERROR_STRING("Missing a comma or ']' after an array element.");

+

+        case kParseErrorStringUnicodeEscapeInvalidHex:  return RAPIDJSON_ERROR_STRING("Incorrect hex digit after \\u escape in string.");

+        case kParseErrorStringUnicodeSurrogateInvalid:  return RAPIDJSON_ERROR_STRING("The surrogate pair in string is invalid.");

+        case kParseErrorStringEscapeInvalid:            return RAPIDJSON_ERROR_STRING("Invalid escape character in string.");

+        case kParseErrorStringMissQuotationMark:        return RAPIDJSON_ERROR_STRING("Missing a closing quotation mark in string.");

+        case kParseErrorStringInvalidEncoding:          return RAPIDJSON_ERROR_STRING("Invalid encoding in string.");

+

+        case kParseErrorNumberTooBig:                   return RAPIDJSON_ERROR_STRING("Number too big to be stored in double.");

+        case kParseErrorNumberMissFraction:             return RAPIDJSON_ERROR_STRING("Miss fraction part in number.");

+        case kParseErrorNumberMissExponent:             return RAPIDJSON_ERROR_STRING("Miss exponent in number.");

+

+        case kParseErrorTermination:                    return RAPIDJSON_ERROR_STRING("Terminate parsing due to Handler error.");

+        case kParseErrorUnspecificSyntaxError:          return RAPIDJSON_ERROR_STRING("Unspecific syntax error.");

+

+        default:                                        return RAPIDJSON_ERROR_STRING("Unknown error.");

+    }

+}

+

+RAPIDJSON_NAMESPACE_END

+

+#ifdef __clang__

+RAPIDJSON_DIAG_POP

+#endif

+

+#endif // RAPIDJSON_ERROR_EN_H_

+

+// End file:error/en.h

+

+

+// Begin file: cursorstreamwrapper.h

 // Tencent is pleased to support the open source community by making RapidJSON available.

 //

 // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.

@@ -1617,15 +1844,8 @@
 // CONDITIONS OF ANY KIND, either express or implied. See the License for the

 // specific language governing permissions and limitations under the License.

 

-#ifndef RAPIDJSON_READER_H_

-#define RAPIDJSON_READER_H_

-

-/*! \file reader.h */

-

-

-// Begin file: allocators.h

-// already included

-// End file:allocators.h

+#ifndef RAPIDJSON_CURSORSTREAMWRAPPER_H_

+#define RAPIDJSON_CURSORSTREAMWRAPPER_H_

 

 

 // Begin file: stream.h

@@ -2584,6 +2804,121 @@
 // End file:stream.h

 

 

+#if defined(__GNUC__)

+RAPIDJSON_DIAG_PUSH

+RAPIDJSON_DIAG_OFF(effc++)

+#endif

+

+#if defined(_MSC_VER) && _MSC_VER <= 1800

+RAPIDJSON_DIAG_PUSH

+RAPIDJSON_DIAG_OFF(4702)  // unreachable code

+RAPIDJSON_DIAG_OFF(4512)  // assignment operator could not be generated

+#endif

+

+RAPIDJSON_NAMESPACE_BEGIN

+

+

+//! Cursor stream wrapper for counting line and column number if error exists.

+/*!

+    \tparam InputStream     Any stream that implements Stream Concept

+*/

+template <typename InputStream, typename Encoding = UTF8<> >

+class CursorStreamWrapper : public GenericStreamWrapper<InputStream, Encoding> {

+public:

+    typedef typename Encoding::Ch Ch;

+

+    CursorStreamWrapper(InputStream& is):

+        GenericStreamWrapper<InputStream, Encoding>(is), line_(1), col_(0) {}

+

+    // counting line and column number

+    Ch Take() {

+        Ch ch = this->is_.Take();

+        if(ch == '\n') {

+            line_ ++;

+            col_ = 0;

+        } else {

+            col_ ++;

+        }

+        return ch;

+    }

+

+    //! Get the error line number, if error exists.

+    size_t GetLine() const { return line_; }

+    //! Get the error column number, if error exists.

+    size_t GetColumn() const { return col_; }

+

+private:

+    size_t line_;   //!< Current Line

+    size_t col_;    //!< Current Column

+};

+

+#if defined(_MSC_VER) && _MSC_VER <= 1800

+RAPIDJSON_DIAG_POP

+#endif

+

+#if defined(__GNUC__)

+RAPIDJSON_DIAG_POP

+#endif

+

+RAPIDJSON_NAMESPACE_END

+

+#endif // RAPIDJSON_CURSORSTREAMWRAPPER_H_

+

+// End file:cursorstreamwrapper.h

+

+

+// Begin file: document.h

+// Tencent is pleased to support the open source community by making RapidJSON available.

+// 

+// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.

+//

+// Licensed under the MIT License (the "License"); you may not use this file except

+// in compliance with the License. You may obtain a copy of the License at

+//

+// http://opensource.org/licenses/MIT

+//

+// Unless required by applicable law or agreed to in writing, software distributed 

+// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 

+// CONDITIONS OF ANY KIND, either express or implied. See the License for the 

+// specific language governing permissions and limitations under the License.

+

+#ifndef RAPIDJSON_DOCUMENT_H_

+#define RAPIDJSON_DOCUMENT_H_

+

+/*! \file document.h */

+

+

+// Begin file: reader.h

+// Tencent is pleased to support the open source community by making RapidJSON available.

+//

+// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.

+//

+// Licensed under the MIT License (the "License"); you may not use this file except

+// in compliance with the License. You may obtain a copy of the License at

+//

+// http://opensource.org/licenses/MIT

+//

+// Unless required by applicable law or agreed to in writing, software distributed

+// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR

+// CONDITIONS OF ANY KIND, either express or implied. See the License for the

+// specific language governing permissions and limitations under the License.

+

+#ifndef RAPIDJSON_READER_H_

+#define RAPIDJSON_READER_H_

+

+/*! \file reader.h */

+

+

+// Begin file: allocators.h

+// already included

+// End file:allocators.h

+

+

+// Begin file: stream.h

+// already included

+// End file:stream.h

+

+

 // Begin file: encodedstream.h

 // Tencent is pleased to support the open source community by making RapidJSON available.

 // 

@@ -4582,172 +4917,7 @@
 

 

 // Begin file: error/error.h

-// Tencent is pleased to support the open source community by making RapidJSON available.

-// 

-// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.

-//

-// Licensed under the MIT License (the "License"); you may not use this file except

-// in compliance with the License. You may obtain a copy of the License at

-//

-// http://opensource.org/licenses/MIT

-//

-// Unless required by applicable law or agreed to in writing, software distributed 

-// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 

-// CONDITIONS OF ANY KIND, either express or implied. See the License for the 

-// specific language governing permissions and limitations under the License.

-

-#ifndef RAPIDJSON_ERROR_ERROR_H_

-#define RAPIDJSON_ERROR_ERROR_H_

-

-

-// Begin file: ../rapidjson.h

 // already included

-// End file:../rapidjson.h

-

-

-#ifdef __clang__

-RAPIDJSON_DIAG_PUSH

-RAPIDJSON_DIAG_OFF(padded)

-#endif

-

-/*! \file error.h */

-

-/*! \defgroup RAPIDJSON_ERRORS RapidJSON error handling */

-

-///////////////////////////////////////////////////////////////////////////////

-// RAPIDJSON_ERROR_CHARTYPE

-

-//! Character type of error messages.

-/*! \ingroup RAPIDJSON_ERRORS

-    The default character type is \c char.

-    On Windows, user can define this macro as \c TCHAR for supporting both

-    unicode/non-unicode settings.

-*/

-#ifndef RAPIDJSON_ERROR_CHARTYPE

-#define RAPIDJSON_ERROR_CHARTYPE char

-#endif

-

-///////////////////////////////////////////////////////////////////////////////

-// RAPIDJSON_ERROR_STRING

-

-//! Macro for converting string literial to \ref RAPIDJSON_ERROR_CHARTYPE[].

-/*! \ingroup RAPIDJSON_ERRORS

-    By default this conversion macro does nothing.

-    On Windows, user can define this macro as \c _T(x) for supporting both

-    unicode/non-unicode settings.

-*/

-#ifndef RAPIDJSON_ERROR_STRING

-#define RAPIDJSON_ERROR_STRING(x) x

-#endif

-

-RAPIDJSON_NAMESPACE_BEGIN

-

-///////////////////////////////////////////////////////////////////////////////

-// ParseErrorCode

-

-//! Error code of parsing.

-/*! \ingroup RAPIDJSON_ERRORS

-    \see GenericReader::Parse, GenericReader::GetParseErrorCode

-*/

-enum ParseErrorCode {

-    kParseErrorNone = 0,                        //!< No error.

-

-    kParseErrorDocumentEmpty,                   //!< The document is empty.

-    kParseErrorDocumentRootNotSingular,         //!< The document root must not follow by other values.

-

-    kParseErrorValueInvalid,                    //!< Invalid value.

-

-    kParseErrorObjectMissName,                  //!< Missing a name for object member.

-    kParseErrorObjectMissColon,                 //!< Missing a colon after a name of object member.

-    kParseErrorObjectMissCommaOrCurlyBracket,   //!< Missing a comma or '}' after an object member.

-

-    kParseErrorArrayMissCommaOrSquareBracket,   //!< Missing a comma or ']' after an array element.

-

-    kParseErrorStringUnicodeEscapeInvalidHex,   //!< Incorrect hex digit after \\u escape in string.

-    kParseErrorStringUnicodeSurrogateInvalid,   //!< The surrogate pair in string is invalid.

-    kParseErrorStringEscapeInvalid,             //!< Invalid escape character in string.

-    kParseErrorStringMissQuotationMark,         //!< Missing a closing quotation mark in string.

-    kParseErrorStringInvalidEncoding,           //!< Invalid encoding in string.

-

-    kParseErrorNumberTooBig,                    //!< Number too big to be stored in double.

-    kParseErrorNumberMissFraction,              //!< Miss fraction part in number.

-    kParseErrorNumberMissExponent,              //!< Miss exponent in number.

-

-    kParseErrorTermination,                     //!< Parsing was terminated.

-    kParseErrorUnspecificSyntaxError            //!< Unspecific syntax error.

-};

-

-//! Result of parsing (wraps ParseErrorCode)

-/*!

-    \ingroup RAPIDJSON_ERRORS

-    \code

-        Document doc;

-        ParseResult ok = doc.Parse("[42]");

-        if (!ok) {

-            fprintf(stderr, "JSON parse error: %s (%u)",

-                    GetParseError_En(ok.Code()), ok.Offset());

-            exit(EXIT_FAILURE);

-        }

-    \endcode

-    \see GenericReader::Parse, GenericDocument::Parse

-*/

-struct ParseResult {

-    //!! Unspecified boolean type

-    typedef bool (ParseResult::*BooleanType)() const;

-public:

-    //! Default constructor, no error.

-    ParseResult() : code_(kParseErrorNone), offset_(0) {}

-    //! Constructor to set an error.

-    ParseResult(ParseErrorCode code, size_t offset) : code_(code), offset_(offset) {}

-

-    //! Get the error code.

-    ParseErrorCode Code() const { return code_; }

-    //! Get the error offset, if \ref IsError(), 0 otherwise.

-    size_t Offset() const { return offset_; }

-

-    //! Explicit conversion to \c bool, returns \c true, iff !\ref IsError().

-    operator BooleanType() const { return !IsError() ? &ParseResult::IsError : NULL; }

-    //! Whether the result is an error.

-    bool IsError() const { return code_ != kParseErrorNone; }

-

-    bool operator==(const ParseResult& that) const { return code_ == that.code_; }

-    bool operator==(ParseErrorCode code) const { return code_ == code; }

-    friend bool operator==(ParseErrorCode code, const ParseResult & err) { return code == err.code_; }

-

-    bool operator!=(const ParseResult& that) const { return !(*this == that); }

-    bool operator!=(ParseErrorCode code) const { return !(*this == code); }

-    friend bool operator!=(ParseErrorCode code, const ParseResult & err) { return err != code; }

-

-    //! Reset error code.

-    void Clear() { Set(kParseErrorNone); }

-    //! Update error code and offset.

-    void Set(ParseErrorCode code, size_t offset = 0) { code_ = code; offset_ = offset; }

-

-private:

-    ParseErrorCode code_;

-    size_t offset_;

-};

-

-//! Function pointer type of GetParseError().

-/*! \ingroup RAPIDJSON_ERRORS

-

-    This is the prototype for \c GetParseError_X(), where \c X is a locale.

-    User can dynamically change locale in runtime, e.g.:

-\code

-    GetParseErrorFunc GetParseError = GetParseError_En; // or whatever

-    const RAPIDJSON_ERROR_CHARTYPE* s = GetParseError(document.GetParseErrorCode());

-\endcode

-*/

-typedef const RAPIDJSON_ERROR_CHARTYPE* (*GetParseErrorFunc)(ParseErrorCode);

-

-RAPIDJSON_NAMESPACE_END

-

-#ifdef __clang__

-RAPIDJSON_DIAG_POP

-#endif

-

-#endif // RAPIDJSON_ERROR_ERROR_H_

-

 // End file:error/error.h

 

 

@@ -16733,3 +16903,4 @@
 // Begin file: writer.h

 // already included

 // End file:writer.h

+

diff --git a/tiny_gltf.h b/tiny_gltf.h
index 9c7a479..b702597 100644
--- a/tiny_gltf.h
+++ b/tiny_gltf.h
@@ -921,13 +921,13 @@
 #pragma clang diagnostic ignored "-Wc++98-compat"
 #endif
 
-  TinyGLTF() : bin_data_(nullptr), bin_size_(0), is_binary_(false) {}
+  TinyGLTF();
 
 #ifdef __clang__
 #pragma clang diagnostic pop
 #endif
 
-  ~TinyGLTF() {}
+  ~TinyGLTF();
 
   ///
   /// Loads glTF ASCII asset from a file.
@@ -1048,8 +1048,12 @@
       nullptr;
 #endif
   void *write_image_user_data_ = reinterpret_cast<void *>(&fs);
+
+  class PImpl;
+  PImpl *pimpl_;
 };
 
+
 #ifdef __clang__
 #pragma clang diagnostic pop  // -Wpadded
 #endif
@@ -1200,7 +1204,7 @@
 
 #if defined(TINYGLTF_ENABLE_SCHEMA_VALIDATOR)
 // Include glTF Schema as embedded C string
-#include "glTF.schema.resolved.inc"
+#include "gltf.schema.resolved.inc"
 #endif
 
 // Equals function for Value, for recursivity
@@ -1617,6 +1621,55 @@
 #pragma clang diagnostic pop
 #endif
 
+class TinyGLTF::PImpl
+{
+  public:
+
+  PImpl() {
+#if defined(TINYGLTF_ENABLE_SCHEMA_VALIDATOR)
+    validator_ = nullptr;
+#endif
+  }
+
+  ~PImpl()
+  {
+#if defined(TINYGLTF_ENABLE_SCHEMA_VALIDATOR)
+    if (schema_doc_) {
+      delete schema_doc_;
+    }
+
+    if (schema_) {
+      delete schema_;
+    }
+
+    if (validator_) {
+      delete validator_;
+    }
+
+#endif
+  }
+
+#if defined(TINYGLTF_ENABLE_SCHEMA_VALIDATOR)
+
+  std::string schema_json_string_;
+  rapidjson::Document *schema_doc_;
+  rapidjson::SchemaDocument *schema_;
+  rapidjson::SchemaValidator *validator_;
+#endif
+};
+
+
+TinyGLTF::TinyGLTF() : bin_data_(nullptr), bin_size_(0), is_binary_(false) {
+  pimpl_ = new TinyGLTF::PImpl();
+}
+
+TinyGLTF::~TinyGLTF()
+{
+  if (pimpl_) {
+    delete pimpl_;
+  }
+}
+
 static bool LoadExternalFile(std::vector<unsigned char> *out, std::string *err,
                              std::string *warn, const std::string &filename,
                              const std::string &basedir, bool required,
@@ -3722,13 +3775,25 @@
     return false;
   }
 
+  // To enable error report with lines and columns,
+  // We'll use CursorStreamWrapper.
+  // https://github.com/Tencent/rapidjson/pull/1070
+  // It looks StringStream does not have a constrcutor with (str, len),
+  // so create a temporary string and ensure it ends with NULL character.
+  // although this is a bit redundant...
+  std::string in_str(str, length);
+
+  rapidjson::StringStream sis(in_str.c_str());
+
+  rapidjson::CursorStreamWrapper<rapidjson::StringStream> csw(sis);
+
   rapidjson::Document v;
 
 #if (defined(__cpp_exceptions) || defined(__EXCEPTIONS) || \
      defined(_CPPUNWIND)) &&                               \
     !defined(TINYGLTF_NOEXCEPTION)
   try {
-    v.Parse(str);
+    v.ParseStream(csw);
 
   } catch (const std::exception &e) {
     if (err) {
@@ -3738,14 +3803,49 @@
   }
 
   if (v.HasParseError()) {
-    // TODO(syoyo): Report error
+    if (err) {
+      std::stringstream ss;
+      ss << "JSON parse error: (byte offset " << v.GetErrorOffset()
+         << ", line " << csw.GetLine()
+         << ", column " << csw.GetColumn()
+         << "): " << rapidjson::GetParseError_En(v.GetParseError());
+      (*err) = ss.str();
+    }
     return false;
   }
 #else
   {
-    v.Parse(str);
+    v.ParseStream(csw);
     if (v.HasParseError()) {
-      // TODO(syoyo): Report error
+      if (err) {
+        std::stringstream ss;
+        ss << "JSON parse error: (byte offset " << v.GetErrorOffset()
+           << ", line " << csw.GetLine()
+           << ", column " << csw.GetColumn()
+           << "): " << rapidjson::GetParseError_En(v.GetParseError());
+        (*err) = ss.str();
+      }
+      return false;
+    }
+  }
+#endif
+
+#if defined(TINYGLTF_ENABLE_SCHEMA_VALIDATOR)
+  if (pimpl_->validator_) {
+    if (!v.Accept(*(pimpl_->validator_))) {
+      // Input JSON is invalid according to the schema
+      // Output diagnostic information
+      rapidjson::StringBuffer sb;
+      pimpl_->validator_->GetInvalidSchemaPointer().StringifyUriFragment(sb);
+
+      std::stringstream ss;
+      printf("Invalid schema: %s\n", sb.GetString());
+      ss << "glTF schema validation error. Invalid keyword: " << pimpl_->validator_->GetInvalidSchemaKeyword();
+      sb.Clear();
+
+      if (err) {
+        (*err) = ss.str();
+      }
       return false;
     }
   }
@@ -4334,6 +4434,53 @@
                         check_sections);
 }
 
+#if defined(TINYGLTF_ENABLE_SCHEMA_VALIDATOR)
+bool TinyGLTF::LoadASCIIFromStringWithValidation(Model *model, std::string *err,
+                                   std::string *warn, const char *str,
+                                   unsigned int length,
+                                   const std::string &base_dir,
+                                   unsigned int check_sections) {
+  is_binary_ = false;
+  bin_data_ = nullptr;
+  bin_size_ = 0;
+
+  if (!pimpl_->validator_) {
+
+    pimpl_->schema_json_string_ = std::string();
+
+    // Construct glTF JSON schema string.
+    const size_t num_str = sizeof(kglTFSchemaStrings)/sizeof(kglTFSchemaStrings[0]);
+    for (size_t i = 0; i < num_str; i++) {
+      pimpl_->schema_json_string_ += std::string(kglTFSchemaStrings[i]);
+    }
+
+    // Validate input glTF string
+    if (pimpl_->schema_doc_) {
+      delete pimpl_->schema_doc_;
+    }
+    pimpl_->schema_doc_ = new rapidjson::Document();
+    pimpl_->schema_doc_->Parse(pimpl_->schema_json_string_.c_str(), pimpl_->schema_json_string_.size());
+
+    if (pimpl_->schema_doc_->HasParseError()) {
+      if(err) {
+        (*err) += "Internal error. Failed to parse glTF schema JSON.";
+      }
+      return false;
+    }
+
+    if (pimpl_->schema_) {
+      delete pimpl_->schema_;
+    }
+    pimpl_->schema_ = new rapidjson::SchemaDocument(*pimpl_->schema_doc_);
+
+    pimpl_->validator_ = new rapidjson::SchemaValidator(*pimpl_->schema_);
+  }
+
+  return LoadFromString(model, err, warn, str, length, base_dir,
+                        check_sections);
+}
+#endif
+
 bool TinyGLTF::LoadASCIIFromFile(Model *model, std::string *err,
                                  std::string *warn, const std::string &filename,
                                  unsigned int check_sections) {
@@ -4377,6 +4524,51 @@
   return ret;
 }
 
+#if defined(TINYGLTF_ENABLE_SCHEMA_VALIDATOR)
+bool TinyGLTF::LoadASCIIFromFileWithValidation(Model *model, std::string *err,
+                                 std::string *warn, const std::string &filename,
+                                 unsigned int check_sections) {
+  std::stringstream ss;
+
+  if (fs.ReadWholeFile == nullptr) {
+    // Programmer error, assert() ?
+    ss << "Failed to read file: " << filename
+       << ": one or more FS callback not set" << std::endl;
+    if (err) {
+      (*err) = ss.str();
+    }
+    return false;
+  }
+
+  std::vector<unsigned char> data;
+  std::string fileerr;
+  bool fileread = fs.ReadWholeFile(&data, &fileerr, filename, fs.user_data);
+  if (!fileread) {
+    ss << "Failed to read file: " << filename << ": " << fileerr << std::endl;
+    if (err) {
+      (*err) = ss.str();
+    }
+    return false;
+  }
+
+  size_t sz = data.size();
+  if (sz == 0) {
+    if (err) {
+      (*err) = "Empty file.";
+    }
+    return false;
+  }
+
+  std::string basedir = GetBaseDir(filename);
+
+  bool ret = LoadASCIIFromStringWithValidation(
+      model, err, warn, reinterpret_cast<const char *>(&data.at(0)),
+      static_cast<unsigned int>(data.size()), basedir, check_sections);
+
+  return ret;
+}
+#endif
+
 bool TinyGLTF::LoadBinaryFromMemory(Model *model, std::string *err,
                                     std::string *warn,
                                     const unsigned char *bytes,