Skip to content

Commit

Permalink
[Truffle] Pulled in String#index from Rubinius.
Browse files Browse the repository at this point in the history
  • Loading branch information
nirvdrum committed Mar 10, 2015
1 parent bd795b2 commit 68be707
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 15 deletions.
12 changes: 0 additions & 12 deletions spec/truffle/tags/core/string/index_tags.txt
Original file line number Diff line number Diff line change
@@ -1,9 +1,5 @@
fails:String#index raises a TypeError if passed nil
fails:String#index raises a TypeError if passed a boolean
fails:String#index raises a TypeError if passed a Symbol
fails:String#index calls #to_str to convert the first argument
fails:String#index calls #to_int to convert the second argument
fails:String#index raises a TypeError if passed a Fixnum
fails:String#index with String behaves the same as String#index(char) for one-character strings
fails:String#index with String returns the index of the first occurrence of the given substring
fails:String#index with String doesn't set $~
Expand All @@ -14,17 +10,9 @@ fails:String#index with String returns nil if the substring isn't found
fails:String#index with String returns the character index of a multibyte character
fails:String#index with String returns the character index after offset
fails:String#index with String returns the character index after a partial first match
fails:String#index with String raises an Encoding::CompatibilityError if the encodings are incompatible
fails:String#index with Regexp behaves the same as String#index(string) for escaped string regexps
fails:String#index with Regexp returns the index of the first match of regexp
fails:String#index with Regexp sets $~ to MatchData of match and nil when there's none
fails:String#index with Regexp starts the search at the given offset
fails:String#index with Regexp starts the search at offset + self.length if offset is negative
fails:String#index with Regexp returns nil if the substring isn't found
fails:String#index with Regexp returns nil if the Regexp matches the empty string and the offset is out of range
fails:String#index with Regexp supports \G which matches at the given start offset
fails:String#index with Regexp converts start_offset to an integer via to_int
fails:String#index with Regexp returns the character index of a multibyte character
fails:String#index with Regexp returns the character index after offset
fails:String#index with Regexp treats the offset as a character index
fails:String#index with Regexp raises an Encoding::CompatibilityError if the encodings are incompatible
Original file line number Diff line number Diff line change
Expand Up @@ -363,11 +363,22 @@ public StringCharacterByteIndexPrimitiveNode(StringCharacterByteIndexPrimitiveNo
super(prev);
}

@Specialization
public Object stringCharacterByteIndex(RubyString string, Object index, Object start) {
throw new UnsupportedOperationException("string_character_byte_index");
@Specialization(guards = "isSingleByteOptimizable")
public int stringCharacterByteIndex(RubyString string, int index, int start) {
return start + index;
}

@Specialization(guards = "!isSingleByteOptimizable")
public int stringCharacterByteIndexMultiByteEncoding(RubyString string, int index, int start) {
final ByteList bytes = string.getBytes();

return StringSupport.nth(bytes.getEncoding(), bytes.getUnsafeBytes(), bytes.getBegin(),
bytes.getBegin() + bytes.getRealSize(), start + index);
}

public static boolean isSingleByteOptimizable(RubyString string) {
return StringSupport.isSingleByteOptimizable(string, string.getBytes().getEncoding());
}
}

@RubiniusPrimitive(name = "string_byte_character_index", needsSelf = false)
Expand Down
35 changes: 35 additions & 0 deletions truffle/src/main/ruby/core/rubinius/common/string.rb
Original file line number Diff line number Diff line change
Expand Up @@ -699,6 +699,41 @@ def rjust(width, padding=" ")
str.force_encoding enc
end

def index(str, start=undefined)
if undefined.equal?(start)
start = 0
else
start = Rubinius::Type.coerce_to start, Fixnum, :to_int

start += size if start < 0
return if start < 0 or start > size
end

if str.kind_of? Regexp
Rubinius::Type.compatible_encoding self, str

m = Rubinius::Mirror.reflect self
start = m.character_to_byte_index start
if match = str.match_from(self, start)
Regexp.last_match = match
return match.begin(0)
else
Regexp.last_match = nil
return
end
end

str = StringValue(str)
return start if str == ""

Rubinius::Type.compatible_encoding self, str

return if str.size > size

m = Rubinius::Mirror.reflect self
m.character_index str, start
end

def upto(stop, exclusive=false)
return to_enum :upto, stop, exclusive unless block_given?
stop = StringValue(stop)
Expand Down

0 comments on commit 68be707

Please sign in to comment.