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.
11 #include <bits/uClibc_uintmaxtostr.h>
14 /* Avoid using long long / and % operations to cut down dependencies on
15 * libgcc.a. Definitely helps on i386 at least. */
16 #if (INTMAX_MAX > INT_MAX) && (((INTMAX_MAX/INT_MAX)/2) - 2 <= INT_MAX)
17 #define INTERNAL_DIV_MOD
20 char attribute_hidden
*_uintmaxtostr(register char * __restrict bufend
, uintmax_t uval
,
21 int base
, __UIM_CASE alphacase
)
25 #ifdef INTERNAL_DIV_MOD
26 unsigned int H
, L
, high
, low
, rh
;
28 #ifndef __LOCALE_C_ONLY
29 int grouping
, outdigit
;
30 const char *g
; /* This does not need to be initialized. */
31 #endif /* __LOCALE_C_ONLY */
34 if (base
< 0) { /* signed value */
36 if (uval
> INTMAX_MAX
) {
42 /* this is an internal routine -- we shouldn't need to check this */
43 assert(!((base
< 2) || (base
> 36)));
45 #ifndef __LOCALE_C_ONLY
47 outdigit
= 0x80 & alphacase
;
48 alphacase
^= outdigit
;
49 if (alphacase
== __UIM_GROUP
) {
51 if (*(g
= __UCLIBC_CURLOCALE
->grouping
)) {
55 #endif /* __LOCALE_C_ONLY */
59 #ifndef INTERNAL_DIV_MOD
61 #ifndef __LOCALE_C_ONLY
62 if (!grouping
) { /* Finished a group. */
63 bufend
-= __UCLIBC_CURLOCALE
->thousands_sep_len
;
64 memcpy(bufend
, __UCLIBC_CURLOCALE
->thousands_sep
,
65 __UCLIBC_CURLOCALE
->thousands_sep_len
);
66 if (g
[1] != 0) { /* g[1] == 0 means repeat last grouping. */
67 /* Note: g[1] == -1 means no further grouping. But since
68 * we'll never wrap around, we can set grouping to -1 without
75 #endif /* __LOCALE_C_ONLY */
79 #ifndef __LOCALE_C_ONLY
80 if (unlikely(outdigit
)) {
81 bufend
-= __UCLIBC_CURLOCALE
->outdigit_length
[digit
];
83 (&__UCLIBC_CURLOCALE
->outdigit0_mb
)[digit
],
84 __UCLIBC_CURLOCALE
->outdigit_length
[digit
]);
88 *--bufend
= ( (digit
< 10) ? digit
+ '0' : digit
+ alphacase
);
92 #else /* ************************************************** */
94 H
= (UINT_MAX
/ base
);
95 L
= UINT_MAX
% base
+ 1;
100 low
= (unsigned int) uval
;
101 high
= (unsigned int) (uval
>> (sizeof(unsigned int) * CHAR_BIT
));
104 #ifndef __LOCALE_C_ONLY
105 if (!grouping
) { /* Finished a group. */
106 bufend
-= __UCLIBC_CURLOCALE
->thousands_sep_len
;
107 memcpy(bufend
, __UCLIBC_CURLOCALE
->thousands_sep
,
108 __UCLIBC_CURLOCALE
->thousands_sep_len
);
109 if (g
[1] != 0) { /* g[1] == 0 means repeat last grouping. */
110 /* Note: g[1] == -1 means no further grouping. But since
111 * we'll never wrap around, we can set grouping to -1 without
118 #endif /* __LOCALE_C_ONLY */
120 if (unlikely(high
)) {
123 digit
= (low
% base
) + (L
* rh
);
124 low
= (low
/ base
) + (H
* rh
) + (digit
/ base
);
131 #ifndef __LOCALE_C_ONLY
132 if (unlikely(outdigit
)) {
133 bufend
-= __UCLIBC_CURLOCALE
->outdigit_length
[digit
];
135 (&__UCLIBC_CURLOCALE
->outdigit0_mb
)[digit
],
136 __UCLIBC_CURLOCALE
->outdigit_length
[digit
]);
140 *--bufend
= ( (digit
< 10) ? digit
+ '0' : digit
+ alphacase
);
142 } while (low
| high
);
144 #endif /******************************************************/