SDL

Форк
0
/
SDL_dialog_utils.c 
259 строк · 7.5 Кб
1
/*
2
  Simple DirectMedia Layer
3
  Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
4

5
  This software is provided 'as-is', without any express or implied
6
  warranty.  In no event will the authors be held liable for any damages
7
  arising from the use of this software.
8

9
  Permission is granted to anyone to use this software for any purpose,
10
  including commercial applications, and to alter it and redistribute it
11
  freely, subject to the following restrictions:
12

13
  1. The origin of this software must not be misrepresented; you must not
14
     claim that you wrote the original software. If you use this software
15
     in a product, an acknowledgment in the product documentation would be
16
     appreciated but is not required.
17
  2. Altered source versions must be plainly marked as such, and must not be
18
     misrepresented as being the original software.
19
  3. This notice may not be removed or altered from any source distribution.
20
*/
21
#include "SDL_internal.h"
22

23
#include "SDL_dialog_utils.h"
24

25
char *convert_filters(const SDL_DialogFileFilter *filters, int nfilters,
26
                      NameTransform ntf, const char *prefix,
27
                      const char *separator, const char *suffix,
28
                      const char *filt_prefix, const char *filt_separator,
29
                      const char *filt_suffix, const char *ext_prefix,
30
                      const char *ext_separator, const char *ext_suffix)
31
{
32
    char *combined;
33
    char *new_combined;
34
    char *converted;
35
    const char *terminator;
36
    size_t new_length;
37
    int i;
38

39
    if (!filters) {
40
        SDL_SetError("Called convert_filters() with NULL filters (SDL bug)");
41
        return NULL;
42
    }
43

44
    combined = SDL_strdup(prefix);
45

46
    if (!combined) {
47
        return NULL;
48
    }
49

50
    for (i = 0; i < nfilters; i++) {
51
        const SDL_DialogFileFilter *f = &filters[i];
52

53
        converted = convert_filter(*f, ntf, filt_prefix, filt_separator,
54
                                   filt_suffix, ext_prefix, ext_separator,
55
                                   ext_suffix);
56

57
        if (!converted) {
58
            SDL_free(combined);
59
            return NULL;
60
        }
61

62
        terminator = f[1].name ? separator : suffix;
63
        new_length = SDL_strlen(combined) + SDL_strlen(converted)
64
                   + SDL_strlen(terminator) + 1;
65

66
        new_combined = (char *)SDL_realloc(combined, new_length);
67

68
        if (!new_combined) {
69
            SDL_free(converted);
70
            SDL_free(combined);
71
            return NULL;
72
        }
73

74
        combined = new_combined;
75

76
        SDL_strlcat(combined, converted, new_length);
77
        SDL_strlcat(combined, terminator, new_length);
78
        SDL_free(converted);
79
    }
80

81
    // If the filter list is empty, put the suffix
82
    if (!filters->name || !filters->pattern) {
83
        new_length = SDL_strlen(combined) + SDL_strlen(suffix) + 1;
84

85
        new_combined = (char *)SDL_realloc(combined, new_length);
86

87
        if (!new_combined) {
88
            SDL_free(combined);
89
            return NULL;
90
        }
91

92
        combined = new_combined;
93

94
        SDL_strlcat(combined, suffix, new_length);
95
    }
96

97
    return combined;
98
}
99

100
char *convert_filter(const SDL_DialogFileFilter filter, NameTransform ntf,
101
                     const char *prefix, const char *separator,
102
                     const char *suffix, const char *ext_prefix,
103
                     const char *ext_separator, const char *ext_suffix)
104
{
105
    char *converted;
106
    char *name_filtered;
107
    size_t total_length;
108
    char *list;
109

110
    list = convert_ext_list(filter.pattern, ext_prefix, ext_separator,
111
                            ext_suffix);
112

113
    if (!list) {
114
        return NULL;
115
    }
116

117
    if (ntf) {
118
        name_filtered = ntf(filter.name);
119
    } else {
120
        // Useless strdup, but easier to read and maintain code this way
121
        name_filtered = SDL_strdup(filter.name);
122
    }
123

124
    if (!name_filtered) {
125
        SDL_free(list);
126
        return NULL;
127
    }
128

129
    total_length = SDL_strlen(prefix) + SDL_strlen(name_filtered)
130
                 + SDL_strlen(separator) + SDL_strlen(list)
131
                 + SDL_strlen(suffix) + 1;
132

133
    converted = (char *) SDL_malloc(total_length);
134

135
    if (!converted) {
136
        SDL_free(list);
137
        SDL_free(name_filtered);
138
        return NULL;
139
    }
140

141
    SDL_snprintf(converted, total_length, "%s%s%s%s%s", prefix, name_filtered,
142
                 separator, list, suffix);
143

144
    SDL_free(list);
145
    SDL_free(name_filtered);
146

147
    return converted;
148
}
149

150
char *convert_ext_list(const char *list, const char *prefix,
151
                       const char *separator, const char *suffix)
152
{
153
    char *converted;
154
    int semicolons;
155
    size_t total_length;
156

157
    semicolons = 0;
158

159
    for (const char *c = list; *c; c++) {
160
        semicolons += (*c == ';');
161
    }
162

163
    total_length =
164
        SDL_strlen(list) - semicolons // length of list contents
165
      + semicolons * SDL_strlen(separator) // length of separators
166
      + SDL_strlen(prefix) + SDL_strlen(suffix) // length of prefix/suffix
167
      + 1; // terminating null byte
168

169
    converted = (char *) SDL_malloc(total_length);
170

171
    if (!converted) {
172
        return NULL;
173
    }
174

175
    *converted = '\0';
176

177
    SDL_strlcat(converted, prefix, total_length);
178

179
    /* Some platforms may prefer to handle the asterisk manually, but this
180
       function offers to handle it for ease of use. */
181
    if (SDL_strcmp(list, "*") == 0) {
182
        SDL_strlcat(converted, "*", total_length);
183
    } else {
184
        for (const char *c = list; *c; c++) {
185
            if ((*c >= 'a' && *c <= 'z') || (*c >= 'A' && *c <= 'Z')
186
             || (*c >= '0' && *c <= '9') || *c == '-' || *c == '_'
187
             || *c == '.') {
188
                char str[2];
189
                str[0] = *c;
190
                str[1] = '\0';
191
                SDL_strlcat(converted, str, total_length);
192
            } else if (*c == ';') {
193
                if (c == list || c[-1] == ';') {
194
                    SDL_SetError("Empty pattern not allowed");
195
                    SDL_free(converted);
196
                    return NULL;
197
                }
198

199
                SDL_strlcat(converted, separator, total_length);
200
            } else {
201
                SDL_SetError("Invalid character '%c' in pattern (Only [a-zA-Z0-9_.-] allowed, or a single *)", *c);
202
                SDL_free(converted);
203
                return NULL;
204
            }
205
        }
206
    }
207

208
    if (list[SDL_strlen(list) - 1] == ';') {
209
        SDL_SetError("Empty pattern not allowed");
210
        SDL_free(converted);
211
        return NULL;
212
    }
213

214
    SDL_strlcat(converted, suffix, total_length);
215

216
    return converted;
217
}
218

219
const char *validate_filters(const SDL_DialogFileFilter *filters, int nfilters)
220
{
221
    if (filters) {
222
        for (int i = 0; i < nfilters; i++) {
223
             const char *msg = validate_list(filters[i].pattern);
224

225
             if (msg) {
226
                 return msg;
227
             }
228
        }
229
    }
230

231
    return NULL;
232
}
233

234
const char *validate_list(const char *list)
235
{
236
    if (SDL_strcmp(list, "*") == 0) {
237
        return NULL;
238
    } else {
239
        for (const char *c = list; *c; c++) {
240
            if ((*c >= 'a' && *c <= 'z') || (*c >= 'A' && *c <= 'Z')
241
             || (*c >= '0' && *c <= '9') || *c == '-' || *c == '_'
242
             || *c == '.') {
243
                continue;
244
            } else if (*c == ';') {
245
                if (c == list || c[-1] == ';') {
246
                    return "Empty pattern not allowed";
247
                }
248
            } else {
249
                return "Invalid character in pattern (Only [a-zA-Z0-9_.-] allowed, or a single *)";
250
            }
251
        }
252
    }
253

254
    if (list[SDL_strlen(list) - 1] == ';') {
255
        return "Empty pattern not allowed";
256
    }
257

258
    return NULL;
259
}
260

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.