blob: 6cf1299b30fc43cfa057709b6a679e85b251c6ce [file] [log] [blame]
Denis Vlasenkoed836cd2006-11-25 14:44:13 +00001/* vi: set sw=4 ts=4: */
2/*
3 * ascii-to-numbers implementations for busybox
4 *
5 * Copyright (C) 2003 Manuel Novoa III <mjn3@codepoet.org>
6 *
7 * Licensed under GPLv2, see file LICENSE in this tarball for details.
8 */
9
Denis Vlasenko98636eb2008-05-09 17:59:34 +000010#if __GNUC_PREREQ(4,1)
11# pragma GCC visibility push(hidden)
12#endif
13
Denis Vlasenkoed836cd2006-11-25 14:44:13 +000014/* Provides extern declarations of functions */
15#define DECLARE_STR_CONV(type, T, UT) \
16\
17unsigned type xstrto##UT##_range_sfx(const char *str, int b, unsigned type l, unsigned type u, const struct suffix_mult *sfx); \
18unsigned type xstrto##UT##_range(const char *str, int b, unsigned type l, unsigned type u); \
19unsigned type xstrto##UT##_sfx(const char *str, int b, const struct suffix_mult *sfx); \
20unsigned type xstrto##UT(const char *str, int b); \
21unsigned type xato##UT##_range_sfx(const char *str, unsigned type l, unsigned type u, const struct suffix_mult *sfx); \
22unsigned type xato##UT##_range(const char *str, unsigned type l, unsigned type u); \
23unsigned type xato##UT##_sfx(const char *str, const struct suffix_mult *sfx); \
24unsigned type xato##UT(const char *str); \
Denis Vlasenkob71c6682007-07-21 15:08:09 +000025type xstrto##T##_range_sfx(const char *str, int b, type l, type u, const struct suffix_mult *sfx); \
Denis Vlasenkoed836cd2006-11-25 14:44:13 +000026type xstrto##T##_range(const char *str, int b, type l, type u); \
27type xato##T##_range_sfx(const char *str, type l, type u, const struct suffix_mult *sfx); \
28type xato##T##_range(const char *str, type l, type u); \
29type xato##T##_sfx(const char *str, const struct suffix_mult *sfx); \
30type xato##T(const char *str); \
31
32/* Unsigned long long functions always exist */
33DECLARE_STR_CONV(long long, ll, ull)
34
35
Denis Vlasenkoa597aad2006-12-16 23:48:13 +000036/* Provides inline definitions of functions */
Denis Vlasenkoed836cd2006-11-25 14:44:13 +000037/* (useful for mapping them to the type of the same width) */
38#define DEFINE_EQUIV_STR_CONV(narrow, N, W, UN, UW) \
39\
Denis Vlasenko3ad5d0c2007-06-12 20:54:54 +000040static ALWAYS_INLINE \
Denis Vlasenkoed836cd2006-11-25 14:44:13 +000041unsigned narrow xstrto##UN##_range_sfx(const char *str, int b, unsigned narrow l, unsigned narrow u, const struct suffix_mult *sfx) \
42{ return xstrto##UW##_range_sfx(str, b, l, u, sfx); } \
Denis Vlasenko3ad5d0c2007-06-12 20:54:54 +000043static ALWAYS_INLINE \
Denis Vlasenkoed836cd2006-11-25 14:44:13 +000044unsigned narrow xstrto##UN##_range(const char *str, int b, unsigned narrow l, unsigned narrow u) \
45{ return xstrto##UW##_range(str, b, l, u); } \
Denis Vlasenko3ad5d0c2007-06-12 20:54:54 +000046static ALWAYS_INLINE \
Denis Vlasenkoed836cd2006-11-25 14:44:13 +000047unsigned narrow xstrto##UN##_sfx(const char *str, int b, const struct suffix_mult *sfx) \
48{ return xstrto##UW##_sfx(str, b, sfx); } \
Denis Vlasenko3ad5d0c2007-06-12 20:54:54 +000049static ALWAYS_INLINE \
Denis Vlasenkoed836cd2006-11-25 14:44:13 +000050unsigned narrow xstrto##UN(const char *str, int b) \
51{ return xstrto##UW(str, b); } \
Denis Vlasenko3ad5d0c2007-06-12 20:54:54 +000052static ALWAYS_INLINE \
Denis Vlasenkoed836cd2006-11-25 14:44:13 +000053unsigned narrow xato##UN##_range_sfx(const char *str, unsigned narrow l, unsigned narrow u, const struct suffix_mult *sfx) \
54{ return xato##UW##_range_sfx(str, l, u, sfx); } \
Denis Vlasenko3ad5d0c2007-06-12 20:54:54 +000055static ALWAYS_INLINE \
Denis Vlasenkoed836cd2006-11-25 14:44:13 +000056unsigned narrow xato##UN##_range(const char *str, unsigned narrow l, unsigned narrow u) \
57{ return xato##UW##_range(str, l, u); } \
Denis Vlasenko3ad5d0c2007-06-12 20:54:54 +000058static ALWAYS_INLINE \
Denis Vlasenkoed836cd2006-11-25 14:44:13 +000059unsigned narrow xato##UN##_sfx(const char *str, const struct suffix_mult *sfx) \
60{ return xato##UW##_sfx(str, sfx); } \
Denis Vlasenko3ad5d0c2007-06-12 20:54:54 +000061static ALWAYS_INLINE \
Denis Vlasenkoed836cd2006-11-25 14:44:13 +000062unsigned narrow xato##UN(const char *str) \
63{ return xato##UW(str); } \
Denis Vlasenko3ad5d0c2007-06-12 20:54:54 +000064static ALWAYS_INLINE \
Denis Vlasenkoed836cd2006-11-25 14:44:13 +000065narrow xstrto##N##_range_sfx(const char *str, int b, narrow l, narrow u, const struct suffix_mult *sfx) \
66{ return xstrto##W##_range_sfx(str, b, l, u, sfx); } \
Denis Vlasenko3ad5d0c2007-06-12 20:54:54 +000067static ALWAYS_INLINE \
Denis Vlasenkoed836cd2006-11-25 14:44:13 +000068narrow xstrto##N##_range(const char *str, int b, narrow l, narrow u) \
69{ return xstrto##W##_range(str, b, l, u); } \
Denis Vlasenko3ad5d0c2007-06-12 20:54:54 +000070static ALWAYS_INLINE \
Denis Vlasenkoed836cd2006-11-25 14:44:13 +000071narrow xato##N##_range_sfx(const char *str, narrow l, narrow u, const struct suffix_mult *sfx) \
72{ return xato##W##_range_sfx(str, l, u, sfx); } \
Denis Vlasenko3ad5d0c2007-06-12 20:54:54 +000073static ALWAYS_INLINE \
Denis Vlasenkoed836cd2006-11-25 14:44:13 +000074narrow xato##N##_range(const char *str, narrow l, narrow u) \
75{ return xato##W##_range(str, l, u); } \
Denis Vlasenko3ad5d0c2007-06-12 20:54:54 +000076static ALWAYS_INLINE \
Denis Vlasenkoed836cd2006-11-25 14:44:13 +000077narrow xato##N##_sfx(const char *str, const struct suffix_mult *sfx) \
78{ return xato##W##_sfx(str, sfx); } \
Denis Vlasenko3ad5d0c2007-06-12 20:54:54 +000079static ALWAYS_INLINE \
Denis Vlasenkoed836cd2006-11-25 14:44:13 +000080narrow xato##N(const char *str) \
81{ return xato##W(str); } \
82
83/* If long == long long, then just map them one-to-one */
84#if ULONG_MAX == ULLONG_MAX
85DEFINE_EQUIV_STR_CONV(long, l, ll, ul, ull)
86#else
87/* Else provide extern defs */
88DECLARE_STR_CONV(long, l, ul)
89#endif
90
91/* Same for int -> [long] long */
92#if UINT_MAX == ULLONG_MAX
93DEFINE_EQUIV_STR_CONV(int, i, ll, u, ull)
94#elif UINT_MAX == ULONG_MAX
95DEFINE_EQUIV_STR_CONV(int, i, l, u, ul)
96#else
97DECLARE_STR_CONV(int, i, u)
98#endif
Denis Vlasenko43bddf32006-11-25 14:49:04 +000099
100/* Specialized */
101
102int BUG_xatou32_unimplemented(void);
Denis Vlasenko3ad5d0c2007-06-12 20:54:54 +0000103static ALWAYS_INLINE uint32_t xatou32(const char *numstr)
Denis Vlasenko43bddf32006-11-25 14:49:04 +0000104{
105 if (UINT_MAX == 0xffffffff)
106 return xatou(numstr);
107 if (ULONG_MAX == 0xffffffff)
108 return xatoul(numstr);
109 return BUG_xatou32_unimplemented();
110}
Denis Vlasenkod686a042006-11-27 14:43:21 +0000111
Denis Vlasenkof74194e2007-10-18 12:54:39 +0000112/* Non-aborting kind of convertors: bb_strto[u][l]l */
113
114/* On exit: errno = 0 only if there was non-empty, '\0' terminated value
115 * errno = EINVAL if value was not '\0' terminated, but othervise ok
116 * Return value is still valid, caller should just check whether end[0]
117 * is a valid terminating char for particular case. OTOH, if caller
118 * requires '\0' terminated input, [s]he can just check errno == 0.
119 * errno = ERANGE if value had alphanumeric terminating char ("1234abcg").
120 * errno = ERANGE if value is out of range, missing, etc.
121 * errno = ERANGE if value had minus sign for strtouXX (even "-0" is not ok )
122 * return value is all-ones in this case.
123 */
Denis Vlasenkod686a042006-11-27 14:43:21 +0000124
125unsigned long long bb_strtoull(const char *arg, char **endp, int base);
126long long bb_strtoll(const char *arg, char **endp, int base);
127
128#if ULONG_MAX == ULLONG_MAX
Denis Vlasenko3ad5d0c2007-06-12 20:54:54 +0000129static ALWAYS_INLINE
Denis Vlasenkod686a042006-11-27 14:43:21 +0000130unsigned long bb_strtoul(const char *arg, char **endp, int base)
131{ return bb_strtoull(arg, endp, base); }
Denis Vlasenko3ad5d0c2007-06-12 20:54:54 +0000132static ALWAYS_INLINE
Denis Vlasenkoa597aad2006-12-16 23:48:13 +0000133long bb_strtol(const char *arg, char **endp, int base)
Denis Vlasenkod686a042006-11-27 14:43:21 +0000134{ return bb_strtoll(arg, endp, base); }
135#else
136unsigned long bb_strtoul(const char *arg, char **endp, int base);
137long bb_strtol(const char *arg, char **endp, int base);
138#endif
139
140#if UINT_MAX == ULLONG_MAX
Denis Vlasenko3ad5d0c2007-06-12 20:54:54 +0000141static ALWAYS_INLINE
Denis Vlasenkoa597aad2006-12-16 23:48:13 +0000142unsigned bb_strtou(const char *arg, char **endp, int base)
Denis Vlasenkod686a042006-11-27 14:43:21 +0000143{ return bb_strtoull(arg, endp, base); }
Denis Vlasenko3ad5d0c2007-06-12 20:54:54 +0000144static ALWAYS_INLINE
Denis Vlasenkoa597aad2006-12-16 23:48:13 +0000145int bb_strtoi(const char *arg, char **endp, int base)
Denis Vlasenkod686a042006-11-27 14:43:21 +0000146{ return bb_strtoll(arg, endp, base); }
147#elif UINT_MAX == ULONG_MAX
Denis Vlasenko3ad5d0c2007-06-12 20:54:54 +0000148static ALWAYS_INLINE
Denis Vlasenkoa597aad2006-12-16 23:48:13 +0000149unsigned bb_strtou(const char *arg, char **endp, int base)
Denis Vlasenkod686a042006-11-27 14:43:21 +0000150{ return bb_strtoul(arg, endp, base); }
Denis Vlasenko3ad5d0c2007-06-12 20:54:54 +0000151static ALWAYS_INLINE
Denis Vlasenkoa597aad2006-12-16 23:48:13 +0000152int bb_strtoi(const char *arg, char **endp, int base)
Denis Vlasenkod686a042006-11-27 14:43:21 +0000153{ return bb_strtol(arg, endp, base); }
154#else
Denis Vlasenkoa597aad2006-12-16 23:48:13 +0000155unsigned bb_strtou(const char *arg, char **endp, int base);
156int bb_strtoi(const char *arg, char **endp, int base);
Denis Vlasenkod686a042006-11-27 14:43:21 +0000157#endif
158
159int BUG_bb_strtou32_unimplemented(void);
Denis Vlasenko3ad5d0c2007-06-12 20:54:54 +0000160static ALWAYS_INLINE
Denis Vlasenkod686a042006-11-27 14:43:21 +0000161uint32_t bb_strtou32(const char *arg, char **endp, int base)
162{
163 if (sizeof(uint32_t) == sizeof(unsigned))
164 return bb_strtou(arg, endp, base);
165 if (sizeof(uint32_t) == sizeof(unsigned long))
166 return bb_strtoul(arg, endp, base);
167 return BUG_bb_strtou32_unimplemented();
168}
169
170/* Floating point */
171
172/* double bb_strtod(const char *arg, char **endp); */
Denis Vlasenko98636eb2008-05-09 17:59:34 +0000173
174#if __GNUC_PREREQ(4,1)
175# pragma GCC visibility pop
176#endif