1
0
mirror of https://github.com/borgesdan/xn65 synced 2024-12-29 21:54:47 +01:00

Implementa ContentTypeReaderManager

This commit is contained in:
Danilo 2024-05-02 10:52:08 -03:00
parent efab931113
commit 956c9e6ebf
11 changed files with 228 additions and 65 deletions

View File

@ -39,7 +39,7 @@ add_executable (xna WIN32
"content/manager.cpp" "content/manager.cpp"
"content/reader.cpp" "content/reader.cpp"
"csharp/binary.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) if (CMAKE_VERSION VERSION_GREATER 3.12)
set_property(TARGET xna PROPERTY CXX_STANDARD 20) set_property(TARGET xna PROPERTY CXX_STANDARD 20)

View File

@ -1,6 +1,7 @@
#include "reader.hpp" #include "reader.hpp"
#include "manager.hpp" #include "manager.hpp"
#include "lzx/decoderstream.hpp" #include "lzx/decoderstream.hpp"
#include "typereadermanager.hpp"
namespace xna { namespace xna {
sptr<ContentReader> ContentReader::Create(ContentManager* contentManager, Stream* input, String const& assetName) sptr<ContentReader> ContentReader::Create(ContentManager* contentManager, Stream* input, String const& assetName)
@ -53,6 +54,6 @@ namespace xna {
} }
Int ContentReader::ReadHeader() { Int ContentReader::ReadHeader() {
return Int(); //typeReaders = ContentTypeReaderManager::ReadTypeManifest(this->Read7BitEncodedInt(), this);
} }
} }

View File

@ -34,10 +34,12 @@ namespace xna {
return contentTypeReaderArray; 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; return nullptr;
}
sptr<ContentTypeReader> typeReader = nullptr; sptr<ContentTypeReader> typeReader = nullptr;
@ -57,10 +59,13 @@ namespace xna {
{ {
sptr<ContentTypeReader> reader = nullptr; 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]; return ContentTypeReaderManager::nameToReader[readerTypeName];
} }
if (xna_error_haserros(err))
return nullptr;
ContentTypeReaderManager::AddTypeReader(readerTypeName, contentReader, reader, err); ContentTypeReaderManager::AddTypeReader(readerTypeName, contentReader, reader, err);
if (xna_error_haserros(err)) return nullptr; if (xna_error_haserros(err)) return nullptr;
@ -70,15 +75,30 @@ namespace xna {
return reader; 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)) { sptr<Type> type = nullptr;
reader = ContentTypeReaderManager::readerTypeToReader[readerTypeName];
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 }); ContentTypeReaderManager::nameToReader.insert({ readerTypeName, reader });
return false; 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) 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::targetTypeToReader, newTypeReader);
ContentTypeReaderManager::RollbackAddReader(ContentTypeReaderManager::readerTypeToReader, 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() void ContentTypeReaderManager::initMaps()
{ {
@ -125,8 +134,10 @@ namespace xna {
auto typeReader = New<ObjectReader>(); auto typeReader = New<ObjectReader>();
auto contentTypeReader = reinterpret_pointer_cast<ContentTypeReader>(typeReader); auto contentTypeReader = reinterpret_pointer_cast<ContentTypeReader>(typeReader);
targetTypeToReader.insert({ typeReader->TargetType(), contentTypeReader}); //targetTypeToReader.insert({ typeReader->TargetType(), contentTypeReader});
readerTypeToReader.insert({ typeReader->GetType(), contentTypeReader}); //readerTypeToReader.insert({ typeReader->GetType(), contentTypeReader});
targetTypeToReader.insert({ typeof<Object>(), contentTypeReader});
readerTypeToReader.insert({ typeof<ObjectReader>(), contentTypeReader});
} }
} }

View File

@ -1,56 +1,100 @@
#ifndef XNA_CONTENT_TYPEREADER_HPP #ifndef XNA_CONTENT_TYPEREADER_HPP
#define XNA_CONTENT_TYPEREADER_HPP #define XNA_CONTENT_TYPEREADER_HPP
#include "../csharp/type.hpp"
#include "../default.hpp" #include "../default.hpp"
#include <map>
#include <algorithm> #include <algorithm>
#include <map>
namespace xna { namespace xna {
//ContentTypeReader //-------------------------------------------------------//
class ContentTypeReader { // ContentTypeReader //
//-------------------------------------------------------//
class ContentTypeReader : public Object {
public:
ContentTypeReader(){}
public: public:
virtual Int TypeVersion() { return 0; } virtual Int TypeVersion() { return 0; }
virtual bool CanDeserializeIntoExistingObject() { return 0; } virtual bool CanDeserializeIntoExistingObject() { return false; }
virtual void Initialize(sptr<ContentTypeReaderManager>& manager) {} 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: protected:
ContentTypeReader(String targetType) : _targetType(targetType) { ContentTypeReader(sptr<Type> const& targetType) : _targetType(targetType)
{
} }
virtual sptr<void> Read(ContentReader input, sptr<void> existingInstance) = 0; virtual sptr<void> Read(ContentReader input, sptr<void> existingInstance) = 0;
public:
bool TargetIsValueType{ false };
private: 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 { class ContentTypeReaderActivador {
public: public:
using Activador = sptr<ContentTypeReader>(*)(); using Activador = sptr<ContentTypeReader>(*)();
static sptr<ContentTypeReader> CreateInstance(String const& readerTypeName) { static sptr<ContentTypeReader> CreateInstance(sptr<Type> const& type, xna_error_nullarg) {
if (!activators.contains(readerTypeName)) if (!type)
{
xna_error_apply(err, XnaErrorCode::ARGUMENT_IS_NULL);
return nullptr;
}
const auto hash = type->GetHashCode();
if (!activators.contains(hash))
return nullptr; return nullptr;
auto activador = activators[readerTypeName]; auto activador = activators[hash];
if (!activador) return nullptr; if (!activador) return nullptr;
return activador(); return activador();
} }
static void SetActivador(String const& readerTypeName, Activador activador) { static void SetActivador(sptr<Type> const& type, Activador activador, xna_error_nullarg) {
if (!activators.contains(readerTypeName)) if (!type) {
activators.insert({ readerTypeName, activador }); xna_error_apply(err, XnaErrorCode::ARGUMENT_IS_NULL);
return;
}
const auto hash = type->GetHashCode();
if (!activators.contains(hash))
activators.insert({ hash, activador });
} }
private: private:
inline static std::map<String, Activador> activators = //inline static auto activators = std::map<size_t, Activador, TypeComparator>();
std::map<String, Activador>(); inline static auto activators = std::map<size_t, Activador>();
ContentTypeReaderActivador(); ContentTypeReaderActivador();
ContentTypeReaderActivador(ContentTypeReaderActivador&&); ContentTypeReaderActivador(ContentTypeReaderActivador&&);
@ -58,55 +102,87 @@ namespace xna {
}; };
using PContentTypeReader = sptr<ContentTypeReader>; using PContentTypeReader = sptr<ContentTypeReader>;
using PType = sptr<Type>;
//ContentTypeReaderManager //-------------------------------------------------------//
// ContentTypeReaderManager //
//-------------------------------------------------------//
class ContentTypeReaderManager { class ContentTypeReaderManager {
public: public:
static std::vector<PContentTypeReader> ReadTypeManifest(Int typeCount, sptr<ContentReader>& contentReader, xna_error_nullarg); 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); 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); return ContentTypeReaderManager::targetTypeToReader.contains(targetType);
} }
private: private:
ContentTypeReaderManager(sptr<ContentReader>& contentReader); ContentTypeReaderManager(sptr<ContentReader>& contentReader);
static sptr<ContentTypeReader> GetTypeReader(String const& readerTypeName, sptr<ContentReader>& contentReader, std::vector<PContentTypeReader>& newTypeReaders, xna_error_nullarg); 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 AddTypeReader(String const& readerTypeName, sptr<ContentReader>& contentReader, sptr<ContentTypeReader>& reader, xna_error_nullarg);
static void RollbackAddReaders(std::vector<sptr<ContentTypeReader>>& newTypeReaders); static void RollbackAddReaders(std::vector<sptr<ContentTypeReader>>& newTypeReaders);
static void RollbackAddReader(std::map<String, sptr<ContentTypeReader>>& dictionary, sptr<ContentTypeReader>& reader);
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: private:
sptr<ContentReader> contentReader = nullptr; sptr<ContentReader> contentReader = nullptr;
inline static std::map<String, PContentTypeReader> nameToReader = std::map<String, PContentTypeReader>(); inline static auto nameToReader = std::map<String, PContentTypeReader>();
inline static std::map<String, PContentTypeReader> targetTypeToReader = std::map<String, PContentTypeReader>(); //inline static auto targetTypeToReader = std::map<PType, PContentTypeReader, TypeComparator>();
inline static std::map<String, PContentTypeReader> readerTypeToReader = std::map<String, PContentTypeReader>(); //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(); static void initMaps();
}; };
//ObjectReader //-------------------------------------------------------//
// ObjectReader //
//-------------------------------------------------------//
class ObjectReader : public ContentTypeReader { class ObjectReader : public ContentTypeReader {
public: public:
ObjectReader() : ContentTypeReader("object"){ ObjectReader() : ContentTypeReader(typeof(this)){
ContentTypeReaderActivador::SetActivador("object", []() -> sptr<ContentTypeReader> { ContentTypeReaderActivador::SetActivador(typeof(this), []() -> sptr<ContentTypeReader> {
auto obj = New <ObjectReader>(); auto obj = New <ObjectReader>();
return reinterpret_pointer_cast<ContentTypeReader>(obj); return reinterpret_pointer_cast<ContentTypeReader>(obj);
}); });
} }
// Inherited via ContentTypeReader // Inherited via ContentTypeReader
sptr<void> Read(ContentReader input, sptr<void> existingInstance) override; sptr<void> Read(ContentReader input, sptr<void> existingInstance) override;
String GetType() override { sptr<Type> GetType() const override{
return "ObjectReader"; auto type = New<Type>();
type->FullName = "xna::ObjectReader";
type->Namespace = "xna";
type->IsClass = true;
return type;
} }
}; };
} }

View File

@ -43,6 +43,7 @@ namespace xna {
bool m2BytesPerChar{ false }; bool m2BytesPerChar{ false };
protected:
Int InternalReadOneChar(xna_error_nullarg); Int InternalReadOneChar(xna_error_nullarg);
void FillBuffer(Int numBytes, xna_error_nullarg); void FillBuffer(Int numBytes, xna_error_nullarg);

View File

@ -2,12 +2,20 @@
#include "type.hpp" #include "type.hpp"
namespace xna { namespace xna {
sptr<Type> Object::GetType() sptr<Type> Object::GetType() const
{ {
auto type = New<Type>(); auto type = New<Type>();
type->FullName = "Object"; type->FullName = "xna::Object";
type->Namespace = "xna"; type->Namespace = "xna";
type->IsClass = true; type->IsClass = true;
return type; return type;
} }
size_t Object::GetHashCode() const
{
size_t seed = 0;
XnaHHashCombine(seed, this);
return seed;
}
} }

View File

@ -6,7 +6,8 @@
namespace xna { namespace xna {
class Object { class Object {
public: public:
virtual sptr<Type> GetType(); virtual sptr<Type> GetType() const;
virtual size_t GetHashCode() const;
}; };
} }

28
framework/csharp/type.cpp Normal file
View 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;
}
}

View File

@ -5,7 +5,7 @@
#include "object.hpp" #include "object.hpp"
namespace xna { namespace xna {
class Type { class Type : public Object {
public: public:
String Namespace; String Namespace;
String FullName; String FullName;
@ -16,13 +16,43 @@ namespace xna {
bool IsCOMObject{ false }; bool IsCOMObject{ false };
bool IsEnum{ false }; bool IsEnum{ false };
bool IsValueType{ 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> template <class T>
inline sptr<Type> typeof(T const& obj) { inline sptr<Type> typeof() {
auto obj = reinterpret_cast<Object*>(&obj); 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 nullptr;
return obj->GetType(); return obj->GetType();

View File

@ -2,6 +2,7 @@
#define XNA_HELPERS_HPP #define XNA_HELPERS_HPP
#include <string> #include <string>
#include <utility>
namespace xna { namespace xna {
inline std::wstring XnaHToWString(const std::string& str) 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()); wcstombs_s(&size, &str[0], str.size() + 1, wstr.c_str(), wstr.size());
return str; 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 #endif

View File

@ -23,7 +23,7 @@ namespace xna {
} }
inline bool xna_error_haserros(XnaErrorCode* source) { inline bool xna_error_haserros(XnaErrorCode* source) {
return source != nullptr; return source != nullptr && *source != XnaErrorCode::NONE;
} }
#define xna_error_nullarg XnaErrorCode* err = nullptr #define xna_error_nullarg XnaErrorCode* err = nullptr