tor  0.4.2.1-alpha-dev
unitparse.c
Go to the documentation of this file.
1 /* Copyright (c) 2001 Matej Pfajfar.
2  * Copyright (c) 2001-2004, Roger Dingledine.
3  * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
4  * Copyright (c) 2007-2019, The Tor Project, Inc. */
5 /* See LICENSE for licensing information */
6 
12 #include "orconfig.h"
13 #include "lib/confmgt/unitparse.h"
14 #include "lib/log/log.h"
15 #include "lib/log/util_bug.h"
16 #include "lib/string/parse_int.h"
17 #include "lib/string/util_string.h"
18 
19 #include <string.h>
20 
23 const struct unit_table_t memory_units[] = {
24  { "", 1 },
25  { "b", 1<< 0 },
26  { "byte", 1<< 0 },
27  { "bytes", 1<< 0 },
28  { "kb", 1<<10 },
29  { "kbyte", 1<<10 },
30  { "kbytes", 1<<10 },
31  { "kilobyte", 1<<10 },
32  { "kilobytes", 1<<10 },
33  { "kilobits", 1<<7 },
34  { "kilobit", 1<<7 },
35  { "kbits", 1<<7 },
36  { "kbit", 1<<7 },
37  { "m", 1<<20 },
38  { "mb", 1<<20 },
39  { "mbyte", 1<<20 },
40  { "mbytes", 1<<20 },
41  { "megabyte", 1<<20 },
42  { "megabytes", 1<<20 },
43  { "megabits", 1<<17 },
44  { "megabit", 1<<17 },
45  { "mbits", 1<<17 },
46  { "mbit", 1<<17 },
47  { "gb", 1<<30 },
48  { "gbyte", 1<<30 },
49  { "gbytes", 1<<30 },
50  { "gigabyte", 1<<30 },
51  { "gigabytes", 1<<30 },
52  { "gigabits", 1<<27 },
53  { "gigabit", 1<<27 },
54  { "gbits", 1<<27 },
55  { "gbit", 1<<27 },
56  { "tb", UINT64_C(1)<<40 },
57  { "tbyte", UINT64_C(1)<<40 },
58  { "tbytes", UINT64_C(1)<<40 },
59  { "terabyte", UINT64_C(1)<<40 },
60  { "terabytes", UINT64_C(1)<<40 },
61  { "terabits", UINT64_C(1)<<37 },
62  { "terabit", UINT64_C(1)<<37 },
63  { "tbits", UINT64_C(1)<<37 },
64  { "tbit", UINT64_C(1)<<37 },
65  { NULL, 0 },
66 };
67 
70 const struct unit_table_t time_units[] = {
71  { "", 1 },
72  { "second", 1 },
73  { "seconds", 1 },
74  { "minute", 60 },
75  { "minutes", 60 },
76  { "hour", 60*60 },
77  { "hours", 60*60 },
78  { "day", 24*60*60 },
79  { "days", 24*60*60 },
80  { "week", 7*24*60*60 },
81  { "weeks", 7*24*60*60 },
82  { "month", 2629728, }, /* about 30.437 days */
83  { "months", 2629728, },
84  { NULL, 0 },
85 };
86 
89 const struct unit_table_t time_msec_units[] = {
90  { "", 1 },
91  { "msec", 1 },
92  { "millisecond", 1 },
93  { "milliseconds", 1 },
94  { "second", 1000 },
95  { "seconds", 1000 },
96  { "minute", 60*1000 },
97  { "minutes", 60*1000 },
98  { "hour", 60*60*1000 },
99  { "hours", 60*60*1000 },
100  { "day", 24*60*60*1000 },
101  { "days", 24*60*60*1000 },
102  { "week", 7*24*60*60*1000 },
103  { "weeks", 7*24*60*60*1000 },
104  { NULL, 0 },
105 };
106 
113 uint64_t
114 config_parse_units(const char *val, const unit_table_t *u, int *ok)
115 {
116  uint64_t v = 0;
117  double d = 0;
118  int use_float = 0;
119  char *cp;
120 
121  tor_assert(ok);
122 
123  v = tor_parse_uint64(val, 10, 0, UINT64_MAX, ok, &cp);
124  if (!*ok || (cp && *cp == '.')) {
125  d = tor_parse_double(val, 0, (double)UINT64_MAX, ok, &cp);
126  if (!*ok)
127  goto done;
128  use_float = 1;
129  }
130 
131  if (BUG(!cp)) {
132  // cp should always be non-NULL if the parse operation succeeds.
133 
134  // LCOV_EXCL_START
135  *ok = 1;
136  v = use_float ? ((uint64_t)d) : v;
137  goto done;
138  // LCOV_EXCL_STOP
139  }
140 
141  cp = (char*) eat_whitespace(cp);
142 
143  for ( ;u->unit;++u) {
144  if (!strcasecmp(u->unit, cp)) {
145  if (use_float)
146  v = (uint64_t)(u->multiplier * d);
147  else
148  v *= u->multiplier;
149  *ok = 1;
150  goto done;
151  }
152  }
153  log_warn(LD_CONFIG, "Unknown unit '%s'.", cp);
154  *ok = 0;
155  done:
156 
157  if (*ok)
158  return v;
159  else
160  return 0;
161 }
162 
167 uint64_t
168 config_parse_memunit(const char *s, int *ok)
169 {
170  uint64_t u = config_parse_units(s, memory_units, ok);
171  return u;
172 }
173 
178 int
179 config_parse_msec_interval(const char *s, int *ok)
180 {
181  uint64_t r;
183  if (r > INT_MAX) {
184  log_warn(LD_CONFIG, "Msec interval '%s' is too long", s);
185  *ok = 0;
186  return -1;
187  }
188  return (int)r;
189 }
190 
195 int
196 config_parse_interval(const char *s, int *ok)
197 {
198  uint64_t r;
199  r = config_parse_units(s, time_units, ok);
200  if (r > INT_MAX) {
201  log_warn(LD_CONFIG, "Interval '%s' is too long", s);
202  *ok = 0;
203  return -1;
204  }
205  return (int)r;
206 }
Header for lib/confmgt/unitparse.c.
const struct unit_table_t memory_units[]
Definition: unitparse.c:23
uint64_t tor_parse_uint64(const char *s, int base, uint64_t min, uint64_t max, int *ok, char **next)
Definition: parse_int.c:107
int config_parse_interval(const char *s, int *ok)
Definition: unitparse.c:196
const struct unit_table_t time_msec_units[]
Definition: unitparse.c:89
Header for util_string.c.
int config_parse_msec_interval(const char *s, int *ok)
Definition: unitparse.c:179
tor_assert(buffer)
const char * eat_whitespace(const char *s)
Definition: util_string.c:268
uint64_t config_parse_units(const char *val, const unit_table_t *u, int *ok)
Definition: unitparse.c:114
double tor_parse_double(const char *s, double min, double max, int *ok, char **next)
Definition: parse_int.c:94
const char * unit
Definition: unitparse.h:20
uint64_t config_parse_memunit(const char *s, int *ok)
Definition: unitparse.c:168
const struct unit_table_t time_units[]
Definition: unitparse.c:70
Headers for log.c.
Macros to manage assertions, fatal and non-fatal.
Header for parse_int.c.
#define LD_CONFIG
Definition: log.h:66
uint64_t multiplier
Definition: unitparse.h:21