Skip to content

Commit

Permalink
Add C API rb_enc_interned_str_cstr function
Browse files Browse the repository at this point in the history
Co-authored-by: Thomas Marshall <thomas.marshall@shopify.com>
  • Loading branch information
goyox86 and thomasmarshall committed Feb 2, 2024
1 parent 90bfaa0 commit 6e48998
Show file tree
Hide file tree
Showing 5 changed files with 38 additions and 1 deletion.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ Compatibility:
* Do not autosplat a proc that accepts a single positional argument and keywords (#3039, @andrykonchin).
* Support passing anonymous * and ** parameters as method call arguments (#3039, @andrykonchin).
* Handle either positional or keywords arguments by default in `Struct.new` (#3039, @rwstauner).
* Add `rb_enc_interned_str_cstr` function (#3408, @goyox86, @thomasmarshall).

Performance:

Expand Down
2 changes: 1 addition & 1 deletion lib/cext/ABI_check.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
10
11
6 changes: 6 additions & 0 deletions spec/ruby/optional/capi/ext/string_spec.c
Original file line number Diff line number Diff line change
Expand Up @@ -584,6 +584,11 @@ static VALUE string_spec_rb_str_unlocktmp(VALUE self, VALUE str) {
return rb_str_unlocktmp(str);
}

static VALUE string_spec_rb_enc_interned_str_cstr(VALUE self, VALUE str, VALUE enc) {
rb_encoding *e = rb_to_encoding(enc);
return rb_enc_interned_str_cstr(RSTRING_PTR(str), e);
}

void Init_string_spec(void) {
VALUE cls = rb_define_class("CApiStringSpecs", rb_cObject);
rb_define_method(cls, "rb_cstr2inum", string_spec_rb_cstr2inum, 2);
Expand Down Expand Up @@ -685,6 +690,7 @@ void Init_string_spec(void) {
rb_define_method(cls, "rb_str_catf", string_spec_rb_str_catf, 1);
rb_define_method(cls, "rb_str_locktmp", string_spec_rb_str_locktmp, 1);
rb_define_method(cls, "rb_str_unlocktmp", string_spec_rb_str_unlocktmp, 1);
rb_define_method(cls, "rb_enc_interned_str_cstr", string_spec_rb_enc_interned_str_cstr, 2);
}

#ifdef __cplusplus
Expand Down
25 changes: 25 additions & 0 deletions spec/ruby/optional/capi/string_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -1227,4 +1227,29 @@ def inspect
-> { @s.rb_str_unlocktmp("test") }.should raise_error(RuntimeError, 'temporal unlocking already unlocked string')
end
end

describe "rb_enc_interned_str_cstr" do
it "returns a frozen string" do
str = "hello"
val = @s.rb_enc_interned_str_cstr(str, Encoding::US_ASCII)

val.should.is_a?(String)
val.encoding.should == Encoding::US_ASCII
val.should.frozen?
end

it "returns the same frozen string" do
str = "hello"
result1 = @s.rb_enc_interned_str_cstr(str, Encoding::US_ASCII)
result2 = @s.rb_enc_interned_str_cstr(str, Encoding::US_ASCII)
result1.should.equal?(result2)
end

it "returns different frozen strings for different encodings" do
str = "hello"
result1 = @s.rb_enc_interned_str_cstr(str, Encoding::US_ASCII)
result2 = @s.rb_enc_interned_str_cstr(str, Encoding::UTF_8)
result1.should_not.equal?(result2)
end
end
end
5 changes: 5 additions & 0 deletions src/main/c/cext/string.c
Original file line number Diff line number Diff line change
Expand Up @@ -437,3 +437,8 @@ long rb_str_coderange_scan_restartable(const char *s, const char *e, rb_encoding
*cr = ENC_CODERANGE_VALID;
return e - s;
}

VALUE rb_enc_interned_str_cstr(const char *ptr, rb_encoding *enc) {
VALUE str = rb_enc_str_new_cstr(ptr, enc);
return rb_fstring(str);
}

0 comments on commit 6e48998

Please sign in to comment.