123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151 |
- /* Copyright (C) 2004 Manuel Novoa III <mjn3@codepoet.org>
- *
- * GNU Library General Public License (LGPL) version 2 or later.
- *
- * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details.
- */
- #include "_stdio.h"
- #include <limits.h>
- #include <locale.h>
- #include <bits/uClibc_uintmaxtostr.h>
- /* Avoid using long long / and % operations to cut down dependencies on
- * libgcc.a. Definitely helps on i386 at least. */
- #if (INTMAX_MAX > INT_MAX) && (((INTMAX_MAX/INT_MAX)/2) - 2 <= INT_MAX)
- #define INTERNAL_DIV_MOD
- #endif
- char attribute_hidden *_uintmaxtostr(register char * __restrict bufend, uintmax_t uval,
- int base, __UIM_CASE alphacase)
- {
- int negative;
- unsigned int digit;
- #ifdef INTERNAL_DIV_MOD
- unsigned int H, L, high, low, rh;
- #endif
- #ifndef __LOCALE_C_ONLY
- int grouping, outdigit;
- const char *g; /* This does not need to be initialized. */
- #endif /* __LOCALE_C_ONLY */
- negative = 0;
- if (base < 0) { /* signed value */
- base = -base;
- if (uval > INTMAX_MAX) {
- uval = -uval;
- negative = 1;
- }
- }
- /* this is an internal routine -- we shouldn't need to check this */
- assert(!((base < 2) || (base > 36)));
- #ifndef __LOCALE_C_ONLY
- grouping = -1;
- outdigit = 0x80 & alphacase;
- alphacase ^= outdigit;
- if (alphacase == __UIM_GROUP) {
- assert(base == 10);
- if (*(g = __UCLIBC_CURLOCALE->grouping)) {
- grouping = *g;
- }
- }
- #endif /* __LOCALE_C_ONLY */
- *bufend = '\0';
- #ifndef INTERNAL_DIV_MOD
- do {
- #ifndef __LOCALE_C_ONLY
- if (!grouping) { /* Finished a group. */
- bufend -= __UCLIBC_CURLOCALE->thousands_sep_len;
- memcpy(bufend, __UCLIBC_CURLOCALE->thousands_sep,
- __UCLIBC_CURLOCALE->thousands_sep_len);
- if (g[1] != 0) { /* g[1] == 0 means repeat last grouping. */
- /* Note: g[1] == -1 means no further grouping. But since
- * we'll never wrap around, we can set grouping to -1 without
- * fear of */
- ++g;
- }
- grouping = *g;
- }
- --grouping;
- #endif /* __LOCALE_C_ONLY */
- digit = uval % base;
- uval /= base;
- #ifndef __LOCALE_C_ONLY
- if (unlikely(outdigit)) {
- bufend -= __UCLIBC_CURLOCALE->outdigit_length[digit];
- memcpy(bufend,
- (&__UCLIBC_CURLOCALE->outdigit0_mb)[digit],
- __UCLIBC_CURLOCALE->outdigit_length[digit]);
- } else
- #endif
- {
- *--bufend = ( (digit < 10) ? digit + '0' : digit + alphacase );
- }
- } while (uval);
- #else /* ************************************************** */
- H = (UINT_MAX / base);
- L = UINT_MAX % base + 1;
- if (L == base) {
- ++H;
- L = 0;
- }
- low = (unsigned int) uval;
- high = (unsigned int) (uval >> (sizeof(unsigned int) * CHAR_BIT));
- do {
- #ifndef __LOCALE_C_ONLY
- if (!grouping) { /* Finished a group. */
- bufend -= __UCLIBC_CURLOCALE->thousands_sep_len;
- memcpy(bufend, __UCLIBC_CURLOCALE->thousands_sep,
- __UCLIBC_CURLOCALE->thousands_sep_len);
- if (g[1] != 0) { /* g[1] == 0 means repeat last grouping. */
- /* Note: g[1] == -1 means no further grouping. But since
- * we'll never wrap around, we can set grouping to -1 without
- * fear of */
- ++g;
- }
- grouping = *g;
- }
- --grouping;
- #endif /* __LOCALE_C_ONLY */
- if (unlikely(high)) {
- rh = high % base;
- high /= base;
- digit = (low % base) + (L * rh);
- low = (low / base) + (H * rh) + (digit / base);
- digit %= base;
- } else {
- digit = low % base;
- low /= base;
- }
- #ifndef __LOCALE_C_ONLY
- if (unlikely(outdigit)) {
- bufend -= __UCLIBC_CURLOCALE->outdigit_length[digit];
- memcpy(bufend,
- (&__UCLIBC_CURLOCALE->outdigit0_mb)[digit],
- __UCLIBC_CURLOCALE->outdigit_length[digit]);
- } else
- #endif
- {
- *--bufend = ( (digit < 10) ? digit + '0' : digit + alphacase );
- }
- } while (low | high);
- #endif /******************************************************/
- if (negative) {
- *--bufend = '-';
- }
- return bufend;
- }
|