mruby: add methods KernAux.utoa, .itoa

This commit is contained in:
Alex Kotov 2022-02-03 13:27:14 +05:00
parent c1c4fc6c46
commit ac73b63b3d
Signed by: kotovalexarian
GPG Key ID: 553C0EBBEB5D5F08
4 changed files with 216 additions and 1 deletions

View File

@ -11,5 +11,7 @@ MRuby::Gem::Specification.new 'mruby-kernaux' do |spec|
Binding to libkernaux - auxiliary library for kernel development.
DESCRIPTION
spec.add_test_dependency 'mruby-random'
spec.linker.libraries << 'kernaux'
end

View File

@ -20,7 +20,10 @@ void mrb_mruby_kernaux_gem_init(mrb_state *const mrb)
mrb_stack[index] = NULL;
}
struct RClass *const rb_KernAux =
mrb_define_module_id(mrb, MRB_SYM(KernAux));
mrb_define_class_under_id(mrb, rb_KernAux, MRB_SYM(Error), E_RUNTIME_ERROR);
init_assert(mrb);
init_ntoa(mrb);
}

View File

@ -5,18 +5,32 @@
#include <kernaux.h>
#include <mruby.h>
#include <mruby/numeric.h>
#include <mruby/presym.h>
#include <mruby/string.h>
static mrb_value rb_KernAux_utoa(mrb_state *mrb, mrb_value self);
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);
static int convert_base(mrb_state *mrb, mrb_value base);
void init_ntoa(mrb_state *const mrb)
{
struct RClass *const rb_KernAux = mrb_module_get_id(mrb, MRB_SYM(KernAux));
struct RClass *const rb_KernAux_Error =
mrb_class_get_under_id(mrb, rb_KernAux, MRB_SYM(Error));
mrb_define_class_under_id(mrb, rb_KernAux, MRB_SYM(InvalidNtoaBaseError),
rb_KernAux_Error);
mrb_define_class_method(mrb, rb_KernAux, "utoa",
rb_KernAux_utoa, MRB_ARGS_REQ(2));
mrb_define_class_method(mrb, rb_KernAux, "itoa",
rb_KernAux_itoa, MRB_ARGS_REQ(2));
mrb_define_class_method(mrb, rb_KernAux, "utoa10",
rb_KernAux_utoa10, MRB_ARGS_REQ(1));
mrb_define_class_method(mrb, rb_KernAux, "itoa10",
@ -27,6 +41,43 @@ void init_ntoa(mrb_state *const mrb)
rb_KernAux_itoa16, MRB_ARGS_REQ(1));
}
mrb_value rb_KernAux_utoa(mrb_state *mrb, mrb_value self)
{
mrb_int value = 0;
mrb_value base;
mrb_get_args(mrb, "io", &value, &base);
if (value < 0) {
mrb_raise(mrb, E_RANGE_ERROR,
"can't convert negative number to uint64_t");
}
char buffer[KERNAUX_UTOA_BUFFER_SIZE];
current_mrb_start(mrb);
kernaux_utoa(value, buffer, convert_base(mrb, base));
current_mrb_finish(mrb);
mrb_value result = mrb_str_new_lit(mrb, "");
result = mrb_str_cat_cstr(mrb, result, buffer);
return result;
}
mrb_value rb_KernAux_itoa(mrb_state *mrb, mrb_value self)
{
mrb_int value = 0;
mrb_value base;
mrb_get_args(mrb, "io", &value, &base);
char buffer[KERNAUX_ITOA_BUFFER_SIZE];
current_mrb_start(mrb);
kernaux_itoa(value, buffer, convert_base(mrb, base));
current_mrb_finish(mrb);
mrb_value result = mrb_str_new_lit(mrb, "");
result = mrb_str_cat_cstr(mrb, result, buffer);
return result;
}
mrb_value rb_KernAux_utoa10(mrb_state *mrb, mrb_value self)
{
mrb_int value = 0;
@ -96,3 +147,32 @@ mrb_value rb_KernAux_itoa16(mrb_state *mrb, mrb_value self)
result = mrb_str_cat_cstr(mrb, result, buffer);
return result;
}
int convert_base(mrb_state *mrb, mrb_value base_rb)
{
if (mrb_obj_is_kind_of(mrb, base_rb, mrb->symbol_class)) {
mrb_sym base_sym = mrb_obj_to_sym(mrb, base_rb);
switch (base_sym) {
case MRB_SYM(b): return 'b';
case MRB_SYM(B): return 'B';
case MRB_SYM(h): return 'h';
case MRB_SYM(H): return 'H';
case MRB_SYM(o): return 'o';
case MRB_SYM(O): return 'O';
case MRB_SYM(d): return 'd';
case MRB_SYM(D): return 'D';
case MRB_SYM(x): return 'x';
case MRB_SYM(X): return 'X';
default:
{
struct RClass *const rb_KernAux =
mrb_module_get_id(mrb, MRB_SYM(KernAux));
struct RClass *const rb_KernAux_Error =
mrb_class_get_under_id(mrb, rb_KernAux, MRB_SYM(Error));
mrb_raise(mrb, rb_KernAux_Error, "invalid base");
}
}
} else {
return mrb_integer(base_rb);
}
}

View File

@ -1,3 +1,133 @@
assert 'KernAux.utoa' do
number = Random.rand(2**32 - 1)
base = 2 + Random.rand(36 - 2)
assert_equal number.to_s(base), KernAux.utoa(number, base)
number = 0
base = 2 + Random.rand(36 - 2)
assert_equal '0', KernAux.utoa(number, base)
number = 2**32 - 1
base = 2 + Random.rand(36 - 2)
assert_equal number.to_s(base), KernAux.utoa(number, base)
number = -1
base = 2 + Random.rand(36 - 2)
assert_raise RangeError, 'can\'t convert negative number to uint64_t' do
KernAux.utoa number, base
end
number = Random.rand(2**32 - 1)
base = -(2 + Random.rand(36 - 2))
assert_equal number.to_s(-base).upcase, KernAux.utoa(number, base)
number = Random.rand(2**32 - 1)
base = :b
assert_equal number.to_s(2), KernAux.utoa(number, base)
number = Random.rand(2**32 - 1)
base = :B
assert_equal number.to_s(2), KernAux.utoa(number, base)
number = Random.rand(2**32 - 1)
base = :o
assert_equal number.to_s(8), KernAux.utoa(number, base)
number = Random.rand(2**32 - 1)
base = :O
assert_equal number.to_s(8), KernAux.utoa(number, base)
number = Random.rand(2**32 - 1)
base = :d
assert_equal number.to_s(10), KernAux.utoa(number, base)
number = Random.rand(2**32 - 1)
base = :D
assert_equal number.to_s(10), KernAux.utoa(number, base)
number = Random.rand(2**32 - 1)
base = :h
assert_equal number.to_s(16), KernAux.utoa(number, base)
number = Random.rand(2**32 - 1)
base = :x
assert_equal number.to_s(16), KernAux.utoa(number, base)
number = Random.rand(2**32 - 1)
base = :H
assert_equal number.to_s(16).upcase, KernAux.utoa(number, base)
number = Random.rand(2**32 - 1)
base = :X
assert_equal number.to_s(16).upcase, KernAux.utoa(number, base)
end
assert 'KernAux.itoa' do
number = Random.rand(2**31 - 1) * [1, -1].sample
base = 2 + Random.rand(36 - 2)
assert_equal number.to_s(base), KernAux.itoa(number, base)
number = 0
base = 2 + Random.rand(36 - 2)
assert_equal '0', KernAux.itoa(number, base)
number = 1
base = 2 + Random.rand(36 - 2)
assert_equal '1', KernAux.itoa(number, base)
number = -1
base = 2 + Random.rand(36 - 2)
assert_equal '-1', KernAux.itoa(number, base)
number = 2**31 - 1
base = 2 + Random.rand(36 - 2)
assert_equal number.to_s(base), KernAux.itoa(number, base)
number = -(2**31 - 1)
base = 2 + Random.rand(36 - 2)
assert_equal number.to_s(base), KernAux.itoa(number, base)
number = Random.rand(2**31 - 1) * [1, -1].sample
base = :b
assert_equal number.to_s(2), KernAux.itoa(number, base)
number = Random.rand(2**31 - 1) * [1, -1].sample
base = :B
assert_equal number.to_s(2), KernAux.itoa(number, base)
number = Random.rand(2**31 - 1) * [1, -1].sample
base = :o
assert_equal number.to_s(8), KernAux.itoa(number, base)
number = Random.rand(2**31 - 1) * [1, -1].sample
base = :O
assert_equal number.to_s(8), KernAux.itoa(number, base)
number = Random.rand(2**31 - 1) * [1, -1].sample
base = :d
assert_equal number.to_s(10), KernAux.itoa(number, base)
number = Random.rand(2**31 - 1) * [1, -1].sample
base = :D
assert_equal number.to_s(10), KernAux.itoa(number, base)
number = Random.rand(2**31 - 1) * [1, -1].sample
base = :h
assert_equal number.to_s(16), KernAux.itoa(number, base)
number = Random.rand(2**31 - 1) * [1, -1].sample
base = :x
assert_equal number.to_s(16), KernAux.itoa(number, base)
number = Random.rand(2**31 - 1) * [1, -1].sample
base = :H
assert_equal number.to_s(16).upcase, KernAux.itoa(number, base)
number = Random.rand(2**31 - 1) * [1, -1].sample
base = :X
assert_equal number.to_s(16).upcase, KernAux.itoa(number, base)
end
assert 'KernAux.utoa10' do
assert_equal '0', KernAux.utoa10(0)
assert_equal '1', KernAux.utoa10(1)