#include "main.h" #include #include #include #include #ifdef KERNAUX_VERSION_WITH_NTOA 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_utoa2(mrb_state *mrb, mrb_value self); static mrb_value rb_KernAux_itoa2(mrb_state *mrb, mrb_value self); static mrb_value rb_KernAux_utoa8(mrb_state *mrb, mrb_value self); static mrb_value rb_KernAux_itoa8(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_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)); mrb_define_class_method(mrb, rb_KernAux, "itoa", rb_KernAux_itoa, MRB_ARGS_REQ(2) | MRB_ARGS_OPT(1)); mrb_define_class_method(mrb, rb_KernAux, "utoa2", rb_KernAux_utoa2, MRB_ARGS_REQ(1)); mrb_define_class_method(mrb, rb_KernAux, "itoa2", rb_KernAux_itoa2, MRB_ARGS_REQ(1)); mrb_define_class_method(mrb, rb_KernAux, "utoa8", rb_KernAux_utoa8, MRB_ARGS_REQ(1)); mrb_define_class_method(mrb, rb_KernAux, "itoa8", rb_KernAux_itoa8, MRB_ARGS_REQ(1)); 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)); } mrb_value rb_KernAux_utoa(mrb_state *mrb, mrb_value self) { mrb_int value = 0; mrb_value base; const char *prefix = NULL; mrb_int prefix_len = 0; mrb_get_args(mrb, "io|s!", &value, &base, &prefix, &prefix_len); if (value < 0) { mrb_raise(mrb, E_RANGE_ERROR, "can't convert negative number to uint64_t"); } if (prefix_len > KERNAUX_NTOA_MAX_PREFIX_LEN || prefix_len < 0) { 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); } char buffer[KERNAUX_UTOA_MIN_BUFFER_SIZE + prefix_len]; current_mrb_start(mrb); kernaux_utoa(value, buffer, convert_base(mrb, base), prefix); current_mrb_finish(mrb); mrb_value result = mrb_str_new_lit(mrb, ""); result = mrb_str_cat_cstr(mrb, result, buffer); return mrb_obj_freeze(mrb, result); } mrb_value rb_KernAux_itoa(mrb_state *mrb, mrb_value self) { mrb_int value = 0; mrb_value base; const char *prefix = NULL; mrb_int prefix_len = 0; mrb_get_args(mrb, "io|s!", &value, &base, &prefix, &prefix_len); if (prefix_len > KERNAUX_NTOA_MAX_PREFIX_LEN || prefix_len < 0) { 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); } char buffer[KERNAUX_ITOA_MIN_BUFFER_SIZE + prefix_len]; current_mrb_start(mrb); kernaux_itoa(value, buffer, convert_base(mrb, base), prefix); current_mrb_finish(mrb); mrb_value result = mrb_str_new_lit(mrb, ""); result = mrb_str_cat_cstr(mrb, result, buffer); return mrb_obj_freeze(mrb, result); } mrb_value rb_KernAux_utoa2(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_UTOA2_BUFFER_SIZE]; current_mrb_start(mrb); kernaux_utoa2(value, buffer); current_mrb_finish(mrb); mrb_value result = mrb_str_new_lit(mrb, ""); result = mrb_str_cat_cstr(mrb, result, buffer); return mrb_obj_freeze(mrb, result); } mrb_value rb_KernAux_itoa2(mrb_state *mrb, mrb_value self) { mrb_int value = 0; mrb_get_args(mrb, "i", &value); char buffer[KERNAUX_ITOA2_BUFFER_SIZE]; current_mrb_start(mrb); kernaux_itoa2(value, buffer); current_mrb_finish(mrb); mrb_value result = mrb_str_new_lit(mrb, ""); result = mrb_str_cat_cstr(mrb, result, buffer); return mrb_obj_freeze(mrb, result); } mrb_value rb_KernAux_utoa8(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_UTOA8_BUFFER_SIZE]; current_mrb_start(mrb); kernaux_utoa8(value, buffer); current_mrb_finish(mrb); mrb_value result = mrb_str_new_lit(mrb, ""); result = mrb_str_cat_cstr(mrb, result, buffer); return mrb_obj_freeze(mrb, result); } mrb_value rb_KernAux_itoa8(mrb_state *mrb, mrb_value self) { mrb_int value = 0; mrb_get_args(mrb, "i", &value); char buffer[KERNAUX_ITOA8_BUFFER_SIZE]; current_mrb_start(mrb); kernaux_itoa8(value, buffer); current_mrb_finish(mrb); mrb_value result = mrb_str_new_lit(mrb, ""); result = mrb_str_cat_cstr(mrb, result, buffer); return mrb_obj_freeze(mrb, result); } 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); return mrb_obj_freeze(mrb, result); } 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); return mrb_obj_freeze(mrb, result); } 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); return mrb_obj_freeze(mrb, result); } 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); return mrb_obj_freeze(mrb, 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); } } #endif // KERNAUX_VERSION_WITH_NTOA