Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: rubinius/rubinius
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: cdc89a9712a9
Choose a base ref
...
head repository: rubinius/rubinius
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: db6c098d9300
Choose a head ref
  • 2 commits
  • 2 files changed
  • 1 contributor

Commits on Feb 16, 2016

  1. Copy the full SHA
    bdb5e33 View commit details
  2. Copy the full SHA
    db6c098 View commit details
Showing with 34 additions and 16 deletions.
  1. +8 −0 spec/core/mirror/string/byte_index_spec.rb
  2. +26 −16 vm/builtin/string.cpp
8 changes: 8 additions & 0 deletions spec/core/mirror/string/byte_index_spec.rb
Original file line number Diff line number Diff line change
@@ -15,10 +15,18 @@
lambda { string_mirror("abc").byte_index(-1) }.should raise_error(ArgumentError)
end

it "returns nil if index is greater than string's length" do
string_mirror("abc").byte_index(4).should be_nil
end

with_feature :encoding do
it "returns the byte index of a multibyte character index" do
string_mirror("あそこ").byte_index(1).should == 3
end

it "returns nil if index is greater than string's length" do
string_mirror("あそこ").byte_index(4).should be_nil
end
end
end

42 changes: 26 additions & 16 deletions vm/builtin/string.cpp
Original file line number Diff line number Diff line change
@@ -1723,30 +1723,40 @@ namespace rubinius {

return nil<Fixnum>();
} else if(Fixnum* index = try_as<Fixnum>(value)) {
OnigEncodingType* enc = encoding(state)->get_encoding();
uint8_t* p = byte_address();
uint8_t* e = p + total;
native_int i, k = index->to_native();
native_int k = index->to_native();

if(k < 0) {
Exception::argument_error(state, "character index is negative");
}

for(i = 0; i < k && p < e; i++) {
int c = Encoding::precise_mbclen(p, e, enc);

// If it's an invalid byte, just treat it as a single byte
if(!ONIGENC_MBCLEN_CHARFOUND_P(c)) {
++p;
if(byte_compatible_p(encoding_) || CBOOL(ascii_only_p(state))) {
if(k > total) {
return nil<Fixnum>();
} else {
p += ONIGENC_MBCLEN_CHARFOUND_LEN(c);
return index;
}
}

if(i < k) {
return nil<Fixnum>();
} else {
return Fixnum::from(p - byte_address());
OnigEncodingType* enc = encoding(state)->get_encoding();
uint8_t* p = byte_address();
uint8_t* e = p + total;
native_int i;

for(i = 0; i < k && p < e; i++) {
int c = Encoding::precise_mbclen(p, e, enc);

// If it's an invalid byte, just treat it as a single byte
if(!ONIGENC_MBCLEN_CHARFOUND_P(c)) {
++p;
} else {
p += ONIGENC_MBCLEN_CHARFOUND_LEN(c);
}
}

if(i < k) {
return nil<Fixnum>();
} else {
return Fixnum::from(p - byte_address());
}
}
}