Skip to content

Commit 68be707

Browse files
committed
[Truffle] Pulled in String#index from Rubinius.
1 parent bd795b2 commit 68be707

File tree

3 files changed

+49
-15
lines changed

3 files changed

+49
-15
lines changed
Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,5 @@
1-
fails:String#index raises a TypeError if passed nil
2-
fails:String#index raises a TypeError if passed a boolean
3-
fails:String#index raises a TypeError if passed a Symbol
41
fails:String#index calls #to_str to convert the first argument
52
fails:String#index calls #to_int to convert the second argument
6-
fails:String#index raises a TypeError if passed a Fixnum
73
fails:String#index with String behaves the same as String#index(char) for one-character strings
84
fails:String#index with String returns the index of the first occurrence of the given substring
95
fails:String#index with String doesn't set $~
@@ -14,17 +10,9 @@ fails:String#index with String returns nil if the substring isn't found
1410
fails:String#index with String returns the character index of a multibyte character
1511
fails:String#index with String returns the character index after offset
1612
fails:String#index with String returns the character index after a partial first match
17-
fails:String#index with String raises an Encoding::CompatibilityError if the encodings are incompatible
1813
fails:String#index with Regexp behaves the same as String#index(string) for escaped string regexps
19-
fails:String#index with Regexp returns the index of the first match of regexp
20-
fails:String#index with Regexp sets $~ to MatchData of match and nil when there's none
21-
fails:String#index with Regexp starts the search at the given offset
2214
fails:String#index with Regexp starts the search at offset + self.length if offset is negative
23-
fails:String#index with Regexp returns nil if the substring isn't found
24-
fails:String#index with Regexp returns nil if the Regexp matches the empty string and the offset is out of range
2515
fails:String#index with Regexp supports \G which matches at the given start offset
26-
fails:String#index with Regexp converts start_offset to an integer via to_int
2716
fails:String#index with Regexp returns the character index of a multibyte character
2817
fails:String#index with Regexp returns the character index after offset
2918
fails:String#index with Regexp treats the offset as a character index
30-
fails:String#index with Regexp raises an Encoding::CompatibilityError if the encodings are incompatible

truffle/src/main/java/org/jruby/truffle/nodes/rubinius/StringPrimitiveNodes.java

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -363,11 +363,22 @@ public StringCharacterByteIndexPrimitiveNode(StringCharacterByteIndexPrimitiveNo
363363
super(prev);
364364
}
365365

366-
@Specialization
367-
public Object stringCharacterByteIndex(RubyString string, Object index, Object start) {
368-
throw new UnsupportedOperationException("string_character_byte_index");
366+
@Specialization(guards = "isSingleByteOptimizable")
367+
public int stringCharacterByteIndex(RubyString string, int index, int start) {
368+
return start + index;
369+
}
370+
371+
@Specialization(guards = "!isSingleByteOptimizable")
372+
public int stringCharacterByteIndexMultiByteEncoding(RubyString string, int index, int start) {
373+
final ByteList bytes = string.getBytes();
374+
375+
return StringSupport.nth(bytes.getEncoding(), bytes.getUnsafeBytes(), bytes.getBegin(),
376+
bytes.getBegin() + bytes.getRealSize(), start + index);
369377
}
370378

379+
public static boolean isSingleByteOptimizable(RubyString string) {
380+
return StringSupport.isSingleByteOptimizable(string, string.getBytes().getEncoding());
381+
}
371382
}
372383

373384
@RubiniusPrimitive(name = "string_byte_character_index", needsSelf = false)

truffle/src/main/ruby/core/rubinius/common/string.rb

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -699,6 +699,41 @@ def rjust(width, padding=" ")
699699
str.force_encoding enc
700700
end
701701

702+
def index(str, start=undefined)
703+
if undefined.equal?(start)
704+
start = 0
705+
else
706+
start = Rubinius::Type.coerce_to start, Fixnum, :to_int
707+
708+
start += size if start < 0
709+
return if start < 0 or start > size
710+
end
711+
712+
if str.kind_of? Regexp
713+
Rubinius::Type.compatible_encoding self, str
714+
715+
m = Rubinius::Mirror.reflect self
716+
start = m.character_to_byte_index start
717+
if match = str.match_from(self, start)
718+
Regexp.last_match = match
719+
return match.begin(0)
720+
else
721+
Regexp.last_match = nil
722+
return
723+
end
724+
end
725+
726+
str = StringValue(str)
727+
return start if str == ""
728+
729+
Rubinius::Type.compatible_encoding self, str
730+
731+
return if str.size > size
732+
733+
m = Rubinius::Mirror.reflect self
734+
m.character_index str, start
735+
end
736+
702737
def upto(stop, exclusive=false)
703738
return to_enum :upto, stop, exclusive unless block_given?
704739
stop = StringValue(stop)

0 commit comments

Comments
 (0)