[PATCH] Split config name parse functions into parse.c
[fio.git] / parse.c
1 /*
2  * This file contains the ini and command liner parser main.
3  */
4 #include <stdio.h>
5 #include <stdlib.h>
6 #include <unistd.h>
7 #include <ctype.h>
8 #include <string.h>
9 #include <errno.h>
10 #include <limits.h>
11
12 #include "parse.h"
13
14 static unsigned long get_mult_time(char c)
15 {
16         switch (c) {
17                 case 'm':
18                 case 'M':
19                         return 60;
20                 case 'h':
21                 case 'H':
22                         return 60 * 60;
23                 case 'd':
24                 case 'D':
25                         return 24 * 60 * 60;
26                 default:
27                         return 1;
28         }
29 }
30
31 static unsigned long get_mult_bytes(char c)
32 {
33         switch (c) {
34                 case 'k':
35                 case 'K':
36                         return 1024;
37                 case 'm':
38                 case 'M':
39                         return 1024 * 1024;
40                 case 'g':
41                 case 'G':
42                         return 1024 * 1024 * 1024;
43                 default:
44                         return 1;
45         }
46 }
47
48 /*
49  * convert string after '=' into decimal value, noting any size suffix
50  */
51 static int str_to_decimal(char *p, unsigned long long *val, int kilo)
52 {
53         char *str;
54         int len;
55
56         str = strchr(p, '=');
57         if (!str)
58                 return 1;
59
60         str++;
61         len = strlen(str);
62
63         *val = strtoul(str, NULL, 10);
64         if (*val == ULONG_MAX && errno == ERANGE)
65                 return 1;
66
67         if (kilo)
68                 *val *= get_mult_bytes(str[len - 1]);
69         else
70                 *val *= get_mult_time(str[len - 1]);
71         return 0;
72 }
73
74 int check_str_bytes(char *p, char *name, unsigned long long *val)
75 {
76         if (strncmp(p, name, strlen(name) - 1))
77                 return 1;
78
79         return str_to_decimal(p, val, 1);
80 }
81
82 int check_str_time(char *p, char *name, unsigned long long *val)
83 {
84         if (strncmp(p, name, strlen(name) - 1))
85                 return 1;
86
87         return str_to_decimal(p, val, 0);
88 }
89
90 void strip_blank_front(char **p)
91 {
92         char *s = *p;
93
94         while (isspace(*s))
95                 s++;
96 }
97
98 void strip_blank_end(char *p)
99 {
100         char *s = p + strlen(p) - 1;
101
102         while (isspace(*s) || iscntrl(*s))
103                 s--;
104
105         *(s + 1) = '\0';
106 }
107
108 int check_str(char *p, char *name, str_cb_fn *cb, void *data)
109 {
110         char *s;
111
112         if (strncmp(p, name, strlen(name)))
113                 return 1;
114
115         s = strstr(p, name);
116         if (!s)
117                 return 1;
118
119         s = strchr(s, '=');
120         if (!s)
121                 return 1;
122
123         s++;
124         strip_blank_front(&s);
125         return cb(data, s);
126 }
127
128 int check_strstore(char *p, char *name, char *dest)
129 {
130         char *s;
131
132         if (strncmp(p, name, strlen(name)))
133                 return 1;
134
135         s = strstr(p, name);
136         if (!s)
137                 return 1;
138
139         s = strchr(p, '=');
140         if (!s)
141                 return 1;
142
143         s++;
144         strip_blank_front(&s);
145
146         strcpy(dest, s);
147         return 0;
148 }
149
150 static int __check_range_bytes(char *str, unsigned long *val)
151 {
152         char suffix;
153
154         if (sscanf(str, "%lu%c", val, &suffix) == 2) {
155                 *val *= get_mult_bytes(suffix);
156                 return 0;
157         }
158
159         if (sscanf(str, "%lu", val) == 1)
160                 return 0;
161
162         return 1;
163 }
164
165 int check_range_bytes(char *p, char *name, unsigned long *s, unsigned long *e)
166 {
167         char option[128];
168         char *str, *p1, *p2;
169
170         if (strncmp(p, name, strlen(name)))
171                 return 1;
172
173         strcpy(option, p);
174         p = option;
175
176         str = strstr(p, name);
177         if (!str)
178                 return 1;
179
180         p += strlen(name);
181
182         str = strchr(p, '=');
183         if (!str)
184                 return 1;
185
186         /*
187          * 'p' now holds whatever is after the '=' sign
188          */
189         p1 = str + 1;
190
191         /*
192          * terminate p1 at the '-' sign
193          */
194         p = strchr(p1, '-');
195         if (!p)
196                 return 1;
197
198         p2 = p + 1;
199         *p = '\0';
200
201         if (!__check_range_bytes(p1, s) && !__check_range_bytes(p2, e))
202                 return 0;
203
204         return 1;
205 }
206
207 int check_int(char *p, char *name, unsigned int *val)
208 {
209         char *str;
210
211         if (strncmp(p, name, strlen(name)))
212                 return 1;
213
214         str = strstr(p, name);
215         if (!str)
216                 return 1;
217
218         str = strchr(p, '=');
219         if (!str)
220                 return 1;
221
222         str++;
223
224         if (sscanf(str, "%u", val) == 1)
225                 return 0;
226
227         return 1;
228 }
229
230 int check_strset(char *p, char *name)
231 {
232         return strncmp(p, name, strlen(name));
233 }
234