Skip to content

Commit bcf6547

Browse files
tenderlovejhawthorn
andcommitted
implement String.new in Ruby
Co-authored-by: jhawthorn <john@hawthorn.email>
1 parent bb75c28 commit bcf6547

4 files changed

Lines changed: 49 additions & 19 deletions

File tree

common.mk

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1201,6 +1201,7 @@ BUILTIN_RB_SRCS = \
12011201
$(srcdir)/ractor.rb \
12021202
$(srcdir)/string.rb \
12031203
$(srcdir)/symbol.rb \
1204+
$(srcdir)/string.rb \
12041205
$(srcdir)/timev.rb \
12051206
$(srcdir)/thread_sync.rb \
12061207
$(srcdir)/nilclass.rb \

inits.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,7 @@ rb_call_builtin_inits(void)
107107
BUILTIN(hash);
108108
BUILTIN(string);
109109
BUILTIN(symbol);
110+
BUILTIN(string);
110111
BUILTIN(timev);
111112
BUILTIN(thread_sync);
112113
BUILTIN(nilclass);

string.c

Lines changed: 16 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@
5050
#include "shape.h"
5151
#include "vm_sync.h"
5252
#include "ruby/internal/attr/nonstring.h"
53+
#include "builtin.h"
5354

5455
#if defined HAVE_CRYPT_R
5556
# if defined HAVE_CRYPT_H
@@ -2142,29 +2143,26 @@ rb_str_init(int argc, VALUE *argv, VALUE str)
21422143
return str;
21432144
}
21442145

2145-
/* :nodoc: */
2146+
/* String.new fast path: no positional argument and no keywords.
2147+
* Returns the same empty, embedded, ASCII-8BIT string that String's alloc
2148+
* func produces (klass is always rb_cString here; the Ruby-side dispatch
2149+
* routes subclasses through Class#new). */
21462150
static VALUE
2147-
rb_str_s_new(int argc, VALUE *argv, VALUE klass)
2151+
rb_str_s_new_empty(rb_execution_context_t *ec, VALUE klass)
21482152
{
2149-
if (klass != rb_cString) {
2150-
return rb_class_new_instance_pass_kw(argc, argv, klass);
2151-
}
2153+
return empty_str_alloc(klass);
2154+
}
21522155

2153-
static ID keyword_ids[2];
2154-
VALUE orig, opt, encoding = Qnil, capacity = Qnil;
2155-
VALUE kwargs[2];
2156+
/* :nodoc: */
2157+
static VALUE
2158+
rb_str_s_new(struct rb_execution_context_struct *ec, VALUE klass, VALUE orig, VALUE no_str, VALUE encoding, VALUE no_encoding, VALUE capacity, VALUE no_capacity)
2159+
{
21562160
rb_encoding *enc = NULL;
2161+
int n = 0;
21572162

2158-
int n = rb_scan_args(argc, argv, "01:", &orig, &opt);
2159-
if (NIL_P(opt)) {
2160-
return rb_class_new_instance_pass_kw(argc, argv, klass);
2161-
}
2162-
2163-
keyword_ids[0] = rb_id_encoding();
2164-
CONST_ID(keyword_ids[1], "capacity");
2165-
rb_get_kwargs(opt, keyword_ids, 0, 2, kwargs);
2166-
encoding = kwargs[0];
2167-
capacity = kwargs[1];
2163+
if (RTEST(no_encoding)) encoding = Qundef;
2164+
if (RTEST(no_capacity)) capacity = Qundef;
2165+
if (!RTEST(no_str)) n = 1;
21682166

21692167
if (n == 1) {
21702168
orig = StringValue(orig);
@@ -12887,7 +12885,6 @@ Init_String(void)
1288712885

1288812886
rb_include_module(rb_cString, rb_mComparable);
1288912887
rb_define_alloc_func(rb_cString, empty_str_alloc);
12890-
rb_define_singleton_method(rb_cString, "new", rb_str_s_new, -1);
1289112888
rb_define_singleton_method(rb_cString, "try_convert", rb_str_s_try_convert, 1);
1289212889
rb_define_method(rb_cString, "initialize", rb_str_init, -1);
1289312890
rb_define_method(rb_cString, "replace", rb_str_replace, 1);

string.rb

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,4 +22,35 @@ def ascii_only?
2222
Primitive.attr! :leaf
2323
Primitive.cexpr! 'rb_str_is_ascii_only_p(self)'
2424
end
25+
26+
# :nodoc:
27+
def self._new(orig = (no_str = true; nil),
28+
encoding: (no_encoding = true; nil),
29+
capacity: (no_capacity = true; nil))
30+
31+
Primitive.rb_str_s_new(orig, no_str, encoding, no_encoding, capacity, no_capacity)
32+
end
33+
private_class_method :_new
34+
35+
# call-seq:
36+
# String.new(string = ''.encode(Encoding::ASCII_8BIT), **options) -> new_string
37+
#
38+
# :include: doc/string/new.rdoc
39+
#
40+
def self.new(...)
41+
# If the receiver isn't a String, jbb
42+
if Primitive.mandatory_only?
43+
if String.equal?(self)
44+
Primitive.rb_str_s_new_empty
45+
else
46+
super
47+
end
48+
else
49+
if String.equal?(self)
50+
_new(...)
51+
else
52+
super
53+
end
54+
end
55+
end
2556
end

0 commit comments

Comments
 (0)