feat(instance): utility functions for casting/types
This commit is contained in:
parent
1617086692
commit
be3c7bd6b2
4 changed files with 50 additions and 16 deletions
|
@ -25,4 +25,9 @@ class MemberNotFound : public Error {
|
||||||
class AssignToReadOnlyMember : public Error {
|
class AssignToReadOnlyMember : public Error {
|
||||||
public:
|
public:
|
||||||
inline AssignToReadOnlyMember(std::string className, std::string memberName) : Error("AssignToReadOnlyMember", "Attempt to assign value to read-only member '" + memberName + "' in class " + className) {}
|
inline AssignToReadOnlyMember(std::string className, std::string memberName) : Error("AssignToReadOnlyMember", "Attempt to assign value to read-only member '" + memberName + "' in class " + className) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
class InstanceCastError : public Error {
|
||||||
|
public:
|
||||||
|
inline InstanceCastError(std::string sourceClass, std::string targetClass) : Error("InstanceCastError", "Attempt to cast object of type " + sourceClass + " to incompatible type " + targetClass) {}
|
||||||
};
|
};
|
|
@ -100,6 +100,15 @@ public:
|
||||||
// Returning a list of property names feels kinda janky. Is this really the way to go?
|
// Returning a list of property names feels kinda janky. Is this really the way to go?
|
||||||
std::vector<std::string> GetProperties();
|
std::vector<std::string> GetProperties();
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
result<std::shared_ptr<T>, InstanceCastError> CastTo() {
|
||||||
|
// TODO: Too lazy to implement a manual check
|
||||||
|
std::shared_ptr<T> result = std::dynamic_pointer_cast<T>(shared_from_this());
|
||||||
|
if (result != nullptr)
|
||||||
|
return InstanceCastError(GetClass()->className, T::TYPE.className);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
// Serialization
|
// Serialization
|
||||||
void Serialize(pugi::xml_node parent);
|
void Serialize(pugi::xml_node parent);
|
||||||
static result<std::shared_ptr<Instance>, NoSuchInstance> Deserialize(pugi::xml_node node);
|
static result<std::shared_ptr<Instance>, NoSuchInstance> Deserialize(pugi::xml_node node);
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <optional>
|
||||||
|
|
||||||
const InstanceType DataModel::TYPE = {
|
const InstanceType DataModel::TYPE = {
|
||||||
.super = &Instance::TYPE,
|
.super = &Instance::TYPE,
|
||||||
|
@ -120,4 +121,28 @@ std::shared_ptr<DataModel> DataModel::LoadFromFile(std::string path) {
|
||||||
newModel->Init();
|
newModel->Init();
|
||||||
|
|
||||||
return newModel;
|
return newModel;
|
||||||
|
}
|
||||||
|
|
||||||
|
result<std::shared_ptr<Service>, NoSuchService> DataModel::GetService(std::string className) {
|
||||||
|
if (services.count(className) != 0)
|
||||||
|
return std::dynamic_pointer_cast<Service>(services[className]);
|
||||||
|
|
||||||
|
if (!INSTANCE_MAP[className] || (INSTANCE_MAP[className]->flags ^ (INSTANCE_NOTCREATABLE | INSTANCE_SERVICE)) != 0) {
|
||||||
|
return NoSuchService(className);
|
||||||
|
}
|
||||||
|
|
||||||
|
services[className] = std::dynamic_pointer_cast<Service>(INSTANCE_MAP[className]->constructor());
|
||||||
|
AddChild(std::dynamic_pointer_cast<Instance>(services[className]));
|
||||||
|
|
||||||
|
return std::dynamic_pointer_cast<Service>(services[className]);
|
||||||
|
}
|
||||||
|
|
||||||
|
result<std::optional<std::shared_ptr<Service>>, NoSuchService> DataModel::FindService(std::string className) {
|
||||||
|
if (!INSTANCE_MAP[className] || (INSTANCE_MAP[className]->flags ^ (INSTANCE_NOTCREATABLE | INSTANCE_SERVICE)) != 0) {
|
||||||
|
return NoSuchService(className);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (services.count(className) != 0)
|
||||||
|
return std::make_optional(std::dynamic_pointer_cast<Service>(services[className]));
|
||||||
|
return (std::optional<std::shared_ptr<Service>>)std::nullopt;
|
||||||
}
|
}
|
|
@ -1,5 +1,6 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "error/instance.h"
|
||||||
#include "error/result.h"
|
#include "error/result.h"
|
||||||
#include "logger.h"
|
#include "logger.h"
|
||||||
#include "objects/base/instance.h"
|
#include "objects/base/instance.h"
|
||||||
|
@ -46,27 +47,21 @@ public:
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
result<std::shared_ptr<Service>, NoSuchService> GetService(std::string className);
|
||||||
|
result<std::optional<std::shared_ptr<Service>>, NoSuchService> FindService(std::string className);
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
result<std::shared_ptr<T>, NoSuchService> GetService(std::string name) {
|
result<std::shared_ptr<T>, NoSuchService> GetService() {
|
||||||
if (services.count(name) != 0)
|
auto result = GetService(T::TYPE.className);
|
||||||
return std::dynamic_pointer_cast<T>(services[name]);
|
if (result.isError()) return result.error().value();
|
||||||
|
return std::dynamic_pointer_cast<T>(result.success().value());
|
||||||
// TODO: Replace this with a result return type
|
|
||||||
if (!INSTANCE_MAP[name] || (INSTANCE_MAP[name]->flags ^ (INSTANCE_NOTCREATABLE | INSTANCE_SERVICE)) != 0) {
|
|
||||||
return NoSuchService(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
services[name] = std::dynamic_pointer_cast<Service>(INSTANCE_MAP[name]->constructor());
|
|
||||||
AddChild(std::dynamic_pointer_cast<Instance>(services[name]));
|
|
||||||
|
|
||||||
return std::dynamic_pointer_cast<T>(services[name]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
std::optional<std::shared_ptr<T>> FindService() {
|
std::optional<std::shared_ptr<T>> FindService() {
|
||||||
if (services.count(name) != 0)
|
auto result = FindService(T::TYPE.className);
|
||||||
return std::dynamic_pointer_cast<T>(services[name]);
|
if (result.isError()) return result.error().value();
|
||||||
return std::nullopt;
|
return std::dynamic_pointer_cast<T>(result.success().value());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Saving/loading
|
// Saving/loading
|
||||||
|
|
Loading…
Add table
Reference in a new issue