#pragma once #include #include #include void safe_strcpy( std::string_view const src, char * dest, size_t const dest_size ); #define IKARUS_VOID_RETURN #define IKARUS_SET_ERROR(msg, err_info) \ if (error_out != nullptr) { \ safe_strcpy( \ msg, \ static_cast(error_out->message), \ IKARUS_ERROR_DATA_MAX_MESSAGE_LIMIT \ ); \ error_out->info = err_info; \ } #define IKARUS_FAIL(ret, msg, err_info) \ IKARUS_SET_ERROR(msg, err_info); \ return ret #define IKARUS_FAIL_IF(condition, ret, msg, err_info) \ if (condition) { \ IKARUS_SET_ERROR(msg, err_info) \ return ret; \ } #define IKARUS_TRY_OR_FAIL_IMPL(var_name, msg, err_info, ...) \ auto var_name = __VA_ARGS__; \ if (var_name.is_error()) { \ IKARUS_SET_ERROR( \ fmt::format( \ fmt::runtime(msg), \ std::move(var_name).unwrap_error() \ ), \ err_info \ ); \ return var_name; \ } #define IKARUS_TRY_OR_FAIL(msg, err_info, ...) \ IKARUS_TRY_OR_FAIL_IMPL( \ CPPBASE_UNIQUE_NAME(result), \ msg, \ err_info, \ __VA_ARGS__ \ ); #define IKARUS_TRYRV_OR_FAIL_IMPL(var_name, ret, msg, err_info, ...) \ auto var_name = __VA_ARGS__; \ if (var_name.is_error()) { \ IKARUS_SET_ERROR( \ fmt::format( \ fmt::runtime(msg), \ std::move(var_name).unwrap_error() \ ), \ err_info \ ); \ return ret; \ } #define IKARUS_TRYRV_OR_FAIL(ret, msg, err_info, ...) \ IKARUS_TRYRV_OR_FAIL_IMPL( \ CPPBASE_UNIQUE_NAME(result), \ ret, \ msg, \ err_info, \ __VA_ARGS__ \ ); #define IKARUS_VTRY_OR_FAIL_IMPL(var_name, value, msg, err_info, ...) \ auto var_name = __VA_ARGS__; \ if (var_name.is_error()) { \ IKARUS_SET_ERROR( \ fmt::format( \ fmt::runtime(msg), \ std::move(var_name).unwrap_error() \ ), \ err_info \ ); \ return var_name; \ } \ value = std::move(var_name).unwrap_value() #define IKARUS_VTRY_OR_FAIL(value, msg, err_info, ...) \ IKARUS_VTRY_OR_FAIL_IMPL( \ CPPBASE_UNIQUE_NAME(result), \ value, \ msg, \ err_info, \ __VA_ARGS__ \ ); #define IKARUS_VTRYRV_OR_FAIL_IMPL(var_name, value, ret, msg, err_info, ...) \ auto var_name = __VA_ARGS__; \ if (var_name.is_error()) { \ IKARUS_SET_ERROR( \ fmt::format(fmt::runtime(msg), var_name.unwrap_error()), \ err_info \ ); \ return ret; \ } \ value = std::move(var_name).unwrap_value() #define IKARUS_VTRYRV_OR_FAIL(value, ret, msg, err_info, ...) \ IKARUS_VTRYRV_OR_FAIL_IMPL( \ CPPBASE_UNIQUE_NAME(result), \ value, \ ret, \ msg, \ err_info, \ __VA_ARGS__ \ ); #define IKARUS_FAIL_IF_ERROR(ret) \ if (ikarus_error_data_is_error(error_out)) { \ return ret; \ } #define IKARUS_FAIL_IF_NULL(ptr, ret) \ IKARUS_FAIL_IF( \ ((ptr) == nullptr), \ ret, \ #ptr " must not be null", \ IkarusErrorInfo_Client_InvalidNull \ ) #define IKARUS_FAIL_IF_NAME_INVALID(name, 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 \ ); #define IKARUS_FAIL_IF_NOT_EXIST_IMPL(exists_name, object, ret) \ IKARUS_VTRYRV_OR_FAIL( \ auto exists_name, \ ret, \ fmt::format( \ "failed to check if {} exists", \ std::remove_cvref_t::object_name \ ), \ IkarusErrorInfo_Database_QueryFailed, \ object->project->db->query_one( \ fmt::format( \ "SELECT EXISTS(SELECT 1 FROM `{}` WHERE `id` = ?)", \ std::remove_cvref_t::table_name \ ), \ object->id \ ) \ ); \ \ IKARUS_FAIL_IF( \ !exists_name, \ ret, \ fmt::format( \ "{} doesn't exist", \ std::remove_cvref_t::object_name \ ), \ IkarusErrorInfo_Client_NonExistent \ ) #define IKARUS_FAIL_IF_NOT_EXIST(object, ret) \ IKARUS_FAIL_IF_NOT_EXIST_IMPL(CPPBASE_UNIQUE_NAME(exists), object, ret)