2022-02-01 05:19:54 +00:00
|
|
|
#include "main.h"
|
|
|
|
|
|
|
|
#include <stdint.h>
|
|
|
|
|
|
|
|
#include <kernaux.h>
|
|
|
|
|
|
|
|
#include <mruby.h>
|
2022-02-03 08:27:14 +00:00
|
|
|
#include <mruby/numeric.h>
|
2022-02-01 05:19:54 +00:00
|
|
|
#include <mruby/presym.h>
|
|
|
|
#include <mruby/string.h>
|
|
|
|
|
2022-05-30 09:49:58 +00:00
|
|
|
#define MAX_PREFIX_LEN 100
|
|
|
|
|
2022-02-03 08:27:14 +00:00
|
|
|
static mrb_value rb_KernAux_utoa(mrb_state *mrb, mrb_value self);
|
|
|
|
static mrb_value rb_KernAux_itoa(mrb_state *mrb, mrb_value self);
|
2022-05-30 09:49:58 +00:00
|
|
|
|
2022-02-01 05:19:54 +00:00
|
|
|
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);
|
|
|
|
|
2022-02-03 08:27:14 +00:00
|
|
|
static int convert_base(mrb_state *mrb, mrb_value base);
|
|
|
|
|
2022-02-01 05:19:54 +00:00
|
|
|
void init_ntoa(mrb_state *const mrb)
|
|
|
|
{
|
|
|
|
struct RClass *const rb_KernAux = mrb_module_get_id(mrb, MRB_SYM(KernAux));
|
2022-02-03 08:27:14 +00:00
|
|
|
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);
|
2022-02-01 05:19:54 +00:00
|
|
|
|
2022-02-03 08:27:14 +00:00
|
|
|
mrb_define_class_method(mrb, rb_KernAux, "utoa",
|
2022-05-30 09:49:58 +00:00
|
|
|
rb_KernAux_utoa, MRB_ARGS_REQ(2) | MRB_ARGS_OPT(1));
|
2022-02-03 08:27:14 +00:00
|
|
|
mrb_define_class_method(mrb, rb_KernAux, "itoa",
|
2022-05-30 09:49:58 +00:00
|
|
|
rb_KernAux_itoa, MRB_ARGS_REQ(2) | MRB_ARGS_OPT(1));
|
|
|
|
|
2022-02-01 05:19:54 +00:00
|
|
|
mrb_define_class_method(mrb, rb_KernAux, "utoa10",
|
|
|
|
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",
|
|
|
|
rb_KernAux_itoa16, MRB_ARGS_REQ(1));
|
|
|
|
}
|
|
|
|
|
2022-02-03 08:27:14 +00:00
|
|
|
mrb_value rb_KernAux_utoa(mrb_state *mrb, mrb_value self)
|
|
|
|
{
|
|
|
|
mrb_int value = 0;
|
|
|
|
mrb_value base;
|
2022-05-30 09:49:58 +00:00
|
|
|
const char *prefix = NULL;
|
|
|
|
mrb_int prefix_len = 0;
|
|
|
|
mrb_get_args(mrb, "io|s!", &value, &base, &prefix, &prefix_len);
|
2022-02-03 08:27:14 +00:00
|
|
|
|
|
|
|
if (value < 0) {
|
|
|
|
mrb_raise(mrb, E_RANGE_ERROR,
|
|
|
|
"can't convert negative number to uint64_t");
|
|
|
|
}
|
2022-05-30 09:49:58 +00:00
|
|
|
if (prefix_len > MAX_PREFIX_LEN || prefix_len < 0) {
|
|
|
|
mrb_raisef(mrb, E_ARGUMENT_ERROR,
|
|
|
|
"prefix length %d is too long", prefix_len);
|
|
|
|
}
|
2022-02-03 08:27:14 +00:00
|
|
|
|
2022-05-30 09:49:58 +00:00
|
|
|
char buffer[KERNAUX_UTOA_BUFFER_SIZE + prefix_len];
|
2022-02-03 08:27:14 +00:00
|
|
|
current_mrb_start(mrb);
|
2022-05-30 09:49:58 +00:00
|
|
|
kernaux_utoa(value, buffer, convert_base(mrb, base), prefix);
|
2022-02-03 08:27:14 +00:00
|
|
|
current_mrb_finish(mrb);
|
|
|
|
|
|
|
|
mrb_value result = mrb_str_new_lit(mrb, "");
|
|
|
|
result = mrb_str_cat_cstr(mrb, result, buffer);
|
2022-02-03 09:44:51 +00:00
|
|
|
return mrb_obj_freeze(mrb, result);
|
2022-02-03 08:27:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
mrb_value rb_KernAux_itoa(mrb_state *mrb, mrb_value self)
|
|
|
|
{
|
|
|
|
mrb_int value = 0;
|
|
|
|
mrb_value base;
|
2022-05-30 09:49:58 +00:00
|
|
|
const char *prefix = NULL;
|
|
|
|
mrb_int prefix_len = 0;
|
|
|
|
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,
|
|
|
|
"prefix length %d is too long", prefix_len);
|
|
|
|
}
|
2022-02-03 08:27:14 +00:00
|
|
|
|
2022-05-30 09:49:58 +00:00
|
|
|
char buffer[KERNAUX_ITOA_BUFFER_SIZE + prefix_len];
|
2022-02-03 08:27:14 +00:00
|
|
|
current_mrb_start(mrb);
|
2022-05-30 09:49:58 +00:00
|
|
|
kernaux_itoa(value, buffer, convert_base(mrb, base), prefix);
|
2022-02-03 08:27:14 +00:00
|
|
|
current_mrb_finish(mrb);
|
|
|
|
|
|
|
|
mrb_value result = mrb_str_new_lit(mrb, "");
|
|
|
|
result = mrb_str_cat_cstr(mrb, result, buffer);
|
2022-02-03 09:44:51 +00:00
|
|
|
return mrb_obj_freeze(mrb, result);
|
2022-02-03 08:27:14 +00:00
|
|
|
}
|
|
|
|
|
2022-02-01 05:19:54 +00:00
|
|
|
mrb_value rb_KernAux_utoa10(mrb_state *mrb, mrb_value self)
|
|
|
|
{
|
|
|
|
mrb_int value = 0;
|
|
|
|
mrb_get_args(mrb, "i", &value);
|
|
|
|
|
|
|
|
if (value < 0) {
|
|
|
|
mrb_raise(mrb, E_RANGE_ERROR,
|
|
|
|
"can't convert negative number to uint64_t");
|
|
|
|
}
|
|
|
|
|
|
|
|
char buffer[KERNAUX_UTOA10_BUFFER_SIZE];
|
|
|
|
current_mrb_start(mrb);
|
|
|
|
kernaux_utoa10(value, buffer);
|
|
|
|
current_mrb_finish(mrb);
|
|
|
|
|
|
|
|
mrb_value result = mrb_str_new_lit(mrb, "");
|
|
|
|
result = mrb_str_cat_cstr(mrb, result, buffer);
|
2022-02-03 09:44:51 +00:00
|
|
|
return mrb_obj_freeze(mrb, result);
|
2022-02-01 05:19:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
mrb_value rb_KernAux_itoa10(mrb_state *mrb, mrb_value self)
|
|
|
|
{
|
|
|
|
mrb_int value = 0;
|
|
|
|
mrb_get_args(mrb, "i", &value);
|
|
|
|
|
|
|
|
char buffer[KERNAUX_ITOA10_BUFFER_SIZE];
|
|
|
|
current_mrb_start(mrb);
|
|
|
|
kernaux_itoa10(value, buffer);
|
|
|
|
current_mrb_finish(mrb);
|
|
|
|
|
|
|
|
mrb_value result = mrb_str_new_lit(mrb, "");
|
|
|
|
result = mrb_str_cat_cstr(mrb, result, buffer);
|
2022-02-03 09:44:51 +00:00
|
|
|
return mrb_obj_freeze(mrb, result);
|
2022-02-01 05:19:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
mrb_value rb_KernAux_utoa16(mrb_state *mrb, mrb_value self)
|
|
|
|
{
|
|
|
|
mrb_int value = 0;
|
|
|
|
mrb_get_args(mrb, "i", &value);
|
|
|
|
|
|
|
|
if (value < 0) {
|
|
|
|
mrb_raise(mrb, E_RANGE_ERROR,
|
|
|
|
"can't convert negative number to uint64_t");
|
|
|
|
}
|
|
|
|
|
|
|
|
char buffer[KERNAUX_UTOA16_BUFFER_SIZE];
|
|
|
|
current_mrb_start(mrb);
|
|
|
|
kernaux_utoa16(value, buffer);
|
|
|
|
current_mrb_finish(mrb);
|
|
|
|
|
|
|
|
mrb_value result = mrb_str_new_lit(mrb, "");
|
|
|
|
result = mrb_str_cat_cstr(mrb, result, buffer);
|
2022-02-03 09:44:51 +00:00
|
|
|
return mrb_obj_freeze(mrb, result);
|
2022-02-01 05:19:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
mrb_value rb_KernAux_itoa16(mrb_state *mrb, mrb_value self)
|
|
|
|
{
|
|
|
|
mrb_int value = 0;
|
|
|
|
mrb_get_args(mrb, "i", &value);
|
|
|
|
|
|
|
|
char buffer[KERNAUX_ITOA16_BUFFER_SIZE];
|
|
|
|
current_mrb_start(mrb);
|
|
|
|
kernaux_itoa16(value, buffer);
|
|
|
|
current_mrb_finish(mrb);
|
|
|
|
|
|
|
|
mrb_value result = mrb_str_new_lit(mrb, "");
|
|
|
|
result = mrb_str_cat_cstr(mrb, result, buffer);
|
2022-02-03 09:44:51 +00:00
|
|
|
return mrb_obj_freeze(mrb, result);
|
2022-02-01 05:19:54 +00:00
|
|
|
}
|
2022-02-03 08:27:14 +00:00
|
|
|
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
}
|