libikarus/src/ikarus/objects/util.hpp
Folling 5dce2ced94
add src/ikarus subdir and make names unique for objects per scope
Signed-off-by: Folling <mail@folling.io>
2025-01-01 14:07:47 +01:00

125 lines
4.9 KiB
C++

#pragma once
#include <string_view>
#include <cppbase/strings.hpp>
#include <ikarus/errors.h>
#include <ikarus/errors.hpp>
#include <ikarus/objects/blueprint.hpp>
#include <ikarus/objects/entity.hpp>
#include <ikarus/objects/object.hpp>
#include <ikarus/objects/properties/property.h>
#include <ikarus/objects/properties/property.hpp>
#include <ikarus/objects/properties/property_scope.hpp>
#include <ikarus/persistence/project.hpp>
namespace ikarus::util {
template<typename O>
[[nodiscard]] IkarusProject * object_get_project(O const * object, IkarusErrorData * error_out) {
IKARUS_FAIL_IF_NULL(object, nullptr);
IKARUS_FAIL_IF_OBJECT_MISSING(object, nullptr);
return object->project;
}
template<typename O>
[[nodiscard]] char const * object_get_name(O const * object, IkarusErrorData * error_out) {
IKARUS_FAIL_IF_NULL(object, nullptr);
IKARUS_FAIL_IF_OBJECT_MISSING(object, nullptr);
IKARUS_VTRYRV_OR_FAIL(
auto const ret,
nullptr,
fmt::runtime(fmt::format("unable to fetch {} name: {{}}", ikarus_object_type_to_string(ikarus_id_get_object_type(object->id)))),
IkarusErrorInfo_Database_QueryFailed,
object->project->db
->template query_one<std::string>(fmt::format("SELECT `name` FROM `{}` WHERE `id` = ?", object->get_table_name()), object->id)
);
return strdup(ret.data());
}
[[nodiscard]] inline bool name_is_unique(
IkarusProject const * project,
std::string_view name,
[[maybe_unused]] IkarusBlueprint const * blueprint,
IkarusErrorData * error_out
) {
IKARUS_VTRYRV_OR_FAIL(
bool const exists,
false,
"unable to check if blueprint name is unique",
IkarusErrorInfo_Database_QueryFailed,
project->db->query_one<bool>("SELECT EXISTS(SELECT 1 FROM `blueprints` WHERE `name` = ?)", name)
);
return exists;
}
[[nodiscard]] inline bool name_is_unique(
IkarusProject const * project,
std::string_view name,
[[maybe_unused]] IkarusEntity const * entity,
IkarusErrorData * error_out
) {
IKARUS_VTRYRV_OR_FAIL(
bool const exists,
false,
"unable to check if entity name is unique",
IkarusErrorInfo_Database_QueryFailed,
project->db->query_one<bool>("SELECT EXISTS(SELECT 1 FROM `entities` WHERE `name` = ?)", name)
);
return exists;
}
[[nodiscard]] inline bool
name_is_unique(IkarusProject const * project, std::string_view name, IkarusPropertyScope const * scope, IkarusErrorData * error_out) {
IKARUS_VTRYRV_OR_FAIL(
bool const exists,
false,
"unable to check if property name is unique",
IkarusErrorInfo_Database_QueryFailed,
project->db->query_one<bool>("SELECT EXISTS(SELECT 1 FROM `properties` WHERE `name` = ? AND `scope` = ?)", name, scope->get_id())
);
return exists;
}
[[nodiscard]] inline bool
name_is_unique(IkarusProject * project, std::string_view name, IkarusProperty const * property, IkarusErrorData * error_out) {
std::unique_ptr<IkarusPropertyScope const> scope{ikarus_property_get_scope(property, error_out)};
IKARUS_FAIL_IF_ERROR(false);
return name_is_unique(project, name, scope.get(), error_out);
}
#define IKARUS_FAIL_IF_NAME_INVALID(name, project, object, ret, ...) \
IKARUS_FAIL_IF_NULL(name, ret); \
IKARUS_FAIL_IF(cppbase::is_empty_or_blank(name), ret, "name must not be empty", IkarusErrorInfo_Client_InvalidInput); \
IKARUS_FAIL_IF( \
!ikarus::util::name_is_unique(project, name, object, error_out), \
ret, \
"name must be unique", \
IkarusErrorInfo_Client_InvalidInput \
); \
IKARUS_FAIL_IF_ERROR(ret);
template<typename O>
void object_set_name(O * object, char const * name, IkarusErrorData * error_out) {
IKARUS_FAIL_IF_NULL(object, );
IKARUS_FAIL_IF_OBJECT_MISSING(object, );
IKARUS_FAIL_IF_NULL(name, );
IKARUS_FAIL_IF_NAME_INVALID(name, object->project, object, );
IKARUS_TRYRV_OR_FAIL(
,
fmt::runtime(fmt::format("unable to set {} name: {{}}", ikarus_object_type_to_string(ikarus_id_get_object_type(object->id)))),
IkarusErrorInfo_Database_QueryFailed,
object->project->db->execute(fmt::format("UPDATE `{}` SET `name` = ? WHERE `id` = ?", object->get_table_name()), name, object->id)
);
}
} // namespace ikarus::util