ARGOBOTS  1.1
atoi.c
Go to the documentation of this file.
1 /* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */
2 /*
3  * See COPYRIGHT in top-level directory.
4  */
5 
6 #include "abti.h"
7 
8 static ABTU_ret_err int atoi_impl(const char *str, ABT_bool *p_is_signed,
9  uint64_t *p_val, ABT_bool *p_overflow);
10 
11 ABTU_ret_err int ABTU_atoi(const char *str, int *p_val, ABT_bool *p_overflow)
12 {
13  uint64_t val;
14  ABT_bool overflow, is_signed;
15  int abt_errno = atoi_impl(str, &is_signed, &val, &overflow);
16  ABTI_CHECK_ERROR(abt_errno);
17  if (is_signed) {
18  if (val > (uint64_t)(-(int64_t)INT_MIN)) {
19  /* Underflow. */
20  overflow = ABT_TRUE;
21  *p_val = INT_MIN;
22  } else {
23  *p_val = (int)(-(int64_t)val);
24  }
25  } else {
26  if (val > (uint64_t)INT_MAX) {
27  /* Overflow. */
28  overflow = ABT_TRUE;
29  *p_val = INT_MAX;
30  } else {
31  *p_val = (int)val;
32  }
33  }
34  if (p_overflow)
35  *p_overflow = overflow;
36  return abt_errno;
37 }
38 
39 ABTU_ret_err int ABTU_atoui32(const char *str, uint32_t *p_val,
40  ABT_bool *p_overflow)
41 {
42  uint64_t val;
43  ABT_bool overflow, is_signed;
44  int abt_errno = atoi_impl(str, &is_signed, &val, &overflow);
45  ABTI_CHECK_ERROR(abt_errno);
46  if (is_signed) {
47  /* Underflow. */
48  if (val != 0)
49  overflow = ABT_TRUE;
50  *p_val = 0;
51  } else {
52  if (val > (uint64_t)UINT32_MAX) {
53  /* Overflow. */
54  overflow = ABT_TRUE;
55  *p_val = UINT32_MAX;
56  } else {
57  *p_val = (uint32_t)val;
58  }
59  }
60  if (p_overflow)
61  *p_overflow = overflow;
62  return abt_errno;
63 }
64 
65 ABTU_ret_err int ABTU_atoui64(const char *str, uint64_t *p_val,
66  ABT_bool *p_overflow)
67 {
68  uint64_t val;
69  ABT_bool overflow, is_signed;
70  int abt_errno = atoi_impl(str, &is_signed, &val, &overflow);
71  ABTI_CHECK_ERROR(abt_errno);
72  if (is_signed) {
73  /* Underflow. */
74  if (val != 0)
75  overflow = ABT_TRUE;
76  *p_val = 0;
77  } else {
78  *p_val = val;
79  }
80  if (p_overflow)
81  *p_overflow = overflow;
82  return abt_errno;
83 }
84 
85 ABTU_ret_err int ABTU_atosz(const char *str, size_t *p_val,
86  ABT_bool *p_overflow)
87 {
88  ABTI_STATIC_ASSERT(sizeof(size_t) == 4 || sizeof(size_t) == 8);
89  if (sizeof(size_t) == 4) {
90  uint32_t val;
91  ABT_bool overflow;
92  int abt_errno = ABTU_atoui32(str, &val, &overflow);
93  ABTI_CHECK_ERROR(abt_errno);
94  *p_val = (size_t)val;
95  if (p_overflow)
96  *p_overflow = overflow;
97  return abt_errno;
98  } else {
99  uint64_t val;
100  ABT_bool overflow;
101  int abt_errno = ABTU_atoui64(str, &val, &overflow);
102  ABTI_CHECK_ERROR(abt_errno);
103  *p_val = (size_t)val;
104  if (p_overflow)
105  *p_overflow = overflow;
106  return abt_errno;
107  }
108 }
109 
110 /*****************************************************************************/
111 /* Internal static functions */
112 /*****************************************************************************/
113 
114 static ABTU_ret_err int atoi_impl(const char *str, ABT_bool *p_is_signed,
115  uint64_t *p_val, ABT_bool *p_overflow)
116 {
117  uint64_t val = 0;
118  ABT_bool is_signed = ABT_FALSE, read_char = ABT_FALSE,
119  read_digit = ABT_FALSE;
120  while (1) {
121  if ((*str == '\n' || *str == '\t' || *str == ' ' || *str == '\r') &&
122  read_char == ABT_FALSE) {
123  /* Do nothing. */
124  } else if (*str == '+' && read_digit == ABT_FALSE) {
125  read_char = ABT_TRUE;
126  } else if (*str == '-' && read_digit == ABT_FALSE) {
127  /* Flip the digit. */
128  read_char = ABT_TRUE;
129  is_signed = is_signed ? ABT_FALSE : ABT_TRUE;
130  } else if ('0' <= *str && *str <= '9') {
131  read_char = ABT_TRUE;
132  read_digit = ABT_TRUE;
133  /* Will val overflow? */
134  if ((val > UINT64_MAX / 10) ||
135  (val * 10 > UINT64_MAX - (uint64_t)(*str - '0'))) {
136  /* Overflow. */
137  *p_overflow = ABT_TRUE;
138  *p_val = UINT64_MAX;
139  *p_is_signed = is_signed;
140  return ABT_SUCCESS;
141  }
142  val = val * 10 + (uint64_t)(*str - '0');
143  read_digit = ABT_TRUE;
144  } else {
145  /* Stop reading str. */
146  if (read_digit == ABT_FALSE) {
147  /* No integer. */
148  return ABT_ERR_INV_ARG;
149  }
150  *p_overflow = ABT_FALSE;
151  *p_val = val;
152  *p_is_signed = is_signed;
153  return ABT_SUCCESS;
154  }
155  str++;
156  }
157 }
158 
159 #if 0
160 
161 void test_ABTU_atoi(const char *str, int err, int val, ABT_bool overflow)
162 {
163  int ret_val;
164  ABT_bool ret_overflow;
165  int ret_err = ABTU_atoi(str, &ret_val, &ret_overflow);
166  assert(err == ret_err);
167  if (err == ABT_SUCCESS) {
168  assert(val == ret_val);
169  assert(overflow == ret_overflow);
170  }
171 }
172 
173 void test_ABTU_atoui32(const char *str, int err, uint32_t val, ABT_bool overflow)
174 {
175  uint32_t ret_val;
176  ABT_bool ret_overflow;
177  int ret_err = ABTU_atoui32(str, &ret_val, &ret_overflow);
178  assert(err == ret_err);
179  if (err == ABT_SUCCESS) {
180  assert(val == ret_val);
181  assert(overflow == ret_overflow);
182  }
183 }
184 
185 void test_ABTU_atoui64(const char *str, int err, uint64_t val, ABT_bool overflow)
186 {
187  uint64_t ret_val;
188  ABT_bool ret_overflow;
189  int ret_err = ABTU_atoui64(str, &ret_val, &ret_overflow);
190  assert(err == ret_err);
191  if (err == ABT_SUCCESS) {
192  assert(val == ret_val);
193  assert(overflow == ret_overflow);
194  }
195 }
196 
197 void test_ABTU_atosz(const char *str, int err, size_t val, ABT_bool overflow)
198 {
199  size_t ret_val;
200  ABT_bool ret_overflow;
201  int ret_err = ABTU_atosz(str, &ret_val, &ret_overflow);
202  assert(err == ret_err);
203  if (err == ABT_SUCCESS) {
204  assert(val == ret_val);
205  assert(overflow == ret_overflow);
206  }
207 }
208 
209 int main()
210 {
211  typedef struct {
212  const char *str;
213  int err;
214  int val;
215  } base_case_t;
216 
217  /* Basic cases (no overflow). */
218  base_case_t cases[] = {
219  { "0", ABT_SUCCESS, 0 },
220  { "63", ABT_SUCCESS, 63 },
221  { "+14", ABT_SUCCESS, 14 },
222  { "+0", ABT_SUCCESS, 0 },
223  { "+-+-+---++0", ABT_SUCCESS, 0 },
224  { "+-+-+---+-+8800", ABT_SUCCESS, 8800 },
225  { "----1---", ABT_SUCCESS, 1 },
226  { "abc", ABT_ERR_INV_ARG, 0 },
227  { "13abc", ABT_SUCCESS, 13 },
228  { "000123456", ABT_SUCCESS, 123456 },
229  { "00000000", ABT_SUCCESS, 0 },
230  { "123x456", ABT_SUCCESS, 123 },
231  { "123+456", ABT_SUCCESS, 123 },
232  { "123 456", ABT_SUCCESS, 123 },
233  { "--12-3-45-6", ABT_SUCCESS, 12 },
234  { "", ABT_ERR_INV_ARG, 0 },
235  { "+", ABT_ERR_INV_ARG, 0 },
236  { "-", ABT_ERR_INV_ARG, 0 },
237  { "+ 2", ABT_ERR_INV_ARG, 0 },
238  { " \n\t\r+-+-", ABT_ERR_INV_ARG, 0 },
239  { " \n\t\r+-+-123", ABT_SUCCESS, 123 },
240  };
241 
242  size_t i;
243  for (i = 0; i < sizeof(cases) / sizeof(cases[0]); i++) {
244  test_ABTU_atoi(cases[i].str, cases[i].err, cases[i].val, ABT_FALSE);
245  test_ABTU_atoui32(cases[i].str, cases[i].err, cases[i].val, ABT_FALSE);
246  test_ABTU_atoui64(cases[i].str, cases[i].err, cases[i].val, ABT_FALSE);
247  test_ABTU_atosz(cases[i].str, cases[i].err, cases[i].val, ABT_FALSE);
248  }
249 
250  /* Check negative values. */
251  test_ABTU_atoi("-1", ABT_SUCCESS, -1, ABT_FALSE);
252  test_ABTU_atoi("-9990", ABT_SUCCESS, -9990, ABT_FALSE);
253  test_ABTU_atoi(" --+-1234a-", ABT_SUCCESS, -1234, ABT_FALSE);
254 
255  /* Check overflow/underflow */
256  test_ABTU_atoi("2147483646", ABT_SUCCESS, 2147483646, ABT_FALSE);
257  test_ABTU_atoi("2147483647", ABT_SUCCESS, 2147483647, ABT_FALSE);
258  test_ABTU_atoi("2147483648", ABT_SUCCESS, 2147483647, ABT_TRUE);
259  test_ABTU_atoi("11112147483648", ABT_SUCCESS, 2147483647, ABT_TRUE);
260  test_ABTU_atoi("-2147483647", ABT_SUCCESS, -2147483647, ABT_FALSE);
261  test_ABTU_atoi("-2147483648", ABT_SUCCESS, -2147483648, ABT_FALSE);
262  test_ABTU_atoi("-2147483649", ABT_SUCCESS, -2147483648, ABT_TRUE);
263  test_ABTU_atoi("-11112147483648", ABT_SUCCESS, -2147483648, ABT_TRUE);
264 
265  test_ABTU_atoui32("4294967294", ABT_SUCCESS, 4294967294, ABT_FALSE);
266  test_ABTU_atoui32("4294967295", ABT_SUCCESS, 4294967295, ABT_FALSE);
267  test_ABTU_atoui32("4294967296", ABT_SUCCESS, 4294967295, ABT_TRUE);
268  test_ABTU_atoui32("11114294967295", ABT_SUCCESS, 4294967295, ABT_TRUE);
269  test_ABTU_atoui32("-1", ABT_SUCCESS, 0, ABT_TRUE);
270  test_ABTU_atoui32("-2147483649", ABT_SUCCESS, 0, ABT_TRUE);
271 
272  test_ABTU_atoui64("18446744073709551614", ABT_SUCCESS,
273  18446744073709551614u, ABT_FALSE);
274  test_ABTU_atoui64("18446744073709551615", ABT_SUCCESS,
275  18446744073709551615u, ABT_FALSE);
276  test_ABTU_atoui64("18446744073709551616", ABT_SUCCESS,
277  18446744073709551615u, ABT_TRUE);
278  test_ABTU_atoui64("111118446744073709551615", ABT_SUCCESS,
279  18446744073709551615u, ABT_TRUE);
280  test_ABTU_atoui64("-1", ABT_SUCCESS, 0, ABT_TRUE);
281  test_ABTU_atoui64("-18446744073709551616", ABT_SUCCESS, 0, ABT_TRUE);
282 
283  if (sizeof(size_t) == 4) {
284  test_ABTU_atosz("4294967294", ABT_SUCCESS, 4294967294, ABT_FALSE);
285  test_ABTU_atosz("4294967295", ABT_SUCCESS, 4294967295, ABT_FALSE);
286  test_ABTU_atosz("4294967296", ABT_SUCCESS, 4294967295, ABT_TRUE);
287  test_ABTU_atosz("11114294967295", ABT_SUCCESS, 4294967295, ABT_TRUE);
288  test_ABTU_atosz("-1", ABT_SUCCESS, 0, ABT_TRUE);
289  test_ABTU_atosz("-2147483649", ABT_SUCCESS, 0, ABT_TRUE);
290  } else {
291  assert(sizeof(size_t) == 8);
292  test_ABTU_atosz("18446744073709551614", ABT_SUCCESS,
293  18446744073709551614u, ABT_FALSE);
294  test_ABTU_atosz("18446744073709551615", ABT_SUCCESS,
295  18446744073709551615u, ABT_FALSE);
296  test_ABTU_atosz("18446744073709551616", ABT_SUCCESS,
297  18446744073709551615u, ABT_TRUE);
298  test_ABTU_atosz("111118446744073709551615", ABT_SUCCESS,
299  18446744073709551615u, ABT_TRUE);
300  test_ABTU_atosz("-1", ABT_SUCCESS, 0, ABT_TRUE);
301  test_ABTU_atosz("-18446744073709551616", ABT_SUCCESS, 0, ABT_TRUE);
302  }
303 }
304 
305 #endif
ABT_bool
int ABT_bool
Boolean type.
Definition: abt.h:1001
ABTI_CHECK_ERROR
#define ABTI_CHECK_ERROR(abt_errno)
Definition: abti_error.h:120
ABTU_atosz
ABTU_ret_err int ABTU_atosz(const char *str, size_t *p_val, ABT_bool *p_overflow)
Definition: atoi.c:85
abti.h
ABTU_atoui32
ABTU_ret_err int ABTU_atoui32(const char *str, uint32_t *p_val, ABT_bool *p_overflow)
Definition: atoi.c:39
ABTI_STATIC_ASSERT
#define ABTI_STATIC_ASSERT(cond)
Definition: abti_error.h:19
ABTU_atoui64
ABTU_ret_err int ABTU_atoui64(const char *str, uint64_t *p_val, ABT_bool *p_overflow)
Definition: atoi.c:65
ABT_SUCCESS
#define ABT_SUCCESS
Error code: the routine returns successfully.
Definition: abt.h:92
ABTU_ret_err
#define ABTU_ret_err
Definition: abtu.h:146
atoi_impl
static ABTU_ret_err int atoi_impl(const char *str, ABT_bool *p_is_signed, uint64_t *p_val, ABT_bool *p_overflow)
Definition: atoi.c:114
ABT_TRUE
#define ABT_TRUE
True constant for ABT_bool.
Definition: abt.h:748
ABT_FALSE
#define ABT_FALSE
False constant for ABT_bool.
Definition: abt.h:750
ABT_ERR_INV_ARG
#define ABT_ERR_INV_ARG
Error code: invalid user argument.
Definition: abt.h:250
ABTU_atoi
ABTU_ret_err int ABTU_atoi(const char *str, int *p_val, ABT_bool *p_overflow)
Definition: atoi.c:11