1 #include "osdialog.h"
2 #include <assert.h>
3 #include <stdlib.h>
4 #include <string.h>
5 
6 
osdialog_strndup(const char * s,size_t n)7 char *osdialog_strndup(const char *s, size_t n) {
8 	char *d = OSDIALOG_MALLOC(n + 1);
9 	memcpy(d, s, n);
10 	d[n] = '\0';
11 	return d;
12 }
13 
osdialog_filters_parse(const char * str)14 osdialog_filters *osdialog_filters_parse(const char *str) {
15 	osdialog_filters *filters_head = OSDIALOG_MALLOC(sizeof(osdialog_filters));
16 	filters_head->next = NULL;
17 
18 	osdialog_filters *filters = filters_head;
19 	osdialog_filter_patterns *patterns = NULL;
20 
21 	const char *text = str;
22 	while (1) {
23 		switch (*str) {
24 			case ':': {
25 				filters->name = osdialog_strndup(text, str - text);
26 				filters->patterns = OSDIALOG_MALLOC(sizeof(osdialog_filter_patterns));
27 				patterns = filters->patterns;
28 				patterns->next = NULL;
29 				text = str + 1;
30 			} break;
31 			case ',': {
32 				assert(patterns);
33 				patterns->pattern = osdialog_strndup(text, str - text);
34 				patterns->next = OSDIALOG_MALLOC(sizeof(osdialog_filter_patterns));
35 				patterns = patterns->next;
36 				patterns->next = NULL;
37 				text = str + 1;
38 			} break;
39 			case ';': {
40 				assert(patterns);
41 				patterns->pattern = osdialog_strndup(text, str - text);
42 				filters->next = OSDIALOG_MALLOC(sizeof(osdialog_filters));
43 				filters = filters->next;
44 				filters->next = NULL;
45 				patterns = NULL;
46 				text = str + 1;
47 			} break;
48 			case '\0': {
49 				assert(patterns);
50 				patterns->pattern = osdialog_strndup(text, str - text);
51 			} break;
52 			default: break;
53 		}
54 		if (!*str)
55 			break;
56 		str++;
57 	}
58 
59 	return filters_head;
60 }
61 
patterns_free(osdialog_filter_patterns * patterns)62 static void patterns_free(osdialog_filter_patterns *patterns) {
63 	if (!patterns)
64 		return;
65 	OSDIALOG_FREE(patterns->pattern);
66 	osdialog_filter_patterns *next = patterns->next;
67 	OSDIALOG_FREE(patterns);
68 	patterns_free(next);
69 }
70 
osdialog_filters_free(osdialog_filters * filters)71 void osdialog_filters_free(osdialog_filters *filters) {
72 	if (!filters)
73 		return;
74 	OSDIALOG_FREE(filters->name);
75 	patterns_free(filters->patterns);
76 	osdialog_filters *next = filters->next;
77 	OSDIALOG_FREE(filters);
78 	osdialog_filters_free(next);
79 }
80