Common: ntoa fixes

This commit is contained in:
Alex Kotov 2022-05-30 15:55:38 +03:00
parent 53f782ce5a
commit 995bac1f73
Signed by: kotovalexarian
GPG Key ID: 553C0EBBEB5D5F08
6 changed files with 53 additions and 13 deletions

View File

@ -16,6 +16,7 @@ static mrb_value rb_KernAux_itoa(mrb_state *mrb, mrb_value self);
static mrb_value rb_KernAux_utoa10(mrb_state *mrb, mrb_value self);
static mrb_value rb_KernAux_itoa10(mrb_state *mrb, mrb_value self);
static mrb_value rb_KernAux_utoa16(mrb_state *mrb, mrb_value self);
static mrb_value rb_KernAux_itoa16(mrb_state *mrb, mrb_value self);
@ -29,6 +30,8 @@ void init_ntoa(mrb_state *const mrb)
mrb_define_class_under_id(mrb, rb_KernAux, MRB_SYM(InvalidNtoaBaseError),
rb_KernAux_Error);
mrb_define_class_under_id(mrb, rb_KernAux, MRB_SYM(TooLongNtoaPrefixError),
rb_KernAux_Error);
mrb_define_class_method(mrb, rb_KernAux, "utoa",
rb_KernAux_utoa, MRB_ARGS_REQ(2) | MRB_ARGS_OPT(1));
@ -39,6 +42,7 @@ void init_ntoa(mrb_state *const mrb)
rb_KernAux_utoa10, MRB_ARGS_REQ(1));
mrb_define_class_method(mrb, rb_KernAux, "itoa10",
rb_KernAux_itoa10, MRB_ARGS_REQ(1));
mrb_define_class_method(mrb, rb_KernAux, "utoa16",
rb_KernAux_utoa16, MRB_ARGS_REQ(1));
mrb_define_class_method(mrb, rb_KernAux, "itoa16",
@ -58,7 +62,15 @@ mrb_value rb_KernAux_utoa(mrb_state *mrb, mrb_value self)
"can't convert negative number to uint64_t");
}
if (prefix_len > MAX_PREFIX_LEN || prefix_len < 0) {
mrb_raisef(mrb, E_ARGUMENT_ERROR,
struct RClass *const rb_KernAux =
mrb_module_get_id(mrb, MRB_SYM(KernAux));
struct RClass *const rb_KernAux_TooLongNtoaPrefixError =
mrb_class_get_under_id(
mrb,
rb_KernAux,
MRB_SYM(TooLongNtoaPrefixError)
);
mrb_raisef(mrb, rb_KernAux_TooLongNtoaPrefixError,
"prefix length %d is too long", prefix_len);
}
@ -81,7 +93,15 @@ mrb_value rb_KernAux_itoa(mrb_state *mrb, mrb_value self)
mrb_get_args(mrb, "io|s!", &value, &base, &prefix, &prefix_len);
if (prefix_len > MAX_PREFIX_LEN || prefix_len < 0) {
mrb_raisef(mrb, E_ARGUMENT_ERROR,
struct RClass *const rb_KernAux =
mrb_module_get_id(mrb, MRB_SYM(KernAux));
struct RClass *const rb_KernAux_TooLongNtoaPrefixError =
mrb_class_get_under_id(
mrb,
rb_KernAux,
MRB_SYM(TooLongNtoaPrefixError)
);
mrb_raisef(mrb, rb_KernAux_TooLongNtoaPrefixError,
"prefix length %d is too long", prefix_len);
}

View File

@ -52,8 +52,8 @@ assert 'KernAux.utoa' do
base = 2 + Random.rand(36 - 2)
test_utoa number, base, number.to_s(base)
base = 2 + Random.rand(36 - 2)
assert_raise RangeError, 'can\'t convert negative number to uint64_t' do
base = 2 + Random.rand(36 - 2)
KernAux.utoa(-1, base)
end
@ -101,7 +101,10 @@ assert 'KernAux.utoa' do
prefix = 'a' * 100
test_utoax number, base, prefix, "#{prefix}#{number.abs.to_s(base)}"
assert_raise ArgumentError, 'prefix length 101 is too long' do
assert_raise(
KernAux::TooLongNtoaPrefixError,
'prefix length 101 is too long',
) do
number = Random.rand(2**32 - 1)
base = 2 + Random.rand(36 - 2)
prefix = 'a' * 101
@ -181,7 +184,10 @@ assert 'KernAux.itoa' do
sign = number < 0 ? '-' : ''
test_itoax number, base, prefix, "#{sign}#{prefix}#{number.abs.to_s(base)}"
assert_raise ArgumentError, 'prefix length 101 is too long' do
assert_raise(
KernAux::TooLongNtoaPrefixError,
'prefix length 101 is too long',
) do
number = Random.rand(2**31 - 1) * [1, -1].sample
base = 2 + Random.rand(36 - 2)
prefix = 'a' * 101

View File

@ -9,7 +9,6 @@ static VALUE rb_KernAux_utoa(VALUE self, VALUE number, VALUE base, VALUE prefix)
#ifdef HAVE_KERNAUX_ITOA
static VALUE rb_KernAux_itoa(VALUE self, VALUE number, VALUE base, VALUE prefix);
#endif
#ifdef HAVE_KERNAUX_UTOA10
static VALUE rb_KernAux_utoa10(VALUE self, VALUE number);
#endif
@ -39,6 +38,7 @@ static ID rb_intern_X = Qnil;
static VALUE rb_KernAux = Qnil;
static VALUE rb_KernAux_Error = Qnil;
static VALUE rb_KernAux_InvalidNtoaBaseError = Qnil;
static VALUE rb_KernAux_TooLongNtoaPrefixError = Qnil;
#if defined(HAVE_KERNAUX_UTOA) || defined(HAVE_KERNAUX_ITOA)
static int convert_base(VALUE base);
@ -65,6 +65,9 @@ void init_ntoa()
rb_gc_register_mark_object(rb_KernAux_InvalidNtoaBaseError =
rb_define_class_under(rb_KernAux, "InvalidNtoaBaseError",
rb_KernAux_Error));
rb_gc_register_mark_object(rb_KernAux_TooLongNtoaPrefixError =
rb_define_class_under(rb_KernAux, "TooLongNtoaPrefixError",
rb_KernAux_Error));
#ifdef HAVE_KERNAUX_UTOA
rb_define_singleton_method(rb_KernAux, "utoa", rb_KernAux_utoa, 3);
@ -72,7 +75,6 @@ void init_ntoa()
#ifdef HAVE_KERNAUX_ITOA
rb_define_singleton_method(rb_KernAux, "itoa", rb_KernAux_itoa, 3);
#endif
#ifdef HAVE_KERNAUX_UTOA10
rb_define_singleton_method(rb_KernAux, "utoa10", rb_KernAux_utoa10, 1);
#endif
@ -107,7 +109,7 @@ VALUE rb_KernAux_utoa(
if (prefix_len > MAX_PREFIX_LEN || prefix_len < 0) {
rb_raise(
rb_eArgError,
rb_KernAux_TooLongNtoaPrefixError,
"prefix length %ld is too long",
prefix_len
);
@ -137,7 +139,7 @@ VALUE rb_KernAux_itoa(
if (prefix_len > MAX_PREFIX_LEN || prefix_len < 0) {
rb_raise(
rb_eArgError,
rb_KernAux_TooLongNtoaPrefixError,
"prefix length %ld is too long",
prefix_len
);

View File

@ -127,7 +127,7 @@ module KernAux
# @!parse [ruby]
##
# @!method utoa(number, base)
# @!method utoa(number, base, prefix)
# Convert `uint64_t` to a string in multiple numeral systems.
#
# Base can be a positive or negative integer between 2 and 36, or a symbol
@ -139,16 +139,18 @@ module KernAux
#
# @param number [Integer] a number between 0 and `UINT64_MAX`
# @param base [Integer, Symbol] base of a numeral system
# @param prefix [nil, String] string to put before a number
# @return [String]
#
# @raise [RangeError] number is out of range
# @raise [InvalidNtoaBaseError] base is invalid
# @raise [TooLongNtoaPrefixError] prefix is too long
#
# @see .itoa Convert signed integers
##
##
# @!method itoa(number, base)
# @!method itoa(number, base, prefix)
# Convert `int64_t` to a string in multiple numeral systems.
#
# Base can be a positive or negative integer between 2 and 36, or a symbol
@ -160,10 +162,12 @@ module KernAux
#
# @param number [Integer] a number between `INT64_MIN` and `INT64_MAX`
# @param base [Integer, Symbol] base of a numeral system
# @param prefix [nil, String] string to put between a sign and a number
# @return [String]
#
# @raise [RangeError] number is out of range
# @raise [InvalidNtoaBaseError] base is invalid
# @raise [TooLongNtoaPrefixError] prefix is too long
#
# @see .utoa Convert unsigned integers
##
@ -235,4 +239,12 @@ module KernAux
# @see .itoa
#
class InvalidNtoaBaseError < Error; end
##
# Raised when prefix is too long.
#
# @see .utoa
# @see .itoa
#
class TooLongNtoaPrefixError < Error; end
end

View File

@ -221,7 +221,7 @@ RSpec.describe KernAux, '.itoa' do
specify do
expect { itoa }.to raise_error(
ArgumentError,
described_class::TooLongNtoaPrefixError,
"prefix length #{prefix.length} is too long",
)
end

View File

@ -193,7 +193,7 @@ RSpec.describe KernAux, '.utoa' do
specify do
expect { utoa }.to raise_error(
ArgumentError,
described_class::TooLongNtoaPrefixError,
"prefix length #{prefix.length} is too long",
)
end