1 /* Copyright (C) 2004 Manuel Novoa III <mjn3@codepoet.org>
3 * GNU Library General Public License (LGPL) version 2 or later.
5 * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details.
8 #define _ISOC99_SOURCE /* for ULLONG primarily... */
12 #include <bits/uClibc_uintmaxtostr.h>
14 /* Experimentally off - libc_hidden_proto(memcpy) */
16 /* Avoid using long long / and % operations to cut down dependencies on
17 * libgcc.a. Definitely helps on i386 at least. */
18 #if (INTMAX_MAX > INT_MAX) && (((INTMAX_MAX/INT_MAX)/2) - 2 <= INT_MAX)
19 #define INTERNAL_DIV_MOD
22 char attribute_hidden
*_uintmaxtostr(register char * __restrict bufend
, uintmax_t uval
,
23 int base
, __UIM_CASE alphacase
)
27 #ifdef INTERNAL_DIV_MOD
28 unsigned int H
, L
, high
, low
, rh
;
30 #ifndef __LOCALE_C_ONLY
31 int grouping
, outdigit
;
32 const char *g
; /* This does not need to be initialized. */
33 #endif /* __LOCALE_C_ONLY */
36 if (base
< 0) { /* signed value */
38 if (uval
> INTMAX_MAX
) {
44 /* this is an internal routine -- we shouldn't need to check this */
45 assert(!((base
< 2) || (base
> 36)));
47 #ifndef __LOCALE_C_ONLY
49 outdigit
= 0x80 & alphacase
;
50 alphacase
^= outdigit
;
51 if (alphacase
== __UIM_GROUP
) {
53 if (*(g
= __UCLIBC_CURLOCALE
->grouping
)) {
57 #endif /* __LOCALE_C_ONLY */
61 #ifndef INTERNAL_DIV_MOD
63 #ifndef __LOCALE_C_ONLY
64 if (!grouping
) { /* Finished a group. */
65 bufend
-= __UCLIBC_CURLOCALE
->thousands_sep_len
;
66 memcpy(bufend
, __UCLIBC_CURLOCALE
->thousands_sep
,
67 __UCLIBC_CURLOCALE
->thousands_sep_len
);
68 if (g
[1] != 0) { /* g[1] == 0 means repeat last grouping. */
69 /* Note: g[1] == -1 means no further grouping. But since
70 * we'll never wrap around, we can set grouping to -1 without
77 #endif /* __LOCALE_C_ONLY */
81 #ifndef __LOCALE_C_ONLY
82 if (unlikely(outdigit
)) {
83 bufend
-= __UCLIBC_CURLOCALE
->outdigit_length
[digit
];
85 (&__UCLIBC_CURLOCALE
->outdigit0_mb
)[digit
],
86 __UCLIBC_CURLOCALE
->outdigit_length
[digit
]);
90 *--bufend
= ( (digit
< 10) ? digit
+ '0' : digit
+ alphacase
);
94 #else /* ************************************************** */
96 H
= (UINT_MAX
/ base
);
97 L
= UINT_MAX
% base
+ 1;
102 low
= (unsigned int) uval
;
103 high
= (unsigned int) (uval
>> (sizeof(unsigned int) * CHAR_BIT
));
106 #ifndef __LOCALE_C_ONLY
107 if (!grouping
) { /* Finished a group. */
108 bufend
-= __UCLIBC_CURLOCALE
->thousands_sep_len
;
109 memcpy(bufend
, __UCLIBC_CURLOCALE
->thousands_sep
,
110 __UCLIBC_CURLOCALE
->thousands_sep_len
);
111 if (g
[1] != 0) { /* g[1] == 0 means repeat last grouping. */
112 /* Note: g[1] == -1 means no further grouping. But since
113 * we'll never wrap around, we can set grouping to -1 without
120 #endif /* __LOCALE_C_ONLY */
122 if (unlikely(high
)) {
125 digit
= (low
% base
) + (L
* rh
);
126 low
= (low
/ base
) + (H
* rh
) + (digit
/ base
);
133 #ifndef __LOCALE_C_ONLY
134 if (unlikely(outdigit
)) {
135 bufend
-= __UCLIBC_CURLOCALE
->outdigit_length
[digit
];
137 (&__UCLIBC_CURLOCALE
->outdigit0_mb
)[digit
],
138 __UCLIBC_CURLOCALE
->outdigit_length
[digit
]);
142 *--bufend
= ( (digit
< 10) ? digit
+ '0' : digit
+ alphacase
);
144 } while (low
| high
);
146 #endif /******************************************************/