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:
parent
e39c2dc05d
commit
6fe0254dce
2 changed files with 50 additions and 10 deletions
|
@ -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') {
|
||||
|
|
|
@ -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) { '%%' }
|
||||
|
||||
|
|
Loading…
Reference in a new issue