Created
August 15, 2020 09:55
-
-
Save fffe/e5d7b4780bebf44304534adcd78d02f4 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <inttypes.h> | |
#include <stdarg.h> | |
#include <stdint.h> | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <string.h> | |
#include <unistd.h> | |
static void outb(char c, char *target, const size_t length, const size_t index) { | |
if (target && index < length) | |
target[index] = c; | |
} | |
static void outc(char c, char *target, const size_t length, const size_t index) { | |
(void)target, (void)length, (void)index; | |
putchar(c); | |
} | |
typedef void (*out_t)(char, char *, const size_t, const size_t); | |
static inline size_t number(const char **pointer) { | |
size_t ret = 0; | |
for (; **pointer >= '0' && **pointer <= '9'; (*pointer)++) | |
ret = ret * 10 + **pointer - '0'; | |
return ret; | |
} | |
int xvsnprintf(const out_t out, char *buf, const size_t buflen, const char *format, va_list args) { | |
size_t index = 0; | |
for (; *format; format++) { | |
enum state_flags { | |
PLUS = 2 << 0, | |
SPACE = 2 << 1, | |
ZERO_PAD = 2 << 2, | |
ALTERNATE = 2 << 3, | |
LEFT = 2 << 4, | |
UPPERCASE = 2 << 5, | |
REVERSE = 2 << 6, | |
PRECISION = 2 << 7, | |
NEGATIVE = 2 << 8, | |
SIGNED = 2 << 9 | |
} state = 0; | |
size_t precision = 0; | |
char character; | |
const char null_value[] = "(null)"; | |
if (*format != '%') { | |
out(*format, buf, buflen, index++); | |
continue; | |
} else | |
format++; | |
// %% -> % | |
if (*format == '%') { | |
out(*format, buf, buflen, index++); | |
continue; | |
} | |
// flags | |
for (; *format; format++) { | |
switch (*format) { | |
case '+': | |
state |= PLUS; | |
continue; | |
case ' ': | |
state |= SPACE; | |
continue; | |
case '0': | |
state |= ZERO_PAD; | |
continue; | |
case '#': | |
state |= ALTERNATE; | |
continue; | |
case '-': | |
state |= LEFT; | |
continue; | |
default: | |
break; | |
} | |
break; | |
} | |
// mututally exclusive flags | |
if (state & PLUS) | |
state &= ~SPACE; | |
if (state & LEFT) | |
state &= ~ZERO_PAD; | |
// width | |
size_t width = number(&format); | |
// precision | |
if (*format == '.') { | |
state = (state | PRECISION) & ~ZERO_PAD; | |
format++; | |
precision = number(&format); | |
} | |
// length | |
enum variable_length { L_CHAR, L_SHORT, L_INT, L_LONG, L_LONG_LONG, L_SIZE } length = L_INT; | |
switch (*format) { | |
case 'h': | |
format++; | |
length = L_SHORT; | |
if (*format && *format == 'h') { | |
format++; | |
length = L_CHAR; | |
} | |
break; | |
case 'l': | |
format++; | |
length = L_LONG; | |
if (*format && *format == 'l') { | |
format++; | |
length = L_LONG_LONG; | |
} | |
break; | |
case 'z': | |
format++; | |
length = L_SIZE; | |
break; | |
default: | |
break; | |
} | |
// types | |
enum base_t { OCTAL = 8, DECIMAL = 10, HEXADECIMAL = 16 } base = DECIMAL; | |
uint8_t prefix_length = 0; | |
size_t source_length = 0; | |
char buffer[64] = {0}, prefix_buffer[4] = {0}; | |
const char *source = buffer; | |
if (*format == 'c') { | |
character = (char)va_arg(args, int); | |
source = &character; | |
source_length = 1; | |
state &= ~(ALTERNATE | PRECISION); | |
} else if (*format == 's') { | |
const char *argument = va_arg(args, char *); | |
source = (argument) ? argument : null_value; | |
source_length = strlen(source); | |
state &= ~ALTERNATE; | |
if (state & PRECISION && source_length > precision) | |
source_length = precision; | |
} else { | |
switch (*format) { | |
case 'd': | |
case 'i': | |
state = (state | SIGNED) & ~ALTERNATE; | |
break; | |
case 'X': | |
state |= UPPERCASE; | |
// fall through | |
case 'x': | |
base = HEXADECIMAL; | |
break; | |
case 'u': | |
state &= ~ALTERNATE; | |
break; | |
case 'o': | |
base = OCTAL; | |
break; | |
default: | |
out(*format, buf, buflen, index++); | |
continue; | |
} | |
uint64_t value = 0; | |
state |= REVERSE; | |
if (state & SIGNED) { | |
int64_t signed_value = 0; | |
switch (length) { | |
case L_CHAR: | |
signed_value = (char)va_arg(args, int); | |
break; | |
case L_SHORT: | |
signed_value = (short)va_arg(args, int); | |
break; | |
case L_INT: | |
signed_value = (int)va_arg(args, int); | |
break; | |
case L_LONG: | |
signed_value = (long)va_arg(args, long); | |
break; | |
case L_LONG_LONG: | |
signed_value = (long long)va_arg(args, long long); | |
break; | |
case L_SIZE: | |
signed_value = (ssize_t)va_arg(args, ssize_t); | |
break; | |
} | |
if (signed_value < 0) { | |
value = (uint64_t)-signed_value; | |
state |= NEGATIVE; | |
} else | |
value = (uint64_t)signed_value; | |
} else | |
switch (length) { | |
case L_CHAR: | |
value = (unsigned char)va_arg(args, unsigned int); | |
break; | |
case L_SHORT: | |
value = (unsigned short)va_arg(args, unsigned int); | |
break; | |
case L_INT: | |
value = (unsigned int)va_arg(args, unsigned int); | |
break; | |
case L_LONG: | |
value = (unsigned long)va_arg(args, unsigned long); | |
break; | |
case L_LONG_LONG: | |
value = (unsigned long long)va_arg(args, unsigned long long); | |
break; | |
case L_SIZE: | |
value = (size_t)va_arg(args, size_t); | |
break; | |
} | |
if (state & SIGNED) { | |
if (state & NEGATIVE) | |
prefix_buffer[prefix_length++] = '-'; | |
else if (state & PLUS) | |
prefix_buffer[prefix_length++] = '+'; | |
else if (state & SPACE) | |
prefix_buffer[prefix_length++] = ' '; | |
} | |
if (state & ALTERNATE && value) | |
switch (base) { | |
case HEXADECIMAL: | |
prefix_buffer[prefix_length++] = '0'; | |
prefix_buffer[prefix_length++] = (state & UPPERCASE) ? 'X' : 'x'; | |
break; | |
case OCTAL: | |
if (buffer[source_length] != '0') | |
prefix_buffer[prefix_length++] = '0'; | |
break; | |
case DECIMAL: | |
break; | |
} | |
if (!value && (!(state & PRECISION) || precision)) | |
buffer[source_length++] = '0'; | |
else { | |
const char lower[] = "0123456789abcdef", upper[] = "0123456789ABCDEF"; | |
const char *characters = (state & UPPERCASE) ? upper : lower; | |
for (; value; value /= base) | |
buffer[source_length++] = characters[value % base]; | |
} | |
if (precision > 64) | |
precision = 64; | |
if (source_length > precision) | |
precision = source_length; | |
else | |
while (source_length < precision) | |
buffer[source_length++] = '0'; | |
} | |
size_t padding_bytes = (width > source_length) ? width - source_length : 0; | |
const char padding_byte = (state & ZERO_PAD) ? '0' : ' '; | |
if (prefix_length && padding_bytes) | |
padding_bytes = (padding_bytes > prefix_length) ? padding_bytes - prefix_length : 0; | |
if (!(state & ZERO_PAD) && !(state & LEFT)) | |
for (; padding_bytes; padding_bytes--) | |
out(padding_byte, buf, buflen, index++); | |
for (size_t i = 0; i < prefix_length; i++) | |
out(prefix_buffer[i], buf, buflen, index++); | |
if ((state & ZERO_PAD) && !(state & LEFT)) | |
for (; padding_bytes; padding_bytes--) | |
out(padding_byte, buf, buflen, index++); | |
if (state & REVERSE) | |
for (; source_length--;) | |
out(source[source_length], buf, buflen, index++); | |
else | |
for (size_t i = 0; i < source_length; i++) | |
out(source[i], buf, buflen, index++); | |
if (state & LEFT) | |
for (; padding_bytes; padding_bytes--) | |
out(padding_byte, buf, buflen, index++); | |
} | |
if (buf && buflen) | |
out('\0', buf, buflen, (index >= buflen) ? buflen - 1 : index); | |
return index; | |
} | |
int xprintf(const char *fmt, ...) { | |
va_list args; | |
int printed; | |
va_start(args, fmt); | |
printed = xvsnprintf(outc, NULL, 0, fmt, args); | |
va_end(args); | |
return printed; | |
} | |
int xsprintf(char *buf, const char *fmt, ...) { | |
va_list args; | |
int printed; | |
va_start(args, fmt); | |
printed = xvsnprintf(outb, buf, SIZE_MAX, fmt, args); | |
va_end(args); | |
return printed; | |
} | |
int xsnprintf(char *buf, size_t size, const char *fmt, ...) { | |
va_list args; | |
int printed; | |
va_start(args, fmt); | |
printed = xvsnprintf(outb, buf, size, fmt, args); | |
va_end(args); | |
return printed; | |
} | |
void REQUIRE(char *got, char *wanted) { | |
if (strcmp(wanted, got)) | |
printf("REQUIRE FAILED: wanted \"%s\" but got \"%s\"\n", wanted, got); | |
else | |
printf("REQUIRE OK\n"); | |
} | |
void REQUIRES(size_t got, size_t wanted) { | |
if (wanted != got) | |
printf("REQUIRES FAILED: wanted \"%zu\" but got \"%zu\"\n", wanted, got); | |
else | |
printf("REQUIRES OK\n"); | |
} | |
void REQUIREC(char got, char wanted) { | |
if (wanted != got) | |
printf("REQUIREC FAILED: wanted \"%c\" (%d) but got \"%c\" (%d)\n", wanted, wanted, got, got); | |
else | |
printf("REQUIREC OK\n"); | |
} | |
void TEST_CASE(char *x) { printf("==== %s\n", x); } | |
int main(int argc, char **argv) { | |
// return xprintf("this [% d] will %0#10.20lX [%-10.20s] %s [%'d] get truncated?\n", 1, 0x45BA, "AAAA", NULL, | |
// -1000000000); | |
if (argc > 1) { | |
xprintf("%d\n", 10000); | |
} else { | |
TEST_CASE("space flag"); | |
char buffer[100]; | |
xsprintf(buffer, "% d", 42); | |
REQUIRE(buffer, " 42"); | |
xsprintf(buffer, "% d", -42); | |
REQUIRE(buffer, "-42"); | |
xsprintf(buffer, "% 5d", 42); | |
REQUIRE(buffer, " 42"); | |
xsprintf(buffer, "% 5d", -42); | |
REQUIRE(buffer, " -42"); | |
xsprintf(buffer, "% 15d", 42); | |
REQUIRE(buffer, " 42"); | |
xsprintf(buffer, "% 15d", -42); | |
REQUIRE(buffer, " -42"); | |
xsprintf(buffer, "% 15d", -42); | |
REQUIRE(buffer, " -42"); | |
/* | |
xsprintf(buffer, "% 15.3f", -42.987); | |
REQUIRE(buffer, " -42.987"); | |
xsprintf(buffer, "% 15.3f", 42.987); | |
REQUIRE(buffer, " 42.987"); | |
*/ | |
xsprintf(buffer, "% s", "Hello testing"); | |
REQUIRE(buffer, "Hello testing"); | |
xsprintf(buffer, "% d", 1024); | |
REQUIRE(buffer, " 1024"); | |
xsprintf(buffer, "% d", -1024); | |
REQUIRE(buffer, "-1024"); | |
xsprintf(buffer, "% i", 1024); | |
REQUIRE(buffer, " 1024"); | |
xsprintf(buffer, "% i", -1024); | |
REQUIRE(buffer, "-1024"); | |
xsprintf(buffer, "% u", 1024); | |
REQUIRE(buffer, "1024"); | |
xsprintf(buffer, "% u", 4294966272U); | |
REQUIRE(buffer, "4294966272"); | |
xsprintf(buffer, "% o", 511); | |
REQUIRE(buffer, "777"); | |
xsprintf(buffer, "% o", 4294966785U); | |
REQUIRE(buffer, "37777777001"); | |
xsprintf(buffer, "% x", 305441741); | |
REQUIRE(buffer, "1234abcd"); | |
xsprintf(buffer, "% x", 3989525555U); | |
REQUIRE(buffer, "edcb5433"); | |
xsprintf(buffer, "% X", 305441741); | |
REQUIRE(buffer, "1234ABCD"); | |
xsprintf(buffer, "% X", 3989525555U); | |
REQUIRE(buffer, "EDCB5433"); | |
xsprintf(buffer, "% c", 'x'); | |
REQUIRE(buffer, "x"); | |
TEST_CASE("+ flag"); | |
xsprintf(buffer, "%+d", 42); | |
REQUIRE(buffer, "+42"); | |
xsprintf(buffer, "%+d", -42); | |
REQUIRE(buffer, "-42"); | |
xsprintf(buffer, "%+5d", 42); | |
REQUIRE(buffer, " +42"); | |
xsprintf(buffer, "%+5d", -42); | |
REQUIRE(buffer, " -42"); | |
xsprintf(buffer, "%+15d", 42); | |
REQUIRE(buffer, " +42"); | |
xsprintf(buffer, "%+15d", -42); | |
REQUIRE(buffer, " -42"); | |
xsprintf(buffer, "%+s", "Hello testing"); | |
REQUIRE(buffer, "Hello testing"); | |
xsprintf(buffer, "%+d", 1024); | |
REQUIRE(buffer, "+1024"); | |
xsprintf(buffer, "%+d", -1024); | |
REQUIRE(buffer, "-1024"); | |
xsprintf(buffer, "%+i", 1024); | |
REQUIRE(buffer, "+1024"); | |
xsprintf(buffer, "%+i", -1024); | |
REQUIRE(buffer, "-1024"); | |
xsprintf(buffer, "%+u", 1024); | |
REQUIRE(buffer, "1024"); | |
xsprintf(buffer, "%+u", 4294966272U); | |
REQUIRE(buffer, "4294966272"); | |
xsprintf(buffer, "%+o", 511); | |
REQUIRE(buffer, "777"); | |
xsprintf(buffer, "%+o", 4294966785U); | |
REQUIRE(buffer, "37777777001"); | |
xsprintf(buffer, "%+x", 305441741); | |
REQUIRE(buffer, "1234abcd"); | |
xsprintf(buffer, "%+x", 3989525555U); | |
REQUIRE(buffer, "edcb5433"); | |
xsprintf(buffer, "%+X", 305441741); | |
REQUIRE(buffer, "1234ABCD"); | |
xsprintf(buffer, "%+X", 3989525555U); | |
REQUIRE(buffer, "EDCB5433"); | |
xsprintf(buffer, "%+c", 'x'); | |
REQUIRE(buffer, "x"); | |
xsprintf(buffer, "%+.0d", 0); | |
REQUIRE(buffer, "+"); | |
TEST_CASE("0 flag"); | |
xsprintf(buffer, "%0d", 42); | |
REQUIRE(buffer, "42"); | |
xsprintf(buffer, "%0ld", 42L); | |
REQUIRE(buffer, "42"); | |
xsprintf(buffer, "%0d", -42); | |
REQUIRE(buffer, "-42"); | |
xsprintf(buffer, "%05d", 42); | |
REQUIRE(buffer, "00042"); | |
xsprintf(buffer, "%05d", -42); | |
REQUIRE(buffer, "-0042"); | |
xsprintf(buffer, "%015d", 42); | |
REQUIRE(buffer, "000000000000042"); | |
xsprintf(buffer, "%015d", -42); | |
REQUIRE(buffer, "-00000000000042"); | |
/* | |
xsprintf(buffer, "%015.2f", 42.1234); | |
REQUIRE(buffer, "000000000042.12"); | |
xsprintf(buffer, "%015.3f", 42.9876); | |
REQUIRE(buffer, "00000000042.988"); | |
xsprintf(buffer, "%015.5f", -42.9876); | |
REQUIRE(buffer, "-00000042.98760"); | |
*/ | |
TEST_CASE("- flag"); | |
xsprintf(buffer, "%-d", 42); | |
REQUIRE(buffer, "42"); | |
xsprintf(buffer, "%-d", -42); | |
REQUIRE(buffer, "-42"); | |
xsprintf(buffer, "%-5d", 42); | |
REQUIRE(buffer, "42 "); | |
xsprintf(buffer, "%-5d", -42); | |
REQUIRE(buffer, "-42 "); | |
xsprintf(buffer, "%-15d", 42); | |
REQUIRE(buffer, "42 "); | |
xsprintf(buffer, "%-15d", -42); | |
REQUIRE(buffer, "-42 "); | |
xsprintf(buffer, "%-0d", 42); | |
REQUIRE(buffer, "42"); | |
xsprintf(buffer, "%-0d", -42); | |
REQUIRE(buffer, "-42"); | |
xsprintf(buffer, "%-05d", 42); | |
REQUIRE(buffer, "42 "); | |
xsprintf(buffer, "%-05d", -42); | |
REQUIRE(buffer, "-42 "); | |
xsprintf(buffer, "%-015d", 42); | |
REQUIRE(buffer, "42 "); | |
xsprintf(buffer, "%-015d", -42); | |
REQUIRE(buffer, "-42 "); | |
xsprintf(buffer, "%0-d", 42); | |
REQUIRE(buffer, "42"); | |
xsprintf(buffer, "%0-d", -42); | |
REQUIRE(buffer, "-42"); | |
xsprintf(buffer, "%0-5d", 42); | |
REQUIRE(buffer, "42 "); | |
xsprintf(buffer, "%0-5d", -42); | |
REQUIRE(buffer, "-42 "); | |
xsprintf(buffer, "%0-15d", 42); | |
REQUIRE(buffer, "42 "); | |
xsprintf(buffer, "%0-15d", -42); | |
REQUIRE(buffer, "-42 "); | |
xsprintf(buffer, "%0-15.3e", -42.); | |
REQUIRE(buffer, "e"); | |
xsprintf(buffer, "%0-15.3g", -42.); | |
REQUIRE(buffer, "g"); | |
TEST_CASE("# flag"); | |
xsprintf(buffer, "%#.0x", 0); | |
REQUIRE(buffer, ""); | |
xsprintf(buffer, "%#.1x", 0); | |
REQUIRE(buffer, "0"); | |
xsprintf(buffer, "%#.0llx", (long long)0); | |
REQUIRE(buffer, ""); | |
xsprintf(buffer, "%#.8x", 0x614e); | |
REQUIRE(buffer, "0x0000614e"); | |
/* | |
xsprintf(buffer,"%#b", 6); | |
REQUIRE(buffer, "0b110"); | |
*/ | |
TEST_CASE("specifier"); | |
xsprintf(buffer, "Hello testing"); | |
REQUIRE(buffer, "Hello testing"); | |
xsprintf(buffer, "%s", "Hello testing"); | |
REQUIRE(buffer, "Hello testing"); | |
xsprintf(buffer, "%d", 1024); | |
REQUIRE(buffer, "1024"); | |
xsprintf(buffer, "%d", -1024); | |
REQUIRE(buffer, "-1024"); | |
xsprintf(buffer, "%i", 1024); | |
REQUIRE(buffer, "1024"); | |
xsprintf(buffer, "%i", -1024); | |
REQUIRE(buffer, "-1024"); | |
xsprintf(buffer, "%u", 1024); | |
REQUIRE(buffer, "1024"); | |
xsprintf(buffer, "%u", 4294966272U); | |
REQUIRE(buffer, "4294966272"); | |
xsprintf(buffer, "%o", 511); | |
REQUIRE(buffer, "777"); | |
xsprintf(buffer, "%o", 4294966785U); | |
REQUIRE(buffer, "37777777001"); | |
xsprintf(buffer, "%x", 305441741); | |
REQUIRE(buffer, "1234abcd"); | |
xsprintf(buffer, "%x", 3989525555U); | |
REQUIRE(buffer, "edcb5433"); | |
xsprintf(buffer, "%X", 305441741); | |
REQUIRE(buffer, "1234ABCD"); | |
xsprintf(buffer, "%X", 3989525555U); | |
REQUIRE(buffer, "EDCB5433"); | |
xsprintf(buffer, "%%"); | |
REQUIRE(buffer, "%"); | |
TEST_CASE("width"); | |
xsprintf(buffer, "%1s", "Hello testing"); | |
REQUIRE(buffer, "Hello testing"); | |
xsprintf(buffer, "%1d", 1024); | |
REQUIRE(buffer, "1024"); | |
xsprintf(buffer, "%1d", -1024); | |
REQUIRE(buffer, "-1024"); | |
xsprintf(buffer, "%1i", 1024); | |
REQUIRE(buffer, "1024"); | |
xsprintf(buffer, "%1i", -1024); | |
REQUIRE(buffer, "-1024"); | |
xsprintf(buffer, "%1u", 1024); | |
REQUIRE(buffer, "1024"); | |
xsprintf(buffer, "%1u", 4294966272U); | |
REQUIRE(buffer, "4294966272"); | |
xsprintf(buffer, "%1o", 511); | |
REQUIRE(buffer, "777"); | |
xsprintf(buffer, "%1o", 4294966785U); | |
REQUIRE(buffer, "37777777001"); | |
xsprintf(buffer, "%1x", 305441741); | |
REQUIRE(buffer, "1234abcd"); | |
xsprintf(buffer, "%1x", 3989525555U); | |
REQUIRE(buffer, "edcb5433"); | |
xsprintf(buffer, "%1X", 305441741); | |
REQUIRE(buffer, "1234ABCD"); | |
xsprintf(buffer, "%1X", 3989525555U); | |
REQUIRE(buffer, "EDCB5433"); | |
xsprintf(buffer, "%1c", 'x'); | |
REQUIRE(buffer, "x"); | |
TEST_CASE("width 20"); | |
xsprintf(buffer, "%20s", "Hello"); | |
REQUIRE(buffer, " Hello"); | |
xsprintf(buffer, "%20d", 1024); | |
REQUIRE(buffer, " 1024"); | |
xsprintf(buffer, "%20d", -1024); | |
REQUIRE(buffer, " -1024"); | |
xsprintf(buffer, "%20i", 1024); | |
REQUIRE(buffer, " 1024"); | |
xsprintf(buffer, "%20i", -1024); | |
REQUIRE(buffer, " -1024"); | |
xsprintf(buffer, "%20u", 1024); | |
REQUIRE(buffer, " 1024"); | |
xsprintf(buffer, "%20u", 4294966272U); | |
REQUIRE(buffer, " 4294966272"); | |
xsprintf(buffer, "%20o", 511); | |
REQUIRE(buffer, " 777"); | |
xsprintf(buffer, "%20o", 4294966785U); | |
REQUIRE(buffer, " 37777777001"); | |
xsprintf(buffer, "%20x", 305441741); | |
REQUIRE(buffer, " 1234abcd"); | |
xsprintf(buffer, "%20x", 3989525555U); | |
REQUIRE(buffer, " edcb5433"); | |
xsprintf(buffer, "%20X", 305441741); | |
REQUIRE(buffer, " 1234ABCD"); | |
xsprintf(buffer, "%20X", 3989525555U); | |
REQUIRE(buffer, " EDCB5433"); | |
xsprintf(buffer, "%20c", 'x'); | |
REQUIRE(buffer, " x"); | |
/* | |
TEST_CASE("width *20"); | |
char buffer[100]; | |
xsprintf(buffer, "%*s", 20, "Hello"); | |
REQUIRE(buffer, " Hello"); | |
xsprintf(buffer, "%*d", 20, 1024); | |
REQUIRE(buffer, " 1024"); | |
xsprintf(buffer, "%*d", 20, -1024); | |
REQUIRE(buffer, " -1024"); | |
xsprintf(buffer, "%*i", 20, 1024); | |
REQUIRE(buffer, " 1024"); | |
xsprintf(buffer, "%*i", 20, -1024); | |
REQUIRE(buffer, " -1024"); | |
xsprintf(buffer, "%*u", 20, 1024); | |
REQUIRE(buffer, " 1024"); | |
xsprintf(buffer, "%*u", 20, 4294966272U); | |
REQUIRE(buffer, " 4294966272"); | |
xsprintf(buffer, "%*o", 20, 511); | |
REQUIRE(buffer, " 777"); | |
xsprintf(buffer, "%*o", 20, 4294966785U); | |
REQUIRE(buffer, " 37777777001"); | |
xsprintf(buffer, "%*x", 20, 305441741); | |
REQUIRE(buffer, " 1234abcd"); | |
xsprintf(buffer, "%*x", 20, 3989525555U); | |
REQUIRE(buffer, " edcb5433"); | |
xsprintf(buffer, "%*X", 20, 305441741); | |
REQUIRE(buffer, " 1234ABCD"); | |
xsprintf(buffer, "%*X", 20, 3989525555U); | |
REQUIRE(buffer, " EDCB5433"); | |
xsprintf(buffer, "%*c", 20,'x'); | |
REQUIRE(buffer, " x"); | |
} | |
*/ | |
TEST_CASE("width -20"); | |
xsprintf(buffer, "%-20s", "Hello"); | |
REQUIRE(buffer, "Hello "); | |
xsprintf(buffer, "%-20d", 1024); | |
REQUIRE(buffer, "1024 "); | |
xsprintf(buffer, "%-20d", -1024); | |
REQUIRE(buffer, "-1024 "); | |
xsprintf(buffer, "%-20i", 1024); | |
REQUIRE(buffer, "1024 "); | |
xsprintf(buffer, "%-20i", -1024); | |
REQUIRE(buffer, "-1024 "); | |
xsprintf(buffer, "%-20u", 1024); | |
REQUIRE(buffer, "1024 "); | |
/* | |
xsprintf(buffer, "%-20.4f", 1024.1234); | |
REQUIRE(buffer, "1024.1234 "); | |
*/ | |
xsprintf(buffer, "%-20u", 4294966272U); | |
REQUIRE(buffer, "4294966272 "); | |
xsprintf(buffer, "%-20o", 511); | |
REQUIRE(buffer, "777 "); | |
xsprintf(buffer, "%-20o", 4294966785U); | |
REQUIRE(buffer, "37777777001 "); | |
xsprintf(buffer, "%-20x", 305441741); | |
REQUIRE(buffer, "1234abcd "); | |
xsprintf(buffer, "%-20x", 3989525555U); | |
REQUIRE(buffer, "edcb5433 "); | |
xsprintf(buffer, "%-20X", 305441741); | |
REQUIRE(buffer, "1234ABCD "); | |
xsprintf(buffer, "%-20X", 3989525555U); | |
REQUIRE(buffer, "EDCB5433 "); | |
xsprintf(buffer, "%-20c", 'x'); | |
REQUIRE(buffer, "x "); | |
xsprintf(buffer, "|%5d| |%-2d| |%5d|", 9, 9, 9); | |
REQUIRE(buffer, "| 9| |9 | | 9|"); | |
xsprintf(buffer, "|%5d| |%-2d| |%5d|", 10, 10, 10); | |
REQUIRE(buffer, "| 10| |10| | 10|"); | |
xsprintf(buffer, "|%5d| |%-12d| |%5d|", 9, 9, 9); | |
REQUIRE(buffer, "| 9| |9 | | 9|"); | |
xsprintf(buffer, "|%5d| |%-12d| |%5d|", 10, 10, 10); | |
REQUIRE(buffer, "| 10| |10 | | 10|"); | |
TEST_CASE("width 0-20"); | |
xsprintf(buffer, "%0-20s", "Hello"); | |
REQUIRE(buffer, "Hello "); | |
xsprintf(buffer, "%0-20d", 1024); | |
REQUIRE(buffer, "1024 "); | |
xsprintf(buffer, "%0-20d", -1024); | |
REQUIRE(buffer, "-1024 "); | |
xsprintf(buffer, "%0-20i", 1024); | |
REQUIRE(buffer, "1024 "); | |
xsprintf(buffer, "%0-20i", -1024); | |
REQUIRE(buffer, "-1024 "); | |
xsprintf(buffer, "%0-20u", 1024); | |
REQUIRE(buffer, "1024 "); | |
xsprintf(buffer, "%0-20u", 4294966272U); | |
REQUIRE(buffer, "4294966272 "); | |
xsprintf(buffer, "%0-20o", 511); | |
REQUIRE(buffer, "777 "); | |
xsprintf(buffer, "%0-20o", 4294966785U); | |
REQUIRE(buffer, "37777777001 "); | |
xsprintf(buffer, "%0-20x", 305441741); | |
REQUIRE(buffer, "1234abcd "); | |
xsprintf(buffer, "%0-20x", 3989525555U); | |
REQUIRE(buffer, "edcb5433 "); | |
xsprintf(buffer, "%0-20X", 305441741); | |
REQUIRE(buffer, "1234ABCD "); | |
xsprintf(buffer, "%0-20X", 3989525555U); | |
REQUIRE(buffer, "EDCB5433 "); | |
xsprintf(buffer, "%0-20c", 'x'); | |
REQUIRE(buffer, "x "); | |
TEST_CASE("padding 20"); | |
xsprintf(buffer, "%020d", 1024); | |
REQUIRE(buffer, "00000000000000001024"); | |
xsprintf(buffer, "%020d", -1024); | |
REQUIRE(buffer, "-0000000000000001024"); | |
xsprintf(buffer, "%020i", 1024); | |
REQUIRE(buffer, "00000000000000001024"); | |
xsprintf(buffer, "%020i", -1024); | |
REQUIRE(buffer, "-0000000000000001024"); | |
xsprintf(buffer, "%020u", 1024); | |
REQUIRE(buffer, "00000000000000001024"); | |
xsprintf(buffer, "%020u", 4294966272U); | |
REQUIRE(buffer, "00000000004294966272"); | |
xsprintf(buffer, "%020o", 511); | |
REQUIRE(buffer, "00000000000000000777"); | |
xsprintf(buffer, "%020o", 4294966785U); | |
REQUIRE(buffer, "00000000037777777001"); | |
xsprintf(buffer, "%020x", 305441741); | |
REQUIRE(buffer, "0000000000001234abcd"); | |
xsprintf(buffer, "%020x", 3989525555U); | |
REQUIRE(buffer, "000000000000edcb5433"); | |
xsprintf(buffer, "%020X", 305441741); | |
REQUIRE(buffer, "0000000000001234ABCD"); | |
xsprintf(buffer, "%020X", 3989525555U); | |
REQUIRE(buffer, "000000000000EDCB5433"); | |
TEST_CASE("padding .20"); | |
xsprintf(buffer, "%.20d", 1024); | |
REQUIRE(buffer, "00000000000000001024"); | |
xsprintf(buffer, "%.20d", -1024); | |
REQUIRE(buffer, "-00000000000000001024"); | |
xsprintf(buffer, "%.20i", 1024); | |
REQUIRE(buffer, "00000000000000001024"); | |
xsprintf(buffer, "%.20i", -1024); | |
REQUIRE(buffer, "-00000000000000001024"); | |
xsprintf(buffer, "%.20u", 1024); | |
REQUIRE(buffer, "00000000000000001024"); | |
xsprintf(buffer, "%.20u", 4294966272U); | |
REQUIRE(buffer, "00000000004294966272"); | |
xsprintf(buffer, "%.20o", 511); | |
REQUIRE(buffer, "00000000000000000777"); | |
xsprintf(buffer, "%.20o", 4294966785U); | |
REQUIRE(buffer, "00000000037777777001"); | |
xsprintf(buffer, "%.20x", 305441741); | |
REQUIRE(buffer, "0000000000001234abcd"); | |
xsprintf(buffer, "%.20x", 3989525555U); | |
REQUIRE(buffer, "000000000000edcb5433"); | |
xsprintf(buffer, "%.20X", 305441741); | |
REQUIRE(buffer, "0000000000001234ABCD"); | |
xsprintf(buffer, "%.20X", 3989525555U); | |
REQUIRE(buffer, "000000000000EDCB5433"); | |
TEST_CASE("padding #020"); | |
xsprintf(buffer, "%#020d", 1024); | |
REQUIRE(buffer, "00000000000000001024"); | |
xsprintf(buffer, "%#020d", -1024); | |
REQUIRE(buffer, "-0000000000000001024"); | |
xsprintf(buffer, "%#020i", 1024); | |
REQUIRE(buffer, "00000000000000001024"); | |
xsprintf(buffer, "%#020i", -1024); | |
REQUIRE(buffer, "-0000000000000001024"); | |
xsprintf(buffer, "%#020u", 1024); | |
REQUIRE(buffer, "00000000000000001024"); | |
xsprintf(buffer, "%#020u", 4294966272U); | |
REQUIRE(buffer, "00000000004294966272"); | |
xsprintf(buffer, "%#020o", 511); | |
REQUIRE(buffer, "00000000000000000777"); | |
xsprintf(buffer, "%#020o", 4294966785U); | |
REQUIRE(buffer, "00000000037777777001"); | |
xsprintf(buffer, "%#020x", 305441741); | |
REQUIRE(buffer, "0x00000000001234abcd"); | |
xsprintf(buffer, "%#020x", 3989525555U); | |
REQUIRE(buffer, "0x0000000000edcb5433"); | |
xsprintf(buffer, "%#020X", 305441741); | |
REQUIRE(buffer, "0X00000000001234ABCD"); | |
xsprintf(buffer, "%#020X", 3989525555U); | |
REQUIRE(buffer, "0X0000000000EDCB5433"); | |
TEST_CASE("padding #20"); | |
xsprintf(buffer, "%#20d", 1024); | |
REQUIRE(buffer, " 1024"); | |
xsprintf(buffer, "%#20d", -1024); | |
REQUIRE(buffer, " -1024"); | |
xsprintf(buffer, "%#20i", 1024); | |
REQUIRE(buffer, " 1024"); | |
xsprintf(buffer, "%#20i", -1024); | |
REQUIRE(buffer, " -1024"); | |
xsprintf(buffer, "%#20u", 1024); | |
REQUIRE(buffer, " 1024"); | |
xsprintf(buffer, "%#20u", 4294966272U); | |
REQUIRE(buffer, " 4294966272"); | |
xsprintf(buffer, "%#20o", 511); | |
REQUIRE(buffer, " 0777"); | |
xsprintf(buffer, "%#20o", 4294966785U); | |
REQUIRE(buffer, " 037777777001"); | |
xsprintf(buffer, "%#20x", 305441741); | |
REQUIRE(buffer, " 0x1234abcd"); | |
xsprintf(buffer, "%#20x", 3989525555U); | |
REQUIRE(buffer, " 0xedcb5433"); | |
xsprintf(buffer, "%#20X", 305441741); | |
REQUIRE(buffer, " 0X1234ABCD"); | |
xsprintf(buffer, "%#20X", 3989525555U); | |
REQUIRE(buffer, " 0XEDCB5433"); | |
TEST_CASE("padding 20.5"); | |
xsprintf(buffer, "%20.5d", 1024); | |
REQUIRE(buffer, " 01024"); | |
xsprintf(buffer, "%20.5d", -1024); | |
REQUIRE(buffer, " -01024"); | |
xsprintf(buffer, "%20.5i", 1024); | |
REQUIRE(buffer, " 01024"); | |
xsprintf(buffer, "%20.5i", -1024); | |
REQUIRE(buffer, " -01024"); | |
xsprintf(buffer, "%20.5u", 1024); | |
REQUIRE(buffer, " 01024"); | |
xsprintf(buffer, "%20.5u", 4294966272U); | |
REQUIRE(buffer, " 4294966272"); | |
xsprintf(buffer, "%20.5o", 511); | |
REQUIRE(buffer, " 00777"); | |
xsprintf(buffer, "%20.5o", 4294966785U); | |
REQUIRE(buffer, " 37777777001"); | |
xsprintf(buffer, "%20.5x", 305441741); | |
REQUIRE(buffer, " 1234abcd"); | |
xsprintf(buffer, "%20.10x", 3989525555U); | |
REQUIRE(buffer, " 00edcb5433"); | |
xsprintf(buffer, "%20.5X", 305441741); | |
REQUIRE(buffer, " 1234ABCD"); | |
xsprintf(buffer, "%20.10X", 3989525555U); | |
REQUIRE(buffer, " 00EDCB5433"); | |
TEST_CASE("padding neg numbers"); | |
// space padding | |
xsprintf(buffer, "% 1d", -5); | |
REQUIRE(buffer, "-5"); | |
xsprintf(buffer, "% 2d", -5); | |
REQUIRE(buffer, "-5"); | |
xsprintf(buffer, "% 3d", -5); | |
REQUIRE(buffer, " -5"); | |
xsprintf(buffer, "% 4d", -5); | |
REQUIRE(buffer, " -5"); | |
// zero padding | |
xsprintf(buffer, "%01d", -5); | |
REQUIRE(buffer, "-5"); | |
xsprintf(buffer, "%02d", -5); | |
REQUIRE(buffer, "-5"); | |
xsprintf(buffer, "%03d", -5); | |
REQUIRE(buffer, "-05"); | |
xsprintf(buffer, "%04d", -5); | |
REQUIRE(buffer, "-005"); | |
/* | |
TEST_CASE("float padding neg numbers"); | |
// space padding | |
xsprintf(buffer, "% 3.1f", -5.); | |
REQUIRE(buffer, "-5.0"); | |
xsprintf(buffer, "% 4.1f", -5.); | |
REQUIRE(buffer, "-5.0"); | |
xsprintf(buffer, "% 5.1f", -5.); | |
REQUIRE(buffer, " -5.0"); | |
#ifndef PRINTF_DISABLE_SUPPORT_EXPONENTIAL | |
xsprintf(buffer, "% 6.1g", -5.); | |
REQUIRE(buffer, " -5"); | |
xsprintf(buffer, "% 6.1e", -5.); | |
REQUIRE(buffer, "-5.0e+00"); | |
xsprintf(buffer, "% 10.1e", -5.); | |
REQUIRE(buffer, " -5.0e+00"); | |
#endif | |
// zero padding | |
xsprintf(buffer, "%03.1f", -5.); | |
REQUIRE(buffer, "-5.0"); | |
xsprintf(buffer, "%04.1f", -5.); | |
REQUIRE(buffer, "-5.0"); | |
xsprintf(buffer, "%05.1f", -5.); | |
REQUIRE(buffer, "-05.0"); | |
// zero padding no decimal point | |
xsprintf(buffer, "%01.0f", -5.); | |
REQUIRE(buffer, "-5"); | |
xsprintf(buffer, "%02.0f", -5.); | |
REQUIRE(buffer, "-5"); | |
xsprintf(buffer, "%03.0f", -5.); | |
REQUIRE(buffer, "-05"); | |
#ifndef PRINTF_DISABLE_SUPPORT_EXPONENTIAL | |
xsprintf(buffer, "%010.1e", -5.); | |
REQUIRE(buffer, "-005.0e+00"); | |
xsprintf(buffer, "%07.0E", -5.); | |
REQUIRE(buffer, "-05E+00"); | |
xsprintf(buffer, "%03.0g", -5.); | |
REQUIRE(buffer, "-05"); | |
#endif | |
*/ | |
TEST_CASE("length"); | |
xsprintf(buffer, "%.0s", "Hello testing"); | |
REQUIRE(buffer, ""); | |
xsprintf(buffer, "%20.0s", "Hello testing"); | |
REQUIRE(buffer, " "); | |
xsprintf(buffer, "%.s", "Hello testing"); | |
REQUIRE(buffer, ""); | |
xsprintf(buffer, "%20.s", "Hello testing"); | |
REQUIRE(buffer, " "); | |
xsprintf(buffer, "%20.0d", 1024); | |
REQUIRE(buffer, " 1024"); | |
xsprintf(buffer, "%20.0d", -1024); | |
REQUIRE(buffer, " -1024"); | |
xsprintf(buffer, "%20.d", 0); | |
REQUIRE(buffer, " "); | |
xsprintf(buffer, "%20.0i", 1024); | |
REQUIRE(buffer, " 1024"); | |
xsprintf(buffer, "%20.i", -1024); | |
REQUIRE(buffer, " -1024"); | |
xsprintf(buffer, "%20.i", 0); | |
REQUIRE(buffer, " "); | |
xsprintf(buffer, "%20.u", 1024); | |
REQUIRE(buffer, " 1024"); | |
xsprintf(buffer, "%20.0u", 4294966272U); | |
REQUIRE(buffer, " 4294966272"); | |
xsprintf(buffer, "%20.u", 0U); | |
REQUIRE(buffer, " "); | |
xsprintf(buffer, "%20.o", 511); | |
REQUIRE(buffer, " 777"); | |
xsprintf(buffer, "%20.0o", 4294966785U); | |
REQUIRE(buffer, " 37777777001"); | |
xsprintf(buffer, "%20.o", 0U); | |
REQUIRE(buffer, " "); | |
xsprintf(buffer, "%20.x", 305441741); | |
REQUIRE(buffer, " 1234abcd"); | |
xsprintf(buffer, "%50.x", 305441741); | |
REQUIRE(buffer, " 1234abcd"); | |
xsprintf(buffer, "%50.x%10.u", 305441741, 12345); | |
REQUIRE(buffer, " 1234abcd 12345"); | |
xsprintf(buffer, "%20.0x", 3989525555U); | |
REQUIRE(buffer, " edcb5433"); | |
xsprintf(buffer, "%20.x", 0U); | |
REQUIRE(buffer, " "); | |
xsprintf(buffer, "%20.X", 305441741); | |
REQUIRE(buffer, " 1234ABCD"); | |
xsprintf(buffer, "%20.0X", 3989525555U); | |
REQUIRE(buffer, " EDCB5433"); | |
xsprintf(buffer, "%20.X", 0U); | |
REQUIRE(buffer, " "); | |
xsprintf(buffer, "%02.0u", 0U); | |
REQUIRE(buffer, " "); | |
xsprintf(buffer, "%02.0d", 0); | |
REQUIRE(buffer, " "); | |
/* | |
TEST_CASE("float"); | |
// test special-case floats using math.h macros | |
xsprintf(buffer, "%8f", NAN); | |
REQUIRE(buffer, " nan"); | |
xsprintf(buffer, "%8f", INFINITY); | |
REQUIRE(buffer, " inf"); | |
xsprintf(buffer, "%-8f", -INFINITY); | |
REQUIRE(buffer, "-inf "); | |
#ifndef PRINTF_DISABLE_SUPPORT_EXPONENTIAL | |
xsprintf(buffer, "%+8e", INFINITY); | |
REQUIRE(buffer, " +inf"); | |
#endif | |
xsprintf(buffer, "%.4f", 3.1415354); | |
REQUIRE(buffer, "3.1415"); | |
xsprintf(buffer, "%.3f", 30343.1415354); | |
REQUIRE(buffer, "30343.142"); | |
xsprintf(buffer, "%.0f", 34.1415354); | |
REQUIRE(buffer, "34"); | |
xsprintf(buffer, "%.0f", 1.3); | |
REQUIRE(buffer, "1"); | |
xsprintf(buffer, "%.0f", 1.55); | |
REQUIRE(buffer, "2"); | |
xsprintf(buffer, "%.1f", 1.64); | |
REQUIRE(buffer, "1.6"); | |
xsprintf(buffer, "%.2f", 42.8952); | |
REQUIRE(buffer, "42.90"); | |
xsprintf(buffer, "%.9f", 42.8952); | |
REQUIRE(buffer, "42.895200000"); | |
xsprintf(buffer, "%.10f", 42.895223); | |
REQUIRE(buffer, "42.8952230000"); | |
// this testcase checks, that the precision is truncated to 9 digits. | |
// a perfect working float should return the whole number | |
xsprintf(buffer, "%.12f", 42.89522312345678); | |
REQUIRE(buffer, "42.895223123000"); | |
// this testcase checks, that the precision is truncated AND rounded to 9 digits. | |
// a perfect working float should return the whole number | |
xsprintf(buffer, "%.12f", 42.89522387654321); | |
REQUIRE(buffer, "42.895223877000"); | |
xsprintf(buffer, "%6.2f", 42.8952); | |
REQUIRE(buffer, " 42.90"); | |
xsprintf(buffer, "%+6.2f", 42.8952); | |
REQUIRE(buffer, "+42.90"); | |
xsprintf(buffer, "%+5.1f", 42.9252); | |
REQUIRE(buffer, "+42.9"); | |
xsprintf(buffer, "%f", 42.5); | |
REQUIRE(buffer, "42.500000"); | |
xsprintf(buffer, "%.1f", 42.5); | |
REQUIRE(buffer, "42.5"); | |
xsprintf(buffer, "%f", 42167.0); | |
REQUIRE(buffer, "42167.000000"); | |
xsprintf(buffer, "%.9f", -12345.987654321); | |
REQUIRE(buffer, "-12345.987654321"); | |
xsprintf(buffer, "%.1f", 3.999); | |
REQUIRE(buffer, "4.0"); | |
xsprintf(buffer, "%.0f", 3.5); | |
REQUIRE(buffer, "4"); | |
xsprintf(buffer, "%.0f", 4.5); | |
REQUIRE(buffer, "4"); | |
xsprintf(buffer, "%.0f", 3.49); | |
REQUIRE(buffer, "3"); | |
xsprintf(buffer, "%.1f", 3.49); | |
REQUIRE(buffer, "3.5"); | |
xsprintf(buffer, "a%-5.1f", 0.5); | |
REQUIRE(buffer, "a0.5 "); | |
xsprintf(buffer, "a%-5.1fend", 0.5); | |
REQUIRE(buffer, "a0.5 end"); | |
#ifndef PRINTF_DISABLE_SUPPORT_EXPONENTIAL | |
xsprintf(buffer, "%G", 12345.678); | |
REQUIRE(buffer, "12345.7"); | |
xsprintf(buffer, "%.7G", 12345.678); | |
REQUIRE(buffer, "12345.68"); | |
xsprintf(buffer, "%.5G", 123456789.); | |
REQUIRE(buffer, "1.2346E+08"); | |
xsprintf(buffer, "%.6G", 12345.); | |
REQUIRE(buffer, "12345.0"); | |
xsprintf(buffer, "%+12.4g", 123456789.); | |
REQUIRE(buffer, " +1.235e+08"); | |
xsprintf(buffer, "%.2G", 0.001234); | |
REQUIRE(buffer, "0.0012"); | |
xsprintf(buffer, "%+10.4G", 0.001234); | |
REQUIRE(buffer, " +0.001234"); | |
xsprintf(buffer, "%+012.4g", 0.00001234); | |
REQUIRE(buffer, "+001.234e-05"); | |
xsprintf(buffer, "%.3g", -1.2345e-308); | |
REQUIRE(buffer, "-1.23e-308"); | |
xsprintf(buffer, "%+.3E", 1.23e+308); | |
REQUIRE(buffer, "+1.230E+308"); | |
#endif | |
// out of range for float: should switch to exp notation if supported, else empty | |
xsprintf(buffer, "%.1f", 1E20); | |
#ifndef PRINTF_DISABLE_SUPPORT_EXPONENTIAL | |
REQUIRE(buffer, "1.0e+20"); | |
#else | |
REQUIRE(buffer, ""); | |
#endif | |
// brute force float | |
bool fail = false; | |
std::stringstream str; | |
str.precision(5); | |
for (float i = -100000; i < 100000; i += 1) { | |
xsprintf(buffer, "%.5f", i / 10000); | |
str.str(""); | |
str << std::fixed << i / 10000; | |
fail = fail || !buffer, str.str().c_str(); | |
} | |
REQUIRE(!fail); | |
#ifndef PRINTF_DISABLE_SUPPORT_EXPONENTIAL | |
// brute force exp | |
str.setf(std::ios::scientific, std::ios::floatfield); | |
for (float i = -1e20; i < 1e20; i += 1e15) { | |
xsprintf(buffer, "%.5f", i); | |
str.str(""); | |
str << i; | |
fail = fail || !buffer, str.str().c_str(); | |
} | |
REQUIRE(!fail); | |
#endif | |
*/ | |
TEST_CASE("types"); | |
xsprintf(buffer, "%i", 0); | |
REQUIRE(buffer, "0"); | |
xsprintf(buffer, "%i", 1234); | |
REQUIRE(buffer, "1234"); | |
xsprintf(buffer, "%i", 32767); | |
REQUIRE(buffer, "32767"); | |
xsprintf(buffer, "%i", -32767); | |
REQUIRE(buffer, "-32767"); | |
xsprintf(buffer, "%li", 30L); | |
REQUIRE(buffer, "30"); | |
xsprintf(buffer, "%li", -2147483647L); | |
REQUIRE(buffer, "-2147483647"); | |
xsprintf(buffer, "%li", 2147483647L); | |
REQUIRE(buffer, "2147483647"); | |
xsprintf(buffer, "%lli", 30LL); | |
REQUIRE(buffer, "30"); | |
xsprintf(buffer, "%lli", -9223372036854775807LL); | |
REQUIRE(buffer, "-9223372036854775807"); | |
xsprintf(buffer, "%lli", 9223372036854775807LL); | |
REQUIRE(buffer, "9223372036854775807"); | |
xsprintf(buffer, "%lu", 100000L); | |
REQUIRE(buffer, "100000"); | |
xsprintf(buffer, "%lu", 0xFFFFFFFFL); | |
REQUIRE(buffer, "4294967295"); | |
xsprintf(buffer, "%llu", 281474976710656LLU); | |
REQUIRE(buffer, "281474976710656"); | |
xsprintf(buffer, "%llu", 18446744073709551615LLU); | |
REQUIRE(buffer, "18446744073709551615"); | |
xsprintf(buffer, "%zu", 2147483647UL); | |
REQUIRE(buffer, "2147483647"); | |
xsprintf(buffer, "%zd", 2147483647UL); | |
REQUIRE(buffer, "2147483647"); | |
if (sizeof(size_t) == sizeof(long)) { | |
xsprintf(buffer, "%zi", -2147483647L); | |
REQUIRE(buffer, "-2147483647"); | |
} else { | |
xsprintf(buffer, "%zi", -2147483647LL); | |
REQUIRE(buffer, "-2147483647"); | |
} | |
/* | |
xsprintf(buffer, "%b", 60000); | |
REQUIRE(buffer, "1110101001100000"); | |
xsprintf(buffer, "%lb", 12345678L); | |
REQUIRE(buffer, "101111000110000101001110"); | |
*/ | |
xsprintf(buffer, "%o", 60000); | |
REQUIRE(buffer, "165140"); | |
xsprintf(buffer, "%lo", 12345678L); | |
REQUIRE(buffer, "57060516"); | |
xsprintf(buffer, "%lx", 0x12345678L); | |
REQUIRE(buffer, "12345678"); | |
xsprintf(buffer, "%llx", 0x1234567891234567LLU); | |
REQUIRE(buffer, "1234567891234567"); | |
xsprintf(buffer, "%lx", 0xabcdefabL); | |
REQUIRE(buffer, "abcdefab"); | |
xsprintf(buffer, "%lX", 0xabcdefabL); | |
REQUIRE(buffer, "ABCDEFAB"); | |
xsprintf(buffer, "%c", 'v'); | |
REQUIRE(buffer, "v"); | |
xsprintf(buffer, "%cv", 'w'); | |
REQUIRE(buffer, "wv"); | |
xsprintf(buffer, "%s", "A Test"); | |
REQUIRE(buffer, "A Test"); | |
xsprintf(buffer, "%hhu", 0xFFFFUL); | |
REQUIRE(buffer, "255"); | |
xsprintf(buffer, "%hu", 0x123456UL); | |
REQUIRE(buffer, "13398"); | |
xsprintf(buffer, "%s%hhi %hu", "Test", 10000, 0xFFFFFFFF); | |
REQUIRE(buffer, "Test16 65535"); | |
/* | |
xsprintf(buffer, "%tx", &buffer[10] - &buffer[0]); | |
REQUIRE(buffer, "a"); | |
// TBD | |
if (sizeof(intmax_t) == sizeof(long)) { | |
xsprintf(buffer, "%ji", -2147483647L); | |
REQUIRE(buffer, "-2147483647"); | |
} | |
else { | |
xsprintf(buffer, "%ji", -2147483647LL); | |
REQUIRE(buffer, "-2147483647"); | |
} | |
*/ | |
/* | |
TEST_CASE("pointer"); | |
xsprintf(buffer, "%p", (void*)0x1234U); | |
if (sizeof(void*) == 4U) { | |
REQUIRE(buffer, "00001234"); | |
} | |
else { | |
REQUIRE(buffer, "0000000000001234"); | |
} | |
xsprintf(buffer, "%p", (void*)0x12345678U); | |
if (sizeof(void*) == 4U) { | |
REQUIRE(buffer, "12345678"); | |
} | |
else { | |
REQUIRE(buffer, "0000000012345678"); | |
} | |
xsprintf(buffer, "%p-%p", (void*)0x12345678U, (void*)0x7EDCBA98U); | |
if (sizeof(void*) == 4U) { | |
REQUIRE(buffer, "12345678-7EDCBA98"); | |
} | |
else { | |
REQUIRE(buffer, "0000000012345678-000000007EDCBA98"); | |
} | |
if (sizeof(uintptr_t) == sizeof(uint64_t)) { | |
xsprintf(buffer, "%p", (void*)(uintptr_t)0xFFFFFFFFU); | |
REQUIRE(buffer, "00000000FFFFFFFF"); | |
} | |
else { | |
xsprintf(buffer, "%p", (void*)(uintptr_t)0xFFFFFFFFU); | |
REQUIRE(buffer, "FFFFFFFF"); | |
} | |
*/ | |
TEST_CASE("unknown flag"); | |
xsprintf(buffer, "%kmarco", 42, 37); | |
REQUIRE(buffer, "kmarco"); | |
TEST_CASE("string length"); | |
xsprintf(buffer, "%.4s", "This is a test"); | |
REQUIRE(buffer, "This"); | |
xsprintf(buffer, "%.4s", "test"); | |
REQUIRE(buffer, "test"); | |
xsprintf(buffer, "%.7s", "123"); | |
REQUIRE(buffer, "123"); | |
xsprintf(buffer, "%.7s", ""); | |
REQUIRE(buffer, ""); | |
xsprintf(buffer, "%.4s%.2s", "123456", "abcdef"); | |
REQUIRE(buffer, "1234ab"); | |
xsprintf(buffer, "%.4.2s", "123456"); | |
REQUIRE(buffer, ".2s"); | |
/* | |
xsprintf(buffer, "%.*s", 3, "123456"); | |
REQUIRE(buffer, "123"); | |
*/ | |
int ret; | |
ret = xsnprintf(NULL, 10, "%s", "Test"); | |
REQUIRES(ret, 4); | |
ret = xsnprintf(NULL, 0, "%s", "Test"); | |
REQUIRES(ret, 4); | |
buffer[0] = (char)0xA5; | |
ret = xsnprintf(buffer, 0, "%s", "Test"); | |
REQUIREC(buffer[0], (char)0xA5); | |
REQUIRES(ret, 4); | |
buffer[0] = (char)0xCC; | |
xsnprintf(buffer, 1, "%s", "Test"); | |
REQUIREC(buffer[0], '\0'); | |
xsnprintf(buffer, 2, "%s", "Hello"); | |
REQUIRE(buffer, "H"); | |
TEST_CASE("ret value"); | |
ret = xsnprintf(buffer, 6, "0%s", "1234"); | |
REQUIRE(buffer, "01234"); | |
REQUIRES(ret, 5); | |
ret = xsnprintf(buffer, 6, "0%s", "12345"); | |
REQUIRE(buffer, "01234"); | |
REQUIRES(ret, 6); // '5' is truncated | |
ret = xsnprintf(buffer, 6, "0%s", "1234567"); | |
REQUIRE(buffer, "01234"); | |
REQUIRES(ret, 8); // '567' are truncated | |
ret = xsnprintf(buffer, 10, "hello, world"); | |
REQUIRES(ret, 12); | |
ret = xsnprintf(buffer, 3, "%d", 10000); | |
REQUIRES(ret, 5); | |
REQUIRES(strlen(buffer), 2U); | |
REQUIREC(buffer[0], '1'); | |
REQUIREC(buffer[1], '0'); | |
REQUIREC(buffer[2], '\0'); | |
TEST_CASE("misc"); | |
xsprintf(buffer, "%u%u%ctest%d %s", 5, 3000, 'a', -20, "bit"); | |
REQUIRE(buffer, "53000atest-20 bit"); | |
/* | |
xsprintf(buffer, "%.*f", 2, 0.33333333); | |
REQUIRE(buffer, "0.33"); | |
xsprintf(buffer, "%.*d", -1, 1); | |
REQUIRE(buffer, "1"); | |
*/ | |
xsprintf(buffer, "%.3s", "foobar"); | |
REQUIRE(buffer, "foo"); | |
xsprintf(buffer, "% .0d", 0); | |
REQUIRE(buffer, " "); | |
xsprintf(buffer, "%10.5d", 4); | |
REQUIRE(buffer, " 00004"); | |
/* | |
xsprintf(buffer, "%*sx", -3, "hi"); | |
REQUIRE(buffer, "hi x"); | |
#ifndef PRINTF_DISABLE_SUPPORT_EXPONENTIAL | |
xsprintf(buffer, "%.*g", 2, 0.33333333); | |
REQUIRE(buffer, "0.33"); | |
xsprintf(buffer, "%.*e", 2, 0.33333333); | |
REQUIRE(buffer, "3.33e-01"); | |
#endif | |
*/ | |
} | |
return 1; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment