初始提交: UE5.3项目基础框架

This commit is contained in:
2025-10-14 11:14:54 +08:00
commit 721d9fd98e
5334 changed files with 316782 additions and 0 deletions

View File

@ -0,0 +1,628 @@
#pragma once
#include "CesiumUtility/Assert.h"
#include "DoubleJsonHandler.h"
#include "IntegerJsonHandler.h"
#include "JsonHandler.h"
#include "Library.h"
#include "StringJsonHandler.h"
#include <functional>
#include <memory>
#include <vector>
namespace CesiumJsonReader {
/**
* @brief \ref IJsonHandler for reading a JSON array into an `std::vector`.
*
* @tparam T The element type of the destination vector.
* @tparam THandler The \ref IJsonHandler to handle each element.
*/
template <typename T, typename THandler>
class CESIUMJSONREADER_API ArrayJsonHandler : public JsonHandler {
public:
/** @brief The destination type. */
using ValueType = std::vector<T>;
/**
* @brief Creates a new \ref ArrayJsonHandler.
*
* @param args The arguments that will be passed to the constructor of
* THandler when it's instantiated.
*/
template <typename... Ts>
ArrayJsonHandler(Ts&&... args) noexcept
: JsonHandler(),
_handlerFactory(
std::bind(handlerFactory<Ts...>, std::forward<Ts>(args)...)),
_objectHandler() {}
/**
* @brief Resets the parent and destination array of this \ref
* ArrayJsonHandler.
*/
void reset(IJsonHandler* pParent, std::vector<T>* pArray) {
JsonHandler::reset(pParent);
this->_pArray = pArray;
this->_arrayIsOpen = false;
this->_objectHandler.reset(this->_handlerFactory());
}
virtual IJsonHandler* readNull() override {
return this->invalid("A null")->readNull();
}
virtual IJsonHandler* readBool(bool b) override {
return this->invalid("A boolean")->readBool(b);
}
virtual IJsonHandler* readInt32(int32_t i) override {
return this->invalid("An integer")->readInt32(i);
}
virtual IJsonHandler* readUint32(uint32_t i) override {
return this->invalid("An integer")->readUint32(i);
}
virtual IJsonHandler* readInt64(int64_t i) override {
return this->invalid("An integer")->readInt64(i);
}
virtual IJsonHandler* readUint64(uint64_t i) override {
return this->invalid("An integer")->readUint64(i);
}
virtual IJsonHandler* readDouble(double d) override {
return this->invalid("A double (floating-point)")->readDouble(d);
}
virtual IJsonHandler* readString(const std::string_view& str) override {
return this->invalid("A string")->readString(str);
}
virtual IJsonHandler* readObjectStart() override {
if (!this->_arrayIsOpen) {
return this->invalid("An object")->readObjectStart();
}
CESIUM_ASSERT(this->_pArray);
T& o = this->_pArray->emplace_back();
this->_objectHandler->reset(this, &o);
return this->_objectHandler->readObjectStart();
}
virtual IJsonHandler*
readObjectKey(const std::string_view& /*str*/) noexcept override {
return nullptr;
}
virtual IJsonHandler* readObjectEnd() noexcept override { return nullptr; }
virtual IJsonHandler* readArrayStart() override {
if (this->_arrayIsOpen) {
return this->invalid("An array")->readArrayStart();
}
this->_arrayIsOpen = true;
this->_pArray->clear();
return this;
}
virtual IJsonHandler* readArrayEnd() override { return this->parent(); }
virtual void reportWarning(
const std::string& warning,
std::vector<std::string>&& context =
std::vector<std::string>()) override {
context.push_back(
std::string("[") + std::to_string(this->_pArray->size()) + "]");
this->parent()->reportWarning(warning, std::move(context));
}
private:
IJsonHandler* invalid(const std::string& type) {
if (this->_arrayIsOpen) {
this->reportWarning(
type + " value is not allowed in the object array and has been "
"replaced with a default value.");
this->_pArray->emplace_back();
return this->ignoreAndContinue();
} else {
this->reportWarning(type + " is not allowed and has been ignored.");
return this->ignoreAndReturnToParent();
}
}
template <typename... Ts> static THandler* handlerFactory(Ts&&... args) {
return new THandler(std::forward<Ts>(args)...);
}
std::vector<T>* _pArray = nullptr;
bool _arrayIsOpen = false;
std::function<THandler*()> _handlerFactory;
std::unique_ptr<THandler> _objectHandler;
};
/**
* @brief Special case of \ref ArrayJsonHandler for handling arrays of double
* values. This will read every scalar value as a double, regardless of whether
* it's floating point or not. Attempting to read other values will cause a
* warning.
*/
template <>
class CESIUMJSONREADER_API ArrayJsonHandler<double, DoubleJsonHandler>
: public JsonHandler {
public:
/** @brief The destination type. */
using ValueType = std::vector<double>;
ArrayJsonHandler() noexcept : JsonHandler() {}
/**
* @brief Resets the parent and destination array of this \ref
* ArrayJsonHandler.
*/
void reset(IJsonHandler* pParent, std::vector<double>* pArray) {
JsonHandler::reset(pParent);
this->_pArray = pArray;
this->_arrayIsOpen = false;
}
virtual IJsonHandler* readNull() override {
return this->invalid("A null")->readNull();
}
virtual IJsonHandler* readBool(bool b) override {
return this->invalid("A bool")->readBool(b);
}
virtual IJsonHandler* readInt32(int32_t i) override {
if (!this->_arrayIsOpen) {
return this->invalid("An integer")->readInt32(i);
}
CESIUM_ASSERT(this->_pArray);
this->_pArray->emplace_back(static_cast<double>(i));
return this;
}
virtual IJsonHandler* readUint32(uint32_t i) override {
if (!this->_arrayIsOpen) {
return this->invalid("An integer")->readUint32(i);
}
CESIUM_ASSERT(this->_pArray);
this->_pArray->emplace_back(static_cast<double>(i));
return this;
}
virtual IJsonHandler* readInt64(int64_t i) override {
if (!this->_arrayIsOpen) {
return this->invalid("An integer")->readInt64(i);
}
CESIUM_ASSERT(this->_pArray);
this->_pArray->emplace_back(static_cast<double>(i));
return this;
}
virtual IJsonHandler* readUint64(uint64_t i) override {
if (!this->_arrayIsOpen) {
return this->invalid("An integer")->readUint64(i);
}
CESIUM_ASSERT(this->_pArray);
this->_pArray->emplace_back(static_cast<double>(i));
return this;
}
virtual IJsonHandler* readDouble(double d) override {
if (!this->_arrayIsOpen) {
return this->invalid("An integer")->readDouble(d);
}
CESIUM_ASSERT(this->_pArray);
this->_pArray->emplace_back(d);
return this;
}
virtual IJsonHandler* readString(const std::string_view& str) override {
return this->invalid("A string")->readString(str);
}
virtual IJsonHandler* readObjectStart() override {
return this->invalid("An object")->readObjectStart();
}
virtual IJsonHandler* readArrayStart() override {
if (this->_arrayIsOpen) {
return this->invalid("An array")->readArrayStart();
}
this->_arrayIsOpen = true;
this->_pArray->clear();
return this;
}
virtual IJsonHandler* readArrayEnd() override { return this->parent(); }
virtual void reportWarning(
const std::string& warning,
std::vector<std::string>&& context =
std::vector<std::string>()) override {
context.push_back(
std::string("[") + std::to_string(this->_pArray->size()) + "]");
this->parent()->reportWarning(warning, std::move(context));
}
private:
IJsonHandler* invalid(const std::string& type) {
if (this->_arrayIsOpen) {
this->reportWarning(
type + " value is not allowed in the double array and has been "
"replaced with a default value.");
this->_pArray->emplace_back();
return this->ignoreAndContinue();
} else {
this->reportWarning(type + " is not allowed and has been ignored.");
return this->ignoreAndReturnToParent();
}
}
std::vector<double>* _pArray = nullptr;
bool _arrayIsOpen = false;
};
/**
* @brief Special case of \ref ArrayJsonHandler for handling arrays of integer
* values. Attempting to read other values will cause a warning.
*/
template <typename T>
class CESIUMJSONREADER_API ArrayJsonHandler<T, IntegerJsonHandler<T>>
: public JsonHandler {
public:
/** @brief The destination type. */
using ValueType = std::vector<T>;
ArrayJsonHandler() noexcept : JsonHandler() {}
/**
* @brief Resets the parent and destination array of this \ref
* ArrayJsonHandler.
*/
void reset(IJsonHandler* pParent, std::vector<T>* pArray) {
JsonHandler::reset(pParent);
this->_pArray = pArray;
this->_arrayIsOpen = false;
}
virtual IJsonHandler* readNull() override {
return this->invalid("A null")->readNull();
}
virtual IJsonHandler* readBool(bool b) override {
return this->invalid("A bool")->readBool(b);
}
virtual IJsonHandler* readInt32(int32_t i) override {
if (!this->_arrayIsOpen) {
return this->invalid("An integer")->readInt32(i);
}
CESIUM_ASSERT(this->_pArray);
this->_pArray->emplace_back(static_cast<T>(i));
return this;
}
virtual IJsonHandler* readUint32(uint32_t i) override {
if (!this->_arrayIsOpen) {
return this->invalid("An integer")->readUint32(i);
}
CESIUM_ASSERT(this->_pArray);
this->_pArray->emplace_back(static_cast<T>(i));
return this;
}
virtual IJsonHandler* readInt64(int64_t i) override {
if (!this->_arrayIsOpen) {
return this->invalid("An integer")->readInt64(i);
}
CESIUM_ASSERT(this->_pArray);
this->_pArray->emplace_back(static_cast<T>(i));
return this;
}
virtual IJsonHandler* readUint64(uint64_t i) override {
if (!this->_arrayIsOpen) {
return this->invalid("An integer")->readUint64(i);
}
CESIUM_ASSERT(this->_pArray);
this->_pArray->emplace_back(static_cast<T>(i));
return this;
}
virtual IJsonHandler* readDouble(double d) override {
return this->invalid("A double (floating-point)")->readDouble(d);
}
virtual IJsonHandler* readString(const std::string_view& str) override {
return this->invalid("A string")->readString(str);
}
virtual IJsonHandler* readObjectStart() override {
return this->invalid("An object")->readObjectStart();
}
virtual IJsonHandler* readArrayStart() override {
if (this->_arrayIsOpen) {
return this->invalid("An array")->readArrayStart();
}
this->_arrayIsOpen = true;
this->_pArray->clear();
return this;
}
virtual IJsonHandler* readArrayEnd() override { return this->parent(); }
virtual void reportWarning(
const std::string& warning,
std::vector<std::string>&& context =
std::vector<std::string>()) override {
context.push_back(
std::string("[") + std::to_string(this->_pArray->size()) + "]");
this->parent()->reportWarning(warning, std::move(context));
}
private:
IJsonHandler* invalid(const std::string& type) {
if (this->_arrayIsOpen) {
this->reportWarning(
type + " value is not allowed in the integer array and has been "
"replaced with a default value.");
this->_pArray->emplace_back();
return this->ignoreAndContinue();
} else {
this->reportWarning(type + " is not allowed and has been ignored.");
return this->ignoreAndReturnToParent();
}
}
std::vector<T>* _pArray = nullptr;
bool _arrayIsOpen = false;
};
/**
* @brief Special case of \ref ArrayJsonHandler for reading arrays of string
* values. Attempting to read other values will cause a warning.
*/
template <>
class CESIUMJSONREADER_API ArrayJsonHandler<std::string, StringJsonHandler>
: public JsonHandler {
public:
/** @brief The destination type. */
using ValueType = std::vector<std::string>;
ArrayJsonHandler() noexcept : JsonHandler() {}
/**
* @brief Resets the parent and destination array of this \ref
* ArrayJsonHandler.
*/
void reset(IJsonHandler* pParent, std::vector<std::string>* pArray) {
JsonHandler::reset(pParent);
this->_pArray = pArray;
this->_arrayIsOpen = false;
}
virtual IJsonHandler* readNull() override {
return this->invalid("A null")->readNull();
}
virtual IJsonHandler* readBool(bool b) override {
return this->invalid("A bool")->readBool(b);
}
virtual IJsonHandler* readInt32(int32_t i) override {
return this->invalid("An integer")->readInt32(i);
}
virtual IJsonHandler* readUint32(uint32_t i) override {
return this->invalid("An integer")->readUint32(i);
}
virtual IJsonHandler* readInt64(int64_t i) override {
return this->invalid("An integer")->readInt64(i);
}
virtual IJsonHandler* readUint64(uint64_t i) override {
return this->invalid("An integer")->readUint64(i);
}
virtual IJsonHandler* readDouble(double d) override {
return this->invalid("A double (floating-point)")->readDouble(d);
}
virtual IJsonHandler* readObjectStart() override {
return this->invalid("An object")->readObjectStart();
}
virtual IJsonHandler* readArrayStart() override {
if (this->_arrayIsOpen) {
return this->invalid("An array")->readArrayStart();
}
this->_arrayIsOpen = true;
this->_pArray->clear();
return this;
}
virtual IJsonHandler* readArrayEnd() override { return this->parent(); }
virtual IJsonHandler* readString(const std::string_view& str) override {
if (!this->_arrayIsOpen) {
return this->invalid("A string")->readString(str);
}
CESIUM_ASSERT(this->_pArray);
this->_pArray->emplace_back(str);
return this;
}
virtual void reportWarning(
const std::string& warning,
std::vector<std::string>&& context =
std::vector<std::string>()) override {
context.push_back(
std::string("[") + std::to_string(this->_pArray->size()) + "]");
this->parent()->reportWarning(warning, std::move(context));
}
private:
IJsonHandler* invalid(const std::string& type) {
if (this->_arrayIsOpen) {
this->reportWarning(
type + " value is not allowed in the string array and has been "
"replaced with a default value.");
this->_pArray->emplace_back();
return this->ignoreAndContinue();
} else {
this->reportWarning(type + " is not allowed and has been ignored.");
return this->ignoreAndReturnToParent();
}
}
std::vector<std::string>* _pArray = nullptr;
bool _arrayIsOpen = false;
};
/**
* @brief Special case of \ref ArrayJsonHandler for reading arrays of arrays.
* Attempting to read other values will cause a warning.
*
* @tparam T The inner type of the nested array.
* @tparam THandler The handler of the inner type of the array.
*/
template <typename T, typename THandler>
class CESIUMJSONREADER_API
ArrayJsonHandler<std::vector<T>, ArrayJsonHandler<T, THandler>>
: public JsonHandler {
public:
/** @brief The destination type. */
using ValueType = std::vector<T>;
/**
* @brief Creates a new \ref ArrayJsonHandler.
*
* @param args The arguments passed to the constructor of THandler when it's
* instantiated.
*/
template <typename... Ts>
ArrayJsonHandler(Ts&&... args) noexcept
: JsonHandler(),
_handlerFactory(
std::bind(handlerFactory<Ts...>, std::forward<Ts>(args)...)),
_elementHandler() {}
/**
* @brief Resets the parent and destination array of this \ref
* ArrayJsonHandler.
*/
void reset(IJsonHandler* pParent, std::vector<std::vector<T>>* pArray) {
JsonHandler::reset(pParent);
this->_pArray = pArray;
this->_arrayIsOpen = false;
this->_elementHandler.reset(this->_handlerFactory());
}
virtual IJsonHandler* readNull() override {
return this->invalid("A null")->readNull();
}
virtual IJsonHandler* readBool(bool b) override {
return this->invalid("A bool")->readBool(b);
}
virtual IJsonHandler* readInt32(int32_t i) override {
return this->invalid("An integer")->readInt32(i);
}
virtual IJsonHandler* readUint32(uint32_t i) override {
return this->invalid("An integer")->readUint32(i);
}
virtual IJsonHandler* readInt64(int64_t i) override {
return this->invalid("An integer")->readInt64(i);
}
virtual IJsonHandler* readUint64(uint64_t i) override {
return this->invalid("An integer")->readUint64(i);
}
virtual IJsonHandler* readDouble(double d) override {
return this->invalid("A double (floating-point)")->readDouble(d);
}
virtual IJsonHandler* readString(const std::string_view& str) override {
return this->invalid("A string")->readString(str);
}
virtual IJsonHandler* readObjectStart() override {
return this->invalid("An object")->readObjectStart();
}
virtual IJsonHandler* readArrayStart() override {
if (this->_arrayIsOpen) {
CESIUM_ASSERT(this->_pArray);
std::vector<T>& o = this->_pArray->emplace_back();
this->_elementHandler->reset(this, &o);
return this->_elementHandler->readArrayStart();
} else {
this->_arrayIsOpen = true;
this->_pArray->clear();
return this;
}
}
virtual IJsonHandler* readArrayEnd() override { return this->parent(); }
virtual void reportWarning(
const std::string& warning,
std::vector<std::string>&& context =
std::vector<std::string>()) override {
context.push_back(
std::string("[") + std::to_string(this->_pArray->size()) + "]");
this->parent()->reportWarning(warning, std::move(context));
}
private:
IJsonHandler* invalid(const std::string& type) {
if (this->_arrayIsOpen) {
this->reportWarning(
type + " value is not allowed in the array of arrays and has been "
"replaced with a default value.");
this->_pArray->emplace_back();
return this->ignoreAndContinue();
} else {
this->reportWarning(type + " is not allowed and has been ignored.");
return this->ignoreAndReturnToParent();
}
}
template <typename... Ts>
static ArrayJsonHandler<T, THandler>* handlerFactory(Ts&&... args) {
return new ArrayJsonHandler<T, THandler>(std::forward<Ts>(args)...);
}
std::vector<std::vector<T>>* _pArray = nullptr;
bool _arrayIsOpen = false;
std::function<ArrayJsonHandler<T, THandler>*()> _handlerFactory;
std::unique_ptr<ArrayJsonHandler<T, THandler>> _elementHandler;
};
} // namespace CesiumJsonReader

View File

@ -0,0 +1,25 @@
#pragma once
#include "JsonHandler.h"
#include "Library.h"
namespace CesiumJsonReader {
/**
* @brief \ref IJsonHandler for reading bool values.
*/
class CESIUMJSONREADER_API BoolJsonHandler : public JsonHandler {
public:
BoolJsonHandler() noexcept;
/**
* @brief Resets the parent \ref IJsonHandler of this handler, and the pointer
* to its destination bool value.
*/
void reset(IJsonHandler* pParent, bool* pBool);
/** @copydoc IJsonHandler::readBool */
virtual IJsonHandler* readBool(bool b) override;
private:
bool* _pBool = nullptr;
};
} // namespace CesiumJsonReader

View File

@ -0,0 +1,76 @@
#pragma once
#include "CesiumUtility/Assert.h"
#include "IntegerJsonHandler.h"
#include "Library.h"
#include "ObjectJsonHandler.h"
#include <map>
#include <unordered_map>
namespace CesiumJsonReader {
/**
* @brief Reads the keys and values of a JSON object into a
* `std::map<std::string, T>` or an `std::unordered_map<std::string, T>`.
*
* @tparam T The type of values in the map.
* @tparam THandler The type of the \ref IJsonHandler to handle the map values.
*/
template <typename T, typename THandler>
class CESIUMJSONREADER_API DictionaryJsonHandler : public ObjectJsonHandler {
public:
/**
* @brief Creates a new \ref DictionaryJsonHandler, passing the specified
* arguments to the constructor of THandler.
*/
template <typename... Ts>
DictionaryJsonHandler(Ts&&... args) noexcept
: ObjectJsonHandler(), _item(std::forward<Ts>(args)...) {}
/**
* @brief Resets the parent of this \ref IJsonHandler and sets the destination
* pointer of this handler to an `std::unordered_map<std::string, T>`.
*
* @warning Technically, there is no reason why you can't call `reset` twice
* on the same \ref DictionaryJsonHandler, once with an `std::map` and once
* with an `std::unordered_map`. In practice, if a pointer to an
* `std::unordered_map` is present, it will always be used as the destination
* and the pointer to an `std::map` will be ignored.
*/
void reset(
IJsonHandler* pParent,
std::unordered_map<std::string, T>* pDictionary) {
ObjectJsonHandler::reset(pParent);
this->_pDictionary1 = pDictionary;
}
/**
* @brief Resets the parent of this \ref IJsonHandler and sets the destination
* pointer of this handler to an `std::map<std::string, T>`.
*/
void reset(IJsonHandler* pParent, std::map<std::string, T>* pDictionary) {
ObjectJsonHandler::reset(pParent);
this->_pDictionary2 = pDictionary;
}
/** @copydoc IJsonHandler::readObjectKey */
virtual IJsonHandler* readObjectKey(const std::string_view& str) override {
CESIUM_ASSERT(this->_pDictionary1 || this->_pDictionary2);
if (this->_pDictionary1) {
auto it = this->_pDictionary1->emplace(str, T()).first;
return this->property(it->first.c_str(), this->_item, it->second);
}
auto it = this->_pDictionary2->emplace(str, T()).first;
return this->property(it->first.c_str(), this->_item, it->second);
}
private:
std::unordered_map<std::string, T>* _pDictionary1 = nullptr;
std::map<std::string, T>* _pDictionary2 = nullptr;
THandler _item;
};
} // namespace CesiumJsonReader

View File

@ -0,0 +1,33 @@
#pragma once
#include "JsonHandler.h"
#include "Library.h"
namespace CesiumJsonReader {
/**
* @brief \ref IJsonHandler for reading double values.
*/
class CESIUMJSONREADER_API DoubleJsonHandler : public JsonHandler {
public:
DoubleJsonHandler() noexcept;
/**
* @brief Resets the parent \ref IJsonHandler of this handler, and the pointer
* to its destination double value.
*/
void reset(IJsonHandler* pParent, double* pDouble);
/** @copydoc IJsonHandler::readInt32 */
virtual IJsonHandler* readInt32(int32_t i) override;
/** @copydoc IJsonHandler::readUint32 */
virtual IJsonHandler* readUint32(uint32_t i) override;
/** @copydoc IJsonHandler::readInt64 */
virtual IJsonHandler* readInt64(int64_t i) override;
/** @copydoc IJsonHandler::readUint64 */
virtual IJsonHandler* readUint64(uint64_t i) override;
/** @copydoc IJsonHandler::readDouble */
virtual IJsonHandler* readDouble(double d) override;
private:
double* _pDouble = nullptr;
};
} // namespace CesiumJsonReader

View File

@ -0,0 +1,58 @@
#pragma once
#include "DictionaryJsonHandler.h"
#include "ExtensionsJsonHandler.h"
#include "JsonObjectJsonHandler.h"
#include "JsonReaderOptions.h"
#include "ObjectJsonHandler.h"
#include <CesiumUtility/ExtensibleObject.h>
#include <CesiumUtility/JsonValue.h>
namespace CesiumJsonReader {
/**
* @brief An \ref IJsonHandler for reading \ref CesiumUtility::ExtensibleObject
* "ExtensibleObject" types.
*/
class ExtensibleObjectJsonHandler : public CesiumJsonReader::ObjectJsonHandler {
public:
/**
* @brief Creates an \ref ExtensibleObjectJsonHandler with the specified
* options.
*
* @param context Options to configure how the JSON is parsed.
*/
explicit ExtensibleObjectJsonHandler(
const JsonReaderOptions& context) noexcept;
protected:
/**
* @brief Resets the current parent of this handler, and the current object
* being handled.
*/
void reset(IJsonHandler* pParent, CesiumUtility::ExtensibleObject* pObject);
/**
* @brief Reads a property of an \ref CesiumUtility::ExtensibleObject
* "ExtensibleObject" from the JSON.
*
* @param objectType The name of the ExtensibleObject's type.
* @param str The object key being read.
* @param o The \ref CesiumUtility::ExtensibleObject "ExtensibleObject" we're
* currently reading into.
*/
IJsonHandler* readObjectKeyExtensibleObject(
const std::string& objectType,
const std::string_view& str,
CesiumUtility::ExtensibleObject& o);
private:
CesiumJsonReader::DictionaryJsonHandler<
CesiumUtility::JsonValue,
CesiumJsonReader::JsonObjectJsonHandler>
_extras;
ExtensionsJsonHandler _extensions;
JsonObjectJsonHandler _unknownProperties;
bool _captureUnknownProperties;
};
} // namespace CesiumJsonReader

View File

@ -0,0 +1,49 @@
#pragma once
#include "IExtensionJsonHandler.h"
#include "JsonReaderOptions.h"
#include "ObjectJsonHandler.h"
#include <CesiumUtility/ExtensibleObject.h>
#include <memory>
namespace CesiumJsonReader {
/**
* @brief \ref IJsonHandler for reading extensions, such as those listed in an
* \ref CesiumUtility::ExtensibleObject "ExtensibleObject".
*/
class ExtensionsJsonHandler : public CesiumJsonReader::ObjectJsonHandler {
public:
/**
* @brief Creates a new \ref ExtensionsJsonHandler with the specified reader
* options.
*
* @param context Options to configure how the JSON is read.
*/
explicit ExtensionsJsonHandler(const JsonReaderOptions& context) noexcept
: ObjectJsonHandler(),
_context(context),
_pObject(nullptr),
_currentExtensionHandler() {}
/**
* @brief Resets the \ref IJsonHandler's parent and pointer to destination, as
* well as the name of the object type that the extension is attached to.
*/
void reset(
IJsonHandler* pParent,
CesiumUtility::ExtensibleObject* pObject,
const std::string& objectType);
/** @copydoc IJsonHandler::readObjectKey */
virtual IJsonHandler* readObjectKey(const std::string_view& str) override;
private:
const JsonReaderOptions& _context;
CesiumUtility::ExtensibleObject* _pObject = nullptr;
std::string _objectType;
std::unique_ptr<IExtensionJsonHandler> _currentExtensionHandler;
};
} // namespace CesiumJsonReader

View File

@ -0,0 +1,40 @@
#pragma once
#include "IJsonHandler.h"
#include <CesiumUtility/ExtensibleObject.h>
#include <any>
#include <string_view>
namespace CesiumJsonReader {
/**
* @brief An interface for JSON handlers that handle extensions on \ref
* CesiumUtility::ExtensibleObject "ExtensibleObject" types.
*
* Usually, this will be a handler deriving from \ref ExtensionsJsonHandler that
* handles the specific extension found in the JSON. However, unknown extensions
* are read by a special \ref IExtensionJsonHandler returned by \ref
* JsonReaderOptions::createExtensionHandler, which reads the extension into the
* ExtensibleObject's `extensions` map as a \ref CesiumUtility::JsonValue
* "JsonValue".
*/
class IExtensionJsonHandler {
public:
virtual ~IExtensionJsonHandler() noexcept = default;
/**
* @brief Resets this \ref IExtensionJsonHandler's parent handler, destination
* object, and extension name.
*/
virtual void reset(
IJsonHandler* pParentHandler,
CesiumUtility::ExtensibleObject& o,
const std::string_view& extensionName) = 0;
/**
* @brief Obtains an \ref IJsonHandler from this \ref IExtensionJsonHandler.
*/
virtual IJsonHandler& getHandler() = 0;
};
} // namespace CesiumJsonReader

View File

@ -0,0 +1,122 @@
#pragma once
#include "Library.h"
#include <cstdint>
#include <string>
#include <string_view>
#include <vector>
namespace CesiumJsonReader {
/**
* @brief Base interface for all JSON handlers. Types that need to be
* deserialized from JSON should implement `IJsonHandler` or a class that
* derives from it. As the JSON is parsed, the corresponding `read...` method to
* the token that was parsed will be called. These methods can return themselves
* or a different handler to handle the value.
*/
class CESIUMJSONREADER_API IJsonHandler {
public:
virtual ~IJsonHandler(){};
/**
* @brief Called when the JSON parser encounters a `null`.
* @returns A \ref IJsonHandler that will handle the next `read...` call.
* This can be the same handler as the current one.
*/
virtual IJsonHandler* readNull() = 0;
/**
* @brief Called when the JSON parser encounters a boolean value.
* @param b The boolean value.
* @returns A \ref IJsonHandler that will handle the next `read...` call.
* This can be the same handler as the current one.
*/
virtual IJsonHandler* readBool(bool b) = 0;
/**
* @brief Called when the JSON parser encounters an int32 value.
* @param i The int32 value.
* @returns A \ref IJsonHandler that will handle the next `read...` call.
* This can be the same handler as the current one.
*/
virtual IJsonHandler* readInt32(int32_t i) = 0;
/**
* @brief Called when the JSON parser encounters a uint32 value.
* @param i The uint32 value.
* @returns A \ref IJsonHandler that will handle the next `read...` call.
* This can be the same handler as the current one.
*/
virtual IJsonHandler* readUint32(uint32_t i) = 0;
/**
* @brief Called when the JSON parser encounters an int64 value.
* @param i The int64 value.
* @returns A \ref IJsonHandler that will handle the next `read...` call.
* This can be the same handler as the current one.
*/
virtual IJsonHandler* readInt64(int64_t i) = 0;
/**
* @brief Called when the JSON parser encounters a uint64 value.
* @param i The uint64 value.
* @returns A \ref IJsonHandler that will handle the next `read...` call.
* This can be the same handler as the current one.
*/
virtual IJsonHandler* readUint64(uint64_t i) = 0;
/**
* @brief Called when the JSON parser encounters a double value.
* @param d The double value.
* @returns A \ref IJsonHandler that will handle the next `read...` call.
* This can be the same handler as the current one.
*/
virtual IJsonHandler* readDouble(double d) = 0;
/**
* @brief Called when the JSON parser encounters a string value.
* @param str The string value.
* @returns A \ref IJsonHandler that will handle the next `read...` call.
* This can be the same handler as the current one.
*/
virtual IJsonHandler* readString(const std::string_view& str) = 0;
/**
* @brief Called when the JSON parser encounters the beginning of an object.
* @returns A \ref IJsonHandler that will handle the next `read...` call.
* This can be the same handler as the current one.
*/
virtual IJsonHandler* readObjectStart() = 0;
/**
* @brief Called when the JSON parser encounters a key while reading an
* object.
* @param str The key.
* @returns A \ref IJsonHandler that will handle the next `read...` call.
* This can be the same handler as the current one.
*/
virtual IJsonHandler* readObjectKey(const std::string_view& str) = 0;
/**
* @brief Called when the JSON parser encounters the end of an object.
* @returns A \ref IJsonHandler that will handle the next `read...` call.
* This can be the same handler as the current one.
*/
virtual IJsonHandler* readObjectEnd() = 0;
/**
* @brief Called when the JSON parser encounters the start of an array.
* @returns A \ref IJsonHandler that will handle the next `read...` call.
* This can be the same handler as the current one.
*/
virtual IJsonHandler* readArrayStart() = 0;
/**
* @brief Called when the JSON parser encounters the end of an array.
* @returns A \ref IJsonHandler that will handle the next `read...` call.
* This can be the same handler as the current one.
*/
virtual IJsonHandler* readArrayEnd() = 0;
/**
* @brief Report a warning while reading JSON.
*
* @param warning The warning to report.
* @param context Context information to include with this warning to help
* debugging.
*/
virtual void reportWarning(
const std::string& warning,
std::vector<std::string>&& context = std::vector<std::string>()) = 0;
};
} // namespace CesiumJsonReader

View File

@ -0,0 +1,65 @@
#pragma once
#include "IJsonHandler.h"
#include "Library.h"
#include <cstdint>
namespace CesiumJsonReader {
/**
* @brief \ref IJsonHandler that does nothing but ignore the next value.
*
* Each `read...` call will return the current parent of this JsonHandler,
* unless the value being read is an object or array, in which case it will
* continue until the object or array is ended before returning.
*/
class CESIUMJSONREADER_API IgnoreValueJsonHandler : public IJsonHandler {
public:
/**
* @brief Resets the parent of this \ref IJsonHandler.
*/
void reset(IJsonHandler* pParent) noexcept;
/** @copydoc IJsonHandler::readNull */
virtual IJsonHandler* readNull() override;
/** @copydoc IJsonHandler::readBool */
virtual IJsonHandler* readBool(bool b) override;
/** @copydoc IJsonHandler::readInt32 */
virtual IJsonHandler* readInt32(int32_t i) override;
/** @copydoc IJsonHandler::readUint32 */
virtual IJsonHandler* readUint32(uint32_t i) override;
/** @copydoc IJsonHandler::readInt64 */
virtual IJsonHandler* readInt64(int64_t i) override;
/** @copydoc IJsonHandler::readUint64 */
virtual IJsonHandler* readUint64(uint64_t i) override;
/** @copydoc IJsonHandler::readDouble */
virtual IJsonHandler* readDouble(double d) override;
/** @copydoc IJsonHandler::readString */
virtual IJsonHandler* readString(const std::string_view& str) override;
/** @copydoc IJsonHandler::readObjectStart */
virtual IJsonHandler* readObjectStart() override;
/** @copydoc IJsonHandler::readObjectKey */
virtual IJsonHandler* readObjectKey(const std::string_view& str) override;
/** @copydoc IJsonHandler::readObjectEnd */
virtual IJsonHandler* readObjectEnd() override;
/** @copydoc IJsonHandler::readArrayStart */
virtual IJsonHandler* readArrayStart() override;
/** @copydoc IJsonHandler::readArrayEnd */
virtual IJsonHandler* readArrayEnd() override;
/** @copydoc IJsonHandler::reportWarning */
virtual void reportWarning(
const std::string& warning,
std::vector<std::string>&& context = std::vector<std::string>()) override;
/**
* @brief Obtains the currently set parent of this handler, or `nullptr` if
* `reset` hasn't yet been called.
*/
IJsonHandler* parent() noexcept;
private:
IJsonHandler* _pParent = nullptr;
int32_t _depth = 0;
};
} // namespace CesiumJsonReader

View File

@ -0,0 +1,79 @@
#pragma once
#include "CesiumUtility/Assert.h"
#include "JsonHandler.h"
#include "Library.h"
#include <cmath>
namespace CesiumJsonReader {
/**
* @brief \ref IJsonHandler for reading integer values.
*/
template <typename T>
class CESIUMJSONREADER_API IntegerJsonHandler : public JsonHandler {
public:
IntegerJsonHandler() noexcept : JsonHandler() {}
/**
* @brief Resets the parent \ref IJsonHandler of this instance and sets the
* pointer to its destination integer value.
*/
void reset(IJsonHandler* pParent, T* pInteger) {
JsonHandler::reset(pParent);
this->_pInteger = pInteger;
}
/**
* @brief Obtains the integer pointer set on this handler by \ref reset.
*/
T* getObject() { return this->_pInteger; }
/** @copydoc IJsonHandler::readInt32 */
virtual IJsonHandler* readInt32(int32_t i) override {
CESIUM_ASSERT(this->_pInteger);
*this->_pInteger = static_cast<T>(i);
return this->parent();
}
/** @copydoc IJsonHandler::readUint32 */
virtual IJsonHandler* readUint32(uint32_t i) override {
CESIUM_ASSERT(this->_pInteger);
*this->_pInteger = static_cast<T>(i);
return this->parent();
}
/** @copydoc IJsonHandler::readInt64 */
virtual IJsonHandler* readInt64(int64_t i) override {
CESIUM_ASSERT(this->_pInteger);
*this->_pInteger = static_cast<T>(i);
return this->parent();
}
/** @copydoc IJsonHandler::readUint64 */
virtual IJsonHandler* readUint64(uint64_t i) override {
CESIUM_ASSERT(this->_pInteger);
*this->_pInteger = static_cast<T>(i);
return this->parent();
}
/** @copydoc IJsonHandler::readDouble */
virtual IJsonHandler* readDouble(double d) override {
CESIUM_ASSERT(this->_pInteger);
double intPart;
double fractPart = std::modf(d, &intPart);
if (fractPart != 0) {
return JsonHandler::readDouble(d);
}
*this->_pInteger = static_cast<T>(intPart);
return this->parent();
}
/** @copydoc IJsonHandler::reportWarning */
virtual void reportWarning(
const std::string& warning,
std::vector<std::string>&& context) override {
context.push_back("(expecting an integer)");
this->parent()->reportWarning(warning, std::move(context));
}
private:
T* _pInteger = nullptr;
};
} // namespace CesiumJsonReader

View File

@ -0,0 +1,81 @@
#pragma once
#include "IJsonHandler.h"
#include "IgnoreValueJsonHandler.h"
#include "Library.h"
#include <cstdint>
#include <string>
namespace CesiumJsonReader {
/**
* @brief A dummy implementation of \ref IJsonHandler that will report a warning
* and return its parent when any of its `read...` methods are called.
*
* This class can be used as a base for any specialized JsonHandlers, overriding
* the methods required for the value you're handling and leaving the rest to
* report warnings if called.
*/
class CESIUMJSONREADER_API JsonHandler : public IJsonHandler {
public:
JsonHandler() noexcept;
/** @copydoc IJsonHandler::readNull */
virtual IJsonHandler* readNull() override;
/** @copydoc IJsonHandler::readBool */
virtual IJsonHandler* readBool(bool b) override;
/** @copydoc IJsonHandler::readInt32 */
virtual IJsonHandler* readInt32(int32_t i) override;
/** @copydoc IJsonHandler::readUint32 */
virtual IJsonHandler* readUint32(uint32_t i) override;
/** @copydoc IJsonHandler::readInt64 */
virtual IJsonHandler* readInt64(int64_t i) override;
/** @copydoc IJsonHandler::readUint64 */
virtual IJsonHandler* readUint64(uint64_t i) override;
/** @copydoc IJsonHandler::readDouble */
virtual IJsonHandler* readDouble(double d) override;
/** @copydoc IJsonHandler::readString */
virtual IJsonHandler* readString(const std::string_view& str) override;
/** @copydoc IJsonHandler::readObjectStart */
virtual IJsonHandler* readObjectStart() override;
/** @copydoc IJsonHandler::readObjectKey */
virtual IJsonHandler* readObjectKey(const std::string_view& str) override;
/** @copydoc IJsonHandler::readObjectEnd */
virtual IJsonHandler* readObjectEnd() override;
/** @copydoc IJsonHandler::readArrayStart */
virtual IJsonHandler* readArrayStart() override;
/** @copydoc IJsonHandler::readArrayEnd */
virtual IJsonHandler* readArrayEnd() override;
/** @copydoc IJsonHandler::reportWarning */
virtual void reportWarning(
const std::string& warning,
std::vector<std::string>&& context = std::vector<std::string>()) override;
protected:
/**
* @brief Resets the parent \ref IJsonHandler of this handler.
*/
void reset(IJsonHandler* pParent);
/**
* @brief Obtains the parent \ref IJsonHandler of this handler.
*/
IJsonHandler* parent();
/**
* @brief Ignore a single value and then return to the parent handler.
*/
IJsonHandler* ignoreAndReturnToParent();
/**
* @brief Ignore a single value and the continue processing more tokens with
* this handler.
*/
IJsonHandler* ignoreAndContinue();
private:
IJsonHandler* _pParent = nullptr;
IgnoreValueJsonHandler _ignore;
};
} // namespace CesiumJsonReader

View File

@ -0,0 +1,58 @@
#pragma once
#include "JsonHandler.h"
#include "Library.h"
#include <CesiumUtility/JsonValue.h>
namespace CesiumJsonReader {
/**
* @brief \ref IJsonHandler for arbitrary \ref CesiumUtility::JsonValue
* JsonValue objects.
*/
class CESIUMJSONREADER_API JsonObjectJsonHandler : public JsonHandler {
public:
JsonObjectJsonHandler() noexcept;
/**
* @brief Resets this \ref IJsonHandler's parent handler, as well as its
* destination pointer.
*/
void reset(IJsonHandler* pParent, CesiumUtility::JsonValue* pValue);
/** @copydoc IJsonHandler::readNull */
virtual IJsonHandler* readNull() override;
/** @copydoc IJsonHandler::readBool */
virtual IJsonHandler* readBool(bool b) override;
/** @copydoc IJsonHandler::readInt32 */
virtual IJsonHandler* readInt32(int32_t i) override;
/** @copydoc IJsonHandler::readUint32 */
virtual IJsonHandler* readUint32(uint32_t i) override;
/** @copydoc IJsonHandler::readInt64 */
virtual IJsonHandler* readInt64(int64_t i) override;
/** @copydoc IJsonHandler::readUint64 */
virtual IJsonHandler* readUint64(uint64_t i) override;
/** @copydoc IJsonHandler::readDouble */
virtual IJsonHandler* readDouble(double d) override;
/** @copydoc IJsonHandler::readString */
virtual IJsonHandler* readString(const std::string_view& str) override;
/** @copydoc IJsonHandler::readObjectStart */
virtual IJsonHandler* readObjectStart() override;
/** @copydoc IJsonHandler::readObjectKey */
virtual IJsonHandler* readObjectKey(const std::string_view& str) override;
/** @copydoc IJsonHandler::readObjectEnd */
virtual IJsonHandler* readObjectEnd() override;
/** @copydoc IJsonHandler::readArrayStart */
virtual IJsonHandler* readArrayStart() override;
/** @copydoc IJsonHandler::readArrayEnd */
virtual IJsonHandler* readArrayEnd() override;
private:
IJsonHandler* doneElement();
std::vector<CesiumUtility::JsonValue*> _stack;
std::string_view _currentKey;
};
} // namespace CesiumJsonReader

View File

@ -0,0 +1,148 @@
#pragma once
#include "JsonHandler.h"
#include "Library.h"
#include <rapidjson/document.h>
#include <cstddef>
#include <optional>
#include <span>
#include <string>
#include <vector>
namespace rapidjson {
struct MemoryStream;
}
namespace CesiumJsonReader {
/**
* @brief The result of {@link JsonReader::readJson}.
*/
template <typename T> struct ReadJsonResult {
/**
* @brief The value read from the JSON, or `std::nullopt` on error.
*/
std::optional<T> value;
/**
* @brief Errors that occurred while reading.
*/
std::vector<std::string> errors;
/**
* @brief Warnings that occurred while reading.
*/
std::vector<std::string> warnings;
};
/**
* @brief Reads JSON.
*/
class CESIUMJSONREADER_API JsonReader {
public:
/**
* @brief Reads JSON from a byte buffer into a statically-typed class.
*
* @param data The buffer from which to read JSON.
* @param handler The handler to receive the top-level JSON object. This
* instance must:
* - Implement {@link IJsonHandler}.
* - Contain a `ValueType` type alias indicating the type of the instance to
* be read into.
* - Have a `reset` method taking 1) a parent `IJsonHandler` pointer, and 2)
* and a pointer to a value of type `ValueType`.
* @return The result of reading the JSON.
*/
template <typename T>
static ReadJsonResult<typename T::ValueType>
readJson(const std::span<const std::byte>& data, T& handler) {
ReadJsonResult<typename T::ValueType> result;
result.value.emplace();
FinalJsonHandler finalHandler(result.warnings);
handler.reset(&finalHandler, &result.value.value());
JsonReader::internalRead(
data,
handler,
finalHandler,
result.errors,
result.warnings);
if (!result.errors.empty()) {
result.value.reset();
}
return result;
}
/**
* @brief Reads JSON from a `rapidjson::Value` into a statically-typed class.
*
* @param jsonValue The `rapidjson::Value` from which to read JSON.
* @param handler The handler to receive the top-level JSON object. This
* instance must:
* - Implement {@link IJsonHandler}.
* - Contain a `ValueType` type alias indicating the type of the instance to
* be read into.
* - Have a `reset` method taking 1) a parent `IJsonHandler` pointer, and 2)
* and a pointer to a value of type `ValueType`.
* @return The result of reading the JSON.
*/
template <typename T>
static ReadJsonResult<typename T::ValueType>
readJson(const rapidjson::Value& jsonValue, T& handler) {
ReadJsonResult<typename T::ValueType> result;
result.value.emplace();
FinalJsonHandler finalHandler(result.warnings);
handler.reset(&finalHandler, &result.value.value());
JsonReader::internalRead(
jsonValue,
handler,
finalHandler,
result.errors,
result.warnings);
if (!result.errors.empty()) {
result.value.reset();
}
return result;
}
private:
class FinalJsonHandler : public JsonHandler {
public:
FinalJsonHandler(std::vector<std::string>& warnings);
virtual void reportWarning(
const std::string& warning,
std::vector<std::string>&& context) override;
void setInputStream(rapidjson::MemoryStream* pInputStream) noexcept;
private:
std::vector<std::string>& _warnings;
rapidjson::MemoryStream* _pInputStream;
};
static void internalRead(
const std::span<const std::byte>& data,
IJsonHandler& handler,
FinalJsonHandler& finalHandler,
std::vector<std::string>& errors,
std::vector<std::string>& warnings);
static void internalRead(
const rapidjson::Value& jsonValue,
IJsonHandler& handler,
FinalJsonHandler& finalHandler,
std::vector<std::string>& errors,
std::vector<std::string>& warnings);
};
} // namespace CesiumJsonReader

View File

@ -0,0 +1,165 @@
#pragma once
#include "IExtensionJsonHandler.h"
#include "Library.h"
#include <functional>
#include <map>
#include <memory>
#include <optional>
#include <string>
#include <vector>
namespace CesiumJsonReader {
/**
* @brief The state of an extension.
*/
enum class ExtensionState {
/**
* @brief The extension is enabled.
*
* If a statically-typed class is available for the extension, it will be
* used. Otherwise the extension will be represented as a
* {@link CesiumUtility::JsonValue}.
*/
Enabled,
/**
* @brief The extension is enabled but will always be deserialized as a
* {@link CesiumUtility::JsonValue}.
*
* Even if a statically-typed class is available for the extension, it will
* not be used.
*/
JsonOnly,
/**
* @brief The extension is disabled.
*
* It will not be represented in the loaded model at all.
*/
Disabled
};
/**
* @brief Holds options for reading statically-typed data structures from JSON.
*/
class CESIUMJSONREADER_API JsonReaderOptions {
public:
/**
* @brief Gets a value indicating whether the values of unknown properties are
* captured in the {@link CesiumUtility::ExtensibleObject::unknownProperties} field.
*
* If this is false, unknown properties are completely ignored.
*/
bool getCaptureUnknownProperties() const {
return this->_captureUnknownProperties;
}
/**
* @brief Sets a value indicating whether the values of unknown properties are
* captured in the {@link CesiumUtility::ExtensibleObject::unknownProperties} field.
*
* If this is false, unknown properties are completely ignored.
*/
void setCaptureUnknownProperties(bool value) {
this->_captureUnknownProperties = value;
}
/**
* @brief Registers an extension for an object.
*
* @tparam TExtended The object to extend.
* @tparam TExtensionHandler The extension's
* {@link CesiumJsonReader::JsonHandler}.
* @param extensionName The name of the extension.
*/
template <typename TExtended, typename TExtensionHandler>
void registerExtension(const std::string& extensionName) {
auto it =
this->_extensions.emplace(extensionName, ObjectTypeToHandler()).first;
it->second.insert_or_assign(
TExtended::TypeName,
ExtensionReaderFactory([](const JsonReaderOptions& context) {
return std::make_unique<TExtensionHandler>(context);
}));
}
/**
* @brief Registers an extension for an object.
*
* The extension name is obtained from `TExtensionHandler::ExtensionName`.
*
* @tparam TExtended The object to extend.
* @tparam TExtensionHandler The extension's
* {@link CesiumJsonReader::JsonHandler}.
*/
template <typename TExtended, typename TExtensionHandler>
void registerExtension() {
auto it =
this->_extensions
.emplace(TExtensionHandler::ExtensionName, ObjectTypeToHandler())
.first;
it->second.insert_or_assign(
TExtended::TypeName,
ExtensionHandlerFactory([](const JsonReaderOptions& context) {
return std::make_unique<TExtensionHandler>(context);
}));
}
/**
* @brief Returns whether an extension is enabled or disabled.
*
* By default, all extensions are enabled.
*
* @param extensionName The name of the extension.
*/
ExtensionState getExtensionState(const std::string& extensionName) const;
/**
* @brief Enables or disables an extension.
*
* By default, all extensions are enabled. When an enabled extension is
* encountered in the source JSON, it is read into a statically-typed
* extension class, if one is registered, or into a
* {@link CesiumUtility::JsonValue} if not.
*
* When a disabled extension is encountered in the source JSON, it is ignored
* completely.
*
* An extension may also be set to `ExtensionState::JsonOnly`, in which case
* it will be read into a {@link CesiumUtility::JsonValue} even if a
* statically-typed extension class is registered.
*
* @param extensionName The name of the extension to be enabled or disabled.
* @param newState The new state for the extension.
*/
void
setExtensionState(const std::string& extensionName, ExtensionState newState);
/**
* @brief Creates an extension handler for the given extension.
*
* @param extensionName The name of the extension to create a handler for.
* @param extendedObjectType The name of the type of the object that is being
* extended.
* @returns An \ref IExtensionJsonHandler to read the extension.
*/
std::unique_ptr<IExtensionJsonHandler> createExtensionHandler(
const std::string_view& extensionName,
const std::string& extendedObjectType) const;
private:
using ExtensionHandlerFactory =
std::function<std::unique_ptr<IExtensionJsonHandler>(
const JsonReaderOptions&)>;
using ObjectTypeToHandler = std::map<std::string, ExtensionHandlerFactory>;
using ExtensionNameMap = std::map<std::string, ObjectTypeToHandler>;
ExtensionNameMap _extensions;
std::unordered_map<std::string, ExtensionState> _extensionStates;
bool _captureUnknownProperties = true;
};
} // namespace CesiumJsonReader

View File

@ -0,0 +1,18 @@
#pragma once
/**
* @brief Classes for reading JSON.
*
* @mermaid-interactive{dependencies/CesiumJsonReader}
*/
namespace CesiumJsonReader {}
#if defined(_WIN32) && defined(CESIUM_SHARED)
#ifdef CESIUMJSONREADER_BUILDING
#define CESIUMJSONREADER_API __declspec(dllexport)
#else
#define CESIUMJSONREADER_API __declspec(dllimport)
#endif
#else
#define CESIUMJSONREADER_API
#endif

View File

@ -0,0 +1,101 @@
#pragma once
#include "JsonHandler.h"
#include "Library.h"
#include <CesiumUtility/IntrusivePointer.h>
#include <optional>
namespace CesiumJsonReader {
/**
* @brief \ref IJsonHandler for handling JSON objects.
*/
class CESIUMJSONREADER_API ObjectJsonHandler : public JsonHandler {
public:
ObjectJsonHandler() noexcept : JsonHandler() {}
/** @copydoc IJsonHandler::readObjectStart */
virtual IJsonHandler* readObjectStart() override /* final */;
/** @copydoc IJsonHandler::readObjectEnd */
virtual IJsonHandler* readObjectEnd() override /* final */;
protected:
/**
* @brief Called when \ref readObjectStart is called when the depth of the
* \ref ObjectJsonHandler is greater than 0.
*/
virtual IJsonHandler* StartSubObject() noexcept;
/**
* @brief Called when \ref readObjectEnd is called when the depth of the
* \ref ObjectJsonHandler is greater than 0.
*/
virtual IJsonHandler* EndSubObject() noexcept;
/**
* @brief Called from \ref IJsonHandler::readObjectKey to read a property into
* an object.
*
* @param currentKey The key that's currently being read.
* @param accessor An \ref IJsonHandler that can read the type of this
* property.
* @param value A reference to the location to store the read value.
* @returns The `accessor` \ref IJsonHandler that will read the next token
* into `value`.
*/
template <typename TAccessor, typename TProperty>
IJsonHandler*
property(const char* currentKey, TAccessor& accessor, TProperty& value) {
this->_currentKey = currentKey;
if constexpr (isOptional<TProperty>::value) {
value.emplace();
accessor.reset(this, &value.value());
} else if constexpr (isIntrusivePointer<TProperty>::value) {
value.emplace();
accessor.reset(this, value.get());
} else {
accessor.reset(this, &value);
}
return &accessor;
}
/**
* @brief Obtains the most recent key handled by this JsonHandler.
*/
const char* getCurrentKey() const noexcept;
/** @copydoc IJsonHandler::reportWarning */
virtual void reportWarning(
const std::string& warning,
std::vector<std::string>&& context = std::vector<std::string>()) override;
protected:
/**
* @brief Sets the most recent key handled by this JsonHandler.
*/
void setCurrentKey(const char* key) noexcept;
private:
template <typename T> struct isOptional {
static constexpr bool value = false;
};
template <typename T> struct isOptional<std::optional<T>> {
static constexpr bool value = true;
};
template <typename T> struct isIntrusivePointer {
static constexpr bool value = false;
};
template <typename T>
struct isIntrusivePointer<CesiumUtility::IntrusivePointer<T>> {
static constexpr bool value = true;
};
int32_t _depth = 0;
const char* _currentKey = nullptr;
};
} // namespace CesiumJsonReader

View File

@ -0,0 +1,42 @@
#pragma once
#include <CesiumJsonReader/ExtensibleObjectJsonHandler.h>
#include <CesiumUtility/ExtensibleObject.h>
#include <CesiumUtility/JsonValue.h>
#include <string_view>
namespace CesiumJsonReader {
/**
* @brief \ref IJsonHandler for \ref CesiumUtility::SharedAsset "SharedAsset"
* values.
*
* This is more or less the same as directly using \ref
* ExtensibleObjectJsonHandler, and exists for compatibility with generated
* code.
*/
class SharedAssetJsonHandler
: public CesiumJsonReader::ExtensibleObjectJsonHandler {
public:
/**
* @brief Creates an \ref SharedAssetJsonHandler with the specified
* options.
*
* @param context Options to configure how the JSON is parsed.
*/
explicit SharedAssetJsonHandler(
const CesiumJsonReader::JsonReaderOptions& context) noexcept;
protected:
/** @copydoc ExtensibleObjectJsonHandler::reset */
void reset(IJsonHandler* pParent, CesiumUtility::ExtensibleObject* pObject);
/** @copydoc ExtensibleObjectJsonHandler::readObjectKeyExtensibleObject */
IJsonHandler* readObjectKeySharedAsset(
const std::string& objectType,
const std::string_view& str,
CesiumUtility::ExtensibleObject& o);
private:
};
} // namespace CesiumJsonReader

View File

@ -0,0 +1,31 @@
#pragma once
#include "JsonHandler.h"
#include "Library.h"
#include <string>
namespace CesiumJsonReader {
/**
* @brief \ref IJsonHandler for reading string values.
*/
class CESIUMJSONREADER_API StringJsonHandler : public JsonHandler {
public:
StringJsonHandler() noexcept;
/**
* @brief Resets the parent \ref IJsonHandler of this handler, and the pointer
* to its destination string value.
*/
void reset(IJsonHandler* pParent, std::string* pString);
/**
* @brief Obtains the pointer to the current destination string value of this
* handler.
*/
std::string* getObject() noexcept;
/** @copydoc IJsonHandler::readString */
virtual IJsonHandler* readString(const std::string_view& str) override;
private:
std::string* _pString = nullptr;
};
} // namespace CesiumJsonReader