mirror of
https://github.com/borgesdan/xn65
synced 2024-12-29 21:54:47 +01:00
Implementa ContentTypeReaderManager
This commit is contained in:
parent
efab931113
commit
956c9e6ebf
@ -39,7 +39,7 @@ add_executable (xna WIN32
|
||||
"content/manager.cpp"
|
||||
"content/reader.cpp"
|
||||
"csharp/binary.cpp"
|
||||
"content/decstream.cpp" "content/lzx/decoder.cpp" "content/lzx/decoderstream.cpp" "content/typereadermanager.cpp" "csharp/object.cpp")
|
||||
"content/decstream.cpp" "content/lzx/decoder.cpp" "content/lzx/decoderstream.cpp" "content/typereadermanager.cpp" "csharp/object.cpp" "csharp/type.cpp")
|
||||
|
||||
if (CMAKE_VERSION VERSION_GREATER 3.12)
|
||||
set_property(TARGET xna PROPERTY CXX_STANDARD 20)
|
||||
|
@ -1,6 +1,7 @@
|
||||
#include "reader.hpp"
|
||||
#include "manager.hpp"
|
||||
#include "lzx/decoderstream.hpp"
|
||||
#include "typereadermanager.hpp"
|
||||
|
||||
namespace xna {
|
||||
sptr<ContentReader> ContentReader::Create(ContentManager* contentManager, Stream* input, String const& assetName)
|
||||
@ -53,6 +54,6 @@ namespace xna {
|
||||
}
|
||||
|
||||
Int ContentReader::ReadHeader() {
|
||||
return Int();
|
||||
//typeReaders = ContentTypeReaderManager::ReadTypeManifest(this->Read7BitEncodedInt(), this);
|
||||
}
|
||||
}
|
||||
|
@ -34,10 +34,12 @@ namespace xna {
|
||||
return contentTypeReaderArray;
|
||||
}
|
||||
|
||||
sptr<ContentTypeReader> ContentTypeReaderManager::GetTypeReader(String const& targetType, sptr<ContentReader>& contentReader, xna_error_ptr_arg)
|
||||
sptr<ContentTypeReader> ContentTypeReaderManager::GetTypeReader(sptr<Type> const& targetType, sptr<ContentReader>& contentReader, xna_error_ptr_arg)
|
||||
{
|
||||
if (targetType.empty())
|
||||
if (!targetType) {
|
||||
xna_error_apply(err, XnaErrorCode::ARGUMENT_IS_NULL);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
sptr<ContentTypeReader> typeReader = nullptr;
|
||||
|
||||
@ -57,10 +59,13 @@ namespace xna {
|
||||
{
|
||||
sptr<ContentTypeReader> reader = nullptr;
|
||||
|
||||
if (ContentTypeReaderManager::nameToReader.contains(readerTypeName) || !ContentTypeReaderManager::InstantiateTypeReader(readerTypeName, contentReader, reader)) {
|
||||
if (ContentTypeReaderManager::nameToReader.contains(readerTypeName) || !ContentTypeReaderManager::InstantiateTypeReader(readerTypeName, contentReader, reader, err)) {
|
||||
return ContentTypeReaderManager::nameToReader[readerTypeName];
|
||||
}
|
||||
|
||||
if (xna_error_haserros(err))
|
||||
return nullptr;
|
||||
|
||||
ContentTypeReaderManager::AddTypeReader(readerTypeName, contentReader, reader, err);
|
||||
|
||||
if (xna_error_haserros(err)) return nullptr;
|
||||
@ -70,15 +75,30 @@ namespace xna {
|
||||
return reader;
|
||||
}
|
||||
|
||||
bool ContentTypeReaderManager::InstantiateTypeReader(String const& readerTypeName, sptr<ContentReader>& contentReader, sptr<ContentTypeReader>& reader)
|
||||
bool ContentTypeReaderManager::InstantiateTypeReader(String const& readerTypeName, sptr<ContentReader>& contentReader, sptr<ContentTypeReader>& reader, xna_error_ptr_arg)
|
||||
{
|
||||
if (ContentTypeReaderManager::readerTypeToReader.contains(readerTypeName)) {
|
||||
reader = ContentTypeReaderManager::readerTypeToReader[readerTypeName];
|
||||
sptr<Type> type = nullptr;
|
||||
|
||||
std::map<sptr<Type>, sptr<ContentTypeReader>>::iterator it;
|
||||
|
||||
for (it = readerTypeToReader.begin(); it != readerTypeToReader.end(); it++) {
|
||||
if (it->first->FullName == readerTypeName)
|
||||
type = it->first;
|
||||
}
|
||||
|
||||
if (!type) {
|
||||
xna_error_apply(err, XnaErrorCode::INVALID_OPERATION);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (ContentTypeReaderManager::readerTypeToReader.contains(type)) {
|
||||
reader = ContentTypeReaderManager::readerTypeToReader[type];
|
||||
ContentTypeReaderManager::nameToReader.insert({ readerTypeName, reader });
|
||||
return false;
|
||||
}
|
||||
|
||||
reader = ContentTypeReaderActivador::CreateInstance(readerTypeName);
|
||||
reader = ContentTypeReaderActivador::CreateInstance(type, err);
|
||||
return true;
|
||||
}
|
||||
|
||||
void ContentTypeReaderManager::AddTypeReader(String const& readerTypeName, sptr<ContentReader>& contentReader, sptr<ContentTypeReader>& reader, xna_error_ptr_arg)
|
||||
@ -106,18 +126,7 @@ namespace xna {
|
||||
ContentTypeReaderManager::RollbackAddReader(ContentTypeReaderManager::targetTypeToReader, newTypeReader);
|
||||
ContentTypeReaderManager::RollbackAddReader(ContentTypeReaderManager::readerTypeToReader, newTypeReader);
|
||||
}
|
||||
}
|
||||
|
||||
void ContentTypeReaderManager::RollbackAddReader(std::map<String, sptr<ContentTypeReader>>& dictionary, sptr<ContentTypeReader>& reader) {
|
||||
std::map<String, sptr<ContentTypeReader>>::iterator it;
|
||||
|
||||
for (it = dictionary.begin(); it != dictionary.end(); it++) {
|
||||
if (it->second == reader) {
|
||||
dictionary.erase(it->first);
|
||||
it = dictionary.begin();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ContentTypeReaderManager::initMaps()
|
||||
{
|
||||
@ -125,8 +134,10 @@ namespace xna {
|
||||
auto typeReader = New<ObjectReader>();
|
||||
auto contentTypeReader = reinterpret_pointer_cast<ContentTypeReader>(typeReader);
|
||||
|
||||
targetTypeToReader.insert({ typeReader->TargetType(), contentTypeReader});
|
||||
readerTypeToReader.insert({ typeReader->GetType(), contentTypeReader});
|
||||
//targetTypeToReader.insert({ typeReader->TargetType(), contentTypeReader});
|
||||
//readerTypeToReader.insert({ typeReader->GetType(), contentTypeReader});
|
||||
targetTypeToReader.insert({ typeof<Object>(), contentTypeReader});
|
||||
readerTypeToReader.insert({ typeof<ObjectReader>(), contentTypeReader});
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,56 +1,100 @@
|
||||
#ifndef XNA_CONTENT_TYPEREADER_HPP
|
||||
#define XNA_CONTENT_TYPEREADER_HPP
|
||||
|
||||
#include "../csharp/type.hpp"
|
||||
#include "../default.hpp"
|
||||
#include <map>
|
||||
#include <algorithm>
|
||||
#include <map>
|
||||
|
||||
namespace xna {
|
||||
//ContentTypeReader
|
||||
class ContentTypeReader {
|
||||
//-------------------------------------------------------//
|
||||
// ContentTypeReader //
|
||||
//-------------------------------------------------------//
|
||||
class ContentTypeReader : public Object {
|
||||
public:
|
||||
ContentTypeReader(){}
|
||||
|
||||
public:
|
||||
virtual Int TypeVersion() { return 0; }
|
||||
virtual bool CanDeserializeIntoExistingObject() { return 0; }
|
||||
virtual bool CanDeserializeIntoExistingObject() { return false; }
|
||||
virtual void Initialize(sptr<ContentTypeReaderManager>& manager) {}
|
||||
|
||||
constexpr String TargetType() { return _targetType; }
|
||||
sptr<Type> TargetType() { return _targetType; }
|
||||
|
||||
virtual String GetType() { return "ContentTypeReader"; }
|
||||
virtual sptr<Type> GetType() const override {
|
||||
auto type = New<Type>();
|
||||
type->FullName = "xna::ContentTypeReader";
|
||||
type->Namespace = "xna";
|
||||
type->IsClass = true;
|
||||
return type;
|
||||
}
|
||||
|
||||
protected:
|
||||
ContentTypeReader(String targetType) : _targetType(targetType) {
|
||||
ContentTypeReader(sptr<Type> const& targetType) : _targetType(targetType)
|
||||
{
|
||||
}
|
||||
|
||||
virtual sptr<void> Read(ContentReader input, sptr<void> existingInstance) = 0;
|
||||
|
||||
public:
|
||||
bool TargetIsValueType{ false };
|
||||
|
||||
private:
|
||||
String _targetType = "contentTypeReader";
|
||||
sptr<Type> _targetType = nullptr;
|
||||
};
|
||||
|
||||
//ContentTypeReaderActivador
|
||||
//-------------------------------------------------------//
|
||||
// TypeComparator //
|
||||
//-------------------------------------------------------//
|
||||
struct TypeComparator
|
||||
{
|
||||
bool operator()(sptr<Type> t1, sptr<Type> t2) const
|
||||
{
|
||||
return t1->GetHashCode() < t2->GetHashCode();
|
||||
}
|
||||
};
|
||||
|
||||
//-------------------------------------------------------//
|
||||
// ContentTypeReaderActivador //
|
||||
//-------------------------------------------------------//
|
||||
class ContentTypeReaderActivador {
|
||||
public:
|
||||
using Activador = sptr<ContentTypeReader>(*)();
|
||||
|
||||
static sptr<ContentTypeReader> CreateInstance(String const& readerTypeName) {
|
||||
if (!activators.contains(readerTypeName))
|
||||
static sptr<ContentTypeReader> CreateInstance(sptr<Type> const& type, xna_error_nullarg) {
|
||||
if (!type)
|
||||
{
|
||||
xna_error_apply(err, XnaErrorCode::ARGUMENT_IS_NULL);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const auto hash = type->GetHashCode();
|
||||
|
||||
if (!activators.contains(hash))
|
||||
return nullptr;
|
||||
|
||||
auto activador = activators[readerTypeName];
|
||||
auto activador = activators[hash];
|
||||
|
||||
if (!activador) return nullptr;
|
||||
|
||||
return activador();
|
||||
}
|
||||
|
||||
static void SetActivador(String const& readerTypeName, Activador activador) {
|
||||
if (!activators.contains(readerTypeName))
|
||||
activators.insert({ readerTypeName, activador });
|
||||
static void SetActivador(sptr<Type> const& type, Activador activador, xna_error_nullarg) {
|
||||
if (!type) {
|
||||
xna_error_apply(err, XnaErrorCode::ARGUMENT_IS_NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
const auto hash = type->GetHashCode();
|
||||
|
||||
if (!activators.contains(hash))
|
||||
activators.insert({ hash, activador });
|
||||
}
|
||||
|
||||
private:
|
||||
inline static std::map<String, Activador> activators =
|
||||
std::map<String, Activador>();
|
||||
//inline static auto activators = std::map<size_t, Activador, TypeComparator>();
|
||||
inline static auto activators = std::map<size_t, Activador>();
|
||||
|
||||
ContentTypeReaderActivador();
|
||||
ContentTypeReaderActivador(ContentTypeReaderActivador&&);
|
||||
@ -58,55 +102,87 @@ namespace xna {
|
||||
};
|
||||
|
||||
using PContentTypeReader = sptr<ContentTypeReader>;
|
||||
using PType = sptr<Type>;
|
||||
|
||||
//ContentTypeReaderManager
|
||||
//-------------------------------------------------------//
|
||||
// ContentTypeReaderManager //
|
||||
//-------------------------------------------------------//
|
||||
class ContentTypeReaderManager {
|
||||
public:
|
||||
static std::vector<PContentTypeReader> ReadTypeManifest(Int typeCount, sptr<ContentReader>& contentReader, xna_error_nullarg);
|
||||
static sptr<ContentTypeReader> GetTypeReader(String const& targetType, sptr<ContentReader>& contentReader, xna_error_nullarg);
|
||||
static sptr<ContentTypeReader> GetTypeReader(sptr<Type> const& targetType, sptr<ContentReader>& contentReader, xna_error_nullarg);
|
||||
|
||||
inline sptr<ContentTypeReader> GetTypeReader(String const& targetType, xna_error_nullarg) {
|
||||
inline sptr<ContentTypeReader> GetTypeReader(sptr<Type> const& targetType, xna_error_nullarg) {
|
||||
return ContentTypeReaderManager::GetTypeReader(targetType, this->contentReader, err);
|
||||
}
|
||||
|
||||
inline static bool ContainsTypeReader(String const& targetType) {
|
||||
inline static bool ContainsTypeReader(sptr<Type> const& targetType) {
|
||||
return ContentTypeReaderManager::targetTypeToReader.contains(targetType);
|
||||
}
|
||||
|
||||
private:
|
||||
ContentTypeReaderManager(sptr<ContentReader>& contentReader);
|
||||
static sptr<ContentTypeReader> GetTypeReader(String const& readerTypeName, sptr<ContentReader>& contentReader, std::vector<PContentTypeReader>& newTypeReaders, xna_error_nullarg);
|
||||
static bool InstantiateTypeReader(String const& readerTypeName, sptr<ContentReader>& contentReader, sptr<ContentTypeReader>& reader);
|
||||
static bool InstantiateTypeReader(String const& readerTypeName, sptr<ContentReader>& contentReader, sptr<ContentTypeReader>& reader, xna_error_nullarg);
|
||||
static void AddTypeReader(String const& readerTypeName, sptr<ContentReader>& contentReader, sptr<ContentTypeReader>& reader, xna_error_nullarg);
|
||||
static void RollbackAddReaders(std::vector<sptr<ContentTypeReader>>& newTypeReaders);
|
||||
static void RollbackAddReader(std::map<String, sptr<ContentTypeReader>>& dictionary, sptr<ContentTypeReader>& reader);
|
||||
static void RollbackAddReaders(std::vector<sptr<ContentTypeReader>>& newTypeReaders);
|
||||
|
||||
static void RollbackAddReader(std::map<String, PContentTypeReader>& dictionary, sptr<ContentTypeReader>& reader) {
|
||||
std::map<String, sptr<ContentTypeReader>>::iterator it;
|
||||
|
||||
for (it = dictionary.begin(); it != dictionary.end(); it++) {
|
||||
if (it->second == reader) {
|
||||
dictionary.erase(it->first);
|
||||
it = dictionary.begin();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void RollbackAddReader(std::map<PType, PContentTypeReader>& dictionary, sptr<ContentTypeReader>& reader) {
|
||||
std::map<PType, sptr<ContentTypeReader>>::iterator it;
|
||||
|
||||
for (it = dictionary.begin(); it != dictionary.end(); it++) {
|
||||
if (it->second == reader) {
|
||||
dictionary.erase(it->first);
|
||||
it = dictionary.begin();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
sptr<ContentReader> contentReader = nullptr;
|
||||
|
||||
inline static std::map<String, PContentTypeReader> nameToReader = std::map<String, PContentTypeReader>();
|
||||
inline static std::map<String, PContentTypeReader> targetTypeToReader = std::map<String, PContentTypeReader>();
|
||||
inline static std::map<String, PContentTypeReader> readerTypeToReader = std::map<String, PContentTypeReader>();
|
||||
inline static auto nameToReader = std::map<String, PContentTypeReader>();
|
||||
//inline static auto targetTypeToReader = std::map<PType, PContentTypeReader, TypeComparator>();
|
||||
//inline static auto readerTypeToReader = std::map<PType, PContentTypeReader, TypeComparator>();
|
||||
inline static auto targetTypeToReader = std::map<PType, PContentTypeReader>();
|
||||
inline static auto readerTypeToReader = std::map<PType, PContentTypeReader>();
|
||||
|
||||
static void initMaps();
|
||||
};
|
||||
|
||||
//ObjectReader
|
||||
//-------------------------------------------------------//
|
||||
// ObjectReader //
|
||||
//-------------------------------------------------------//
|
||||
class ObjectReader : public ContentTypeReader {
|
||||
public:
|
||||
ObjectReader() : ContentTypeReader("object"){
|
||||
ContentTypeReaderActivador::SetActivador("object", []() -> sptr<ContentTypeReader> {
|
||||
ObjectReader() : ContentTypeReader(typeof(this)){
|
||||
ContentTypeReaderActivador::SetActivador(typeof(this), []() -> sptr<ContentTypeReader> {
|
||||
auto obj = New <ObjectReader>();
|
||||
return reinterpret_pointer_cast<ContentTypeReader>(obj);
|
||||
});
|
||||
}
|
||||
|
||||
// Inherited via ContentTypeReader
|
||||
sptr<void> Read(ContentReader input, sptr<void> existingInstance) override;
|
||||
sptr<void> Read(ContentReader input, sptr<void> existingInstance) override;
|
||||
|
||||
String GetType() override {
|
||||
return "ObjectReader";
|
||||
sptr<Type> GetType() const override{
|
||||
auto type = New<Type>();
|
||||
type->FullName = "xna::ObjectReader";
|
||||
type->Namespace = "xna";
|
||||
type->IsClass = true;
|
||||
return type;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -43,6 +43,7 @@ namespace xna {
|
||||
|
||||
bool m2BytesPerChar{ false };
|
||||
|
||||
protected:
|
||||
Int InternalReadOneChar(xna_error_nullarg);
|
||||
|
||||
void FillBuffer(Int numBytes, xna_error_nullarg);
|
||||
|
@ -2,12 +2,20 @@
|
||||
#include "type.hpp"
|
||||
|
||||
namespace xna {
|
||||
sptr<Type> Object::GetType()
|
||||
sptr<Type> Object::GetType() const
|
||||
{
|
||||
auto type = New<Type>();
|
||||
type->FullName = "Object";
|
||||
type->FullName = "xna::Object";
|
||||
type->Namespace = "xna";
|
||||
type->IsClass = true;
|
||||
return type;
|
||||
}
|
||||
|
||||
size_t Object::GetHashCode() const
|
||||
{
|
||||
size_t seed = 0;
|
||||
XnaHHashCombine(seed, this);
|
||||
|
||||
return seed;
|
||||
}
|
||||
}
|
@ -6,7 +6,8 @@
|
||||
namespace xna {
|
||||
class Object {
|
||||
public:
|
||||
virtual sptr<Type> GetType();
|
||||
virtual sptr<Type> GetType() const;
|
||||
virtual size_t GetHashCode() const;
|
||||
};
|
||||
}
|
||||
|
||||
|
28
framework/csharp/type.cpp
Normal file
28
framework/csharp/type.cpp
Normal file
@ -0,0 +1,28 @@
|
||||
#include "type.hpp"
|
||||
|
||||
namespace xna {
|
||||
sptr<Type> Type::GetType() const
|
||||
{
|
||||
auto type = New<Type>();
|
||||
type->FullName = "xna::Type";
|
||||
type->Namespace = "xna";
|
||||
type->IsClass = true;
|
||||
return type;
|
||||
}
|
||||
|
||||
size_t Type::GetHashCode() const
|
||||
{
|
||||
size_t seed = 0;
|
||||
XnaHHashCombine(seed, Namespace);
|
||||
XnaHHashCombine(seed, FullName);
|
||||
XnaHHashCombine(seed, IsInterface);
|
||||
XnaHHashCombine(seed, IsArray);
|
||||
XnaHHashCombine(seed, IsPointer);
|
||||
XnaHHashCombine(seed, IsClass);
|
||||
XnaHHashCombine(seed, IsCOMObject);
|
||||
XnaHHashCombine(seed, IsEnum);
|
||||
XnaHHashCombine(seed, IsValueType);
|
||||
|
||||
return seed;
|
||||
}
|
||||
}
|
@ -5,7 +5,7 @@
|
||||
#include "object.hpp"
|
||||
|
||||
namespace xna {
|
||||
class Type {
|
||||
class Type : public Object {
|
||||
public:
|
||||
String Namespace;
|
||||
String FullName;
|
||||
@ -16,13 +16,43 @@ namespace xna {
|
||||
bool IsCOMObject{ false };
|
||||
bool IsEnum{ false };
|
||||
bool IsValueType{ false };
|
||||
};
|
||||
|
||||
constexpr bool operator==(const Type& other) const
|
||||
{
|
||||
return Namespace == other.Namespace
|
||||
&& FullName == other.FullName
|
||||
&& IsInterface == other.IsInterface
|
||||
&& IsArray == other.IsArray
|
||||
&& IsPointer == other.IsPointer
|
||||
&& IsClass == other.IsClass
|
||||
&& IsCOMObject == other.IsCOMObject
|
||||
&& IsEnum == other.IsEnum
|
||||
&& IsValueType == other.IsValueType;
|
||||
}
|
||||
|
||||
virtual sptr<Type> GetType() const override;
|
||||
virtual size_t GetHashCode() const;
|
||||
|
||||
bool operator()(Type const& t1, Type const& t2) const {
|
||||
return t1.GetHashCode() < t2.GetHashCode();
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
inline sptr<Type> typeof(T const& obj) {
|
||||
auto obj = reinterpret_cast<Object*>(&obj);
|
||||
inline sptr<Type> typeof() {
|
||||
auto t = New<T>();
|
||||
auto obj = reinterpret_pointer_cast<Object>(t);
|
||||
|
||||
if (!obj)
|
||||
if (!obj) return nullptr;
|
||||
|
||||
return obj->GetType();
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline sptr<Type> typeof(T const* object) {
|
||||
auto obj = reinterpret_cast<const Object*>(object);
|
||||
|
||||
if (!obj)
|
||||
return nullptr;
|
||||
|
||||
return obj->GetType();
|
||||
|
@ -2,6 +2,7 @@
|
||||
#define XNA_HELPERS_HPP
|
||||
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
namespace xna {
|
||||
inline std::wstring XnaHToWString(const std::string& str)
|
||||
@ -21,6 +22,12 @@ namespace xna {
|
||||
wcstombs_s(&size, &str[0], str.size() + 1, wstr.c_str(), wstr.size());
|
||||
return str;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
static constexpr void XnaHHashCombine(std::size_t& seed, const T& v) {
|
||||
std::hash<T> hasher;
|
||||
seed ^= hasher(v) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
@ -23,7 +23,7 @@ namespace xna {
|
||||
}
|
||||
|
||||
inline bool xna_error_haserros(XnaErrorCode* source) {
|
||||
return source != nullptr;
|
||||
return source != nullptr && *source != XnaErrorCode::NONE;
|
||||
}
|
||||
|
||||
#define xna_error_nullarg XnaErrorCode* err = nullptr
|
||||
|
Loading…
x
Reference in New Issue
Block a user