# HG changeset patch # User Michael Goffioul # Date 1369332753 14400 # Node ID 2823f8e3da771d159b5c2921ff2ebfc076f4577e # Parent 50b37deadb663a4ae70f1bc6bc5fb86e6e7ab29a Add multi-level index assignment for object array. * libinterp/octave-value/ov-classdef.h (cdef_object::is): New method. * libinterp/octave-value/ov-classdef.cc (cdef_object_array::subsasgn): Support multi-level index assignment. diff -r 50b37deadb66 -r 2823f8e3da77 libinterp/octave-value/ov-classdef.cc --- a/libinterp/octave-value/ov-classdef.cc Wed May 22 15:48:31 2013 -0400 +++ b/libinterp/octave-value/ov-classdef.cc Thu May 23 14:12:33 2013 -0400 @@ -1372,8 +1372,89 @@ } } else - ::error ("can't perform indexing operation on array of %s objects", - class_name ().c_str ()); + { + const octave_value_list& ival = idx.front (); + + bool is_scalar = true; + + Array iv (dim_vector (1, ival.length ())); + + for (int i = 0; ! error_state && i < ival.length (); i++) + { + iv(i) = ival(i).index_vector (); + + if (! error_state) + { + is_scalar = is_scalar && iv(i).is_scalar (); + + if (! is_scalar) + error ("subsasgn: invalid indexing for object array " + "assignment, the index must reference a single " + "object in the array."); + } + } + + if (! error_state) + { + Array a = array.index (iv, true); + + if (a.numel () != 1) + error ("subsasgn: invalid indexing for object array " + "assignment"); + + if (! error_state) + { + cdef_object obj = a(0); + + // If the object in 'a' is not valid, this means the index + // was out-of-bound and we need to create a new object. + + if (! obj.ok ()) + obj = get_class ().construct_object (octave_value_list ()); + + std::list next_idx (idx); + + next_idx.erase (next_idx.begin ()); + + octave_value tmp = obj.subsasgn (type.substr (1), next_idx, + rhs); + + if (! error_state) + { + cdef_object robj = to_cdef (tmp); + + if (robj.ok () + && ! robj.is_array () + && robj.get_class () == get_class ()) + { + // Small optimization, when dealing with handle + // objects, we don't need to re-assign the result + // of subsasgn back into the array. + + if (! robj.is (a(0))) + { + Array rhs_a (dim_vector (1, 1), + robj); + + octave_idx_type n = array.numel (); + + array.assign (iv, rhs_a); + + if (array.numel () > n) + fill_empty_values (); + } + + refcount++; + + retval = to_ov (cdef_object (this)); + } + else + error ("subasgn: invalid assignment into array of %s " + "objects", class_name ().c_str ()); + } + } + } + } break; default: diff -r 50b37deadb66 -r 2823f8e3da77 libinterp/octave-value/ov-classdef.h --- a/libinterp/octave-value/ov-classdef.h Wed May 22 15:48:31 2013 -0400 +++ b/libinterp/octave-value/ov-classdef.h Thu May 23 14:12:33 2013 -0400 @@ -289,6 +289,8 @@ void mark_as_constructed (const cdef_class& cls) { rep->mark_as_constructed (cls); } + bool is (const cdef_object& obj) const { return rep == obj.rep; } + protected: cdef_object_rep* get_rep (void) { return rep; }