# HG changeset patch # User John W. Eaton # Date 1322033737 18000 # Node ID 0c38351a4dde73c3100ceadcf10fa6c636d5f2ce # Parent e86bbb00757128d36316c95c7c48c97653121631 subsref, subsasgn: allow empty subscript structs * ov.cc (decode_subscripts): Move here. * utils.cc: From here. * utils.h: Delete decl. * ov.cc (decode_subscripts): Empty type_string and idx and return early if map is empty with fields type and subs. (Fsubsref): Return VAL if subscript struct is empty. (Fsubsasgn): Return RHS if subscript struct is empty. diff --git a/src/ov.cc b/src/ov.cc --- a/src/ov.cc +++ b/src/ov.cc @@ -2714,6 +2714,83 @@ %!assert (sizeof ({"foo", "bar", "baaz"}), 10) */ +static void +decode_subscripts (const char* name, const octave_value& arg, + std::string& type_string, + std::list& idx) +{ + const octave_map m = arg.map_value (); + + if (! error_state + && m.nfields () == 2 && m.contains ("type") && m.contains ("subs")) + { + octave_idx_type nel = m.numel (); + + type_string = std::string (nel, '\0'); + idx = std::list (); + + if (nel == 0) + return; + + const Cell type = m.contents ("type"); + const Cell subs = m.contents ("subs"); + + for (int k = 0; k < nel; k++) + { + std::string item = type(k).string_value (); + + if (! error_state) + { + if (item == "{}") + type_string[k] = '{'; + else if (item == "()") + type_string[k] = '('; + else if (item == ".") + type_string[k] = '.'; + else + { + error("%s: invalid indexing type `%s'", name, item.c_str ()); + return; + } + } + else + { + error ("%s: expecting type(%d) to be a character string", + name, k+1); + return; + } + + octave_value_list idx_item; + + if (subs(k).is_string ()) + idx_item(0) = subs(k); + else if (subs(k).is_cell ()) + { + Cell subs_cell = subs(k).cell_value (); + + for (int n = 0; n < subs_cell.length (); n++) + { + if (subs_cell(n).is_string () + && subs_cell(n).string_value () == ":") + idx_item(n) = octave_value(octave_value::magic_colon_t); + else + idx_item(n) = subs_cell(n); + } + } + else + { + error ("%s: expecting subs(%d) to be a character string or cell array", + name, k+1); + return; + } + + idx.push_back (idx_item); + } + } + else + error ("%s: second argument must be a structure with fields `type' and `subs'", name); +} + DEFUN (subsref, args, nargout, "-*- texinfo -*-\n\ @deftypefn {Built-in Function} {} subsref (@var{val}, @var{idx})\n\ @@ -2746,6 +2823,9 @@ \n\ @noindent\n\ Note that this is the same as writing @code{val(:,1:2)}.\n\ +\n\ +If @var{idx} is an empty structure array with fields @samp{type}\n\ +and @samp{subs}, return @var{val}.\n\ @seealso{subsasgn, substruct}\n\ @end deftypefn") { @@ -2760,8 +2840,12 @@ if (! error_state) { - octave_value tmp = args(0); - retval = tmp.subsref (type, idx, nargout); + octave_value arg0 = args(0); + + if (type.empty ()) + retval = arg0; + else + retval = arg0.subsref (type, idx, nargout); } } else @@ -2798,6 +2882,9 @@ @end example\n\ \n\ Note that this is the same as writing @code{val(:,1:2) = 0}.\n\ +\n\ +If @var{idx} is an empty structure array with fields @samp{type}\n\ +and @samp{subs}, return @var{rhs}.\n\ @seealso{subsref, substruct}\n\ @end deftypefn") { @@ -2810,12 +2897,24 @@ decode_subscripts ("subsasgn", args(1), type, idx); - octave_value arg0 = args(0); - - arg0.make_unique (); - if (! error_state) - retval = arg0.subsasgn (type, idx, args(2)); + { + if (type.empty ()) + { + // Regularize a null matrix if stored into a variable. + + retval = args(2).storable_value (); + } + else + { + octave_value arg0 = args(0); + + arg0.make_unique (); + + if (! error_state) + retval= arg0.subsasgn (type, idx, args(2)); + } + } } else print_usage (); diff --git a/src/utils.cc b/src/utils.cc --- a/src/utils.cc +++ b/src/utils.cc @@ -1162,79 +1162,6 @@ return retval; } -void -decode_subscripts (const char* name, const octave_value& arg, - std::string& type_string, - std::list& idx) -{ - const octave_map m = arg.map_value (); - - if (! error_state - && m.nfields () == 2 && m.contains ("type") && m.contains ("subs")) - { - const Cell type = m.contents ("type"); - const Cell subs = m.contents ("subs"); - - octave_idx_type nel = type.numel (); - - type_string = std::string (nel, '\0'); - - for (int k = 0; k < nel; k++) - { - std::string item = type(k).string_value (); - - if (! error_state) - { - if (item == "{}") - type_string[k] = '{'; - else if (item == "()") - type_string[k] = '('; - else if (item == ".") - type_string[k] = '.'; - else - { - error("%s: invalid indexing type `%s'", name, item.c_str ()); - return; - } - } - else - { - error ("%s: expecting type(%d) to be a character string", - name, k+1); - return; - } - - octave_value_list idx_item; - - if (subs(k).is_string ()) - idx_item(0) = subs(k); - else if (subs(k).is_cell ()) - { - Cell subs_cell = subs(k).cell_value (); - - for (int n = 0; n < subs_cell.length (); n++) - { - if (subs_cell(n).is_string () - && subs_cell(n).string_value () == ":") - idx_item(n) = octave_value(octave_value::magic_colon_t); - else - idx_item(n) = subs_cell(n); - } - } - else - { - error ("%s: expecting subs(%d) to be a character string or cell array", - name, k+1); - return; - } - - idx.push_back (idx_item); - } - } - else - error ("%s: second argument must be a structure with fields `type' and `subs'", name); -} - Matrix identity_matrix (octave_idx_type nr, octave_idx_type nc) { diff --git a/src/utils.h b/src/utils.h --- a/src/utils.h +++ b/src/utils.h @@ -97,11 +97,6 @@ extern OCTINTERP_API octave_idx_type dims_to_numel (const dim_vector& dims, const octave_value_list& idx); -extern OCTINTERP_API void -decode_subscripts (const char* name, const octave_value& arg, - std::string& type_string, - std::list& idx); - extern OCTINTERP_API Matrix identity_matrix (octave_idx_type nr, octave_idx_type nc);