Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

printf: Handle binary format specifiers #72

Merged
merged 1 commit into from
Aug 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions include/frg/formatting.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -94,14 +94,14 @@ enum class format_error {

namespace _fmt_basics {
// width: Minimum width of the output (padded with spaces by default).
// precision: Minimum number of digits in the ouput (always padded with zeros).
// precision: Minimum number of digits in the output (always padded with zeros).
template<Sink S, typename T>
void print_digits(S &sink, T number, bool negative, int radix,
int width, int precision, char padding, bool left_justify,
bool group_thousands, bool always_sign, bool plus_becomes_space,
bool use_capitals, locale_options locale_opts) {
const char *digits = use_capitals ? "0123456789ABCDEF" : "0123456789abcdef";
char buffer[32];
char buffer[64];

int k = 0; // number of digits
int c = 0; // number of chars since last grouping
Expand Down Expand Up @@ -137,7 +137,7 @@ namespace _fmt_basics {

// print the number in reverse order and determine #digits.
do {
FRG_ASSERT(k < 32); // TODO: variable number of digits
FRG_ASSERT(k < 64); // TODO: variable number of digits
buffer[k++] = digits[number % radix];
number /= radix;
step_grouping();
Expand Down
18 changes: 10 additions & 8 deletions include/frg/printf.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -335,15 +335,16 @@ void do_printf_ints(S &sink, char t, format_options opts,
opts.plus_becomes_space, false, locale_opts);
}
} break;
case 'o': {
case 'b':
case 'B' : {
auto print = [&] (auto number) {
if (number && opts.alt_conversion)
sink.append('0');
sink.append(t == 'b' ? "0b" : "0B");

if(opts.precision && *opts.precision == 0 && !number) {
// print nothing in this case
}else{
_fmt_basics::print_int(sink, number, 8, opts.minimum_width,
_fmt_basics::print_int(sink, number, 2, opts.minimum_width,
opts.precision ? *opts.precision : 1, opts.fill_zeros ? '0' : ' ',
opts.left_justify, false, opts.always_sign, opts.plus_becomes_space,
false, locale_opts);
Expand All @@ -367,15 +368,15 @@ void do_printf_ints(S &sink, char t, format_options opts,
print(pop_arg<unsigned int>(vsp, &opts));
}
} break;
case 'x': {
case 'o': {
auto print = [&] (auto number) {
if (number && opts.alt_conversion)
sink.append("0x");
sink.append('0');

if(opts.precision && *opts.precision == 0 && !number) {
// print nothing in this case
}else{
_fmt_basics::print_int(sink, number, 16, opts.minimum_width,
_fmt_basics::print_int(sink, number, 8, opts.minimum_width,
opts.precision ? *opts.precision : 1, opts.fill_zeros ? '0' : ' ',
opts.left_justify, false, opts.always_sign, opts.plus_becomes_space,
false, locale_opts);
Expand All @@ -399,18 +400,19 @@ void do_printf_ints(S &sink, char t, format_options opts,
print(pop_arg<unsigned int>(vsp, &opts));
}
} break;
case 'x':
case 'X': {
auto print = [&] (auto number) {
if (number && opts.alt_conversion)
sink.append("0X");
sink.append(t == 'x' ? "0x" : "0X");

if(opts.precision && *opts.precision == 0 && !number) {
// print nothing in this case
}else{
_fmt_basics::print_int(sink, number, 16, opts.minimum_width,
opts.precision ? *opts.precision : 1, opts.fill_zeros ? '0' : ' ',
opts.left_justify, false, opts.always_sign, opts.plus_becomes_space,
true, locale_opts);
t == 'X', locale_opts);
}
};

Expand Down
14 changes: 13 additions & 1 deletion tests/tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -264,7 +264,7 @@ TEST(formatting, printf) {
case 'p': case 's':
frg::do_printf_chars(*sink_, t, opts, szmod, vsp_);
break;
case 'd': case 'i': case 'o': case 'x': case 'X': case 'u':
case 'd': case 'i': case 'o': case 'x': case 'X': case 'b': case 'B': case 'u':
frg::do_printf_ints(*sink_, t, opts, szmod, vsp_);
break;
default:
Expand Down Expand Up @@ -333,6 +333,8 @@ TEST(formatting, printf) {
// Test '#' flag.
do_test("0xc", "%#x", 12);
do_test("0XC", "%#X", 12);
do_test("0b1100", "%#b", 12);
do_test("0B1100", "%#B", 12);
do_test("014", "%#o", 12);
do_test("0", "%#x", 0);
do_test("0", "%#X", 0);
Expand Down Expand Up @@ -368,6 +370,16 @@ TEST(formatting, printf) {
do_test("C", "%hhX", 12);
do_test("C", "%jX", (uintmax_t)12);

// Test 'b' with different size mods to see
// if they work
do_test("1100", "%b", 12);
do_test("1100", "%lb", 12L);
do_test("1100", "%llb", 12LL);
do_test("1100", "%zb", (size_t)12);
do_test("1100", "%hb", 12);
do_test("1100", "%hhb", 12);
do_test("1100", "%jb", (uintmax_t)12);

// Test 'o' with different size mods to see
// if they work
do_test("14", "%o", 12);
Expand Down
Loading