Adds SDL_GameControllerAddMappingsFromFile
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105
diff --git a/include/SDL_gamecontroller.h b/include/SDL_gamecontroller.h
index e55749c..84d58d8 100644
--- a/include/SDL_gamecontroller.h
+++ b/include/SDL_gamecontroller.h
@@ -109,6 +109,14 @@ typedef struct SDL_GameControllerButtonBind
*/
/**
+ * Load a set of mappings from a file, filtered by the current SDL_GetPlatform()
+ * A community sourced database of controllers is available at https://raw.github.com/gabomdq/SDL_GameControllerDB/master/gamecontrollerdb.txt
+ *
+ * \return number of mappings added, -1 on error
+ */
+extern DECLSPEC int SDLCALL SDL_GameControllerAddMappingsFromFile( const char* mapDB );
+
+/**
* Add or update an existing mapping configuration
*
* \return 1 if mapping is added, 0 if updated, -1 on error
diff --git a/src/joystick/SDL_gamecontroller.c b/src/joystick/SDL_gamecontroller.c
index 26769b8..1563f51 100644
--- a/src/joystick/SDL_gamecontroller.c
+++ b/src/joystick/SDL_gamecontroller.c
@@ -33,6 +33,7 @@
#endif
#define ABS(_x) ((_x) < 0 ? -(_x) : (_x))
+#define SDL_CONTROLLER_PLATFORM_FIELD "platform:"
/* a list of currently opened game controllers */
static SDL_GameController *SDL_gamecontrollers = NULL;
@@ -657,6 +658,73 @@ void SDL_PrivateGameControllerRefreshMapping( ControllerMapping_t *pControllerMa
* Add or update an entry into the Mappings Database
*/
int
+SDL_GameControllerAddMappingsFromFile( const char* mapDB )
+{
+ const char *platform = SDL_GetPlatform();
+ SDL_RWops *rw;
+ int controllers = 0;
+ char *buf, *line, *line_end, *tmp, *comma, line_platform[64];
+ size_t db_size, platform_len;
+
+ rw = SDL_RWFromFile(mapDB, "rb");
+ if (rw == NULL) {
+ return SDL_SetError("Could not open %s", mapDB);
+ }
+ db_size = SDL_RWsize(rw);
+
+ buf = (char *) SDL_malloc(db_size + 1);
+ if (buf == NULL) {
+ SDL_RWclose(rw);
+ return SDL_SetError("Could allocate space to not read DB into memory");
+ }
+
+ if (SDL_RWread(rw, buf, db_size, 1) != 1) {
+ SDL_RWclose(rw);
+ SDL_free(buf);
+ return SDL_SetError("Could not read DB");
+ }
+ SDL_RWclose(rw);
+
+ buf[db_size] = '\0';
+ line = buf;
+
+ while (line < buf + db_size) {
+ line_end = SDL_strchr( line, '\n' );
+ if (line_end != NULL) {
+ *line_end = '\0';
+ }
+ else {
+ line_end = buf + db_size;
+ }
+
+ /* Extract and verify the platform */
+ tmp = SDL_strstr(line, SDL_CONTROLLER_PLATFORM_FIELD);
+ if ( tmp != NULL ) {
+ tmp += SDL_strlen(SDL_CONTROLLER_PLATFORM_FIELD);
+ comma = SDL_strchr(tmp, ',');
+ if (comma != NULL) {
+ platform_len = comma - tmp + 1;
+ if (platform_len + 1 < SDL_arraysize(line_platform)) {
+ SDL_strlcpy(line_platform, tmp, platform_len);
+ if(SDL_strncasecmp(line_platform, platform, platform_len) == 0
+ && SDL_GameControllerAddMapping(line) > 0) {
+ controllers++;
+ }
+ }
+ }
+ }
+
+ line = line_end + 1;
+ }
+
+ SDL_free(buf);
+ return controllers;
+}
+
+/*
+ * Add or update an entry into the Mappings Database
+ */
+int
SDL_GameControllerAddMapping( const char *mappingString )
{
char *pchGUID;