Skip to content

Write a byte escape in upper case hex, as CRuby does - #7145

Merged
matz merged 2 commits into
mruby:masterfrom
takumin:inspect-hex-escape-uppercase
Aug 14, 2026
Merged

Write a byte escape in upper case hex, as CRuby does#7145
matz merged 2 commits into
mruby:masterfrom
takumin:inspect-hex-escape-uppercase

Conversation

@takumin

@takumin takumin commented Aug 14, 2026

Copy link
Copy Markdown
Contributor

String#inspect and String#dump write a byte that spells no character as \xNN, and mruby spells the two digits in lower case where CRuby spells them in upper case:

171.chr.inspect  #=> "\"\\xAB\"" in CRuby, "\"\\xab\"" in mruby
"る".dump        #=> "\"\\xE3\\x82\\x8B\"" in CRuby, lower case in mruby

str_escape() takes the two digits from mrb_digitmap, the table Integer#to_s reads a number through. Lower case is right for that table, since CRuby spells a number in lower case as well, so the escape gets a table of its own rather than the shared one moving under both readers.

What moves with it

Everything that prints through str_escape(): String#inspect, String#dump, Symbol#inspect of a name that has to be quoted, and the %! conversions of mrb_vformat(), which is what the debugger's p prints through.

What stays

mrb_ptr_to_str() keeps mrb_digitmap, since CRuby writes the address in #<Object:0x...> in lower case too. %X in mruby-sprintf upper cases its own output through toupper() and never reads the table.

Tests

The first commit moves every expectation that pinned the lower case spelling, and gives String#inspect a case of a single byte above ASCII, which it had none of. It fails without the second.

Five places held such an expectation: core String#inspect and mrb_vformat, mruby-string-ext's String#dump and its inspect of a byte-read string, mruby-encoding's Integer#chr above ASCII, and mruby-bin-debugger's bintest for p.

Verification

At the tip, the full suite is green on ci/gcc-clang in full, which is full-debug, bintest, cxx_abi and the default gembox build, and on the plain host build. 0 failures, 0 crashes. The bintest run is included, since the debugger's p prints through this escape.

Summary by CodeRabbit

  • Bug Fixes
    • Updated string inspection, dumping, and formatting to use uppercase hexadecimal escapes, such as \xAB, for non-printable and binary characters.
    • Standardized escape output across regular, formatted, UTF-8, and non-UTF-8 strings.

`String#inspect` and `String#dump` write a byte that spells no character
as `\xNN`, and mruby spells the two digits in lower case where CRuby
spells them in upper case:

```ruby
171.chr.inspect  #=> "\"\\xAB\"" in CRuby, "\"\\xab\"" in mruby
"る".dump        #=> "\"\\xE3\\x82\\x8B\"" in CRuby, lower case here
```

Move the expectations that pinned the lower case spelling, and give
`String#inspect` a case of a single byte above ASCII, which it had none
of. `mrb_vformat`'s `%!l` and the debugger's `p` print through the same
escape, so their expectations move with it.
`str_escape()` spelled the two digits of a `\xNN` escape out of
`mrb_digitmap`, which is lower case because `Integer#to_s` reads a
number through it and CRuby spells that in lower case. CRuby spells the
escape itself in upper case, so the two cannot share one table.

Give the escape a table of its own. `mrb_ptr_to_str()` stays on
`mrb_digitmap`, since CRuby writes the address in `#<Object:0x...>` in
lower case as well.

`String#inspect`, `String#dump`, `Symbol#inspect` of a name that has to
be quoted, and the `%!` conversions of `mrb_vformat()` all print through
`str_escape()`, so they change together.
@coderabbitai

coderabbitai Bot commented Aug 14, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 9574dbfb-9a44-4c29-92a4-083c63a0a3d5

📥 Commits

Reviewing files that changed from the base of the PR and between 7fcad02 and 6c1cd92.

📒 Files selected for processing (6)
  • mrbgems/mruby-bin-debugger/bintest/print.rb
  • mrbgems/mruby-encoding/test/numeric.rb
  • mrbgems/mruby-string-ext/test/string.rb
  • src/string.c
  • test/t/string.rb
  • test/t/vformat.rb

📝 Walkthrough

Walkthrough

String escape generation now uses uppercase hexadecimal digits for \xNN sequences. Related debugger, encoding, string-extension, string inspection, and formatting tests now expect the uppercase output.

Changes

String escape formatting

Layer / File(s) Summary
Uppercase escape generation
src/string.c
str_escape now uses a dedicated uppercase hexadecimal map for byte escape output.
Escape output test updates
mrbgems/mruby-bin-debugger/bintest/print.rb, mrbgems/mruby-encoding/test/numeric.rb, mrbgems/mruby-string-ext/test/string.rb, test/t/string.rb, test/t/vformat.rb
Tests now expect uppercase hexadecimal digits in string dumps, inspections, debugger output, and formatted strings.

Estimated code review effort: 1 (Trivial) | ~5 minutes

Merge Risk: ⚪ Minimal · up to 6c1cd

This PR changes byte escapes from lowercase to uppercase hexadecimal to match CRuby and updates the affected tests; no actionable merge-blocking risk remains after normal checks and review.

Possibly related PRs

  • mruby/mruby#7081: Both changes modify str_escape for binary-string escaping, but address different behavior.
  • mruby/mruby#7083: Both changes modify str_escape and related String#inspect tests, but address different escaping behavior.
  • mruby/mruby#7131: Both changes modify str_escape string escaping behavior.

Suggested reviewers: matz

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main change: producing byte escapes with uppercase hexadecimal digits to match CRuby.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@matz
matz merged commit 2c249af into mruby:master Aug 14, 2026
21 checks passed
@takumin
takumin deleted the inspect-hex-escape-uppercase branch August 14, 2026 05:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants