From 0907f345cb36c77bfdcc9e9f9f2942ecb42824a2 Mon Sep 17 00:00:00 2001
From: Sam Lantinga <[EMAIL REDACTED]>
Date: Sun, 12 Nov 2023 09:47:31 -0800
Subject: [PATCH] Added property types: pointer, string, number, float
---
include/SDL3/SDL_properties.h | 171 ++++++++-
include/SDL3/SDL_render.h | 38 +-
include/SDL3/SDL_video.h | 54 +--
src/SDL_properties.c | 345 ++++++++++++++++--
src/core/linux/SDL_fcitx.c | 6 +-
src/core/linux/SDL_ibus.c | 6 +-
src/dynapi/SDL_dynapi.sym | 8 +
src/dynapi/SDL_dynapi_overrides.h | 8 +
src/dynapi/SDL_dynapi_procs.h | 10 +-
src/render/SDL_render.c | 2 +-
src/render/direct3d/SDL_render_d3d.c | 2 +-
src/render/direct3d11/SDL_render_d3d11.c | 2 +-
src/render/direct3d11/SDL_render_winrt.cpp | 2 +-
src/render/direct3d12/SDL_render_d3d12.c | 2 +-
src/render/metal/SDL_render_metal.m | 12 +-
src/render/opengl/SDL_render_gl.c | 10 +-
src/render/opengles2/SDL_render_gles2.c | 8 +-
src/video/SDL_video.c | 6 +-
src/video/cocoa/SDL_cocoawindow.m | 2 +-
src/video/dummy/SDL_nullframebuffer.c | 2 +-
src/video/kmsdrm/SDL_kmsdrmvideo.c | 4 +-
src/video/n3ds/SDL_n3dsframebuffer.c | 2 +-
.../offscreen/SDL_offscreenframebuffer.c | 2 +-
src/video/uikit/SDL_uikitwindow.m | 2 +-
src/video/x11/SDL_x11window.c | 4 +-
test/testautomation_properties.c | 134 ++++++-
test/testautomation_video.c | 19 +-
test/testffmpeg.c | 6 +-
28 files changed, 727 insertions(+), 142 deletions(-)
diff --git a/include/SDL3/SDL_properties.h b/include/SDL3/SDL_properties.h
index 17b280ae19e0..655a21d41551 100644
--- a/include/SDL3/SDL_properties.h
+++ b/include/SDL3/SDL_properties.h
@@ -39,6 +39,18 @@ extern "C" {
*/
typedef Uint32 SDL_PropertiesID;
+/**
+ * SDL property type
+ */
+typedef enum
+{
+ SDL_PROPERTY_TYPE_INVALID,
+ SDL_PROPERTY_TYPE_POINTER,
+ SDL_PROPERTY_TYPE_STRING,
+ SDL_PROPERTY_TYPE_NUMBER,
+ SDL_PROPERTY_TYPE_FLOAT,
+} SDL_PropertyType;
+
/**
* Get the global SDL properties
*
@@ -105,6 +117,28 @@ extern DECLSPEC int SDLCALL SDL_LockProperties(SDL_PropertiesID props);
*/
extern DECLSPEC void SDLCALL SDL_UnlockProperties(SDL_PropertiesID props);
+/**
+ * Set a property on a set of properties with a cleanup function that is
+ * called when the property is deleted
+ *
+ * \param props the properties to modify
+ * \param name the name of the property to modify
+ * \param value the new value of the property, or NULL to delete the property
+ * \param cleanup the function to call when this property is deleted, or NULL
+ * if no cleanup is necessary
+ * \param userdata a pointer that is passed to the cleanup function
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \threadsafety It is safe to call this function from any thread.
+ *
+ * \since This function is available since SDL 3.0.0.
+ *
+ * \sa SDL_GetProperty
+ * \sa SDL_SetProperty
+ */
+extern DECLSPEC int SDLCALL SDL_SetPropertyWithCleanup(SDL_PropertiesID props, const char *name, void *value, void (SDLCALL *cleanup)(void *userdata, void *value), void *userdata);
+
/**
* Set a property on a set of properties
*
@@ -124,15 +158,11 @@ extern DECLSPEC void SDLCALL SDL_UnlockProperties(SDL_PropertiesID props);
extern DECLSPEC int SDLCALL SDL_SetProperty(SDL_PropertiesID props, const char *name, void *value);
/**
- * Set a property on a set of properties with a cleanup function that is
- * called when the property is deleted
+ * Set a string property on a set of properties
*
* \param props the properties to modify
* \param name the name of the property to modify
* \param value the new value of the property, or NULL to delete the property
- * \param cleanup the function to call when this property is deleted, or NULL
- * if no cleanup is necessary
- * \param userdata a pointer that is passed to the cleanup function
* \returns 0 on success or a negative error code on failure; call
* SDL_GetError() for more information.
*
@@ -140,10 +170,56 @@ extern DECLSPEC int SDLCALL SDL_SetProperty(SDL_PropertiesID props, const char *
*
* \since This function is available since SDL 3.0.0.
*
- * \sa SDL_GetProperty
- * \sa SDL_SetProperty
+ * \sa SDL_GetStringProperty
*/
-extern DECLSPEC int SDLCALL SDL_SetPropertyWithCleanup(SDL_PropertiesID props, const char *name, void *value, void (SDLCALL *cleanup)(void *userdata, void *value), void *userdata);
+extern DECLSPEC int SDLCALL SDL_SetStringProperty(SDL_PropertiesID props, const char *name, const char *value);
+
+/**
+ * Set an integer property on a set of properties
+ *
+ * \param props the properties to modify
+ * \param name the name of the property to modify
+ * \param value the new value of the property
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \threadsafety It is safe to call this function from any thread.
+ *
+ * \since This function is available since SDL 3.0.0.
+ *
+ * \sa SDL_GetNumberProperty
+ */
+extern DECLSPEC int SDLCALL SDL_SetNumberProperty(SDL_PropertiesID props, const char *name, Sint64 value);
+
+/**
+ * Set a floating point property on a set of properties
+ *
+ * \param props the properties to modify
+ * \param name the name of the property to modify
+ * \param value the new value of the property
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \threadsafety It is safe to call this function from any thread.
+ *
+ * \since This function is available since SDL 3.0.0.
+ *
+ * \sa SDL_GetFloatProperty
+ */
+extern DECLSPEC int SDLCALL SDL_SetFloatProperty(SDL_PropertiesID props, const char *name, float value);
+
+/**
+ * Get the type of a property on a set of properties
+ *
+ * \param props the properties to query
+ * \param name the name of the property to query
+ * \returns the type of the property, or SDL_PROPERTY_TYPE_INVALID if it is not set.
+ *
+ * \threadsafety It is safe to call this function from any thread.
+ *
+ * \since This function is available since SDL 3.0.0.
+ */
+extern DECLSPEC SDL_PropertyType SDLCALL SDL_GetPropertyType(SDL_PropertiesID props, const char *name);
/**
* Get a property on a set of properties
@@ -155,7 +231,8 @@ extern DECLSPEC int SDLCALL SDL_SetPropertyWithCleanup(SDL_PropertiesID props, c
*
* \param props the properties to query
* \param name the name of the property to query
- * \returns the value of the property, or NULL if it is not set.
+ * \param default_value the default value of the property
+ * \returns the value of the property, or `default_value` if it is not set or not a pointer property.
*
* \threadsafety It is safe to call this function from any thread, although
* the data returned is not protected and could potentially be
@@ -165,9 +242,65 @@ extern DECLSPEC int SDLCALL SDL_SetPropertyWithCleanup(SDL_PropertiesID props, c
*
* \since This function is available since SDL 3.0.0.
*
+ * \sa SDL_GetPropertyType
* \sa SDL_SetProperty
*/
-extern DECLSPEC void *SDLCALL SDL_GetProperty(SDL_PropertiesID props, const char *name);
+extern DECLSPEC void *SDLCALL SDL_GetProperty(SDL_PropertiesID props, const char *name, void *default_value);
+
+/**
+ * Get a string property on a set of properties
+ *
+ * \param props the properties to query
+ * \param name the name of the property to query
+ * \param default_value the default value of the property
+ * \returns the value of the property, or `default_value` if it is not set or not a string property.
+ *
+ * \threadsafety It is safe to call this function from any thread.
+ *
+ * \since This function is available since SDL 3.0.0.
+ *
+ * \sa SDL_GetPropertyType
+ * \sa SDL_SetStringProperty
+ */
+extern DECLSPEC const char *SDLCALL SDL_GetStringProperty(SDL_PropertiesID props, const char *name, const char *default_value);
+
+/**
+ * Get a number property on a set of properties
+ *
+ * You can use SDL_GetPropertyType() to query whether the property exists and is a number property.
+ *
+ * \param props the properties to query
+ * \param name the name of the property to query
+ * \param default_value the default value of the property
+ * \returns the value of the property, or `default_value` if it is not set or not a number property.
+ *
+ * \threadsafety It is safe to call this function from any thread.
+ *
+ * \since This function is available since SDL 3.0.0.
+ *
+ * \sa SDL_GetPropertyType
+ * \sa SDL_SetNumberProperty
+ */
+extern DECLSPEC Sint64 SDLCALL SDL_GetNumberProperty(SDL_PropertiesID props, const char *name, Sint64 default_value);
+
+/**
+ * Get a floating point property on a set of properties
+ *
+ * You can use SDL_GetPropertyType() to query whether the property exists and is a floating point property.
+ *
+ * \param props the properties to query
+ * \param name the name of the property to query
+ * \param default_value the default value of the property
+ * \returns the value of the property, or `default_value` if it is not set or not a float property.
+ *
+ * \threadsafety It is safe to call this function from any thread.
+ *
+ * \since This function is available since SDL 3.0.0.
+ *
+ * \sa SDL_GetPropertyType
+ * \sa SDL_SetFloatProperty
+ */
+extern DECLSPEC float SDLCALL SDL_GetFloatProperty(SDL_PropertiesID props, const char *name, float default_value);
/**
* Clear a property on a set of properties
@@ -185,6 +318,24 @@ extern DECLSPEC void *SDLCALL SDL_GetProperty(SDL_PropertiesID props, const char
*/
extern DECLSPEC int SDLCALL SDL_ClearProperty(SDL_PropertiesID props, const char *name);
+typedef void (SDLCALL *SDL_EnumeratePropertiesCallback)(void *userdata, SDL_PropertiesID props, const char *name);
+/**
+ * Enumerate the properties on a set of properties
+ *
+ * The callback function is called for each property on the set of properties. The properties are locked during enumeration.
+ *
+ * \param props the properties to query
+ * \param callback the function to call for each property
+ * \param userdata a pointer that is passed to `callback`
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \threadsafety It is safe to call this function from any thread.
+ *
+ * \since This function is available since SDL 3.0.0.
+ */
+extern DECLSPEC int SDLCALL SDL_EnumerateProperties(SDL_PropertiesID props, SDL_EnumeratePropertiesCallback callback, void *userdata);
+
/**
* Destroy a set of properties
*
diff --git a/include/SDL3/SDL_render.h b/include/SDL3/SDL_render.h
index 120543dd436e..72cb5d263d81 100644
--- a/include/SDL3/SDL_render.h
+++ b/include/SDL3/SDL_render.h
@@ -311,10 +311,10 @@ extern DECLSPEC int SDLCALL SDL_GetRendererInfo(SDL_Renderer *renderer, SDL_Rend
*
* The following properties are provided by SDL:
* ```
- * "SDL.renderer.d3d9.device" - the IDirect3DDevice9 associated with the renderer
- * "SDL.renderer.d3d11.device" - the ID3D11Device associated with the renderer
- * "SDL.renderer.d3d12.device" - the ID3D12Device associated with the renderer
- * "SDL.renderer.d3d12.command_queue" - the ID3D12CommandQueue associated with the renderer
+ * "SDL.renderer.d3d9.device" (pointer) - the IDirect3DDevice9 associated with the renderer
+ * "SDL.renderer.d3d11.device" (pointer) - the ID3D11Device associated with the renderer
+ * "SDL.renderer.d3d12.device" (pointer) - the ID3D12Device associated with the renderer
+ * "SDL.renderer.d3d12.command_queue" (pointer) - the ID3D12CommandQueue associated with the renderer
* ```
*
* \param renderer the rendering context
@@ -424,33 +424,33 @@ extern DECLSPEC SDL_Texture *SDLCALL SDL_CreateTextureFromSurface(SDL_Renderer *
*
* With the direct3d11 renderer:
* ```
- * "SDL.texture.d3d11.texture" - the ID3D11Texture2D associated with the texture
- * "SDL.texture.d3d11.texture_u" - the ID3D11Texture2D associated with the U plane of a YUV texture
- * "SDL.texture.d3d11.texture_v" - the ID3D11Texture2D associated with the V plane of a YUV texture
+ * "SDL.texture.d3d11.texture" (pointer) - the ID3D11Texture2D associated with the texture
+ * "SDL.texture.d3d11.texture_u" (pointer) - the ID3D11Texture2D associated with the U plane of a YUV texture
+ * "SDL.texture.d3d11.texture_v" (pointer) - the ID3D11Texture2D associated with the V plane of a YUV texture
* ```
*
* With the direct3d12 renderer:
* ```
- * "SDL.texture.d3d12.texture" - the ID3D12Resource associated with the texture
- * "SDL.texture.d3d12.texture_u" - the ID3D12Resource associated with the U plane of a YUV texture
- * "SDL.texture.d3d12.texture_v" - the ID3D12Resource associated with the V plane of a YUV texture
+ * "SDL.texture.d3d12.texture" (pointer) - the ID3D12Resource associated with the texture
+ * "SDL.texture.d3d12.texture_u" (pointer) - the ID3D12Resource associated with the U plane of a YUV texture
+ * "SDL.texture.d3d12.texture_v" (pointer) - the ID3D12Resource associated with the V plane of a YUV texture
* ```
*
* With the opengl renderer:
* ```
- * "SDL.texture.opengl.texture" - the GLuint texture associated with the texture
- * "SDL.texture.opengl.texture_u" - the GLuint texture associated with the U plane of a YUV texture
- * "SDL.texture.opengl.texture_v" - the GLuint texture associated with the V plane of a YUV texture
- * "SDL.texture.opengl.tex_w" - the 16.16 fixed point texture coordinate width of the texture
- * "SDL.texture.opengl.tex_h" - the 16.16 fixed point texture coordinate height of the texture
+ * "SDL.texture.opengl.texture" (number) - the GLuint texture associated with the texture
+ * "SDL.texture.opengl.texture_u" (number) - the GLuint texture associated with the U plane of a YUV texture
+ * "SDL.texture.opengl.texture_v" (number) - the GLuint texture associated with the V plane of a YUV texture
+ * "SDL.texture.opengl.tex_w" (float) - the texture coordinate width of the texture (0.0 - 1.0)
+ * "SDL.texture.opengl.tex_h" (float) - the texture coordinate height of the texture (0.0 - 1.0)
* ```
*
* With the opengles2 renderer:
* ```
- * "SDL.texture.opengles2.texture" - the GLuint texture associated with the texture
- * "SDL.texture.opengles2.texture_uv" - the GLuint texture associated with the UV plane of an NV12 texture
- * "SDL.texture.opengles2.texture_u" - the GLuint texture associated with the U plane of a YUV texture
- * "SDL.texture.opengles2.texture_v" - the GLuint texture associated with the V plane of a YUV texture
+ * "SDL.texture.opengles2.texture" (number) - the GLuint texture associated with the texture
+ * "SDL.texture.opengles2.texture_uv" (number) - the GLuint texture associated with the UV plane of an NV12 texture
+ * "SDL.texture.opengles2.texture_u" (number) - the GLuint texture associated with the U plane of a YUV texture
+ * "SDL.texture.opengles2.texture_v" (number) - the GLuint texture associated with the V plane of a YUV texture
* ```
*
* \param texture the texture to query
diff --git a/include/SDL3/SDL_video.h b/include/SDL3/SDL_video.h
index e0363eccdfaf..e8db562df843 100644
--- a/include/SDL3/SDL_video.h
+++ b/include/SDL3/SDL_video.h
@@ -938,58 +938,58 @@ extern DECLSPEC SDL_Window *SDLCALL SDL_GetWindowParent(SDL_Window *window);
*
* On Android:
* ```
- * "SDL.window.android.window" - the ANativeWindow associated with the window
- * "SDL.window.android.surface" - the EGLSurface associated with the window
+ * "SDL.window.android.window" (pointer) - the ANativeWindow associated with the window
+ * "SDL.window.android.surface" (pointer) - the EGLSurface associated with the window
* ```
*
* On iOS:
* ```
- * "SDL.window.uikit.window" - the (__unsafe_unretained) UIWindow associated with the window
- * "SDL.window.uikit.metal_view_tag" - the NSInteger tag assocated with metal views on the window
+ * "SDL.window.uikit.window" (pointer) - the (__unsafe_unretained) UIWindow associated with the window
+ * "SDL.window.uikit.metal_view_tag" (number) - the NSInteger tag assocated with metal views on the window
* ```
*
* On KMS/DRM:
* ```
- * "SDL.window.kmsdrm.dev_index" - the device index associated with the window (e.g. the X in /dev/dri/cardX)
- * "SDL.window.kmsdrm.drm_fd" - the DRM FD associated with the window
- * "SDL.window.kmsdrm.gbm_dev" - the GBM device associated with the window
+ * "SDL.window.kmsdrm.dev_index" (number) - the device index associated with the window (e.g. the X in /dev/dri/cardX)
+ * "SDL.window.kmsdrm.drm_fd" (number) - the DRM FD associated with the window
+ * "SDL.window.kmsdrm.gbm_dev" (pointer) - the GBM device associated with the window
* ```
*
* On macOS:
* ```
- * "SDL.window.cocoa.window" - the (__unsafe_unretained) NSWindow associated with the window
- * "SDL.window.cocoa.metal_view_tag" - the NSInteger tag assocated with metal views on the window
+ * "SDL.window.cocoa.window" (pointer) - the (__unsafe_unretained) NSWindow associated with the window
+ * "SDL.window.cocoa.metal_view_tag" (number) - the NSInteger tag assocated with metal views on the window
* ```
*
* On Vivante:
* ```
- * "SDL.window.vivante.display" - the EGLNativeDisplayType associated with the window
- * "SDL.window.vivante.window" - the EGLNativeWindowType associated with the window
- * "SDL.window.vivante.surface" - the EGLSurface associated with the window
+ * "SDL.window.vivante.display" (pointer) - the EGLNativeDisplayType associated with the window
+ * "SDL.window.vivante.window" (pointer) - the EGLNativeWindowType associated with the window
+ * "SDL.window.vivante.surface" (pointer) - the EGLSurface associated with the window
* ```
*
* On UWP:
* ```
- * "SDL.window.winrt.window" - the IInspectable CoreWindow associated with the window
+ * "SDL.window.winrt.window" (pointer) - the IInspectable CoreWindow associated with the window
* ```
*
* On Windows:
* ```
- * "SDL.window.win32.hwnd" - the HWND associated with the window
- * "SDL.window.win32.hdc" - the HDC associated with the window
- * "SDL.window.win32.instance" - the HINSTANCE associated with the window
+ * "SDL.window.win32.hwnd" (pointer) - the HWND associated with the window
+ * "SDL.window.win32.hdc" (pointer) - the HDC associated with the window
+ * "SDL.window.win32.instance" (pointer) - the HINSTANCE associated with the window
* ```
*
* On Wayland:
* ```
- * "SDL.window.wayland.registry" - the wl_registry associated with the window
- * "SDL.window.wayland.display" - the wl_display associated with the window
- * "SDL.window.wayland.surface" - the wl_surface associated with the window
- * "SDL.window.wayland.egl_window" - the wl_egl_window associated with the window
- * "SDL.window.wayland.xdg_surface" - the xdg_surface associated with the window
- * "SDL.window.wayland.xdg_toplevel" - the xdg_toplevel role associated with the window
- * "SDL.window.wayland.xdg_popup" - the xdg_popup role associated with the window
- * "SDL.window.wayland.xdg_positioner" - the xdg_positioner associated with the window, in popup mode
+ * "SDL.window.wayland.registry" (pointer) - the wl_registry associated with the window
+ * "SDL.window.wayland.display" (pointer) - the wl_display associated with the window
+ * "SDL.window.wayland.surface" (pointer) - the wl_surface associated with the window
+ * "SDL.window.wayland.egl_window" (pointer) - the wl_egl_window associated with the window
+ * "SDL.window.wayland.xdg_surface" (pointer) - the xdg_surface associated with the window
+ * "SDL.window.wayland.xdg_toplevel" (pointer) - the xdg_toplevel role associated with the window
+ * "SDL.window.wayland.xdg_popup" (pointer) - the xdg_popup role associated with the window
+ * "SDL.window.wayland.xdg_positioner" (pointer) - the xdg_positioner associated with the window, in popup mode
* ```
*
* Note: The xdg_* window objects do not internally persist across window show/hide calls.
@@ -997,9 +997,9 @@ extern DECLSPEC SDL_Window *SDLCALL SDL_GetWindowParent(SDL_Window *window);
*
* On X11:
* ```
- * "SDL.window.x11.display" - the X11 Display associated with the window
- * "SDL.window.x11.screen" - the screen number associated with the window
- * "SDL.window.x11.window" - the X11 Window associated with the window
+ * "SDL.window.x11.display" (pointer) - the X11 Display associated with the window
+ * "SDL.window.x11.screen" (number) - the screen number associated with the window
+ * "SDL.window.x11.window" (number) - the X11 Window associated with the window
* ```
*
* \param window the window to query
diff --git a/src/SDL_properties.c b/src/SDL_properties.c
index de54ee8c3009..5b47b597ac98 100644
--- a/src/SDL_properties.c
+++ b/src/SDL_properties.c
@@ -25,7 +25,15 @@
typedef struct
{
- void *value;
+ SDL_PropertyType type;
+
+ union {
+ void *pointer_value;
+ char *string_value;
+ Sint64 number_value;
+ float float_value;
+ } value;
+
void (SDLCALL *cleanup)(void *userdata, void *value);
void *userdata;
} SDL_Property;
@@ -45,8 +53,19 @@ static SDL_PropertiesID SDL_global_properties;
static void SDL_FreeProperty(const void *key, const void *value, void *data)
{
SDL_Property *property = (SDL_Property *)value;
- if (property->cleanup) {
- property->cleanup(property->userdata, property->value);
+ if (property) {
+ switch (property->type) {
+ case SDL_PROPERTY_TYPE_POINTER:
+ if (property->cleanup) {
+ property->cleanup(property->userdata, property->value.pointer_value);
+ }
+ break;
+ case SDL_PROPERTY_TYPE_STRING:
+ SDL_free(property->value.string_value);
+ break;
+ default:
+ break;
+ }
}
SDL_free((void *)key);
SDL_free((void *)value);
@@ -196,21 +215,17 @@ void SDL_UnlockProperties(SDL_PropertiesID props)
SDL_UnlockMutex(properties->lock);
}
-int SDL_SetProperty(SDL_PropertiesID props, const char *name, void *value)
-{
- return SDL_SetPropertyWithCleanup(props, name, value, NULL, NULL);
-}
-
-int SDL_SetPropertyWithCleanup(SDL_PropertiesID props, const char *name, void *value, void (SDLCALL *cleanup)(void *userdata, void *value), void *userdata)
+static int SDL_PrivateSetProperty(SDL_PropertiesID props, const char *name, SDL_Property *property)
{
SDL_Properties *properties = NULL;
- SDL_Property *property = NULL;
int result = 0;
if (!props) {
+ SDL_FreeProperty(NULL, property, NULL);
return SDL_InvalidParamError("props");
}
if (!name || !*name) {
+ SDL_FreeProperty(NULL, property, NULL);
return SDL_InvalidParamError("name");
}
@@ -219,20 +234,10 @@ int SDL_SetPropertyWithCleanup(SDL_PropertiesID props, const char *name, void *v
SDL_UnlockRWLock(SDL_properties_lock);
if (!properties) {
+ SDL_FreeProperty(NULL, property, NULL);
return SDL_InvalidParamError("props");
}
- if (value) {
- property = (SDL_Property *)SDL_malloc(sizeof(*property));
- if (!property) {
- return SDL_OutOfMemory();
- }
-
- property->value = value;
- property->cleanup = cleanup;
- property->userdata = userdata;
- }
-
SDL_LockMutex(properties->lock);
{
SDL_RemoveFromHashTable(properties->props, name);
@@ -249,18 +254,135 @@ int SDL_SetPropertyWithCleanup(SDL_PropertiesID props, const char *name, void *v
return result;
}
-void *SDL_GetProperty(SDL_PropertiesID props, const char *name)
+int SDL_SetPropertyWithCleanup(SDL_PropertiesID props, const char *name, void *value, void (SDLCALL *cleanup)(void *userdata, void *value), void *userdata)
+{
+ SDL_Property *property;
+
+ if (!value) {
+ return SDL_ClearProperty(props, name);
+ }
+
+ property = (SDL_Property *)SDL_calloc(1, sizeof(*property));
+ if (!property) {
+ return SDL_OutOfMemory();
+ }
+ property->type = SDL_PROPERTY_TYPE_POINTER;
+ property->value.pointer_value = value;
+ property->cleanup = cleanup;
+ property->userdata = userdata;
+ return SDL_PrivateSetProperty(props, name, property);
+}
+
+int SDL_SetProperty(SDL_PropertiesID props, const char *name, void *value)
+{
+ SDL_Property *property;
+
+ if (!value) {
+ return SDL_ClearProperty(props, name);
+ }
+
+ property = (SDL_Property *)SDL_calloc(1, sizeof(*property));
+ if (!property) {
+ return SDL_OutOfMemory();
+ }
+ property->type = SDL_PROPERTY_TYPE_POINTER;
+ property->value.pointer_value = value;
+ return SDL_PrivateSetProperty(props, name, property);
+}
+
+
+int SDL_SetStringProperty(SDL_PropertiesID props, const char *name, const char *value)
+{
+ SDL_Property *property;
+
+ if (!value) {
+ return SDL_ClearProperty(props, name);
+ }
+
+ property = (SDL_Property *)SDL_calloc(1, sizeof(*property));
+ if (!property) {
+ return SDL_OutOfMemory();
+ }
+ property->type = SDL_PROPERTY_TYPE_STRING;
+ property->value.string_value = SDL_strdup(value);
+ if (!property->value.string_value) {
+ SDL_free(property);
+ return SDL_OutOfMemory();
+ }
+ return SDL_PrivateSetProperty(props, name, property);
+}
+
+int SDL_SetNumberProperty(SDL_PropertiesID props, const char *name, Sint64 value)
+{
+ SDL_Property *property = (SDL_Property *)SDL_calloc(1, sizeof(*property));
+ if (!property) {
+ return SDL_OutOfMemory();
+ }
+ property->type = SDL_PROPERTY_TYPE_NUMBER;
+ property->value.number_value = value;
+ return SDL_PrivateSetProperty(props, name, property);
+}
+
+int SDL_SetFloatProperty(SDL_PropertiesID props, const char *name, float value)
+{
+ SDL_Property *property = (SDL_Property *)SDL_calloc(1, sizeof(*property));
+ if (!property) {
+ return SDL_OutOfMemory();
+ }
+ property->type = SDL_PROPERTY_TYPE_FLOAT;
+ property->value.float_value = value;
+ return SDL_PrivateSetProperty(props, name, property);
+}
+
+SDL_PropertyType SDL_GetPropertyType(SDL_PropertiesID props, const char *name)
+{
+ SDL_Properties *properties = NULL;
+ SDL_PropertyType type = SDL_PROPERTY_TYPE_INVALID;
+
+ if (!props) {
+ SDL_InvalidParamError("props");
+ return SDL_PROPERTY_TYPE_INVALID;
+ }
+ if (!name || !*name) {
+ SDL_InvalidParamError("name");
+ return SDL_PROPERTY_TYPE_INVALID;
+ }
+
+ SDL_LockRWLockForReading(SDL_properties_lock);
+ SDL_FindInHashTable(SDL_properties, (const void *)(uintptr_t)props, (const void **)&properties);
+ SDL_UnlockRWLock(SDL_properties_lock);
+
+ if (!properties) {
+ SDL_InvalidParamError("props");
+ return SDL_PROPERTY_TYPE_INVALID;
+ }
+
+ SDL_LockMutex(properties->lock);
+ {
+ SDL_Property *property = NULL;
+ if (SDL_FindInHashTable(properties->props, name, (const void **)&property)) {
+ type = property->type;
+ } else {
+ SDL_SetError("Couldn't find property named %s", name);
+ }
+ }
+ SDL_UnlockMutex(properties->lock);
+
+ return type;
+}
+
+void *SDL_GetProperty(SDL_PropertiesID props, const char *name, void *default_value)
{
SDL_Properties *properties = NULL;
- void *value = NULL;
+ void *value = default_value;
if (!props) {
SDL_InvalidParamError("props");
- return NULL;
+ return value;
}
if (!name || !*name) {
SDL_InvalidParamError("name");
- return NULL;
+ return value;
}
SDL_LockRWLockForReading(SDL_properties_lock);
@@ -269,7 +391,7 @@ void *SDL_GetProperty(SDL_PropertiesID props, const char *name)
if (!properties) {
SDL_InvalidParamError("props");
- return NULL;
+ return value;
}
/* Note that taking the lock here only guarantees that we won't read the
@@ -280,7 +402,140 @@ void *SDL_GetProperty(SDL_PropertiesID props, const char *name)
{
SDL_Property *property = NULL;
if (SDL_FindInHashTable(properties->props, name, (const void **)&property)) {
- value = property->value;
+ if (property->type == SDL_PROPERTY_TYPE_POINTER) {
+ value = property->value.pointer_value;
+ } else {
+ SDL_SetError("Property %s isn't a pointer value", name);
+ }
+ } else {
+ SDL_SetError("Couldn't find property named %s", name);
+ }
+ }
+ SDL_UnlockMutex(properties->lock);
+
+ return value;
+}
+
+const char *SDL_GetStringProperty(SDL_PropertiesID props, const char *name, const char *default_value)
+{
+ SDL_Properties *properties = NULL;
+ const char *value = default_value;
+
+ if (!props) {
+ SDL_InvalidParamError("props");
+ return value;
+ }
+ if (!name || !*name) {
+ SDL_InvalidParamError("name");
+ return value;
+ }
+
+ SDL_LockRWLockForReading(SDL_properties_lock);
+ SDL_FindInHashTable(SDL_properties, (const void *)(uintptr_t)props, (const void **)&properties);
+ SDL_UnlockRWLock(SDL_properties_lock);
+
+ if (!properties) {
+ SDL_InvalidParamError("props");
+ return value;
+ }
+
+ /* Note that taking the lock here only guarantees that we won't read the
+ * hashtable while it's being modified. The value itself can easily be
+ * freed from another thread after it is returned here.
+ *
+ * FIXME: Should we SDL_strdup() the return value to avoid this?
+ */
+ SDL_LockMutex(properties->lock);
+ {
+ SDL_Property *property = NULL;
+ if (SDL_FindInHashTable(properties->props, name, (const void **)&property)) {
+ if (property->type == SDL_PROPERTY_TYPE_STRING) {
+ value = property->value.string_value;
+ } else {
+ SDL_SetError("Property %s isn't a string value", name);
+ }
+ } else {
+ SDL_SetError("Couldn't find property named %s", name);
+ }
+ }
+ SDL_UnlockMutex(properties->lock);
+
+ return value;
+}
+
+Sint64 SDL_GetNumberProperty(SDL_PropertiesID props, const char *name, Sint64 default_value)
+{
+ SDL_Properties *properties = NULL;
+ Sint64 value = default_value;
+
+ if (!props) {
+ SDL_InvalidParamError("props");
+ return value;
+ }
+ if (!name || !*name) {
+ SDL_InvalidParamError("name");
+ return value;
+ }
+
+ SDL_LockRWLockForReading(SDL_properties_lock);
+ SDL_FindInHashTable(SDL_properties, (const void *)(uintptr_t)props, (const void **)&properties);
+ SDL_UnlockRWLock(SDL_properties_lock);
+
+ if (!properties) {
+ SDL_InvalidParamError("props");
+ return value;
+ }
+
+ SDL_LockMutex(properties->lock);
+ {
+ SDL_Property *property = NULL;
+ if (SDL_FindInHashTable(properties->props, name, (const void **)&property)) {
+ if (property->type == SDL_PROPERTY_TYPE_NUMBER) {
+ value = property->value.number_value;
+ } else {
+ SDL_SetError("Property %s isn't a string value", name);
+ }
+ } else {
+ SDL_SetError("Couldn't find property named %s", name);
+
(Patch may be truncated, please check the link at the top of this post.)