From 6afae6681b2900964be5e3fc48aed9b68374d75c Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Sun, 12 Nov 2023 19:06:23 -0800 Subject: [PATCH] Allow casting properties of different types --- src/SDL_properties.c | 92 ++++++++++++++++++++++++++++---- test/testautomation_properties.c | 52 +++++++++--------- 2 files changed, 108 insertions(+), 36 deletions(-) diff --git a/src/SDL_properties.c b/src/SDL_properties.c index e32d1d11c..e44734494 100644 --- a/src/SDL_properties.c +++ b/src/SDL_properties.c @@ -20,6 +20,7 @@ */ #include "SDL_internal.h" #include "SDL_hashtable.h" +#include "SDL_hints_c.h" #include "SDL_properties_c.h" @@ -35,6 +36,8 @@ typedef struct SDL_bool boolean_value; } value; + char *string_storage; + void (SDLCALL *cleanup)(void *userdata, void *value); void *userdata; } SDL_Property; @@ -67,6 +70,9 @@ static void SDL_FreeProperty(const void *key, const void *value, void *data) default: break; } + if (property->string_storage) { + SDL_free(property->string_storage); + } } SDL_free((void *)key); SDL_free((void *)value); @@ -342,7 +348,7 @@ int SDL_SetBooleanProperty(SDL_PropertiesID props, const char *name, SDL_bool va return SDL_OutOfMemory(); } property->type = SDL_PROPERTY_TYPE_BOOLEAN; - property->value.boolean_value = value; + property->value.boolean_value = value ? SDL_TRUE : SDL_FALSE; return SDL_PrivateSetProperty(props, name, property); } @@ -461,10 +467,40 @@ const char *SDL_GetStringProperty(SDL_PropertiesID props, const char *name, cons { SDL_Property *property = NULL; if (SDL_FindInHashTable(properties->props, name, (const void **)&property)) { - if (property->type == SDL_PROPERTY_TYPE_STRING) { + switch (property->type) { + case SDL_PROPERTY_TYPE_STRING: value = property->value.string_value; - } else { + break; + case SDL_PROPERTY_TYPE_NUMBER: + if (property->string_storage) { + value = property->string_storage; + } else { + SDL_asprintf(&property->string_storage, "%" SDL_PRIs64 "", property->value.number_value); + if (property->string_storage) { + value = property->string_storage; + } else { + SDL_OutOfMemory(); + } + } + break; + case SDL_PROPERTY_TYPE_FLOAT: + if (property->string_storage) { + value = property->string_storage; + } else { + SDL_asprintf(&property->string_storage, "%f", property->value.float_value); + if (property->string_storage) { + value = property->string_storage; + } else { + SDL_OutOfMemory(); + } + } + break; + case SDL_PROPERTY_TYPE_BOOLEAN: + value = property->value.boolean_value ? "true" : "false"; + break; + default: SDL_SetError("Property %s isn't a string value", name); + break; } } else { SDL_SetError("Couldn't find property named %s", name); @@ -502,10 +538,22 @@ Sint64 SDL_GetNumberProperty(SDL_PropertiesID props, const char *name, Sint64 de { SDL_Property *property = NULL; if (SDL_FindInHashTable(properties->props, name, (const void **)&property)) { - if (property->type == SDL_PROPERTY_TYPE_NUMBER) { + switch (property->type) { + case SDL_PROPERTY_TYPE_STRING: + value = SDL_strtoll(property->value.string_value, NULL, 0); + break; + case SDL_PROPERTY_TYPE_NUMBER: value = property->value.number_value; - } else { - SDL_SetError("Property %s isn't a string value", name); + break; + case SDL_PROPERTY_TYPE_FLOAT: + value = (Sint64)SDL_round((double)property->value.float_value); + break; + case SDL_PROPERTY_TYPE_BOOLEAN: + value = property->value.boolean_value; + break; + default: + SDL_SetError("Property %s isn't a number value", name); + break; } } else { SDL_SetError("Couldn't find property named %s", name); @@ -543,10 +591,22 @@ float SDL_GetFloatProperty(SDL_PropertiesID props, const char *name, float defau { SDL_Property *property = NULL; if (SDL_FindInHashTable(properties->props, name, (const void **)&property)) { - if (property->type == SDL_PROPERTY_TYPE_FLOAT) { + switch (property->type) { + case SDL_PROPERTY_TYPE_STRING: + value = (float)SDL_atof(property->value.string_value); + break; + case SDL_PROPERTY_TYPE_NUMBER: + value = (float)property->value.number_value; + break; + case SDL_PROPERTY_TYPE_FLOAT: value = property->value.float_value; - } else { + break; + case SDL_PROPERTY_TYPE_BOOLEAN: + value = (float)property->value.boolean_value; + break; + default: SDL_SetError("Property %s isn't a float value", name); + break; } } else { SDL_SetError("Couldn't find property named %s", name); @@ -584,10 +644,22 @@ SDL_bool SDL_GetBooleanProperty(SDL_PropertiesID props, const char *name, SDL_bo { SDL_Property *property = NULL; if (SDL_FindInHashTable(properties->props, name, (const void **)&property)) { - if (property->type == SDL_PROPERTY_TYPE_BOOLEAN) { + switch (property->type) { + case SDL_PROPERTY_TYPE_STRING: + value = SDL_GetStringBoolean(property->value.string_value, default_value); + break; + case SDL_PROPERTY_TYPE_NUMBER: + value = (property->value.number_value != 0); + break; + case SDL_PROPERTY_TYPE_FLOAT: + value = (property->value.float_value != 0.0f); + break; + case SDL_PROPERTY_TYPE_BOOLEAN: value = property->value.boolean_value; - } else { + break; + default: SDL_SetError("Property %s isn't a boolean value", name); + break; } } else { SDL_SetError("Couldn't find property named %s", name); diff --git a/test/testautomation_properties.c b/test/testautomation_properties.c index 3feca3e04..7c05c240b 100644 --- a/test/testautomation_properties.c +++ b/test/testautomation_properties.c @@ -81,7 +81,7 @@ static int properties_testBasic(void *arg) "Verify property, expected 0xabcd, got: %p", value); value_string = SDL_GetStringProperty(props, "foo", "abcd"); SDLTest_AssertCheck(value_string && SDL_strcmp(value_string, "abcd") == 0, - "Verify string property, expected \"abcd\", got: %s", value_string); + "Verify string property, expected abcd, got: %s", value_string); value_number = SDL_GetNumberProperty(props, "foo", 1234); SDLTest_AssertCheck(value_number == 1234, "Verify number property, expected 1234, got: %" SDL_PRIu64 "", value_number); @@ -125,7 +125,7 @@ static int properties_testBasic(void *arg) "Verify property, expected NULL, got: %p", value); value_string = SDL_GetStringProperty(props, "foo", NULL); SDLTest_AssertCheck(value_string != NULL && SDL_strcmp(value_string, "bar") == 0, - "Verify string property, expected \"bar\", got: %s", value_string); + "Verify string property, expected bar, got: %s", value_string); value_number = SDL_GetNumberProperty(props, "foo", 0); SDLTest_AssertCheck(value_number == 0, "Verify number property, expected 0, got: %" SDL_PRIu64 "", value_number); @@ -133,8 +133,8 @@ static int properties_testBasic(void *arg) SDLTest_AssertCheck(value_float == 0.0f, "Verify float property, expected 0, got: %f", value_float); value_bool = SDL_GetBooleanProperty(props, "foo", SDL_FALSE); - SDLTest_AssertCheck(value_bool == SDL_FALSE, - "Verify boolean property, expected SDL_FALSE, got: %s", value_bool ? "SDL_TRUE" : "SDL_FALSE"); + SDLTest_AssertCheck(value_bool == SDL_TRUE, + "Verify boolean property, expected SDL_TRUE, got: %s", value_bool ? "SDL_TRUE" : "SDL_FALSE"); /* Check number value */ SDLTest_AssertPass("Call to SDL_SetNumberProperty(\"foo\", 1)"); @@ -146,21 +146,21 @@ static int properties_testBasic(void *arg) SDLTest_AssertCheck(value == NULL, "Verify property, expected NULL, got: %p", value); value_string = SDL_GetStringProperty(props, "foo", NULL); - SDLTest_AssertCheck(value_string == NULL, - "Verify string property, expected NULL, got: %s", value_string); + SDLTest_AssertCheck(value_string && SDL_strcmp(value_string, "1") == 0, + "Verify string property, expected 1, got: %s", value_string); value_number = SDL_GetNumberProperty(props, "foo", 0); SDLTest_AssertCheck(value_number == 1, "Verify number property, expected 1, got: %" SDL_PRIu64 "", value_number); value_float = SDL_GetFloatProperty(props, "foo", 0.0f); - SDLTest_AssertCheck(value_float == 0.0f, - "Verify float property, expected 0, got: %f", value_float); + SDLTest_AssertCheck(value_float == 1.0f, + "Verify float property, expected 1, got: %f", value_float); value_bool = SDL_GetBooleanProperty(props, "foo", SDL_FALSE); - SDLTest_AssertCheck(value_bool == SDL_FALSE, - "Verify boolean property, expected SDL_FALSE, got: %s", value_bool ? "SDL_TRUE" : "SDL_FALSE"); + SDLTest_AssertCheck(value_bool == SDL_TRUE, + "Verify boolean property, expected SDL_TRUE, got: %s", value_bool ? "SDL_TRUE" : "SDL_FALSE"); /* Check float value */ SDLTest_AssertPass("Call to SDL_SetFloatProperty(\"foo\", 1)"); - SDL_SetFloatProperty(props, "foo", 1.0f); + SDL_SetFloatProperty(props, "foo", 1.75f); type = SDL_GetPropertyType(props, "foo"); SDLTest_AssertCheck(type == SDL_PROPERTY_TYPE_FLOAT, "Verify property type, expected %d, got: %d", SDL_PROPERTY_TYPE_FLOAT, type); @@ -168,21 +168,21 @@ static int properties_testBasic(void *arg) SDLTest_AssertCheck(value == NULL, "Verify property, expected NULL, got: %p", value); value_string = SDL_GetStringProperty(props, "foo", NULL); - SDLTest_AssertCheck(value_string == NULL, - "Verify string property, expected NULL, got: %s", value_string); + SDLTest_AssertCheck(value_string && SDL_strcmp(value_string, "1.750000") == 0, + "Verify string property, expected 1.750000, got: %s", value_string); value_number = SDL_GetNumberProperty(props, "foo", 0); - SDLTest_AssertCheck(value_number == 0, - "Verify number property, expected 0, got: %" SDL_PRIu64 "", value_number); + SDLTest_AssertCheck(value_number == 2, + "Verify number property, expected 2, got: %" SDL_PRIu64 "", value_number); value_float = SDL_GetFloatProperty(props, "foo", 0.0f); - SDLTest_AssertCheck(value_float == 1.0f, - "Verify string property, expected 1, got: %f", value_float); + SDLTest_AssertCheck(value_float == 1.75f, + "Verify float property, expected 1.75, got: %f", value_float); value_bool = SDL_GetBooleanProperty(props, "foo", SDL_FALSE); - SDLTest_AssertCheck(value_bool == SDL_FALSE, - "Verify boolean property, expected SDL_FALSE, got: %s", value_bool ? "SDL_TRUE" : "SDL_FALSE"); + SDLTest_AssertCheck(value_bool == SDL_TRUE, + "Verify boolean property, expected SDL_TRUE, got: %s", value_bool ? "SDL_TRUE" : "SDL_FALSE"); /* Check boolean value */ SDLTest_AssertPass("Call to SDL_SetBooleanProperty(\"foo\", SDL_TRUE)"); - SDL_SetBooleanProperty(props, "foo", SDL_TRUE); + SDL_SetBooleanProperty(props, "foo", 3); /* Note we're testing non-true/false value here */ type = SDL_GetPropertyType(props, "foo"); SDLTest_AssertCheck(type == SDL_PROPERTY_TYPE_BOOLEAN, "Verify property type, expected %d, got: %d", SDL_PROPERTY_TYPE_BOOLEAN, type); @@ -190,14 +190,14 @@ static int properties_testBasic(void *arg) SDLTest_AssertCheck(value == NULL, "Verify property, expected NULL, got: %p", value); value_string = SDL_GetStringProperty(props, "foo", NULL); - SDLTest_AssertCheck(value_string == NULL, - "Verify string property, expected NULL, got: %s", value_string); + SDLTest_AssertCheck(value_string && SDL_strcmp(value_string, "true") == 0, + "Verify string property, expected true, got: %s", value_string); value_number = SDL_GetNumberProperty(props, "foo", 0); - SDLTest_AssertCheck(value_number == 0, - "Verify number property, expected 0, got: %" SDL_PRIu64 "", value_number); + SDLTest_AssertCheck(value_number == 1, + "Verify number property, expected 1, got: %" SDL_PRIu64 "", value_number); value_float = SDL_GetFloatProperty(props, "foo", 0.0f); - SDLTest_AssertCheck(value_float == 0.0f, - "Verify string property, expected 0, got: %f", value_float); + SDLTest_AssertCheck(value_float == 1.0f, + "Verify float property, expected 1, got: %f", value_float); value_bool = SDL_GetBooleanProperty(props, "foo", SDL_FALSE); SDLTest_AssertCheck(value_bool == SDL_TRUE, "Verify boolean property, expected SDL_TRUE, got: %s", value_bool ? "SDL_TRUE" : "SDL_FALSE");