3Copyright (C) 1996, 1997, 1998, 2000, 2002, 2003, 2004, 2005, 2006,
4 2007, 2008, 2009 John W. Eaton
6This file is part of Octave.
8Octave is free software; you can redistribute it and/or modify it
9under the terms of the GNU General Public License as published by the
10Free Software Foundation; either version 3 of the License, or (at your
11option) any later version.
13Octave is distributed in the hope that it will be useful, but WITHOUT
14ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
18You should have received a copy of the GNU General Public License
19along with Octave; see the file COPYING. If not, see
20<http://www.gnu.org/licenses/>.
34#include "oct-lvalue.h"
37#include "unwind-prot.h"
41#include "Array-util.h"
42#include "oct-locbuf.h"
45#include "ls-oct-ascii.h"
46#include "ls-oct-binary.h"
51DEFINE_OCTAVE_ALLOCATOR(octave_struct);
53DEFINE_OV_TYPEID_FUNCTIONS_AND_DATA(octave_struct, "struct", "struct");
56octave_struct::dotref (const octave_value_list& idx, bool auto_add)
60 assert (idx.length () == 1);
62 std::string nm = idx(0).string_value ();
64 Octave_map::const_iterator p = map.seek (nm);
67 retval = map.contents (p);
69 retval = (numel () == 0) ? Cell (dim_vector (1)) : Cell (dims ());
71 error ("structure has no member `%s'", nm.c_str ());
78gripe_invalid_index (void)
80 error ("invalid index for structure array");
85gripe_invalid_index_for_assignment (void)
87 error ("invalid index for structure array assignment");
91gripe_invalid_index_type (const std::string& nm, char t)
93 error ("%s cannot be indexed with %c", nm.c_str (), t);
97gripe_failed_assignment (void)
99 error ("assignment to structure element failed");
103octave_struct::subsref (const std::string& type,
104 const std::list<octave_value_list>& idx,
107 octave_value_list retval;
115 if (type.length () > 1 && type[1] == '.')
117 std::list<octave_value_list>::const_iterator p = idx.begin ();
118 octave_value_list key_idx = *++p;
120 const Cell tmp = dotref (key_idx);
124 const Cell t = tmp.index (idx.front ());
126 retval(0) = (t.length () == 1) ? t(0) : octave_value (t, true);
128 // We handled two index elements, so tell
129 // next_subsref to skip both of them.
135 retval(0) = map.index (idx.front ());
143 const Cell t = dotref (idx.front ());
145 retval(0) = (t.length () == 1) ? t(0) : octave_value (t, true);
151 gripe_invalid_index_type (type_name (), type[0]);
158 // FIXME -- perhaps there should be an
159 // octave_value_list::next_subsref member function? See also
160 // octave_user_function::subsref.
163 retval = retval(0).next_subsref (nargout, type, idx, skip);
169octave_struct::subsref (const std::string& type,
170 const std::list<octave_value_list>& idx,
181 if (type.length () > 1 && type[1] == '.')
183 std::list<octave_value_list>::const_iterator p = idx.begin ();
184 octave_value_list key_idx = *++p;
186 const Cell tmp = dotref (key_idx, auto_add);
190 const Cell t = tmp.index (idx.front (), auto_add);
192 retval = (t.length () == 1) ? t(0) : octave_value (t, true);
194 // We handled two index elements, so tell
195 // next_subsref to skip both of them.
201 retval = map.index (idx.front (), auto_add);
209 const Cell t = dotref (idx.front (), auto_add);
211 retval = (t.length () == 1) ? t(0) : octave_value (t, true);
217 gripe_invalid_index_type (type_name (), type[0]);
224 // FIXME -- perhaps there should be an
225 // octave_value_list::next_subsref member function? See also
226 // octave_user_function::subsref.
229 retval = retval.next_subsref (auto_add, type, idx, skip);
236%! x(1).a.a = 1; x(2).a.a = 2;
237%! assert (size (x), [1, 2]);
238%! assert (x(1).a.a, 1);
239%! assert (x(2).a.a, 2);
243octave_struct::numeric_conv (const octave_value& val,
244 const std::string& type)
248 if (type.length () > 0 && type[0] == '.' && ! val.is_map ())
249 retval = Octave_map ();
257octave_struct::subsasgn (const std::string& type,
258 const std::list<octave_value_list>& idx,
259 const octave_value& rhs)
263 int n = type.length ();
265 octave_value t_rhs = rhs;
267 if (idx.front ().empty ())
269 error ("missing index in indexed assignment");
273 if (n > 1 && ! (type.length () == 2 && type[0] == '(' && type[1] == '.'))
279 if (type.length () > 1 && type[1] == '.')
281 std::list<octave_value_list>::const_iterator p = idx.begin ();
282 octave_value_list t_idx = *p;
284 octave_value_list key_idx = *++p;
286 assert (key_idx.length () == 1);
288 std::string key = key_idx(0).string_value ();
290 std::list<octave_value_list> next_idx (idx);
292 // We handled two index elements, so subsasgn to
293 // needs to skip both of them.
295 next_idx.erase (next_idx.begin ());
296 next_idx.erase (next_idx.begin ());
298 std::string next_type = type.substr (2);
301 Octave_map::iterator pkey = map.seek (key);
302 if (pkey != map.end ())
304 pkey->second.make_unique ();
305 tmpc = pkey->second.index (idx.front (), true);
308 // FIXME: better code reuse? cf. octave_cell::subsasgn and the case below.
311 if (tmpc.numel () == 1)
313 octave_value& tmp = tmpc(0);
315 if (! tmp.is_defined () || tmp.is_zero_by_zero ())
317 tmp = octave_value::empty_conv (next_type, rhs);
318 tmp.make_unique (); // probably a no-op.
321 // optimization: ignore the copy still stored inside our map.
325 t_rhs = tmp.subsasgn (next_type, next_idx, rhs);
328 gripe_indexed_cs_list ();
332 gripe_invalid_index_for_assignment ();
338 octave_value_list key_idx = idx.front ();
340 assert (key_idx.length () == 1);
342 std::string key = key_idx(0).string_value ();
344 std::list<octave_value_list> next_idx (idx);
346 next_idx.erase (next_idx.begin ());
348 std::string next_type = type.substr (1);
351 Octave_map::iterator pkey = map.seek (key);
352 if (pkey != map.end ())
354 pkey->second.make_unique ();
358 // FIXME: better code reuse?
361 if (tmpc.numel () == 1)
363 octave_value& tmp = tmpc(0);
365 if (! tmp.is_defined () || tmp.is_zero_by_zero ())
367 tmp = octave_value::empty_conv (next_type, rhs);
368 tmp.make_unique (); // probably a no-op.
371 // optimization: ignore the copy still stored inside our map.
375 t_rhs = tmp.subsasgn (next_type, next_idx, rhs);
378 gripe_indexed_cs_list ();
384 gripe_invalid_index_type (type_name (), type[0]);
398 if (n > 1 && type[1] == '.')
400 std::list<octave_value_list>::const_iterator p = idx.begin ();
401 octave_value_list key_idx = *++p;
402 octave_value_list idxf = idx.front ();
404 assert (key_idx.length () == 1);
406 std::string key = key_idx(0).string_value ();
410 if (t_rhs.is_cs_list ())
412 Cell tmp_cell = Cell (t_rhs.list_value ());
414 // Inquire the proper shape of the RHS.
416 dim_vector didx = dims ().redim (idxf.length ());
417 for (octave_idx_type k = 0; k < idxf.length (); k++)
418 if (! idxf(k).is_magic_colon ()) didx(k) = idxf(k).numel ();
420 if (didx.numel () == tmp_cell.numel ())
421 tmp_cell = tmp_cell.reshape (didx);
424 map.assign (idxf, key, tmp_cell);
429 retval = octave_value (this);
432 gripe_failed_assignment ();
436 const Octave_map& cmap = const_cast<const Octave_map &> (map);
437 // cast map to const reference to avoid forced key insertion.
438 if (idxf.all_scalars ()
439 || cmap.contents (key).index (idxf, true).numel () == 1)
441 map.assign (idxf, key, t_rhs.storable_value ());
445 retval = octave_value (this);
448 gripe_failed_assignment ();
450 else if (! error_state)
451 error ("invalid assignment to cs-list outside multiple assignment.");
455 gripe_failed_assignment ();
461 Octave_map rhs_map = t_rhs.map_value ();
465 map.assign (idx.front (), rhs_map);
470 retval = octave_value (this);
473 gripe_failed_assignment ();
476 error ("invalid structure assignment");
480 if (t_rhs.is_null_value())
482 map.maybe_delete_elements (idx.front());
487 retval = octave_value (this);
490 gripe_failed_assignment ();
493 error ("invalid structure assignment");
501 octave_value_list key_idx = idx.front ();
503 assert (key_idx.length () == 1);
505 std::string key = key_idx(0).string_value ();
507 if (t_rhs.is_cs_list ())
509 Cell tmp_cell = Cell (t_rhs.list_value ());
511 // The shape of the RHS is irrelevant, we just want
512 // the number of elements to agree and to preserve the
513 // shape of the left hand side of the assignment.
515 if (numel () == tmp_cell.numel ())
516 tmp_cell = tmp_cell.reshape (dims ());
518 map.assign (key, tmp_cell);
521 // Regularize a null matrix if stored into a struct component.
522 map.assign (key, t_rhs.storable_value ());
527 retval = octave_value (this);
530 gripe_failed_assignment ();
535 gripe_invalid_index_type (type_name (), type[0]);
543 gripe_failed_assignment ();
549octave_struct::do_index_op (const octave_value_list& idx, bool resize_ok)
551 // Octave_map handles indexing itself.
552 return map.index (idx, resize_ok);
556octave_struct::byte_size (void) const
558 // Neglect the size of the fieldnames.
562 for (Octave_map::const_iterator p = map.begin (); p != map.end (); p++)
564 std::string key = map.key (p);
566 octave_value val = octave_value (map.contents (p));
568 retval += val.byte_size ();
575octave_struct::print (std::ostream& os, bool) const
581octave_struct::print_raw (std::ostream& os, bool) const
583 unwind_protect::frame_id_t uwp_frame = unwind_protect::begin_frame ();
585 unwind_protect::protect_var (Vstruct_levels_to_print);
587 if (Vstruct_levels_to_print >= 0)
589 bool print_keys_only = Vstruct_levels_to_print-- == 0;
595 increment_indent_level ();
597 octave_idx_type n = map.numel ();
599 if (n != 1 || print_keys_only)
602 dim_vector dv = dims ();
603 os << dv.str () << " struct array containing the fields:";
607 increment_indent_level ();
610 string_vector key_list = map.keys ();
612 for (octave_idx_type i = 0; i < key_list.length (); i++)
614 std::string key = key_list[i];
616 Cell val = map.contents (key);
618 octave_value tmp = (n == 1) ? val(0) : octave_value (val, true);
620 if (n != 1 || print_keys_only)
626 dim_vector dv = tmp.dims ();
627 os << ": " << dv.str () << " " << tmp.type_name ();
632 tmp.print_with_name (os, key);
635 if (n != 1 || print_keys_only)
636 decrement_indent_level ();
638 decrement_indent_level ();
651 unwind_protect::run_frame (uwp_frame);
655octave_struct::print_name_tag (std::ostream& os, const std::string& name) const
661 if (Vstruct_levels_to_print < 0)
674scalar (const dim_vector& dims)
676 return dims.length () == 2 && dims (0) == 1 && dims (1) == 1;
681%! x(1).a=1; x(2).a=2; x(1).b=3; x(2).b=3;
682%!assert(struct('a',1,'b',3),x(1))
683%!assert(isempty(x([])))
684%!assert(isempty(struct('a',{},'b',{})))
685%!assert(struct('a',{1,2},'b',{3,3}),x)
686%!assert(struct('a',{1,2},'b',3),x)
687%!assert(struct('a',{1,2},'b',{3}),x)
688%!assert(struct('b',3,'a',{1,2}),x)
689%!assert(struct('b',{3},'a',{1,2}),x)
691%!assert(size(x),[0,0]);
692%!assert(isstruct(x));
693%!assert(isempty(fieldnames(x)));
694%!fail("struct('a',{1,2},'b',{1,2,3})","dimensions of parameter 2 do not match those of parameter 4")
695%!fail("struct(1,2,3,4)","struct expects alternating \"field\", VALUE pairs");
696%!fail("struct('1',2,'3')","struct expects alternating \"field\", VALUE pairs");
699DEFUN (struct, args, ,
701@deftypefn {Built-in Function} {} struct (\"field\", @var{value}, \"field\", @var{value}, @dots{})\n\
703Create a structure and initialize its value.\n\
705If the values are cell arrays, create a structure array and initialize\n\
706its values. The dimensions of each cell array of values must match.\n\
707Singleton cells and non-cell values are repeated so that they fill\n\
708the entire array. If the cells are empty, create an empty structure\n\
709array with the specified field names.\n\
711If the argument is an object, return the underlying struct.\n\
716 int nargin = args.length ();
718 // struct ([]) returns an empty struct.
720 // struct (empty_matrix) returns an empty struct with the same
721 // dimensions as the empty matrix.
723 // Note that struct () creates a 1x1 struct with no fields for
724 // compatibility with Matlab.
726 if (nargin == 1 && args(0).is_object ())
728 Octave_map m = args(0).map_value ();
729 retval = octave_value (new octave_struct (m));
734 if ((nargin == 1 || nargin == 2)
735 && args(0).is_empty () && args(0).is_real_matrix ())
741 if (args(1).is_cellstr ())
742 retval = Octave_map (args(0).dims (), args(1).cell_value ());
744 error ("struct: expecting cell array of field names as second argument");
747 retval = Octave_map (args(0).dims ());
752 // Check for "field", VALUE pairs.
754 for (int i = 0; i < nargin; i += 2)
756 if (! args(i).is_string () || i + 1 >= nargin)
758 error ("struct expects alternating \"field\", VALUE pairs");
763 // Check that the dimensions of the values correspond.
765 dim_vector dims (1, 1);
767 int first_dimensioned_value = 0;
769 for (int i = 1; i < nargin; i += 2)
771 if (args(i).is_cell ())
773 dim_vector argdims (args(i).dims ());
775 if (! scalar (argdims))
777 if (! first_dimensioned_value)
780 first_dimensioned_value = i + 1;
782 else if (dims != argdims)
784 error ("struct: dimensions of parameter %d do not match those of parameter %d",
785 first_dimensioned_value, i+1);
792 // Create the return value.
794 Octave_map map (dims);
796 for (int i = 0; i < nargin; i+= 2)
800 std::string key (args(i).string_value ());
805 if (! valid_identifier (key))
807 error ("struct: invalid structure field name `%s'", key.c_str ());
811 // Value may be v, { v }, or { v1, v2, ... }
812 // In the first two cases, we need to create a cell array of
813 // the appropriate dimensions filled with v. In the last case,
814 // the cell array has already been determined to be of the
815 // correct dimensions.
817 if (args(i+1).is_cell ())
819 const Cell c (args(i+1).cell_value ());
824 if (scalar (c.dims ()))
825 map.assign (key, Cell (dims, c(0)));
830 map.assign (key, Cell (dims, args(i+1)));
836 return octave_value (map);
839DEFUN (isstruct, args, ,
841@deftypefn {Built-in Function} {} isstruct (@var{expr})\n\
842Return 1 if the value of the expression @var{expr} is a structure.\n\
847 if (args.length () == 1)
848 retval = args(0).is_map ();
855DEFUN (fieldnames, args, ,
857@deftypefn {Built-in Function} {} fieldnames (@var{struct})\n\
858Return a cell array of strings naming the elements of the structure\n\
859@var{struct}. It is an error to call @code{fieldnames} with an\n\
860argument that is not a structure.\n\
865 int nargin = args.length ();
869 octave_value arg = args(0);
871 if (arg.is_map () || arg.is_object ())
873 Octave_map m = arg.map_value ();
875 string_vector keys = m.keys ();
877 if (keys.length () == 0)
878 retval = Cell (0, 1);
880 retval = Cell (m.keys ());
883 gripe_wrong_type_arg ("fieldnames", args(0));
891DEFUN (isfield, args, ,
893@deftypefn {Built-in Function} {} isfield (@var{expr}, @var{name})\n\
894Return true if the expression @var{expr} is a structure and it includes an\n\
895element named @var{name}. The first argument must be a structure and\n\
896the second must be a string.\n\
901 int nargin = args.length ();
907 // FIXME -- should this work for all types that can do
908 // structure reference operations?
910 if (args(0).is_map () && args(1).is_string ())
912 std::string key = args(1).string_value ();
914 Octave_map m = args(0).map_value ();
916 retval = m.contains (key) != 0;
925DEFUN (nfields, args, ,
927@deftypefn {Built-in Function} {} nfields (@var{s})\n\
928Return the number of fields of the structure @var{s}.\n\
933 int nargin = args.length ();
935 if (nargin == 1 && args(0).is_map ())
937 retval = static_cast<double> (args(0).nfields ());
945// Check that the dimensions of the input arguments are correct.
948cell2struct_check_args (const dim_vector& c_dv, const dim_vector& f_dv,
949 bool is_cell, int dim)
953 if (dim >= 0 && dim < c_dv.length ())
957 if (f_dv.numel () != c_dv(dim))
959 error ("cell2struct: numel (FIELD) != size (CELL, DIM)");
966 if (f_dv.length () > 2)
968 error ("cell2struct: field array must be a 2-d matrix");
972 else if (f_dv(0) != c_dv(dim))
974 error ("cell2struct: size (FIELD, 1) != length (C, DIM)");
982 error ("cell2struct: DIM out of range");
991cell2struct_construct_idx (Array<octave_idx_type>& ra_idx1,
992 const Array<octave_idx_type>& ra_idx2,
993 octave_idx_type dim, octave_idx_type fill_value)
995 octave_idx_type iidx = 0;
997 for (octave_idx_type idx = 0; idx < ra_idx1.length (); idx++)
1000 ra_idx1.elem (idx) = fill_value;
1002 ra_idx1.elem (idx) = ra_idx2(iidx++);
1006DEFUN (cell2struct, args, ,
1008@deftypefn {Built-in Function} {} cell2struct (@var{cell}, @var{fields}, @var{dim})\n\
1009Convert @var{cell} to a structure. The number of fields in @var{fields}\n\
1010must match the number of elements in @var{cell} along dimension @var{dim},\n\
1011that is @code{numel (@var{fields}) == size (@var{cell}, @var{dim})}.\n\
1015A = cell2struct (@{'Peter', 'Hannah', 'Robert';\n\
1017 @{'Name','Height'@}, 1);\n\
1029 octave_value retval;
1031 if (args.length () == 3)
1033 Cell c = args(0).cell_value ();
1037 octave_value field = args(1);
1039 // Field is either cell or character matrix.
1041 // FIXME -- this could be simplified if we had
1042 // cellstr and iscellstr functions available.
1044 bool field_is_cell = field.is_cell ();
1047 charMatrix field_char;
1050 field_cell = field.cell_value ();
1052 field_char = field.char_matrix_value ();
1056 // Retrieve the dimension value.
1058 // FIXME -- int_value () should print out the
1059 // conversions it does to be Matlab compatible.
1061 octave_idx_type dim = args(2).int_value () - 1;
1065 dim_vector c_dv = c.dims ();
1066 dim_vector field_dv = field.dims ();
1068 if (cell2struct_check_args (c_dv, field_dv, field_is_cell,
1071 octave_idx_type c_dv_length = c_dv.length ();
1073 // Dimension vector for the Cell arrays to be
1074 // put into the structure.
1076 dim_vector value_dv;
1078 // Initialize c_value_dv.
1080 if (c_dv_length == 2)
1081 value_dv = dim_vector (1, 1);
1083 value_dv.resize (c_dv_length - 1);
1085 octave_idx_type idx_tmp = 0;
1087 for (octave_idx_type i = 0; i < c_dv_length; i++)
1090 value_dv.elem (idx_tmp++) = c_dv.elem (i);
1093 // All initializing is done, we can start moving
1098 // If field is a cell array then we use all
1099 // elements in array, on the other hand when
1100 // field is a character array the number of
1101 // elements is equals the number of rows.
1103 octave_idx_type field_numel
1104 = field_is_cell ? field_dv.numel (): field_dv(0);
1106 // For matlab compatibility.
1108 if (field_numel == 0)
1109 map.reshape (dim_vector (0, 1));
1111 for (octave_idx_type i = 0; i < field_numel; i++)
1113 // Construct cell array which goes into the
1114 // structure together with the appropriate
1117 Cell c_value (value_dv);
1119 Array<octave_idx_type> value_idx (value_dv.length (), 0);
1120 Array<octave_idx_type> c_idx (c_dv_length, 0);
1122 for (octave_idx_type j = 0; j < value_dv.numel (); j++)
1124 // Need to do this to construct the
1125 // appropriate idx for getting elements
1126 // from the original cell array.
1128 cell2struct_construct_idx (c_idx, value_idx,
1131 c_value.elem (value_idx) = c.elem (c_idx);
1133 increment_index (value_idx, value_dv);
1136 std::string field_str;
1140 // Matlab retrieves the field values
1141 // column by column.
1143 octave_value field_tmp = field_cell.elem (i);
1145 field_str = field_tmp.string_value ();
1149 error ("cell2struct: fields have to be of type string");
1155 field_str = field_char.row_as_string (i);
1161 if (! valid_identifier (field_str))
1163 error ("cell2struct: invalid field name `%s'",
1164 field_str.c_str ());
1168 map.reshape (value_dv);
1170 map.assign (field_str, c_value);
1178 error ("cell2struct: expecting third argument to be an integer");
1181 error ("cell2struct: expecting second argument to be a cell or character array");
1184 error ("cell2struct: expecting first argument to be a cell array");
1192// So we can call Fcellstr directly.
1193extern octave_value_list Fcellstr (const octave_value_list& args, int);
1195DEFUN (rmfield, args, ,
1197@deftypefn {Built-in Function} {} rmfield (@var{s}, @var{f})\n\
1198Remove field @var{f} from the structure @var{s}. If @var{f} is a\n\
1199cell array of character strings or a character array, remove the\n\
1201@seealso{cellstr, iscellstr, setfield}\n\
1204 octave_value retval;
1206 int nargin = args.length ();
1210 Octave_map m = args(0).map_value ();
1212 octave_value_list fval = Fcellstr (args(1), 1);
1216 Cell fcell = fval(0).cell_value ();
1218 for (int i = 0; i < fcell.numel (); i++)
1220 std::string key = fcell(i).string_value ();
1222 if (m.contains (key))
1226 error ("rmfield: structure does not contain field %s",
1244octave_struct::save_ascii (std::ostream& os)
1246 Octave_map m = map_value ();
1248 octave_idx_type nf = m.nfields ();
1250 os << "# length: " << nf << "\n";
1252 // Iterating over the list of keys will preserve the order of the
1254 string_vector keys = m.keys ();
1256 for (octave_idx_type i = 0; i < nf; i++)
1258 std::string key = keys(i);
1260 octave_value val = map.contents (key);
1262 bool b = save_ascii_data (os, val, key, false, 0);
1272octave_struct::load_ascii (std::istream& is)
1274 octave_idx_type len = 0;
1275 bool success = true;
1277 if (extract_keyword (is, "length", len) && len >= 0)
1283 for (octave_idx_type j = 0; j < len; j++)
1288 // recurse to read cell elements
1290 = read_ascii_data (is, std::string (), dummy, t2, j);
1295 Cell tcell = t2.is_cell () ? t2.cell_value () : Cell (t2);
1299 error ("load: internal error loading struct elements");
1303 m.assign (nm, tcell);
1310 error ("load: failed to load structure");
1315 map = Octave_map (dim_vector (1, 1));
1317 panic_impossible ();
1320 error ("load: failed to extract number of elements in structure");
1328octave_struct::save_binary (std::ostream& os, bool& save_as_floats)
1330 Octave_map m = map_value ();
1332 octave_idx_type nf = m.nfields ();
1335 os.write (reinterpret_cast<char *> (&len), 4);
1337 // Iterating over the list of keys will preserve the order of the
1339 string_vector keys = m.keys ();
1341 for (octave_idx_type i = 0; i < nf; i++)
1343 std::string key = keys(i);
1345 octave_value val = map.contents (key);
1347 bool b = save_binary_data (os, val, key, "", 0, save_as_floats);
1357octave_struct::load_binary (std::istream& is, bool swap,
1358 oct_mach_info::float_format fmt)
1360 bool success = true;
1362 if (! is.read (reinterpret_cast<char *> (&len), 4))
1365 swap_bytes<4> (&len);
1371 for (octave_idx_type j = 0; j < len; j++)
1377 // recurse to read cell elements
1378 std::string nm = read_binary_data (is, swap, fmt, std::string (),
1384 Cell tcell = t2.is_cell () ? t2.cell_value () : Cell (t2);
1388 error ("load: internal error loading struct elements");
1392 m.assign (nm, tcell);
1399 error ("load: failed to load structure");
1404 map = Octave_map (dim_vector (1, 1));
1406 panic_impossible ();
1411#if defined (HAVE_HDF5)
1414octave_struct::save_hdf5 (hid_t loc_id, const char *name, bool save_as_floats)
1416 hid_t data_hid = -1;
1418 data_hid = H5Gcreate (loc_id, name, 0);
1419 if (data_hid < 0) return false;
1421 // recursively add each element of the structure to this group
1422 Octave_map m = map_value ();
1424 octave_idx_type nf = m.nfields ();
1426 // Iterating over the list of keys will preserve the order of the
1428 string_vector keys = m.keys ();
1430 for (octave_idx_type i = 0; i < nf; i++)
1432 std::string key = keys(i);
1434 octave_value val = map.contents (key);
1436 bool retval2 = add_hdf5_data (data_hid, val, key, "", false,
1443 H5Gclose (data_hid);
1449octave_struct::load_hdf5 (hid_t loc_id, const char *name,
1450 bool have_h5giterate_bug)
1452 bool retval = false;
1454 hdf5_callback_data dsub;
1457 Octave_map m (dim_vector (1, 1));
1458 int current_item = 0;
1459#ifdef HAVE_H5GGET_NUM_OBJS
1460 hsize_t num_obj = 0;
1461 hid_t group_id = H5Gopen (loc_id, name);
1462 H5Gget_num_objs (group_id, &num_obj);
1463 H5Gclose (group_id);
1465 // FIXME -- fields appear to be sorted alphabetically on loading.
1466 // Why is that happening?
1468 while (current_item < static_cast<int> (num_obj)
1469 && (retval2 = H5Giterate (loc_id, name, ¤t_item,
1470 hdf5_read_next_data, &dsub)) > 0)
1472 while ((retval2 = H5Giterate (loc_id, name, ¤t_item,
1473 hdf5_read_next_data, &dsub)) > 0)
1476 octave_value t2 = dsub.tc;
1478 Cell tcell = t2.is_cell () ? t2.cell_value () : Cell (t2);
1482 error ("load: internal error loading struct elements");
1486 m.assign (dsub.name, tcell);
1488 if (have_h5giterate_bug)
1489 current_item++; // H5Giterate returned the last index processed
1504octave_struct::as_mxArray (void) const
1506 int nf = nfields ();
1507 string_vector kv = map_keys ();
1509 OCTAVE_LOCAL_BUFFER (const char *, f, nf);
1511 for (int i = 0; i < nf; i++)
1512 f[i] = kv[i].c_str ();
1514 mxArray *retval = new mxArray (dims (), nf, f);
1516 mxArray **elts = static_cast<mxArray **> (retval->get_data ());
1518 mwSize nel = numel ();
1520 mwSize ntot = nf * nel;
1522 for (int i = 0; i < nf; i++)
1524 Cell c = map.contents (kv[i]);
1526 const octave_value *p = c.data ();
1529 for (mwIndex j = i; j < ntot; j += nf)
1530 elts[j] = new mxArray (p[k++]);
1537;;; Local Variables: ***