string.h: name what makes a character index a byte index - #7178
Conversation
Nine places asked the same question of a string and spelled it out each time: whether its coderange stands at 7BIT, or its bytes are read as bytes. Both answers mean the same thing to the caller, which is that a character index into the string is already a byte index. `mrb_str_char_to_byte` returns the index it was handed, `mrb_str_byte_to_char` likewise, `mrb_str_check_byte_pos` has no boundary to check, and `mrb_str_rindex_m` hands the whole search to `mrb_str_byterindex_m`. `RSTR_SINGLE_BYTE_P` gives that question a name. It is derived from what the string carries rather than carried alongside it, so it is not the `MRB_STR_SINGLE_BYTE` flag coming back: nothing stores it and nothing has to keep it up to date. The expansion is what the call sites spelled, so nothing changes in what is generated.
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (3)
📝 WalkthroughWalkthroughThe change adds ChangesSingle-byte string handling
Estimated code review effort: 2 (Simple) | ~10 minutes Merge Risk: ⚪ Minimal · up to This change names an existing single-byte string condition and replaces equivalent inline checks without changing generated size or tested behavior; no actionable merge-blocking risk remains after normal checks and review. Possibly related PRs
Suggested reviewers: 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
Ten places ask the same question of a string and spell it out each time:
The two halves arrive from different sides, but they say one thing to every reader of them: a character index into this string is already a byte index.
mrb_str_char_to_byte()returns the index it was handed,mrb_str_byte_to_char()likewise,mrb_str_check_byte_pos()has no boundary left to check, andmrb_str_rindex_m()hands the whole search tomrb_str_byterindex_m().This PR gives that question a name.
What goes into
include/mruby/string.hIt sits next to
RSTR_BINARY_P, which is the other predicate derived from a field rather than read straight out of one.This is not
MRB_STR_SINGLE_BYTEcoming back. That was a stored flag, one bit a writer had to set and keep true; this is derived from what the string already carries, so nothing stores it and nothing can leave it stale.RSTR_CODERANGE()folds toMRB_STR_CODERANGE_7BITon a build withoutMRB_UTF8_STRING, where every byte is a character, so the predicate folds to a constant there as it did before.The call sites are all of them
Ten on master, and no eleventh:
and after, one definition and the same ten:
Eight were the positive form above. Two were the negation, and one of those spells the halves in the other order:
str_chars_ary()had!A && !Bwith the halves in the macro's order, so!(A || B)is what it spelled.mrb_str_chomp_bang()had!B && !A, and that is the one place where the macro asks for something other than what the source said.The one thing that changes in the object code
Nine call sites expand to the instructions they had.
mrb_str_chomp_bang()tests the two halves in the other order, master above and this branch below, frombintest:Same instructions, same count, the two tests swapped. Both are pure reads of one word already in a register, so neither order can raise, and the second test is reached only when the first says no in either order. That is the whole of the difference between master and this branch in the object code, over every build measured below.
Generated code
gcc 13.3.0 -O3, x86-64, against the same objects built from master..textofbin/mruby:build_config/default.rbfull-core,i686-linux-gnu-gccObjects differing, comparing
objdump -dover every.oin the build:build_config/default.rbThe one object is
src/string.o, and the swap above is what differs in it. A build that indexes by byte carries no coderange, soRSTR_SINGLE_BYTE_P()folds to true there and both orders fold with it:byte-stringanddefault.rbcome out identical to master, object by object.Testing
rake -m test, all green, 0 KO, 0 crash, 0 warnings, and the same counts as master:build_config/default.rbfull-core,i686-linux-gnu-gccenable_debugbuild_config/host-m32.rbneeds a multilib toolchain, so the 32-bit build above isfull-corewith the compiler set toi686-linux-gnu-gccinstead.No test accompanies the change. Nine call sites are the expression they were and the tenth is the same two tests in the other order, so no string answers anything different and there is nothing new to pin.
Not in this PR
The macro is put where the ten call sites already asked the question, and nowhere else: no path that walks a string gains a shortcut it did not have. The write side of these two fields is untouched, and so is what either field means.
Summary by CodeRabbit