Ruby STL container setting slices fixes

Setting an STL container wrapper slice better matches the way Ruby
arrays work. The behaviour is now the same as Ruby arrays. The only
exception is the default value used when expanding a container
cannot be nil as this is not a valid type/value for C++ container
elements.
This commit is contained in:
William S Fulton 2015-11-24 23:58:30 +00:00
commit bb2523a003
4 changed files with 68 additions and 22 deletions

View file

@ -72,13 +72,12 @@ ai = ArrayInt6.new()
compare_containers([0, 0, 0, 0, 0, 0], ai)
# Set slice
#newvals = [10, 20, 30, 40, 50, 60]
#ai[0..5] = newvals
#compare_containers(ai, newvals)
newvals = [10, 20, 30, 40, 50, 60]
ai[0, 6] = newvals
compare_containers(ai, newvals)
#newvals = [10000, 20000, 30000, 40000, 50000, 60000]
#ai[0..100] = newvals
#compare_containers(ai, newvals[0..100])
ai[-6, 6] = newvals
compare_containers(ai, newvals)
setslice_exception(ai, [1, 2, 3, 4, 5, 6, 7])
setslice_exception(ai, [1, 2, 3, 4, 5])

View file

@ -109,7 +109,7 @@ end
def compare_sequences(a, b)
if a != nil && b != nil
if a.size != b.size
failed(a, b, "different sizes")
failed(a, b, "different sizes")
end
for i in 0..a.size-1
failed(a, b, "elements are different") if a[i] != b[i]
@ -121,9 +121,26 @@ def compare_sequences(a, b)
end
end
def compare_expanded_sequences(a, b)
# a can contain nil elements which indicate additional elements
# b won't contain nil for additional elements
if a != nil && b != nil
if a.size != b.size
failed(a, b, "different sizes")
end
for i in 0..a.size-1
failed(a, b, "elements are different") if a[i] != b[i] && a[i] != nil
end
else
unless a == nil && b == nil
failed(a, b, "only one of the sequences is nil")
end
end
end
def check_slice(i, length)
aa = [0,1,2,3]
iv = IntVector.new([0,1,2,3])
aa = [1,2,3,4]
iv = IntVector.new(aa)
aa_slice = aa[i, length]
iv_slice = iv[i, length]
@ -135,8 +152,8 @@ def check_slice(i, length)
end
def check_range(i, j)
aa = [0,1,2,3]
iv = IntVector.new([0,1,2,3])
aa = [1,2,3,4]
iv = IntVector.new(aa)
aa_range = aa[i..j]
iv_range = iv[i..j]
@ -147,6 +164,21 @@ def check_range(i, j)
compare_sequences(aa_range, iv_range)
end
def set_slice(i, length, expect_nil_expanded_elements)
aa = [1,2,3,4]
iv = IntVector.new(aa)
aa_new = [8, 9]
iv_new = IntVector.new(aa_new)
aa[i, length] = aa_new
iv[i, length] = iv_new
if expect_nil_expanded_elements
compare_expanded_sequences(aa, iv)
else
compare_sequences(aa, iv)
end
end
for i in -5..5
for length in -5..5
check_slice(i, length)
@ -159,6 +191,18 @@ for i in -5..5
end
end
for i in -4..4
for length in 0..4
set_slice(i, length, false)
end
end
for i in [5, 6]
for length in 0..5
set_slice(i, length, true)
end
end
dv = DoubleVector.new(10)

View file

@ -101,7 +101,7 @@ namespace swig {
inline Sequence*
getslice(const Sequence* self, Difference i, Difference j) {
typename Sequence::size_type size = self->size();
typename Sequence::size_type ii = (i == size && j == size) ? i : swig::check_index(i, size);
typename Sequence::size_type ii = swig::check_index(i, size, (i == size && j == size));
typename Sequence::size_type jj = swig::slice_index(j, size);
if (jj > ii) {
@ -847,16 +847,20 @@ namespace swig
return swig::from< Sequence::value_type >( x );
}
VALUE __setitem__(difference_type i, difference_type j, const Sequence& v) throw (std::invalid_argument)
{
VALUE __setitem__(difference_type i, difference_type length, const Sequence& v) throw (std::invalid_argument) {
if ( j <= 0 ) return Qnil;
if ( length < 0 )
return Qnil;
std::size_t len = $self->size();
if ( i < 0 ) i = len - i;
j += i;
if ( static_cast<std::size_t>(j) >= len ) {
swig::resize( $self, j+1, *(v.begin()) );
j = len-1;
if ( i < 0 ) {
if ( i + static_cast<Sequence::difference_type>(len) < 0 )
return Qnil;
else
i = len + i;
}
Sequence::difference_type j = length + i;
if ( j > static_cast<Sequence::difference_type>(len) ) {
swig::resize( $self, j, *(v.begin()) );
}
VALUE r = Qnil;

View file

@ -41,7 +41,7 @@
getslice(const std::array<T, N>* self, Difference i, Difference j) {
using Sequence = std::array<T, N>;
typename Sequence::size_type size = self->size();
typename Sequence::size_type ii = (i == size && j == size) ? i : swig::check_index(i, size);
typename Sequence::size_type ii = swig::check_index(i, size, (i == size && j == size));
typename Sequence::size_type jj = swig::slice_index(j, size);
if (ii == 0 && jj == size) {
@ -61,7 +61,6 @@
typename Sequence::size_type ii = swig::check_index(i, size, true);
typename Sequence::size_type jj = swig::slice_index(j, size);
std::cout << "setslice " << v[0] << " " << v[1] << std::endl;
if (ii == 0 && jj == size) {
std::copy(v.begin(), v.end(), self->begin());
} else {