From 1d919fef38ff9c2b5e6b827bc7c41fa9c51c4b9a Mon Sep 17 00:00:00 2001 From: Sara Date: Thu, 25 Jan 2024 09:58:00 +0100 Subject: [PATCH] feat: implemented variant_from_str, Drop, and Mirror --- core/src/variant.c | 69 ++++++++++++++++++++++++++++++++++++++++++++++ core/src/variant.h | 8 ++++++ 2 files changed, 77 insertions(+) create mode 100644 core/src/variant.c diff --git a/core/src/variant.c b/core/src/variant.c new file mode 100644 index 0000000..85ec773 --- /dev/null +++ b/core/src/variant.c @@ -0,0 +1,69 @@ +#include "variant.h" +#include "debug.h" + +impl_Drop_for(Variant, + destroy_variant +) + +START_REFLECT(Variant) + REFLECT_TYPECLASS(Variant, Drop) +END_REFLECT(Variant) + +Variant variant_from_str(const char* str) { + size_t length = strlen(str); + if(isdigit(str[0])) { + // variant is a number + // convert to double + return NumberVariant(atof(str)); + } else if(str[0] == '"') { + // variant should be a string + // format: "" + // copy the input string without the quotes + size_t result_length = strfirst(str+1, str+length, '"'); + char* string = malloc(result_length); + strncpy(string, str+1, result_length-1); + string[result_length] = '\0'; + return StringVariant(string, result_length); + } else if(strncmp(str, "Vector(", 7) == 0) { + // variant is a vector + // format: Vector(, ) + // get the location of the brackets + long close_bracket = strfirst(str, str + length, ')'); + if(close_bracket == -1) goto variant_from_str_err; + char buf[24]; buf[23] = '\0'; + // copy what is within the brackets + // 7 is the number of characters in "Vector(", which should be skipped + strncpy(buf, str + 7, close_bracket - 7); + length = strlen(buf); + long comma_ind = strfirst(buf, buf+length, ','); + if(comma_ind == -1) goto variant_from_str_err; + // split the string at the comma by inserting a null terminator + buf[comma_ind] = '\0'; + return VectorVariant(MakeVector(atof(buf), atof(buf + comma_ind + 1))); + } +variant_from_str_err: + return UndefinedVariant(); +} + +void destroy_variant(Variant* self) { + destroy_contained(self); + free(self); +} + +void destroy_contained(Variant* self) { + switch(self->type) { + default: break; + case Variant_String: + if(self->as_string != NULL) + free(self->as_string); + break; + case Variant_Object: + if(TC_MIRRORS(self->as_object, Drop)) { + Drop drop = TC_CAST(self->as_object, Drop); + drop.tc->drop(drop.data); + } else { + LOG_ERROR("Deallocating Object Variant that does not mirror Drop, pointer will be orphaned"); + } + break; + } +} diff --git a/core/src/variant.h b/core/src/variant.h index d20b7ec..29fcbe1 100644 --- a/core/src/variant.h +++ b/core/src/variant.h @@ -2,6 +2,7 @@ #define _fencer_variant_h #include "vmath.h" +#include "drop.h" #include "mirror.h" typedef enum VariantType { @@ -23,10 +24,17 @@ typedef struct Variant { }; } Variant; +extern Variant variant_from_str(const char* str); +extern void destroy_variant(Variant* self); +extern void destroy_contained(Variant* self); + #define NumberVariant(Value_) (Variant){.type = Variant_Number, .as_number = Value_} #define VectorVariant(Value_) (Variant){.type = Variant_Vector, .as_vector = Value_} #define ObjectVariant(Value_) (Variant){.type = Variant_Object, .as_object = Value_} #define StringVariant(Value_, BufSize_) (Variant){.type = Variant_String, .as_string = Value_, .string_size = BufSize_} #define UndefinedVariant() (Variant){.type = Variant_Undefined } +decl_typeclass_impl(Drop, Variant); +decl_typeclass_impl(Mirror, Variant); + #endif // !_fencer_variant_h