git
/
parse.c
211 строк · 3.9 Кб
1#include "git-compat-util.h"
2#include "gettext.h"
3#include "parse.h"
4
5static uintmax_t get_unit_factor(const char *end)
6{
7if (!*end)
8return 1;
9else if (!strcasecmp(end, "k"))
10return 1024;
11else if (!strcasecmp(end, "m"))
12return 1024 * 1024;
13else if (!strcasecmp(end, "g"))
14return 1024 * 1024 * 1024;
15return 0;
16}
17
18int git_parse_signed(const char *value, intmax_t *ret, intmax_t max)
19{
20if (value && *value) {
21char *end;
22intmax_t val;
23intmax_t factor;
24
25if (max < 0)
26BUG("max must be a positive integer");
27
28errno = 0;
29val = strtoimax(value, &end, 0);
30if (errno == ERANGE)
31return 0;
32if (end == value) {
33errno = EINVAL;
34return 0;
35}
36factor = get_unit_factor(end);
37if (!factor) {
38errno = EINVAL;
39return 0;
40}
41if ((val < 0 && -max / factor > val) ||
42(val > 0 && max / factor < val)) {
43errno = ERANGE;
44return 0;
45}
46val *= factor;
47*ret = val;
48return 1;
49}
50errno = EINVAL;
51return 0;
52}
53
54static int git_parse_unsigned(const char *value, uintmax_t *ret, uintmax_t max)
55{
56if (value && *value) {
57char *end;
58uintmax_t val;
59uintmax_t factor;
60
61/* negative values would be accepted by strtoumax */
62if (strchr(value, '-')) {
63errno = EINVAL;
64return 0;
65}
66errno = 0;
67val = strtoumax(value, &end, 0);
68if (errno == ERANGE)
69return 0;
70if (end == value) {
71errno = EINVAL;
72return 0;
73}
74factor = get_unit_factor(end);
75if (!factor) {
76errno = EINVAL;
77return 0;
78}
79if (unsigned_mult_overflows(factor, val) ||
80factor * val > max) {
81errno = ERANGE;
82return 0;
83}
84val *= factor;
85*ret = val;
86return 1;
87}
88errno = EINVAL;
89return 0;
90}
91
92int git_parse_int(const char *value, int *ret)
93{
94intmax_t tmp;
95if (!git_parse_signed(value, &tmp, maximum_signed_value_of_type(int)))
96return 0;
97*ret = tmp;
98return 1;
99}
100
101int git_parse_int64(const char *value, int64_t *ret)
102{
103intmax_t tmp;
104if (!git_parse_signed(value, &tmp, maximum_signed_value_of_type(int64_t)))
105return 0;
106*ret = tmp;
107return 1;
108}
109
110int git_parse_ulong(const char *value, unsigned long *ret)
111{
112uintmax_t tmp;
113if (!git_parse_unsigned(value, &tmp, maximum_unsigned_value_of_type(long)))
114return 0;
115*ret = tmp;
116return 1;
117}
118
119int git_parse_ssize_t(const char *value, ssize_t *ret)
120{
121intmax_t tmp;
122if (!git_parse_signed(value, &tmp, maximum_signed_value_of_type(ssize_t)))
123return 0;
124*ret = tmp;
125return 1;
126}
127
128int git_parse_double(const char *value, double *ret)
129{
130char *end;
131double val;
132uintmax_t factor;
133
134if (!value || !*value) {
135errno = EINVAL;
136return 0;
137}
138
139errno = 0;
140val = strtod(value, &end);
141if (errno == ERANGE)
142return 0;
143if (end == value) {
144errno = EINVAL;
145return 0;
146}
147factor = get_unit_factor(end);
148if (!factor) {
149errno = EINVAL;
150return 0;
151}
152val *= factor;
153*ret = val;
154return 1;
155}
156
157int git_parse_maybe_bool_text(const char *value)
158{
159if (!value)
160return 1;
161if (!*value)
162return 0;
163if (!strcasecmp(value, "true")
164|| !strcasecmp(value, "yes")
165|| !strcasecmp(value, "on"))
166return 1;
167if (!strcasecmp(value, "false")
168|| !strcasecmp(value, "no")
169|| !strcasecmp(value, "off"))
170return 0;
171return -1;
172}
173
174int git_parse_maybe_bool(const char *value)
175{
176int v = git_parse_maybe_bool_text(value);
177if (0 <= v)
178return v;
179if (git_parse_int(value, &v))
180return !!v;
181return -1;
182}
183
184/*
185* Parse environment variable 'k' as a boolean (in various
186* possible spellings); if missing, use the default value 'def'.
187*/
188int git_env_bool(const char *k, int def)
189{
190const char *v = getenv(k);
191int val;
192if (!v)
193return def;
194val = git_parse_maybe_bool(v);
195if (val < 0)
196die(_("bad boolean environment value '%s' for '%s'"),
197v, k);
198return val;
199}
200
201/*
202* Parse environment variable 'k' as ulong with possibly a unit
203* suffix; if missing, use the default value 'val'.
204*/
205unsigned long git_env_ulong(const char *k, unsigned long val)
206{
207const char *v = getenv(k);
208if (v && !git_parse_ulong(v, &val))
209die(_("failed to parse %s"), k);
210return val;
211}
212