os-k/kaleid/libc/itoa.c

111 lines
2.4 KiB
C

//----------------------------------------------------------------------------//
// GNU GPL OS/K //
// //
// Authors: spectral` //
// NeoX //
// //
// Desc: Conversion utilities - itoa family //
//----------------------------------------------------------------------------//
#include <kalbase.h>
// Digits table for bases <=36 (unused)
#if 0
static const char digits[] =
"0123456789abcdefghijklmnopqrstuvwxyz";
#endif
//
// Integer to string in any base between 2 and 36 (included)
// Returns str
//
#if defined(_NEED_ITOA)
#define _IL_MIN INT_MIN
#define _IL_MIN_STRING "-2147483648"
char *itoa(int i, char *str, int base)
{
int rem;
#elif defined(_NEED_LTOA)
#define _IL_MIN LONG_MIN
#define _IL_MIN_STRING "-9223372036854775808"
char *ltoa(long i, char *str, int base)
{
long rem;
#elif defined(_NEED_UTOA)
char *utoa(uint i, char *str, int base)
{
uint rem;
#elif defined(_NEED_ULTOA)
char *ultoa(ulong i, char *str, int base)
{
ulong rem;
#else
#error "What am I supposed to declare?"
#endif
char *orig = str;
#if defined(_NEED_ITOA) || defined(_NEED_LTOA)
// Deal with negatives
int neg = 0;
if (i < 0 && base == 10) {
// Handle INT_MIN and LONG_MIN...
if (__builtin_expect(i == _IL_MIN, 0)) {
strcpy(orig, _IL_MIN_STRING);
goto leave;
}
else {
neg = 1;
i = -i;
}
}
#endif
// Only handle base 2 -> 36
if (base < 2 || base > 36) {
seterrno(EINVAL);
*orig = '\0';
goto leave;
}
// Deal with zero separately
if (i == 0) {
*str++ = '0';
*str = '\0';
goto leave;
}
// Compute digits... in reverse order
while (i > 0) {
rem = i % base;
*str++ = (rem > 9)
? (rem - 10) + 'a'
: rem + '0';
i /= base;
}
#if defined(_NEED_ITOA) || defined(_NEED_LTOA)
if (neg) *str++ = '-';
#endif
*str = '\0';
// Reverse the string
orig = strrev2(orig);
// End of conversion
leave:
return orig;
}