Compare commits
2 Commits
88af7a915b
...
56c2ca3381
Author | SHA1 | Date | |
---|---|---|---|
56c2ca3381 | |||
bad856afe0 |
@ -10,7 +10,7 @@ typedef int (*callback_t)(char, void*);
|
|||||||
|
|
||||||
extern "C" usize strlen(const char*);
|
extern "C" usize strlen(const char*);
|
||||||
|
|
||||||
typedef usize flags_t;
|
typedef int flags_t;
|
||||||
#define FLAG_ZERO_PAD 1 << 0
|
#define FLAG_ZERO_PAD 1 << 0
|
||||||
#define FLAG_LEFT_ALIGN 1 << 1
|
#define FLAG_LEFT_ALIGN 1 << 1
|
||||||
#define FLAG_BLANK_SIGNED 1 << 2
|
#define FLAG_BLANK_SIGNED 1 << 2
|
||||||
@ -224,6 +224,7 @@ static int output_integer(char specifier, conv_state& vstate, format_state& stat
|
|||||||
|
|
||||||
switch (specifier)
|
switch (specifier)
|
||||||
{
|
{
|
||||||
|
case 'p':
|
||||||
case 'x':
|
case 'x':
|
||||||
case 'X': base = 16; break;
|
case 'X': base = 16; break;
|
||||||
case 'o': base = 8; break;
|
case 'o': base = 8; break;
|
||||||
@ -291,6 +292,8 @@ static int va_output_integer(char specifier, conv_state& vstate, format_state& s
|
|||||||
|
|
||||||
if (specifier == 'd' || specifier == 'i') is_signed = true;
|
if (specifier == 'd' || specifier == 'i') is_signed = true;
|
||||||
|
|
||||||
|
if (!is_signed) vstate.flags &= ~(FLAG_SIGN | FLAG_BLANK_SIGNED);
|
||||||
|
|
||||||
if (vstate.flags & FLAG_CHAR)
|
if (vstate.flags & FLAG_CHAR)
|
||||||
{
|
{
|
||||||
if (is_signed)
|
if (is_signed)
|
||||||
@ -404,6 +407,12 @@ isize cstyle_format(const char* format, callback_t callback, void* arg, va_list
|
|||||||
|
|
||||||
format++;
|
format++;
|
||||||
|
|
||||||
|
if (*format == '%')
|
||||||
|
{
|
||||||
|
TRY_PUTCHAR('%', state);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// %[flags][width][.precision][length]conversion
|
// %[flags][width][.precision][length]conversion
|
||||||
|
|
||||||
flags_t flags = parse_flags(&format);
|
flags_t flags = parse_flags(&format);
|
||||||
@ -419,6 +428,22 @@ isize cstyle_format(const char* format, callback_t callback, void* arg, va_list
|
|||||||
if (is_integer_format_specifier(specifier))
|
if (is_integer_format_specifier(specifier))
|
||||||
{
|
{
|
||||||
if (va_output_integer(specifier, vstate, state, ap)) return -1;
|
if (va_output_integer(specifier, vstate, state, ap)) return -1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else if (specifier == 'p')
|
||||||
|
{
|
||||||
|
void* ptr = va_arg(ap, void*);
|
||||||
|
if (ptr == nullptr)
|
||||||
|
{
|
||||||
|
TRY_START_PAD(vstate, state, 5);
|
||||||
|
TRY_PUTS("(nil)", state);
|
||||||
|
TRY_END_PAD(vstate, state, 5);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
vstate.width = (sizeof(void*) * 2) + 2;
|
||||||
|
vstate.flags |= (FLAG_ZERO_PAD | FLAG_ALTERNATE);
|
||||||
|
if (output_integer('p', vstate, state, (usize)ptr, false)) return -1;
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
else if (specifier == 'c')
|
else if (specifier == 'c')
|
||||||
{
|
{
|
||||||
|
@ -38,3 +38,116 @@ inline isize _atos(const char** str)
|
|||||||
|
|
||||||
return neg ? -val : val;
|
return neg ? -val : val;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline usize _strtou(const char* str, const char** endptr, int base)
|
||||||
|
{
|
||||||
|
usize val = 0;
|
||||||
|
|
||||||
|
auto valid_digit = [](int _base, char c) -> bool {
|
||||||
|
if (_base <= 10)
|
||||||
|
{
|
||||||
|
if (!_isdigit(c)) return false;
|
||||||
|
if ((c - '0') < _base) return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!_isalnum(c)) return false;
|
||||||
|
if (_isdigit(c)) return true;
|
||||||
|
bool lower = _islower(c);
|
||||||
|
if (((c - lower ? 'a' : 'A') + 10) < _base) return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
auto to_digit = [](char c) -> usize {
|
||||||
|
if (_isdigit(c)) return c - '0';
|
||||||
|
if (_islower(c)) return (c - 'a') + 10;
|
||||||
|
return (c - 'A') + 10;
|
||||||
|
};
|
||||||
|
|
||||||
|
while (_isspace(*str)) str++;
|
||||||
|
|
||||||
|
if ((base == 0 || base == 16) && *str == '0')
|
||||||
|
{
|
||||||
|
str++;
|
||||||
|
if (_tolower(*str) == 'x')
|
||||||
|
{
|
||||||
|
base = 16;
|
||||||
|
str++;
|
||||||
|
}
|
||||||
|
else if (base == 0)
|
||||||
|
base = 8;
|
||||||
|
}
|
||||||
|
else if (base == 0)
|
||||||
|
base = 10;
|
||||||
|
|
||||||
|
while (valid_digit(base, *str))
|
||||||
|
{
|
||||||
|
val = (base * val) + to_digit(*str);
|
||||||
|
str++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (endptr) *endptr = str;
|
||||||
|
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline isize _strtoi(const char* str, const char** endptr, int base)
|
||||||
|
{
|
||||||
|
isize val = 0;
|
||||||
|
bool negative = false;
|
||||||
|
|
||||||
|
auto valid_digit = [](int _base, char c) -> bool {
|
||||||
|
if (_base <= 10)
|
||||||
|
{
|
||||||
|
if (!_isdigit(c)) return false;
|
||||||
|
if ((c - '0') < _base) return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!_isalnum(c)) return false;
|
||||||
|
if (_isdigit(c)) return true;
|
||||||
|
bool lower = _islower(c);
|
||||||
|
if (((c - lower ? 'a' : 'A') + 10) < _base) return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
auto to_digit = [](char c) -> isize {
|
||||||
|
if (_isdigit(c)) return c - '0';
|
||||||
|
if (_islower(c)) return (c - 'a') + 10;
|
||||||
|
return (c - 'A') + 10;
|
||||||
|
};
|
||||||
|
|
||||||
|
while (_isspace(*str)) str++;
|
||||||
|
|
||||||
|
if (*str == '-' || *str == '+')
|
||||||
|
{
|
||||||
|
if (*str == '-') negative = true;
|
||||||
|
str++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((base == 0 || base == 16) && *str == '0')
|
||||||
|
{
|
||||||
|
str++;
|
||||||
|
if (_tolower(*str) == 'x')
|
||||||
|
{
|
||||||
|
base = 16;
|
||||||
|
str++;
|
||||||
|
}
|
||||||
|
else if (base == 0)
|
||||||
|
base = 8;
|
||||||
|
}
|
||||||
|
else if (base == 0)
|
||||||
|
base = 10;
|
||||||
|
|
||||||
|
while (valid_digit(base, *str))
|
||||||
|
{
|
||||||
|
val = (base * val) + to_digit(*str);
|
||||||
|
str++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (endptr) *endptr = str;
|
||||||
|
|
||||||
|
return negative ? -val : val;
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user