diff --git a/include/SDL3/SDL_properties.h b/include/SDL3/SDL_properties.h index abd7b2aa50..e8c27c10c2 100644 --- a/include/SDL3/SDL_properties.h +++ b/include/SDL3/SDL_properties.h @@ -508,6 +508,21 @@ extern SDL_DECLSPEC bool SDLCALL SDL_GetBooleanProperty(SDL_PropertiesID props, */ extern SDL_DECLSPEC bool SDLCALL SDL_ClearProperty(SDL_PropertiesID props, const char *name); +/** + * Get the current number of items in a group of properties. + * + * For an invalid SDL_PropertiesID, this returns zero and does not set an + * error message. + * + * \param props the properties to query. + * \returns the number of property items available. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL 3.6.0. + */ +extern SDL_DECLSPEC int SDLCALL SDL_GetNumProperties(SDL_PropertiesID props); + /** * A callback used to enumerate all the properties in a group of properties. * diff --git a/src/SDL_hashtable.c b/src/SDL_hashtable.c index 8bc79f7e31..91359231a0 100644 --- a/src/SDL_hashtable.c +++ b/src/SDL_hashtable.c @@ -409,18 +409,23 @@ bool SDL_IterateHashTable(const SDL_HashTable *table, SDL_HashTableIterateCallba return true; } -bool SDL_HashTableEmpty(SDL_HashTable *table) +int SDL_GetNumHashTableItems(SDL_HashTable *table) { CHECK_PARAM(!table) { - return SDL_InvalidParamError("table"); + SDL_InvalidParamError("table"); + return 0; } SDL_LockRWLockForReading(table->lock); - const bool retval = (table->num_occupied_slots == 0); + const int retval = (int) table->num_occupied_slots; SDL_UnlockRWLock(table->lock); return retval; } +bool SDL_HashTableEmpty(SDL_HashTable *table) +{ + return SDL_GetNumHashTableItems(table) <= 0; +} static void destroy_all(SDL_HashTable *table) { diff --git a/src/SDL_hashtable.h b/src/SDL_hashtable.h index e947efc22c..a8a9f099e9 100644 --- a/src/SDL_hashtable.h +++ b/src/SDL_hashtable.h @@ -393,12 +393,30 @@ extern bool SDL_RemoveFromHashTable(SDL_HashTable *table, const void *key); */ extern void SDL_ClearHashTable(SDL_HashTable *table); +/** + * Query the number of items currently in a hash table. + * + * Invalid tables report 0 items. + * + * \param table the hash table to check. + * \returns number of items in the table. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL 3.6.0. + * + * \sa SDL_HashTableEmpty + */ +extern int SDL_GetNumHashTableItems(SDL_HashTable *table); + /** * Check if any items are currently stored in a hash table. * * If there are no items stored (the table is completely empty), this will * return true. * + * Invalid tables report true. + * * \param table the hash table to check. * \returns true if the table is completely empty, false otherwise. * diff --git a/src/SDL_properties.c b/src/SDL_properties.c index f91db7de5a..254d25c46a 100644 --- a/src/SDL_properties.c +++ b/src/SDL_properties.c @@ -746,6 +746,25 @@ bool SDL_ClearProperty(SDL_PropertiesID props, const char *name) return SDL_PrivateSetProperty(props, name, NULL); } +int SDL_GetNumProperties(SDL_PropertiesID props) +{ + if (!props) { + return 0; + } + + SDL_Properties *properties = NULL; + SDL_FindInHashTable(SDL_properties, (const void *)(uintptr_t)props, (const void **)&properties); + if (!properties) { + return 0; + } + + SDL_LockMutex(properties->lock); + const int retval = SDL_GetNumHashTableItems(properties->props); + SDL_UnlockMutex(properties->lock); + return retval; +} + + typedef struct EnumerateOnePropertyData { SDL_EnumeratePropertiesCallback callback; diff --git a/src/dynapi/SDL_dynapi.exports b/src/dynapi/SDL_dynapi.exports index 87e38965c9..f0c685c4be 100644 --- a/src/dynapi/SDL_dynapi.exports +++ b/src/dynapi/SDL_dynapi.exports @@ -1301,3 +1301,4 @@ _SDL_RemoveNotification _SDL_GetDeviceFormFactor _SDL_GetDeviceFormFactorName _SDL_IsUbuntuTouch +_SDL_GetNumProperties diff --git a/src/dynapi/SDL_dynapi.sym b/src/dynapi/SDL_dynapi.sym index 607222b2b7..f30ea16eb5 100644 --- a/src/dynapi/SDL_dynapi.sym +++ b/src/dynapi/SDL_dynapi.sym @@ -1302,6 +1302,7 @@ SDL3_0.0.0 { SDL_GetDeviceFormFactor; SDL_GetDeviceFormFactorName; SDL_IsUbuntuTouch; + SDL_GetNumProperties; # extra symbols go here (don't modify this line) local: *; }; diff --git a/src/dynapi/SDL_dynapi_overrides.h b/src/dynapi/SDL_dynapi_overrides.h index b2d767829f..c7ce948a96 100644 --- a/src/dynapi/SDL_dynapi_overrides.h +++ b/src/dynapi/SDL_dynapi_overrides.h @@ -1328,3 +1328,4 @@ #define SDL_GetDeviceFormFactor SDL_GetDeviceFormFactor_REAL #define SDL_GetDeviceFormFactorName SDL_GetDeviceFormFactorName_REAL #define SDL_IsUbuntuTouch SDL_IsUbuntuTouch_REAL +#define SDL_GetNumProperties SDL_GetNumProperties_REAL diff --git a/src/dynapi/SDL_dynapi_procs.h b/src/dynapi/SDL_dynapi_procs.h index 884cf2ae96..299f77f2e8 100644 --- a/src/dynapi/SDL_dynapi_procs.h +++ b/src/dynapi/SDL_dynapi_procs.h @@ -1336,3 +1336,4 @@ SDL_DYNAPI_PROC(bool,SDL_RemoveNotification,(SDL_NotificationID a),(a),return) SDL_DYNAPI_PROC(SDL_FormFactor,SDL_GetDeviceFormFactor,(void),(),return) SDL_DYNAPI_PROC(const char*,SDL_GetDeviceFormFactorName,(SDL_FormFactor a),(a),return) SDL_DYNAPI_PROC(bool,SDL_IsUbuntuTouch,(void),(),return) +SDL_DYNAPI_PROC(int,SDL_GetNumProperties,(SDL_PropertiesID a),(a),return)