Skip to content

Commit eda3415

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

5 files changed

Lines changed: 53 additions & 19 deletions

File tree

common.mk

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

depend

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17896,6 +17896,7 @@ string.$(OBJEXT): {$(VPATH)}rubyparser.h
1789617896
string.$(OBJEXT): {$(VPATH)}shape.h
1789717897
string.$(OBJEXT): {$(VPATH)}st.h
1789817898
string.$(OBJEXT): {$(VPATH)}string.c
17899+
string.$(OBJEXT): {$(VPATH)}string.rbinc
1789917900
string.$(OBJEXT): {$(VPATH)}subst.h
1790017901
string.$(OBJEXT): {$(VPATH)}thread.h
1790117902
string.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h

inits.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@ rb_call_builtin_inits(void)
106106
BUILTIN(array);
107107
BUILTIN(hash);
108108
BUILTIN(symbol);
109+
BUILTIN(string);
109110
BUILTIN(timev);
110111
BUILTIN(thread_sync);
111112
BUILTIN(nilclass);

string.c

Lines changed: 18 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);
@@ -12905,7 +12903,6 @@ Init_String(void)
1290512903

1290612904
rb_include_module(rb_cString, rb_mComparable);
1290712905
rb_define_alloc_func(rb_cString, empty_str_alloc);
12908-
rb_define_singleton_method(rb_cString, "new", rb_str_s_new, -1);
1290912906
rb_define_singleton_method(rb_cString, "try_convert", rb_str_s_try_convert, 1);
1291012907
rb_define_method(rb_cString, "initialize", rb_str_init, -1);
1291112908
rb_define_method(rb_cString, "replace", rb_str_replace, 1);
@@ -13107,3 +13104,5 @@ Init_String(void)
1310713104
rb_define_method(rb_cSymbol, "encoding", sym_encoding, 0);
1310813105
}
1310913106

13107+
#include "string.rbinc"
13108+

string.rb

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
class String
2+
# :nodoc:
3+
def self._new(orig = (no_str = true; nil),
4+
encoding: (no_encoding = true; nil),
5+
capacity: (no_capacity = true; nil))
6+
7+
Primitive.rb_str_s_new(orig, no_str, encoding, no_encoding, capacity, no_capacity)
8+
end
9+
private_class_method :_new
10+
11+
# call-seq:
12+
# String.new(string = ''.encode(Encoding::ASCII_8BIT), **options) -> new_string
13+
#
14+
# :include: doc/string/new.rdoc
15+
#
16+
def self.new(...)
17+
# If the receiver isn't a String, jbb
18+
if Primitive.mandatory_only?
19+
if String.equal?(self)
20+
Primitive.rb_str_s_new_empty
21+
else
22+
super
23+
end
24+
else
25+
if String.equal?(self)
26+
_new(...)
27+
else
28+
super
29+
end
30+
end
31+
end
32+
end

0 commit comments

Comments
 (0)