Mercurial > octave
changeset 28695:b3770a5f210d
improve validation of cell2struct fields argument (bug #58617)
* ov-struct.cc (invalid_cell2struct_fields_error): New function.
(get_cell2struct_fields): New function.
(Fcell2struct): Use get_cell2struct_fields to extract field names.
New tests for cell2struct.
author | John W. Eaton <jwe@octave.org> |
---|---|
date | Tue, 08 Sep 2020 13:42:23 -0400 |
parents | d91935bd879c |
children | 8d04d7c58d49 |
files | libinterp/octave-value/ov-struct.cc |
diffstat | 1 files changed, 50 insertions(+), 8 deletions(-) [+] |
line wrap: on
line diff
--- a/libinterp/octave-value/ov-struct.cc Tue Sep 08 08:41:57 2020 -0700 +++ b/libinterp/octave-value/ov-struct.cc Tue Sep 08 13:42:23 2020 -0400 @@ -1991,6 +1991,46 @@ %!assert (isfield (struct ("a", 1, "b", 2), {"a", "c"}), [true, false]) */ +OCTAVE_NORETURN +static void +invalid_cell2struct_fields_error (void) +{ + error ("cell2struct: FIELDS must be a cell array of strings or a scalar string"); +} + +static Array<std::string> +get_cell2struct_fields (const octave_value& arg) +{ + if (arg.is_string ()) + { + if (arg.rows () != 1) + invalid_cell2struct_fields_error (); + + return Array<std::string> (dim_vector (1, 1), arg.string_value ()); + } + + if (arg.iscell ()) + { + const Cell c = arg.cell_value (); + + Array<std::string> retval (c.dims ()); + + for (octave_idx_type i = 0; i < c.numel (); i++) + { + const octave_value val = c(i); + + if (! val.is_string () || val.rows () != 1) + invalid_cell2struct_fields_error (); + + retval(i) = c(i).string_value (); + } + + return retval; + } + + invalid_cell2struct_fields_error (); +} + DEFUN (cell2struct, args, , doc: /* -*- texinfo -*- @deftypefn {} {} cell2struct (@var{cell}, @var{fields}) @@ -2024,11 +2064,10 @@ if (nargin < 2 || nargin > 3) print_usage (); - if (! args(0).iscell ()) - error ("cell2struct: argument CELL must be of type cell"); - - if (! (args(1).iscellstr () || args(1).is_char_matrix ())) - error ("cell2struct: FIELDS must be a cell array of strings or a character matrix"); + const Cell vals + = args(0).xcell_value ("cell2struct: argument CELL must be of type cell"); + + const Array<std::string> fields = get_cell2struct_fields (args(1)); int dim = 0; @@ -2043,9 +2082,6 @@ if (dim < 0) error ("cell2struct: DIM must be a valid dimension"); - const Cell vals = args(0).cell_value (); - const Array<std::string> fields = args(1).cellstr_value (); - octave_idx_type ext = (vals.ndims () > dim ? vals.dims ()(dim) : 1); if (ext != fields.numel ()) @@ -2095,6 +2131,12 @@ %!assert (cell2struct ({1; 2}, {"a"; "b"}), struct ("a", 1, "b", 2)) %!assert (cell2struct ({}, {"f"}, 3), struct ("f", {})) + +%!assert (cell2struct ({1; 2; 3; 4}, {'a', 'b'; 'c', 'd'}), +%! struct ('a', 1, 'c', 2, 'b', 3, 'd', 4)); +%!assert (cell2struct ({1, 2, 3, 4}, {'a', 'b'; 'c', 'd'}, 2), +%! struct ('a', 1, 'c', 2, 'b', 3, 'd', 4)); +%!error cell2struct ({1, 2, 3, 4}, {'a', 'b'; 'c', 'd'}) */ DEFUN (rmfield, args, ,