123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239 |
- /*
- Simple DirectMedia Layer
- Copyright (C) 1997-2024 Sam Lantinga <[email protected]>
- This software is provided 'as-is', without any express or implied
- warranty. In no event will the authors be held liable for any damages
- arising from the use of this software.
- Permission is granted to anyone to use this software for any purpose,
- including commercial applications, and to alter it and redistribute it
- freely, subject to the following restrictions:
- 1. The origin of this software must not be misrepresented; you must not
- claim that you wrote the original software. If you use this software
- in a product, an acknowledgment in the product documentation would be
- appreciated but is not required.
- 2. Altered source versions must be plainly marked as such, and must not be
- misrepresented as being the original software.
- 3. This notice may not be removed or altered from any source distribution.
- */
- #include "SDL_internal.h"
- #include "SDL_dialog_utils.h"
- char *convert_filters(const SDL_DialogFileFilter *filters, NameTransform ntf,
- const char *prefix, const char *separator,
- const char *suffix, const char *filt_prefix,
- const char *filt_separator, const char *filt_suffix,
- const char *ext_prefix, const char *ext_separator,
- const char *ext_suffix)
- {
- char *combined;
- char *new_combined;
- char *converted;
- const char *terminator;
- int new_length;
- combined = SDL_strdup(prefix);
- if (!combined) {
- SDL_OutOfMemory();
- return NULL;
- }
- for (const SDL_DialogFileFilter *f = filters; f->name; f++) {
- converted = convert_filter(*f, ntf, filt_prefix, filt_separator,
- filt_suffix, ext_prefix, ext_separator,
- ext_suffix);
- if (!converted) {
- SDL_free(combined);
- return NULL;
- }
- terminator = f[1].name ? separator : suffix;
- new_length = SDL_strlen(combined) + SDL_strlen(converted)
- + SDL_strlen(terminator) + 1;
- new_combined = SDL_realloc(combined, new_length);
- if (!new_combined) {
- SDL_free(converted);
- SDL_free(combined);
- SDL_OutOfMemory();
- return NULL;
- }
- combined = new_combined;
- SDL_strlcat(combined, converted, new_length);
- SDL_strlcat(combined, terminator, new_length);
- SDL_free(converted);
- }
- return combined;
- }
- char *convert_filter(const SDL_DialogFileFilter filter, NameTransform ntf,
- const char *prefix, const char *separator,
- const char *suffix, const char *ext_prefix,
- const char *ext_separator, const char *ext_suffix)
- {
- char *converted;
- char *name_filtered;
- int total_length;
- char *list;
- list = convert_ext_list(filter.pattern, ext_prefix, ext_separator,
- ext_suffix);
- if (!list) {
- return NULL;
- }
- if (ntf) {
- name_filtered = ntf(filter.name);
- } else {
- /* Useless strdup, but easier to read and maintain code this way */
- name_filtered = SDL_strdup(filter.name);
- }
- if (!name_filtered) {
- SDL_free(list);
- return NULL;
- }
- total_length = SDL_strlen(prefix) + SDL_strlen(name_filtered)
- + SDL_strlen(separator) + SDL_strlen(list)
- + SDL_strlen(suffix) + 1;
- converted = (char *) SDL_malloc(total_length);
- if (!converted) {
- SDL_free(list);
- SDL_free(name_filtered);
- SDL_OutOfMemory();
- return NULL;
- }
- SDL_snprintf(converted, total_length, "%s%s%s%s%s", prefix, name_filtered,
- separator, list, suffix);
- SDL_free(list);
- SDL_free(name_filtered);
- return converted;
- }
- char *convert_ext_list(const char *list, const char *prefix,
- const char *separator, const char *suffix)
- {
- char *converted;
- int semicolons;
- int total_length;
- semicolons = 0;
- for (const char *c = list; *c; c++) {
- semicolons += (*c == ';');
- }
- total_length =
- SDL_strlen(list) - semicolons /* length of list contents */
- + semicolons * SDL_strlen(separator) /* length of separators */
- + SDL_strlen(prefix) + SDL_strlen(suffix) /* length of prefix/suffix */
- + 1; /* terminating null byte */
- converted = (char *) SDL_malloc(total_length);
- if (!converted) {
- SDL_OutOfMemory();
- return NULL;
- }
- *converted = '\0';
- SDL_strlcat(converted, prefix, total_length);
- /* Some platforms may prefer to handle the asterisk manually, but this
- function offers to handle it for ease of use. */
- if (SDL_strcmp(list, "*") == 0) {
- SDL_strlcat(converted, "*", total_length);
- } else {
- for (const char *c = list; *c; c++) {
- if ((*c >= 'a' && *c <= 'z') || (*c >= 'A' && *c <= 'Z')
- || (*c >= '0' && *c <= '9') || *c == '-' || *c == '_'
- || *c == '.') {
- char str[2];
- str[0] = *c;
- str[1] = '\0';
- SDL_strlcat(converted, str, total_length);
- } else if (*c == ';') {
- if (c == list || c[-1] == ';') {
- SDL_SetError("Empty pattern not allowed");
- SDL_free(converted);
- return NULL;
- }
- SDL_strlcat(converted, separator, total_length);
- } else {
- SDL_SetError("Invalid character '%c' in pattern (Only [a-zA-Z0-9_.-] allowed, or a single *)", *c);
- SDL_free(converted);
- return NULL;
- }
- }
- }
- if (list[SDL_strlen(list) - 1] == ';') {
- SDL_SetError("Empty pattern not allowed");
- SDL_free(converted);
- return NULL;
- }
- SDL_strlcat(converted, suffix, total_length);
- return converted;
- }
- const char *validate_filters(const SDL_DialogFileFilter *filters)
- {
- if (filters) {
- for (const SDL_DialogFileFilter *f = filters; f->name; f++) {
- const char *msg = validate_list(f->pattern);
- if (msg) {
- return msg;
- }
- }
- }
- return NULL;
- }
- const char *validate_list(const char *list)
- {
- if (SDL_strcmp(list, "*") == 0) {
- return NULL;
- } else {
- for (const char *c = list; *c; c++) {
- if ((*c >= 'a' && *c <= 'z') || (*c >= 'A' && *c <= 'Z')
- || (*c >= '0' && *c <= '9') || *c == '-' || *c == '_'
- || *c == '.') {
- continue;
- } else if (*c == ';') {
- if (c == list || c[-1] == ';') {
- return "Empty pattern not allowed";
- }
- } else {
- return "Invalid character in pattern (Only [a-zA-Z0-9_.-] allowed, or a single *)";
- }
- }
- }
- if (list[SDL_strlen(list) - 1] == ';') {
- return "Empty pattern not allowed";
- }
- return NULL;
- }
|