Compare commits

...

5 Commits

Author SHA1 Message Date
Syoyo Fujita
fed3f31e95 Implement iterator for SAJSON backend(W.I.P). 2020-06-11 21:57:54 +09:00
Syoyo Fujita
6fcee26d0f Merge branch 'separate-serializer' into sajson 2020-06-08 16:47:46 +09:00
Syoyo Fujita
bafde6a53e Use TINYGLTF_ENABLE_SERIALIZER ifdef to enable/disable serialization code. 2020-06-08 16:46:33 +09:00
Syoyo Fujita
3d939fd3ee Add comment on tinygltf::ExpandFilePath() 2020-06-06 18:13:15 +09:00
Syoyo Fujita
b8c04b0a9d sajson experiment(W.I.P.) 2020-05-05 03:22:22 +09:00
2 changed files with 202 additions and 6 deletions

View File

@@ -153,6 +153,7 @@ if (!ret) {
## Compile options
* `TINYGLTF_ENABLE_SERIALIZER` : Enable glTF serialization feature.
* `TINYGLTF_NOEXCEPTION` : Disable C++ exception in JSON parsing. You can use `-fno-exceptions` or by defining the symbol `JSON_NOEXCEPTION` and `TINYGLTF_NOEXCEPTION` to fully remove C++ exception codes when compiling TinyGLTF.
* `TINYGLTF_NO_STB_IMAGE` : Do not load images with stb_image. Instead use `TinyGLTF::SetImageLoader(LoadimageDataFunction LoadImageData, void *user_data)` to set a callback for loading images.
* `TINYGLTF_NO_STB_IMAGE_WRITE` : Do not write images with stb_image_write. Instead use `TinyGLTF::SetImageWriter(WriteimageDataFunction WriteImageData, void *user_data)` to set a callback for writing images.

View File

@@ -26,6 +26,8 @@
// THE SOFTWARE.
// Version:
// - v2.4.3 Experimental sajson(lightweight JSON parser) backend support.
// Introduce TINYGLTF_ENABLE_SERIALIZER.
// - v2.4.2 Decode percent-encoded URI.
// - v2.4.1 Fix some glTF object class does not have `extensions` and/or
// `extras` property.
@@ -43,6 +45,7 @@
//
// Tiny glTF loader is using following third party libraries:
//
// - sajso: Lightweight C++ JSON library.
// - jsonhpp: C++ JSON library.
// - base64: base64 decode/encode library.
// - stb_image: Image loading library.
@@ -1249,7 +1252,13 @@ struct FsCallbacks {
bool FileExists(const std::string &abs_filename, void *);
std::string ExpandFilePath(const std::string &filepath, void *);
///
/// Expand file path(e.g. `~` to home directory on posix, `%APPDATA%` to `C:\Users\tinygltf\AppData`)
///
/// @param[in] filepath File path string. Assume UTF-8
/// @param[in] userdata User data. Set to `nullptr` if you don't need it.
///
std::string ExpandFilePath(const std::string &filepath, void *userdata);
bool ReadWholeFile(std::vector<unsigned char> *out, std::string *err,
const std::string &filepath, void *);
@@ -1317,6 +1326,8 @@ class TinyGLTF {
const std::string &base_dir = "",
unsigned int check_sections = REQUIRE_VERSION);
#if defined(TINYGLTF_ENABLE_SERIALIZER)
///
/// Write glTF to stream, buffers and images will be embeded
///
@@ -1330,16 +1341,22 @@ class TinyGLTF {
bool embedImages, bool embedBuffers,
bool prettyPrint, bool writeBinary);
#endif
///
/// Set callback to use for loading image data
///
void SetImageLoader(LoadImageDataFunction LoadImageData, void *user_data);
#if defined(TINYGLTF_ENABLE_SERIALIZER)
///
/// Set callback to use for writing image data
///
void SetImageWriter(WriteImageDataFunction WriteImageData, void *user_data);
#endif
///
/// Set callbacks to use for filesystem (fs) access and their user data
///
@@ -1501,14 +1518,38 @@ class TinyGLTF {
#endif // __GNUC__
#ifndef TINYGLTF_NO_INCLUDE_JSON
#ifndef TINYGLTF_USE_RAPIDJSON
#include "json.hpp"
#else
#if defined(TINYGLTF_USE_RAPIDJSON)
#include "document.h"
#include "prettywriter.h"
#include "rapidjson.h"
#include "stringbuffer.h"
#include "writer.h"
#elif defined(TINYGLTF_USE_SAJSON)
#ifdef __clang__
#if __has_warning("-Wc99-extensions")
#pragma clang diagnostic ignored "-Wc99-extensions"
#endif
#if __has_warning("-Wshadow-field-in-constructor")
#pragma clang diagnostic ignored "-Wshadow-field-in-constructor"
#endif
#endif
#include "sajson.h"
// Serialization is not available for sajson backend.
#ifdef TINYGLTF_ENABLE_SERIALIZER
#undef TINYGLTF_ENABLE_SERIALIZER
#endif
#else
// Default = nlohmann json
#include "json.hpp"
#endif
#endif
@@ -1644,7 +1685,62 @@ struct JsonDocument : public rapidjson::Document {
#endif // TINYGLTF_USE_RAPIDJSON_CRTALLOCATOR
#else
#elif defined(TINYGLTF_USE_SAJSON)
using json = sajson::value;
using JsonDocument = json;
// TODO(syoyo): Implement
// muda
class sajson_const_iterator
{
public:
sajson_const_iterator() = default;
sajson_const_iterator(const sajson::value &v) : _v(v) {
}
sajson_const_iterator(const sajson_const_iterator &rhs) = default;
sajson_const_iterator &operator=(const sajson_const_iterator &rhs) = default;
std::string key() const {
}
sajson::value &value() {
return _v;
}
sajson::value *begin() {
return &_v;
}
bool operator!=(sajson_const_iterator &rhs) {
// TODO
assert(0);
return false;
}
sajson_const_iterator &operator++() {
// TODO
assert(0);
return (*this);
}
sajson::value &operator*() {
return _v;
}
private:
// `sajson::value` itself is a small struct, so having a copy of it
// does not affect performance and memory consumption.
sajson::value _v;
};
using json_const_iterator = sajson_const_iterator;
using json_const_array_iterator = json_const_iterator;
#else // nlohmann JSON
using nlohmann::json;
using json_const_iterator = json::const_iterator;
using json_const_array_iterator = json_const_iterator;
@@ -1656,6 +1752,14 @@ void JsonParse(JsonDocument &doc, const char *str, size_t length,
#ifdef TINYGLTF_USE_RAPIDJSON
(void)throwExc;
doc.Parse(str, length);
#elif defined(TINYGLTF_USE_SAJSON)
// This code path is not available.
(void)doc;
(void)str;
(void)length;
(void)throwExc;
//doc = sajson::parse(sajson::dynamic_allocation(), sajson::mutable_string_view(length, const_cast<char *>(str)));
//doc.parse(sajson::dynamic_allocation(), sajson::mutable_string_view(length, const_cast<char *>(str)));
#else
doc = json::parse(str, str + length, nullptr, throwExc);
#endif
@@ -2387,11 +2491,15 @@ bool LoadImageData(Image *image, const int image_idx, std::string *err,
}
#endif
#if defined(TINYGLTF_ENABLE_SERIALIZER)
void TinyGLTF::SetImageWriter(WriteImageDataFunction func, void *user_data) {
WriteImageData = func;
write_image_user_data_ = user_data;
}
#endif
#ifndef TINYGLTF_NO_STB_IMAGE_WRITE
static void WriteToMemory_stbi(void *context, void *data, int size) {
std::vector<unsigned char> *buffer =
@@ -2882,6 +2990,15 @@ bool GetInt(const json &o, int &val) {
}
}
return false;
#elif defined(TINYGLTF_USE_SAJSON)
auto type = o.get_type();
if (type == sajson::TYPE_INTEGER) {
val = static_cast<int>(o.get_number_value());
return true;
}
return false;
#else
auto type = o.type();
@@ -2914,6 +3031,16 @@ bool GetNumber(const json &o, double &val) {
return true;
}
return false;
#elif defined(TINYGLTF_USE_SAJSON)
auto type = o.get_type();
if ((type == sajson::TYPE_DOUBLE) ||
(type == sajson::TYPE_INTEGER)) {
val = static_cast<double>(o.get_number_value());
return true;
}
return false;
#else
if (o.is_number()) {
@@ -2932,6 +3059,15 @@ bool GetString(const json &o, std::string &val) {
return true;
}
return false;
#elif defined(TINYGLTF_USE_SAJSON)
auto type = o.get_type();
if (type == sajson::TYPE_STRING) {
val = o.as_string();
return true;
}
return false;
#else
if (o.type() == json::value_t::string) {
@@ -2946,6 +3082,8 @@ bool GetString(const json &o, std::string &val) {
bool IsArray(const json &o) {
#ifdef TINYGLTF_USE_RAPIDJSON
return o.IsArray();
#elif defined(TINYGLTF_USE_SAJSON)
return o.get_type() == sajson::TYPE_ARRAY;
#else
return o.is_array();
#endif
@@ -2954,6 +3092,10 @@ bool IsArray(const json &o) {
json_const_array_iterator ArrayBegin(const json &o) {
#ifdef TINYGLTF_USE_RAPIDJSON
return o.Begin();
#elif TINYGLTF_USE_SAJSON
// TODO(syoyo): Implement
assert(0);
return json_const_array_iterator(o);
#else
return o.begin();
#endif
@@ -2962,6 +3104,10 @@ json_const_array_iterator ArrayBegin(const json &o) {
json_const_array_iterator ArrayEnd(const json &o) {
#ifdef TINYGLTF_USE_RAPIDJSON
return o.End();
#elif TINYGLTF_USE_SAJSON
// TODO(syoyo): Implement
assert(0);
return json_const_array_iterator(o);
#else
return o.end();
#endif
@@ -2970,6 +3116,8 @@ json_const_array_iterator ArrayEnd(const json &o) {
bool IsObject(const json &o) {
#ifdef TINYGLTF_USE_RAPIDJSON
return o.IsObject();
#elif defined(TINYGLTF_USE_SAJSON)
return o.get_type() == sajson::TYPE_OBJECT;
#else
return o.is_object();
#endif
@@ -2978,6 +3126,11 @@ bool IsObject(const json &o) {
json_const_iterator ObjectBegin(const json &o) {
#ifdef TINYGLTF_USE_RAPIDJSON
return o.MemberBegin();
#elif defined(TINYGLTF_USE_SAJSON)
assert(o.get_type() == sajson::TYPE_OBJECT);
// TODO(syoyo): Implement
assert(0);
return json_const_iterator(o);
#else
return o.begin();
#endif
@@ -2986,6 +3139,11 @@ json_const_iterator ObjectBegin(const json &o) {
json_const_iterator ObjectEnd(const json &o) {
#ifdef TINYGLTF_USE_RAPIDJSON
return o.MemberEnd();
#elif defined(TINYGLTF_USE_SAJSON)
assert(o.get_type() == sajson::TYPE_OBJECT);
// TODO(syoyo): Implement
assert(0);
return json_const_iterator(o);
#else
return o.end();
#endif
@@ -2994,6 +3152,10 @@ json_const_iterator ObjectEnd(const json &o) {
const char *GetKey(json_const_iterator &it) {
#ifdef TINYGLTF_USE_RAPIDJSON
return it->name.GetString();
#elif defined(TINYGLTF_USE_SAJSON)
// TODO(syoyo): Implement
assert(0);
return nullptr;
#else
return it.key().c_str();
#endif
@@ -3006,6 +3168,10 @@ bool FindMember(const json &o, const char *member, json_const_iterator &it) {
}
it = o.FindMember(member);
return it != o.MemberEnd();
#elif defined(TINYGLTF_USE_SAJSON)
// TODO(syoyo): Implement
assert(0);
return false;
#else
it = o.find(member);
return it != o.end();
@@ -3015,6 +3181,10 @@ bool FindMember(const json &o, const char *member, json_const_iterator &it) {
const json &GetValue(json_const_iterator &it) {
#ifdef TINYGLTF_USE_RAPIDJSON
return it->value;
#elif defined(TINYGLTF_USE_SAJSON)
// TODO(syoyo): Implement
assert(0);
return it.value();
#else
return it.value();
#endif
@@ -3033,6 +3203,11 @@ std::string JsonToString(const json &o, int spacing = -1) {
o.Accept(writer);
}
return buffer.GetString();
#elif defined(TINYGLTF_USE_SAJSON)
// Serialize is not available for Sajson
(void)o;
(void)spacing;
return std::string();
#else
return o.dump(spacing);
#endif
@@ -3088,7 +3263,10 @@ static bool ParseJsonAsValue(Value *ret, const json &o) {
break;
// all types are covered, so no `case default`
}
#else
#elif defined(TINYGLTF_USE_SAJSON)
// TODO
assert(0);
#else // json.hpp
switch (o.type()) {
case json::value_t::object: {
Value::Object value_object;
@@ -3171,6 +3349,11 @@ static bool ParseBooleanProperty(bool *ret, std::string *err, const json &o,
if (isBoolean) {
boolValue = value.GetBool();
}
#elif defined(TINYGLTF_USE_SAJSON)
isBoolean = value.is_boolean();
if (isBoolean) {
boolValue = value.get_boolean_value();
}
#else
isBoolean = value.is_boolean();
if (isBoolean) {
@@ -3260,6 +3443,11 @@ static bool ParseUnsignedProperty(size_t *ret, std::string *err, const json &o,
uValue = value.GetUint64();
isUValue = true;
}
#elif defined(TINYGLTF_USE_SAJSON)
isUValue = value.get_type() == sajson::TYPE_INTEGER;
if (isUValue) {
uValue = value.get_integer_value();
}
#else
isUValue = value.is_number_unsigned();
if (isUValue) {
@@ -6038,10 +6226,13 @@ bool TinyGLTF::LoadFromString(Model *model, std::string *err, std::string *warn,
// 19. Parse Extras
ParseExtrasProperty(&model->extras, v);
#if !defined(TINYGLTF_USE_SAJSON)
// TODO(syoyo): Support SAJSON backend
if (store_original_json_for_extras_and_extensions_) {
model->extras_json_string = JsonToString(v["extras"]);
model->extensions_json_string = JsonToString(v["extensions"]);
}
#endif
return true;
}
@@ -6208,6 +6399,8 @@ bool TinyGLTF::LoadBinaryFromFile(Model *model, std::string *err,
return ret;
}
#if defined(TINYGLTF_ENABLE_SERIALIZER)
///////////////////////
// GLTF Serialization
///////////////////////
@@ -7613,6 +7806,8 @@ bool TinyGLTF::WriteGltfSceneToFile(Model *model, const std::string &filename,
return true;
}
#endif // TINYGLTF_ENABLE_SERIALIZER
} // namespace tinygltf
#ifdef __clang__