diff --git a/loader_example.cc b/loader_example.cc index 2adc498..93a6866 100644 --- a/loader_example.cc +++ b/loader_example.cc @@ -4,7 +4,6 @@ #define TINYGLTF_IMPLEMENTATION #define STB_IMAGE_IMPLEMENTATION #define STB_IMAGE_WRITE_IMPLEMENTATION -//#define TINYGLTF_USE_RAPIDJSON #include "tiny_gltf.h" #include diff --git a/tests/tester.cc b/tests/tester.cc index d9d2dca..83187d1 100644 --- a/tests/tester.cc +++ b/tests/tester.cc @@ -20,7 +20,7 @@ TEST_CASE("parse-error", "[parse]") { std::string err; std::string warn; - bool ret = ctx.LoadASCIIFromString(&model, &err, &warn, "bora", strlen("bora"), /* basedir*/ ""); + bool ret = ctx.LoadASCIIFromString(&model, &err, &warn, "bora", static_cast(strlen("bora")), /* basedir*/ ""); REQUIRE(false == ret); diff --git a/tiny_gltf.h b/tiny_gltf.h index b8e1449..90b8572 100644 --- a/tiny_gltf.h +++ b/tiny_gltf.h @@ -882,7 +882,7 @@ struct Accessor { return static_cast(bufferViewObject.byteStride); } - return 0; + //unreachable return 0; } Accessor() { @@ -1015,6 +1015,7 @@ struct Mesh { Value extras; Mesh() = default; + ~Mesh() = default; Mesh(const Mesh&) = default; Mesh(Mesh&& rhs) noexcept : name(std::move(rhs.name)) @@ -1022,6 +1023,14 @@ struct Mesh { , weights(std::move(rhs.weights)) , extensions(std::move(rhs.extensions)) , extras(std::move(rhs.extras)) {} + Mesh &operator=(const Mesh &) = default; + Mesh &operator=(Mesh &&rhs) { + if (&rhs != this) { + this->~Mesh(); + new (reinterpret_cast(this)) Mesh(std::move(rhs)); + } + return *this; + } bool operator==(const Mesh &) const; }; @@ -1062,6 +1071,13 @@ class Node { ~Node() {} Node &operator=(const Node &rhs) = default; + Node &operator=(Node &&rhs) { + if (&rhs != this) { + this->~Node(); + new (reinterpret_cast(this)) Node(std::move(rhs)); + } + return *this; + } bool operator==(const Node &) const; @@ -1107,6 +1123,7 @@ struct Asset { Value extras; Asset() = default; + ~Asset() = default; Asset(const Asset&) = default; Asset(Asset&& rhs) noexcept : version(std::move(rhs.version)) @@ -1115,6 +1132,14 @@ struct Asset { , copyright(std::move(rhs.copyright)) , extensions(std::move(rhs.extensions)) , extras(std::move(rhs.extras)) {} + Asset &operator=(const Asset &) = default; + Asset &operator=(Asset &&rhs) { + if (&rhs != this) { + this->~Asset(); + new (reinterpret_cast(this)) Asset(std::move(rhs)); + } + return *this; + } bool operator==(const Asset &) const; }; @@ -1625,33 +1650,52 @@ class TinyGLTF { namespace { #ifdef TINYGLTF_USE_RAPIDJSON + +#ifdef TINYGLTF_USE_RAPIDJSON_CRTALLOCATOR + // This uses the RapidJSON CRTAllocator. It is thread safe and multiple + // documents may be active at once. + using json = rapidjson::GenericValue, rapidjson::CrtAllocator>; + using json_const_iterator = json::ConstMemberIterator; + using json_const_array_iterator = json const *; + using JsonDocument = + rapidjson::GenericDocument, rapidjson::CrtAllocator>; + rapidjson::CrtAllocator s_CrtAllocator; //stateless and thread safe + rapidjson::CrtAllocator &GetAllocator() { return s_CrtAllocator; } +#else + // This uses the default RapidJSON MemoryPoolAllocator. It is very fast, but + // not thread safe. Only a single JsonDocument may be active at any one time, + // meaning only a single gltf load/save can be active any one time. using json = rapidjson::Value; using json_const_iterator = json::ConstMemberIterator; - using json_const_array_iterator = json const*; - - rapidjson::Document* s_pActiveDocument = nullptr; - - struct JsonDocument : public rapidjson::Document - { + using json_const_array_iterator = json const *; + rapidjson::Document *s_pActiveDocument = nullptr; + rapidjson::Document::AllocatorType &GetAllocator() { + assert(s_pActiveDocument); //Root json node must be JsonDocument type + return s_pActiveDocument->GetAllocator(); + } + struct JsonDocument : public rapidjson::Document { JsonDocument() { - assert(s_pActiveDocument == nullptr); //Code assumes only one document is active at a time + assert(s_pActiveDocument == + nullptr); // When using default allocator, only one document can be active at a time, if you need + // multiple active at once, define TINYGLTF_USE_RAPIDJSON_CRTALLOCATOR s_pActiveDocument = this; } - JsonDocument(const JsonDocument&) = delete; - JsonDocument(JsonDocument&& rhs) noexcept : rapidjson::Document(std::move(rhs)) - { + JsonDocument(const JsonDocument &) = delete; + JsonDocument(JsonDocument &&rhs) noexcept + : rapidjson::Document(std::move(rhs)) { s_pActiveDocument = this; rhs.isNil = true; } ~JsonDocument() { - if (!isNil) - { + if (!isNil) { s_pActiveDocument = nullptr; } } + private: bool isNil = false; }; +#endif // TINYGLTF_USE_RAPIDJSON_CRTALLOCATOR #else using nlohmann::json; using json_const_iterator = json::const_iterator; @@ -3046,7 +3090,7 @@ static bool ParseBooleanProperty(bool *ret, std::string *err, const json &o, auto& value = GetValue(it); bool isBoolean; - bool boolValue; + bool boolValue = false; #ifdef TINYGLTF_USE_RAPIDJSON isBoolean = value.IsBool(); if (isBoolean) @@ -3132,7 +3176,7 @@ static bool ParseUnsignedProperty(size_t *ret, std::string *err, const json &o, auto& value = GetValue(it); - size_t uValue; + size_t uValue = 0; bool isUValue; #ifdef TINYGLTF_USE_RAPIDJSON isUValue = false; @@ -4987,9 +5031,9 @@ bool TinyGLTF::LoadFromString(Model *model, std::string *err, std::string *warn, auto ForEachInArray = [](const json& v, const char* member, const std::function& cb)->bool #endif { - json_const_iterator it; - if (FindMember(v, member, it) && IsArray(GetValue(it))) { - const json &root = GetValue(it); + json_const_iterator itm; + if (FindMember(v, member, itm) && IsArray(GetValue(itm))) { + const json &root = GetValue(itm); auto it = ArrayBegin(root); auto end = ArrayEnd(root); for (; it != end; ++it) { @@ -5649,7 +5693,7 @@ namespace json JsonFromString(const char* s) { #ifdef TINYGLTF_USE_RAPIDJSON - return json(s, s_pActiveDocument->GetAllocator()); + return json(s, GetAllocator()); #else return json(s); #endif @@ -5680,7 +5724,7 @@ namespace void JsonAssign(json& dest, const json& src) { #ifdef TINYGLTF_USE_RAPIDJSON - dest.CopyFrom(src, s_pActiveDocument->GetAllocator()); + dest.CopyFrom(src, GetAllocator()); #else dest = src; #endif @@ -5693,7 +5737,7 @@ namespace { o.SetObject(); } - o.AddMember(json(key, s_pActiveDocument->GetAllocator()), std::move(value), s_pActiveDocument->GetAllocator()); + o.AddMember(json(key, GetAllocator()), std::move(value), GetAllocator()); #else o[key] = std::move(value); #endif @@ -5702,7 +5746,7 @@ namespace void JsonPushBack(json& o, json&& value) { #ifdef TINYGLTF_USE_RAPIDJSON - o.PushBack(std::move(value), s_pActiveDocument->GetAllocator()); + o.PushBack(std::move(value), GetAllocator()); #else o.push_back(std::move(value)); #endif @@ -5730,7 +5774,7 @@ namespace { #ifdef TINYGLTF_USE_RAPIDJSON o.SetArray(); - o.Reserve(static_cast(s), s_pActiveDocument->GetAllocator()); + o.Reserve(static_cast(s), GetAllocator()); #endif (void)(o); (void)(s); @@ -5795,16 +5839,16 @@ static bool ValueToJson(const Value &value, json *ret) { obj.SetBool(value.Get()); break; case STRING_TYPE: - obj.SetString(value.Get().c_str(), s_pActiveDocument->GetAllocator()); + obj.SetString(value.Get().c_str(), GetAllocator()); break; case ARRAY_TYPE: { obj.SetArray(); - obj.Reserve(static_cast(value.ArrayLen()), s_pActiveDocument->GetAllocator()); + obj.Reserve(static_cast(value.ArrayLen()), GetAllocator()); for (unsigned int i = 0; i < value.ArrayLen(); ++i) { Value elementValue = value.Get(int(i)); json elementJson; if (ValueToJson(value.Get(int(i)), &elementJson)) - obj.PushBack(std::move(elementJson), s_pActiveDocument->GetAllocator()); + obj.PushBack(std::move(elementJson), GetAllocator()); } break; } @@ -5819,7 +5863,7 @@ static bool ValueToJson(const Value &value, json *ret) { for (auto &it : objMap) { json elementJson; if (ValueToJson(it.second, &elementJson)) { - obj.AddMember(json(it.first.c_str(), s_pActiveDocument->GetAllocator()), std::move(elementJson), s_pActiveDocument->GetAllocator()); + obj.AddMember(json(it.first.c_str(), GetAllocator()), std::move(elementJson), GetAllocator()); } } break;