forked from regehr/str2long_contest
-
Notifications
You must be signed in to change notification settings - Fork 0
/
daniel.c
50 lines (36 loc) · 1.14 KB
/
daniel.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
#include "str2long.h"
long str2long_daniel (const char *str)
{
#define ULONG_MSB (1ul << (sizeof(long) * CHAR_BIT - 1))
int neg = 0;
unsigned long val = 0;
if (*str == '-') {
neg = 1;
str++;
}
do {
unsigned c = *str++;
unsigned long newval;
/* not decimal digit */
if (c < '0' || c > '9') goto err;
/* this might overflow, but unsigned overflow is defined as modulo arithmetic */
newval = val * 10ul + (c - '0');
/* larger than max positive representable value */
if (newval > ULONG_MSB) goto err;
/* wraparound */
if (val > newval) goto err;
/* largest negative, but more input left */
if (val == ULONG_MSB && *str) goto err;
val = newval;
} while (*str);
/* largest representable negative - must have negative sign */
if (val == ULONG_MSB && !neg) goto err;
/* negate if necessary; assume 2's complement */
if (neg) val = -val;
error = 0;
/* conversion from unsigned to signed is implementation defined; assume 2's complement */
return val;
err:
error = 1;
return 0;
}