初始提交: 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,133 @@
#pragma once
#include "CesiumJsonWriter/JsonWriter.h"
#include "CesiumJsonWriter/Library.h"
#include <any>
#include <functional>
#include <map>
#include <string>
#include <unordered_map>
namespace CesiumJsonWriter {
/**
* @brief The state of an extension.
*/
enum class ExtensionState {
/**
* @brief The extension is enabled.
*
* If the extension is a {@link CesiumUtility::JsonValue} or a registered
* statically-typed class it will be written to the serialized model;
* otherwise it will be ignored and a warning will be reported.
*/
Enabled,
/**
* @brief The extension is disabled.
*
* It will not be represented in the serialized model at all.
*/
Disabled
};
/**
* @brief A context for writing extensions where known extensions and their
* handlers can be registered.
*/
class CESIUMJSONWRITER_API ExtensionWriterContext {
private:
template <typename TExtension>
using ExtensionHandler = std::function<
void(const TExtension&, JsonWriter&, const ExtensionWriterContext&)>;
public:
/**
* @brief Registers an extension for an object.
*
* @tparam TExtended The object to extend.
* @tparam TExtensionHandler The extension's writer.
* @param extensionName The name of the extension.
*/
template <typename TExtended, typename TExtensionHandler>
void registerExtension(const std::string& extensionName) {
using TExtension = typename TExtensionHandler::ValueType;
auto it =
this->_extensions.emplace(extensionName, ObjectTypeToHandler()).first;
it->second.insert_or_assign(
TExtended::TypeName,
[](const std::any& obj,
JsonWriter& jsonWriter,
const ExtensionWriterContext& context) {
return TExtensionHandler::write(
std::any_cast<const TExtension&>(obj),
jsonWriter,
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 writer.
*/
template <typename TExtended, typename TExtensionHandler>
void registerExtension() {
registerExtension<TExtended, TExtensionHandler>(
TExtensionHandler::ExtensionName);
}
/**
* @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. However, if the extension is a
* statically-typed class and is not registered it will be ignored and a
* warning will be reported.
*
* When a disabled extension is encountered, it is ignored completely.
*
* @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 Attempts to create an `ExtensionHandler` for the given object,
* returning `nullptr` if no handler could be found.
*
* @param extensionName The name of the extension.
* @param obj The object of unknown type to create the handler for.
* @param extendedObjectType The `TypeName` of the extended object.
* @returns The handler for this extension, or `nullptr` if none could be
* created.
*/
ExtensionHandler<std::any> createExtensionHandler(
const std::string_view& extensionName,
const std::any& obj,
const std::string& extendedObjectType) const;
private:
using ObjectTypeToHandler =
std::unordered_map<std::string, ExtensionHandler<std::any>>;
using ExtensionNameMap = std::map<std::string, ObjectTypeToHandler>;
ExtensionNameMap _extensions;
std::unordered_map<std::string, ExtensionState> _extensionStates;
};
} // namespace CesiumJsonWriter

View File

@ -0,0 +1,21 @@
#pragma once
// forward declarations
namespace CesiumJsonWriter {
class JsonWriter;
}
// forward declarations
namespace CesiumUtility {
class JsonValue;
}
namespace CesiumJsonWriter {
/**
* @brief Writes the given \ref CesiumUtility::JsonValue to the provided writer.
*
* @param value The value to write.
* @param writer The writer used to write the provided value.
*/
void writeJsonValue(const CesiumUtility::JsonValue& value, JsonWriter& writer);
} // namespace CesiumJsonWriter

View File

@ -0,0 +1,295 @@
#pragma once
#include <rapidjson/stringbuffer.h>
#include <rapidjson/writer.h>
#include <cstddef>
#include <cstdint>
#include <functional>
#include <memory>
#include <string>
#include <string_view>
#include <vector>
namespace CesiumJsonWriter {
/**
* @brief Wrapper around `rapidjson::Writer` for writing objects to JSON.
*/
class JsonWriter {
public:
JsonWriter();
virtual ~JsonWriter() {}
/**
* @brief Writes a `null` value to the output.
* @returns True if the write was successful.
*/
virtual bool Null();
/**
* @brief Writes a boolean value to the output.
* @param b The boolean value to write.
* @returns True if the write was successful.
*/
virtual bool Bool(bool b);
/**
* @brief Writes a signed integer value to the output.
* @param i The integer value to write.
* @returns True if the write was successful.
*/
virtual bool Int(int i);
/**
* @brief Writes an unsigned integer value to the output.
* @param i The integer value to write.
* @returns True if the write was successful.
*/
virtual bool Uint(unsigned int i);
/**
* @brief Writes an unsigned 64-bit integer value to the output.
* @param i The integer value to write.
* @returns True if the write was successful.
*/
virtual bool Uint64(std::uint64_t i);
/**
* @brief Writes an signed 64-bit integer value to the output.
* @param i The integer value to write.
* @returns True if the write was successful.
*/
virtual bool Int64(std::int64_t i);
/**
* @brief Writes a 64-bit floating point value to the output.
* @param d The double value to write.
* @returns True if the write was successful.
*/
virtual bool Double(double d);
/**
* @brief Writes the given string as a number to the output without any kind
* of special handling.
*
* @param str The raw number to write directly to the output.
* @param length The length of the string.
* @param copy If true, the string will be copied.
* @returns True if the write was successful.
*/
virtual bool RawNumber(const char* str, unsigned int length, bool copy);
/**
* @brief Writes the given string as an object key to the output.
*
* @param string The key to write.
* @returns True if the write was successful.
*/
virtual bool Key(std::string_view string);
/**
* @brief Writes the given string as a value to the output.
*
* @param string The string to write.
* @returns True if the write was successful.
*/
virtual bool String(std::string_view string);
/**
* @brief Writes the start of a JSON object to the output.
*
* @returns True if the write was successful.
*/
virtual bool StartObject();
/**
* @brief Writes the end of a JSON object to the output.
*
* @returns True if the write was successful.
*/
virtual bool EndObject();
/**
* @brief Writes the start of a JSON array to the output.
*
* @returns True if the write was successful.
*/
virtual bool StartArray();
/**
* @brief Writes the end of a JSON array to the output.
*
* @returns True if the write was successful.
*/
virtual bool EndArray();
/**
* @brief Writes the given primitive to the output. This is a convenience
* function for \ref Int.
* @param value The int32_t value to write.
*/
virtual void Primitive(std::int32_t value);
/**
* @brief Writes the given primitive to the output. This is a convenience
* function for \ref Uint.
* @param value The uint32_t value to write.
*/
virtual void Primitive(std::uint32_t value);
/**
* @brief Writes the given primitive to the output. This is a convenience
* function for \ref Int64.
* @param value The int64_t value to write.
*/
virtual void Primitive(std::int64_t value);
/**
* @brief Writes the given primitive to the output. This is a convenience
* function for \ref Uint64.
* @param value The uint64_t value to write.
*/
virtual void Primitive(std::uint64_t value);
/**
* @brief Writes the given primitive to the output. This is a convenience
* function for \ref Double.
* @param value The float value to write.
*/
virtual void Primitive(float value);
/**
* @brief Writes the given primitive to the output. This is a convenience
* function for \ref Double.
* @param value The double value to write.
*/
virtual void Primitive(double value);
/**
* @brief Writes the given primitive to the output. This is a convenience
* function for \ref Null.
* @param value The null value to write.
*/
virtual void Primitive(std::nullptr_t value);
/**
* @brief Writes the given primitive to the output. This is a convenience
* function for \ref String.
* @param string The string value to write.
*/
virtual void Primitive(std::string_view string);
/**
* @brief Writes the given key and its corresponding value primitive to the
* output. This is a convenience function for calling \ref Key followed by
* \ref Int.
* @param keyName The key to write to the output.
* @param value The primitive value to write.
*/
virtual void KeyPrimitive(std::string_view keyName, std::int32_t value);
/**
* @brief Writes the given key and its corresponding value primitive to the
* output. This is a convenience function for calling \ref Key followed by
* \ref Uint.
* @param keyName The key to write to the output.
* @param value The primitive value to write.
*/
virtual void KeyPrimitive(std::string_view keyName, std::uint32_t value);
/**
* @brief Writes the given key and its corresponding value primitive to the
* output. This is a convenience function for calling \ref Key followed by
* \ref Int64.
* @param keyName The key to write to the output.
* @param value The primitive value to write.
*/
virtual void KeyPrimitive(std::string_view keyName, std::int64_t value);
/**
* @brief Writes the given key and its corresponding value primitive to the
* output. This is a convenience function for calling \ref Key followed by
* \ref Uint64.
* @param keyName The key to write to the output.
* @param value The primitive value to write.
*/
virtual void KeyPrimitive(std::string_view keyName, std::uint64_t value);
/**
* @brief Writes the given key and its corresponding value primitive to the
* output. This is a convenience function for calling \ref Key followed by
* \ref String.
* @param keyName The key to write to the output.
* @param value The primitive value to write.
*/
virtual void KeyPrimitive(std::string_view keyName, std::string_view value);
/**
* @brief Writes the given key and its corresponding value primitive to the
* output. This is a convenience function for calling \ref Key followed by
* \ref Double.
* @param keyName The key to write to the output.
* @param value The primitive value to write.
*/
virtual void KeyPrimitive(std::string_view keyName, float value);
/**
* @brief Writes the given key and its corresponding value primitive to the
* output. This is a convenience function for calling \ref Key followed by
* \ref Double.
* @param keyName The key to write to the output.
* @param value The primitive value to write.
*/
virtual void KeyPrimitive(std::string_view keyName, double value);
/**
* @brief Writes the given key and its corresponding value primitive to the
* output. This is a convenience function for calling \ref Key followed by
* \ref Null.
* @param keyName The key to write to the output.
* @param value The primitive value to write.
*/
virtual void KeyPrimitive(std::string_view keyName, std::nullptr_t value);
/**
* @brief Writes an array to the output with the given key and calls the
* provided callback to write values inside of the array. This is a
* convenience function for calling \ref Key followed by \ref StartArray
* followed by the values you wish to write and ending with \ref EndArray.
*
* @param keyName The key to write to the output.
* @param insideArray The callback to run, after \ref StartArray but before
* \ref EndArray.
*/
virtual void
KeyArray(std::string_view keyName, std::function<void(void)> insideArray);
/**
* @brief Writes an object to the output with the given key and calls the
* provided callback to write values inside of the object. This is a
* convenience function for calling \ref Key followed by \ref StartObject
* followed by the values you wish to write and ending with \ref EndObject.
*
* @param keyName The key to write to the output.
* @param insideObject The callback to run, after \ref StartObject but before
* \ref EndObject.
*/
virtual void
KeyObject(std::string_view keyName, std::function<void(void)> insideObject);
/**
* @brief Obtains the written output as a string.
*/
virtual std::string toString();
/**
* @brief Obtains the written output as a string_view.
*/
virtual std::string_view toStringView();
/**
* @brief Obtains the written output as a buffer of bytes.
*/
virtual std::vector<std::byte> toBytes();
/**
* @brief Emplaces a new error into the internal error buffer.
*/
template <typename ErrorStr> void emplaceError(ErrorStr&& error) {
_errors.emplace_back(std::forward<ErrorStr>(error));
}
/**
* @brief Emplaces a new warning into the internal warning buffer.
*/
template <typename WarningStr> void emplaceWarning(WarningStr&& warning) {
_warnings.emplace_back(std::forward<WarningStr>(warning));
}
/**
* @brief Obtains the current error buffer.
*/
const std::vector<std::string>& getErrors() const { return _errors; }
/**
* @brief Obtains the current warning buffer.
*/
const std::vector<std::string>& getWarnings() const { return _warnings; }
private:
rapidjson::StringBuffer _compactBuffer;
std::unique_ptr<rapidjson::Writer<rapidjson::StringBuffer>> _compact;
std::vector<std::string> _errors;
std::vector<std::string> _warnings;
};
} // namespace CesiumJsonWriter

View File

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

View File

@ -0,0 +1,71 @@
#pragma once
#include "JsonWriter.h"
#include <rapidjson/prettywriter.h>
#include <rapidjson/stringbuffer.h>
#include <cstdint>
#include <functional>
#include <memory>
#include <string_view>
#include <vector>
namespace CesiumJsonWriter {
/**
* @brief Implementation of \ref JsonWriter that "pretty-prints" JSON to the
* output, formatted with new lines and indentation.
*/
class PrettyJsonWriter : public JsonWriter {
rapidjson::StringBuffer _prettyBuffer;
std::unique_ptr<rapidjson::PrettyWriter<rapidjson::StringBuffer>> pretty;
public:
PrettyJsonWriter() noexcept;
~PrettyJsonWriter() {}
bool Null() override;
bool Bool(bool b) override;
bool Int(int i) override;
bool Uint(unsigned int i) override;
bool Uint64(std::uint64_t i) override;
bool Int64(std::int64_t i) override;
bool Double(double d) override;
bool RawNumber(const char* str, unsigned int length, bool copy) override;
bool Key(std::string_view string) override;
bool String(std::string_view string) override;
bool StartObject() override;
bool EndObject() override;
bool StartArray() override;
bool EndArray() override;
void Primitive(std::int32_t value) override;
void Primitive(std::uint32_t value) override;
void Primitive(std::int64_t value) override;
void Primitive(std::uint64_t value) override;
void Primitive(float value) override;
void Primitive(double value) override;
void Primitive(std::nullptr_t value) override;
void Primitive(std::string_view string) override;
void KeyPrimitive(std::string_view keyName, std::int32_t value) override;
void KeyPrimitive(std::string_view keyName, std::uint32_t value) override;
void KeyPrimitive(std::string_view keyName, std::int64_t value) override;
void KeyPrimitive(std::string_view keyName, std::uint64_t value) override;
void KeyPrimitive(std::string_view keyName, std::string_view value) override;
void KeyPrimitive(std::string_view keyName, float value) override;
void KeyPrimitive(std::string_view keyName, double value) override;
void KeyPrimitive(std::string_view keyName, std::nullptr_t value) override;
void KeyArray(std::string_view keyName, std::function<void(void)> insideArray)
override;
void KeyObject(
std::string_view keyName,
std::function<void(void)> insideObject) override;
std::string toString() override;
std::string_view toStringView() override;
std::vector<std::byte> toBytes() override;
};
} // namespace CesiumJsonWriter

View File

@ -0,0 +1,85 @@
#pragma once
#include "CesiumJsonWriter/ExtensionWriterContext.h"
#include "CesiumJsonWriter/JsonWriter.h"
#include <spdlog/fmt/fmt.h>
namespace CesiumJsonWriter {
/**
* @brief Writes the extensions attached to the provided object as a new JSON
* object.
*
* @tparam TExtended The type with extensions attached to write. This type must
* have an `extensions` property of type `std::unordered_map<std::string,
* std::any>` or a similar type with an `empty()` method that returns pairs of
* `<std::string, std::any>` when iterated.
* @param obj The object with extensions to write.
* @param jsonWriter The writer to write the extensions object to.
* @param context The \ref ExtensionWriterContext that provides information on
* how to write each extension.
*/
template <typename TExtended>
void writeJsonExtensions(
const TExtended& obj,
JsonWriter& jsonWriter,
const ExtensionWriterContext& context) {
if (obj.extensions.empty()) {
return;
}
jsonWriter.StartObject();
for (const auto& item : obj.extensions) {
auto handler = context.createExtensionHandler(
item.first,
item.second,
TExtended::TypeName);
if (handler) {
jsonWriter.Key(item.first);
handler(item.second, jsonWriter, context);
}
}
jsonWriter.EndObject();
}
/**
* @brief Checks if the provided object has any extensions attached that have
* been registered with the provided \ref ExtensionWriterContext.
*
* @tparam TExtended The type with extensions attached to write. This type must
* have an `extensions` property of type `std::unordered_map<std::string,
* std::any>` or a similar type with an `empty()` method that returns pairs of
* `<std::string, std::any>` when iterated.
* @param obj The object with extensions to write.
* @param jsonWriter The writer to write the extensions object to.
* @param context The \ref ExtensionWriterContext with registered extensions.
* @returns True if any extensions attached to `obj` have been registered, false
* otherwise.
*/
template <typename TExtended>
bool hasRegisteredExtensions(
const TExtended& obj,
JsonWriter& jsonWriter,
const ExtensionWriterContext& context) {
bool hasRegisteredExtensions = false;
for (const auto& item : obj.extensions) {
auto handler = context.createExtensionHandler(
item.first,
item.second,
TExtended::TypeName);
if (handler) {
hasRegisteredExtensions = true;
} else if (
context.getExtensionState(item.first) != ExtensionState::Disabled) {
jsonWriter.emplaceWarning(fmt::format(
"Encountered unregistered extension {}. This extension will be "
"ignored. To silence this warning, disable the extension with "
"ExtensionWriterContext::setExtensionState.",
item.first));
}
}
return hasRegisteredExtensions;
}
} // namespace CesiumJsonWriter