diff --git a/CMakeLists.txt b/CMakeLists.txt index e931347885bc39a64e131d8ae8003a67ebf72847..97830558c446a3e6718d68b8ba2cee7c033bd88d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -20,7 +20,7 @@ cmake_minimum_required(VERSION 3.13) -set(libcaosdb_VERSION 0.0.16) +set(libcaosdb_VERSION 0.0.17) set(libcaosdb_COMPATIBLE_SERVER_VERSION_MAJOR 0) set(libcaosdb_COMPATIBLE_SERVER_VERSION_MINOR 5) set(libcaosdb_COMPATIBLE_SERVER_VERSION_PATCH 0) diff --git a/conanfile.py b/conanfile.py index 3748da681bff0aa278059c0a4e42df0d6432e67a..7a712bbd99136c5054f7a8fedeee6fb5af5ce4f7 100644 --- a/conanfile.py +++ b/conanfile.py @@ -3,7 +3,7 @@ from conans import ConanFile, CMake, tools class CaosdbConan(ConanFile): name = "caosdb" - version = "0.0.16" + version = "0.0.17" license = "AGPL-3.0-or-later" author = "Timm C. Fitschen <t.fitschen@indiscale.com>" url = "https://gitlab.indiscale.com/caosdb/src/caosdb-cpplib.git" diff --git a/include/caosdb/data_type.h b/include/caosdb/data_type.h index 22358fcda808c8ebf93c140156ba7e39c5757e8d..e6b92d53d6ddb1aa8360af55f6438d23eafff7ae 100644 --- a/include/caosdb/data_type.h +++ b/include/caosdb/data_type.h @@ -179,14 +179,14 @@ public: [[nodiscard]] inline auto IsAtomic() const noexcept -> bool { return this->wrapped->data_type_case() == DataTypeCase::kAtomicDataType; } - [[nodiscard]] inline auto AsAtomic() const noexcept -> AtomicDataType { + [[nodiscard]] inline auto GetAsAtomic() const noexcept -> AtomicDataType { return static_cast<AtomicDataType>(this->wrapped->atomic_data_type()); } [[nodiscard]] inline auto IsReference() const noexcept -> bool { return this->wrapped->data_type_case() == DataTypeCase::kReferenceDataType; } - [[nodiscard]] inline auto AsReference() const noexcept -> const ReferenceDataType & { + [[nodiscard]] inline auto GetAsReference() const noexcept -> const ReferenceDataType & { if (!IsReference()) { return ReferenceDataType::GetEmptyInstance(); } else if (reference_data_type == nullptr) { @@ -200,7 +200,7 @@ public: return this->wrapped->data_type_case() == DataTypeCase::kListDataType; } - [[nodiscard]] inline auto AsList() const noexcept -> const ListDataType & { + [[nodiscard]] inline auto GetAsList() const noexcept -> const ListDataType & { if (!IsList()) { return ListDataType::GetEmptyInstance(); } else if (list_data_type == nullptr) { diff --git a/include/caosdb/entity.h b/include/caosdb/entity.h index fea060d726d67c0cf6f21d42f6b8f3ead0622671..de6d4928771af83edca68d748d73b58f690a35f7 100644 --- a/include/caosdb/entity.h +++ b/include/caosdb/entity.h @@ -515,6 +515,7 @@ public: * Set the value of this property. */ auto SetValue(const Value &value) -> StatusCode; + auto SetValue(const AbstractValue &value) -> StatusCode; auto SetValue(const std::string &value) -> StatusCode; auto SetValue(const char *value) -> StatusCode; auto SetValue(const double value) -> StatusCode; @@ -687,6 +688,7 @@ public: */ auto SetDescription(const std::string &description) -> void; + auto SetValue(const AbstractValue &value) -> StatusCode; auto SetValue(const Value &value) -> StatusCode; auto SetValue(const std::string &value) -> StatusCode; auto SetValue(const char *value) -> StatusCode; diff --git a/include/caosdb/value.h b/include/caosdb/value.h index 6031e75dbd69c262cc69079c63323d916cec223d..7bf0f7d3f9a7e0c55f7ccf48fd0af536baec5e1e 100644 --- a/include/caosdb/value.h +++ b/include/caosdb/value.h @@ -22,12 +22,17 @@ #ifndef CAOSDB_VALUE_H #define CAOSDB_VALUE_H #include "caosdb/protobuf_helper.h" // for ProtoMessageWrapper +#include "caosdb/logging.h" // IWYU pragma: keep #include "caosdb/entity/v1alpha1/main.pb.h" // for RepeatedPtrField, Message -#include "caosdb/logging.h" -#include <google/protobuf/util/json_util.h> // for MessageToJson... -#include <memory> // for unique_ptr -#include <string> // for string -#include <vector> // for vector + +#include <cstdint> // for int64_t +#include <google/protobuf/arena.h> // for Arena +#include <google/protobuf/generated_message_util.h> // for Arena +#include <google/protobuf/util/json_util.h> // IWYU pragma: keep +#include <memory> // for unique_ptr +#include <string> // for string, operator== +#include <utility> // for move +#include <vector> // for vector #define LIST_VALUE_CONSTRUCTOR(TYPE, SETTER) \ explicit inline Value(const std::vector<TYPE> &values) : ProtoMessageWrapper<ProtoValue>() { \ @@ -37,15 +42,17 @@ } namespace caosdb::entity { +using caosdb::utility::get_arena; using caosdb::utility::ProtoMessageWrapper; +using google::protobuf::Arena; using ProtoSpecialValue = caosdb::entity::v1alpha1::SpecialValue; using ProtoValue = caosdb::entity::v1alpha1::Value; using ProtoScalarValue = caosdb::entity::v1alpha1::ScalarValue; using ValueCase = caosdb::entity::v1alpha1::Value::ValueCase; using ScalarValueCase = caosdb::entity::v1alpha1::ScalarValue::ScalarValueCase; -class Entity; -class Property; +class ScalarValue; +class Value; // Represents special values which are otherwise hard to tranfer via protobuf. enum SpecialValue { @@ -55,46 +62,239 @@ enum SpecialValue { EMPTY_STRING = ProtoSpecialValue::SPECIAL_VALUE_EMPTY_STRING, }; -class ScalarValue : public ProtoMessageWrapper<ProtoScalarValue> { +/** + * Pure abstract base class for values. + */ +class AbstractValue { public: - inline ScalarValue(ProtoScalarValue *wrapped) : ProtoMessageWrapper<ProtoScalarValue>(wrapped) {} + /** + * Pure virtual destructor. + */ + virtual ~AbstractValue() = 0; + /** + * Return true iff the value is a NULL value (NULL in the CaosDB sense). + */ + [[nodiscard]] virtual auto IsNull() const noexcept -> bool = 0; + /** + * Return true iff the value is best represented in C++ types as a + * std::string. + * + * If true, clients may call GetAsString to receive a std::string + * representation of the value. + */ + [[nodiscard]] virtual auto IsString() const noexcept -> bool = 0; + /** + * Return true iff the value is best represented in C++ types as a + * bool. + * + * If true, clients may call GetAsBool to receive a bool + * representation of the value. + */ + [[nodiscard]] virtual auto IsBool() const noexcept -> bool = 0; + /** + * Return true iff the value is best represented in C++ types as a + * double. + * + * If true, clients may call GetAsDouble to receive a double + * representation of the value. + */ + [[nodiscard]] virtual auto IsDouble() const noexcept -> bool = 0; + /** + * Return true iff the value is best represented in C++ types as an + * int64_t. + * + * If true, clients may call GetAsInt64 to receive an int64_t + * representation of the value. + */ + [[nodiscard]] virtual auto IsInt64() const noexcept -> bool = 0; + /** + * Return true iff the value is best represented in C++ types as a + * std::vector<ScalarValue>. + * + * If true, clients may call GetAsVector to receive a + * std::vector<ScalarValue> representation of the value. + */ + [[nodiscard]] virtual auto IsVector() const noexcept -> bool = 0; + + /** + * Return a std::string representation of this value. + * + * Clients should call IsString before calling this function in order to + * assure that this value is indeed best represented by a std::string. + * + * The return value is undefined if IsString is false. + */ + [[nodiscard]] virtual auto GetAsString() const noexcept -> const std::string & = 0; + /** + * Return a bool representation of this value. + * + * Clients should call IsBool before calling this function in order to + * assure that this value is indeed best represented by a bool. + * + * The return value is undefined if IsBool is false. + */ + [[nodiscard]] virtual auto GetAsBool() const noexcept -> bool = 0; + /** + * Return a double representation of this value. + * + * Clients should call IsDouble before calling this function in order to + * assure that this value is indeed best represented by a double. + * + * The return value is undefined if IsDouble is false. + */ + [[nodiscard]] virtual auto GetAsDouble() const noexcept -> double = 0; + /** + * Return an int64_t representation of this value. + * + * Clients should call IsInt64 before calling this function in order to + * assure that this value is indeed best represented by an int64_t. + * + * The return value is undefined if IsInt64 is false. + */ + [[nodiscard]] virtual auto GetAsInt64() const noexcept -> int64_t = 0; + /** + * Return a std::vector<ScalarValue> representation of this value. + * + * Clients should call IsVector before calling this function in order to + * assure that this value is indeed best represented by a + * std::vector<ScalarValue>. + * + * The return value is undefined if IsVector is false. + */ + [[nodiscard]] virtual auto GetAsVector() const noexcept -> const std::vector<ScalarValue> & = 0; + [[nodiscard]] virtual auto ToString() const noexcept -> const std::string = 0; + friend class Value; + +protected: + [[nodiscard]] virtual auto GetProtoValue() const noexcept -> const ProtoValue * = 0; +}; +inline AbstractValue::~AbstractValue() {} + +class ScalarValue : public AbstractValue, public ProtoMessageWrapper<ProtoScalarValue> { +public: + /** + * Destructor. + */ + inline ~ScalarValue(){}; + /** + * Copy constructor. + */ + inline ScalarValue(const ScalarValue &original) : ScalarValue() { + this->wrapped->CopyFrom(*original.wrapped); + } + /** + * Move constructor. + */ + inline ScalarValue(ScalarValue &&other) : ScalarValue(std::move(other.wrapped)){}; + /** + * Copy assignment operator. + */ + inline auto operator=(const ScalarValue &original) -> ScalarValue & { + if (&original != this) { + this->wrapped->CopyFrom(*original.wrapped); + } + return *this; + } + /** + * Move assignment operator. + */ + inline auto operator=(ScalarValue &&other) -> ScalarValue & { + if (&other != this) { + this->wrapped = std::move(other.wrapped); + } + return *this; + } + + inline ScalarValue(ProtoScalarValue *wrapped) + : ProtoMessageWrapper<ProtoScalarValue>(wrapped), proto_value(nullptr) {} + + [[nodiscard]] inline auto IsNull() const noexcept -> bool { + return (this->wrapped->scalar_value_case() == ScalarValueCase::kSpecialValue && + this->wrapped->special_value() == ProtoSpecialValue::SPECIAL_VALUE_UNSPECIFIED); + } [[nodiscard]] inline auto IsString() const noexcept -> bool { return (this->wrapped->scalar_value_case() == ScalarValueCase::kStringValue) || (this->wrapped->scalar_value_case() == ScalarValueCase::kSpecialValue && this->wrapped->special_value() == ProtoSpecialValue::SPECIAL_VALUE_EMPTY_STRING); } - [[nodiscard]] inline auto AsString() const noexcept -> const std::string & { + [[nodiscard]] inline auto GetAsString() const noexcept -> const std::string & { return this->wrapped->string_value(); } [[nodiscard]] inline auto IsDouble() const noexcept -> bool { return (this->wrapped->scalar_value_case() == ScalarValueCase::kDoubleValue); } - [[nodiscard]] inline auto AsDouble() const noexcept -> double { + [[nodiscard]] inline auto GetAsDouble() const noexcept -> double { return this->wrapped->double_value(); } - [[nodiscard]] inline auto IsInteger() const noexcept -> bool { + [[nodiscard]] inline auto IsInt64() const noexcept -> bool { return (this->wrapped->scalar_value_case() == ScalarValueCase::kIntegerValue); } - [[nodiscard]] inline auto AsInteger() const noexcept -> int64_t { + [[nodiscard]] inline auto GetAsInt64() const noexcept -> int64_t { return this->wrapped->integer_value(); } [[nodiscard]] inline auto IsBool() const noexcept -> bool { return (this->wrapped->scalar_value_case() == ScalarValueCase::kBooleanValue); } - [[nodiscard]] inline auto AsBool() const noexcept -> bool { + [[nodiscard]] inline auto GetAsBool() const noexcept -> bool { return this->wrapped->boolean_value(); } + [[nodiscard]] auto IsVector() const noexcept -> bool { + // Always false b/c a scalar value is never a collection. + return false; + } + [[nodiscard]] auto GetAsVector() const noexcept -> const std::vector<ScalarValue> & { + // Always return an empty vector. + static const std::vector<ScalarValue> empty_collection; + return empty_collection; + } + inline auto ToString() const noexcept -> const std::string { + CAOSDB_DEBUG_MESSAGE_STRING(*wrapped, out) + return out; + } + + friend class Value; + +protected: + [[nodiscard]] auto GetProtoValue() const noexcept -> const ProtoValue * { + if (this->proto_value == nullptr) { + this->proto_value = Arena::CreateMessage<ProtoValue>(get_arena()); + this->proto_value->mutable_scalar_value()->CopyFrom(*this->wrapped); + } + return this->proto_value; + }; + inline ScalarValue() : ProtoMessageWrapper<ProtoScalarValue>(), proto_value(nullptr) {} + +private: + mutable ProtoValue *proto_value; }; -class Value : public ProtoMessageWrapper<ProtoValue> { +class Value : public AbstractValue, public ProtoMessageWrapper<ProtoValue> { public: + /** + * Copy constructor. + */ + inline Value(const Value &original) : Value() { this->wrapped->CopyFrom(*original.wrapped); } + /** + * Move constructor. + */ + inline Value(Value &&other) : Value(std::move(other.wrapped)) {} + /** + * Destructor. + */ + inline ~Value() {} inline Value() : ProtoMessageWrapper<ProtoValue>() { // has NULL_VALUE now } + explicit inline Value(const ScalarValue &value) : Value() { + this->wrapped->mutable_scalar_value()->CopyFrom(*value.wrapped); + } + explicit inline Value(const AbstractValue &value) : Value() { + this->wrapped->CopyFrom(*value.GetProtoValue()); + } explicit inline Value(ProtoValue *wrapped) : ProtoMessageWrapper<ProtoValue>(wrapped) {} explicit inline Value(const std::string &value) : ProtoMessageWrapper<ProtoValue>() { this->wrapped->mutable_scalar_value()->set_string_value(value); @@ -121,7 +321,10 @@ public: LIST_VALUE_CONSTRUCTOR(bool, set_boolean_value) [[nodiscard]] inline auto IsNull() const noexcept -> bool { - return this->wrapped->value_case() == ValueCase::VALUE_NOT_SET; + return this->wrapped->value_case() == ValueCase::VALUE_NOT_SET || + (this->wrapped->scalar_value().scalar_value_case() == ScalarValueCase::kSpecialValue && + this->wrapped->scalar_value().special_value() == + ProtoSpecialValue::SPECIAL_VALUE_UNSPECIFIED); } [[nodiscard]] inline auto IsString() const noexcept -> bool { @@ -134,7 +337,7 @@ public: } return false; } - [[nodiscard]] inline auto AsString() const noexcept -> const std::string & { + [[nodiscard]] inline auto GetAsString() const noexcept -> const std::string & { return this->wrapped->scalar_value().string_value(); ; } @@ -146,18 +349,18 @@ public: } return false; } - [[nodiscard]] inline auto AsDouble() const noexcept -> double { + [[nodiscard]] inline auto GetAsDouble() const noexcept -> double { return this->wrapped->scalar_value().double_value(); } - [[nodiscard]] inline auto IsInteger() const noexcept -> bool { + [[nodiscard]] inline auto IsInt64() const noexcept -> bool { if (this->wrapped->value_case() == ValueCase::kScalarValue) { return (this->wrapped->scalar_value().scalar_value_case() == ScalarValueCase::kIntegerValue); } return false; } - [[nodiscard]] inline auto AsInteger() const noexcept -> int64_t { + [[nodiscard]] inline auto GetAsInt64() const noexcept -> int64_t { return this->wrapped->scalar_value().integer_value(); } @@ -168,31 +371,55 @@ public: } return false; } - [[nodiscard]] inline auto AsBool() const noexcept -> bool { + [[nodiscard]] inline auto GetAsBool() const noexcept -> bool { return this->wrapped->scalar_value().boolean_value(); } - [[nodiscard]] inline auto IsList() const noexcept -> bool { + [[nodiscard]] inline auto IsVector() const noexcept -> bool { return this->wrapped->value_case() == ValueCase::kListValues; } - [[nodiscard]] inline auto AsList() const noexcept -> const std::vector<ScalarValue> & { - if (!IsList()) { + [[nodiscard]] inline auto GetAsVector() const noexcept -> const std::vector<ScalarValue> & { + if (!IsVector()) { // create empty list - this->list_values = std::make_unique<std::vector<ScalarValue>>(); + this->collection_values = std::make_unique<std::vector<ScalarValue>>(); } - if (this->list_values == nullptr) { - this->list_values = std::make_unique<std::vector<ScalarValue>>(); + if (this->collection_values == nullptr) { + this->collection_values = std::make_unique<std::vector<ScalarValue>>(); for (auto &scalar : *(this->wrapped->mutable_list_values()->mutable_values())) { - this->list_values->push_back(ScalarValue(&scalar)); + this->collection_values->push_back(ScalarValue(&scalar)); } } - return *(this->list_values); + return *(this->collection_values); } + /** + * Return true if the underlying Protobuf messages have the same + * serialization. + */ inline auto operator==(const Value &other) const noexcept -> bool { return this->wrapped->SerializeAsString() == other.wrapped->SerializeAsString(); } + /** + * Copy assignment operator. + */ + inline auto operator=(const Value &other) -> Value & { + if (&other != this) { + this->wrapped->CopyFrom(*other.wrapped); + } + return *this; + } + + /** + * Move assignment operator. + */ + inline auto operator=(Value &&other) -> Value & { + if (&other != this) { + this->wrapped = std::move(other.wrapped); + } + return *this; + } + inline auto ToString() const noexcept -> const std::string { CAOSDB_DEBUG_MESSAGE_STRING(*wrapped, out) return out; @@ -201,8 +428,11 @@ public: friend class Entity; friend class Property; +protected: + [[nodiscard]] auto GetProtoValue() const noexcept -> const ProtoValue * { return this->wrapped; }; + private: - mutable std::unique_ptr<std::vector<ScalarValue>> list_values; + mutable std::unique_ptr<std::vector<ScalarValue>> collection_values; }; } // namespace caosdb::entity diff --git a/include/ccaosdb.h b/include/ccaosdb.h index 788cf0bdaa49bea9fffa787a66d55d35addbd14a..b9296349b6f9592bed9e60362ae4848faf95a649 100644 --- a/include/ccaosdb.h +++ b/include/ccaosdb.h @@ -264,8 +264,6 @@ int caosdb_connection_connection_manager_get_connection(caosdb_connection_connec * ENTITY STUFF AND TRANSACTIONS ****************************************************************************/ -// TODO(fspreck) implementations needed, and probably these declarations are -// not sufficient yet. typedef struct caosdb_transaction_transaction { void *wrapped_transaction; bool _deletable = false; @@ -363,33 +361,25 @@ typedef struct caosdb_entity_message { bool _deletable = false; } caosdb_entity_message; +typedef struct caosdb_entity_value { + void *wrapped_value; + bool _deletable = false; +} caosdb_entity_value; + +typedef struct caosdb_entity_datatype { + void *wrapped_datatype; + bool _deletable = false; +} caosdb_entity_datatype; + // GETTERS FOR EVERYTHING int caosdb_entity_entity_get_id(caosdb_entity_entity *entity, char **out); int caosdb_entity_entity_get_role(caosdb_entity_entity *entity, char **out); int caosdb_entity_entity_get_name(caosdb_entity_entity *entity, char **out); int caosdb_entity_entity_get_description(caosdb_entity_entity *entity, char **out); int caosdb_entity_entity_get_local_path(caosdb_entity_entity *entity, char **out); -/** - * Get the name of the entity's datatype, whether it is a reference, and whether it is a list. - */ -int caosdb_entity_entity_get_datatype(caosdb_entity_entity *entity, char **name, bool *is_ref, - bool *is_list); +int caosdb_entity_entity_get_datatype(caosdb_entity_entity *entity, caosdb_entity_datatype *out); int caosdb_entity_entity_get_unit(caosdb_entity_entity *entity, char **out); - -int caosdb_entity_entity_get_int_value(caosdb_entity_entity *entity, int64_t *out); -int caosdb_entity_entity_get_double_value(caosdb_entity_entity *entity, double *out); -int caosdb_entity_entity_get_boolean_value(caosdb_entity_entity *entity, bool *out); -int caosdb_entity_entity_get_string_value(caosdb_entity_entity *entity, char **out); -int caosdb_entity_entity_get_int_list_value_at(caosdb_entity_entity *entity, int64_t *out, - const int index); -int caosdb_entity_entity_get_double_list_value_at(caosdb_entity_entity *entity, double *out, - const int index); -int caosdb_entity_entity_get_boolean_list_value_at(caosdb_entity_entity *entity, bool *out, - const int index); -int caosdb_entity_entity_get_string_list_value_at(caosdb_entity_entity *entity, char **out, - const int index); -int caosdb_entity_entity_get_value_list_length(caosdb_entity_entity *entity, int *out); - +int caosdb_entity_entity_get_value(caosdb_entity_entity *entity, caosdb_entity_value *out); int caosdb_entity_entity_get_version_id(caosdb_entity_entity *entity, char **out); int caosdb_entity_entity_get_errors_size(caosdb_entity_entity *entity, int *out); int caosdb_entity_entity_get_error(caosdb_entity_entity *entity, caosdb_entity_message *out, @@ -411,27 +401,10 @@ int caosdb_entity_property_get_id(caosdb_entity_property *property, char **out); int caosdb_entity_property_get_name(caosdb_entity_property *property, char **out); int caosdb_entity_property_get_description(caosdb_entity_property *property, char **out); int caosdb_entity_property_get_importance(caosdb_entity_property *property, char **out); -/** - * Get the name of the property's datatype, whether it is a reference, and whether it is a list. - */ -int caosdb_entity_property_get_datatype(caosdb_entity_property *property, char **name, bool *is_ref, - bool *is_list); +int caosdb_entity_property_get_datatype(caosdb_entity_property *property, + caosdb_entity_datatype *out); int caosdb_entity_property_get_unit(caosdb_entity_property *property, char **out); - -int caosdb_entity_property_get_int_value(caosdb_entity_property *property, int64_t *out); -int caosdb_entity_property_get_double_value(caosdb_entity_property *property, double *out); -int caosdb_entity_property_get_boolean_value(caosdb_entity_property *property, bool *out); -int caosdb_entity_property_get_string_value(caosdb_entity_property *property, char **out); -int caosdb_entity_property_get_int_list_value_at(caosdb_entity_property *property, int64_t *out, - const int index); -int caosdb_entity_property_get_double_list_value_at(caosdb_entity_property *property, double *out, - const int index); -int caosdb_entity_property_get_boolean_list_value_at(caosdb_entity_property *property, bool *out, - const int index); -int caosdb_entity_property_get_string_list_value_at(caosdb_entity_property *property, char **out, - const int index); -int caosdb_entity_property_get_value_list_length(caosdb_entity_property *property, int *out); - +int caosdb_entity_property_get_value(caosdb_entity_property *property, caosdb_entity_value *out); int caosdb_entity_parent_get_id(caosdb_entity_parent *parent, char **out); int caosdb_entity_parent_get_name(caosdb_entity_parent *parent, char **out); int caosdb_entity_parent_get_description(caosdb_entity_parent *parent, char **out); @@ -439,6 +412,26 @@ int caosdb_entity_parent_get_description(caosdb_entity_parent *parent, char **ou int caosdb_entity_message_get_code(caosdb_entity_message *message, int *out); int caosdb_entity_message_get_description(caosdb_entity_message *message, char **out); +int caosdb_entity_datatype_is_atomic(caosdb_entity_datatype *datatype, bool *out); +int caosdb_entity_datatype_is_reference(caosdb_entity_datatype *datatype, bool *out); +int caosdb_entity_datatype_is_list_of_atomic(caosdb_entity_datatype *datatype, bool *out); +int caosdb_entity_datatype_is_list_of_reference(caosdb_entity_datatype *datatype, bool *out); +int caosdb_entity_datatype_get_datatype_name(caosdb_entity_datatype *datatype, char **out); + +int caosdb_entity_value_is_null(caosdb_entity_value *value, bool *out); +int caosdb_entity_value_is_string(caosdb_entity_value *value, bool *out); +int caosdb_entity_value_is_double(caosdb_entity_value *value, bool *out); +int caosdb_entity_value_is_integer(caosdb_entity_value *value, bool *out); +int caosdb_entity_value_is_bool(caosdb_entity_value *value, bool *out); +int caosdb_entity_value_is_vector(caosdb_entity_value *value, bool *out); +int caosdb_entity_value_get_as_string(caosdb_entity_value *value, char **out); +int caosdb_entity_value_get_as_double(caosdb_entity_value *value, double *out); +int caosdb_entity_value_get_as_integer(caosdb_entity_value *value, int64_t *out); +int caosdb_entity_value_get_as_bool(caosdb_entity_value *value, bool *out); +int caosdb_entity_value_get_as_vector_size(caosdb_entity_value *value, int *out); +int caosdb_entity_value_get_as_vector_at(caosdb_entity_value *value, caosdb_entity_value *out, + const int index); + // CONSTRUCTORS AND DESTRUCTORS int caosdb_entity_create_entity(caosdb_entity_entity *out); int caosdb_entity_delete_entity(caosdb_entity_entity *out); @@ -447,31 +440,38 @@ int caosdb_entity_delete_property(caosdb_entity_property *out); int caosdb_entity_create_parent(caosdb_entity_parent *out); int caosdb_entity_delete_parent(caosdb_entity_parent *out); +// DATATYPE CONSTRUCTORS for atomic and reference datatypes and lists thereof +int caosdb_entity_create_atomic_datatype(caosdb_entity_datatype *out, const char *name); +int caosdb_entity_create_reference_datatype(caosdb_entity_datatype *out, const char *name); +int caosdb_entity_create_atomic_list_datatype(caosdb_entity_datatype *out, const char *name); +int caosdb_entity_create_reference_list_datatype(caosdb_entity_datatype *out, const char *name); +int caosdb_entity_delete_datatype(caosdb_entity_datatype *out); + +// VALUE CONSTRUCTORS (resolve overloaded constructors) +int caosdb_entity_create_int_value(caosdb_entity_value *out, const int64_t value); +int caosdb_entity_create_string_value(caosdb_entity_value *out, const char *value); +int caosdb_entity_create_double_value(caosdb_entity_value *out, const double value); +int caosdb_entity_create_bool_value(caosdb_entity_value *out, const bool value); +int caosdb_entity_create_int_vector_value(caosdb_entity_value *out, const int64_t *value, + const int length); +int caosdb_entity_create_string_vector_value(caosdb_entity_value *out, const char **value, + const int length); +int caosdb_entity_create_double_vector_value(caosdb_entity_value *out, const double *value, + const int length); +int caosdb_entity_create_bool_vector_value(caosdb_entity_value *out, const bool *value, + const int length); +int caosdb_entity_delete_value(caosdb_entity_value *out); + // SETTERS FOR EVERYTHING THAT MAY BE SET int caosdb_entity_entity_set_role(caosdb_entity_entity *entity, const char *role); int caosdb_entity_entity_set_name(caosdb_entity_entity *entity, const char *name); int caosdb_entity_entity_set_description(caosdb_entity_entity *entity, const char *description); int caosdb_entity_entity_set_local_path(caosdb_entity_entity *entity, const char *name); int caosdb_entity_entity_set_file_path(caosdb_entity_entity *entity, const char *name); -/** - * Set the entity's datatype by name, and whether it is a reference or a list. - */ -int caosdb_entity_entity_set_datatype(caosdb_entity_entity *entity, const char *datatype, - const bool is_ref, const bool is_list); +int caosdb_entity_entity_set_datatype(caosdb_entity_entity *entity, + caosdb_entity_datatype *datatype); int caosdb_entity_entity_set_unit(caosdb_entity_entity *entity, const char *unit); -// TODO(fspreck) replace by more specific setters -int caosdb_entity_entity_set_int_value(caosdb_entity_entity *entity, const int64_t value); -int caosdb_entity_entity_set_double_value(caosdb_entity_entity *entity, const double value); -int caosdb_entity_entity_set_boolean_value(caosdb_entity_entity *entity, const bool value); -int caosdb_entity_entity_set_string_value(caosdb_entity_entity *entity, const char *value); -int caosdb_entity_entity_set_int_list_value(caosdb_entity_entity *entity, const int64_t *value, - const int length); -int caosdb_entity_entity_set_double_list_value(caosdb_entity_entity *entity, const double *value, - const int length); -int caosdb_entity_entity_set_boolean_list_value(caosdb_entity_entity *entity, const bool *value, - const int length); -int caosdb_entity_entity_set_string_list_value(caosdb_entity_entity *entity, const char **value, - const int length); +int caosdb_entity_entity_set_value(caosdb_entity_entity *entity, caosdb_entity_value *value); int caosdb_entity_entity_append_parent(caosdb_entity_entity *entity, caosdb_entity_parent *parent); int caosdb_entity_entity_remove_parent(caosdb_entity_entity *entity, int index); @@ -481,26 +481,11 @@ int caosdb_entity_entity_remove_property(caosdb_entity_entity *entity, int index int caosdb_entity_property_set_id(caosdb_entity_property *property, const char *id); int caosdb_entity_property_set_name(caosdb_entity_property *property, const char *name); -/** - * Set the property's datatype by name, and whether it is a reference or a list. - */ -int caosdb_entity_property_set_datatype(caosdb_entity_property *property, const char *datatype, - const bool is_ref, const bool is_list); +int caosdb_entity_property_set_datatype(caosdb_entity_property *property, + caosdb_entity_datatype *datatype); int caosdb_entity_property_set_importance(caosdb_entity_property *property, const char *importance); int caosdb_entity_property_set_unit(caosdb_entity_property *property, const char *unit); - -int caosdb_entity_property_set_int_value(caosdb_entity_property *property, const int64_t value); -int caosdb_entity_property_set_double_value(caosdb_entity_property *property, const double value); -int caosdb_entity_property_set_boolean_value(caosdb_entity_property *property, const bool value); -int caosdb_entity_property_set_string_value(caosdb_entity_property *property, const char *value); -int caosdb_entity_property_set_int_list_value(caosdb_entity_property *property, - const int64_t *value, const int length); -int caosdb_entity_property_set_double_list_value(caosdb_entity_property *property, - const double *value, const int length); -int caosdb_entity_property_set_boolean_list_value(caosdb_entity_property *property, - const bool *value, const int length); -int caosdb_entity_property_set_string_list_value(caosdb_entity_property *property, - const char **value, const int length); +int caosdb_entity_property_set_value(caosdb_entity_property *property, caosdb_entity_value *value); int caosdb_entity_parent_set_id(caosdb_entity_parent *parent, const char *id); int caosdb_entity_parent_set_name(caosdb_entity_parent *parent, const char *name); diff --git a/src/caosdb/entity.cpp b/src/caosdb/entity.cpp index 167e3ae994b3d2b7beaff07f5b09e37eebdb3060..7f241520ac9e29b7c628eb363698a4d365945ea9 100644 --- a/src/caosdb/entity.cpp +++ b/src/caosdb/entity.cpp @@ -109,6 +109,8 @@ auto Property::SetImportance(Importance importance) -> void { auto Property::SetValue(const Value &value) -> StatusCode { return this->value.CopyFrom(value); } +auto Property::SetValue(const AbstractValue &value) -> StatusCode { return SetValue(Value(value)); } + auto Property::SetValue(const std::string &value) -> StatusCode { return SetValue(Value(value)); } auto Property::SetValue(const char *value) -> StatusCode { return SetValue(Value(value)); } @@ -203,6 +205,8 @@ auto Entity::SetValue(const Value &value) -> StatusCode { return this->value.CopyFrom(value); } +auto Entity::SetValue(const AbstractValue &value) -> StatusCode { return SetValue(Value(value)); } + auto Entity::SetValue(const std::string &value) -> StatusCode { return SetValue(Value(value)); } auto Entity::SetValue(const char *value) -> StatusCode { return SetValue(Value(value)); } diff --git a/src/ccaosdb.cpp b/src/ccaosdb.cpp index 2e2a452729518ea5fb4acf125dea24337dc4a0e2..a18c56d90a2b72449ef7fcb60c0dd3e79603dafc 100644 --- a/src/ccaosdb.cpp +++ b/src/ccaosdb.cpp @@ -23,6 +23,8 @@ #include "caosdb/connection.h" #include "caosdb/constants.h" #include "caosdb/data_type.h" // for DataType, AtomicDat... +#include "caosdb/entity.h" +#include "caosdb/value.h" #include "caosdb/utility.h" #include "caosdb/status_code.h" #include "caosdb/logging.h" @@ -46,12 +48,21 @@ extern "C" { #define WRAPPED_MESSAGE_CAST(name) static_cast<caosdb::entity::Message *>(name->wrapped_message) +#define WRAPPED_DATATYPE_CAST(name) static_cast<caosdb::entity::DataType *>(name->wrapped_datatype) + +#define WRAPPED_VALUE_CAST(name) static_cast<caosdb::entity::AbstractValue *>(name->wrapped_value) + #define ENUM_NAME_FROM_VALUE(arg, etype) \ caosdb::utility::getEnumNameFromValue<caosdb::entity::etype>(arg) #define ENUM_VALUE_FROM_NAME(arg, etype) \ caosdb::utility::getEnumValueFromName<caosdb::entity::etype>(arg) +#define RETURN_ASSIGNEMENT_ERROR_IF_DELETABLE(name) \ + if (name->_deletable) { \ + return caosdb::StatusCode::EXTERN_C_ASSIGNMENT_ERROR; \ + } + /* * Macro for wrapping every function into a try-catch clause. If an exception * occurs, the given StatusCode is being returned. @@ -146,6 +157,58 @@ extern "C" { body_part return 0; \ }) +/** + * Macro for scalar value creators + */ +#define CREATE_VALUE(fname, arg) \ + ERROR_RETURN_CODE(GENERIC_ERROR, \ + int caosdb_entity_create_##fname(caosdb_entity_value *out, arg), { \ + RETURN_ASSIGNEMENT_ERROR_IF_DELETABLE(out) \ + out->wrapped_value = new caosdb::entity::Value(value); \ + out->_deletable = true; \ + return 0; \ + }) +/** + * Macro for list-value creators + */ +#define CREATE_VECTOR_VALUE(fname, type, arg, assign) \ + ERROR_RETURN_CODE( \ + GENERIC_ERROR, \ + int caosdb_entity_create_##fname(caosdb_entity_value *out, arg, const int length), { \ + if (out->_deletable) { \ + return caosdb::StatusCode::EXTERN_C_ASSIGNMENT_ERROR; \ + } \ + std::vector<type> value_vec; \ + for (int i = 0; i < length; i++) { \ + value_vec.push_back(assign); \ + } \ + out->wrapped_value = new caosdb::entity::Value(value_vec); \ + out->_deletable = true; \ + return 0; \ + }) + +/** + * Macro for value is-a functions + */ +#define VALUE_IS(fname, isfunction) \ + ERROR_RETURN_CODE(GENERIC_ERROR, \ + int caosdb_entity_value_is_##fname(caosdb_entity_value *value, bool *out), { \ + auto *wrapped_value = WRAPPED_VALUE_CAST(value); \ + *out = wrapped_value->isfunction(); \ + return 0; \ + }) + +/** + * Macro for some value getters + */ +#define VALUE_GET_AS(fname, getfunction, arg) \ + ERROR_RETURN_CODE(GENERIC_ERROR, \ + int caosdb_entity_value_get_as_##fname(caosdb_entity_value *value, arg), { \ + auto *wrapped_value = WRAPPED_VALUE_CAST(value); \ + *out = wrapped_value->getfunction(); \ + return 0; \ + }) + int caosdb_constants_LIBCAOSDB_VERSION_MAJOR() { return caosdb::LIBCAOSDB_VERSION_MAJOR; } int caosdb_constants_LIBCAOSDB_VERSION_MINOR() { return caosdb::LIBCAOSDB_VERSION_MINOR; } @@ -625,139 +688,125 @@ ERROR_RETURN_CODE(GENERIC_ERROR, int caosdb_entity_delete_parent(caosdb_entity_p return 0; }) -CAOSDB_ENTITY_GET(id, GetId()) ERROR_RETURN_CODE(GENERIC_ERROR, - int caosdb_entity_entity_get_role(caosdb_entity_entity *entity, char **out), { - auto *wrapped_entity = WRAPPED_ENTITY_CAST(entity); - std::string role_str = ENUM_NAME_FROM_VALUE(wrapped_entity->GetRole(), Role); - auto *tmp = (char *)malloc(sizeof(char) * role_str.length() + 1); - strcpy(tmp, role_str.c_str()); - delete[] * out; - *out = tmp; - return 0; - }) -CAOSDB_ENTITY_GET(name, GetName()) -ERROR_RETURN_CODE(GENERIC_ERROR, - int caosdb_entity_entity_get_local_path(caosdb_entity_entity *entity, char **out), + int caosdb_entity_create_atomic_datatype(caosdb_entity_datatype *out, + const char *name), { - auto *wrapped_entity = WRAPPED_ENTITY_CAST(entity); - auto path = wrapped_entity->GetLocalPath().string(); - auto *tmp = (char *)(malloc(sizeof(char) * path.length() + 1)); - strcpy(tmp, path.c_str()); - delete[] * out; - *out = tmp; - return 0; - }) -// CAOSDB_ENTITY_GET(file_path, GetFilePath()) TODO(henrik) -CAOSDB_ENTITY_GET(description, GetDescription()) -ERROR_RETURN_CODE(GENERIC_ERROR, - int caosdb_entity_entity_get_datatype(caosdb_entity_entity *entity, char **name, - bool *is_ref, bool *is_list), - { - auto *wrapped_entity = WRAPPED_ENTITY_CAST(entity); - const auto &datatype = wrapped_entity->GetDataType(); - *is_list = datatype.IsList(); - std::string datatype_name; - if (*is_list) { - const auto &list_datatype = datatype.AsList(); - *is_ref = list_datatype.IsListOfReference(); - if (*is_ref) { - datatype_name = list_datatype.GetReferenceDataType().GetName(); - } else { - datatype_name = - ENUM_NAME_FROM_VALUE(list_datatype.GetAtomicDataType(), AtomicDataType); - } - } else { - *is_ref = datatype.IsReference(); - if (*is_ref) { - datatype_name = datatype.AsReference().GetName(); - } else { - datatype_name = ENUM_NAME_FROM_VALUE(datatype.AsAtomic(), AtomicDataType); - } + RETURN_ASSIGNEMENT_ERROR_IF_DELETABLE(out) + try { + auto enum_value = ENUM_VALUE_FROM_NAME(std::string(name), AtomicDataType); + out->wrapped_datatype = new caosdb::entity::DataType(enum_value); + out->_deletable = true; + return 0; + } catch (const std::out_of_range &exc) { + caosdb::logging::caosdb_log_fatal(CCAOSDB_LOGGER_NAME, exc.what()); + return caosdb::StatusCode::ENUM_MAPPING_ERROR; } - char *tmp = (char *)malloc(sizeof(char) * datatype_name.length() + 1); - strcpy(tmp, datatype_name.c_str()); - delete[] * name; - *name = tmp; - return 0; }) ERROR_RETURN_CODE(GENERIC_ERROR, - int caosdb_entity_entity_get_int_value(caosdb_entity_entity *entity, - int64_t *out), + int caosdb_entity_create_reference_datatype(caosdb_entity_datatype *out, + const char *name), { - auto *wrapped_entity = WRAPPED_ENTITY_CAST(entity); - *out = wrapped_entity->GetValue().AsInteger(); + RETURN_ASSIGNEMENT_ERROR_IF_DELETABLE(out) + out->wrapped_datatype = new caosdb::entity::DataType(std::string(name)); + out->_deletable = true; return 0; }) ERROR_RETURN_CODE(GENERIC_ERROR, - int caosdb_entity_entity_get_double_value(caosdb_entity_entity *entity, - double *out), + int caosdb_entity_create_atomic_list_datatype(caosdb_entity_datatype *out, + const char *name), { - auto *wrapped_entity = WRAPPED_ENTITY_CAST(entity); - *out = wrapped_entity->GetValue().AsDouble(); - return 0; + RETURN_ASSIGNEMENT_ERROR_IF_DELETABLE(out) + try { + auto enum_value = ENUM_VALUE_FROM_NAME(std::string(name), AtomicDataType); + out->wrapped_datatype = + new caosdb::entity::DataType(caosdb::entity::DataType::ListOf(enum_value)); + out->_deletable = true; + return 0; + } catch (const std::out_of_range &exc) { + caosdb::logging::caosdb_log_fatal(CCAOSDB_LOGGER_NAME, exc.what()); + return caosdb::StatusCode::ENUM_MAPPING_ERROR; + } }) ERROR_RETURN_CODE(GENERIC_ERROR, - int caosdb_entity_entity_get_boolean_value(caosdb_entity_entity *entity, - bool *out), + int caosdb_entity_create_reference_list_datatype(caosdb_entity_datatype *out, + const char *name), { - auto *wrapped_entity = WRAPPED_ENTITY_CAST(entity); - *out = wrapped_entity->GetValue().AsBool(); + RETURN_ASSIGNEMENT_ERROR_IF_DELETABLE(out) + out->wrapped_datatype = new caosdb::entity::DataType( + caosdb::entity::DataType::ListOf(std::string(name))); + out->_deletable = true; return 0; }) -CAOSDB_ENTITY_GET(string_value, GetValue().AsString()) +ERROR_RETURN_CODE(GENERIC_ERROR, int caosdb_entity_delete_datatype(caosdb_entity_datatype *out), { + if (out->_deletable) { + delete WRAPPED_DATATYPE_CAST(out); + } + out->_deletable = false; + return 0; +}) + +CREATE_VALUE(int_value, const int64_t value) +CREATE_VALUE(string_value, const char *value) +CREATE_VALUE(double_value, const double value) +CREATE_VALUE(bool_value, const bool value) +CREATE_VECTOR_VALUE(int_vector_value, int64_t, const int64_t *value, value[i]) +CREATE_VECTOR_VALUE(string_vector_value, std::string, const char **value, std::string(value[i])) +CREATE_VECTOR_VALUE(double_vector_value, double, const double *value, value[i]) +CREATE_VECTOR_VALUE(bool_vector_value, bool, const bool *value, value[i]) + +ERROR_RETURN_CODE(GENERIC_ERROR, int caosdb_entity_delete_value(caosdb_entity_value *out), { + if (out->_deletable) { + delete WRAPPED_VALUE_CAST(out); + } + out->_deletable = false; + return 0; +}) + +CAOSDB_ENTITY_GET(id, GetId()) ERROR_RETURN_CODE(GENERIC_ERROR, - int caosdb_entity_entity_get_int_list_value_at(caosdb_entity_entity *entity, - int64_t *out, const int index), - { - auto *wrapped_entity = WRAPPED_ENTITY_CAST(entity); - auto value_list = wrapped_entity->GetValue().AsList(); - *out = value_list[index].AsInteger(); - return 0; - }) -ERROR_RETURN_CODE(GENERIC_ERROR, - int caosdb_entity_entity_get_double_list_value_at(caosdb_entity_entity *entity, - double *out, const int index), - { + int caosdb_entity_entity_get_role(caosdb_entity_entity *entity, char **out), { auto *wrapped_entity = WRAPPED_ENTITY_CAST(entity); - auto value_list = wrapped_entity->GetValue().AsList(); - *out = value_list[index].AsDouble(); + std::string role_str = ENUM_NAME_FROM_VALUE(wrapped_entity->GetRole(), Role); + auto *tmp = (char *)malloc(sizeof(char) * role_str.length() + 1); + strcpy(tmp, role_str.c_str()); + delete[] * out; + *out = tmp; return 0; }) +CAOSDB_ENTITY_GET(name, GetName()) ERROR_RETURN_CODE(GENERIC_ERROR, - int caosdb_entity_entity_get_boolean_list_value_at(caosdb_entity_entity *entity, - bool *out, const int index), + int caosdb_entity_entity_get_local_path(caosdb_entity_entity *entity, char **out), { auto *wrapped_entity = WRAPPED_ENTITY_CAST(entity); - auto value_list = wrapped_entity->GetValue().AsList(); - *out = value_list[index].AsBool(); + auto path = wrapped_entity->GetLocalPath().string(); + auto *tmp = (char *)(malloc(sizeof(char) * path.length() + 1)); + strcpy(tmp, path.c_str()); + delete[] * out; + *out = tmp; return 0; }) +// CAOSDB_ENTITY_GET(file_path, GetFilePath()) TODO(henrik) +CAOSDB_ENTITY_GET(description, GetDescription()) ERROR_RETURN_CODE(GENERIC_ERROR, - int caosdb_entity_entity_get_string_list_value_at(caosdb_entity_entity *entity, - char **out, const int index), + int caosdb_entity_entity_get_datatype(caosdb_entity_entity *entity, + caosdb_entity_datatype *out), { + RETURN_ASSIGNEMENT_ERROR_IF_DELETABLE(out) auto *wrapped_entity = WRAPPED_ENTITY_CAST(entity); - auto value_list = wrapped_entity->GetValue().AsList(); - char *tmp = - (char *)malloc(sizeof(char) * value_list[index].AsString().length() + 1); - strcpy(tmp, value_list[index].AsString().c_str()); - delete[] * out; - *out = tmp; + out->wrapped_datatype = (void *)(&(wrapped_entity->GetDataType())); + out->_deletable = false; return 0; }) - ERROR_RETURN_CODE(GENERIC_ERROR, - int caosdb_entity_entity_get_value_list_length(caosdb_entity_entity *entity, - int *out), + int caosdb_entity_entity_get_value(caosdb_entity_entity *entity, + caosdb_entity_value *out), { + RETURN_ASSIGNEMENT_ERROR_IF_DELETABLE(out) auto *wrapped_entity = WRAPPED_ENTITY_CAST(entity); - if (wrapped_entity->GetValue().IsList()) { - *out = wrapped_entity->GetValue().AsList().size(); - } else { - *out = 0; - } + out->wrapped_value = (void *)(&(wrapped_entity->GetValue())); + out->_deletable = false; return 0; }) @@ -901,140 +950,148 @@ ERROR_RETURN_CODE(GENERIC_ERROR, *out = tmp; return 0; }) - ERROR_RETURN_CODE(GENERIC_ERROR, int caosdb_entity_property_get_datatype(caosdb_entity_property *property, - char **name, bool *is_ref, bool *is_list), + caosdb_entity_datatype *out), { + RETURN_ASSIGNEMENT_ERROR_IF_DELETABLE(out) auto *wrapped_property = WRAPPED_PROPERTY_CAST(property); - const auto &datatype = wrapped_property->GetDataType(); - *is_list = datatype.IsList(); - std::string datatype_name; - if (*is_list) { - const auto &list_datatype = datatype.AsList(); - *is_ref = list_datatype.IsListOfReference(); - if (*is_ref) { - datatype_name = list_datatype.GetReferenceDataType().GetName(); - } else { - datatype_name = - ENUM_NAME_FROM_VALUE(list_datatype.GetAtomicDataType(), AtomicDataType); - } - } else { - *is_ref = datatype.IsReference(); - if (*is_ref) { - datatype_name = datatype.AsReference().GetName(); - } else { - datatype_name = ENUM_NAME_FROM_VALUE(datatype.AsAtomic(), AtomicDataType); - } - } - char *tmp = (char *)malloc(sizeof(char) * datatype_name.length() + 1); - strcpy(tmp, datatype_name.c_str()); - delete[] * name; - *name = tmp; + out->wrapped_datatype = (void *)(&(wrapped_property->GetDataType())); + out->_deletable = false; return 0; }) - -CAOSDB_PROPERTY_GET(unit, GetUnit()) - ERROR_RETURN_CODE(GENERIC_ERROR, - int caosdb_entity_property_get_int_value(caosdb_entity_property *property, - int64_t *out), + int caosdb_entity_property_get_value(caosdb_entity_property *property, + caosdb_entity_value *out), { + RETURN_ASSIGNEMENT_ERROR_IF_DELETABLE(out) auto *wrapped_property = WRAPPED_PROPERTY_CAST(property); - *out = wrapped_property->GetValue().AsInteger(); + out->wrapped_value = (void *)(&(wrapped_property->GetValue())); + out->_deletable = false; return 0; }) +CAOSDB_PROPERTY_GET(unit, GetUnit()) + ERROR_RETURN_CODE(GENERIC_ERROR, - int caosdb_entity_property_get_double_value(caosdb_entity_property *property, - double *out), - { - auto *wrapped_property = WRAPPED_PROPERTY_CAST(property); - *out = wrapped_property->GetValue().AsDouble(); + int caosdb_entity_message_get_code(caosdb_entity_message *message, int *out), { + auto *wrapped_message = + static_cast<caosdb::entity::Message *>(message->wrapped_message); + *out = wrapped_message->GetCode(); return 0; }) + +ERROR_RETURN_CODE( + GENERIC_ERROR, + int caosdb_entity_message_get_description(caosdb_entity_message *message, char **out), { + auto *wrapped_message = static_cast<caosdb::entity::Message *>(message->wrapped_message); + auto *tmp = (char *)malloc(sizeof(char) * wrapped_message->GetDescription().length() + 1); + strcpy(tmp, wrapped_message->GetDescription().c_str()); + delete[] * out; + *out = tmp; + return 0; + }) + ERROR_RETURN_CODE(GENERIC_ERROR, - int caosdb_entity_property_get_boolean_value(caosdb_entity_property *property, - bool *out), + int caosdb_entity_datatype_is_atomic(caosdb_entity_datatype *datatype, bool *out), { - auto *wrapped_property = WRAPPED_PROPERTY_CAST(property); - *out = wrapped_property->GetValue().AsBool(); + auto *wrapped_datatype = WRAPPED_DATATYPE_CAST(datatype); + *out = wrapped_datatype->IsAtomic(); return 0; }) -CAOSDB_PROPERTY_GET(string_value, GetValue().AsString()) - ERROR_RETURN_CODE(GENERIC_ERROR, - int caosdb_entity_property_get_int_list_value_at(caosdb_entity_property *property, - int64_t *out, const int index), + int caosdb_entity_datatype_is_reference(caosdb_entity_datatype *datatype, + bool *out), { - auto *wrapped_property = WRAPPED_PROPERTY_CAST(property); - auto value_list = wrapped_property->GetValue().AsList(); - *out = value_list[index].AsInteger(); + auto *wrapped_datatype = WRAPPED_DATATYPE_CAST(datatype); + *out = wrapped_datatype->IsReference(); return 0; }) ERROR_RETURN_CODE(GENERIC_ERROR, - int caosdb_entity_property_get_double_list_value_at( - caosdb_entity_property *property, double *out, const int index), + int caosdb_entity_datatype_is_list_of_atomic(caosdb_entity_datatype *datatype, + bool *out), { - auto *wrapped_property = WRAPPED_PROPERTY_CAST(property); - auto value_list = wrapped_property->GetValue().AsList(); - *out = value_list[index].AsDouble(); + auto *wrapped_datatype = WRAPPED_DATATYPE_CAST(datatype); + if (wrapped_datatype->IsList()) { + const auto &list_datatype = wrapped_datatype->GetAsList(); + *out = list_datatype.IsListOfAtomic(); + } else { + *out = false; + } return 0; }) ERROR_RETURN_CODE(GENERIC_ERROR, - int caosdb_entity_property_get_boolean_list_value_at( - caosdb_entity_property *property, bool *out, const int index), + int caosdb_entity_datatype_is_list_of_reference(caosdb_entity_datatype *datatype, + bool *out), { - auto *wrapped_property = WRAPPED_PROPERTY_CAST(property); - auto value_list = wrapped_property->GetValue().AsList(); - *out = value_list[index].AsBool(); + auto *wrapped_datatype = WRAPPED_DATATYPE_CAST(datatype); + if (wrapped_datatype->IsList()) { + const auto &list_datatype = wrapped_datatype->GetAsList(); + *out = list_datatype.IsListOfReference(); + } else { + *out = false; + } return 0; }) +ERROR_RETURN_CODE( + GENERIC_ERROR, + int caosdb_entity_datatype_get_datatype_name(caosdb_entity_datatype *datatype, char **out), { + auto *wrapped_datatype = WRAPPED_DATATYPE_CAST(datatype); + std::string datatype_name; + if (wrapped_datatype->IsList()) { + const auto &list_datatype = wrapped_datatype->GetAsList(); + if (list_datatype.IsListOfAtomic()) { + datatype_name = ENUM_NAME_FROM_VALUE(list_datatype.GetAtomicDataType(), AtomicDataType); + } else { + datatype_name = list_datatype.GetReferenceDataType().GetName(); + } + } else { + if (wrapped_datatype->IsAtomic()) { + datatype_name = ENUM_NAME_FROM_VALUE(wrapped_datatype->GetAsAtomic(), AtomicDataType); + } else { + datatype_name = wrapped_datatype->GetAsReference().GetName(); + } + } + char *tmp = (char *)malloc(sizeof(char) * datatype_name.length() + 1); + strcpy(tmp, datatype_name.c_str()); + delete[] * out; + *out = tmp; + return 0; + }) + +VALUE_IS(null, IsNull) +VALUE_IS(string, IsString) +VALUE_IS(double, IsDouble) +VALUE_IS(integer, IsInt64) +VALUE_IS(bool, IsBool) +VALUE_IS(vector, IsVector) + ERROR_RETURN_CODE(GENERIC_ERROR, - int caosdb_entity_property_get_string_list_value_at( - caosdb_entity_property *property, char **out, const int index), - { - auto *wrapped_property = WRAPPED_PROPERTY_CAST(property); - auto value_list = wrapped_property->GetValue().AsList(); + int caosdb_entity_value_get_as_string(caosdb_entity_value *value, char **out), { + auto *wrapped_value = WRAPPED_VALUE_CAST(value); auto *tmp = - (char *)malloc(sizeof(char) * value_list[index].AsString().length() + 1); - strcpy(tmp, value_list[index].AsString().c_str()); + (char *)malloc(sizeof(char) * wrapped_value->GetAsString().length() + 1); + strcpy(tmp, wrapped_value->GetAsString().c_str()); delete[] * out; *out = tmp; return 0; }) - +VALUE_GET_AS(double, GetAsDouble, double *out) +VALUE_GET_AS(integer, GetAsInt64, int64_t *out) +VALUE_GET_AS(bool, GetAsBool, bool *out) +VALUE_GET_AS(vector_size, GetAsVector().size, int *out) ERROR_RETURN_CODE(GENERIC_ERROR, - int caosdb_entity_property_get_value_list_length(caosdb_entity_property *property, - int *out), + int caosdb_entity_value_get_as_vector_at(caosdb_entity_value *value, + caosdb_entity_value *out, + const int index), { - auto *wrapped_property = WRAPPED_PROPERTY_CAST(property); - if (wrapped_property->GetValue().IsList()) { - *out = wrapped_property->GetValue().AsList().size(); - } else { - *out = 0; + if (out->_deletable) { + return caosdb::StatusCode::EXTERN_C_ASSIGNMENT_ERROR; } + auto *wrapped_value = WRAPPED_VALUE_CAST(value); + out->wrapped_value = (void *)(&(wrapped_value->GetAsVector().at(index))); + out->_deletable = false; return 0; }) - -ERROR_RETURN_CODE(GENERIC_ERROR, - int caosdb_entity_message_get_code(caosdb_entity_message *message, int *out), { - auto *wrapped_message = - static_cast<caosdb::entity::Message *>(message->wrapped_message); - *out = wrapped_message->GetCode(); - return 0; - }) - -ERROR_RETURN_CODE( - GENERIC_ERROR, - int caosdb_entity_message_get_description(caosdb_entity_message *message, char **out), { - auto *wrapped_message = static_cast<caosdb::entity::Message *>(message->wrapped_message); - auto *tmp = (char *)malloc(sizeof(char) * wrapped_message->GetDescription().length() + 1); - strcpy(tmp, wrapped_message->GetDescription().c_str()); - delete[] * out; - *out = tmp; - return 0; - }) - ERROR_RETURN_CODE(GENERIC_ERROR, int caosdb_entity_entity_set_role(caosdb_entity_entity *entity, const char *role), { @@ -1054,129 +1111,24 @@ CAOSDB_ENTITY_SET(local_path, local_path, CAOSDB_ENTITY_SET(file_path, file_path, wrapped_entity->SetFilePath(std::string(file_path));) CAOSDB_ENTITY_SET(description, description, wrapped_entity->SetDescription(std::string(description));) +CAOSDB_ENTITY_SET(unit, unit, wrapped_entity->SetUnit(std::string(unit));) ERROR_RETURN_CODE(GENERIC_ERROR, int caosdb_entity_entity_set_datatype(caosdb_entity_entity *entity, - const char *datatype, const bool is_ref, - const bool is_list), + caosdb_entity_datatype *datatype), { auto *wrapped_entity = WRAPPED_ENTITY_CAST(entity); - if (is_ref) { - // Refernce datatype with name of reference - wrapped_entity->SetDataType(std::string(datatype), is_list); - return 0; - } else { - // Atomic datatype so get from enum - try { - auto enum_value = - ENUM_VALUE_FROM_NAME(std::string(datatype), AtomicDataType); - wrapped_entity->SetDataType(enum_value, is_list); - return 0; - } catch (const std::out_of_range &exc) { - caosdb::logging::caosdb_log_fatal(CCAOSDB_LOGGER_NAME, exc.what()); - return caosdb::StatusCode::ENUM_MAPPING_ERROR; - } - } - }) -CAOSDB_ENTITY_SET(unit, unit, wrapped_entity->SetUnit(std::string(unit));) + auto *wrapped_datatype = WRAPPED_DATATYPE_CAST(datatype); -ERROR_RETURN_CODE(GENERIC_ERROR, - int caosdb_entity_entity_set_int_value(caosdb_entity_entity *entity, - const int64_t value), - { - auto *wrapped_entity = - static_cast<caosdb::entity::Entity *>(entity->wrapped_entity); - wrapped_entity->SetValue(value); - return 0; + return wrapped_entity->SetDataType(*wrapped_datatype); }) - ERROR_RETURN_CODE(GENERIC_ERROR, - int caosdb_entity_entity_set_double_value(caosdb_entity_entity *entity, - const double value), + int caosdb_entity_entity_set_value(caosdb_entity_entity *entity, + caosdb_entity_value *value), { - auto *wrapped_entity = - static_cast<caosdb::entity::Entity *>(entity->wrapped_entity); - wrapped_entity->SetValue(value); - return 0; - }) - -ERROR_RETURN_CODE(GENERIC_ERROR, - int caosdb_entity_entity_set_boolean_value(caosdb_entity_entity *entity, - const bool value), - { - auto *wrapped_entity = - static_cast<caosdb::entity::Entity *>(entity->wrapped_entity); - wrapped_entity->SetValue(value); - return 0; - }) - -ERROR_RETURN_CODE(GENERIC_ERROR, - int caosdb_entity_entity_set_string_value(caosdb_entity_entity *entity, - const char *value), - { - auto *wrapped_entity = - static_cast<caosdb::entity::Entity *>(entity->wrapped_entity); - wrapped_entity->SetValue(std::string(value)); - return 0; - }) - -ERROR_RETURN_CODE(GENERIC_ERROR, - int caosdb_entity_entity_set_int_list_value(caosdb_entity_entity *entity, - const int64_t *value, - const int length), - { - auto *wrapped_entity = - static_cast<caosdb::entity::Entity *>(entity->wrapped_entity); - std::vector<int64_t> value_list; - for (int i = 0; i < length; i++) { - value_list.push_back(value[i]); - } - wrapped_entity->SetValue(value_list); - return 0; - }) - -ERROR_RETURN_CODE(GENERIC_ERROR, - int caosdb_entity_entity_set_double_list_value(caosdb_entity_entity *entity, - const double *value, - const int length), - { - auto *wrapped_entity = - static_cast<caosdb::entity::Entity *>(entity->wrapped_entity); - std::vector<double> value_list; - for (int i = 0; i < length; i++) { - value_list.push_back(value[i]); - } - wrapped_entity->SetValue(value_list); - return 0; - }) - -ERROR_RETURN_CODE(GENERIC_ERROR, - int caosdb_entity_entity_set_boolean_list_value(caosdb_entity_entity *entity, - const bool *value, - const int length), - { - auto *wrapped_entity = - static_cast<caosdb::entity::Entity *>(entity->wrapped_entity); - std::vector<bool> value_list; - for (int i = 0; i < length; i++) { - value_list.push_back(value[i]); - } - wrapped_entity->SetValue(value_list); - return 0; - }) + auto *wrapped_entity = WRAPPED_ENTITY_CAST(entity); + auto *wrapped_value = WRAPPED_VALUE_CAST(value); -ERROR_RETURN_CODE(GENERIC_ERROR, - int caosdb_entity_entity_set_string_list_value(caosdb_entity_entity *entity, - const char **value, - const int length), - { - auto *wrapped_entity = - static_cast<caosdb::entity::Entity *>(entity->wrapped_entity); - std::vector<std::string> value_list; - for (int i = 0; i < length; i++) { - value_list.push_back(std::string(value[i])); - } - wrapped_entity->SetValue(value_list); - return 0; + return wrapped_entity->SetValue(*wrapped_value); }) ERROR_RETURN_CODE(GENERIC_ERROR, @@ -1224,29 +1176,23 @@ CAOSDB_PARENT_SET(name, name, wrapped_parent->SetName(std::string(name));) CAOSDB_PROPERTY_SET(name, name, wrapped_property->SetName(std::string(name));) CAOSDB_PROPERTY_SET(id, id, wrapped_property->SetId(std::string(id));) - ERROR_RETURN_CODE(GENERIC_ERROR, int caosdb_entity_property_set_datatype(caosdb_entity_property *property, - const char *datatype, const bool is_ref, - const bool is_list), + caosdb_entity_datatype *datatype), { auto *wrapped_property = WRAPPED_PROPERTY_CAST(property); - if (is_ref) { - // Refernce datatype with name of reference - wrapped_property->SetDataType(std::string(datatype), is_list); - return 0; - } else { - // Atomic datatype so get from enum - try { - auto enum_value = - ENUM_VALUE_FROM_NAME(std::string(datatype), AtomicDataType); - wrapped_property->SetDataType(enum_value, is_list); - return 0; - } catch (const std::out_of_range &exc) { - caosdb::logging::caosdb_log_fatal(CCAOSDB_LOGGER_NAME, exc.what()); - return caosdb::StatusCode::ENUM_MAPPING_ERROR; - } - } + auto *wrapped_datatype = WRAPPED_DATATYPE_CAST(datatype); + + return wrapped_property->SetDataType(*wrapped_datatype); + }) +ERROR_RETURN_CODE(GENERIC_ERROR, + int caosdb_entity_property_set_value(caosdb_entity_property *property, + caosdb_entity_value *value), + { + auto *wrapped_property = WRAPPED_PROPERTY_CAST(property); + auto *wrapped_value = WRAPPED_VALUE_CAST(value); + + return wrapped_property->SetValue(*wrapped_value); }) ERROR_RETURN_CODE(GENERIC_ERROR, @@ -1265,103 +1211,4 @@ ERROR_RETURN_CODE(GENERIC_ERROR, }) CAOSDB_PROPERTY_SET(unit, unit, wrapped_property->SetUnit(std::string(unit));) - -ERROR_RETURN_CODE(GENERIC_ERROR, - int caosdb_entity_property_set_int_value(caosdb_entity_property *property, - const int64_t value), - { - auto *wrapped_property = - static_cast<caosdb::entity::Property *>(property->wrapped_property); - wrapped_property->SetValue(value); - return 0; - }) - -ERROR_RETURN_CODE(GENERIC_ERROR, - int caosdb_entity_property_set_double_value(caosdb_entity_property *property, - const double value), - { - auto *wrapped_property = - static_cast<caosdb::entity::Property *>(property->wrapped_property); - wrapped_property->SetValue(value); - return 0; - }) - -ERROR_RETURN_CODE(GENERIC_ERROR, - int caosdb_entity_property_set_boolean_value(caosdb_entity_property *property, - const bool value), - { - auto *wrapped_property = - static_cast<caosdb::entity::Property *>(property->wrapped_property); - wrapped_property->SetValue(value); - return 0; - }) - -ERROR_RETURN_CODE(GENERIC_ERROR, - int caosdb_entity_property_set_string_value(caosdb_entity_property *property, - const char *value), - { - auto *wrapped_property = - static_cast<caosdb::entity::Property *>(property->wrapped_property); - wrapped_property->SetValue(std::string(value)); - return 0; - }) - -ERROR_RETURN_CODE(GENERIC_ERROR, - int caosdb_entity_property_set_int_list_value(caosdb_entity_property *property, - const int64_t *value, - const int length), - { - auto *wrapped_property = - static_cast<caosdb::entity::Property *>(property->wrapped_property); - std::vector<int64_t> value_list; - for (int i = 0; i < length; i++) { - value_list.push_back(value[i]); - } - wrapped_property->SetValue(value_list); - return 0; - }) - -ERROR_RETURN_CODE(GENERIC_ERROR, - int caosdb_entity_property_set_double_list_value(caosdb_entity_property *property, - const double *value, - const int length), - { - auto *wrapped_property = - static_cast<caosdb::entity::Property *>(property->wrapped_property); - std::vector<double> value_list; - for (int i = 0; i < length; i++) { - value_list.push_back(value[i]); - } - wrapped_property->SetValue(value_list); - return 0; - }) - -ERROR_RETURN_CODE(GENERIC_ERROR, - int caosdb_entity_property_set_boolean_list_value( - caosdb_entity_property *property, const bool *value, const int length), - { - auto *wrapped_property = - static_cast<caosdb::entity::Property *>(property->wrapped_property); - std::vector<bool> value_list; - for (int i = 0; i < length; i++) { - value_list.push_back(value[i]); - } - wrapped_property->SetValue(value_list); - return 0; - }) - -ERROR_RETURN_CODE(GENERIC_ERROR, - int caosdb_entity_property_set_string_list_value(caosdb_entity_property *property, - const char **value, - const int length), - { - auto *wrapped_property = - static_cast<caosdb::entity::Property *>(property->wrapped_property); - std::vector<std::string> value_list; - for (int i = 0; i < length; i++) { - value_list.push_back(std::string(value[i])); - } - wrapped_property->SetValue(value_list); - return 0; - }) } diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 6049d0fa369c8e6c2a95bec554c0946e5a2b4aa3..aefe6846d23f2cc3a145cbf6158101e7e1bb3df4 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -61,6 +61,7 @@ foreach (i RANGE "${len_test_cases}") target_include_directories(${test_case_name} PUBLIC ${CMAKE_CURRENT_BINARY_DIR}) if(_LINTING) + message(STATUS "linting for tests: ${_CMAKE_CXX_INCLUDE_WHAT_YOU_USE}") set_target_properties(${test_case_name} PROPERTIES CXX_CLANG_TIDY "${_CMAKE_CXX_CLANG_TIDY};${_CMAKE_CXX_CLANG_TIDY_TEST_CHECKS}" diff --git a/test/test_ccaosdb.cpp b/test/test_ccaosdb.cpp index cbf595f821f45807d8dd780cadd94bde47544fe8..361b0918060e46cf71b435e519b3a7ec20b1ee46 100644 --- a/test/test_ccaosdb.cpp +++ b/test/test_ccaosdb.cpp @@ -127,6 +127,255 @@ TEST_F(test_ccaosdb, test_query) { EXPECT_EQ(return_code, 0); } +TEST_F(test_ccaosdb, test_datatype) { + + caosdb_entity_datatype atomic; + // check that this fails + int return_code(caosdb_entity_create_atomic_datatype(&atomic, "some type")); + EXPECT_EQ(return_code, caosdb::StatusCode::ENUM_MAPPING_ERROR); + + return_code = caosdb_entity_create_atomic_datatype(&atomic, "INTEGER"); + EXPECT_EQ(return_code, 0); + + caosdb_entity_datatype reference; + return_code = caosdb_entity_create_reference_datatype(&reference, "MyType"); + EXPECT_EQ(return_code, 0); + + caosdb_entity_datatype list_of_atomics; + return_code = caosdb_entity_create_atomic_list_datatype(&list_of_atomics, "DATETIME"); + EXPECT_EQ(return_code, 0); + + caosdb_entity_datatype list_of_references; + return_code = caosdb_entity_create_reference_list_datatype(&list_of_references, "MyType"); + EXPECT_EQ(return_code, 0); + + bool is_a(false); + return_code = caosdb_entity_datatype_is_atomic(&atomic, &is_a); + EXPECT_EQ(return_code, 0); + EXPECT_TRUE(is_a); + return_code = caosdb_entity_datatype_is_reference(&atomic, &is_a); + EXPECT_EQ(return_code, 0); + EXPECT_FALSE(is_a); + return_code = caosdb_entity_datatype_is_list_of_atomic(&atomic, &is_a); + EXPECT_EQ(return_code, 0); + EXPECT_FALSE(is_a); + return_code = caosdb_entity_datatype_is_list_of_reference(&atomic, &is_a); + EXPECT_EQ(return_code, 0); + EXPECT_FALSE(is_a); + + return_code = caosdb_entity_datatype_is_atomic(&reference, &is_a); + EXPECT_EQ(return_code, 0); + EXPECT_FALSE(is_a); + return_code = caosdb_entity_datatype_is_reference(&reference, &is_a); + EXPECT_EQ(return_code, 0); + EXPECT_TRUE(is_a); + return_code = caosdb_entity_datatype_is_list_of_atomic(&reference, &is_a); + EXPECT_EQ(return_code, 0); + EXPECT_FALSE(is_a); + return_code = caosdb_entity_datatype_is_list_of_reference(&reference, &is_a); + EXPECT_EQ(return_code, 0); + EXPECT_FALSE(is_a); + + return_code = caosdb_entity_datatype_is_atomic(&list_of_atomics, &is_a); + EXPECT_EQ(return_code, 0); + EXPECT_FALSE(is_a); + return_code = caosdb_entity_datatype_is_reference(&list_of_atomics, &is_a); + EXPECT_EQ(return_code, 0); + EXPECT_FALSE(is_a); + return_code = caosdb_entity_datatype_is_list_of_atomic(&list_of_atomics, &is_a); + EXPECT_EQ(return_code, 0); + EXPECT_TRUE(is_a); + return_code = caosdb_entity_datatype_is_list_of_reference(&list_of_atomics, &is_a); + EXPECT_EQ(return_code, 0); + EXPECT_FALSE(is_a); + + return_code = caosdb_entity_datatype_is_atomic(&list_of_references, &is_a); + EXPECT_EQ(return_code, 0); + EXPECT_FALSE(is_a); + return_code = caosdb_entity_datatype_is_reference(&list_of_references, &is_a); + EXPECT_EQ(return_code, 0); + EXPECT_FALSE(is_a); + return_code = caosdb_entity_datatype_is_list_of_atomic(&list_of_references, &is_a); + EXPECT_EQ(return_code, 0); + EXPECT_FALSE(is_a); + return_code = caosdb_entity_datatype_is_list_of_reference(&list_of_references, &is_a); + EXPECT_EQ(return_code, 0); + EXPECT_TRUE(is_a); + + char *name = nullptr; // NOLINT + return_code = caosdb_entity_datatype_get_datatype_name(&atomic, &name); + EXPECT_EQ(return_code, 0); + EXPECT_STREQ(name, "INTEGER"); + + return_code = caosdb_entity_datatype_get_datatype_name(&reference, &name); + EXPECT_EQ(return_code, 0); + EXPECT_STREQ(name, "MyType"); + + return_code = caosdb_entity_datatype_get_datatype_name(&list_of_atomics, &name); + EXPECT_EQ(return_code, 0); + EXPECT_STREQ(name, "DATETIME"); + + return_code = caosdb_entity_datatype_get_datatype_name(&list_of_references, &name); + EXPECT_EQ(return_code, 0); + EXPECT_STREQ(name, "MyType"); + + return_code = caosdb_entity_delete_datatype(&atomic); + EXPECT_EQ(return_code, 0); + return_code = caosdb_entity_delete_datatype(&reference); + EXPECT_EQ(return_code, 0); + return_code = caosdb_entity_delete_datatype(&list_of_atomics); + EXPECT_EQ(return_code, 0); + return_code = caosdb_entity_delete_datatype(&list_of_references); + EXPECT_EQ(return_code, 0); +} + +TEST_F(test_ccaosdb, test_value) { + + caosdb_entity_value string_value; + int return_code(caosdb_entity_create_string_value(&string_value, "value")); + EXPECT_EQ(return_code, 0); + + caosdb_entity_value int_value; + return_code = caosdb_entity_create_int_value(&int_value, 27); + EXPECT_EQ(return_code, 0); + + caosdb_entity_value bool_value; + return_code = caosdb_entity_create_bool_value(&bool_value, true); + EXPECT_EQ(return_code, 0); + + caosdb_entity_value double_value; + return_code = caosdb_entity_create_double_value(&double_value, 2.7); + EXPECT_EQ(return_code, 0); + + caosdb_entity_value string_vector_value; + const char *string_values[] = {"a", "b", "c"}; // NOLINT + return_code = caosdb_entity_create_string_vector_value(&string_vector_value, string_values, 3); + EXPECT_EQ(return_code, 0); + + caosdb_entity_value int_vector_value; + const int64_t int_values[] = {1, 2, 3}; // NOLINT + return_code = caosdb_entity_create_int_vector_value(&int_vector_value, int_values, 3); + EXPECT_EQ(return_code, 0); + + caosdb_entity_value double_vector_value; + const double double_values[] = {1.1, 2.2, 3.3}; // NOLINT + return_code = caosdb_entity_create_double_vector_value(&double_vector_value, double_values, 3); + EXPECT_EQ(return_code, 0); + + caosdb_entity_value bool_vector_value; + const bool bool_values[] = {true, false, false}; // NOLINT + return_code = caosdb_entity_create_bool_vector_value(&bool_vector_value, bool_values, 3); + EXPECT_EQ(return_code, 0); + + // One thorough check, afterwards only the ones that should be true + bool is_a(false); + return_code = caosdb_entity_value_is_null(&string_value, &is_a); + EXPECT_EQ(return_code, 0); + EXPECT_FALSE(is_a); + return_code = caosdb_entity_value_is_string(&string_value, &is_a); + EXPECT_EQ(return_code, 0); + EXPECT_TRUE(is_a); + return_code = caosdb_entity_value_is_double(&string_value, &is_a); + EXPECT_EQ(return_code, 0); + EXPECT_FALSE(is_a); + return_code = caosdb_entity_value_is_integer(&string_value, &is_a); + EXPECT_EQ(return_code, 0); + EXPECT_FALSE(is_a); + return_code = caosdb_entity_value_is_bool(&string_value, &is_a); + EXPECT_EQ(return_code, 0); + EXPECT_FALSE(is_a); + return_code = caosdb_entity_value_is_vector(&string_value, &is_a); + EXPECT_EQ(return_code, 0); + EXPECT_FALSE(is_a); + + caosdb_entity_value_is_integer(&int_value, &is_a); + EXPECT_TRUE(is_a); + + caosdb_entity_value_is_bool(&bool_value, &is_a); + EXPECT_TRUE(is_a); + + caosdb_entity_value_is_double(&double_value, &is_a); + EXPECT_TRUE(is_a); + + caosdb_entity_value_is_vector(&string_vector_value, &is_a); + EXPECT_TRUE(is_a); + + caosdb_entity_value_is_vector(&int_vector_value, &is_a); + EXPECT_TRUE(is_a); + + caosdb_entity_value_is_vector(&double_vector_value, &is_a); + EXPECT_TRUE(is_a); + + caosdb_entity_value_is_vector(&bool_vector_value, &is_a); + EXPECT_TRUE(is_a); + + char *out_string = nullptr; // NOLINT + return_code = caosdb_entity_value_get_as_string(&string_value, &out_string); + EXPECT_EQ(return_code, 0); + EXPECT_STREQ(out_string, "value"); + + int64_t out_int(0); + return_code = caosdb_entity_value_get_as_integer(&int_value, &out_int); + EXPECT_EQ(return_code, 0); + EXPECT_EQ(out_int, 27); + + bool out_bool(false); + return_code = caosdb_entity_value_get_as_bool(&bool_value, &out_bool); + EXPECT_EQ(return_code, 0); + EXPECT_TRUE(out_bool); + + double out_double(0); + return_code = caosdb_entity_value_get_as_double(&double_value, &out_double); + EXPECT_EQ(return_code, 0); + EXPECT_EQ(out_double, 2.7); + + int list_length(0); + return_code = caosdb_entity_value_get_as_vector_size(&string_vector_value, &list_length); + EXPECT_EQ(return_code, 0); + EXPECT_EQ(list_length, 3); + return_code = caosdb_entity_value_get_as_vector_size(&int_vector_value, &list_length); + EXPECT_EQ(return_code, 0); + EXPECT_EQ(list_length, 3); + return_code = caosdb_entity_value_get_as_vector_size(&double_vector_value, &list_length); + EXPECT_EQ(return_code, 0); + EXPECT_EQ(list_length, 3); + return_code = caosdb_entity_value_get_as_vector_size(&bool_vector_value, &list_length); + EXPECT_EQ(return_code, 0); + EXPECT_EQ(list_length, 3); + + // Only check for one, rest should be covered by this + scalar values + caosdb_entity_value out_val; + return_code = caosdb_entity_value_get_as_vector_at(&string_vector_value, &out_val, 0); + EXPECT_EQ(return_code, 0); + caosdb_entity_value_get_as_string(&out_val, &out_string); + EXPECT_STREQ(out_string, "a"); + return_code = caosdb_entity_value_get_as_vector_at(&string_vector_value, &out_val, 1); + EXPECT_EQ(return_code, 0); + caosdb_entity_value_get_as_string(&out_val, &out_string); + EXPECT_STREQ(out_string, "b"); + return_code = caosdb_entity_value_get_as_vector_at(&string_vector_value, &out_val, 2); + EXPECT_EQ(return_code, 0); + caosdb_entity_value_get_as_string(&out_val, &out_string); + EXPECT_STREQ(out_string, "c"); + + return_code = caosdb_entity_delete_value(&string_value); + EXPECT_EQ(return_code, 0); + return_code = caosdb_entity_delete_value(&int_value); + EXPECT_EQ(return_code, 0); + return_code = caosdb_entity_delete_value(&bool_value); + EXPECT_EQ(return_code, 0); + return_code = caosdb_entity_delete_value(&double_value); + EXPECT_EQ(return_code, 0); + return_code = caosdb_entity_delete_value(&string_vector_value); + EXPECT_EQ(return_code, 0); + return_code = caosdb_entity_delete_value(&int_vector_value); + EXPECT_EQ(return_code, 0); + return_code = caosdb_entity_delete_value(&double_vector_value); + EXPECT_EQ(return_code, 0); + return_code = caosdb_entity_delete_value(&bool_vector_value); + EXPECT_EQ(return_code, 0); +} + TEST_F(test_ccaosdb, test_entity) { caosdb_entity_entity entity; @@ -174,32 +423,94 @@ TEST_F(test_ccaosdb, test_entity) { caosdb_entity_entity_get_description(&entity, &out); EXPECT_EQ(strcmp(out, "The length of an object"), 0); - caosdb_entity_entity_set_datatype(&entity, "DOUBLE", false, false); - bool is_list[] = {false}; // NOLINT - bool is_ref[] = {false}; // NOLINT - caosdb_entity_entity_get_datatype(&entity, &out, is_ref, is_list); - EXPECT_EQ(strcmp(out, "DOUBLE"), 0); - EXPECT_FALSE(*is_list); - EXPECT_FALSE(*is_ref); + caosdb_entity_datatype in_type; + caosdb_entity_create_atomic_datatype(&in_type, "DOUBLE"); + caosdb_entity_entity_set_datatype(&entity, &in_type); + + // verify that this doesn't work ... + return_code = caosdb_entity_entity_get_datatype(&entity, &in_type); + EXPECT_EQ(return_code, caosdb::StatusCode::EXTERN_C_ASSIGNMENT_ERROR); + caosdb_entity_datatype out_type; + // ... but does with a clean property + return_code = caosdb_entity_entity_get_datatype(&entity, &out_type); + EXPECT_EQ(return_code, 0); + bool is_a(false); + return_code = caosdb_entity_datatype_is_atomic(&out_type, &is_a); + EXPECT_EQ(return_code, 0); + EXPECT_TRUE(is_a); + return_code = caosdb_entity_datatype_is_reference(&out_type, &is_a); + EXPECT_EQ(return_code, 0); + EXPECT_FALSE(is_a); + return_code = caosdb_entity_datatype_is_list_of_atomic(&out_type, &is_a); + EXPECT_EQ(return_code, 0); + EXPECT_FALSE(is_a); + return_code = caosdb_entity_datatype_is_list_of_reference(&out_type, &is_a); + EXPECT_EQ(return_code, 0); + EXPECT_FALSE(is_a); + + caosdb_entity_datatype_get_datatype_name(&out_type, &out); + EXPECT_STREQ(out, "DOUBLE"); + + caosdb_entity_value in_value; + return_code = caosdb_entity_create_double_value(&in_value, 5.0); + EXPECT_EQ(return_code, 0); + return_code = caosdb_entity_entity_set_value(&entity, &in_value); + EXPECT_EQ(return_code, 0); + + caosdb_entity_value out_value; + return_code = caosdb_entity_entity_get_value(&entity, &out_value); + EXPECT_EQ(return_code, 0); + + caosdb_entity_value_is_double(&out_value, &is_a); + EXPECT_TRUE(is_a); + caosdb_entity_value_is_null(&out_value, &is_a); + EXPECT_FALSE(is_a); + caosdb_entity_value_is_string(&out_value, &is_a); + EXPECT_FALSE(is_a); + caosdb_entity_value_is_bool(&out_value, &is_a); + EXPECT_FALSE(is_a); + caosdb_entity_value_is_integer(&out_value, &is_a); + EXPECT_FALSE(is_a); + caosdb_entity_value_is_vector(&out_value, &is_a); + EXPECT_FALSE(is_a); - caosdb_entity_entity_set_datatype(&entity, "Person", true, true); - caosdb_entity_entity_get_datatype(&entity, &out, is_ref, is_list); - EXPECT_EQ(strcmp(out, "Person"), 0); - EXPECT_TRUE(*is_list); - EXPECT_TRUE(*is_ref); + double out_double(0); + caosdb_entity_value_get_as_double(&out_value, &out_double); + EXPECT_EQ(out_double, 5.0); + + // clear to re-use + return_code = caosdb_entity_delete_datatype(&in_type); + EXPECT_EQ(return_code, 0); + caosdb_entity_create_reference_list_datatype(&in_type, "Person"); + caosdb_entity_entity_set_datatype(&entity, &in_type); + + // works without clearing since datatype is managed by the owning entity + caosdb_entity_entity_get_datatype(&entity, &out_type); + return_code = caosdb_entity_datatype_is_atomic(&out_type, &is_a); + EXPECT_EQ(return_code, 0); + EXPECT_FALSE(is_a); + return_code = caosdb_entity_datatype_is_reference(&out_type, &is_a); + EXPECT_EQ(return_code, 0); + EXPECT_FALSE(is_a); + return_code = caosdb_entity_datatype_is_list_of_atomic(&out_type, &is_a); + EXPECT_EQ(return_code, 0); + EXPECT_FALSE(is_a); + return_code = caosdb_entity_datatype_is_list_of_reference(&out_type, &is_a); + EXPECT_EQ(return_code, 0); + EXPECT_TRUE(is_a); + + caosdb_entity_datatype_get_datatype_name(&out_type, &out); + EXPECT_STREQ(out, "Person"); caosdb_entity_entity_set_unit(&entity, "m"); caosdb_entity_entity_get_unit(&entity, &out); EXPECT_EQ(strcmp(out, "m"), 0); - return_code = caosdb_entity_entity_set_double_value(&entity, 5.0); + return_code = caosdb_entity_delete_entity(&entity); EXPECT_EQ(return_code, 0); - double value[] = {0.0}; // NOLINT - return_code = caosdb_entity_entity_get_double_value(&entity, value); + return_code = caosdb_entity_delete_datatype(&in_type); EXPECT_EQ(return_code, 0); - EXPECT_EQ(*value, 5.0); - - return_code = caosdb_entity_delete_entity(&entity); + return_code = caosdb_entity_delete_value(&in_value); EXPECT_EQ(return_code, 0); } @@ -232,10 +543,14 @@ TEST_F(test_ccaosdb, test_property) { caosdb_entity_property_set_id(&property, "some_id"); caosdb_entity_property_set_name(&property, "some_name"); - caosdb_entity_property_set_datatype(&property, "TEXT", false, false); + caosdb_entity_datatype in_type; + caosdb_entity_create_atomic_datatype(&in_type, "TEXT"); + caosdb_entity_property_set_datatype(&property, &in_type); caosdb_entity_property_set_importance(&property, "FIX"); caosdb_entity_property_set_unit(&property, "some_unit"); - caosdb_entity_property_set_string_value(&property, "some_value"); + caosdb_entity_value in_value; + caosdb_entity_create_string_value(&in_value, "some_value"); + caosdb_entity_property_set_value(&property, &in_value); char *out = nullptr; // NOLINT caosdb_entity_property_get_id(&property, &out); @@ -244,12 +559,22 @@ TEST_F(test_ccaosdb, test_property) { caosdb_entity_property_get_name(&property, &out); EXPECT_EQ(strcmp(out, "some_name"), 0); - bool is_ref[] = {false}; // NOLINT - bool is_list[] = {false}; // NOLINT - caosdb_entity_property_get_datatype(&property, &out, is_ref, is_list); - EXPECT_EQ(strcmp(out, "TEXT"), 0); - EXPECT_FALSE(*is_ref); - EXPECT_FALSE(*is_list); + caosdb_entity_datatype out_type; + return_code = caosdb_entity_property_get_datatype(&property, &out_type); + EXPECT_EQ(return_code, 0); + bool is_a(false); + + caosdb_entity_datatype_is_atomic(&out_type, &is_a); + EXPECT_TRUE(is_a); + caosdb_entity_datatype_is_reference(&out_type, &is_a); + EXPECT_FALSE(is_a); + caosdb_entity_datatype_is_list_of_atomic(&out_type, &is_a); + EXPECT_FALSE(is_a); + caosdb_entity_datatype_is_list_of_reference(&out_type, &is_a); + EXPECT_FALSE(is_a); + + caosdb_entity_datatype_get_datatype_name(&out_type, &out); + EXPECT_STREQ(out, "TEXT"); caosdb_entity_property_get_importance(&property, &out); EXPECT_EQ(strcmp(out, "FIX"), 0); @@ -257,11 +582,20 @@ TEST_F(test_ccaosdb, test_property) { caosdb_entity_property_get_unit(&property, &out); EXPECT_EQ(strcmp(out, "some_unit"), 0); - caosdb_entity_property_get_string_value(&property, &out); - EXPECT_EQ(strcmp(out, "some_value"), 0); + caosdb_entity_value out_value; + return_code = caosdb_entity_property_get_value(&property, &out_value); + EXPECT_EQ(return_code, 0); + caosdb_entity_value_is_string(&out_value, &is_a); + EXPECT_TRUE(is_a); + caosdb_entity_value_get_as_string(&out_value, &out); + EXPECT_STREQ(out, "some_value"); return_code = caosdb_entity_delete_property(&property); EXPECT_EQ(return_code, 0); + return_code = caosdb_entity_delete_datatype(&in_type); + EXPECT_EQ(return_code, 0); + return_code = caosdb_entity_delete_value(&in_value); + EXPECT_EQ(return_code, 0); } TEST_F(test_ccaosdb, test_string_list_property) { @@ -270,35 +604,59 @@ TEST_F(test_ccaosdb, test_string_list_property) { int return_code(caosdb_entity_create_property(&property)); EXPECT_EQ(return_code, 0); - return_code = caosdb_entity_property_set_datatype(&property, "TEXT", false, true); + caosdb_entity_datatype in_type; + return_code = caosdb_entity_create_atomic_list_datatype(&in_type, "TEXT"); + EXPECT_EQ(return_code, 0); + return_code = caosdb_entity_property_set_datatype(&property, &in_type); EXPECT_EQ(return_code, 0); + caosdb_entity_value in_value; const char *value_list[] = {"val0", "val1", "val2"}; // NOLINT - return_code = caosdb_entity_property_set_string_list_value(&property, value_list, 3); + return_code = caosdb_entity_create_string_vector_value(&in_value, value_list, 3); EXPECT_EQ(return_code, 0); - - char *out = nullptr; // NOLINT - bool is_ref[] = {false}; // NOLINT - bool is_list[] = {false}; // NOLINT - return_code = caosdb_entity_property_get_datatype(&property, &out, is_ref, is_list); + return_code = caosdb_entity_property_set_value(&property, &in_value); EXPECT_EQ(return_code, 0); - EXPECT_EQ(strcmp(out, "TEXT"), 0); - EXPECT_FALSE(*is_ref); - EXPECT_TRUE(*is_list); - int length = -1; // NOLINT - return_code = caosdb_entity_property_get_value_list_length(&property, &length); + caosdb_entity_datatype out_type; + return_code = caosdb_entity_property_get_datatype(&property, &out_type); EXPECT_EQ(return_code, 0); + + bool is_a(false); + caosdb_entity_datatype_is_atomic(&out_type, &is_a); + EXPECT_FALSE(is_a); + caosdb_entity_datatype_is_reference(&out_type, &is_a); + EXPECT_FALSE(is_a); + caosdb_entity_datatype_is_list_of_atomic(&out_type, &is_a); + EXPECT_TRUE(is_a); + caosdb_entity_datatype_is_list_of_reference(&out_type, &is_a); + EXPECT_FALSE(is_a); + char *out = nullptr; // NOLINT + caosdb_entity_datatype_get_datatype_name(&out_type, &out); + EXPECT_STREQ(out, "TEXT"); + + caosdb_entity_value out_value; + caosdb_entity_property_get_value(&property, &out_value); + caosdb_entity_value_is_vector(&out_value, &is_a); + EXPECT_TRUE(is_a); + int length(-1); + caosdb_entity_value_get_as_vector_size(&out_value, &length); EXPECT_EQ(length, 3); + caosdb_entity_value list_elt; for (int i = 0; i < length; i++) { - return_code = caosdb_entity_property_get_string_list_value_at(&property, &out, i); + return_code = caosdb_entity_value_get_as_vector_at(&out_value, &list_elt, i); + EXPECT_EQ(return_code, 0); + return_code = caosdb_entity_value_get_as_string(&list_elt, &out); EXPECT_EQ(return_code, 0); - EXPECT_EQ(strcmp(value_list[i], out), 0); // NOLINT + EXPECT_STREQ(value_list[i], out); // NOLINT } return_code = caosdb_entity_delete_property(&property); EXPECT_EQ(return_code, 0); + return_code = caosdb_entity_delete_datatype(&in_type); + EXPECT_EQ(return_code, 0); + return_code = caosdb_entity_delete_value(&in_value); + EXPECT_EQ(return_code, 0); } TEST_F(test_ccaosdb, test_int_list_property) { @@ -307,36 +665,58 @@ TEST_F(test_ccaosdb, test_int_list_property) { int return_code(caosdb_entity_create_property(&property)); EXPECT_EQ(return_code, 0); - return_code = caosdb_entity_property_set_datatype(&property, "INTEGER", false, true); + caosdb_entity_datatype in_type; + caosdb_entity_create_atomic_list_datatype(&in_type, "INTEGER"); + return_code = caosdb_entity_property_set_datatype(&property, &in_type); EXPECT_EQ(return_code, 0); const int64_t value_list[] = {1, 2, 3}; // NOLINT - return_code = caosdb_entity_property_set_int_list_value(&property, &(value_list)[0], 3); + caosdb_entity_value in_value; + caosdb_entity_create_int_vector_value(&in_value, value_list, 3); + return_code = caosdb_entity_property_set_value(&property, &in_value); EXPECT_EQ(return_code, 0); - char *dt_out = nullptr; // NOLINT - bool is_ref[] = {false}; // NOLINT - bool is_list[] = {false}; // NOLINT - return_code = caosdb_entity_property_get_datatype(&property, &dt_out, is_ref, is_list); + caosdb_entity_datatype out_type; + return_code = caosdb_entity_property_get_datatype(&property, &out_type); EXPECT_EQ(return_code, 0); - EXPECT_STREQ(dt_out, "INTEGER"); - EXPECT_FALSE(*is_ref); - EXPECT_TRUE(*is_list); - int length = -1; // NOLINT - return_code = caosdb_entity_property_get_value_list_length(&property, &length); - EXPECT_EQ(return_code, 0); + bool is_a(false); + caosdb_entity_datatype_is_atomic(&out_type, &is_a); + EXPECT_FALSE(is_a); + caosdb_entity_datatype_is_reference(&out_type, &is_a); + EXPECT_FALSE(is_a); + caosdb_entity_datatype_is_list_of_atomic(&out_type, &is_a); + EXPECT_TRUE(is_a); + caosdb_entity_datatype_is_list_of_reference(&out_type, &is_a); + EXPECT_FALSE(is_a); + char *out = nullptr; // NOLINT + caosdb_entity_datatype_get_datatype_name(&out_type, &out); + EXPECT_STREQ(out, "INTEGER"); + + caosdb_entity_value out_value; + caosdb_entity_property_get_value(&property, &out_value); + caosdb_entity_value_is_vector(&out_value, &is_a); + EXPECT_TRUE(is_a); + int length(-1); + caosdb_entity_value_get_as_vector_size(&out_value, &length); EXPECT_EQ(length, 3); + int64_t out_int = -1; + caosdb_entity_value list_elt; for (int i = 0; i < length; i++) { - int64_t out = -1; - return_code = caosdb_entity_property_get_int_list_value_at(&property, &out, i); + return_code = caosdb_entity_value_get_as_vector_at(&out_value, &list_elt, i); + EXPECT_EQ(return_code, 0); + return_code = caosdb_entity_value_get_as_integer(&list_elt, &out_int); EXPECT_EQ(return_code, 0); - EXPECT_EQ(value_list[i], out); // NOLINT + EXPECT_EQ(value_list[i], out_int); // NOLINT } return_code = caosdb_entity_delete_property(&property); EXPECT_EQ(return_code, 0); + return_code = caosdb_entity_delete_datatype(&in_type); + EXPECT_EQ(return_code, 0); + return_code = caosdb_entity_delete_value(&in_value); + EXPECT_EQ(return_code, 0); } TEST_F(test_ccaosdb, test_bool_list_property) { @@ -345,36 +725,58 @@ TEST_F(test_ccaosdb, test_bool_list_property) { int return_code(caosdb_entity_create_property(&property)); EXPECT_EQ(return_code, 0); - return_code = caosdb_entity_property_set_datatype(&property, "BOOLEAN", false, true); + caosdb_entity_datatype in_type; + caosdb_entity_create_atomic_list_datatype(&in_type, "BOOLEAN"); + return_code = caosdb_entity_property_set_datatype(&property, &in_type); EXPECT_EQ(return_code, 0); const bool value_list[] = {true, true, false}; // NOLINT - return_code = caosdb_entity_property_set_boolean_list_value(&property, &(value_list)[0], 3); + caosdb_entity_value in_value; + caosdb_entity_create_bool_vector_value(&in_value, value_list, 3); + return_code = caosdb_entity_property_set_value(&property, &in_value); EXPECT_EQ(return_code, 0); - char *dt_out = nullptr; // NOLINT - bool is_ref[] = {false}; // NOLINT - bool is_list[] = {false}; // NOLINT - return_code = caosdb_entity_property_get_datatype(&property, &dt_out, is_ref, is_list); + caosdb_entity_datatype out_type; + return_code = caosdb_entity_property_get_datatype(&property, &out_type); EXPECT_EQ(return_code, 0); - EXPECT_STREQ(dt_out, "BOOLEAN"); - EXPECT_FALSE(*is_ref); - EXPECT_TRUE(*is_list); - int length = -1; // NOLINT - return_code = caosdb_entity_property_get_value_list_length(&property, &length); - EXPECT_EQ(return_code, 0); + bool is_a(false); + caosdb_entity_datatype_is_atomic(&out_type, &is_a); + EXPECT_FALSE(is_a); + caosdb_entity_datatype_is_reference(&out_type, &is_a); + EXPECT_FALSE(is_a); + caosdb_entity_datatype_is_list_of_atomic(&out_type, &is_a); + EXPECT_TRUE(is_a); + caosdb_entity_datatype_is_list_of_reference(&out_type, &is_a); + EXPECT_FALSE(is_a); + char *out = nullptr; // NOLINT + caosdb_entity_datatype_get_datatype_name(&out_type, &out); + EXPECT_STREQ(out, "BOOLEAN"); + + caosdb_entity_value out_value; + caosdb_entity_property_get_value(&property, &out_value); + caosdb_entity_value_is_vector(&out_value, &is_a); + EXPECT_TRUE(is_a); + int length(-1); + caosdb_entity_value_get_as_vector_size(&out_value, &length); EXPECT_EQ(length, 3); + bool out_bool(false); + caosdb_entity_value list_elt; for (int i = 0; i < length; i++) { - bool out = true; - return_code = caosdb_entity_property_get_boolean_list_value_at(&property, &out, i); + return_code = caosdb_entity_value_get_as_vector_at(&out_value, &list_elt, i); + EXPECT_EQ(return_code, 0); + return_code = caosdb_entity_value_get_as_bool(&list_elt, &out_bool); EXPECT_EQ(return_code, 0); - EXPECT_EQ(value_list[i], out); // NOLINT + EXPECT_EQ(value_list[i], out_bool); // NOLINT } return_code = caosdb_entity_delete_property(&property); EXPECT_EQ(return_code, 0); + return_code = caosdb_entity_delete_datatype(&in_type); + EXPECT_EQ(return_code, 0); + return_code = caosdb_entity_delete_value(&in_value); + EXPECT_EQ(return_code, 0); } TEST_F(test_ccaosdb, test_entity_with_parent_and_property) { @@ -392,8 +794,12 @@ TEST_F(test_ccaosdb, test_entity_with_parent_and_property) { caosdb_entity_property_set_id(&input_property, "property_id"); caosdb_entity_property_set_name(&input_property, "property_name"); - caosdb_entity_property_set_datatype(&input_property, "TEXT", false, false); - caosdb_entity_property_set_string_value(&input_property, "property_value"); + caosdb_entity_datatype in_type; + caosdb_entity_create_atomic_datatype(&in_type, "TEXT"); + caosdb_entity_value in_value; + caosdb_entity_create_string_value(&in_value, "property_value"); + caosdb_entity_property_set_datatype(&input_property, &in_type); + caosdb_entity_property_set_value(&input_property, &in_value); caosdb_entity_entity entity; return_code = caosdb_entity_create_entity(&entity); @@ -432,19 +838,37 @@ TEST_F(test_ccaosdb, test_entity_with_parent_and_property) { caosdb_entity_property_get_name(&output_property, &out); EXPECT_EQ(strcmp(in, out), 0); - bool is_list[] = {false}; // NOLINT - bool is_ref[] = {false}; // NOLINT - caosdb_entity_property_get_datatype(&input_property, &in, is_ref, is_list); - EXPECT_FALSE(*is_list); - EXPECT_FALSE(*is_ref); - caosdb_entity_property_get_datatype(&output_property, &out, is_ref, is_list); - EXPECT_FALSE(*is_list); - EXPECT_FALSE(*is_ref); - EXPECT_EQ(strcmp(in, out), 0); - - caosdb_entity_property_get_string_value(&input_property, &in); - caosdb_entity_property_get_string_value(&output_property, &out); - EXPECT_EQ(strcmp(in, out), 0); + caosdb_entity_datatype out_type; + caosdb_entity_property_get_datatype(&output_property, &out_type); + + bool in_is(false); + bool out_is(false); + caosdb_entity_datatype_is_atomic(&in_type, &in_is); + caosdb_entity_datatype_is_atomic(&out_type, &out_is); + EXPECT_EQ(in_is, out_is); + caosdb_entity_datatype_is_reference(&in_type, &in_is); + caosdb_entity_datatype_is_reference(&out_type, &out_is); + EXPECT_EQ(in_is, out_is); + caosdb_entity_datatype_is_list_of_atomic(&in_type, &in_is); + caosdb_entity_datatype_is_list_of_atomic(&out_type, &out_is); + EXPECT_EQ(in_is, out_is); + caosdb_entity_datatype_is_list_of_reference(&in_type, &in_is); + caosdb_entity_datatype_is_list_of_reference(&out_type, &out_is); + EXPECT_EQ(in_is, out_is); + + caosdb_entity_datatype_get_datatype_name(&in_type, &in); + caosdb_entity_datatype_get_datatype_name(&out_type, &out); + EXPECT_STREQ(in, out); + + caosdb_entity_value out_value; + caosdb_entity_property_get_value(&output_property, &out_value); + caosdb_entity_value_is_string(&in_value, &in_is); + EXPECT_TRUE(in_is); + caosdb_entity_value_is_string(&out_value, &out_is); + EXPECT_TRUE(out_is); + caosdb_entity_value_get_as_string(&in_value, &in); + caosdb_entity_value_get_as_string(&out_value, &out); + EXPECT_STREQ(in, out); caosdb_entity_parent output_parent; return_code = caosdb_entity_entity_get_parent(&entity, &output_parent, 0); @@ -465,6 +889,10 @@ TEST_F(test_ccaosdb, test_entity_with_parent_and_property) { EXPECT_EQ(return_code, 0); return_code = caosdb_entity_delete_entity(&entity); EXPECT_EQ(return_code, 0); + return_code = caosdb_entity_delete_datatype(&in_type); + EXPECT_EQ(return_code, 0); + return_code = caosdb_entity_delete_value(&in_value); + EXPECT_EQ(return_code, 0); // This tests the `_deletable` flag. The wrapped cpp objects of // `output_parent` and `output_property` are owned by the entity, so diff --git a/test/test_data_type.cpp b/test/test_data_type.cpp index bb2e97ba412d52a979e060f2d9920d591c07e9e8..51624a7e0513f4654f2eaa9fdf3519399726199d 100644 --- a/test/test_data_type.cpp +++ b/test/test_data_type.cpp @@ -53,17 +53,17 @@ TEST(test_data_type, test_atomic) { // the different AtomicDataType are associated with integers entity.SetDataType(map_el.first); EXPECT_TRUE(entity.GetDataType().IsAtomic()); - EXPECT_EQ(entity.GetDataType().AsAtomic(), map_el.first); + EXPECT_EQ(entity.GetDataType().GetAsAtomic(), map_el.first); proto_data_type.set_atomic_data_type(static_cast<ProtoAtomicDataType>(map_el.first)); DataType data_type(&proto_data_type); entity.SetDataType(data_type); EXPECT_FALSE(data_type.IsReference()); - EXPECT_EQ(data_type.AsReference().GetName(), std::basic_string<char>("")); + EXPECT_EQ(data_type.GetAsReference().GetName(), std::basic_string<char>("")); EXPECT_FALSE(data_type.IsList()); EXPECT_TRUE(data_type.IsAtomic()); - EXPECT_EQ(data_type.AsAtomic(), map_el.first); + EXPECT_EQ(data_type.GetAsAtomic(), map_el.first); } } @@ -74,7 +74,7 @@ TEST(test_data_type, test_reference) { entity.SetRole(Role::PROPERTY); entity.SetDataType("Person"); EXPECT_TRUE(entity.GetDataType().IsReference()); - EXPECT_EQ(entity.GetDataType().AsReference().GetName(), "Person"); + EXPECT_EQ(entity.GetDataType().GetAsReference().GetName(), "Person"); proto_data_type.mutable_reference_data_type()->set_name("Person"); DataType data_type(&proto_data_type); @@ -83,7 +83,7 @@ TEST(test_data_type, test_reference) { EXPECT_TRUE(data_type.IsReference()); EXPECT_FALSE(data_type.IsList()); EXPECT_FALSE(data_type.IsAtomic()); - EXPECT_EQ(data_type.AsReference().GetName(), "Person"); + EXPECT_EQ(data_type.GetAsReference().GetName(), "Person"); } TEST(test_data_type, test_list_of_atomic) { @@ -93,7 +93,7 @@ TEST(test_data_type, test_list_of_atomic) { EXPECT_FALSE(data_type.IsReference()); EXPECT_FALSE(data_type.IsAtomic()); EXPECT_TRUE(data_type.IsList()); - const auto &list_data_type = data_type.AsList(); + const auto &list_data_type = data_type.GetAsList(); EXPECT_EQ(list_data_type.GetReferenceDataType().GetName(), std::basic_string<char>("")); EXPECT_TRUE(list_data_type.IsListOfAtomic()); EXPECT_FALSE(list_data_type.IsListOfReference()); @@ -108,7 +108,7 @@ TEST(test_data_type, test_list_of_reference) { EXPECT_FALSE(data_type.IsAtomic()); EXPECT_TRUE(data_type.IsList()); - const auto &list_data_type = data_type.AsList(); + const auto &list_data_type = data_type.GetAsList(); EXPECT_TRUE(list_data_type.IsListOfReference()); EXPECT_FALSE(list_data_type.IsListOfAtomic()); const auto *wrapped = list_data_type.GetReferenceDataType().GetWrapped(); diff --git a/test/test_entity.cpp b/test/test_entity.cpp index df196c124de8901dc047f2fdafe8efaa2e789939..75adc7e7a051cc1e2a154d6b3723e44123e28130 100644 --- a/test/test_entity.cpp +++ b/test/test_entity.cpp @@ -80,15 +80,15 @@ TEST(test_entity, test_property_setters) { EXPECT_EQ(prop.GetId(), "prop_id"); EXPECT_EQ(prop.GetImportance(), Importance::OBLIGATORY); EXPECT_TRUE(prop.GetValue().IsString()); - EXPECT_EQ(prop.GetValue().AsString(), "prop_value"); + EXPECT_EQ(prop.GetValue().GetAsString(), "prop_value"); EXPECT_EQ(prop.GetUnit(), "prop_unit"); EXPECT_TRUE(prop.GetDataType().IsReference()); - EXPECT_EQ(prop.GetDataType().AsReference().GetName(), "prop_dtype"); + EXPECT_EQ(prop.GetDataType().GetAsReference().GetName(), "prop_dtype"); EXPECT_FALSE(prop.GetDataType().IsList()); prop.SetDataType(AtomicDataType::DATETIME); EXPECT_TRUE(prop.GetDataType().IsAtomic()); - EXPECT_EQ(prop.GetDataType().AsAtomic(), AtomicDataType::DATETIME); + EXPECT_EQ(prop.GetDataType().GetAsAtomic(), AtomicDataType::DATETIME); EXPECT_FALSE(prop.GetDataType().IsList()); } @@ -97,16 +97,16 @@ TEST(test_entity, test_list_property_setters) { prop.SetDataType(AtomicDataType::DATETIME); // Set as atomic first. EXPECT_TRUE(prop.GetDataType().IsAtomic()); - EXPECT_EQ(prop.GetDataType().AsAtomic(), AtomicDataType::DATETIME); + EXPECT_EQ(prop.GetDataType().GetAsAtomic(), AtomicDataType::DATETIME); prop.SetDataType(AtomicDataType::DOUBLE, true); auto const &dtype = prop.GetDataType(); EXPECT_FALSE(dtype.IsAtomic()); // Should not be true anymore. EXPECT_FALSE(dtype.IsReference()); EXPECT_TRUE(dtype.IsList()); - EXPECT_NE(dtype.AsAtomic(), AtomicDataType::DATETIME); // Should be overwritten. - EXPECT_TRUE(dtype.AsList().IsListOfAtomic()); - EXPECT_EQ(dtype.AsList().GetAtomicDataType(), AtomicDataType::DOUBLE); + EXPECT_NE(dtype.GetAsAtomic(), AtomicDataType::DATETIME); // Should be overwritten. + EXPECT_TRUE(dtype.GetAsList().IsListOfAtomic()); + EXPECT_EQ(dtype.GetAsList().GetAtomicDataType(), AtomicDataType::DOUBLE); } TEST(test_entity, test_append_property) { @@ -200,11 +200,11 @@ TEST(test_entity, test_insert_with_role) { EXPECT_EQ(entity.GetRole(), Role::PROPERTY); EXPECT_TRUE(entity.GetDataType().IsAtomic()); - EXPECT_EQ(entity.GetDataType().AsAtomic(), AtomicDataType::DOUBLE); + EXPECT_EQ(entity.GetDataType().GetAsAtomic(), AtomicDataType::DOUBLE); EXPECT_EQ(entity.GetName(), "Length"); EXPECT_EQ(entity.GetUnit(), "m"); EXPECT_TRUE(entity.GetValue().IsDouble()); - EXPECT_DOUBLE_EQ(entity.GetValue().AsDouble(), 5.5); + EXPECT_DOUBLE_EQ(entity.GetValue().GetAsDouble(), 5.5); } TEST(test_entity, test_insert_with_parent) { diff --git a/test/test_list_properties.cpp b/test/test_list_properties.cpp index 34895dfa15eabc207c2a485f4a22fcb33428a791..27d0aad53cb9eb1342e1cb87ca24d7c3b71938f0 100644 --- a/test/test_list_properties.cpp +++ b/test/test_list_properties.cpp @@ -52,13 +52,13 @@ TEST(test_list_property, test_list_of_text) { const auto &value = entity.GetProperties().at(0).GetValue(); EXPECT_TRUE(data_type.IsList()); - EXPECT_TRUE(data_type.AsList().IsListOfAtomic()); - EXPECT_EQ(data_type.AsList().GetAtomicDataType(), AtomicDataType::TEXT); + EXPECT_TRUE(data_type.GetAsList().IsListOfAtomic()); + EXPECT_EQ(data_type.GetAsList().GetAtomicDataType(), AtomicDataType::TEXT); - EXPECT_TRUE(value.IsList()); - EXPECT_EQ(value.AsList().size(), 3); - EXPECT_TRUE(value.AsList().at(1).IsString()); - EXPECT_EQ(value.AsList().at(1).AsString(), "item2"); + EXPECT_TRUE(value.IsVector()); + EXPECT_EQ(value.GetAsVector().size(), 3); + EXPECT_TRUE(value.GetAsVector().at(1).IsString()); + EXPECT_EQ(value.GetAsVector().at(1).GetAsString(), "item2"); } } // namespace caosdb::entity diff --git a/test/test_protobuf.cpp b/test/test_protobuf.cpp index 43ab6883b42f1dca1c2785103f6a274eb2b2f1bc..6f9bda0740487db475f1e34757e4a612c59061f9 100644 --- a/test/test_protobuf.cpp +++ b/test/test_protobuf.cpp @@ -102,10 +102,10 @@ TEST(test_protobuf, test_copy_nested) { EXPECT_EQ(entity_destination.data_type().reference_data_type().name(), "src_per"); Entity entity(&entity_destination); - EXPECT_EQ(entity.GetDataType().AsReference().GetName(), "src_per"); + EXPECT_EQ(entity.GetDataType().GetAsReference().GetName(), "src_per"); const Entity ©_entity(entity); - EXPECT_EQ(copy_entity.GetDataType().AsReference().GetName(), "src_per"); + EXPECT_EQ(copy_entity.GetDataType().GetAsReference().GetName(), "src_per"); } } // namespace caosdb diff --git a/test/test_value.cpp b/test/test_value.cpp index 74d30f04b621a0e118bc7591a07aab052786c790..25f8a12909e52fee4e3ed3a6b688b1871a41a32f 100644 --- a/test/test_value.cpp +++ b/test/test_value.cpp @@ -42,9 +42,9 @@ TEST(test_value, test_null) { EXPECT_TRUE(value.IsNull()); EXPECT_FALSE(value.IsDouble()); EXPECT_FALSE(value.IsBool()); - EXPECT_FALSE(value.IsInteger()); + EXPECT_FALSE(value.IsInt64()); EXPECT_FALSE(value.IsString()); - EXPECT_FALSE(value.IsList()); + EXPECT_FALSE(value.IsVector()); } TEST(test_value, test_string) { @@ -53,18 +53,18 @@ TEST(test_value, test_string) { EXPECT_TRUE(value.IsString()); EXPECT_FALSE(value.IsDouble()); EXPECT_FALSE(value.IsBool()); - EXPECT_FALSE(value.IsInteger()); + EXPECT_FALSE(value.IsInt64()); - EXPECT_EQ(value.AsString(), "test"); + EXPECT_EQ(value.GetAsString(), "test"); Value empty_string(std::string("")); EXPECT_FALSE(empty_string.IsNull()); EXPECT_TRUE(empty_string.IsString()); EXPECT_FALSE(empty_string.IsDouble()); EXPECT_FALSE(empty_string.IsBool()); - EXPECT_FALSE(empty_string.IsInteger()); + EXPECT_FALSE(empty_string.IsInt64()); - EXPECT_EQ(empty_string.AsString(), ""); + EXPECT_EQ(empty_string.GetAsString(), ""); // Test inequality Value string1("1"); @@ -78,18 +78,18 @@ TEST(test_value, test_double) { EXPECT_FALSE(value.IsString()); EXPECT_TRUE(value.IsDouble()); EXPECT_FALSE(value.IsBool()); - EXPECT_FALSE(value.IsInteger()); + EXPECT_FALSE(value.IsInt64()); - EXPECT_EQ(value.AsDouble(), 2.26); + EXPECT_EQ(value.GetAsDouble(), 2.26); Value nan(std::sqrt(-1.0)); EXPECT_FALSE(nan.IsNull()); EXPECT_FALSE(nan.IsString()); EXPECT_TRUE(nan.IsDouble()); EXPECT_FALSE(nan.IsBool()); - EXPECT_FALSE(nan.IsInteger()); + EXPECT_FALSE(nan.IsInt64()); - EXPECT_TRUE(std::isnan(nan.AsDouble())); + EXPECT_TRUE(std::isnan(nan.GetAsDouble())); } TEST(test_value, test_integer) { @@ -98,9 +98,9 @@ TEST(test_value, test_integer) { EXPECT_FALSE(value.IsString()); EXPECT_FALSE(value.IsDouble()); EXPECT_FALSE(value.IsBool()); - EXPECT_TRUE(value.IsInteger()); + EXPECT_TRUE(value.IsInt64()); - EXPECT_EQ(value.AsInteger(), 1337); + EXPECT_EQ(value.GetAsInt64(), 1337); } TEST(test_value, test_boolean) { @@ -109,9 +109,9 @@ TEST(test_value, test_boolean) { EXPECT_FALSE(value.IsString()); EXPECT_FALSE(value.IsDouble()); EXPECT_TRUE(value.IsBool()); - EXPECT_FALSE(value.IsInteger()); + EXPECT_FALSE(value.IsInt64()); - EXPECT_EQ(value.AsBool(), true); + EXPECT_EQ(value.GetAsBool(), true); } TEST(test_value, test_list) { @@ -122,17 +122,56 @@ TEST(test_value, test_list) { Value value(ids); EXPECT_FALSE(value.IsNull()); - EXPECT_TRUE(value.IsList()); + EXPECT_TRUE(value.IsVector()); EXPECT_FALSE(value.IsString()); EXPECT_FALSE(value.IsDouble()); EXPECT_FALSE(value.IsBool()); - EXPECT_FALSE(value.IsInteger()); + EXPECT_FALSE(value.IsInt64()); - auto list_value = value.AsList(); + auto list_value = value.GetAsVector(); int counter = 0; - for (auto item : list_value) { + for (const auto &item : list_value) { EXPECT_EQ(item.IsString(), true); - EXPECT_EQ(item.AsString(), "id" + std::to_string(counter++)); + EXPECT_EQ(item.GetAsString(), "id" + std::to_string(counter++)); } } + +TEST(test_value, test_scalar_value_to_value) { + ProtoScalarValue proto_scalar_value; + proto_scalar_value.set_integer_value(5); + ScalarValue scalar_value(&proto_scalar_value); + Value value(scalar_value); + + EXPECT_TRUE(scalar_value.IsInt64()); + EXPECT_TRUE(value.IsInt64()); + EXPECT_EQ(scalar_value.GetAsInt64(), value.GetAsInt64()); +} + +TEST(test_value, test_abstract_value) { + std::vector<double> vals; + for (double num : {0.0, 5.6, 27.5}) { + vals.push_back(num); + } + Value value(vals); + EXPECT_TRUE(value.IsVector()); + + AbstractValue *abstract_value = &value; + EXPECT_TRUE(abstract_value->IsVector()); + + Value value2(*abstract_value); + EXPECT_TRUE(value2.IsVector()); + + ScalarValue scalar_value = value.GetAsVector().at(2); + EXPECT_TRUE(scalar_value.IsDouble()); + EXPECT_EQ(scalar_value.GetAsDouble(), 27.5); + + AbstractValue *abstract_scalar_value = &scalar_value; + EXPECT_TRUE(abstract_scalar_value->IsDouble()); + EXPECT_EQ(abstract_scalar_value->GetAsDouble(), 27.5); + + Value scalar_value2(*abstract_scalar_value); + EXPECT_TRUE(scalar_value2.IsDouble()); + EXPECT_EQ(scalar_value2.GetAsDouble(), 27.5); +} + } // namespace caosdb::entity