1
0
Fork 0
mirror of https://github.com/tailix/libkernaux.git synced 2024-11-13 11:04:27 -05:00

Ruby: Mimic printf behavior

This commit is contained in:
Alex Kotov 2022-01-21 18:55:03 +05:00
parent e39c2dc05d
commit 6fe0254dce
Signed by: kotovalexarian
GPG key ID: 553C0EBBEB5D5F08
2 changed files with 50 additions and 10 deletions

View file

@ -129,16 +129,48 @@ VALUE rb_KernAux_snprintf1(
const char *const format = StringValueCStr(format_rb);
if (size < 0) rb_raise(rb_eRangeError, "expected non-negative size");
if (strlen(format) > 100) rb_raise(rb_eArgError, "invalid format");
const char *fmt = format;
while (*fmt && *fmt != '%') ++fmt;
if (*(fmt++) != '%') rb_raise(rb_eArgError, "invalid format");
// Mimic printf behavior.
if (*fmt == '0' || *fmt == '-' || *fmt == '+' || *fmt == ' ' ||
*fmt == '#')
{
size_t fmt_size = 0, perc_count = 0;
for (const char *fmt = format; *fmt; ++fmt, ++fmt_size) {
if (*fmt == '%') ++perc_count;
}
if (fmt_size > 100 || perc_count == 0 || perc_count > 2) {
rb_raise(rb_eArgError, "invalid format");
++fmt;
}
if (*fmt >= '0' && *fmt <= '9') {
while (*fmt >= '0' && *fmt <= '9') ++fmt;
} else if (*fmt == '*') {
++fmt;
}
if (*fmt == '.') {
++fmt;
if (*fmt >= '0' && *fmt <= '9') {
while (*fmt >= '0' && *fmt <= '9') ++fmt;
} else if (*fmt == '*') {
++fmt;
}
}
if (*fmt == 'l') {
++fmt;
if (*fmt == 'l') ++fmt;
} else if (*fmt == 'h') {
++fmt;
if (*fmt == 'h') ++fmt;
} else if (*fmt == 't' || *fmt == 'j' || *fmt == 'z' || *fmt == 'z') {
++fmt;
}
const char c = *fmt;
if (*fmt == '%') ++fmt;
while (*fmt) {
if (*(fmt++) == '%') rb_raise(rb_eArgError, "invalid format");
}
union {
const char *str;
@ -149,10 +181,6 @@ VALUE rb_KernAux_snprintf1(
} __attribute__((packed)) arg = { .str = "" };
if (argc == 3) {
const char *fmt = format;
while (*(fmt + 1)) ++fmt;
const char c = *fmt;
VALUE arg_rb = argv_rb[2];
if (c == 'd' || c == 'i') {

View file

@ -20,6 +20,12 @@ RSpec.describe KernAux, '.snprintf1' do
specify { expect(snprintf1[0]).to eq '%' }
specify { expect(snprintf1[1]).to eq 1 }
context 'with leading and trailing spaces' do
let(:format) { ' %% ' }
specify { expect(snprintf1[0]).to eq ' % ' }
end
context 'with "%s" format' do
let(:format) { '%s' }
@ -82,6 +88,12 @@ RSpec.describe KernAux, '.snprintf1' do
specify { expect(snprintf1[0]).to eq arg }
specify { expect(snprintf1[1]).to eq arg.size }
context 'with leading and trailing spaces' do
let(:format) { ' %s ' }
specify { expect(snprintf1[0]).to eq " #{arg} " }
end
context 'with "%%" format' do
let(:format) { '%%' }