mirror of
				https://github.com/libsdl-org/SDL.git
				synced 2025-10-26 12:27:44 +00:00 
			
		
		
		
	Introduce formal policy for APIs that return strings.
This declares that any `const char *` returned from SDL is owned by SDL, and promises to be valid _at least_ until the next time the event queue runs, or SDL_Quit() is called, even if the thing that owns the string gets destroyed or changed before then. This is noted in the headers as "the SDL_GetStringRule", so this will both be greppable to find a detailed explaination in docs/README-strings.md and wikiheaders will automatically turn it into a link we can point at the appropriate documentation. Fixes #9902. (and several FIXMEs, both known and yet-undocumented.)
This commit is contained in:
		
							
								
								
									
										58
									
								
								docs/README-strings.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										58
									
								
								docs/README-strings.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,58 @@ | |||||||
|  | # String policies in SDL3. | ||||||
|  |  | ||||||
|  | ## Encoding. | ||||||
|  |  | ||||||
|  | Unless otherwise specified, all strings in SDL, across all platforms, are | ||||||
|  | UTF-8 encoded. | ||||||
|  |  | ||||||
|  |  | ||||||
|  | ## The SDL Get String Rule. | ||||||
|  |  | ||||||
|  | Did you see 'SDL_GetStringRule' in the wiki or headers? Here are the details | ||||||
|  | that aren't worth copying across dozens of functions' documentation. | ||||||
|  |  | ||||||
|  | tl;dr: If an SDL function returns a `const char *` string, do not modify or | ||||||
|  | free it, and if you need to save it, make a copy right away. | ||||||
|  |  | ||||||
|  | In several cases, SDL wants to return a string to the app, and the question | ||||||
|  | in any library that does this is: _who owns this thing?_ | ||||||
|  |  | ||||||
|  | The answer in almost all cases, is that SDL does, but not for long. | ||||||
|  |  | ||||||
|  | The pointer is only guaranteed to be valid until the next time the event | ||||||
|  | queue is updated, or SDL_Quit is called. | ||||||
|  |  | ||||||
|  | The reason for this is memory safety. | ||||||
|  |  | ||||||
|  | There are several strings that SDL provides that could be freed at | ||||||
|  | any moment. For example, an app calls SDL_GetAudioDeviceName(), which returns | ||||||
|  | a string that is part of the internal audio device structure. But, while this | ||||||
|  | function is returning, the user yanks the USB audio device out of the | ||||||
|  | computer, and SDL decides to deallocate the structure...and the string! | ||||||
|  | Now the app is holding a pointer that didn't live long enough to be useful, | ||||||
|  | and could crash if accessed. | ||||||
|  |  | ||||||
|  | To avoid this, instead of calling SDL_free on a string as soon as it's done | ||||||
|  | with it, SDL adds the pointer to a list. This list is freed at specific | ||||||
|  | points: when the event queue is run (for ongoing cleanup) and when SDL_Quit | ||||||
|  | is called (to catch things that are just hanging around). This allows the | ||||||
|  | app to use a string without worrying about it becoming bogus in the middle | ||||||
|  | of a printf() call. If the app needs it for longer, it should copy it. | ||||||
|  |  | ||||||
|  | When does "the event queue run"? There are several points: | ||||||
|  |  | ||||||
|  | - If the app calls SDL_PumpEvents() _from any thread_. | ||||||
|  | - SDL_PumpEvents is also called by several other APIs internally: | ||||||
|  |   SDL_PollEvent(), SDL_PeepEvents(), SDL_WaitEvent(), | ||||||
|  |   SDL_WaitEventTimeout(), and maybe others. | ||||||
|  | - If you are using [the main callbacks](README-main-functions), the | ||||||
|  |   event queue can run immediately after any of the callback functions return. | ||||||
|  |  | ||||||
|  | Note that these are just guaranteed minimum lifespans; any given string | ||||||
|  | might live much longer--some might even be static memory that is _never_ | ||||||
|  | deallocated--but this rule promises that the app has a safe window. | ||||||
|  |  | ||||||
|  | Note that none of this applies if the return value is `char *` instead of | ||||||
|  | `const char *`. Please see the specific function's documentation for how | ||||||
|  | to handle those pointers. | ||||||
|  |  | ||||||
| @@ -374,9 +374,11 @@ extern SDL_DECLSPEC int SDLCALL SDL_GetNumAudioDrivers(void); | |||||||
|  * first (as far as the SDL developers believe) are earlier in the list. |  * first (as far as the SDL developers believe) are earlier in the list. | ||||||
|  * |  * | ||||||
|  * The names of drivers are all simple, low-ASCII identifiers, like "alsa", |  * The names of drivers are all simple, low-ASCII identifiers, like "alsa", | ||||||
|  * "coreaudio" or "xaudio2". These never have Unicode characters, and are not |  * "coreaudio" or "wasapi". These never have Unicode characters, and are not | ||||||
|  * meant to be proper names. |  * meant to be proper names. | ||||||
|  * |  * | ||||||
|  |  * The returned string follows the SDL_GetStringRule. | ||||||
|  |  * | ||||||
|  * \param index the index of the audio driver; the value ranges from 0 to |  * \param index the index of the audio driver; the value ranges from 0 to | ||||||
|  *              SDL_GetNumAudioDrivers() - 1 |  *              SDL_GetNumAudioDrivers() - 1 | ||||||
|  * \returns the name of the audio driver at the requested index, or NULL if an |  * \returns the name of the audio driver at the requested index, or NULL if an | ||||||
| @@ -394,11 +396,11 @@ extern SDL_DECLSPEC const char *SDLCALL SDL_GetAudioDriver(int index); | |||||||
| /** | /** | ||||||
|  * Get the name of the current audio driver. |  * Get the name of the current audio driver. | ||||||
|  * |  * | ||||||
|  * The returned string points to internal static memory and thus never becomes |  * The names of drivers are all simple, low-ASCII identifiers, like "alsa", | ||||||
|  * invalid, even if you quit the audio subsystem and initialize a new driver |  * "coreaudio" or "wasapi". These never have Unicode characters, and are not | ||||||
|  * (although such a case would return a different static string from another |  * meant to be proper names. | ||||||
|  * call to this function, of course). As such, you should not modify or free |  * | ||||||
|  * the returned string. |  * The returned string follows the SDL_GetStringRule. | ||||||
|  * |  * | ||||||
|  * \returns the name of the current audio driver or NULL if no driver has been |  * \returns the name of the current audio driver or NULL if no driver has been | ||||||
|  *          initialized. |  *          initialized. | ||||||
| @@ -470,8 +472,7 @@ extern SDL_DECLSPEC SDL_AudioDeviceID *SDLCALL SDL_GetAudioCaptureDevices(int *c | |||||||
| /** | /** | ||||||
|  * Get the human-readable name of a specific audio device. |  * Get the human-readable name of a specific audio device. | ||||||
|  * |  * | ||||||
|  * The string returned by this function is UTF-8 encoded. The caller should |  * The returned string follows the SDL_GetStringRule. | ||||||
|  * call SDL_free on the return value when done with it. |  | ||||||
|  * |  * | ||||||
|  * \param devid the instance ID of the device to query. |  * \param devid the instance ID of the device to query. | ||||||
|  * \returns the name of the audio device, or NULL on error. |  * \returns the name of the audio device, or NULL on error. | ||||||
| @@ -484,7 +485,7 @@ extern SDL_DECLSPEC SDL_AudioDeviceID *SDLCALL SDL_GetAudioCaptureDevices(int *c | |||||||
|  * \sa SDL_GetAudioCaptureDevices |  * \sa SDL_GetAudioCaptureDevices | ||||||
|  * \sa SDL_GetDefaultAudioInfo |  * \sa SDL_GetDefaultAudioInfo | ||||||
|  */ |  */ | ||||||
| extern SDL_DECLSPEC char *SDLCALL SDL_GetAudioDeviceName(SDL_AudioDeviceID devid); | extern SDL_DECLSPEC const char *SDLCALL SDL_GetAudioDeviceName(SDL_AudioDeviceID devid); | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * Get the current audio format of a specific audio device. |  * Get the current audio format of a specific audio device. | ||||||
|   | |||||||
| @@ -134,6 +134,8 @@ extern SDL_DECLSPEC int SDLCALL SDL_GetNumCameraDrivers(void); | |||||||
|  * "coremedia" or "android". These never have Unicode characters, and are not |  * "coremedia" or "android". These never have Unicode characters, and are not | ||||||
|  * meant to be proper names. |  * meant to be proper names. | ||||||
|  * |  * | ||||||
|  |  * The returned string follows the SDL_GetStringRule. | ||||||
|  |  * | ||||||
|  * \param index the index of the camera driver; the value ranges from 0 to |  * \param index the index of the camera driver; the value ranges from 0 to | ||||||
|  *              SDL_GetNumCameraDrivers() - 1 |  *              SDL_GetNumCameraDrivers() - 1 | ||||||
|  * \returns the name of the camera driver at the requested index, or NULL if |  * \returns the name of the camera driver at the requested index, or NULL if | ||||||
| @@ -150,11 +152,11 @@ extern SDL_DECLSPEC const char *SDLCALL SDL_GetCameraDriver(int index); | |||||||
| /** | /** | ||||||
|  * Get the name of the current camera driver. |  * Get the name of the current camera driver. | ||||||
|  * |  * | ||||||
|  * The returned string points to internal static memory and thus never becomes |  * The names of drivers are all simple, low-ASCII identifiers, like "v4l2", | ||||||
|  * invalid, even if you quit the camera subsystem and initialize a new driver |  * "coremedia" or "android". These never have Unicode characters, and are not | ||||||
|  * (although such a case would return a different static string from another |  * meant to be proper names. | ||||||
|  * call to this function, of course). As such, you should not modify or free |  * | ||||||
|  * the returned string. |  * The returned string follows the SDL_GetStringRule. | ||||||
|  * |  * | ||||||
|  * \returns the name of the current camera driver or NULL if no driver has |  * \returns the name of the current camera driver or NULL if no driver has | ||||||
|  *          been initialized. |  *          been initialized. | ||||||
|   | |||||||
| @@ -96,15 +96,14 @@ extern SDL_DECLSPEC int SDLCALL SDL_OutOfMemory(void); | |||||||
|  * Error strings are set per-thread, so an error set in a different thread |  * Error strings are set per-thread, so an error set in a different thread | ||||||
|  * will not interfere with the current thread's operation. |  * will not interfere with the current thread's operation. | ||||||
|  * |  * | ||||||
|  * The returned string is internally allocated and must not be freed by the |  * The returned string does **NOT** follow the SDL_GetStringRule! The | ||||||
|  * application. |  * pointer is valid until the current thread's error string is changed, so | ||||||
|  |  * the caller should make a copy if the string is to be used after calling | ||||||
|  |  * into SDL again. | ||||||
|  * |  * | ||||||
|  * \returns a message with information about the specific error that occurred, |  * \returns a message with information about the specific error that occurred, | ||||||
|  *          or an empty string if there hasn't been an error message set since |  *          or an empty string if there hasn't been an error message set since | ||||||
|  *          the last call to SDL_ClearError(). The message is only applicable |  *          the last call to SDL_ClearError(). | ||||||
|  *          when an SDL function has signaled an error. You must check the |  | ||||||
|  *          return values of SDL function calls to determine when to |  | ||||||
|  *          appropriately call SDL_GetError(). |  | ||||||
|  * |  * | ||||||
|  * \since This function is available since SDL 3.0.0. |  * \since This function is available since SDL 3.0.0. | ||||||
|  * |  * | ||||||
|   | |||||||
| @@ -500,6 +500,8 @@ extern SDL_DECLSPEC SDL_bool SDLCALL SDL_IsGamepad(SDL_JoystickID instance_id); | |||||||
|  * |  * | ||||||
|  * This can be called before any gamepads are opened. |  * This can be called before any gamepads are opened. | ||||||
|  * |  * | ||||||
|  |  * The returned string follows the SDL_GetStringRule. | ||||||
|  |  * | ||||||
|  * \param instance_id the joystick instance ID |  * \param instance_id the joystick instance ID | ||||||
|  * \returns the name of the selected gamepad. If no name can be found, this |  * \returns the name of the selected gamepad. If no name can be found, this | ||||||
|  *          function returns NULL; call SDL_GetError() for more information. |  *          function returns NULL; call SDL_GetError() for more information. | ||||||
| @@ -516,6 +518,8 @@ extern SDL_DECLSPEC const char *SDLCALL SDL_GetGamepadInstanceName(SDL_JoystickI | |||||||
|  * |  * | ||||||
|  * This can be called before any gamepads are opened. |  * This can be called before any gamepads are opened. | ||||||
|  * |  * | ||||||
|  |  * The returned string follows the SDL_GetStringRule. | ||||||
|  |  * | ||||||
|  * \param instance_id the joystick instance ID |  * \param instance_id the joystick instance ID | ||||||
|  * \returns the path of the selected gamepad. If no path can be found, this |  * \returns the path of the selected gamepad. If no path can be found, this | ||||||
|  *          function returns NULL; call SDL_GetError() for more information. |  *          function returns NULL; call SDL_GetError() for more information. | ||||||
| @@ -748,6 +752,8 @@ extern SDL_DECLSPEC SDL_JoystickID SDLCALL SDL_GetGamepadInstanceID(SDL_Gamepad | |||||||
| /** | /** | ||||||
|  * Get the implementation-dependent name for an opened gamepad. |  * Get the implementation-dependent name for an opened gamepad. | ||||||
|  * |  * | ||||||
|  |  * The returned string follows the SDL_GetStringRule. | ||||||
|  |  * | ||||||
|  * \param gamepad a gamepad identifier previously returned by |  * \param gamepad a gamepad identifier previously returned by | ||||||
|  *                SDL_OpenGamepad() |  *                SDL_OpenGamepad() | ||||||
|  * \returns the implementation dependent name for the gamepad, or NULL if |  * \returns the implementation dependent name for the gamepad, or NULL if | ||||||
| @@ -762,6 +768,8 @@ extern SDL_DECLSPEC const char *SDLCALL SDL_GetGamepadName(SDL_Gamepad *gamepad) | |||||||
| /** | /** | ||||||
|  * Get the implementation-dependent path for an opened gamepad. |  * Get the implementation-dependent path for an opened gamepad. | ||||||
|  * |  * | ||||||
|  |  * The returned string follows the SDL_GetStringRule. | ||||||
|  |  * | ||||||
|  * \param gamepad a gamepad identifier previously returned by |  * \param gamepad a gamepad identifier previously returned by | ||||||
|  *                SDL_OpenGamepad() |  *                SDL_OpenGamepad() | ||||||
|  * \returns the implementation dependent path for the gamepad, or NULL if |  * \returns the implementation dependent path for the gamepad, or NULL if | ||||||
| @@ -887,6 +895,8 @@ extern SDL_DECLSPEC Uint16 SDLCALL SDL_GetGamepadFirmwareVersion(SDL_Gamepad *ga | |||||||
|  * |  * | ||||||
|  * Returns the serial number of the gamepad, or NULL if it is not available. |  * Returns the serial number of the gamepad, or NULL if it is not available. | ||||||
|  * |  * | ||||||
|  |  * The returned string follows the SDL_GetStringRule. | ||||||
|  |  * | ||||||
|  * \param gamepad the gamepad object to query. |  * \param gamepad the gamepad object to query. | ||||||
|  * \returns the serial number, or NULL if unavailable. |  * \returns the serial number, or NULL if unavailable. | ||||||
|  * |  * | ||||||
| @@ -1045,7 +1055,7 @@ extern SDL_DECLSPEC SDL_GamepadType SDLCALL SDL_GetGamepadTypeFromString(const c | |||||||
| /** | /** | ||||||
|  * Convert from an SDL_GamepadType enum to a string. |  * Convert from an SDL_GamepadType enum to a string. | ||||||
|  * |  * | ||||||
|  * The caller should not SDL_free() the returned string. |  * The returned string follows the SDL_GetStringRule. | ||||||
|  * |  * | ||||||
|  * \param type an enum value for a given SDL_GamepadType |  * \param type an enum value for a given SDL_GamepadType | ||||||
|  * \returns a string for the given type, or NULL if an invalid type is |  * \returns a string for the given type, or NULL if an invalid type is | ||||||
| @@ -1083,7 +1093,7 @@ extern SDL_DECLSPEC SDL_GamepadAxis SDLCALL SDL_GetGamepadAxisFromString(const c | |||||||
| /** | /** | ||||||
|  * Convert from an SDL_GamepadAxis enum to a string. |  * Convert from an SDL_GamepadAxis enum to a string. | ||||||
|  * |  * | ||||||
|  * The caller should not SDL_free() the returned string. |  * The returned string follows the SDL_GetStringRule. | ||||||
|  * |  * | ||||||
|  * \param axis an enum value for a given SDL_GamepadAxis |  * \param axis an enum value for a given SDL_GamepadAxis | ||||||
|  * \returns a string for the given axis, or NULL if an invalid axis is |  * \returns a string for the given axis, or NULL if an invalid axis is | ||||||
| @@ -1158,7 +1168,7 @@ extern SDL_DECLSPEC SDL_GamepadButton SDLCALL SDL_GetGamepadButtonFromString(con | |||||||
| /** | /** | ||||||
|  * Convert from an SDL_GamepadButton enum to a string. |  * Convert from an SDL_GamepadButton enum to a string. | ||||||
|  * |  * | ||||||
|  * The caller should not SDL_free() the returned string. |  * The returned string follows the SDL_GetStringRule. | ||||||
|  * |  * | ||||||
|  * \param button an enum value for a given SDL_GamepadButton |  * \param button an enum value for a given SDL_GamepadButton | ||||||
|  * \returns a string for the given button, or NULL if an invalid button is |  * \returns a string for the given button, or NULL if an invalid button is | ||||||
| @@ -1446,6 +1456,8 @@ extern SDL_DECLSPEC void SDLCALL SDL_CloseGamepad(SDL_Gamepad *gamepad); | |||||||
|  * Return the sfSymbolsName for a given button on a gamepad on Apple |  * Return the sfSymbolsName for a given button on a gamepad on Apple | ||||||
|  * platforms. |  * platforms. | ||||||
|  * |  * | ||||||
|  |  * The returned string follows the SDL_GetStringRule. | ||||||
|  |  * | ||||||
|  * \param gamepad the gamepad to query |  * \param gamepad the gamepad to query | ||||||
|  * \param button a button on the gamepad |  * \param button a button on the gamepad | ||||||
|  * \returns the sfSymbolsName or NULL if the name can't be found |  * \returns the sfSymbolsName or NULL if the name can't be found | ||||||
| @@ -1459,6 +1471,8 @@ extern SDL_DECLSPEC const char* SDLCALL SDL_GetGamepadAppleSFSymbolsNameForButto | |||||||
| /** | /** | ||||||
|  * Return the sfSymbolsName for a given axis on a gamepad on Apple platforms. |  * Return the sfSymbolsName for a given axis on a gamepad on Apple platforms. | ||||||
|  * |  * | ||||||
|  |  * The returned string follows the SDL_GetStringRule. | ||||||
|  |  * | ||||||
|  * \param gamepad the gamepad to query |  * \param gamepad the gamepad to query | ||||||
|  * \param axis an axis on the gamepad |  * \param axis an axis on the gamepad | ||||||
|  * \returns the sfSymbolsName or NULL if the name can't be found |  * \returns the sfSymbolsName or NULL if the name can't be found | ||||||
|   | |||||||
| @@ -948,6 +948,8 @@ extern SDL_DECLSPEC SDL_HapticID *SDLCALL SDL_GetHaptics(int *count); | |||||||
|  * |  * | ||||||
|  * This can be called before any haptic devices are opened. |  * This can be called before any haptic devices are opened. | ||||||
|  * |  * | ||||||
|  |  * The returned string follows the SDL_GetStringRule. | ||||||
|  |  * | ||||||
|  * \param instance_id the haptic device instance ID |  * \param instance_id the haptic device instance ID | ||||||
|  * \returns the name of the selected haptic device. If no name can be found, |  * \returns the name of the selected haptic device. If no name can be found, | ||||||
|  *          this function returns NULL; call SDL_GetError() for more |  *          this function returns NULL; call SDL_GetError() for more | ||||||
| @@ -1011,6 +1013,8 @@ extern SDL_DECLSPEC SDL_HapticID SDLCALL SDL_GetHapticInstanceID(SDL_Haptic *hap | |||||||
| /** | /** | ||||||
|  * Get the implementation dependent name of a haptic device. |  * Get the implementation dependent name of a haptic device. | ||||||
|  * |  * | ||||||
|  |  * The returned string follows the SDL_GetStringRule. | ||||||
|  |  * | ||||||
|  * \param haptic the SDL_Haptic obtained from SDL_OpenJoystick() |  * \param haptic the SDL_Haptic obtained from SDL_OpenJoystick() | ||||||
|  * \returns the name of the selected haptic device. If no name can be found, |  * \returns the name of the selected haptic device. If no name can be found, | ||||||
|  *          this function returns NULL; call SDL_GetError() for more |  *          this function returns NULL; call SDL_GetError() for more | ||||||
|   | |||||||
| @@ -3806,6 +3806,8 @@ extern SDL_DECLSPEC void SDLCALL SDL_ResetHints(void); | |||||||
| /** | /** | ||||||
|  * Get the value of a hint. |  * Get the value of a hint. | ||||||
|  * |  * | ||||||
|  |  * The returned string follows the SDL_GetStringRule. | ||||||
|  |  * | ||||||
|  * \param name the hint to query |  * \param name the hint to query | ||||||
|  * \returns the string value of a hint or NULL if the hint isn't set. |  * \returns the string value of a hint or NULL if the hint isn't set. | ||||||
|  * |  * | ||||||
|   | |||||||
| @@ -231,6 +231,8 @@ extern SDL_DECLSPEC SDL_JoystickID *SDLCALL SDL_GetJoysticks(int *count); | |||||||
|  * |  * | ||||||
|  * This can be called before any joysticks are opened. |  * This can be called before any joysticks are opened. | ||||||
|  * |  * | ||||||
|  |  * The returned string follows the SDL_GetStringRule. | ||||||
|  |  * | ||||||
|  * \param instance_id the joystick instance ID |  * \param instance_id the joystick instance ID | ||||||
|  * \returns the name of the selected joystick. If no name can be found, this |  * \returns the name of the selected joystick. If no name can be found, this | ||||||
|  *          function returns NULL; call SDL_GetError() for more information. |  *          function returns NULL; call SDL_GetError() for more information. | ||||||
| @@ -247,6 +249,8 @@ extern SDL_DECLSPEC const char *SDLCALL SDL_GetJoystickInstanceName(SDL_Joystick | |||||||
|  * |  * | ||||||
|  * This can be called before any joysticks are opened. |  * This can be called before any joysticks are opened. | ||||||
|  * |  * | ||||||
|  |  * The returned string follows the SDL_GetStringRule. | ||||||
|  |  * | ||||||
|  * \param instance_id the joystick instance ID |  * \param instance_id the joystick instance ID | ||||||
|  * \returns the path of the selected joystick. If no path can be found, this |  * \returns the path of the selected joystick. If no path can be found, this | ||||||
|  *          function returns NULL; call SDL_GetError() for more information. |  *          function returns NULL; call SDL_GetError() for more information. | ||||||
| @@ -669,6 +673,8 @@ extern SDL_DECLSPEC SDL_PropertiesID SDLCALL SDL_GetJoystickProperties(SDL_Joyst | |||||||
| /** | /** | ||||||
|  * Get the implementation dependent name of a joystick. |  * Get the implementation dependent name of a joystick. | ||||||
|  * |  * | ||||||
|  |  * The returned string follows the SDL_GetStringRule. | ||||||
|  |  * | ||||||
|  * \param joystick the SDL_Joystick obtained from SDL_OpenJoystick() |  * \param joystick the SDL_Joystick obtained from SDL_OpenJoystick() | ||||||
|  * \returns the name of the selected joystick. If no name can be found, this |  * \returns the name of the selected joystick. If no name can be found, this | ||||||
|  *          function returns NULL; call SDL_GetError() for more information. |  *          function returns NULL; call SDL_GetError() for more information. | ||||||
| @@ -682,6 +688,8 @@ extern SDL_DECLSPEC const char *SDLCALL SDL_GetJoystickName(SDL_Joystick *joysti | |||||||
| /** | /** | ||||||
|  * Get the implementation dependent path of a joystick. |  * Get the implementation dependent path of a joystick. | ||||||
|  * |  * | ||||||
|  |  * The returned string follows the SDL_GetStringRule. | ||||||
|  |  * | ||||||
|  * \param joystick the SDL_Joystick obtained from SDL_OpenJoystick() |  * \param joystick the SDL_Joystick obtained from SDL_OpenJoystick() | ||||||
|  * \returns the path of the selected joystick. If no path can be found, this |  * \returns the path of the selected joystick. If no path can be found, this | ||||||
|  *          function returns NULL; call SDL_GetError() for more information. |  *          function returns NULL; call SDL_GetError() for more information. | ||||||
| @@ -799,6 +807,8 @@ extern SDL_DECLSPEC Uint16 SDLCALL SDL_GetJoystickFirmwareVersion(SDL_Joystick * | |||||||
|  * |  * | ||||||
|  * Returns the serial number of the joystick, or NULL if it is not available. |  * Returns the serial number of the joystick, or NULL if it is not available. | ||||||
|  * |  * | ||||||
|  |  * The returned string follows the SDL_GetStringRule. | ||||||
|  |  * | ||||||
|  * \param joystick the SDL_Joystick obtained from SDL_OpenJoystick() |  * \param joystick the SDL_Joystick obtained from SDL_OpenJoystick() | ||||||
|  * \returns the serial number of the selected joystick, or NULL if |  * \returns the serial number of the selected joystick, or NULL if | ||||||
|  *          unavailable. |  *          unavailable. | ||||||
|   | |||||||
| @@ -109,6 +109,8 @@ extern SDL_DECLSPEC SDL_KeyboardID *SDLCALL SDL_GetKeyboards(int *count); | |||||||
|  * |  * | ||||||
|  * This function returns "" if the keyboard doesn't have a name. |  * This function returns "" if the keyboard doesn't have a name. | ||||||
|  * |  * | ||||||
|  |  * The returned string follows the SDL_GetStringRule. | ||||||
|  |  * | ||||||
|  * \param instance_id the keyboard instance ID |  * \param instance_id the keyboard instance ID | ||||||
|  * \returns the name of the selected keyboard, or NULL on failure; call |  * \returns the name of the selected keyboard, or NULL on failure; call | ||||||
|  *          SDL_GetError() for more information. |  *          SDL_GetError() for more information. | ||||||
| @@ -255,6 +257,8 @@ extern SDL_DECLSPEC SDL_Scancode SDLCALL SDL_GetScancodeFromKey(SDL_Keycode key) | |||||||
|  * |  * | ||||||
|  * See SDL_Scancode for details. |  * See SDL_Scancode for details. | ||||||
|  * |  * | ||||||
|  |  * The returned string follows the SDL_GetStringRule. | ||||||
|  |  * | ||||||
|  * **Warning**: The returned name is by design not stable across platforms, |  * **Warning**: The returned name is by design not stable across platforms, | ||||||
|  * e.g. the name for `SDL_SCANCODE_LGUI` is "Left GUI" under Linux but "Left |  * e.g. the name for `SDL_SCANCODE_LGUI` is "Left GUI" under Linux but "Left | ||||||
|  * Windows" under Microsoft Windows, and some scancodes like |  * Windows" under Microsoft Windows, and some scancodes like | ||||||
| @@ -295,6 +299,8 @@ extern SDL_DECLSPEC SDL_Scancode SDLCALL SDL_GetScancodeFromName(const char *nam | |||||||
|  * |  * | ||||||
|  * See SDL_Scancode and SDL_Keycode for details. |  * See SDL_Scancode and SDL_Keycode for details. | ||||||
|  * |  * | ||||||
|  |  * The returned string follows the SDL_GetStringRule. | ||||||
|  |  * | ||||||
|  * \param key the desired SDL_Keycode to query |  * \param key the desired SDL_Keycode to query | ||||||
|  * \returns a pointer to a UTF-8 string that stays valid at least until the |  * \returns a pointer to a UTF-8 string that stays valid at least until the | ||||||
|  *          next call to this function. If you need it around any longer, you |  *          next call to this function. If you need it around any longer, you | ||||||
|   | |||||||
| @@ -152,6 +152,8 @@ extern SDL_DECLSPEC SDL_MouseID *SDLCALL SDL_GetMice(int *count); | |||||||
|  * |  * | ||||||
|  * This function returns "" if the mouse doesn't have a name. |  * This function returns "" if the mouse doesn't have a name. | ||||||
|  * |  * | ||||||
|  |  * The returned string follows the SDL_GetStringRule. | ||||||
|  |  * | ||||||
|  * \param instance_id the mouse instance ID |  * \param instance_id the mouse instance ID | ||||||
|  * \returns the name of the selected mouse, or NULL on failure; call |  * \returns the name of the selected mouse, or NULL on failure; call | ||||||
|  *          SDL_GetError() for more information. |  *          SDL_GetError() for more information. | ||||||
|   | |||||||
| @@ -224,6 +224,8 @@ extern SDL_DECLSPEC SDL_bool SDLCALL SDL_PenConnected(SDL_PenID instance_id); | |||||||
| /** | /** | ||||||
|  * Retrieves a human-readable description for a SDL_PenID. |  * Retrieves a human-readable description for a SDL_PenID. | ||||||
|  * |  * | ||||||
|  |  * The returned string follows the SDL_GetStringRule. | ||||||
|  |  * | ||||||
|  * \param instance_id The pen to query. |  * \param instance_id The pen to query. | ||||||
|  * \returns A string that contains the name of the pen, intended for human |  * \returns A string that contains the name of the pen, intended for human | ||||||
|  *          consumption. The string might or might not be localised, depending |  *          consumption. The string might or might not be localised, depending | ||||||
|   | |||||||
| @@ -758,6 +758,8 @@ typedef struct SDL_PixelFormat | |||||||
| /** | /** | ||||||
|  * Get the human readable name of a pixel format. |  * Get the human readable name of a pixel format. | ||||||
|  * |  * | ||||||
|  |  * The returned string follows the SDL_GetStringRule. | ||||||
|  |  * | ||||||
|  * \param format the pixel format to query |  * \param format the pixel format to query | ||||||
|  * \returns the human readable name of the specified pixel format or |  * \returns the human readable name of the specified pixel format or | ||||||
|  *          `SDL_PIXELFORMAT_UNKNOWN` if the format isn't recognized. |  *          `SDL_PIXELFORMAT_UNKNOWN` if the format isn't recognized. | ||||||
|   | |||||||
| @@ -48,12 +48,14 @@ extern "C" { | |||||||
|  * - "iOS" |  * - "iOS" | ||||||
|  * - "Android" |  * - "Android" | ||||||
|  * |  * | ||||||
|  |  * The returned string follows the SDL_GetStringRule. | ||||||
|  |  * | ||||||
|  * \returns the name of the platform. If the correct platform name is not |  * \returns the name of the platform. If the correct platform name is not | ||||||
|  *          available, returns a string beginning with the text "Unknown". |  *          available, returns a string beginning with the text "Unknown". | ||||||
|  * |  * | ||||||
|  * \since This function is available since SDL 3.0.0. |  * \since This function is available since SDL 3.0.0. | ||||||
|  */ |  */ | ||||||
| extern SDL_DECLSPEC const char * SDLCALL SDL_GetPlatform (void); | extern SDL_DECLSPEC const char * SDLCALL SDL_GetPlatform(void); | ||||||
|  |  | ||||||
| /* Ends C function definitions when using C++ */ | /* Ends C function definitions when using C++ */ | ||||||
| #ifdef __cplusplus | #ifdef __cplusplus | ||||||
|   | |||||||
| @@ -360,6 +360,8 @@ extern SDL_DECLSPEC void *SDLCALL SDL_GetProperty(SDL_PropertiesID props, const | |||||||
| /** | /** | ||||||
|  * Get a string property on a set of properties. |  * Get a string property on a set of properties. | ||||||
|  * |  * | ||||||
|  |  * The returned string follows the SDL_GetStringRule. | ||||||
|  |  * | ||||||
|  * \param props the properties to query |  * \param props the properties to query | ||||||
|  * \param name the name of the property to query |  * \param name the name of the property to query | ||||||
|  * \param default_value the default value of the property |  * \param default_value the default value of the property | ||||||
|   | |||||||
| @@ -166,8 +166,7 @@ extern SDL_DECLSPEC int SDLCALL SDL_GetNumRenderDrivers(void); | |||||||
|  * "direct3d12" or "metal". These never have Unicode characters, and are not |  * "direct3d12" or "metal". These never have Unicode characters, and are not | ||||||
|  * meant to be proper names. |  * meant to be proper names. | ||||||
|  * |  * | ||||||
|  * The returned value points to a static, read-only string; do not modify or |  * The returned string follows the SDL_GetStringRule. | ||||||
|  * free it! |  | ||||||
|  * |  * | ||||||
|  * \param index the index of the rendering driver; the value ranges from 0 to |  * \param index the index of the rendering driver; the value ranges from 0 to | ||||||
|  *              SDL_GetNumRenderDrivers() - 1 |  *              SDL_GetNumRenderDrivers() - 1 | ||||||
|   | |||||||
| @@ -158,6 +158,8 @@ extern SDL_DECLSPEC SDL_SensorID *SDLCALL SDL_GetSensors(int *count); | |||||||
| /** | /** | ||||||
|  * Get the implementation dependent name of a sensor. |  * Get the implementation dependent name of a sensor. | ||||||
|  * |  * | ||||||
|  |  * The returned string follows the SDL_GetStringRule. | ||||||
|  |  * | ||||||
|  * \param instance_id the sensor instance ID |  * \param instance_id the sensor instance ID | ||||||
|  * \returns the sensor name, or NULL if `instance_id` is not valid |  * \returns the sensor name, or NULL if `instance_id` is not valid | ||||||
|  * |  * | ||||||
| @@ -224,6 +226,8 @@ extern SDL_DECLSPEC SDL_PropertiesID SDLCALL SDL_GetSensorProperties(SDL_Sensor | |||||||
| /** | /** | ||||||
|  * Get the implementation dependent name of a sensor. |  * Get the implementation dependent name of a sensor. | ||||||
|  * |  * | ||||||
|  |  * The returned string follows the SDL_GetStringRule. | ||||||
|  |  * | ||||||
|  * \param sensor The SDL_Sensor object |  * \param sensor The SDL_Sensor object | ||||||
|  * \returns the sensor name, or NULL if `sensor` is NULL. |  * \returns the sensor name, or NULL if `sensor` is NULL. | ||||||
|  * |  * | ||||||
|   | |||||||
| @@ -385,6 +385,8 @@ extern SDL_DECLSPEC void SDLCALL SDL_AndroidBackButton(void); | |||||||
|  * Your internal storage path is typically: |  * Your internal storage path is typically: | ||||||
|  * `/data/data/your.app.package/files`. |  * `/data/data/your.app.package/files`. | ||||||
|  * |  * | ||||||
|  |  * The returned string follows the SDL_GetStringRule. | ||||||
|  |  * | ||||||
|  * \returns the path used for internal storage or NULL on failure; call |  * \returns the path used for internal storage or NULL on failure; call | ||||||
|  *          SDL_GetError() for more information. |  *          SDL_GetError() for more information. | ||||||
|  * |  * | ||||||
| @@ -392,7 +394,7 @@ extern SDL_DECLSPEC void SDLCALL SDL_AndroidBackButton(void); | |||||||
|  * |  * | ||||||
|  * \sa SDL_AndroidGetExternalStorageState |  * \sa SDL_AndroidGetExternalStorageState | ||||||
|  */ |  */ | ||||||
| extern SDL_DECLSPEC const char * SDLCALL SDL_AndroidGetInternalStoragePath(void); | extern SDL_DECLSPEC const char *SDLCALL SDL_AndroidGetInternalStoragePath(void); | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * Get the current state of external storage. |  * Get the current state of external storage. | ||||||
| @@ -422,6 +424,8 @@ extern SDL_DECLSPEC int SDLCALL SDL_AndroidGetExternalStorageState(Uint32 *state | |||||||
|  * Your external storage path is typically: |  * Your external storage path is typically: | ||||||
|  * `/storage/sdcard0/Android/data/your.app.package/files`. |  * `/storage/sdcard0/Android/data/your.app.package/files`. | ||||||
|  * |  * | ||||||
|  |  * The returned string follows the SDL_GetStringRule. | ||||||
|  |  * | ||||||
|  * \returns the path used for external storage for this application on success |  * \returns the path used for external storage for this application on success | ||||||
|  *          or NULL on failure; call SDL_GetError() for more information. |  *          or NULL on failure; call SDL_GetError() for more information. | ||||||
|  * |  * | ||||||
| @@ -576,6 +580,8 @@ typedef enum SDL_WinRT_DeviceFamily | |||||||
|  * |  * | ||||||
|  * https://msdn.microsoft.com/en-us/library/windows/apps/hh464917.aspx |  * https://msdn.microsoft.com/en-us/library/windows/apps/hh464917.aspx | ||||||
|  * |  * | ||||||
|  |  * The returned string follows the SDL_GetStringRule. | ||||||
|  |  * | ||||||
|  * \param pathType the type of path to retrieve, one of SDL_WinRT_Path |  * \param pathType the type of path to retrieve, one of SDL_WinRT_Path | ||||||
|  * \returns a UTF-8 string (8-bit, multi-byte) containing the path, or NULL if |  * \returns a UTF-8 string (8-bit, multi-byte) containing the path, or NULL if | ||||||
|  *          the path is not available for any reason; call SDL_GetError() for |  *          the path is not available for any reason; call SDL_GetError() for | ||||||
|   | |||||||
| @@ -331,8 +331,7 @@ extern SDL_DECLSPEC SDL_Thread *SDLCALL SDL_CreateThreadWithPropertiesRuntime(SD | |||||||
| /** | /** | ||||||
|  * Get the thread name as it was specified in SDL_CreateThread(). |  * Get the thread name as it was specified in SDL_CreateThread(). | ||||||
|  * |  * | ||||||
|  * This is internal memory, not to be freed by the caller, and remains valid |  * The returned string follows the SDL_GetStringRule. | ||||||
|  * until the specified thread is cleaned up by SDL_WaitThread(). |  | ||||||
|  * |  * | ||||||
|  * \param thread the thread to query |  * \param thread the thread to query | ||||||
|  * \returns a pointer to a UTF-8 string that names the specified thread, or |  * \returns a pointer to a UTF-8 string that names the specified thread, or | ||||||
|   | |||||||
| @@ -96,7 +96,7 @@ extern SDL_DECLSPEC SDL_TouchID *SDLCALL SDL_GetTouchDevices(int *count); | |||||||
| /** | /** | ||||||
|  * Get the touch device name as reported from the driver. |  * Get the touch device name as reported from the driver. | ||||||
|  * |  * | ||||||
|  * You do not own the returned string, do not modify or free it. |  * The returned string follows the SDL_GetStringRule. | ||||||
|  * |  * | ||||||
|  * \param touchID the touch device instance ID. |  * \param touchID the touch device instance ID. | ||||||
|  * \returns touch device name, or NULL on error; call SDL_GetError() for more |  * \returns touch device name, or NULL on error; call SDL_GetError() for more | ||||||
| @@ -104,7 +104,7 @@ extern SDL_DECLSPEC SDL_TouchID *SDLCALL SDL_GetTouchDevices(int *count); | |||||||
|  * |  * | ||||||
|  * \since This function is available since SDL 3.0.0. |  * \since This function is available since SDL 3.0.0. | ||||||
|  */ |  */ | ||||||
| extern SDL_DECLSPEC const char* SDLCALL SDL_GetTouchDeviceName(SDL_TouchID touchID); | extern SDL_DECLSPEC const char *SDLCALL SDL_GetTouchDeviceName(SDL_TouchID touchID); | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * Get the type of the given touch device. |  * Get the type of the given touch device. | ||||||
|   | |||||||
| @@ -143,6 +143,8 @@ extern SDL_DECLSPEC int SDLCALL SDL_GetVersion(void); | |||||||
|  * You shouldn't use this function for anything but logging it for debugging |  * You shouldn't use this function for anything but logging it for debugging | ||||||
|  * purposes. The string is not intended to be reliable in any way. |  * purposes. The string is not intended to be reliable in any way. | ||||||
|  * |  * | ||||||
|  |  * The returned string follows the SDL_GetStringRule. | ||||||
|  |  * | ||||||
|  * \returns an arbitrary string, uniquely identifying the exact revision of |  * \returns an arbitrary string, uniquely identifying the exact revision of | ||||||
|  *          the SDL library in use. |  *          the SDL library in use. | ||||||
|  * |  * | ||||||
|   | |||||||
| @@ -338,6 +338,12 @@ extern SDL_DECLSPEC int SDLCALL SDL_GetNumVideoDrivers(void); | |||||||
|  * The video drivers are presented in the order in which they are normally |  * The video drivers are presented in the order in which they are normally | ||||||
|  * checked during initialization. |  * checked during initialization. | ||||||
|  * |  * | ||||||
|  |  * The names of drivers are all simple, low-ASCII identifiers, like "cocoa", | ||||||
|  |  * "x11" or "windows". These never have Unicode characters, and are not | ||||||
|  |  * meant to be proper names. | ||||||
|  |  * | ||||||
|  |  * The returned string follows the SDL_GetStringRule. | ||||||
|  |  * | ||||||
|  * \param index the index of a video driver |  * \param index the index of a video driver | ||||||
|  * \returns the name of the video driver with the given **index**. |  * \returns the name of the video driver with the given **index**. | ||||||
|  * |  * | ||||||
| @@ -350,6 +356,12 @@ extern SDL_DECLSPEC const char *SDLCALL SDL_GetVideoDriver(int index); | |||||||
| /** | /** | ||||||
|  * Get the name of the currently initialized video driver. |  * Get the name of the currently initialized video driver. | ||||||
|  * |  * | ||||||
|  |  * The names of drivers are all simple, low-ASCII identifiers, like "cocoa", | ||||||
|  |  * "x11" or "windows". These never have Unicode characters, and are not | ||||||
|  |  * meant to be proper names. | ||||||
|  |  * | ||||||
|  |  * The returned string follows the SDL_GetStringRule. | ||||||
|  |  * | ||||||
|  * \returns the name of the current video driver or NULL if no driver has been |  * \returns the name of the current video driver or NULL if no driver has been | ||||||
|  *          initialized. |  *          initialized. | ||||||
|  * |  * | ||||||
| @@ -438,6 +450,8 @@ extern SDL_DECLSPEC SDL_PropertiesID SDLCALL SDL_GetDisplayProperties(SDL_Displa | |||||||
| /** | /** | ||||||
|  * Get the name of a display in UTF-8 encoding. |  * Get the name of a display in UTF-8 encoding. | ||||||
|  * |  * | ||||||
|  |  * The returned string follows the SDL_GetStringRule. | ||||||
|  |  * | ||||||
|  * \param displayID the instance ID of the display to query |  * \param displayID the instance ID of the display to query | ||||||
|  * \returns the name of a display or NULL on failure; call SDL_GetError() for |  * \returns the name of a display or NULL on failure; call SDL_GetError() for | ||||||
|  *          more information. |  *          more information. | ||||||
| @@ -1260,6 +1274,8 @@ extern SDL_DECLSPEC int SDLCALL SDL_SetWindowTitle(SDL_Window *window, const cha | |||||||
| /** | /** | ||||||
|  * Get the title of a window. |  * Get the title of a window. | ||||||
|  * |  * | ||||||
|  |  * The returned string follows the SDL_GetStringRule. | ||||||
|  |  * | ||||||
|  * \param window the window to query |  * \param window the window to query | ||||||
|  * \returns the title of the window in UTF-8 format or "" if there is no |  * \returns the title of the window in UTF-8 format or "" if there is no | ||||||
|  *          title. |  *          title. | ||||||
|   | |||||||
| @@ -573,10 +573,11 @@ int SDL_GetVersion(void) | |||||||
| /* Get the library source revision */ | /* Get the library source revision */ | ||||||
| const char *SDL_GetRevision(void) | const char *SDL_GetRevision(void) | ||||||
| { | { | ||||||
|     return SDL_REVISION; |     return SDL_REVISION;  // a string literal, no need to SDL_FreeLater it. | ||||||
| } | } | ||||||
|  |  | ||||||
| /* Get the name of the platform */ | // Get the name of the platform | ||||||
|  | // (a string literal, no need to SDL_FreeLater it.) | ||||||
| const char *SDL_GetPlatform(void) | const char *SDL_GetPlatform(void) | ||||||
| { | { | ||||||
| #if defined(SDL_PLATFORM_AIX) | #if defined(SDL_PLATFORM_AIX) | ||||||
|   | |||||||
| @@ -74,9 +74,7 @@ SDL_bool SDL_SetHintWithPriority(const char *name, const char *value, SDL_HintPr | |||||||
|                     entry->callback(entry->userdata, name, old_value, value); |                     entry->callback(entry->userdata, name, old_value, value); | ||||||
|                     entry = next; |                     entry = next; | ||||||
|                 } |                 } | ||||||
|                 if (old_value) { |                 SDL_FreeLater(old_value); | ||||||
|                     SDL_free(old_value); |  | ||||||
|                 } |  | ||||||
|             } |             } | ||||||
|             hint->priority = priority; |             hint->priority = priority; | ||||||
|             return SDL_TRUE; |             return SDL_TRUE; | ||||||
| @@ -120,7 +118,7 @@ SDL_bool SDL_ResetHint(const char *name) | |||||||
|                     entry = next; |                     entry = next; | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|             SDL_free(hint->value); |             SDL_FreeLater(hint->value); | ||||||
|             hint->value = NULL; |             hint->value = NULL; | ||||||
|             hint->priority = SDL_HINT_DEFAULT; |             hint->priority = SDL_HINT_DEFAULT; | ||||||
|             return SDL_TRUE; |             return SDL_TRUE; | ||||||
| @@ -147,7 +145,7 @@ void SDL_ResetHints(void) | |||||||
|                 entry = next; |                 entry = next; | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|         SDL_free(hint->value); |         SDL_FreeLater(hint->value); | ||||||
|         hint->value = NULL; |         hint->value = NULL; | ||||||
|         hint->priority = SDL_HINT_DEFAULT; |         hint->priority = SDL_HINT_DEFAULT; | ||||||
|     } |     } | ||||||
| @@ -305,7 +303,7 @@ void SDL_ClearHints(void) | |||||||
|         SDL_hints = hint->next; |         SDL_hints = hint->next; | ||||||
|  |  | ||||||
|         SDL_free(hint->name); |         SDL_free(hint->name); | ||||||
|         SDL_free(hint->value); |         SDL_FreeLater(hint->value); | ||||||
|         for (entry = hint->callbacks; entry;) { |         for (entry = hint->callbacks; entry;) { | ||||||
|             SDL_HintWatch *freeable = entry; |             SDL_HintWatch *freeable = entry; | ||||||
|             entry = entry->next; |             entry = entry->next; | ||||||
|   | |||||||
| @@ -293,6 +293,13 @@ extern int SDLCALL SDL_WaitSemaphoreTimeoutNS(SDL_Semaphore *sem, Sint64 timeout | |||||||
| extern int SDLCALL SDL_WaitConditionTimeoutNS(SDL_Condition *cond, SDL_Mutex *mutex, Sint64 timeoutNS); | extern int SDLCALL SDL_WaitConditionTimeoutNS(SDL_Condition *cond, SDL_Mutex *mutex, Sint64 timeoutNS); | ||||||
| extern SDL_bool SDLCALL SDL_WaitEventTimeoutNS(SDL_Event *event, Sint64 timeoutNS); | extern SDL_bool SDLCALL SDL_WaitEventTimeoutNS(SDL_Event *event, Sint64 timeoutNS); | ||||||
|  |  | ||||||
|  | /* Queue `memory` to be passed to SDL_free once the event queue is emptied. | ||||||
|  |    this manages the list of pointers to SDL_AllocateEventMemory, but you | ||||||
|  |    can use it to queue pointers from other subsystems that can die at any | ||||||
|  |    moment but definitely need to live long enough for the app to copy them | ||||||
|  |    if they happened to query them in their last moments. */ | ||||||
|  | extern void *SDL_FreeLater(void *memory); | ||||||
|  |  | ||||||
| /* Ends C function definitions when using C++ */ | /* Ends C function definitions when using C++ */ | ||||||
| #ifdef __cplusplus | #ifdef __cplusplus | ||||||
| } | } | ||||||
|   | |||||||
| @@ -65,14 +65,12 @@ static void SDL_FreePropertyWithCleanup(const void *key, const void *value, void | |||||||
|             } |             } | ||||||
|             break; |             break; | ||||||
|         case SDL_PROPERTY_TYPE_STRING: |         case SDL_PROPERTY_TYPE_STRING: | ||||||
|             SDL_free(property->value.string_value); |             SDL_FreeLater(property->value.string_value);  // this pointer might be given to the app by SDL_GetStringProperty. | ||||||
|             break; |             break; | ||||||
|         default: |         default: | ||||||
|             break; |             break; | ||||||
|         } |         } | ||||||
|         if (property->string_storage) { |         SDL_FreeLater(property->string_storage);  // this pointer might be given to the app by SDL_GetStringProperty. | ||||||
|             SDL_free(property->string_storage); |  | ||||||
|         } |  | ||||||
|     } |     } | ||||||
|     SDL_free((void *)key); |     SDL_free((void *)key); | ||||||
|     SDL_free((void *)value); |     SDL_free((void *)value); | ||||||
| @@ -552,12 +550,6 @@ const char *SDL_GetStringProperty(SDL_PropertiesID props, const char *name, cons | |||||||
|         return value; |         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_LockMutex(properties->lock); | ||||||
|     { |     { | ||||||
|         SDL_Property *property = NULL; |         SDL_Property *property = NULL; | ||||||
|   | |||||||
| @@ -131,6 +131,7 @@ int SDL_GetNumAudioDrivers(void) | |||||||
|     return num_drivers; |     return num_drivers; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | // this returns string literals, so there's no need to use SDL_FreeLater. | ||||||
| const char *SDL_GetAudioDriver(int index) | const char *SDL_GetAudioDriver(int index) | ||||||
| { | { | ||||||
|     if (index >= 0 && index < SDL_GetNumAudioDrivers()) { |     if (index >= 0 && index < SDL_GetNumAudioDrivers()) { | ||||||
| @@ -139,6 +140,7 @@ const char *SDL_GetAudioDriver(int index) | |||||||
|     return NULL; |     return NULL; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | // this returns string literals, so there's no need to use SDL_FreeLater. | ||||||
| const char *SDL_GetCurrentAudioDriver(void) | const char *SDL_GetCurrentAudioDriver(void) | ||||||
| { | { | ||||||
|     return current_audio.name; |     return current_audio.name; | ||||||
| @@ -521,7 +523,7 @@ static void DestroyPhysicalAudioDevice(SDL_AudioDevice *device) | |||||||
|     SDL_DestroyMutex(device->lock); |     SDL_DestroyMutex(device->lock); | ||||||
|     SDL_DestroyCondition(device->close_cond); |     SDL_DestroyCondition(device->close_cond); | ||||||
|     SDL_free(device->work_buffer); |     SDL_free(device->work_buffer); | ||||||
|     SDL_free(device->name); |     SDL_FreeLater(device->name);  // this pointer is handed to the app during SDL_GetAudioDeviceName | ||||||
|     SDL_free(device); |     SDL_free(device); | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -1402,12 +1404,12 @@ SDL_AudioDevice *SDL_FindPhysicalAudioDeviceByHandle(void *handle) | |||||||
|     return SDL_FindPhysicalAudioDeviceByCallback(TestDeviceHandleCallback, handle); |     return SDL_FindPhysicalAudioDeviceByCallback(TestDeviceHandleCallback, handle); | ||||||
| } | } | ||||||
|  |  | ||||||
| char *SDL_GetAudioDeviceName(SDL_AudioDeviceID devid) | const char *SDL_GetAudioDeviceName(SDL_AudioDeviceID devid) | ||||||
| { | { | ||||||
|     char *retval = NULL; |     const char *retval = NULL; | ||||||
|     SDL_AudioDevice *device = ObtainPhysicalAudioDevice(devid); |     SDL_AudioDevice *device = ObtainPhysicalAudioDevice(devid); | ||||||
|     if (device) { |     if (device) { | ||||||
|         retval = SDL_strdup(device->name); |         retval = device->name; | ||||||
|     } |     } | ||||||
|     ReleaseAudioDevice(device); |     ReleaseAudioDevice(device); | ||||||
|  |  | ||||||
|   | |||||||
| @@ -63,6 +63,7 @@ int SDL_GetNumCameraDrivers(void) | |||||||
|     return SDL_arraysize(bootstrap) - 1; |     return SDL_arraysize(bootstrap) - 1; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | // this returns string literals, so there's no need to use SDL_FreeLater. | ||||||
| const char *SDL_GetCameraDriver(int index) | const char *SDL_GetCameraDriver(int index) | ||||||
| { | { | ||||||
|     if (index >= 0 && index < SDL_GetNumCameraDrivers()) { |     if (index >= 0 && index < SDL_GetNumCameraDrivers()) { | ||||||
| @@ -71,6 +72,7 @@ const char *SDL_GetCameraDriver(int index) | |||||||
|     return NULL; |     return NULL; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | // this returns string literals, so there's no need to use SDL_FreeLater. | ||||||
| const char *SDL_GetCurrentCameraDriver(void) | const char *SDL_GetCurrentCameraDriver(void) | ||||||
| { | { | ||||||
|     return camera_driver.name; |     return camera_driver.name; | ||||||
|   | |||||||
| @@ -141,7 +141,7 @@ int SDL_AndroidGetExternalStorageState(Uint32 *state) | |||||||
|     return SDL_Unsupported(); |     return SDL_Unsupported(); | ||||||
| } | } | ||||||
| SDL_DECLSPEC const char *SDLCALL SDL_AndroidGetInternalStoragePath(void); | SDL_DECLSPEC const char *SDLCALL SDL_AndroidGetInternalStoragePath(void); | ||||||
| const char *SDL_AndroidGetInternalStoragePath() | const char *SDL_AndroidGetInternalStoragePath(void) | ||||||
| { | { | ||||||
|     SDL_Unsupported(); |     SDL_Unsupported(); | ||||||
|     return NULL; |     return NULL; | ||||||
|   | |||||||
| @@ -2417,6 +2417,7 @@ void SDL_AndroidBackButton(void) | |||||||
|     (*env)->CallStaticVoidMethod(env, mActivityClass, midManualBackButton); |     (*env)->CallStaticVoidMethod(env, mActivityClass, midManualBackButton); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | // this caches a string until the process ends, so there's no need to use SDL_FreeLater. | ||||||
| const char *SDL_AndroidGetInternalStoragePath(void) | const char *SDL_AndroidGetInternalStoragePath(void) | ||||||
| { | { | ||||||
|     static char *s_AndroidInternalFilesPath = NULL; |     static char *s_AndroidInternalFilesPath = NULL; | ||||||
| @@ -2516,6 +2517,7 @@ int SDL_AndroidGetExternalStorageState(Uint32 *state) | |||||||
|     return 0; |     return 0; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | // this caches a string until the process ends, so there's no need to use SDL_FreeLater. | ||||||
| const char *SDL_AndroidGetExternalStoragePath(void) | const char *SDL_AndroidGetExternalStoragePath(void) | ||||||
| { | { | ||||||
|     static char *s_AndroidExternalFilesPath = NULL; |     static char *s_AndroidExternalFilesPath = NULL; | ||||||
|   | |||||||
| @@ -213,7 +213,7 @@ SDL_DYNAPI_PROC(SDL_AssertionHandler,SDL_GetAssertionHandler,(void **a),(a),retu | |||||||
| SDL_DYNAPI_PROC(const SDL_AssertData*,SDL_GetAssertionReport,(void),(),return) | SDL_DYNAPI_PROC(const SDL_AssertData*,SDL_GetAssertionReport,(void),(),return) | ||||||
| SDL_DYNAPI_PROC(SDL_AudioDeviceID*,SDL_GetAudioCaptureDevices,(int *a),(a),return) | SDL_DYNAPI_PROC(SDL_AudioDeviceID*,SDL_GetAudioCaptureDevices,(int *a),(a),return) | ||||||
| SDL_DYNAPI_PROC(int,SDL_GetAudioDeviceFormat,(SDL_AudioDeviceID a, SDL_AudioSpec *b, int *c),(a,b,c),return) | SDL_DYNAPI_PROC(int,SDL_GetAudioDeviceFormat,(SDL_AudioDeviceID a, SDL_AudioSpec *b, int *c),(a,b,c),return) | ||||||
| SDL_DYNAPI_PROC(char*,SDL_GetAudioDeviceName,(SDL_AudioDeviceID a),(a),return) | SDL_DYNAPI_PROC(const char*,SDL_GetAudioDeviceName,(SDL_AudioDeviceID a),(a),return) | ||||||
| SDL_DYNAPI_PROC(const char*,SDL_GetAudioDriver,(int a),(a),return) | SDL_DYNAPI_PROC(const char*,SDL_GetAudioDriver,(int a),(a),return) | ||||||
| SDL_DYNAPI_PROC(SDL_AudioDeviceID*,SDL_GetAudioOutputDevices,(int *a),(a),return) | SDL_DYNAPI_PROC(SDL_AudioDeviceID*,SDL_GetAudioOutputDevices,(int *a),(a),return) | ||||||
| SDL_DYNAPI_PROC(int,SDL_GetAudioStreamAvailable,(SDL_AudioStream *a),(a),return) | SDL_DYNAPI_PROC(int,SDL_GetAudioStreamAvailable,(SDL_AudioStream *a),(a),return) | ||||||
|   | |||||||
| @@ -108,37 +108,40 @@ static SDL_Mutex *SDL_event_memory_lock; | |||||||
| static SDL_EventMemory *SDL_event_memory_head; | static SDL_EventMemory *SDL_event_memory_head; | ||||||
| static SDL_EventMemory *SDL_event_memory_tail; | static SDL_EventMemory *SDL_event_memory_tail; | ||||||
|  |  | ||||||
| void *SDL_AllocateEventMemory(size_t size) | void *SDL_FreeLater(void *memory) | ||||||
| { | { | ||||||
|     void *memory = SDL_malloc(size); |     if (memory == NULL) { | ||||||
|     if (!memory) { |  | ||||||
|         return NULL; |         return NULL; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     SDL_EventMemory *entry = (SDL_EventMemory *)SDL_malloc(sizeof(*entry)); | ||||||
|  |     if (!entry) { | ||||||
|  |         return memory;  // this is now a leak, but you probably have bigger problems if malloc failed. We could probably pool up and reuse entries, though. | ||||||
|  |     } | ||||||
|  |  | ||||||
|     SDL_LockMutex(SDL_event_memory_lock); |     SDL_LockMutex(SDL_event_memory_lock); | ||||||
|     { |     { | ||||||
|         SDL_EventMemory *entry = (SDL_EventMemory *)SDL_malloc(sizeof(*entry)); |         entry->eventID = SDL_last_event_id; | ||||||
|         if (entry) { |         entry->memory = memory; | ||||||
|             entry->eventID = SDL_last_event_id; |         entry->next = NULL; | ||||||
|             entry->memory = memory; |  | ||||||
|             entry->next = NULL; |  | ||||||
|  |  | ||||||
|             if (SDL_event_memory_tail) { |         if (SDL_event_memory_tail) { | ||||||
|                 SDL_event_memory_tail->next = entry; |             SDL_event_memory_tail->next = entry; | ||||||
|             } else { |  | ||||||
|                 SDL_event_memory_head = entry; |  | ||||||
|             } |  | ||||||
|             SDL_event_memory_tail = entry; |  | ||||||
|         } else { |         } else { | ||||||
|             SDL_free(memory); |             SDL_event_memory_head = entry; | ||||||
|             memory = NULL; |  | ||||||
|         } |         } | ||||||
|  |         SDL_event_memory_tail = entry; | ||||||
|     } |     } | ||||||
|     SDL_UnlockMutex(SDL_event_memory_lock); |     SDL_UnlockMutex(SDL_event_memory_lock); | ||||||
|  |  | ||||||
|     return memory; |     return memory; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | void *SDL_AllocateEventMemory(size_t size) | ||||||
|  | { | ||||||
|  |     return SDL_FreeLater(SDL_malloc(size)); | ||||||
|  | } | ||||||
|  |  | ||||||
| static void SDL_FlushEventMemory(Uint32 eventID) | static void SDL_FlushEventMemory(Uint32 eventID) | ||||||
| { | { | ||||||
|     SDL_LockMutex(SDL_event_memory_lock); |     SDL_LockMutex(SDL_event_memory_lock); | ||||||
|   | |||||||
| @@ -742,7 +742,7 @@ void SDL_RemoveKeyboard(SDL_KeyboardID keyboardID, SDL_bool send_event) | |||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     SDL_free(SDL_keyboards[keyboard_index].name); |     SDL_FreeLater(SDL_keyboards[keyboard_index].name); | ||||||
|  |  | ||||||
|     if (keyboard_index != SDL_keyboard_count - 1) { |     if (keyboard_index != SDL_keyboard_count - 1) { | ||||||
|         SDL_memcpy(&SDL_keyboards[keyboard_index], &SDL_keyboards[keyboard_index + 1], (SDL_keyboard_count - keyboard_index - 1) * sizeof(SDL_keyboards[keyboard_index])); |         SDL_memcpy(&SDL_keyboards[keyboard_index], &SDL_keyboards[keyboard_index + 1], (SDL_keyboard_count - keyboard_index - 1) * sizeof(SDL_keyboards[keyboard_index])); | ||||||
| @@ -1334,6 +1334,7 @@ SDL_Scancode SDL_GetScancodeFromKey(SDL_Keycode key) | |||||||
|     return SDL_SCANCODE_UNKNOWN; |     return SDL_SCANCODE_UNKNOWN; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | // these are static memory, so we don't use SDL_FreeLater on them. | ||||||
| const char *SDL_GetScancodeName(SDL_Scancode scancode) | const char *SDL_GetScancodeName(SDL_Scancode scancode) | ||||||
| { | { | ||||||
|     const char *name; |     const char *name; | ||||||
| @@ -1374,7 +1375,7 @@ SDL_Scancode SDL_GetScancodeFromName(const char *name) | |||||||
|  |  | ||||||
| const char *SDL_GetKeyName(SDL_Keycode key) | const char *SDL_GetKeyName(SDL_Keycode key) | ||||||
| { | { | ||||||
|     static char name[8]; |     char name[8]; | ||||||
|     char *end; |     char *end; | ||||||
|  |  | ||||||
|     if (key & SDLK_SCANCODE_MASK) { |     if (key & SDLK_SCANCODE_MASK) { | ||||||
| @@ -1405,7 +1406,7 @@ const char *SDL_GetKeyName(SDL_Keycode key) | |||||||
|  |  | ||||||
|         end = SDL_UCS4ToUTF8((Uint32)key, name); |         end = SDL_UCS4ToUTF8((Uint32)key, name); | ||||||
|         *end = '\0'; |         *end = '\0'; | ||||||
|         return name; |         return SDL_FreeLater(SDL_strdup(name)); | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -288,7 +288,7 @@ void SDL_RemoveMouse(SDL_MouseID mouseID, SDL_bool send_event) | |||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     SDL_free(SDL_mice[mouse_index].name); |     SDL_FreeLater(SDL_mice[mouse_index].name);  // SDL_GetMouseInstanceName returns this pointer. | ||||||
|  |  | ||||||
|     if (mouse_index != SDL_mouse_count - 1) { |     if (mouse_index != SDL_mouse_count - 1) { | ||||||
|         SDL_memcpy(&SDL_mice[mouse_index], &SDL_mice[mouse_index + 1], (SDL_mouse_count - mouse_index - 1) * sizeof(SDL_mice[mouse_index])); |         SDL_memcpy(&SDL_mice[mouse_index], &SDL_mice[mouse_index + 1], (SDL_mouse_count - mouse_index - 1) * sizeof(SDL_mice[mouse_index])); | ||||||
|   | |||||||
| @@ -493,7 +493,7 @@ void SDL_DelTouch(SDL_TouchID id) | |||||||
|         SDL_free(touch->fingers[i]); |         SDL_free(touch->fingers[i]); | ||||||
|     } |     } | ||||||
|     SDL_free(touch->fingers); |     SDL_free(touch->fingers); | ||||||
|     SDL_free(touch->name); |     SDL_FreeLater(touch->name);  // this pointer might be given to the app by SDL_GetTouchDeviceName. | ||||||
|     SDL_free(touch); |     SDL_free(touch); | ||||||
|  |  | ||||||
|     SDL_num_touch--; |     SDL_num_touch--; | ||||||
|   | |||||||
| @@ -93,6 +93,7 @@ static const wchar_t *SDL_WinRTGetFSPathUNICODE(SDL_WinRT_Path pathType) | |||||||
|     return NULL; |     return NULL; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | // this caches a string until the process ends, so there's no need to use SDL_FreeLater. | ||||||
| extern "C" const char *SDL_WinRTGetFSPath(SDL_WinRT_Path pathType) | extern "C" const char *SDL_WinRTGetFSPath(SDL_WinRT_Path pathType) | ||||||
| { | { | ||||||
|     typedef unordered_map<SDL_WinRT_Path, string> UTF8PathMap; |     typedef unordered_map<SDL_WinRT_Path, string> UTF8PathMap; | ||||||
|   | |||||||
| @@ -100,7 +100,7 @@ const char *SDL_GetHapticInstanceName(SDL_HapticID instance_id) | |||||||
|     if (SDL_GetHapticIndex(instance_id, &device_index)) { |     if (SDL_GetHapticIndex(instance_id, &device_index)) { | ||||||
|         name = SDL_SYS_HapticName(device_index); |         name = SDL_SYS_HapticName(device_index); | ||||||
|     } |     } | ||||||
|     return name; |     return name ? SDL_FreeLater(SDL_strdup(name)) : NULL; | ||||||
| } | } | ||||||
|  |  | ||||||
| SDL_Haptic *SDL_OpenHaptic(SDL_HapticID instance_id) | SDL_Haptic *SDL_OpenHaptic(SDL_HapticID instance_id) | ||||||
| @@ -338,7 +338,7 @@ void SDL_CloseHaptic(SDL_Haptic *haptic) | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     /* Free the data associated with this device */ |     /* Free the data associated with this device */ | ||||||
|     SDL_free(haptic->name); |     SDL_FreeLater(haptic->name);  // this pointer is handed to the app in SDL_GetHapticName() | ||||||
|     SDL_free(haptic); |     SDL_free(haptic); | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -1594,7 +1594,7 @@ static GamepadMapping_t *SDL_PrivateAddMappingForGUID(SDL_JoystickGUID jGUID, co | |||||||
|         /* Only overwrite the mapping if the priority is the same or higher. */ |         /* Only overwrite the mapping if the priority is the same or higher. */ | ||||||
|         if (pGamepadMapping->priority <= priority) { |         if (pGamepadMapping->priority <= priority) { | ||||||
|             /* Update existing mapping */ |             /* Update existing mapping */ | ||||||
|             SDL_free(pGamepadMapping->name); |             SDL_FreeLater(pGamepadMapping->name);  // this is returned in SDL_GetGamepadName. | ||||||
|             pGamepadMapping->name = pchName; |             pGamepadMapping->name = pchName; | ||||||
|             SDL_free(pGamepadMapping->mapping); |             SDL_free(pGamepadMapping->mapping); | ||||||
|             pGamepadMapping->mapping = pchMapping; |             pGamepadMapping->mapping = pchMapping; | ||||||
| @@ -3413,7 +3413,8 @@ const char * SDL_GetGamepadSerial(SDL_Gamepad *gamepad) | |||||||
|     if (!joystick) { |     if (!joystick) { | ||||||
|         return NULL; |         return NULL; | ||||||
|     } |     } | ||||||
|     return SDL_GetJoystickSerial(joystick); |     return SDL_GetJoystickSerial(joystick);  // this already returns a SDL_FreeLater pointer. | ||||||
|  |  | ||||||
| } | } | ||||||
|  |  | ||||||
| Uint64 SDL_GetGamepadSteamHandle(SDL_Gamepad *gamepad) | Uint64 SDL_GetGamepadSteamHandle(SDL_Gamepad *gamepad) | ||||||
| @@ -3680,7 +3681,7 @@ void SDL_QuitGamepadMappings(void) | |||||||
|     while (s_pSupportedGamepads) { |     while (s_pSupportedGamepads) { | ||||||
|         pGamepadMap = s_pSupportedGamepads; |         pGamepadMap = s_pSupportedGamepads; | ||||||
|         s_pSupportedGamepads = s_pSupportedGamepads->next; |         s_pSupportedGamepads = s_pSupportedGamepads->next; | ||||||
|         SDL_free(pGamepadMap->name); |         SDL_FreeLater(pGamepadMap->name);  // this is returned in SDL_GetGamepadName. | ||||||
|         SDL_free(pGamepadMap->mapping); |         SDL_free(pGamepadMap->mapping); | ||||||
|         SDL_free(pGamepadMap); |         SDL_free(pGamepadMap); | ||||||
|     } |     } | ||||||
| @@ -3826,8 +3827,8 @@ void SDL_GamepadHandleDelayedGuideButton(SDL_Joystick *joystick) | |||||||
| const char *SDL_GetGamepadAppleSFSymbolsNameForButton(SDL_Gamepad *gamepad, SDL_GamepadButton button) | const char *SDL_GetGamepadAppleSFSymbolsNameForButton(SDL_Gamepad *gamepad, SDL_GamepadButton button) | ||||||
| { | { | ||||||
| #ifdef SDL_JOYSTICK_MFI | #ifdef SDL_JOYSTICK_MFI | ||||||
|     const char *IOS_GetAppleSFSymbolsNameForButton(SDL_Gamepad *gamepad, SDL_GamepadButton button); |     char *IOS_GetAppleSFSymbolsNameForButton(SDL_Gamepad *gamepad, SDL_GamepadButton button); | ||||||
|     const char *retval; |     char *retval; | ||||||
|  |  | ||||||
|     SDL_LockJoysticks(); |     SDL_LockJoysticks(); | ||||||
|     { |     { | ||||||
| @@ -3837,9 +3838,11 @@ const char *SDL_GetGamepadAppleSFSymbolsNameForButton(SDL_Gamepad *gamepad, SDL_ | |||||||
|     } |     } | ||||||
|     SDL_UnlockJoysticks(); |     SDL_UnlockJoysticks(); | ||||||
|  |  | ||||||
|  |     // retval was malloc'd by IOS_GetAppleSFSymbolsNameForButton | ||||||
|     if (retval && *retval) { |     if (retval && *retval) { | ||||||
|         return retval; |         return SDL_FreeLater(retval); | ||||||
|     } |     } | ||||||
|  |     SDL_free(retval); | ||||||
| #endif | #endif | ||||||
|     return NULL; |     return NULL; | ||||||
| } | } | ||||||
| @@ -3847,8 +3850,8 @@ const char *SDL_GetGamepadAppleSFSymbolsNameForButton(SDL_Gamepad *gamepad, SDL_ | |||||||
| const char *SDL_GetGamepadAppleSFSymbolsNameForAxis(SDL_Gamepad *gamepad, SDL_GamepadAxis axis) | const char *SDL_GetGamepadAppleSFSymbolsNameForAxis(SDL_Gamepad *gamepad, SDL_GamepadAxis axis) | ||||||
| { | { | ||||||
| #ifdef SDL_JOYSTICK_MFI | #ifdef SDL_JOYSTICK_MFI | ||||||
|     const char *IOS_GetAppleSFSymbolsNameForAxis(SDL_Gamepad *gamepad, SDL_GamepadAxis axis); |     char *IOS_GetAppleSFSymbolsNameForAxis(SDL_Gamepad *gamepad, SDL_GamepadAxis axis); | ||||||
|     const char *retval; |     char *retval; | ||||||
|  |  | ||||||
|     SDL_LockJoysticks(); |     SDL_LockJoysticks(); | ||||||
|     { |     { | ||||||
| @@ -3858,9 +3861,11 @@ const char *SDL_GetGamepadAppleSFSymbolsNameForAxis(SDL_Gamepad *gamepad, SDL_Ga | |||||||
|     } |     } | ||||||
|     SDL_UnlockJoysticks(); |     SDL_UnlockJoysticks(); | ||||||
|  |  | ||||||
|  |     // retval was malloc'd by IOS_GetAppleSFSymbolsNameForAxis | ||||||
|     if (retval && *retval) { |     if (retval && *retval) { | ||||||
|         return retval; |         return SDL_FreeLater(retval); | ||||||
|     } |     } | ||||||
|  |     SDL_free(retval); | ||||||
| #endif | #endif | ||||||
|     return NULL; |     return NULL; | ||||||
| } | } | ||||||
|   | |||||||
| @@ -785,8 +785,7 @@ const char *SDL_GetJoystickInstanceName(SDL_JoystickID instance_id) | |||||||
|     } |     } | ||||||
|     SDL_UnlockJoysticks(); |     SDL_UnlockJoysticks(); | ||||||
|  |  | ||||||
|     /* FIXME: Really we should reference count this name so it doesn't go away after unlock */ |     return name ? SDL_FreeLater(SDL_strdup(name)) : NULL; | ||||||
|     return name; |  | ||||||
| } | } | ||||||
|  |  | ||||||
| /* | /* | ||||||
| @@ -804,11 +803,10 @@ const char *SDL_GetJoystickInstancePath(SDL_JoystickID instance_id) | |||||||
|     } |     } | ||||||
|     SDL_UnlockJoysticks(); |     SDL_UnlockJoysticks(); | ||||||
|  |  | ||||||
|     /* FIXME: Really we should reference count this path so it doesn't go away after unlock */ |  | ||||||
|     if (!path) { |     if (!path) { | ||||||
|         SDL_Unsupported(); |         SDL_Unsupported(); | ||||||
|     } |     } | ||||||
|     return path; |     return path ? SDL_FreeLater(SDL_strdup(path)) : NULL; | ||||||
| } | } | ||||||
|  |  | ||||||
| /* | /* | ||||||
| @@ -1663,7 +1661,6 @@ const char *SDL_GetJoystickName(SDL_Joystick *joystick) | |||||||
|     } |     } | ||||||
|     SDL_UnlockJoysticks(); |     SDL_UnlockJoysticks(); | ||||||
|  |  | ||||||
|     /* FIXME: Really we should reference count this name so it doesn't go away after unlock */ |  | ||||||
|     return retval; |     return retval; | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -1888,9 +1885,9 @@ void SDL_CloseJoystick(SDL_Joystick *joystick) | |||||||
|         } |         } | ||||||
|  |  | ||||||
|         /* Free the data associated with this joystick */ |         /* Free the data associated with this joystick */ | ||||||
|         SDL_free(joystick->name); |         SDL_FreeLater(joystick->name);  // SDL_GetJoystickName returns this pointer. | ||||||
|         SDL_free(joystick->path); |         SDL_FreeLater(joystick->path);  // SDL_GetJoystickPath returns this pointer. | ||||||
|         SDL_free(joystick->serial); |         SDL_FreeLater(joystick->serial);  // SDL_GetJoystickSerial returns this pointer. | ||||||
|         SDL_free(joystick->axes); |         SDL_free(joystick->axes); | ||||||
|         SDL_free(joystick->balls); |         SDL_free(joystick->balls); | ||||||
|         SDL_free(joystick->hats); |         SDL_free(joystick->hats); | ||||||
|   | |||||||
| @@ -1916,11 +1916,11 @@ static GCControllerDirectionPad *GetDirectionalPadForController(GCController *co | |||||||
| } | } | ||||||
| #endif /* SDL_JOYSTICK_MFI && ENABLE_PHYSICAL_INPUT_PROFILE */ | #endif /* SDL_JOYSTICK_MFI && ENABLE_PHYSICAL_INPUT_PROFILE */ | ||||||
|  |  | ||||||
| static char elementName[256]; | char *IOS_GetAppleSFSymbolsNameForButton(SDL_Gamepad *gamepad, SDL_GamepadButton button) | ||||||
|  |  | ||||||
| const char *IOS_GetAppleSFSymbolsNameForButton(SDL_Gamepad *gamepad, SDL_GamepadButton button) |  | ||||||
| { | { | ||||||
|  |     char elementName[256]; | ||||||
|     elementName[0] = '\0'; |     elementName[0] = '\0'; | ||||||
|  |  | ||||||
| #if defined(SDL_JOYSTICK_MFI) && defined(ENABLE_PHYSICAL_INPUT_PROFILE) | #if defined(SDL_JOYSTICK_MFI) && defined(ENABLE_PHYSICAL_INPUT_PROFILE) | ||||||
|     if (gamepad && SDL_GetGamepadJoystick(gamepad)->driver == &SDL_IOS_JoystickDriver) { |     if (gamepad && SDL_GetGamepadJoystick(gamepad)->driver == &SDL_IOS_JoystickDriver) { | ||||||
|         if (@available(macOS 10.16, iOS 14.0, tvOS 14.0, *)) { |         if (@available(macOS 10.16, iOS 14.0, tvOS 14.0, *)) { | ||||||
| @@ -2030,12 +2030,15 @@ const char *IOS_GetAppleSFSymbolsNameForButton(SDL_Gamepad *gamepad, SDL_Gamepad | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
| #endif | #endif | ||||||
|     return elementName; |  | ||||||
|  |     return SDL_strdup(elementName); | ||||||
| } | } | ||||||
|  |  | ||||||
| const char *IOS_GetAppleSFSymbolsNameForAxis(SDL_Gamepad *gamepad, SDL_GamepadAxis axis) | char *IOS_GetAppleSFSymbolsNameForAxis(SDL_Gamepad *gamepad, SDL_GamepadAxis axis) | ||||||
| { | { | ||||||
|  |     char elementName[256]; | ||||||
|     elementName[0] = '\0'; |     elementName[0] = '\0'; | ||||||
|  |  | ||||||
| #if defined(SDL_JOYSTICK_MFI) && defined(ENABLE_PHYSICAL_INPUT_PROFILE) | #if defined(SDL_JOYSTICK_MFI) && defined(ENABLE_PHYSICAL_INPUT_PROFILE) | ||||||
|     if (gamepad && SDL_GetGamepadJoystick(gamepad)->driver == &SDL_IOS_JoystickDriver) { |     if (gamepad && SDL_GetGamepadJoystick(gamepad)->driver == &SDL_IOS_JoystickDriver) { | ||||||
|         if (@available(macOS 10.16, iOS 14.0, tvOS 14.0, *)) { |         if (@available(macOS 10.16, iOS 14.0, tvOS 14.0, *)) { | ||||||
| @@ -2068,7 +2071,7 @@ const char *IOS_GetAppleSFSymbolsNameForAxis(SDL_Gamepad *gamepad, SDL_GamepadAx | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
| #endif | #endif | ||||||
|     return *elementName ? elementName : NULL; |     return *elementName ? SDL_strdup(elementName) : NULL; | ||||||
| } | } | ||||||
|  |  | ||||||
| SDL_JoystickDriver SDL_IOS_JoystickDriver = { | SDL_JoystickDriver SDL_IOS_JoystickDriver = { | ||||||
|   | |||||||
| @@ -780,6 +780,7 @@ int SDL_GetNumRenderDrivers(void) | |||||||
| #endif | #endif | ||||||
| } | } | ||||||
|  |  | ||||||
|  | // this returns string literals, so there's no need to use SDL_FreeLater. | ||||||
| const char *SDL_GetRenderDriver(int index) | const char *SDL_GetRenderDriver(int index) | ||||||
| { | { | ||||||
| #ifndef SDL_RENDER_DISABLED | #ifndef SDL_RENDER_DISABLED | ||||||
|   | |||||||
| @@ -250,8 +250,7 @@ const char *SDL_GetSensorInstanceName(SDL_SensorID instance_id) | |||||||
|     } |     } | ||||||
|     SDL_UnlockSensors(); |     SDL_UnlockSensors(); | ||||||
|  |  | ||||||
|     /* FIXME: Really we should reference count this name so it doesn't go away after unlock */ |     return name ? SDL_FreeLater(SDL_strdup(name)) : NULL; | ||||||
|     return name; |  | ||||||
| } | } | ||||||
|  |  | ||||||
| SDL_SensorType SDL_GetSensorInstanceType(SDL_SensorID instance_id) | SDL_SensorType SDL_GetSensorInstanceType(SDL_SensorID instance_id) | ||||||
| @@ -527,7 +526,7 @@ void SDL_CloseSensor(SDL_Sensor *sensor) | |||||||
|         } |         } | ||||||
|  |  | ||||||
|         /* Free the data associated with this sensor */ |         /* Free the data associated with this sensor */ | ||||||
|         SDL_free(sensor->name); |         SDL_FreeLater(sensor->name);  // this pointer gets handed to the app by SDL_GetSensorName(). | ||||||
|         SDL_free(sensor); |         SDL_free(sensor); | ||||||
|     } |     } | ||||||
|     SDL_UnlockSensors(); |     SDL_UnlockSensors(); | ||||||
|   | |||||||
| @@ -299,9 +299,7 @@ void SDL_RunThread(SDL_Thread *thread) | |||||||
|     if (!SDL_AtomicCompareAndSwap(&thread->state, SDL_THREAD_STATE_ALIVE, SDL_THREAD_STATE_ZOMBIE)) { |     if (!SDL_AtomicCompareAndSwap(&thread->state, SDL_THREAD_STATE_ALIVE, SDL_THREAD_STATE_ZOMBIE)) { | ||||||
|         /* Clean up if something already detached us. */ |         /* Clean up if something already detached us. */ | ||||||
|         if (SDL_AtomicCompareAndSwap(&thread->state, SDL_THREAD_STATE_DETACHED, SDL_THREAD_STATE_CLEANED)) { |         if (SDL_AtomicCompareAndSwap(&thread->state, SDL_THREAD_STATE_DETACHED, SDL_THREAD_STATE_CLEANED)) { | ||||||
|             if (thread->name) { |             SDL_FreeLater(thread->name); | ||||||
|                 SDL_free(thread->name); |  | ||||||
|             } |  | ||||||
|             SDL_free(thread); |             SDL_free(thread); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| @@ -421,9 +419,7 @@ void SDL_WaitThread(SDL_Thread *thread, int *status) | |||||||
|         if (status) { |         if (status) { | ||||||
|             *status = thread->status; |             *status = thread->status; | ||||||
|         } |         } | ||||||
|         if (thread->name) { |         SDL_FreeLater(thread->name); | ||||||
|             SDL_free(thread->name); |  | ||||||
|         } |  | ||||||
|         SDL_free(thread); |         SDL_free(thread); | ||||||
|     } |     } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -85,6 +85,7 @@ Uint16 SDL_expand_byte10[] = { | |||||||
|  |  | ||||||
| /* Helper functions */ | /* Helper functions */ | ||||||
|  |  | ||||||
|  | // This doesn't need SDL_FreeLater since it returns string literals. | ||||||
| #define CASE(X) \ | #define CASE(X) \ | ||||||
|     case X:     \ |     case X:     \ | ||||||
|         return #X; |         return #X; | ||||||
|   | |||||||
| @@ -498,6 +498,7 @@ int SDL_GetNumVideoDrivers(void) | |||||||
|     return SDL_arraysize(bootstrap) - 1; |     return SDL_arraysize(bootstrap) - 1; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | // this returns string literals, so there's no need to use SDL_FreeLater. | ||||||
| const char *SDL_GetVideoDriver(int index) | const char *SDL_GetVideoDriver(int index) | ||||||
| { | { | ||||||
|     if (index >= 0 && index < SDL_GetNumVideoDrivers()) { |     if (index >= 0 && index < SDL_GetNumVideoDrivers()) { | ||||||
| @@ -642,6 +643,7 @@ pre_driver_error: | |||||||
|     return -1; |     return -1; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | // this returns string literals, so there's no need to use SDL_FreeLater. | ||||||
| const char *SDL_GetCurrentVideoDriver(void) | const char *SDL_GetCurrentVideoDriver(void) | ||||||
| { | { | ||||||
|     if (!_this) { |     if (!_this) { | ||||||
|   | |||||||
| @@ -973,7 +973,7 @@ static Thing *CreatePhysicalDeviceThing(const SDL_AudioDeviceID which, const SDL | |||||||
|     if (thing) { |     if (thing) { | ||||||
|         thing->data.physdev.devid = which; |         thing->data.physdev.devid = which; | ||||||
|         thing->data.physdev.iscapture = iscapture; |         thing->data.physdev.iscapture = iscapture; | ||||||
|         thing->data.physdev.name = SDL_GetAudioDeviceName(which); |         thing->data.physdev.name = SDL_strdup(SDL_GetAudioDeviceName(which)); | ||||||
|         thing->ondrag = DeviceThing_ondrag; |         thing->ondrag = DeviceThing_ondrag; | ||||||
|         thing->ondrop = PhysicalDeviceThing_ondrop; |         thing->ondrop = PhysicalDeviceThing_ondrop; | ||||||
|         thing->ontick = PhysicalDeviceThing_ontick; |         thing->ontick = PhysicalDeviceThing_ontick; | ||||||
|   | |||||||
| @@ -81,12 +81,11 @@ int SDL_AppInit(void **appstate, int argc, char **argv) | |||||||
|  |  | ||||||
|     devices = SDL_GetAudioCaptureDevices(NULL); |     devices = SDL_GetAudioCaptureDevices(NULL); | ||||||
|     for (i = 0; devices[i] != 0; i++) { |     for (i = 0; devices[i] != 0; i++) { | ||||||
|         char *name = SDL_GetAudioDeviceName(devices[i]); |         const char *name = SDL_GetAudioDeviceName(devices[i]); | ||||||
|         SDL_Log(" Capture device #%d: '%s'\n", i, name); |         SDL_Log(" Capture device #%d: '%s'\n", i, name); | ||||||
|         if (devname && (SDL_strcmp(devname, name) == 0)) { |         if (devname && (SDL_strcmp(devname, name) == 0)) { | ||||||
|             want_device = devices[i]; |             want_device = devices[i]; | ||||||
|         } |         } | ||||||
|         SDL_free(name); |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     if (devname && (want_device == SDL_AUDIO_DEVICE_DEFAULT_CAPTURE)) { |     if (devname && (want_device == SDL_AUDIO_DEVICE_DEFAULT_CAPTURE)) { | ||||||
|   | |||||||
| @@ -71,7 +71,7 @@ static void iteration(void) | |||||||
|         } else if (e.type == SDL_EVENT_AUDIO_DEVICE_ADDED) { |         } else if (e.type == SDL_EVENT_AUDIO_DEVICE_ADDED) { | ||||||
|             const SDL_AudioDeviceID which = (SDL_AudioDeviceID) e.adevice.which; |             const SDL_AudioDeviceID which = (SDL_AudioDeviceID) e.adevice.which; | ||||||
|             const SDL_bool iscapture = e.adevice.iscapture ? SDL_TRUE : SDL_FALSE; |             const SDL_bool iscapture = e.adevice.iscapture ? SDL_TRUE : SDL_FALSE; | ||||||
|             char *name = SDL_GetAudioDeviceName(which); |             const char *name = SDL_GetAudioDeviceName(which); | ||||||
|             if (name) { |             if (name) { | ||||||
|                 SDL_Log("New %s audio device at id %u: %s", devtypestr(iscapture), (unsigned int)which, name); |                 SDL_Log("New %s audio device at id %u: %s", devtypestr(iscapture), (unsigned int)which, name); | ||||||
|             } else { |             } else { | ||||||
| @@ -92,7 +92,6 @@ static void iteration(void) | |||||||
|                     /* !!! FIXME: this is leaking the stream for now. We'll wire it up to a dictionary or whatever later. */ |                     /* !!! FIXME: this is leaking the stream for now. We'll wire it up to a dictionary or whatever later. */ | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|             SDL_free(name); |  | ||||||
|         } else if (e.type == SDL_EVENT_AUDIO_DEVICE_REMOVED) { |         } else if (e.type == SDL_EVENT_AUDIO_DEVICE_REMOVED) { | ||||||
|             dev = (SDL_AudioDeviceID)e.adevice.which; |             dev = (SDL_AudioDeviceID)e.adevice.which; | ||||||
|             SDL_Log("%s device %u removed.\n", devtypestr(e.adevice.iscapture), (unsigned int)dev); |             SDL_Log("%s device %u removed.\n", devtypestr(e.adevice.iscapture), (unsigned int)dev); | ||||||
|   | |||||||
| @@ -30,10 +30,9 @@ print_devices(SDL_bool iscapture) | |||||||
|         int i; |         int i; | ||||||
|         SDL_Log("Found %d %s device%s:\n", n, typestr, n != 1 ? "s" : ""); |         SDL_Log("Found %d %s device%s:\n", n, typestr, n != 1 ? "s" : ""); | ||||||
|         for (i = 0; i < n; i++) { |         for (i = 0; i < n; i++) { | ||||||
|             char *name = SDL_GetAudioDeviceName(devices[i]); |             const char *name = SDL_GetAudioDeviceName(devices[i]); | ||||||
|             if (name) { |             if (name) { | ||||||
|                 SDL_Log("  %d: %s\n", i, name); |                 SDL_Log("  %d: %s\n", i, name); | ||||||
|                 SDL_free(name); |  | ||||||
|             } else { |             } else { | ||||||
|                 SDL_Log("  %d Error: %s\n", i, SDL_GetError()); |                 SDL_Log("  %d Error: %s\n", i, SDL_GetError()); | ||||||
|             } |             } | ||||||
|   | |||||||
| @@ -365,7 +365,7 @@ static int audio_enumerateAndNameAudioDevices(void *arg) | |||||||
| { | { | ||||||
|     int t; |     int t; | ||||||
|     int i, n; |     int i, n; | ||||||
|     char *name; |     const char *name; | ||||||
|     SDL_AudioDeviceID *devices = NULL; |     SDL_AudioDeviceID *devices = NULL; | ||||||
|  |  | ||||||
|     /* Iterate over types: t=0 output device, t=1 input/capture device */ |     /* Iterate over types: t=0 output device, t=1 input/capture device */ | ||||||
| @@ -385,7 +385,6 @@ static int audio_enumerateAndNameAudioDevices(void *arg) | |||||||
|                 SDLTest_AssertCheck(name != NULL, "Verify result from SDL_GetAudioDeviceName(%i) is not NULL", i); |                 SDLTest_AssertCheck(name != NULL, "Verify result from SDL_GetAudioDeviceName(%i) is not NULL", i); | ||||||
|                 if (name != NULL) { |                 if (name != NULL) { | ||||||
|                     SDLTest_AssertCheck(name[0] != '\0', "verify result from SDL_GetAudioDeviceName(%i) is not empty, got: '%s'", i, name); |                     SDLTest_AssertCheck(name[0] != '\0', "verify result from SDL_GetAudioDeviceName(%i) is not empty, got: '%s'", i, name); | ||||||
|                     SDL_free(name); |  | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|   | |||||||
| @@ -57,7 +57,7 @@ test_multi_audio(SDL_AudioDeviceID *devices, int devcount) | |||||||
| #endif | #endif | ||||||
|  |  | ||||||
|     for (i = 0; i < devcount; i++) { |     for (i = 0; i < devcount; i++) { | ||||||
|         char *devname = SDL_GetAudioDeviceName(devices[i]); |         const char *devname = SDL_GetAudioDeviceName(devices[i]); | ||||||
|  |  | ||||||
|         SDL_Log("Playing on device #%d of %d: id=%u, name='%s'...", i, devcount, (unsigned int) devices[i], devname); |         SDL_Log("Playing on device #%d of %d: id=%u, name='%s'...", i, devcount, (unsigned int) devices[i], devname); | ||||||
|  |  | ||||||
| @@ -82,7 +82,6 @@ test_multi_audio(SDL_AudioDeviceID *devices, int devcount) | |||||||
|             SDL_Log("done."); |             SDL_Log("done."); | ||||||
|             SDL_DestroyAudioStream(stream); |             SDL_DestroyAudioStream(stream); | ||||||
|         } |         } | ||||||
|         SDL_free(devname); |  | ||||||
|         stream = NULL; |         stream = NULL; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -191,12 +191,11 @@ int main(int argc, char *argv[]) | |||||||
|  |  | ||||||
|     for (i = 0; i < devcount; i++) { |     for (i = 0; i < devcount; i++) { | ||||||
|         SDL_AudioStream *stream = NULL; |         SDL_AudioStream *stream = NULL; | ||||||
|         char *devname = SDL_GetAudioDeviceName(devices[i]); |         const char *devname = SDL_GetAudioDeviceName(devices[i]); | ||||||
|         int j; |         int j; | ||||||
|         SDL_AudioSpec spec; |         SDL_AudioSpec spec; | ||||||
|  |  | ||||||
|         SDL_Log("Testing audio device: %s\n", devname); |         SDL_Log("Testing audio device: %s\n", devname); | ||||||
|         SDL_free(devname); |  | ||||||
|  |  | ||||||
|         if (SDL_GetAudioDeviceFormat(devices[i], &spec, NULL) != 0) { |         if (SDL_GetAudioDeviceFormat(devices[i], &spec, NULL) != 0) { | ||||||
|             SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "SDL_GetAudioDeviceFormat() failed: %s\n", SDL_GetError()); |             SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "SDL_GetAudioDeviceFormat() failed: %s\n", SDL_GetError()); | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Ryan C. Gordon
					Ryan C. Gordon