Git fork
at reftables-rust 211 lines 4.0 kB view raw
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{ 7 if (!*end) 8 return 1; 9 else if (!strcasecmp(end, "k")) 10 return 1024; 11 else if (!strcasecmp(end, "m")) 12 return 1024 * 1024; 13 else if (!strcasecmp(end, "g")) 14 return 1024 * 1024 * 1024; 15 return 0; 16} 17 18int git_parse_signed(const char *value, intmax_t *ret, intmax_t max) 19{ 20 if (value && *value) { 21 char *end; 22 intmax_t val; 23 intmax_t factor; 24 25 if (max < 0) 26 BUG("max must be a positive integer"); 27 28 errno = 0; 29 val = strtoimax(value, &end, 0); 30 if (errno == ERANGE) 31 return 0; 32 if (end == value) { 33 errno = EINVAL; 34 return 0; 35 } 36 factor = get_unit_factor(end); 37 if (!factor) { 38 errno = EINVAL; 39 return 0; 40 } 41 if ((val < 0 && (-max - 1) / factor > val) || 42 (val > 0 && max / factor < val)) { 43 errno = ERANGE; 44 return 0; 45 } 46 val *= factor; 47 *ret = val; 48 return 1; 49 } 50 errno = EINVAL; 51 return 0; 52} 53 54int git_parse_unsigned(const char *value, uintmax_t *ret, uintmax_t max) 55{ 56 if (value && *value) { 57 char *end; 58 uintmax_t val; 59 uintmax_t factor; 60 61 /* negative values would be accepted by strtoumax */ 62 if (strchr(value, '-')) { 63 errno = EINVAL; 64 return 0; 65 } 66 errno = 0; 67 val = strtoumax(value, &end, 0); 68 if (errno == ERANGE) 69 return 0; 70 if (end == value) { 71 errno = EINVAL; 72 return 0; 73 } 74 factor = get_unit_factor(end); 75 if (!factor) { 76 errno = EINVAL; 77 return 0; 78 } 79 if (unsigned_mult_overflows(factor, val) || 80 factor * val > max) { 81 errno = ERANGE; 82 return 0; 83 } 84 val *= factor; 85 *ret = val; 86 return 1; 87 } 88 errno = EINVAL; 89 return 0; 90} 91 92int git_parse_int(const char *value, int *ret) 93{ 94 intmax_t tmp; 95 if (!git_parse_signed(value, &tmp, maximum_signed_value_of_type(int))) 96 return 0; 97 *ret = tmp; 98 return 1; 99} 100 101int git_parse_int64(const char *value, int64_t *ret) 102{ 103 intmax_t tmp; 104 if (!git_parse_signed(value, &tmp, maximum_signed_value_of_type(int64_t))) 105 return 0; 106 *ret = tmp; 107 return 1; 108} 109 110int git_parse_ulong(const char *value, unsigned long *ret) 111{ 112 uintmax_t tmp; 113 if (!git_parse_unsigned(value, &tmp, maximum_unsigned_value_of_type(long))) 114 return 0; 115 *ret = tmp; 116 return 1; 117} 118 119int git_parse_ssize_t(const char *value, ssize_t *ret) 120{ 121 intmax_t tmp; 122 if (!git_parse_signed(value, &tmp, maximum_signed_value_of_type(ssize_t))) 123 return 0; 124 *ret = tmp; 125 return 1; 126} 127 128int git_parse_double(const char *value, double *ret) 129{ 130 char *end; 131 double val; 132 uintmax_t factor; 133 134 if (!value || !*value) { 135 errno = EINVAL; 136 return 0; 137 } 138 139 errno = 0; 140 val = strtod(value, &end); 141 if (errno == ERANGE) 142 return 0; 143 if (end == value) { 144 errno = EINVAL; 145 return 0; 146 } 147 factor = get_unit_factor(end); 148 if (!factor) { 149 errno = EINVAL; 150 return 0; 151 } 152 val *= factor; 153 *ret = val; 154 return 1; 155} 156 157int git_parse_maybe_bool_text(const char *value) 158{ 159 if (!value) 160 return 1; 161 if (!*value) 162 return 0; 163 if (!strcasecmp(value, "true") 164 || !strcasecmp(value, "yes") 165 || !strcasecmp(value, "on")) 166 return 1; 167 if (!strcasecmp(value, "false") 168 || !strcasecmp(value, "no") 169 || !strcasecmp(value, "off")) 170 return 0; 171 return -1; 172} 173 174int git_parse_maybe_bool(const char *value) 175{ 176 int v = git_parse_maybe_bool_text(value); 177 if (0 <= v) 178 return v; 179 if (git_parse_int(value, &v)) 180 return !!v; 181 return -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{ 190 const char *v = getenv(k); 191 int val; 192 if (!v) 193 return def; 194 val = git_parse_maybe_bool(v); 195 if (val < 0) 196 die(_("bad boolean environment value '%s' for '%s'"), 197 v, k); 198 return 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{ 207 const char *v = getenv(k); 208 if (v && !git_parse_ulong(v, &val)) 209 die(_("failed to parse %s"), k); 210 return val; 211}