Skip to content

Commit

Permalink
Showing 2 changed files with 43 additions and 4 deletions.
Original file line number Diff line number Diff line change
@@ -287,9 +287,9 @@ public Rope concat(Rope left, Rope right, Encoding encoding,
depth);
}

private CodeRange commonCodeRange(CodeRange first, CodeRange second,
ConditionProfile sameCodeRangeProfile,
ConditionProfile brokenCodeRangeProfile) {
public static CodeRange commonCodeRange(CodeRange first, CodeRange second,
ConditionProfile sameCodeRangeProfile,
ConditionProfile brokenCodeRangeProfile) {
if (sameCodeRangeProfile.profile(first == second)) {
return first;
}
Original file line number Diff line number Diff line change
@@ -1505,7 +1505,7 @@ public Object spliceAppend(DynamicObject string, DynamicObject other, int splice
return string;
}

@Specialization(guards = { "!indexAtEitherBounds(string, spliceByteIndex)", "isRubyString(other)", "isRubyEncoding(rubyEncoding)" })
@Specialization(guards = { "!indexAtEitherBounds(string, spliceByteIndex)", "isRubyString(other)", "isRubyEncoding(rubyEncoding)", "!isRopeBuffer(string)" })
public DynamicObject splice(DynamicObject string, DynamicObject other, int spliceByteIndex, int byteCountToReplace, DynamicObject rubyEncoding) {
if (leftMakeSubstringNode == null) {
CompilerDirectives.transferToInterpreter();
@@ -1542,6 +1542,39 @@ public DynamicObject splice(DynamicObject string, DynamicObject other, int splic
return string;
}

@Specialization(guards = { "!indexAtEitherBounds(string, spliceByteIndex)", "isRubyString(other)", "isRubyEncoding(rubyEncoding)", "isRopeBuffer(string)" })
public DynamicObject spliceBuffer(DynamicObject string, DynamicObject other, int spliceByteIndex, int byteCountToReplace, DynamicObject rubyEncoding,
@Cached("createBinaryProfile()") ConditionProfile sameCodeRangeProfile,
@Cached("createBinaryProfile()") ConditionProfile brokenCodeRangeProfile) {
final Encoding encoding = EncodingOperations.getEncoding(rubyEncoding);
final RopeBuffer source = (RopeBuffer) rope(string);
final Rope insert = rope(other);
final int rightSideStartingIndex = spliceByteIndex + byteCountToReplace;

final ByteList byteList = new ByteList(source.byteLength() + insert.byteLength() - byteCountToReplace);

byteList.append(source.getByteList(), 0, spliceByteIndex);

for (int i = 0; i < insert.byteLength(); i++) {
byteList.append(insert.getBytes()[i]);
}

This comment has been minimized.

Copy link
@eregon

eregon Apr 13, 2016

Member

Why a loop instead of the 3-args version of append?

This comment has been minimized.

Copy link
@eregon

eregon Apr 13, 2016

Member

(Or append(ByteList moreBytes))

This comment has been minimized.

Copy link
@nirvdrum

nirvdrum Apr 13, 2016

Author Contributor

I was trying to account for non-zero starting offsets, but I messed that up anyway. getBytes should always return something starting at 0. There's no requirement that insert is a RopeBuffer -- converting it to a ByteList can be heavy, so we want to avoid that.

This comment has been minimized.

Copy link
@eregon

eregon Apr 13, 2016

Member

The API is so similar I believed it was ByteList 😄 (but nevertheless, less loops is good)


byteList.append(source.getByteList(), rightSideStartingIndex, source.byteLength() - rightSideStartingIndex);
byteList.setEncoding(encoding);

// NB: The character count is only accurate for single byte-optimizable strings. Rope buffers are not supported
// in general use. If we want to allow for wide characters we would need to recalculate the length doing a
// full scan.
final Rope buffer = new RopeBuffer(byteList,
RopeNodes.MakeConcatNode.commonCodeRange(source.getCodeRange(), insert.getCodeRange(), sameCodeRangeProfile, brokenCodeRangeProfile),
source.isSingleByteOptimizable() && insert.isSingleByteOptimizable(),
source.characterLength() + insert.characterLength() - byteCountToReplace);

StringOperations.setRope(string, buffer);

return string;
}

protected boolean indexAtStartBound(int index) {
return index == 0;
}
@@ -1557,6 +1590,12 @@ protected boolean indexAtEitherBounds(DynamicObject string, int index) {

return indexAtStartBound(index) || indexAtEndBound(string, index);
}

protected boolean isRopeBuffer(DynamicObject string) {
assert RubyGuards.isRubyString(string);

return rope(string) instanceof RopeBuffer;
}
}

@RubiniusPrimitive(name = "string_to_inum")

0 comments on commit c6c34bc

Please sign in to comment.