diff --git a/CHANGELOG.md b/CHANGELOG.md index d7c885af02e1..af3ae69e55be 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,7 @@ Compatibility: * Add `MAJOR`, `MINOR`, `TEENY`, `PATCHLEVEL`, `RUBY_API_VERSION`, and `RUBY_PROGRAM_VERSION` to `RbConfig::CONFIG` (#3396, @rwstauner). * Set `RbConfig::CONFIG['archincludedir']` (#3396, @andrykonchin). * Support the index/length arguments for the string argument to `String#bytesplice` added in 3.3 (#3656, @rwstauner). +* Implement `rb_str_strlen()` (#3697, @Th3-M4jor). Performance: diff --git a/lib/cext/include/truffleruby/truffleruby-abi-version.h b/lib/cext/include/truffleruby/truffleruby-abi-version.h index edde108df446..e819cb98548c 100644 --- a/lib/cext/include/truffleruby/truffleruby-abi-version.h +++ b/lib/cext/include/truffleruby/truffleruby-abi-version.h @@ -20,6 +20,6 @@ // $RUBY_VERSION must be the same as TruffleRuby.LANGUAGE_VERSION. // $ABI_NUMBER starts at 1 and is incremented for every ABI-incompatible change. -#define TRUFFLERUBY_ABI_VERSION "3.2.4.3" +#define TRUFFLERUBY_ABI_VERSION "3.2.4.4" #endif diff --git a/spec/ruby/optional/capi/ext/string_spec.c b/spec/ruby/optional/capi/ext/string_spec.c index cec3f65f458b..94f412267ff7 100644 --- a/spec/ruby/optional/capi/ext/string_spec.c +++ b/spec/ruby/optional/capi/ext/string_spec.c @@ -117,6 +117,10 @@ VALUE string_spec_rb_str_cmp(VALUE self, VALUE str1, VALUE str2) { return INT2NUM(rb_str_cmp(str1, str2)); } +VALUE string_spec_rb_str_strlen(VALUE self, VALUE str) { + return LONG2NUM(rb_str_strlen(str)); +} + VALUE string_spec_rb_str_conv_enc(VALUE self, VALUE str, VALUE from, VALUE to) { rb_encoding* from_enc; rb_encoding* to_enc; @@ -600,6 +604,7 @@ void Init_string_spec(void) { rb_define_method(cls, "rb_str_cat_cstr", string_spec_rb_str_cat_cstr, 2); rb_define_method(cls, "rb_str_cat_cstr_constant", string_spec_rb_str_cat_cstr_constant, 1); rb_define_method(cls, "rb_str_cmp", string_spec_rb_str_cmp, 2); + rb_define_method(cls, "rb_str_strlen", string_spec_rb_str_strlen, 1); rb_define_method(cls, "rb_str_conv_enc", string_spec_rb_str_conv_enc, 3); rb_define_method(cls, "rb_str_conv_enc_opts", string_spec_rb_str_conv_enc_opts, 5); rb_define_method(cls, "rb_str_drop_bytes", string_spec_rb_str_drop_bytes, 2); diff --git a/spec/ruby/optional/capi/string_spec.rb b/spec/ruby/optional/capi/string_spec.rb index a8edf998b54b..d43dddeacf12 100644 --- a/spec/ruby/optional/capi/string_spec.rb +++ b/spec/ruby/optional/capi/string_spec.rb @@ -449,6 +449,20 @@ def inspect end end + describe "rb_str_strlen" do + it 'returns 0 as the length of an empty string' do + @s.rb_str_strlen('').should == 0 + end + + it 'returns the number of characters in a string' do + @s.rb_str_strlen('hello').should == 5 + end + + it 'returns the number of characters in a string with multi-byte characters' do + @s.rb_str_strlen('こんにちは').should == 5 + end + end + describe "rb_str_split" do it "splits strings over a splitter" do @s.rb_str_split("Hello,Goodbye").should == ["Hello", "Goodbye"] diff --git a/src/main/c/cext/string.c b/src/main/c/cext/string.c index a7d95cb7fd1d..96b49287ac39 100644 --- a/src/main/c/cext/string.c +++ b/src/main/c/cext/string.c @@ -204,6 +204,10 @@ int rb_str_cmp(VALUE a, VALUE b) { return polyglot_as_i32(RUBY_INVOKE_NO_WRAP(a, "<=>", b)); } +long rb_str_strlen(VALUE string) { + return polyglot_as_i64(RUBY_INVOKE_NO_WRAP(string, "size")); +} + VALUE rb_str_conv_enc(VALUE string, rb_encoding *from, rb_encoding *to) { return rb_str_conv_enc_opts(string, from, to, 0, Qnil); }