1 | // Copyright 2008 Google Inc. All Rights Reserved. |
2 | // |
3 | // Architecture-neutral plug compatible replacements for strtol() friends. |
4 | // |
5 | // Long's have different lengths on ILP-32 and LP-64 platforms, and so overflow |
6 | // behavior across the two varies when strtol() and similar are used to parse |
7 | // 32-bit integers. Similar problems exist with atoi(), because although it |
8 | // has an all-integer interface, it uses strtol() internally, and so suffers |
9 | // from the same narrowing problems on assignments to int. |
10 | // |
11 | // Examples: |
12 | // errno = 0; |
13 | // i = strtol("3147483647", NULL, 10); |
14 | // printf("%d, errno %d\n", i, errno); |
15 | // // 32-bit platform: 2147483647, errno 34 |
16 | // // 64-bit platform: -1147483649, errno 0 |
17 | // |
18 | // printf("%d\n", atoi("3147483647")); |
19 | // // 32-bit platform: 2147483647 |
20 | // // 64-bit platform: -1147483649 |
21 | // |
22 | // A way round this is to define local replacements for these, and use them |
23 | // instead of the standard libc functions. |
24 | // |
25 | // In most 32-bit cases the replacements can be inlined away to a call to the |
26 | // libc function. In a couple of 64-bit cases, however, adapters are required, |
27 | // to provide the right overflow and errno behavior. |
28 | // |
29 | |
30 | #ifndef BASE_STRTOINT_H_ |
31 | #define BASE_STRTOINT_H_ |
32 | |
33 | #include <stdlib.h> // For strtol* functions. |
34 | #include <string> |
35 | using std::string; |
36 | |
37 | #include "base/port.h" |
38 | #include "base/basictypes.h" |
39 | |
40 | // Adapter functions for handling overflow and errno. |
41 | int32 strto32_adapter(const char *nptr, char **endptr, int base); |
42 | uint32 strtou32_adapter(const char *nptr, char **endptr, int base); |
43 | |
44 | // Conversions to a 32-bit integer can pass the call to strto[u]l on 32-bit |
45 | // platforms, but need a little extra work on 64-bit platforms. |
46 | inline int32 strto32(const char *nptr, char **endptr, int base) { |
47 | if (sizeof(int32) == sizeof(long)) |
48 | return strtol(nptr, endptr, base); |
49 | else |
50 | return strto32_adapter(nptr, endptr, base); |
51 | } |
52 | |
53 | inline uint32 strtou32(const char *nptr, char **endptr, int base) { |
54 | if (sizeof(uint32) == sizeof(unsigned long)) |
55 | return strtoul(nptr, endptr, base); |
56 | else |
57 | return strtou32_adapter(nptr, endptr, base); |
58 | } |
59 | |
60 | // For now, long long is 64-bit on all the platforms we care about, so these |
61 | // functions can simply pass the call to strto[u]ll. |
62 | inline int64 strto64(const char *nptr, char **endptr, int base) { |
63 | COMPILE_ASSERT(sizeof(int64) == sizeof(long long), |
64 | sizeof_int64_is_not_sizeof_long_long); |
65 | return strtoll(nptr, endptr, base); |
66 | } |
67 | |
68 | inline uint64 strtou64(const char *nptr, char **endptr, int base) { |
69 | COMPILE_ASSERT(sizeof(uint64) == sizeof(unsigned long long), |
70 | sizeof_uint64_is_not_sizeof_long_long); |
71 | return strtoull(nptr, endptr, base); |
72 | } |
73 | |
74 | // Although it returns an int, atoi() is implemented in terms of strtol, and |
75 | // so has differing overflow and underflow behavior. atol is the same. |
76 | inline int32 atoi32(const char *nptr) { |
77 | return strto32(nptr, NULL, 10); |
78 | } |
79 | |
80 | inline int64 atoi64(const char *nptr) { |
81 | return strto64(nptr, NULL, 10); |
82 | } |
83 | |
84 | // Convenience versions of the above that take a string argument. |
85 | inline int32 atoi32(const string &s) { |
86 | return atoi32(s.c_str()); |
87 | } |
88 | |
89 | inline int64 atoi64(const string &s) { |
90 | return atoi64(s.c_str()); |
91 | } |
92 | |
93 | #endif // BASE_STRTOINT_H_ |
94 | |