libikarus/src/ikarus/objects/properties/util.hpp
Folling dc8b7712b0
add src/ikarus subdir and make names unique for objects per scope
Signed-off-by: Folling <mail@folling.io>
2025-04-15 12:08:06 +02:00

95 lines
3.2 KiB
C++

#pragma once
#include <boost/type_index.hpp>
#include <cppbase/strings.hpp>
#include <ikarus/errors.hpp>
#include <ikarus/objects/properties/property.h>
#include <ikarus/objects/properties/property.hpp>
#include <ikarus/objects/properties/property_scope.hpp>
#include <ikarus/objects/util.hpp>
#include <ikarus/persistence/project.hpp>
#include <ikarus/values/value.hpp>
namespace ikarus::util {
template<typename T>
T * create_property(
struct IkarusProject * project,
char const * name,
struct IkarusPropertyScope * property_scope,
IkarusErrorData * error_out
) {
IKARUS_FAIL_IF_NULL(project, nullptr);
IKARUS_FAIL_IF_NULL(property_scope, nullptr);
IKARUS_FAIL_IF_PROPERTY_SCOPE_INVALID(property_scope, nullptr);
IKARUS_FAIL_IF_NAME_INVALID(name, project, property_scope, nullptr);
IKARUS_VTRYRV_OR_FAIL(
IkarusId const id,
nullptr,
"failed to create property: {}",
IkarusErrorInfo_Database_QueryFailed,
project->db->transact([name, property_scope](auto * db) -> cppbase::Result<IkarusId, sqlitecpp::TransactionError> {
TRY(db->execute("INSERT INTO `objects`(`type`, `name`, `information`) VALUES(?, ?, ?)", IkarusObjectType_Property, name, ""));
auto id = ikarus_id_from_data_and_type(db->last_insert_rowid(), IkarusObjectType_Property);
TRY(db->execute(
"INSERT INTO `properties`(`id`, `type`, `source`) VALUES(?, ?, ?)",
id,
T::PropertyType,
property_scope->get_id()
));
return cppbase::ok(id);
})
);
auto * ret = dynamic_cast<T *>(project->get_property(id, T::PropertyType));
IKARUS_FAIL_IF(
ret == nullptr,
nullptr,
fmt::format("created {} cannot be casted down from IkarusProject", boost::typeindex::type_id<T>().pretty_name()),
IkarusErrorInfo_LibIkarus_InvalidState
);
return ret;
}
template<typename T>
typename T::value_type * get_default_value(IkarusProperty const * property, IkarusErrorData * error_out) {
auto * value = ikarus_property_get_default_value(property, error_out);
IKARUS_FAIL_IF_ERROR(nullptr);
auto * ret = boost::variant2::get_if<typename T::value_type *>(&value->data);
IKARUS_FAIL_IF(
ret == nullptr,
nullptr,
fmt::format(
"{} default value is not a(n) {}",
boost::typeindex::type_id<T>().pretty_name(),
boost::typeindex::type_id<typename T::value_type>().pretty_name()
),
IkarusErrorInfo_Database_InvalidState
);
return *ret;
}
template<typename T>
void set_default_value(T * property, typename T::value_type * new_default_value, IkarusErrorData * error_out) {
IKARUS_FAIL_IF_NULL(property, );
IKARUS_FAIL_IF_OBJECT_MISSING(property, );
IKARUS_FAIL_IF_NULL(new_default_value, );
auto value_json_str = boost::json::serialize(new_default_value->to_json());
IKARUS_TRYRV_OR_FAIL(
,
"unable to set property default value: {}",
IkarusErrorInfo_Database_QueryFailed,
property->project->db->execute("UPDATE `properties` SET `default_value` = ? WHERE `id` = ?", value_json_str, property->id)
);
}
} // namespace ikarus::util