# HG changeset patch # User John W. Eaton # Date 1322033737 18000 # Node ID 6ead4dc1ca5564c85dcc71d8df17593fd8f3e02f # Parent 9de488c6c59ca778c67f64631866aec0b6c29590 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 -r 9de488c6c59c -r 6ead4dc1ca55 src/ov.cc --- a/src/ov.cc Wed Nov 23 09:42:50 2011 -0800 +++ b/src/ov.cc Wed Nov 23 02:35:37 2011 -0500 @@ -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 (); @@ -2826,15 +2925,18 @@ /* %!test %! a = reshape ([1:25], 5,5); -%! idx1 = substruct ( "()", {3, 3}); -%! idx2 = substruct ( "()", {2:2:5, 2:2:5}); -%! idx3 = substruct ( "()", {":", [1,5]}); -%! assert (subsref (a, idx1), 13) -%! assert (subsref (a, idx2), [7 17; 9 19]) -%! assert (subsref (a, idx3), [1:5; 21:25]') +%! idx1 = substruct ("()", {3, 3}); +%! idx2 = substruct ("()", {2:2:5, 2:2:5}); +%! idx3 = substruct ("()", {":", [1,5]}); +%! idx4 = struct ("type", {}, "subs", {}); +%! assert (subsref (a, idx1), 13); +%! assert (subsref (a, idx2), [7 17; 9 19]); +%! assert (subsref (a, idx3), [1:5; 21:25]'); +%! assert (subsref (a, idx4), a); %! a = subsasgn (a, idx1, 0); %! a = subsasgn (a, idx2, 0); %! a = subsasgn (a, idx3, 0); +%!# a = subsasgn (a, idx4, 0); %! b = [0 6 11 16 0 %! 0 0 12 0 0 %! 0 8 0 18 0 @@ -2844,23 +2946,26 @@ %!test %! c = num2cell (reshape ([1:25],5,5)); -%! idx1 = substruct ( "{}", {3, 3}); -%! idx2 = substruct ( "()", {2:2:5, 2:2:5}); -%! idx3 = substruct ( "()", {":", [1,5]}); -%! idx2p = substruct ( "{}", {2:2:5, 2:2:5}); -%! idx3p = substruct ( "{}", {":", [1,5]}); -%! assert ({ subsref(c, idx1) }, {13}) -%! assert ({ subsref(c, idx2p) }, {7 9 17 19}) -%! assert ({ subsref(c, idx3p) }, num2cell ([1:5, 21:25])) +%! idx1 = substruct ("{}", {3, 3}); +%! idx2 = substruct ("()", {2:2:5, 2:2:5}); +%! idx3 = substruct ("()", {":", [1,5]}); +%! idx2p = substruct ("{}", {2:2:5, 2:2:5}); +%! idx3p = substruct ("{}", {":", [1,5]}); +%! idx4 = struct ("type", {}, "subs", {}); +%! assert ({ subsref(c, idx1) }, {13}); +%! assert ({ subsref(c, idx2p) }, {7 9 17 19}); +%! assert ({ subsref(c, idx3p) }, num2cell ([1:5, 21:25])); +%! assert (subsref(c, idx4), c); %! c = subsasgn (c, idx1, 0); %! c = subsasgn (c, idx2, 0); %! c = subsasgn (c, idx3, 0); +%!# c = subsasgn (c, idx4, 0); %! d = {0 6 11 16 0 %! 0 0 12 0 0 %! 0 8 0 18 0 %! 0 0 14 0 0 %! 0 10 15 20 0}; -%! assert (c,d); +%! assert (c, d); %!test %! s.a = "ohai"; @@ -2869,16 +2974,19 @@ %! idx1 = substruct (".", "a"); %! idx2 = substruct (".", "b"); %! idx3 = substruct (".", "c"); -%! assert (subsref (s, idx1), "ohai") -%! assert (subsref (s, idx2), "dere") -%! assert (subsref (s, idx3), 42) +%! idx4 = struct ("type", {}, "subs", {}); +%! assert (subsref (s, idx1), "ohai"); +%! assert (subsref (s, idx2), "dere"); +%! assert (subsref (s, idx3), 42); +%! assert (subsref (s, idx4), s); %! s = subsasgn (s, idx1, "Hello"); %! s = subsasgn (s, idx2, "There"); %! s = subsasgn (s, idx3, 163); +%!# s = subsasgn (s, idx4, 163); %! t.a = "Hello"; %! t.b = "There"; %! t.c = 163; -%! assert (s, t) +%! assert (s, t); */ diff -r 9de488c6c59c -r 6ead4dc1ca55 src/utils.cc --- a/src/utils.cc Wed Nov 23 09:42:50 2011 -0800 +++ b/src/utils.cc Wed Nov 23 02:35:37 2011 -0500 @@ -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 -r 9de488c6c59c -r 6ead4dc1ca55 src/utils.h --- a/src/utils.h Wed Nov 23 09:42:50 2011 -0800 +++ b/src/utils.h Wed Nov 23 02:35:37 2011 -0500 @@ -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);