intermediate commit

Signed-off-by: Folling <mail@folling.io>
This commit is contained in:
folling 2023-11-14 16:26:29 +01:00 committed by Folling
parent 52580a4382
commit 2ab0109355
Signed by: folling
SSH key fingerprint: SHA256:S9qEx5WCFFLK49tE/LKnKuJYM5sw+++Dn6qJbbyxnCY
37 changed files with 131 additions and 1544 deletions

View file

@ -1,8 +0,0 @@
#pragma once
#include <ikarus/folders/blueprint_folder.h>
struct IkarusBlueprintFolder {
IkarusId id;
std::string name_buffer;
};

View file

@ -1,8 +0,0 @@
#pragma once
#include <ikarus/folders/entity_folder.h>
struct IkarusEntityFolder {
IkarusId id;
std::string name_buffer;
};

View file

@ -1,13 +0,0 @@
#pragma once
#include <variant>
#include <ikarus/folders/folder.h>
#include <folders/blueprint_folder.hpp>
#include <folders/entity_folder.hpp>
#include <folders/property_folder.hpp>
struct IkarusEntityFolder {
std::variant<IkarusBlueprintFolder, IkarusPropertyFolder, IkarusEntityFolder> data;
};

View file

@ -1,8 +0,0 @@
#pragma once
#include <ikarus/folders/property_folder.h>
struct IkarusPropertyFolder {
IkarusId id;
std::string name_buffer;
};

View file

@ -1,4 +1,4 @@
#include "ikarus/id.h"
#include "id.hpp"
#include <catch2/catch_test_macros.hpp>
@ -15,21 +15,11 @@ auto ikarus_id_is_equal(IkarusId left, IkarusId right) -> bool {
return left == right;
}
auto ikarus_id_is_none(IkarusId id) -> bool {
return ikarus_id_is_equal(id, IKARUS_ID_NONE);
}
auto ikarus_id_is_unspecified(IkarusId id) -> bool {
return ikarus_id_is_equal(id, IKARUS_ID_UNSPECIFIED);
}
TEST_CASE("id_object_type", "[id]") {
// NOLINTNEXTLINE(readability-magic-numbers)
auto id = static_cast<uint64_t>(IkarusObjectType_Blueprint) << IKARUS_ID_OBJECT_RANDOM_BITS;
REQUIRE(ikarus_id_get_object_type(id) == IkarusObjectType_Blueprint);
REQUIRE(!ikarus_id_is_none(id) == IkarusObjectType_Blueprint);
REQUIRE(!ikarus_id_is_unspecified(id) == IkarusObjectType_Blueprint);
}
TEST_CASE("id_equal", "[id]") {
@ -40,17 +30,3 @@ TEST_CASE("id_equal", "[id]") {
REQUIRE(ikarus_id_is_equal(id, copy));
REQUIRE(!ikarus_id_is_equal(id, third));
}
TEST_CASE("id_none", "[id]") {
auto id = IKARUS_ID_NONE;
REQUIRE(ikarus_id_is_none(id));
REQUIRE(!ikarus_id_is_unspecified(id));
}
TEST_CASE("id_unspecified", "[id]") {
auto id = IKARUS_ID_UNSPECIFIED;
REQUIRE(!ikarus_id_is_none(id));
REQUIRE(ikarus_id_is_unspecified(id));
}

View file

@ -1,8 +1,9 @@
#pragma once
#include <ikarus/objects/blueprint.h>
#include <id.hpp>
/// \private
struct IkarusBlueprint {
struct IkarusProject * project;
IkarusId id;
};

View file

@ -1,8 +1,9 @@
#pragma once
#include <ikarus/objects/entity.h>
#include <id.hpp>
/// \private
struct IkarusEntity {
struct IkarusProject * project;
IkarusId id;
};

View file

@ -1,25 +0,0 @@
#include "ikarus/objects/object.h"
#include <catch2/catch_test_macros.hpp>
#include <objects/object.hpp>
IkarusObjectType ikarus_object_get_type(IkarusObject const * object) {
return object->type;
}
TEST_CASE("object_type", "[object]") {
auto types = {
IkarusObjectType_Blueprint,
IkarusObjectType_Property,
IkarusObjectType_Entity,
IkarusObjectType_BlueprintFolder,
IkarusObjectType_PropertyFolder,
IkarusObjectType_EntityFolder,
};
for (auto type : types) {
auto object = IkarusObject{.type = type};
REQUIRE(ikarus_object_get_type(&object) == type);
}
}

View file

@ -2,14 +2,12 @@
#include <variant>
#include <folders/blueprint_folder.hpp>
#include <folders/entity_folder.hpp>
#include <folders/property_folder.hpp>
#include <objects/blueprint.hpp>
#include <objects/entity.hpp>
#include <objects/property.hpp>
struct IkarusObject {
std::variant<IkarusBlueprint, IkarusProperty, IkarusEntity, IkarusBlueprintFolder, IkarusPropertyFolder, IkarusEntityFolder>
data;
union IkarusObject {
IkarusBlueprint blueprint;
IkarusEntity entity;
IkarusProperty property;
};

View file

@ -1,8 +1,9 @@
#pragma once
#include <ikarus/objects/property.h>
#include <id.hpp>
/// \private
struct IkarusProperty {
struct IkarusProject * project;
IkarusId id;
};

View file

@ -0,0 +1,111 @@
CREATE TABLE `objects`
(
`do_not_access_rowid_alias` INTEGER PRIMARY KEY,
`object_type` INT NOT NULL,
`id` INT GENERATED ALWAYS AS (`do_not_access_rowid_alias` | (`object_type` << 56)
) VIRTUAL,
`name` TEXT NOT NULL,
`information` TEXT NOT NULL
) STRICT;
CREATE UNIQUE INDEX `object_id` ON `objects` (`id`);
CREATE INDEX `object_type` ON `objects` (`object_type`);
CREATE
VIRTUAL TABLE `objects_fts` USING fts5
(
`name`,
`information`,
content=
'objects',
content_rowid=
'id',
tokenize=
"unicode61 remove_diacritics 2 tokenchars '-_'"
);
CREATE TABLE `blueprints`
(
`id` INT,
PRIMARY KEY (`id`),
FOREIGN KEY (`id`) REFERENCES `objects` (`id`) ON DELETE CASCADE
) WITHOUT ROWID, STRICT;
CREATE TABLE `entities`
(
`id` INT,
PRIMARY KEY (`id`),
FOREIGN KEY (`id`) REFERENCES `objects` (`id`) ON DELETE CASCADE
) WITHOUT ROWID, STRICT;
CREATE TABLE `entity_blueprints`
(
`entity` INT NOT NULL,
`blueprint` INT NOT NULL,
PRIMARY KEY (`entity`),
UNIQUE (`entity`, `blueprint`),
FOREIGN KEY (`blueprint`) REFERENCES `blueprints` (`id`) ON DELETE CASCADE
) WITHOUT ROWID, STRICT;
CREATE INDEX `entity_blueprints_blueprint` ON `entity_blueprints` (`blueprint`);
CREATE TABLE `properties`
(
`id` INT,
`type` INT NOT NULL,
`default_value` TEXT NOT NULL,
`settings` TEXT NOT NULL,
PRIMARY KEY (`id`),
FOREIGN KEY (`id`) REFERENCES `objects` (`id`) ON DELETE CASCADE
) WITHOUT ROWID, STRICT;
CREATE INDEX `properties_type` ON `properties` (`type`);
CREATE
VIRTUAL TABLE `property_default_value_fts` USING fts5
(
`default_value`,
content=
'properties',
content_rowid=
'object_id',
tokenize=
"unicode61 remove_diacritics 2 tokenchars '-_'"
);
CREATE
VIRTUAL TABLE `property_settings_fts` USING fts5
(
`settings`,
content=
'properties',
content_rowid=
'object_id',
tokenize=
"unicode61 remove_diacritics 2 tokenchars '-_'"
);
CREATE TABLE `values`
(
`entity` INT NOT NULL,
`property` INT NOT NULL,
`value` TEXT NOT NULL,
PRIMARY KEY (`entity`, `property`),
FOREIGN KEY (`entity`) REFERENCES `entities` (`id`) ON DELETE CASCADE,
FOREIGN KEY (`property`) REFERENCES `properties` (`id`) ON DELETE CASCADE
) WITHOUT ROWID, STRICT;
CREATE
VIRTUAL TABLE `values_fts` USING fts5
(
`value`,
content=
'values',
tokenize=
"unicode61 remove_diacritics 2 tokenchars '-_'"
)

View file

@ -1,10 +1,11 @@
#include "ikarus/project/project.h"
#include <filesystem>
#include <string>
#include <sqlitecpp/connection.hpp>
/// \private
struct IkarusProject {
std::string name;
std::filesystem::path path;
std::unique_ptr<sqlitecpp::Connection> db;
};

View file

@ -1,12 +0,0 @@
#include "ikarus/scopes/blueprint_scope.h"
#include <scopes/blueprint_scope.hpp>
#include <scopes/object_scope.hpp>
IkarusBlueprintScope * ikarus_blueprint_scope_create() {
return new IkarusBlueprintScope{};
}
struct IkarusObjectScope * ikarus_blueprint_scope_to_object_scope(IkarusBlueprintScope const * scope) {
return new IkarusObjectScope{.data = *scope};
}

View file

@ -1,5 +0,0 @@
#pragma once
#include <ikarus/scopes/blueprint_scope.h>
struct IkarusBlueprintScope {};

View file

@ -1,12 +0,0 @@
#include "ikarus/scopes/entity_scope.h"
#include <scopes/entity_scope.hpp>
#include <scopes/object_scope.hpp>
IkarusEntityScope * ikarus_entity_scope_create() {
return new IkarusEntityScope{};
}
IkarusObjectScope * ikarus_entity_scope_to_object_scope(IkarusEntityScope const * scope) {
return new IkarusObjectScope{.data = *scope};
}

View file

@ -1,5 +0,0 @@
#pragma once
#include <ikarus/scopes/entity_scope.h>
struct IkarusEntityScope {};

View file

@ -1,100 +0,0 @@
#include "ikarus/scopes/object_scope.h"
#include <initializer_list>
#include <utility>
#include <variant>
#include <catch2/catch_test_macros.hpp>
#include <cppbase/templates.hpp>
#include <ikarus/scopes/blueprint_scope.h>
#include <ikarus/scopes/entity_scope.h>
#include <ikarus/scopes/property_scope.h>
#include <scopes/object_scope.hpp>
IkarusObjectScopeType ikarus_object_scope_get_type(IkarusObjectScope * scope) {
return std::visit(
cppbase::overloaded{
[]([[maybe_unused]] IkarusBlueprintScope const& scope) { return IkarusObjectScopeType_Blueprint; },
[]([[maybe_unused]] IkarusPropertyScope const& scope) { return IkarusObjectScopeType_Property; },
[]([[maybe_unused]] IkarusEntityScope const& scope) { return IkarusObjectScopeType_Entity; }},
scope->data
);
}
void ikarus_object_scope_visit(
IkarusObjectScope * scope,
void(blueprint_visitor)(IkarusBlueprintScope *, void *),
void(property_visitor)(IkarusPropertyScope *, void *),
void(entity_visitor)(IkarusEntityScope *, void *),
void * data
) {
std::visit(
cppbase::overloaded{
[blueprint_visitor, data](IkarusBlueprintScope& scope) { blueprint_visitor(&scope, data); },
[property_visitor, data](IkarusPropertyScope& scope) { property_visitor(&scope, data); },
[entity_visitor, data](IkarusEntityScope& scope) { entity_visitor(&scope, data); }},
scope->data
);
}
TEST_CASE("blueprint_object_scope_conversion", "[object_scope]") {
auto * blueprint_scope = ikarus_blueprint_scope_create();
auto * blueprint_object_scope = ikarus_blueprint_scope_to_object_scope(blueprint_scope);
REQUIRE(ikarus_object_scope_get_type(blueprint_object_scope) == IkarusObjectScopeType_Blueprint);
}
TEST_CASE("property_object_scope_conversion", "[object_scope]") {
auto * blueprint = ikarus_blueprint_create();
auto * entity = ikarus_entity_create();
auto * property_blueprint_scope = ikarus_property_scope_create_blueprint(blueprint);
auto * property_blueprint_object_scope = ikarus_property_scope_to_object_scope(property_blueprint_scope);
REQUIRE(ikarus_object_scope_get_type(property_blueprint_object_scope) == IkarusObjectScopeType_Property);
auto * property_entity_scope = ikarus_property_scope_create_entity(entity);
auto * property_entity_object_scope = ikarus_property_scope_to_object_scope(property_entity_scope);
REQUIRE(ikarus_object_scope_get_type(property_entity_object_scope) == IkarusObjectScopeType_Property);
}
TEST_CASE("entity_object_scope_conversion", "[object_scope]") {
auto * entity_scope = ikarus_entity_scope_create();
auto * entity_object_scope = ikarus_entity_scope_to_object_scope(entity_scope);
REQUIRE(ikarus_object_scope_get_type(entity_object_scope) == IkarusObjectScopeType_Entity);
}
TEST_CASE("object_scope_visiting", "[object_scope]") {
auto * blueprint = ikarus_blueprint_create();
auto * blueprint_scope = ikarus_blueprint_scope_create();
auto * property_scope = ikarus_property_scope_create_blueprint(blueprint);
auto * entity_scope = ikarus_entity_scope_create();
auto * blueprint_object_scope = ikarus_blueprint_scope_to_object_scope(blueprint_scope);
auto * property_object_scope = ikarus_property_scope_to_object_scope(property_scope);
auto * entity_object_scope = ikarus_entity_scope_to_object_scope(entity_scope);
auto scopes = {
std::make_pair(blueprint_object_scope, 1),
std::make_pair(property_object_scope, 2),
std::make_pair(entity_object_scope, 3),
};
for (auto [scope, value] : scopes) {
int test = 0;
ikarus_object_scope_visit(
scope,
[](IkarusBlueprintScope *, void * data) { *static_cast<decltype(test) *>(data) = 1; },
[](IkarusPropertyScope *, void * data) { *static_cast<decltype(test) *>(data) = 2; },
[](IkarusEntityScope *, void * data) { *static_cast<decltype(test) *>(data) = 3; },
&test
);
REQUIRE(test == value);
}
}

View file

@ -1,11 +0,0 @@
#pragma once
#include <ikarus/scopes/object_scope.h>
#include <scopes/blueprint_scope.hpp>
#include <scopes/entity_scope.hpp>
#include <scopes/property_scope.hpp>
struct IkarusObjectScope {
std::variant<IkarusBlueprintScope, IkarusPropertyScope, IkarusEntityScope> data;
};

View file

@ -1,35 +0,0 @@
#include "ikarus/scopes/property_scope.h"
#include <cppbase/templates.hpp>
#include <objects/blueprint.hpp>
#include <objects/entity.hpp>
#include <scopes/object_scope.hpp>
#include <scopes/property_scope.hpp>
IkarusPropertyScope * ikarus_property_scope_create_blueprint(IkarusBlueprint * blueprint) {
return new IkarusPropertyScope{.data = *blueprint};
}
IkarusPropertyScope * ikarus_property_scope_create_entity(IkarusEntity * entity) {
return new IkarusPropertyScope{.data = *entity};
}
IkarusObjectScope * ikarus_property_scope_to_object_scope(IkarusPropertyScope const * scope) {
return new IkarusObjectScope{.data = *scope};
}
void ikarus_property_scope_visit(
IkarusPropertyScope * scope,
void (*blueprint_func)(IkarusBlueprint *, void *),
void (*entity_func)(IkarusEntity *, void *),
void * data
) {
std::visit(
cppbase::overloaded{
[blueprint_func, data](IkarusBlueprint& blueprint) { blueprint_func(&blueprint, data); },
[entity_func, data](IkarusEntity& entity) { entity_func(&entity, data); },
},
scope->data
);
}

View file

@ -1,12 +0,0 @@
#pragma once
#include <variant>
#include <ikarus/scopes/property_scope.h>
#include <objects/blueprint.hpp>
#include <objects/entity.hpp>
struct IkarusPropertyScope {
std::variant<IkarusBlueprint, IkarusEntity> data;
};

View file

@ -1,343 +0,0 @@
#include "ikarus/values/value.h"
#include <cmath>
#include <cstring>
#include <initializer_list>
#include <limits>
#include <utility>
#include <catch2/catch_test_macros.hpp>
#include <ikarus/macros.h>
#include <ikarus/objects/property.h>
/// \brief Creates an indeterminate entity value of a given type.
/// \param type The type of the value.
/// \return The entity value.
IKA_API IkarusEntityValue value_create_invalid(IkarusPropertyType type) {
return IkarusEntityValue{
._type = type,
._data = IkarusEntityValueData{},
._state = IkarusEntityValueState_Invalid,
};
}
IkarusEntityValue ikarus_value_create_toggle(bool value) {
return IkarusEntityValue{
._type = IkarusPropertyType_Toggle,
._data = IkarusEntityValueData{._toggle = IkarusToggleValue{._value = value}},
._state = IkarusEntityValueState_Normal,
};
}
IkarusEntityValue ikarus_value_create_number(long double value) {
if (auto fp_class = std::fpclassify(value); fp_class != FP_NORMAL && fp_class != FP_ZERO) {
return value_create_invalid(IkarusPropertyType_Number);
}
return IkarusEntityValue{
._type = IkarusPropertyType_Number,
._data = IkarusEntityValueData{._number = IkarusNumberValue{._value = value}},
._state = IkarusEntityValueState_Normal,
};
}
IkarusEntityValue ikarus_value_create_text(char const * value) {
if (value == nullptr) {
return value_create_invalid(IkarusPropertyType_Text);
}
return IkarusEntityValue{
._type = IkarusPropertyType_Text,
._data = IkarusEntityValueData{._text = IkarusTextValue{._value = value}},
._state = IkarusEntityValueState_Normal,
};
}
IkarusEntityValue ikarus_value_create_indeterminate(IkarusPropertyType type) {
IkarusEntityValueData data{};
switch (type) {
case IkarusPropertyType_Toggle: {
data._toggle = IkarusToggleValue{._value = false};
break;
}
case IkarusPropertyType_Number: {
data._number = IkarusNumberValue{._value = 0.0};
break;
}
case IkarusPropertyType_Text: {
data._text = IkarusTextValue{._value = ""};
break;
}
default: return value_create_invalid(type);
}
return IkarusEntityValue{
._type = type,
._data = data,
._state = IkarusEntityValueState_Indeterminate,
};
}
IkarusEntityValue ikarus_value_get_default(IkarusPropertyType type) {
switch (type) {
case IkarusPropertyType_Toggle: return ikarus_value_create_toggle(false);
case IkarusPropertyType_Number: return ikarus_value_create_number(0.0);
case IkarusPropertyType_Text: return ikarus_value_create_text("");
default: return value_create_invalid(type);
}
}
bool ikarus_toggle_value_get_underlying(IkarusToggleValue const * value) {
return value->_value;
}
long double ikarus_number_value_get_underlying(IkarusNumberValue const * value) {
return value->_value;
}
char const * ikarus_text_value_get_underlying(IkarusTextValue const * value) {
return value->_value;
}
// no need to check for validity here, since these concrete types are only created by the library
bool ikarus_toggle_value_is_equal(IkarusToggleValue const * value, bool check) {
return value != nullptr && value->_value == check;
}
bool ikarus_number_value_is_equal(IkarusNumberValue const * value, long double check) {
return value != nullptr && value->_value == check;
}
bool ikarus_text_value_is_equal(IkarusTextValue const * value, char const * check) {
return value != nullptr && check != nullptr && std::strcmp(value->_value, check) == 0;
}
bool ikarus_value_is_equal(IkarusEntityValue const * left, IkarusEntityValue const * right) {
if (left == nullptr || right == nullptr) {
return false;
}
if (left->_state == IkarusEntityValueState_Invalid || right->_state == IkarusEntityValueState_Invalid) {
return false;
}
if (left->_type != right->_type) {
return false;
}
// indeterminate values are only equal if they have the same type
if (left->_state == IkarusEntityValueState_Indeterminate && right->_state == IkarusEntityValueState_Indeterminate) {
return true;
}
switch (left->_type) {
case IkarusPropertyType_Toggle: return left->_data._toggle._value == right->_data._toggle._value;
case IkarusPropertyType_Number: return left->_data._number._value == right->_data._number._value;
case IkarusPropertyType_Text: return std::strcmp(left->_data._text._value, right->_data._text._value) == 0;
default: return false;
}
}
bool ikarus_value_is_invalid(IkarusEntityValue const * value) {
return value == nullptr || value->_state == IkarusEntityValueState_Invalid;
}
IkarusPropertyType ikarus_value_get_type(IkarusEntityValue const * value) {
return value->_type;
}
void ikarus_value_visit(
IkarusEntityValue const * value,
void (*toggle)(IkarusToggleValue const * value, void * data),
void (*number)(IkarusNumberValue const * value, void * data),
void (*text)(IkarusTextValue const * value, void * data),
void * data
) {
if (value == nullptr) {
return;
}
switch (value->_type) {
case IkarusPropertyType_Toggle: {
if (toggle != nullptr) {
toggle(&value->_data._toggle, data);
}
break;
}
case IkarusPropertyType_Number: {
if (number != nullptr) {
number(&value->_data._number, data);
}
break;
}
case IkarusPropertyType_Text: {
if (text != nullptr) {
text(&value->_data._text, data);
}
break;
}
default: break;
}
}
TEST_CASE("toggle_value_creation", "[value]") {
auto toggle_value = ikarus_value_create_toggle(true);
REQUIRE(ikarus_value_get_type(&toggle_value) == IkarusPropertyType_Toggle);
REQUIRE(ikarus_toggle_value_is_equal(&toggle_value._data._toggle, true));
}
TEST_CASE("number_value_creation", "[value]") {
auto number_value = ikarus_value_create_number(1.0);
REQUIRE(ikarus_value_get_type(&number_value) == IkarusPropertyType_Number);
REQUIRE(ikarus_number_value_is_equal(&number_value._data._number, 1.0));
auto nan_value = ikarus_value_create_number(std::numeric_limits<long double>::quiet_NaN());
REQUIRE(ikarus_value_is_invalid(&nan_value));
auto signaling_non_value = ikarus_value_create_number(std::numeric_limits<long double>::signaling_NaN());
REQUIRE(ikarus_value_is_invalid(&signaling_non_value));
auto inf_value = ikarus_value_create_number(std::numeric_limits<long double>::infinity());
REQUIRE(ikarus_value_is_invalid(&inf_value));
auto neg_inf_value = ikarus_value_create_number(-std::numeric_limits<long double>::infinity());
REQUIRE(ikarus_value_is_invalid(&neg_inf_value));
}
TEST_CASE("text_value_creation", "[value]") {
auto text_value = ikarus_value_create_text("test");
REQUIRE(ikarus_value_get_type(&text_value) == IkarusPropertyType_Text);
REQUIRE(ikarus_text_value_is_equal(&text_value._data._text, "test"));
auto null_value = ikarus_value_create_text(nullptr);
REQUIRE(ikarus_value_is_invalid(&null_value));
}
TEST_CASE("default_value_creation", "[value]") {
auto types = {
IkarusPropertyType_Toggle,
IkarusPropertyType_Number,
IkarusPropertyType_Text,
};
for (auto type : types) {
auto value = ikarus_value_get_default(type);
REQUIRE(ikarus_value_get_type(&value) == type);
}
}
TEST_CASE("toggle_value_underlying", "[value]") {
auto true_toggle_value = ikarus_value_create_toggle(true);
auto false_toggle_value = ikarus_value_create_toggle(false);
REQUIRE(ikarus_toggle_value_get_underlying(&true_toggle_value._data._toggle) == true);
REQUIRE(ikarus_toggle_value_get_underlying(&false_toggle_value._data._toggle) == false);
}
TEST_CASE("number_value_underlying", "[value]") {
auto zero_number_value = ikarus_value_create_number(0.0);
auto third_number_value = ikarus_value_create_number(1.0 / 3.0);
auto large_number_value = ikarus_value_create_number(1.2345678910e123);
REQUIRE(ikarus_number_value_get_underlying(&zero_number_value._data._number) == 0.0);
REQUIRE(ikarus_number_value_get_underlying(&third_number_value._data._number) == 1.0 / 3.0);
REQUIRE(ikarus_number_value_get_underlying(&large_number_value._data._number) == 1.2345678910e123);
}
TEST_CASE("text_value_underlying", "[value]") {
auto test_value = ikarus_value_create_text("test");
auto empty_value = ikarus_value_create_text("");
REQUIRE(std::strcmp(ikarus_text_value_get_underlying(&test_value._data._text), "test") == 0);
REQUIRE(std::strcmp(ikarus_text_value_get_underlying(&empty_value._data._text), "") == 0);
}
TEST_CASE("toggle_comparison", "[value]") {
auto true_toggle_value = ikarus_value_create_toggle(true);
auto false_toggle_value = ikarus_value_create_toggle(false);
REQUIRE(ikarus_toggle_value_is_equal(&true_toggle_value._data._toggle, true));
REQUIRE(ikarus_toggle_value_is_equal(&false_toggle_value._data._toggle, false));
}
TEST_CASE("number_comparison", "[value]") {
auto zero_number_value = ikarus_value_create_number(0.0);
auto third_number_value = ikarus_value_create_number(1.0 / 3.0);
auto large_number_value = ikarus_value_create_number(1.2345678910e123);
REQUIRE(ikarus_number_value_is_equal(&zero_number_value._data._number, 0.0));
REQUIRE(ikarus_number_value_is_equal(&third_number_value._data._number, 1.0 / 6.0 + 1.0 / 6.0));
REQUIRE(ikarus_number_value_is_equal(&large_number_value._data._number, 1.2345678910e123));
}
TEST_CASE("text_comparison", "[value]") {
auto test_value = ikarus_value_create_text("test");
auto empty_value = ikarus_value_create_text("");
REQUIRE(ikarus_text_value_is_equal(&test_value._data._text, "test"));
REQUIRE(ikarus_text_value_is_equal(&empty_value._data._text, ""));
}
TEST_CASE("value_comparison", "[value]") {
auto true_toggle_value = ikarus_value_create_toggle(true);
auto false_toggle_value = ikarus_value_create_toggle(false);
auto number_value1 = ikarus_value_create_number(0.0);
auto number_value2 = ikarus_value_create_number(0.0);
auto invalid_value = ikarus_value_create_text(nullptr);
auto indeterminate_toggle = ikarus_value_create_indeterminate(IkarusPropertyType_Toggle);
auto indeterminate_number1 = ikarus_value_create_indeterminate(IkarusPropertyType_Number);
auto indeterminate_number2 = ikarus_value_create_indeterminate(IkarusPropertyType_Number);
REQUIRE(!ikarus_value_is_equal(nullptr, nullptr));
REQUIRE(!ikarus_value_is_equal(&true_toggle_value, nullptr));
REQUIRE(!ikarus_value_is_equal(nullptr, &true_toggle_value));
REQUIRE(!ikarus_value_is_equal(&invalid_value, &invalid_value));
REQUIRE(!ikarus_value_is_equal(&true_toggle_value, &invalid_value));
REQUIRE(!ikarus_value_is_equal(&invalid_value, &true_toggle_value));
REQUIRE(ikarus_value_is_equal(&true_toggle_value, &true_toggle_value));
REQUIRE(!ikarus_value_is_equal(&true_toggle_value, &false_toggle_value));
REQUIRE(!ikarus_value_is_equal(&true_toggle_value, &number_value1));
REQUIRE(!ikarus_value_is_equal(&number_value1, &true_toggle_value));
REQUIRE(ikarus_value_is_equal(&number_value1, &number_value2));
REQUIRE(!ikarus_value_is_equal(&indeterminate_toggle, &indeterminate_number1));
REQUIRE(ikarus_value_is_equal(&indeterminate_number1, &indeterminate_number2));
}
TEST_CASE("invalid_value", "[value]") {
auto invalid_value = ikarus_value_create_toggle(false);
invalid_value._state = IkarusEntityValueState_Invalid;
REQUIRE(ikarus_value_is_invalid(&invalid_value));
}
TEST_CASE("visit_value", "[value]") {
auto toggle_value = ikarus_value_create_toggle(true);
auto number_value = ikarus_value_create_number(0.0);
auto text_value = ikarus_value_create_text("test");
auto values = {
std::make_pair(toggle_value, 1),
std::make_pair(number_value, 2),
std::make_pair(text_value, 3),
};
for (auto [value, expected] : values) {
int test = 0;
ikarus_value_visit(
&value,
[](IkarusToggleValue const *, void * data) { *reinterpret_cast<decltype(test) *>(data) = 1; },
[](IkarusNumberValue const *, void * data) { *reinterpret_cast<decltype(test) *>(data) = 2; },
[](IkarusTextValue const *, void * data) { *reinterpret_cast<decltype(test) *>(data) = 3; },
&test
);
REQUIRE(test == expected);
}
}