Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor generator options parsing in mrb_yyjson.c #26

Merged
merged 1 commit into from
Jul 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 44 additions & 26 deletions src/mrb_yyjson.c
Original file line number Diff line number Diff line change
Expand Up @@ -192,38 +192,56 @@ yyjson_mut_val *mrb_value_to_json_value(mrb_state *mrb, mrb_value obj, yyjson_mu
return result;
}

mrb_value mrb_value_to_json_string(mrb_state *mrb, mrb_value self, generator_flag flg)
void parse_generator_opts(mrb_state *mrb, mrb_value opts, mrb_yyjson_generator_context *ctx)
{
if (!mrb_hash_p(opts))
{
return;
}

mrb_value max_nesting = mrb_hash_get(mrb, opts, mrb_symbol_value(mrb_intern_cstr(mrb, "max_nesting")));
if (mrb_test(max_nesting))
{
if (mrb_fixnum_p(max_nesting))
{
ctx->max_nesting = mrb_fixnum(max_nesting);
if (ctx->max_nesting < 0)
{
mrb_raise(mrb, E_ARGUMENT_ERROR, "max_nesting must be greater than or equal to 0");
}
}
else
{
mrb_raise(mrb, E_TYPE_ERROR, "max_nesting must be a Fixnum");
}
}

mrb_value pritty_print = mrb_hash_get(mrb, opts, mrb_symbol_value(mrb_intern_cstr(mrb, "pretty_print")));
if (mrb_test(pritty_print))
{
ctx->flg |= GENERATOR_FLAG_PRETTY;
}

mrb_value colorize = mrb_hash_get(mrb, opts, mrb_symbol_value(mrb_intern_cstr(mrb, "colorize")));
if (mrb_test(colorize))
{
ctx->flg |= GENERATOR_FLAG_COLOR;
}
}

mrb_value mrb_value_to_json_string(mrb_state *mrb, generator_flag default_flg)
{
mrb_value obj;
mrb_value opts = mrb_nil_value();
mrb_yyjson_generator_context ctx = {
.flg = flg,
.flg = default_flg,
.depth = 0,
.max_nesting = GENERATOR_DEFAULT_MAX_NESTING,
.exc = NULL,
};

mrb_get_args(mrb, "o|H", &obj, &opts);

if (mrb_hash_p(opts) && mrb_hash_size(mrb, opts) > 0)
{
mrb_value max_nesting = mrb_hash_get(mrb, opts, mrb_symbol_value(mrb_intern_cstr(mrb, "max_nesting")));
if (mrb_test(max_nesting))
{
if (mrb_fixnum_p(max_nesting))
{
ctx.max_nesting = mrb_fixnum(max_nesting);
if (ctx.max_nesting < 0)
{
mrb_raise(mrb, E_ARGUMENT_ERROR, "max_nesting must be greater than or equal to 0");
}
}
else
{
mrb_raise(mrb, E_TYPE_ERROR, "max_nesting must be a Fixnum");
}
}
}
parse_generator_opts(mrb, opts, &ctx);

yyjson_alc alc = {
.malloc = yyjson_mrb_malloc,
Expand All @@ -241,7 +259,7 @@ mrb_value mrb_value_to_json_string(mrb_state *mrb, mrb_value self, generator_fla
yyjson_mut_doc_set_root(doc, root);

yyjson_write_err err;
yyjson_write_flag write_flag = (flg & GENERATOR_FLAG_PRETTY) ? YYJSON_WRITE_PRETTY_TWO_SPACES : YYJSON_WRITE_NOFLAG;
yyjson_write_flag write_flag = (ctx.flg & GENERATOR_FLAG_PRETTY) ? YYJSON_WRITE_PRETTY_TWO_SPACES : YYJSON_WRITE_NOFLAG;
char *json = yyjson_mut_write_opts(doc, write_flag, &alc, NULL, &err);
if (json == NULL)
{
Expand All @@ -258,17 +276,17 @@ mrb_value mrb_value_to_json_string(mrb_state *mrb, mrb_value self, generator_fla

mrb_value mrb_yyjson_generate(mrb_state *mrb, mrb_value self)
{
return mrb_value_to_json_string(mrb, self, GENERATOR_FLAG_NONE);
return mrb_value_to_json_string(mrb, GENERATOR_FLAG_NONE);
}

mrb_value mrb_yyjson_pretty_generate(mrb_state *mrb, mrb_value self)
{
return mrb_value_to_json_string(mrb, self, GENERATOR_FLAG_PRETTY);
return mrb_value_to_json_string(mrb, GENERATOR_FLAG_PRETTY);
}

mrb_value mrb_yyjson_colorize_generate(mrb_state *mrb, mrb_value self)
{
return mrb_value_to_json_string(mrb, self, GENERATOR_FLAG_PRETTY | GENERATOR_FLAG_COLOR);
return mrb_value_to_json_string(mrb, GENERATOR_FLAG_PRETTY | GENERATOR_FLAG_COLOR);
}

typedef uint8_t parse_opts;
Expand Down
18 changes: 15 additions & 3 deletions test/json.rb
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,21 @@ def nesting_array(count)
assert_raise(TypeError, 'TypeError for max_nesting: true') do
JSON.generate(nesting_array(10), max_nesting: true)
end

assert_equal "\e[32m\"mruby-yyjson\"\e[m", JSON.generate('mruby-yyjson', colorize: :green), 'Colorize with :green'
got = JSON.generate({ 'mruby' => 'yyjson', foo: [%w[bar baz qux]] }, pretty_print: true)
assert_equal <<~JSON.chomp, got, 'Pretty print'
{
"mruby": "yyjson",
"foo": [
[
"bar",
"baz",
"qux"
]
]
}
JSON
end

assert('JSON.#parse') do
Expand Down Expand Up @@ -154,7 +169,6 @@ def to_io
end

assert('JSON.#colorize') do
# 各色に対するテストケース
assert_equal "\e[30mmruby-yyjson\e[m", JSON.colorize('mruby-yyjson', :black), 'Colorize with :black'
assert_equal "\e[31mmruby-yyjson\e[m", JSON.colorize('mruby-yyjson', :red), 'Colorize with :red'
assert_equal "\e[32mmruby-yyjson\e[m", JSON.colorize('mruby-yyjson', :green), 'Colorize with :green'
Expand All @@ -165,10 +179,8 @@ def to_io
assert_equal "\e[37mmruby-yyjson\e[m", JSON.colorize('mruby-yyjson', :white), 'Colorize with :white'
assert_equal "\e[90mmruby-yyjson\e[m", JSON.colorize('mruby-yyjson', :gray), 'Colorize with :gray'

# 無効な色が指定された場合
assert_raise(TypeError, 'Raise TypeError for unknown color') { JSON.colorize('mruby-yyjson', :unknown) }

# 特定の入力文字列に対するテスト
assert_equal "\e[32mHello, World!\e[m", JSON.colorize('Hello, World!', :green), 'Colorize specific string with :green'
assert_equal "\e[90mTest String\e[m", JSON.colorize('Test String', :gray), 'Colorize specific string with :gray'
end
Expand Down