GNU Octave  4.2.1
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
ov-struct.cc
Go to the documentation of this file.
1 /*
2 
3 Copyright (C) 1996-2017 John W. Eaton
4 
5 This file is part of Octave.
6 
7 Octave is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by the
9 Free Software Foundation; either version 3 of the License, or (at your
10 option) any later version.
11 
12 Octave is distributed in the hope that it will be useful, but WITHOUT
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 for more details.
16 
17 You should have received a copy of the GNU General Public License
18 along with Octave; see the file COPYING. If not, see
19 <http://www.gnu.org/licenses/>.
20 
21 */
22 
23 #if defined (HAVE_CONFIG_H)
24 # include "config.h"
25 #endif
26 
27 #include <iostream>
28 
29 #include "Cell.h"
30 #include "defun.h"
31 #include "error.h"
32 #include "errwarn.h"
33 #include "mxarray.h"
34 #include "oct-lvalue.h"
35 #include "oct-hdf5.h"
36 #include "ov-struct.h"
37 #include "unwind-prot.h"
38 #include "utils.h"
39 #include "variables.h"
40 
41 #include "Array-util.h"
42 #include "oct-locbuf.h"
43 
44 #include "byte-swap.h"
45 #include "ls-oct-text.h"
46 #include "ls-oct-binary.h"
47 #include "ls-hdf5.h"
48 #include "ls-utils.h"
49 #include "pr-output.h"
50 
51 
53 
54 // How many levels of structure elements should we print?
55 static int Vstruct_levels_to_print = 2;
56 
57 // TRUE means print struct array contents, up to the number of levels
58 // specified by struct_levels_to_print.
59 static bool Vprint_struct_array_contents = false;
60 
63 {
65 
66  if (numel () == 1)
67  retval = new octave_scalar_struct (map.checkelem (0));
68 
69  return retval;
70 }
71 
72 Cell
73 octave_struct::dotref (const octave_value_list& idx, bool auto_add)
74 {
75  Cell retval;
76 
77  assert (idx.length () == 1);
78 
79  std::string nm = idx(0).string_value ();
80 
82 
83  if (p != map.end ())
84  retval = map.contents (p);
85  else if (auto_add)
86  retval = (is_empty ()) ? Cell (dim_vector (1, 1)) : Cell (dims ());
87  else
88  error_with_id ("Octave:invalid-indexing",
89  "structure has no member '%s'", nm.c_str ());
90 
91  return retval;
92 }
93 
94 static void
96 {
97  error ("invalid index for structure array assignment");
98 }
99 
100 static void
102 {
103  error ("%s cannot be indexed with %c", nm.c_str (), t);
104 }
105 
106 static void
107 maybe_warn_invalid_field_name (const std::string& key, const char *who)
108 {
109  if (! valid_identifier (key))
110  {
111  if (who)
112  warning_with_id ("Octave:language-extension",
113  "%s: invalid structure field name '%s'",
114  who, key.c_str ());
115  else
116  warning_with_id ("Octave:language-extension",
117  "invalid structure field name '%s'",
118  key.c_str ());
119  }
120 }
121 
124  const std::list<octave_value_list>& idx,
125  int nargout)
126 {
128 
129  int skip = 1;
130 
131  switch (type[0])
132  {
133  case '(':
134  {
135  if (type.length () > 1 && type[1] == '.')
136  {
137  std::list<octave_value_list>::const_iterator p = idx.begin ();
138  octave_value_list key_idx = *++p;
139 
140  const Cell tmp = dotref (key_idx);
141 
142  const Cell t = tmp.index (idx.front ());
143 
144  retval(0) = (t.numel () == 1) ? t(0) : octave_value (t, true);
145 
146  // We handled two index elements, so tell
147  // next_subsref to skip both of them.
148 
149  skip++;
150  }
151  else
152  retval(0) = do_index_op (idx.front ());
153  }
154  break;
155 
156  case '.':
157  {
158  if (map.numel () > 0)
159  {
160  const Cell t = dotref (idx.front ());
161 
162  retval(0) = (t.numel () == 1) ? t(0) : octave_value (t, true);
163  }
164  }
165  break;
166 
167  case '{':
168  err_invalid_index_type (type_name (), type[0]);
169  break;
170 
171  default:
172  panic_impossible ();
173  }
174 
175  // FIXME: perhaps there should be an
176  // octave_value_list::next_subsref member function? See also
177  // octave_user_function::subsref.
178 
179  if (idx.size () > 1)
180  retval = retval(0).next_subsref (nargout, type, idx, skip);
181 
182  return retval;
183 }
184 
187  const std::list<octave_value_list>& idx,
188  bool auto_add)
189 {
191 
192  int skip = 1;
193 
194  switch (type[0])
195  {
196  case '(':
197  {
198  if (type.length () > 1 && type[1] == '.')
199  {
200  std::list<octave_value_list>::const_iterator p = idx.begin ();
201  octave_value_list key_idx = *++p;
202 
203  const Cell tmp = dotref (key_idx, auto_add);
204 
205  const Cell t = tmp.index (idx.front (), auto_add);
206 
207  retval = (t.numel () == 1) ? t(0) : octave_value (t, true);
208 
209  // We handled two index elements, so tell
210  // next_subsref to skip both of them.
211 
212  skip++;
213  }
214  else
215  retval = do_index_op (idx.front (), auto_add);
216  }
217  break;
218 
219  case '.':
220  {
221  if (map.numel () > 0)
222  {
223  const Cell t = dotref (idx.front (), auto_add);
224 
225  retval = (t.numel () == 1) ? t(0) : octave_value (t, true);
226  }
227  }
228  break;
229 
230  case '{':
231  err_invalid_index_type (type_name (), type[0]);
232  break;
233 
234  default:
235  panic_impossible ();
236  }
237 
238  // FIXME: perhaps there should be an
239  // octave_value_list::next_subsref member function? See also
240  // octave_user_function::subsref.
241 
242  if (idx.size () > 1)
243  retval = retval.next_subsref (auto_add, type, idx, skip);
244 
245  return retval;
246 }
247 
248 /*
249 %!test
250 %! x(1).a.a = 1;
251 %! x(2).a.a = 2;
252 %! assert (size (x), [1, 2]);
253 %! assert (x(1).a.a, 1);
254 %! assert (x(2).a.a, 2);
255 */
256 
259  const std::string& type)
260 {
262 
263  if (type.length () > 0 && type[0] == '.' && ! val.is_map ())
264  retval = octave_map ();
265  else
266  retval = val;
267 
268  return retval;
269 }
270 
273  const std::list<octave_value_list>& idx,
274  const octave_value& rhs)
275 {
277 
278  int n = type.length ();
279 
280  octave_value t_rhs = rhs;
281 
282  if (idx.front ().empty ())
283  error ("missing index in indexed assignment");
284 
285  if (n > 1 && ! (type.length () == 2 && type[0] == '(' && type[1] == '.'))
286  {
287  switch (type[0])
288  {
289  case '(':
290  {
291  if (type.length () > 1 && type[1] == '.')
292  {
293  std::list<octave_value_list>::const_iterator p = idx.begin ();
294  octave_value_list t_idx = *p;
295 
296  octave_value_list key_idx = *++p;
297 
298  assert (key_idx.length () == 1);
299 
300  std::string key = key_idx(0).string_value ();
301 
302  maybe_warn_invalid_field_name (key, "subsasgn");
303 
304  std::list<octave_value_list> next_idx (idx);
305 
306  // We handled two index elements, so subsasgn to
307  // needs to skip both of them.
308 
309  next_idx.erase (next_idx.begin ());
310  next_idx.erase (next_idx.begin ());
311 
312  std::string next_type = type.substr (2);
313 
314  Cell tmpc (1, 1);
315  octave_map::iterator pkey = map.seek (key);
316  if (pkey != map.end ())
317  {
318  map.contents (pkey).make_unique ();
319  tmpc = map.contents (pkey).index (idx.front (), true);
320  }
321 
322  // FIXME: better code reuse?
323  // cf. octave_cell::subsasgn and the case below.
324  if (tmpc.numel () != 1)
326 
327  octave_value& tmp = tmpc(0);
328 
329  bool orig_undefined = tmp.is_undefined ();
330 
331  if (orig_undefined || tmp.is_zero_by_zero ())
332  {
333  tmp = octave_value::empty_conv (next_type, rhs);
334  tmp.make_unique (); // probably a no-op.
335  }
336  else
337  // optimization: ignore the copy
338  // still stored inside our map.
339  tmp.make_unique (1);
340 
341  t_rhs =(orig_undefined
342  ? tmp.undef_subsasgn (next_type, next_idx, rhs)
343  : tmp.subsasgn (next_type, next_idx, rhs));
344  }
345  else
347  }
348  break;
349 
350  case '.':
351  {
352  octave_value_list key_idx = idx.front ();
353 
354  assert (key_idx.length () == 1);
355 
356  std::string key = key_idx(0).string_value ();
357 
358  maybe_warn_invalid_field_name (key, "subsasgn");
359 
360  std::list<octave_value_list> next_idx (idx);
361 
362  next_idx.erase (next_idx.begin ());
363 
364  std::string next_type = type.substr (1);
365 
366  Cell tmpc (1, 1);
367  octave_map::iterator pkey = map.seek (key);
368  if (pkey != map.end ())
369  {
370  map.contents (pkey).make_unique ();
371  tmpc = map.contents (pkey);
372  }
373 
374  // FIXME: better code reuse?
375 
376  if (tmpc.numel () == 1)
377  {
378  octave_value& tmp = tmpc(0);
379 
380  bool orig_undefined = tmp.is_undefined ();
381 
382  if (orig_undefined || tmp.is_zero_by_zero ())
383  {
384  tmp = octave_value::empty_conv (next_type, rhs);
385  tmp.make_unique (); // probably a no-op.
386  }
387  else
388  // optimization: ignore the copy
389  // still stored inside our map.
390  tmp.make_unique (1);
391 
392  t_rhs = (orig_undefined
393  ? tmp.undef_subsasgn (next_type, next_idx, rhs)
394  : tmp.subsasgn (next_type, next_idx, rhs));
395  }
396  else
398  }
399  break;
400 
401  case '{':
402  err_invalid_index_type (type_name (), type[0]);
403  break;
404 
405  default:
406  panic_impossible ();
407  }
408  }
409 
410  switch (type[0])
411  {
412  case '(':
413  {
414  if (n > 1 && type[1] == '.')
415  {
416  std::list<octave_value_list>::const_iterator p = idx.begin ();
417  octave_value_list key_idx = *++p;
418  octave_value_list idxf = idx.front ();
419 
420  assert (key_idx.length () == 1);
421 
422  std::string key = key_idx(0).string_value ();
423 
424  maybe_warn_invalid_field_name (key, "subsasgn");
425 
426  if (t_rhs.is_cs_list ())
427  {
428  Cell tmp_cell = Cell (t_rhs.list_value ());
429 
430  // Inquire the proper shape of the RHS.
431 
432  dim_vector didx = dims ().redim (idxf.length ());
433  for (octave_idx_type k = 0; k < idxf.length (); k++)
434  if (! idxf(k).is_magic_colon ())
435  didx(k) = idxf(k).numel ();
436 
437  if (didx.numel () == tmp_cell.numel ())
438  tmp_cell = tmp_cell.reshape (didx);
439 
440  map.assign (idxf, key, tmp_cell);
441 
442  count++;
443  retval = octave_value (this);
444  }
445  else
446  {
447  const octave_map& cmap =
448  const_cast<const octave_map &> (map);
449  // cast to const reference, avoid forced key insertion.
450  if (idxf.all_scalars ()
451  || cmap.contents (key).index (idxf, true).numel () == 1)
452  {
453  map.assign (idxf,
454  key, Cell (t_rhs.storable_value ()));
455 
456  count++;
457  retval = octave_value (this);
458  }
459  else
461  }
462  }
463  else
464  {
465  if (t_rhs.is_map () || t_rhs.is_object ())
466  {
467  octave_map rhs_map = t_rhs.xmap_value ("invalid structure assignment");
468 
469  map.assign (idx.front (), rhs_map);
470 
471  count++;
472  retval = octave_value (this);
473  }
474  else
475  {
476  if (! t_rhs.is_null_value ())
477  error ("invalid structure assignment");
478 
479  map.delete_elements (idx.front ());
480 
481  count++;
482  retval = octave_value (this);
483  }
484  }
485  }
486  break;
487 
488  case '.':
489  {
490  octave_value_list key_idx = idx.front ();
491 
492  assert (key_idx.length () == 1);
493 
494  std::string key = key_idx(0).string_value ();
495 
496  maybe_warn_invalid_field_name (key, "subsasgn");
497 
498  if (t_rhs.is_cs_list ())
499  {
500  Cell tmp_cell = Cell (t_rhs.list_value ());
501 
502  // The shape of the RHS is irrelevant, we just want
503  // the number of elements to agree and to preserve the
504  // shape of the left hand side of the assignment.
505 
506  if (numel () == tmp_cell.numel ())
507  tmp_cell = tmp_cell.reshape (dims ());
508 
509  map.setfield (key, tmp_cell);
510  }
511  else
512  {
513  Cell tmp_cell(1, 1);
514  tmp_cell(0) = t_rhs.storable_value ();
515  map.setfield (key, tmp_cell);
516  }
517 
518  count++;
519  retval = octave_value (this);
520  }
521  break;
522 
523  case '{':
524  err_invalid_index_type (type_name (), type[0]);
525  break;
526 
527  default:
528  panic_impossible ();
529  }
530 
531  retval.maybe_mutate ();
532 
533  return retval;
534 }
535 
537 octave_struct::do_index_op (const octave_value_list& idx, bool resize_ok)
538 {
539  // octave_map handles indexing itself.
540  return map.index (idx, resize_ok);
541 }
542 
543 size_t
545 {
546  // Neglect the size of the fieldnames.
547 
548  size_t retval = 0;
549 
550  for (octave_map::const_iterator p = map.begin (); p != map.end (); p++)
551  {
552  std::string key = map.key (p);
553 
555 
556  retval += val.byte_size ();
557  }
558 
559  return retval;
560 }
561 
562 void
563 octave_struct::print (std::ostream& os, bool)
564 {
565  print_raw (os);
566 }
567 
568 void
569 octave_struct::print_raw (std::ostream& os, bool) const
570 {
572 
573  frame.protect_var (Vstruct_levels_to_print);
574 
575  if (Vstruct_levels_to_print >= 0)
576  {
577  bool max_depth_reached = Vstruct_levels_to_print-- == 0;
578 
579  bool print_fieldnames_only
580  = (max_depth_reached || ! Vprint_struct_array_contents);
581 
583 
584  newline (os);
585  indent (os);
586  dim_vector dv = dims ();
587  os << dv.str () << " struct array containing the fields:";
588  newline (os);
589 
591 
592  string_vector key_list = map.fieldnames ();
593 
594  for (octave_idx_type i = 0; i < key_list.numel (); i++)
595  {
596  std::string key = key_list[i];
597 
598  Cell val = map.contents (key);
599 
600  newline (os);
601 
602  if (print_fieldnames_only)
603  {
604  indent (os);
605  os << key;
606  }
607  else
608  {
609  octave_value tmp (val);
610  tmp.print_with_name (os, key);
611  }
612  }
613 
614  if (print_fieldnames_only)
615  newline (os);
616 
619  }
620  else
621  {
622  indent (os);
623  os << "<structure>";
624  newline (os);
625  }
626 }
627 
628 bool
629 octave_struct::print_name_tag (std::ostream& os, const std::string& name) const
630 {
631  bool retval = false;
632 
633  indent (os);
634 
635  if (Vstruct_levels_to_print < 0)
636  os << name << " = ";
637  else
638  {
639  os << name << " =";
640  newline (os);
641  retval = true;
642  }
643 
644  return retval;
645 }
646 
647 static bool
649 {
650  return dims.ndims () == 2 && dims(0) == 1 && dims(1) == 1;
651 }
652 
653 bool
654 octave_struct::save_ascii (std::ostream& os)
655 {
656  octave_map m = map_value ();
657 
658  octave_idx_type nf = m.nfields ();
659 
660  const dim_vector dv = dims ();
661 
662  os << "# ndims: " << dv.ndims () << "\n";
663 
664  for (int i = 0; i < dv.ndims (); i++)
665  os << " " << dv(i);
666  os << "\n";
667 
668  os << "# length: " << nf << "\n";
669 
670  // Iterating over the list of keys will preserve the order of the
671  // fields.
672  string_vector keys = m.fieldnames ();
673 
674  for (octave_idx_type i = 0; i < nf; i++)
675  {
676  std::string key = keys(i);
677 
678  octave_value val = map.contents (key);
679 
680  bool b = save_text_data (os, val, key, false, 0);
681 
682  if (! b)
683  return ! os.fail ();
684  }
685 
686  return true;
687 }
688 
689 bool
691 {
692  octave_idx_type len = 0;
693  dim_vector dv (1, 1);
694  bool success = true;
695 
696  // KLUGE: earlier Octave versions did not save extra dimensions with struct,
697  // and as a result did not preserve dimensions for empty structs.
698  // The default dimensions were 1x1, which we want to preserve.
700 
701  keywords[0] = "ndims";
702  keywords[1] = "length";
703 
704  std::string kw;
705 
706  if (extract_keyword (is, keywords, kw, len, true))
707  {
708  if (kw == keywords[0])
709  {
710  int mdims = std::max (static_cast<int> (len), 2);
711  dv.resize (mdims);
712  for (int i = 0; i < mdims; i++)
713  is >> dv(i);
714 
715  success = extract_keyword (is, keywords[1], len);
716  }
717  }
718  else
719  success = false;
720 
721  if (! success || len < 0)
722  error ("load: failed to extract number of elements in structure");
723 
724  if (len > 0)
725  {
726  octave_map m (dv);
727 
728  for (octave_idx_type j = 0; j < len; j++)
729  {
730  octave_value t2;
731  bool dummy;
732 
733  // recurse to read cell elements
735  = read_text_data (is, "", dummy, t2, j);
736 
737  if (! is)
738  break;
739 
740  Cell tcell = t2.is_cell () ? t2.xcell_value ("load: internal error loading struct elements") : Cell (t2);
741 
742  m.setfield (nm, tcell);
743  }
744 
745  if (! is)
746  error ("load: failed to load structure");
747 
748  map = m;
749  }
750  else if (len == 0)
751  map = octave_map (dv);
752  else
753  panic_impossible ();
754 
755  return success;
756 }
757 
758 bool
760 {
761  octave_map m = map_value ();
762 
763  octave_idx_type nf = m.nfields ();
764 
765  dim_vector dv = dims ();
766  if (dv.ndims () < 1)
767  return false;
768 
769  // Use negative value for ndims
770  int32_t di = - dv.ndims ();
771  os.write (reinterpret_cast<char *> (&di), 4);
772  for (int i = 0; i < dv.ndims (); i++)
773  {
774  di = dv(i);
775  os.write (reinterpret_cast<char *> (&di), 4);
776  }
777 
778  int32_t len = nf;
779  os.write (reinterpret_cast<char *> (&len), 4);
780 
781  // Iterating over the list of keys will preserve the order of the
782  // fields.
783  string_vector keys = m.fieldnames ();
784 
785  for (octave_idx_type i = 0; i < nf; i++)
786  {
787  std::string key = keys(i);
788 
789  octave_value val = map.contents (key);
790 
791  bool b = save_binary_data (os, val, key, "", 0, save_as_floats);
792 
793  if (! b)
794  return ! os.fail ();
795  }
796 
797  return true;
798 }
799 
800 bool
801 octave_struct::load_binary (std::istream& is, bool swap,
803 {
804  bool success = true;
805  int32_t len;
806  if (! is.read (reinterpret_cast<char *> (&len), 4))
807  return false;
808  if (swap)
809  swap_bytes<4> (&len);
810 
811  dim_vector dv (1, 1);
812 
813  if (len < 0)
814  {
815  // We have explicit dimensions.
816  int mdims = -len;
817 
818  int32_t di;
819  dv.resize (mdims);
820 
821  for (int i = 0; i < mdims; i++)
822  {
823  if (! is.read (reinterpret_cast<char *> (&di), 4))
824  return false;
825  if (swap)
826  swap_bytes<4> (&di);
827  dv(i) = di;
828  }
829 
830  if (! is.read (reinterpret_cast<char *> (&len), 4))
831  return false;
832  if (swap)
833  swap_bytes<4> (&len);
834  }
835 
836  if (len > 0)
837  {
838  octave_map m (dv);
839 
840  for (octave_idx_type j = 0; j < len; j++)
841  {
842  octave_value t2;
843  bool dummy;
844  std::string doc;
845 
846  // recurse to read cell elements
847  std::string nm = read_binary_data (is, swap, fmt, "",
848  dummy, t2, doc);
849 
850  if (! is)
851  break;
852 
853  Cell tcell = t2.is_cell () ? t2.xcell_value ("load: internal error loading struct elements") : Cell (t2);
854 
855  m.setfield (nm, tcell);
856  }
857 
858  if (! is)
859  error ("load: failed to load structure");
860 
861  map = m;
862  }
863  else if (len == 0)
864  map = octave_map (dv);
865  else
866  success = false;
867 
868  return success;
869 }
870 
871 bool
873  bool save_as_floats)
874 {
875 #if defined (HAVE_HDF5)
876 
877  hid_t data_hid = -1;
878 
879 #if defined (HAVE_HDF5_18)
880  data_hid = H5Gcreate (loc_id, name, octave_H5P_DEFAULT, octave_H5P_DEFAULT,
882 #else
883  data_hid = H5Gcreate (loc_id, name, 0);
884 #endif
885  if (data_hid < 0) return false;
886 
887  // recursively add each element of the structure to this group
888  octave_map m = map_value ();
889 
890  octave_idx_type nf = m.nfields ();
891 
892  // Iterating over the list of keys will preserve the order of the
893  // fields.
894  string_vector keys = m.fieldnames ();
895 
896  for (octave_idx_type i = 0; i < nf; i++)
897  {
898  std::string key = keys(i);
899 
900  octave_value val = map.contents (key);
901 
902  bool retval2 = add_hdf5_data (data_hid, val, key, "", false,
903  save_as_floats);
904 
905  if (! retval2)
906  break;
907  }
908 
909  H5Gclose (data_hid);
910 
911  return true;
912 
913 #else
914  octave_unused_parameter (loc_id);
915  octave_unused_parameter (name);
916  octave_unused_parameter (save_as_floats);
917 
918  warn_save ("hdf5");
919 
920  return false;
921 #endif
922 }
923 
924 bool
926 {
927  bool retval = false;
928 
929 #if defined (HAVE_HDF5)
930 
931  hdf5_callback_data dsub;
932 
933  herr_t retval2 = 0;
934  octave_map m (dim_vector (1, 1));
935  int current_item = 0;
936  hsize_t num_obj = 0;
937 #if defined (HAVE_HDF5_18)
938  hid_t group_id = H5Gopen (loc_id, name, octave_H5P_DEFAULT);
939 #else
940  hid_t group_id = H5Gopen (loc_id, name);
941 #endif
942  H5Gget_num_objs (group_id, &num_obj);
943  H5Gclose (group_id);
944 
945  // FIXME: fields appear to be sorted alphabetically on loading.
946  // Why is that happening?
947 
948  while (current_item < static_cast<int> (num_obj)
949  && (retval2 = hdf5_h5g_iterate (loc_id, name, &current_item,
950  &dsub)) > 0)
951  {
952  octave_value t2 = dsub.tc;
953 
954  Cell tcell = t2.is_cell () ? t2.xcell_value ("load: internal error loading struct elements") : Cell (t2);
955 
956  m.setfield (dsub.name, tcell);
957 
958  }
959 
960  if (retval2 >= 0)
961  {
962  map = m;
963  retval = true;
964  }
965 
966 #else
967  octave_unused_parameter (loc_id);
968  octave_unused_parameter (name);
969 
970  warn_load ("hdf5");
971 #endif
972 
973  return retval;
974 }
975 
976 mxArray *
978 {
979  int nf = nfields ();
980  string_vector kv = map_keys ();
981 
982  OCTAVE_LOCAL_BUFFER (const char *, f, nf);
983 
984  for (int i = 0; i < nf; i++)
985  f[i] = kv[i].c_str ();
986 
987  mxArray *retval = new mxArray (dims (), nf, f);
988 
989  mxArray **elts = static_cast<mxArray **> (retval->get_data ());
990 
991  mwSize nel = numel ();
992 
993  mwSize ntot = nf * nel;
994 
995  for (int i = 0; i < nf; i++)
996  {
997  Cell c = map.contents (kv[i]);
998 
999  const octave_value *p = c.data ();
1000 
1001  mwIndex k = 0;
1002  for (mwIndex j = i; j < ntot; j += nf)
1003  elts[j] = new mxArray (p[k++]);
1004  }
1005 
1006  return retval;
1007 }
1008 
1011 {
1012  if (n < map.numel ())
1013  return map.checkelem (n);
1014  else
1015  return octave_value ();
1016 }
1017 
1018 bool
1020  const octave_value& x)
1021 {
1022  bool retval = false;
1023 
1024  if (n < map.numel ())
1025  {
1026  // To avoid copying the scalar struct, it just stores a pointer to
1027  // itself.
1028  const octave_scalar_map *sm_ptr;
1029  void *here = reinterpret_cast<void *>(&sm_ptr);
1030  return (x.get_rep ().fast_elem_insert_self (here, btyp_struct)
1031  && map.fast_elem_insert (n, *sm_ptr));
1032  }
1033 
1034  return retval;
1035 }
1036 
1038  "struct");
1039 
1042 {
1044 
1045  assert (idx.length () == 1);
1046 
1047  std::string nm = idx(0).string_value ();
1048 
1049  maybe_warn_invalid_field_name (nm, "subsref");
1050 
1051  retval = map.getfield (nm);
1052 
1053  if (! auto_add && retval.is_undefined ())
1054  error_with_id ("Octave:invalid-indexing",
1055  "structure has no member '%s'", nm.c_str ());
1056 
1057  return retval;
1058 }
1059 
1062  const std::list<octave_value_list>& idx)
1063 {
1065 
1066  if (type[0] == '.')
1067  {
1068  int skip = 1;
1069 
1070  retval = dotref (idx.front ());
1071 
1072  if (idx.size () > 1)
1073  retval = retval.next_subsref (type, idx, skip);
1074  }
1075  else
1076  retval = to_array ().subsref (type, idx);
1077 
1078  return retval;
1079 }
1080 
1083  const std::list<octave_value_list>& idx,
1084  int nargout)
1085 {
1087 
1088  if (type[0] == '.')
1089  {
1090  int skip = 1;
1091 
1092  retval(0) = dotref (idx.front ());
1093 
1094  if (idx.size () > 1)
1095  retval = retval(0).next_subsref (nargout, type, idx, skip);
1096  }
1097  else
1098  retval = to_array ().subsref (type, idx, nargout);
1099 
1100  return retval;
1101 }
1102 
1105  const std::list<octave_value_list>& idx,
1106  bool auto_add)
1107 {
1109 
1110  if (type[0] == '.')
1111  {
1112  int skip = 1;
1113 
1114  retval = dotref (idx.front (), auto_add);
1115 
1116  if (idx.size () > 1)
1117  retval = retval.next_subsref (auto_add, type, idx, skip);
1118  }
1119  else
1120  retval = to_array ().subsref (type, idx, auto_add);
1121 
1122  return retval;
1123 }
1124 
1125 /*
1126 %!test
1127 %! x(1).a.a = 1;
1128 %! x(2).a.a = 2;
1129 %! assert (size (x), [1, 2]);
1130 %! assert (x(1).a.a, 1);
1131 %! assert (x(2).a.a, 2);
1132 */
1133 
1136  const std::string& type)
1137 {
1139 
1140  if (type.length () > 0 && type[0] == '.' && ! val.is_map ())
1141  retval = octave_map ();
1142  else
1143  retval = val;
1144 
1145  return retval;
1146 }
1147 
1150  const std::list<octave_value_list>& idx,
1151  const octave_value& rhs)
1152 {
1154 
1155  if (idx.front ().empty ())
1156  error ("missing index in indexed assignment");
1157 
1158  if (type[0] == '.')
1159  {
1160  int n = type.length ();
1161 
1162  octave_value t_rhs = rhs;
1163 
1164  octave_value_list key_idx = idx.front ();
1165 
1166  assert (key_idx.length () == 1);
1167 
1168  std::string key = key_idx(0).string_value ();
1169 
1170  maybe_warn_invalid_field_name (key, "subsasgn");
1171 
1172  if (n > 1)
1173  {
1174  std::list<octave_value_list> next_idx (idx);
1175 
1176  next_idx.erase (next_idx.begin ());
1177 
1178  std::string next_type = type.substr (1);
1179 
1180  octave_value tmp;
1181  octave_map::iterator pkey = map.seek (key);
1182  if (pkey != map.end ())
1183  {
1184  map.contents (pkey).make_unique ();
1185  tmp = map.contents (pkey);
1186  }
1187 
1188  bool orig_undefined = tmp.is_undefined ();
1189 
1190  if (orig_undefined || tmp.is_zero_by_zero ())
1191  {
1192  tmp = octave_value::empty_conv (next_type, rhs);
1193  tmp.make_unique (); // probably a no-op.
1194  }
1195  else
1196  // optimization: ignore the copy still stored inside our map.
1197  tmp.make_unique (1);
1198 
1199  t_rhs = (orig_undefined
1200  ? tmp.undef_subsasgn (next_type, next_idx, rhs)
1201  : tmp.subsasgn (next_type, next_idx, rhs));
1202  }
1203 
1204  map.setfield (key, t_rhs.storable_value ());
1205 
1206  count++;
1207  retval = this;
1208  }
1209  else
1210  {
1211  // Forward this case to octave_struct.
1213  retval = tmp.subsasgn (type, idx, rhs);
1214  }
1215 
1216  return retval;
1217 }
1218 
1221 {
1222  // octave_map handles indexing itself.
1223  return octave_map (map).index (idx, resize_ok);
1224 }
1225 
1226 size_t
1228 {
1229  // Neglect the size of the fieldnames.
1230 
1231  size_t retval = 0;
1232 
1233  for (octave_map::const_iterator p = map.begin (); p != map.end (); p++)
1234  {
1235  std::string key = map.key (p);
1236 
1238 
1239  retval += val.byte_size ();
1240  }
1241 
1242  return retval;
1243 }
1244 
1245 void
1246 octave_scalar_struct::print (std::ostream& os, bool)
1247 {
1248  print_raw (os);
1249 }
1250 
1251 void
1252 octave_scalar_struct::print_raw (std::ostream& os, bool) const
1253 {
1255 
1256  frame.protect_var (Vstruct_levels_to_print);
1257 
1258  if (Vstruct_levels_to_print >= 0)
1259  {
1260  bool max_depth_reached = Vstruct_levels_to_print-- == 0;
1261 
1262  bool print_fieldnames_only = max_depth_reached;
1263 
1265 
1266  if (! Vcompact_format)
1267  newline (os);
1268 
1269  indent (os);
1270  os << "scalar structure containing the fields:";
1271  newline (os);
1272  if (! Vcompact_format)
1273  newline (os);
1274 
1276 
1277  string_vector key_list = map.fieldnames ();
1278 
1279  for (octave_idx_type i = 0; i < key_list.numel (); i++)
1280  {
1281  std::string key = key_list[i];
1282 
1283  octave_value val = map.contents (key);
1284 
1285  if (print_fieldnames_only)
1286  {
1287  indent (os);
1288  os << key;
1289  dim_vector dv = val.dims ();
1290  os << ": " << dv.str () << " " << val.type_name ();
1291  newline (os);
1292  }
1293  else
1294  val.print_with_name (os, key);
1295  }
1296 
1299  }
1300  else
1301  {
1302  indent (os);
1303  os << "<structure>";
1304  newline (os);
1305  }
1306 }
1307 
1308 bool
1310  const std::string& name) const
1311 {
1312  bool retval = false;
1313 
1314  indent (os);
1315 
1316  if (Vstruct_levels_to_print < 0)
1317  os << name << " = ";
1318  else
1319  {
1320  os << name << " =";
1321  newline (os);
1322  retval = true;
1323  }
1324 
1325  return retval;
1326 }
1327 
1328 bool
1330 {
1331  octave_map m = map_value ();
1332 
1333  octave_idx_type nf = m.nfields ();
1334 
1335  const dim_vector dv = dims ();
1336 
1337  os << "# ndims: " << dv.ndims () << "\n";
1338 
1339  for (int i = 0; i < dv.ndims (); i++)
1340  os << " " << dv(i);
1341  os << "\n";
1342 
1343  os << "# length: " << nf << "\n";
1344 
1345  // Iterating over the list of keys will preserve the order of the
1346  // fields.
1347  string_vector keys = m.fieldnames ();
1348 
1349  for (octave_idx_type i = 0; i < nf; i++)
1350  {
1351  std::string key = keys(i);
1352 
1353  octave_value val = map.contents (key);
1354 
1355  bool b = save_text_data (os, val, key, false, 0);
1356 
1357  if (! b)
1358  return ! os.fail ();
1359  }
1360 
1361  return true;
1362 }
1363 
1364 bool
1366 {
1367  octave_idx_type len = 0;
1368 
1369  if (! extract_keyword (is, "length", len) || len < 0)
1370  error ("load: failed to extract number of elements in structure");
1371 
1372  if (len > 0)
1373  {
1375 
1376  for (octave_idx_type j = 0; j < len; j++)
1377  {
1378  octave_value t2;
1379  bool dummy;
1380 
1381  // recurse to read cell elements
1382  std::string nm
1383  = read_text_data (is, "", dummy, t2, j);
1384 
1385  if (! is)
1386  break;
1387 
1388  m.setfield (nm, t2);
1389  }
1390 
1391  if (! is)
1392  error ("load: failed to load structure");
1393 
1394  map = m;
1395  }
1396  else if (len == 0)
1397  map = octave_scalar_map ();
1398  else
1399  panic_impossible ();
1400 
1401  return true;
1402 }
1403 
1404 bool
1406 {
1407  octave_map m = map_value ();
1408 
1409  octave_idx_type nf = m.nfields ();
1410 
1411  int32_t len = nf;
1412  os.write (reinterpret_cast<char *> (&len), 4);
1413 
1414  // Iterating over the list of keys will preserve the order of the
1415  // fields.
1416  string_vector keys = m.fieldnames ();
1417 
1418  for (octave_idx_type i = 0; i < nf; i++)
1419  {
1420  std::string key = keys(i);
1421 
1422  octave_value val = map.contents (key);
1423 
1424  bool b = save_binary_data (os, val, key, "", 0, save_as_floats);
1425 
1426  if (! b)
1427  return ! os.fail ();
1428  }
1429 
1430  return true;
1431 }
1432 
1433 bool
1436 {
1437  bool success = true;
1438  int32_t len;
1439  if (! is.read (reinterpret_cast<char *> (&len), 4))
1440  return false;
1441  if (swap)
1442  swap_bytes<4> (&len);
1443 
1444  if (len > 0)
1445  {
1447 
1448  for (octave_idx_type j = 0; j < len; j++)
1449  {
1450  octave_value t2;
1451  bool dummy;
1452  std::string doc;
1453 
1454  // recurse to read cell elements
1455  std::string nm = read_binary_data (is, swap, fmt, "",
1456  dummy, t2, doc);
1457 
1458  if (! is)
1459  break;
1460 
1461  m.setfield (nm, t2);
1462  }
1463 
1464  if (! is)
1465  error ("load: failed to load structure");
1466 
1467  map = m;
1468  }
1469  else if (len == 0)
1470  map = octave_scalar_map ();
1471  else
1472  success = false;
1473 
1474  return success;
1475 }
1476 
1477 bool
1479  bool save_as_floats)
1480 {
1481 #if defined (HAVE_HDF5)
1482 
1483  hid_t data_hid = -1;
1484 
1485 #if defined (HAVE_HDF5_18)
1486  data_hid = H5Gcreate (loc_id, name, octave_H5P_DEFAULT, octave_H5P_DEFAULT,
1488 #else
1489  data_hid = H5Gcreate (loc_id, name, 0);
1490 #endif
1491  if (data_hid < 0) return false;
1492 
1493  // recursively add each element of the structure to this group
1495 
1496  octave_idx_type nf = m.nfields ();
1497 
1498  // Iterating over the list of keys will preserve the order of the
1499  // fields.
1500  string_vector keys = m.fieldnames ();
1501 
1502  for (octave_idx_type i = 0; i < nf; i++)
1503  {
1504  std::string key = keys(i);
1505 
1506  octave_value val = map.contents (key);
1507 
1508  bool retval2 = add_hdf5_data (data_hid, val, key, "", false,
1509  save_as_floats);
1510 
1511  if (! retval2)
1512  break;
1513  }
1514 
1515  H5Gclose (data_hid);
1516 
1517  return true;
1518 
1519 #else
1520  octave_unused_parameter (loc_id);
1521  octave_unused_parameter (name);
1522  octave_unused_parameter (save_as_floats);
1523 
1524  warn_save ("hdf5");
1525 
1526  return false;
1527 #endif
1528 }
1529 
1530 bool
1532 {
1533  bool retval = false;
1534 
1535 #if defined (HAVE_HDF5)
1536 
1537  hdf5_callback_data dsub;
1538 
1539  herr_t retval2 = 0;
1541  int current_item = 0;
1542  hsize_t num_obj = 0;
1543 #if defined (HAVE_HDF5_18)
1544  hid_t group_id = H5Gopen (loc_id, name, octave_H5P_DEFAULT);
1545 #else
1546  hid_t group_id = H5Gopen (loc_id, name);
1547 #endif
1548  H5Gget_num_objs (group_id, &num_obj);
1549  H5Gclose (group_id);
1550 
1551  // FIXME: fields appear to be sorted alphabetically on loading.
1552  // Why is that happening?
1553 
1554  while (current_item < static_cast<int> (num_obj)
1555  && (retval2 = hdf5_h5g_iterate (loc_id, name, &current_item,
1556  &dsub)) > 0)
1557  {
1558  octave_value t2 = dsub.tc;
1559 
1560  m.setfield (dsub.name, t2);
1561 
1562  }
1563 
1564  if (retval2 >= 0)
1565  {
1566  map = m;
1567  retval = true;
1568  }
1569 
1570 #else
1571  octave_unused_parameter (loc_id);
1572  octave_unused_parameter (name);
1573 
1574  warn_load ("hdf5");
1575 #endif
1576 
1577  return retval;
1578 }
1579 
1580 mxArray *
1582 {
1583  int nf = nfields ();
1584  string_vector kv = map_keys ();
1585 
1586  OCTAVE_LOCAL_BUFFER (const char *, f, nf);
1587 
1588  for (int i = 0; i < nf; i++)
1589  f[i] = kv[i].c_str ();
1590 
1591  mxArray *retval = new mxArray (dims (), nf, f);
1592 
1593  mxArray **elts = static_cast<mxArray **> (retval->get_data ());
1594 
1595  mwSize nel = numel ();
1596 
1597  mwSize ntot = nf * nel;
1598 
1599  for (int i = 0; i < nf; i++)
1600  {
1601  Cell c = map.contents (kv[i]);
1602 
1603  const octave_value *p = c.data ();
1604 
1605  mwIndex k = 0;
1606  for (mwIndex j = i; j < ntot; j += nf)
1607  elts[j] = new mxArray (p[k++]);
1608  }
1609 
1610  return retval;
1611 }
1612 
1615 {
1616  return new octave_struct (octave_map (map));
1617 }
1618 
1619 bool
1621  builtin_type_t btyp) const
1622 {
1623 
1624  if (btyp == btyp_struct)
1625  {
1626  *(reinterpret_cast<const octave_scalar_map **>(where)) = &map;
1627  return true;
1628  }
1629  else
1630  return false;
1631 }
1632 
1633 DEFUN (struct, args, ,
1634  doc: /* -*- texinfo -*-
1635 @deftypefn {} {@var{s} =} struct ()
1636 @deftypefnx {} {@var{s} =} struct (@var{field1}, @var{value1}, @var{field2}, @var{value2}, @dots{})
1637 @deftypefnx {} {@var{s} =} struct (@var{obj})
1638 
1639 Create a scalar or array structure and initialize its values.
1640 
1641 The @var{field1}, @var{field2}, @dots{} variables are strings specifying the
1642 names of the fields and the @var{value1}, @var{value2}, @dots{} variables
1643 can be of any type.
1644 
1645 If the values are cell arrays, create a structure array and initialize its
1646 values. The dimensions of each cell array of values must match. Singleton
1647 cells and non-cell values are repeated so that they fill the entire array.
1648 If the cells are empty, create an empty structure array with the specified
1649 field names.
1650 
1651 If the argument is an object, return the underlying struct.
1652 
1653 Observe that the syntax is optimized for struct @strong{arrays}. Consider
1654 the following examples:
1655 
1656 @example
1657 @group
1658 struct ("foo", 1)
1659  @result{} scalar structure containing the fields:
1660  foo = 1
1661 
1662 struct ("foo", @{@})
1663  @result{} 0x0 struct array containing the fields:
1664  foo
1665 
1666 struct ("foo", @{ @{@} @})
1667  @result{} scalar structure containing the fields:
1668  foo = @{@}(0x0)
1669 
1670 struct ("foo", @{1, 2, 3@})
1671  @result{} 1x3 struct array containing the fields:
1672  foo
1673 
1674 @end group
1675 @end example
1676 
1677 @noindent
1678 The first case is an ordinary scalar struct---one field, one value. The
1679 second produces an empty struct array with one field and no values, since
1680 being passed an empty cell array of struct array values. When the value is
1681 a cell array containing a single entry, this becomes a scalar struct with
1682 that single entry as the value of the field. That single entry happens
1683 to be an empty cell array.
1684 
1685 Finally, if the value is a non-scalar cell array, then @code{struct}
1686 produces a struct @strong{array}.
1687 @seealso{cell2struct, fieldnames, getfield, setfield, rmfield, isfield, orderfields, isstruct, structfun}
1688 @end deftypefn */)
1689 {
1690  int nargin = args.length ();
1691 
1692  // struct ([]) returns an empty struct.
1693 
1694  // struct (empty_matrix) returns an empty struct with the same
1695  // dimensions as the empty matrix.
1696 
1697  // Note that struct () creates a 1x1 struct with no fields for
1698  // compatibility with Matlab.
1699 
1700  if (nargin == 1 && args(0).is_map ())
1701  return ovl (args(0));
1702 
1703  if (nargin == 1 && args(0).is_object ())
1704  return ovl (args(0).map_value ());
1705 
1706  if ((nargin == 1 || nargin == 2)
1707  && args(0).is_empty () && args(0).is_real_matrix ())
1708  {
1709  if (nargin == 2)
1710  {
1711  Array<std::string> cstr = args(1).xcellstr_value ("struct: second argument should be a cell array of field names");
1712 
1713  return ovl (octave_map (args(0).dims (), cstr));
1714  }
1715  else
1716  return ovl (octave_map (args(0).dims ()));
1717  }
1718 
1719  // Check for "field", VALUE pairs.
1720 
1721  for (int i = 0; i < nargin; i += 2)
1722  {
1723  if (! args(i).is_string () || i + 1 >= nargin)
1724  error ("struct: additional arguments must occur as \"field\", VALUE pairs");
1725  }
1726 
1727  // Check that the dimensions of the values correspond.
1728 
1729  dim_vector dims (1, 1);
1730 
1732 
1733  for (int i = 1; i < nargin; i += 2)
1734  {
1735  if (args(i).is_cell ())
1736  {
1737  dim_vector argdims (args(i).dims ());
1738 
1739  if (! scalar (argdims))
1740  {
1741  if (! first_dimensioned_value)
1742  {
1743  dims = argdims;
1744  first_dimensioned_value = i + 1;
1745  }
1746  else if (dims != argdims)
1747  {
1748  error ("struct: dimensions of parameter %d "
1749  "do not match those of parameter %d",
1750  first_dimensioned_value, i+1);
1751  }
1752  }
1753  }
1754  }
1755 
1756  // Create the return value.
1757 
1758  octave_map map (dims);
1759 
1760  for (int i = 0; i < nargin; i+= 2)
1761  {
1762  // Get key.
1763 
1764  std::string key (args(i).string_value ());
1765 
1766  maybe_warn_invalid_field_name (key, "struct");
1767 
1768  // Value may be v, { v }, or { v1, v2, ... }
1769  // In the first two cases, we need to create a cell array of
1770  // the appropriate dimensions filled with v. In the last case,
1771  // the cell array has already been determined to be of the
1772  // correct dimensions.
1773 
1774  if (args(i+1).is_cell ())
1775  {
1776  const Cell c (args(i+1).cell_value ());
1777 
1778  if (scalar (c.dims ()))
1779  map.setfield (key, Cell (dims, c(0)));
1780  else
1781  map.setfield (key, c);
1782  }
1783  else
1784  map.setfield (key, Cell (dims, args(i+1)));
1785  }
1786 
1787  return ovl (map);
1788 }
1789 
1790 /*
1791 %!shared x
1792 %! x(1).a=1; x(2).a=2; x(1).b=3; x(2).b=3;
1793 %!assert (struct ("a",1, "b",3), x(1))
1794 %!assert (isempty (x([])))
1795 %!assert (isempty (struct ("a",{}, "b",{})))
1796 %!assert (struct ("a",{1,2}, "b",{3,3}), x)
1797 %!assert (struct ("a",{1,2}, "b",3), x)
1798 %!assert (struct ("a",{1,2}, "b",{3}), x)
1799 %!assert (struct ("b",3, "a",{1,2}), x)
1800 %!assert (struct ("b",{3}, "a",{1,2}), x)
1801 %!test x = struct ([]);
1802 %!assert (size (x), [0,0])
1803 %!assert (isstruct (x))
1804 %!assert (isempty (fieldnames (x)))
1805 %!fail ('struct ("a",{1,2},"b",{1,2,3})', 'dimensions of parameter 2 do not match those of parameter 4')
1806 %!error <arguments must occur as "field", VALUE pairs> struct (1,2,3,4)
1807 %!fail ('struct ("1",2,"3")', 'struct: additional arguments must occur as "field", VALUE pairs')
1808 */
1809 
1810 DEFUN (isstruct, args, ,
1811  doc: /* -*- texinfo -*-
1812 @deftypefn {} {} isstruct (@var{x})
1813 Return true if @var{x} is a structure or a structure array.
1814 @seealso{ismatrix, iscell, isa}
1815 @end deftypefn */)
1816 {
1817  if (args.length () != 1)
1818  print_usage ();
1819 
1820  return ovl (args(0).is_map ());
1821 }
1822 
1823 DEFUN (__fieldnames__, args, ,
1824  doc: /* -*- texinfo -*-
1825 @deftypefn {} {} __fieldnames__ (@var{struct})
1826 @deftypefnx {} {} __fieldnames__ (@var{obj})
1827 Internal function.
1828 
1829 Implements @code{fieldnames()} for structures and Octave objects.
1830 @seealso{fieldnames}
1831 @end deftypefn */)
1832 {
1834 
1835  // Input validation has already been done in fieldnames.m.
1836  octave_value arg = args(0);
1837 
1838  octave_map m = arg.map_value ();
1839 
1840  string_vector keys = m.fieldnames ();
1841 
1842  if (keys.is_empty ())
1843  retval = Cell (0, 1);
1844  else
1845  retval = Cell (keys);
1846 
1847  return retval;
1848 }
1849 
1850 DEFUN (isfield, args, ,
1851  doc: /* -*- texinfo -*-
1852 @deftypefn {} {} isfield (@var{x}, "@var{name}")
1853 @deftypefnx {} {} isfield (@var{x}, @var{name})
1854 Return true if the @var{x} is a structure and it includes an element named
1855 @var{name}.
1856 
1857 If @var{name} is a cell array of strings then a logical array of equal
1858 dimension is returned.
1859 @seealso{fieldnames}
1860 @end deftypefn */)
1861 {
1862  if (args.length () != 2)
1863  print_usage ();
1864 
1865  octave_value retval = false;
1866 
1867  if (args(0).is_map ())
1868  {
1869  octave_map m = args(0).map_value ();
1870 
1871  // FIXME: should this work for all types that can do
1872  // structure reference operations?
1873  if (args(1).is_string ())
1874  {
1875  std::string key = args(1).string_value ();
1876 
1877  retval = m.isfield (key);
1878  }
1879  else if (args(1).is_cell ())
1880  {
1881  Cell c = args(1).cell_value ();
1882  boolNDArray bm (c.dims ());
1883  octave_idx_type n = bm.numel ();
1884 
1885  for (octave_idx_type i = 0; i < n; i++)
1886  {
1887  if (c(i).is_string ())
1888  {
1889  std::string key = c(i).string_value ();
1890 
1891  bm(i) = m.isfield (key);
1892  }
1893  else
1894  bm(i) = false;
1895  }
1896 
1897  retval = bm;
1898  }
1899  }
1900 
1901  return retval;
1902 }
1903 
1904 DEFUN (numfields, args, ,
1905  doc: /* -*- texinfo -*-
1906 @deftypefn {} {} numfields (@var{s})
1907 Return the number of fields of the structure @var{s}.
1908 @seealso{fieldnames}
1909 @end deftypefn */)
1910 {
1911  if (args.length () != 1)
1912  print_usage ();
1913 
1914  if (! args(0).is_map ())
1915  error ("numfields: argument must be a struct");
1916 
1917  return ovl (static_cast<double> (args(0).nfields ()));
1918 }
1919 
1920 /*
1921 ## test isfield
1922 %!test
1923 %! x(3).d=1; x(2).a=2; x(1).b=3; x(2).c=3;
1924 %! assert (isfield (x, "b"));
1925 %!assert (isfield (struct ("a", "1"), "a"))
1926 %!assert (isfield ({1}, "c"), false)
1927 %!assert (isfield (struct ("a", "1"), 10), false)
1928 %!assert (isfield (struct ("a", "b"), "a "), false)
1929 %!assert (isfield (struct ("a", 1, "b", 2), {"a", "c"}), [true, false])
1930 */
1931 
1932 DEFUN (cell2struct, args, ,
1933  doc: /* -*- texinfo -*-
1934 @deftypefn {} {} cell2struct (@var{cell}, @var{fields})
1935 @deftypefnx {} {} cell2struct (@var{cell}, @var{fields}, @var{dim})
1936 Convert @var{cell} to a structure.
1937 
1938 The number of fields in @var{fields} must match the number of elements in
1939 @var{cell} along dimension @var{dim}, that is
1940 @code{numel (@var{fields}) == size (@var{cell}, @var{dim})}. If @var{dim}
1941 is omitted, a value of 1 is assumed.
1942 
1943 @example
1944 @group
1945 A = cell2struct (@{"Peter", "Hannah", "Robert";
1946  185, 170, 168@},
1947  @{"Name","Height"@}, 1);
1948 A(1)
1949  @result{}
1950  @{
1951  Name = Peter
1952  Height = 185
1953  @}
1954 
1955 @end group
1956 @end example
1957 @seealso{struct2cell, cell2mat, struct}
1958 @end deftypefn */)
1959 {
1960  int nargin = args.length ();
1961 
1962  if (nargin < 2 || nargin > 3)
1963  print_usage ();
1964 
1965  if (! args(0).is_cell ())
1966  error ("cell2struct: argument CELL must be of type cell");
1967 
1968  if (! (args(1).is_cellstr () || args(1).is_char_matrix ()))
1969  error ("cell2struct: FIELDS must be a cell array of strings or a character matrix");
1970 
1971  int dim = 0;
1972 
1973  if (nargin == 3)
1974  {
1975  if (! args(2).is_real_scalar ())
1976  error ("cell2struct: DIM must be a real scalar");
1977 
1978  dim = nargin == 2 ? 0 : args(2).int_value () - 1;
1979  }
1980 
1981  if (dim < 0)
1982  error ("cell2struct: DIM must be a valid dimension");
1983 
1984  const Cell vals = args(0).cell_value ();
1985  const Array<std::string> fields = args(1).cellstr_value ();
1986 
1987  octave_idx_type ext = vals.ndims () > dim ? vals.dims ()(dim) : 1;
1988 
1989  if (ext != fields.numel ())
1990  error ("cell2struct: number of FIELDS does not match dimension");
1991 
1992  int nd = std::max (dim+1, vals.ndims ());
1993  // result dimensions.
1994  dim_vector rdv = vals.dims ().redim (nd);
1995 
1996  assert (ext == rdv(dim));
1997  if (nd == 2)
1998  {
1999  rdv(0) = rdv(1-dim);
2000  rdv(1) = 1;
2001  }
2002  else
2003  {
2004  for (int i = dim + 1; i < nd; i++)
2005  rdv(i-1) = rdv(i);
2006 
2007  rdv.resize (nd-1);
2008  }
2009 
2010  octave_map map (rdv);
2012 
2013  for (octave_idx_type i = 0; i < ext; i++)
2014  {
2015  ia(dim) = i;
2016  map.setfield (fields(i), vals.index (ia).reshape (rdv));
2017  }
2018 
2019  return ovl (map);
2020 }
2021 
2022 /*
2023 ## test cell2struct versus struct2cell
2024 %!test
2025 %! keys = cellstr (char (floor (rand (100,10)*24+65)))';
2026 %! vals = mat2cell (rand (100,1), ones (100,1), 1)';
2027 %! s = struct ([keys; vals]{:});
2028 %! t = cell2struct (vals, keys, 2);
2029 %! assert (s, t);
2030 %! assert (struct2cell (s), vals');
2031 %! assert (fieldnames (s), keys');
2032 
2033 %!assert (cell2struct ({1; 2}, {"a"; "b"}), struct ("a", 1, "b", 2))
2034 
2035 %!assert (cell2struct ({}, {"f"}, 3), struct ("f", {}))
2036 */
2037 
2038 // FIXME: we should be including builtin-defun-decls.h but doing that
2039 // currently exposes a problem with dependencies in the the build system.
2041 Fcellstr (const octave_value_list& = octave_value_list (), int = 0);
2042 
2043 DEFUN (rmfield, args, ,
2044  doc: /* -*- texinfo -*-
2045 @deftypefn {} {@var{sout} =} rmfield (@var{s}, "@var{f}")
2046 @deftypefnx {} {@var{sout} =} rmfield (@var{s}, @var{f})
2047 Return a @emph{copy} of the structure (array) @var{s} with the field @var{f}
2048 removed.
2049 
2050 If @var{f} is a cell array of strings or a character array, remove each of
2051 the named fields.
2052 @seealso{orderfields, fieldnames, isfield}
2053 @end deftypefn */)
2054 {
2055  if (args.length () != 2)
2056  print_usage ();
2057 
2058  octave_map m = args(0).xmap_value ("rmfield: first argument must be a struct");
2059 
2061 
2063 
2064  for (int i = 0; i < fcell.numel (); i++)
2065  {
2066  std::string key = fcell(i).string_value ();
2067 
2068  if (! m.isfield (key))
2069  error ("rmfield: structure does not contain field %s", key.c_str ());
2070 
2071  m.rmfield (key);
2072  }
2073 
2074  return ovl (m);
2075 }
2076 
2077 /*
2078 ## test rmfield
2079 %!shared x
2080 %! x(3).d=1; x(2).a=2; x(1).b=3; x(2).c=3; x(6).f="abc123";
2081 %!
2082 %!test
2083 %! y = rmfield (x, "c");
2084 %! assert (fieldnames (y), {"d"; "a"; "b"; "f"});
2085 %! assert (size (y), [1, 6]);
2086 %!test
2087 %! y = rmfield (x, {"a", "f"});
2088 %! assert (fieldnames (y), {"d"; "b"; "c"});
2089 %! assert (size (y), [1, 6]);
2090 */
2091 
2092 DEFUN (struct_levels_to_print, args, nargout,
2093  doc: /* -*- texinfo -*-
2094 @deftypefn {} {@var{val} =} struct_levels_to_print ()
2095 @deftypefnx {} {@var{old_val} =} struct_levels_to_print (@var{new_val})
2096 @deftypefnx {} {} struct_levels_to_print (@var{new_val}, "local")
2097 Query or set the internal variable that specifies the number of
2098 structure levels to display.
2099 
2100 When called from inside a function with the @qcode{"local"} option, the
2101 variable is changed locally for the function and any subroutines it calls.
2102 The original variable value is restored when exiting the function.
2103 @seealso{print_struct_array_contents}
2104 @end deftypefn */)
2105 {
2106  return SET_INTERNAL_VARIABLE_WITH_LIMITS (struct_levels_to_print, -1,
2108 }
2109 
2110 DEFUN (print_struct_array_contents, args, nargout,
2111  doc: /* -*- texinfo -*-
2112 @deftypefn {} {@var{val} =} print_struct_array_contents ()
2113 @deftypefnx {} {@var{old_val} =} print_struct_array_contents (@var{new_val})
2114 @deftypefnx {} {} print_struct_array_contents (@var{new_val}, "local")
2115 Query or set the internal variable that specifies whether to print struct
2116 array contents.
2117 
2118 If true, values of struct array elements are printed. This variable does
2119 not affect scalar structures whose elements are always printed. In both
2120 cases, however, printing will be limited to the number of levels specified
2121 by @var{struct_levels_to_print}.
2122 
2123 When called from inside a function with the @qcode{"local"} option, the
2124 variable is changed locally for the function and any subroutines it calls.
2125 The original variable value is restored when exiting the function.
2126 @seealso{struct_levels_to_print}
2127 @end deftypefn */)
2128 {
2129  return SET_INTERNAL_VARIABLE (print_struct_array_contents);
2130 }
static void err_invalid_index_for_assignment(void)
Definition: ov-struct.cc:95
void warning_with_id(const char *id, const char *fmt,...)
Definition: error.cc:803
dim_vector dims(1, 1)
scalar structure containing the one value The second produces an empty struct array with one field and no values since being passed an empty cell array of struct array values When the value is a cell array containing a single entry this becomes a scalar struct with that single entry as the value of the field That single entry happens to be an empty cell array Finally if the value is a non scalar cell array then ode isstruct
bool is_object(void) const
Definition: ov.h:593
#define SET_INTERNAL_VARIABLE_WITH_LIMITS(NM, MINVAL, MAXVAL)
Definition: variables.h:132
size_t byte_size(void) const
Definition: ov-struct.cc:1227
const Cell & contents(const_iterator p) const
Definition: oct-map.h:313
bool is_empty(void) const
Definition: Array.h:575
scalar structure containing the fields
Definition: ov-struct.cc:1688
Definition: Cell.h:37
octave_idx_type nfields(void) const
Definition: oct-map.h:203
dim_vector dims(void) const
Definition: ov-struct.h:99
std::string str(char sep= 'x') const
Definition: dim-vector.cc:73
octave_refcount< octave_idx_type > count
Definition: ov-base.h:843
void err_nonbraced_cs_list_assignment(void)
Definition: errwarn.cc:80
octave_map xmap_value(const char *fmt,...) const
Definition: ov.cc:2130
void delete_elements(const idx_vector &i)
Definition: oct-map.cc:1200
octave_value subsref(const std::string &type, const std::list< octave_value_list > &idx)
Definition: ov.h:417
OCTINTERP_API octave_value_list Fcellstr(const octave_value_list &=octave_value_list(), int=0)
void increment_indent_level(void) const
Definition: ov-base.h:824
bool fast_elem_insert_self(void *where, builtin_type_t btyp) const
Definition: ov-struct.cc:1620
void assign(const std::string &k, const Cell &val)
Definition: oct-map.h:347
Cell reshape(const dim_vector &new_dims) const
Definition: Cell.h:92
octave_value fast_elem_extract(octave_idx_type n) const
Definition: ov-struct.cc:1010
dim_vector dims(void) const
Definition: ov-struct.h:215
static const idx_vector colon
Definition: idx-vector.h:482
int ndims(void) const
Definition: Array.h:590
OCTINTERP_API void print_usage(void)
Definition: defun.cc:52
octave_value tc
Definition: ls-hdf5.h:107
octave_idx_type numel(void) const
Number of elements in the array.
Definition: Array.h:363
identity matrix If supplied two scalar respectively For allows like xample val
Definition: data.cc:5068
F77_RET_T F77_REAL &F77_RET_T F77_DBLE &F77_RET_T F77_REAL &F77_RET_T F77_DBLE &F77_RET_T F77_REAL &F77_RET_T F77_DBLE &F77_RET_T const F77_REAL const F77_REAL F77_REAL &F77_RET_T const F77_DBLE const F77_DBLE F77_DBLE &F77_RET_T F77_REAL &F77_RET_T F77_DBLE &F77_RET_T F77_DBLE &F77_RET_T F77_REAL &F77_RET_T F77_REAL &F77_RET_T F77_DBLE &F77_RET_T const F77_DBLE F77_DBLE &F77_RET_T const F77_REAL F77_REAL &F77_RET_T F77_REAL F77_REAL &F77_RET_T F77_DBLE F77_DBLE &F77_RET_T const F77_DBLE const F77_DBLE * f
octave_value do_index_op(const octave_value_list &idx, bool resize_ok=false)
Definition: ov-struct.cc:1220
octave_idx_type length(void) const
Definition: ovl.h:96
const octave_value & contents(const_iterator p) const
Definition: oct-map.h:190
octave_scalar_map scalar_map_value(void) const
Definition: ov-struct.h:244
const_iterator iterator
Definition: oct-map.h:301
octave_map map_value(void) const
Definition: ov.cc:1693
static bool Vprint_struct_array_contents
Definition: ov-struct.cc:59
bool save_ascii(std::ostream &os)
Definition: ov-struct.cc:654
Cell xcell_value(const char *fmt,...) const
Definition: ov.cc:2125
octave_idx_type nfields(void) const
Definition: ov-struct.h:110
std::string name
Definition: ls-hdf5.h:101
for large enough k
Definition: lu.cc:606
void resize(int n, int fill_value=0)
Definition: dim-vector.h:316
string_vector map_keys(void) const
Definition: ov-struct.h:128
void protect_var(T &var)
#define DEFUN(name, args_name, nargout_name, doc)
Definition: defun.h:46
void error(const char *fmt,...)
Definition: error.cc:570
bool load_hdf5(octave_hdf5_id loc_id, const char *name)
Definition: ov-struct.cc:1531
bool save_hdf5(octave_hdf5_id loc_id, const char *name, bool save_as_floats)
Definition: ov-struct.cc:1478
bool fast_elem_insert(octave_idx_type n, const octave_value &x)
Definition: ov-struct.cc:1019
string_vector fieldnames(void) const
Definition: oct-map.h:212
#define SET_INTERNAL_VARIABLE(NM)
Definition: variables.h:126
void indent(std::ostream &os) const
Definition: ov-base.cc:1362
void * get_data(void) const
Definition: mxarray.h:449
bool save_ascii(std::ostream &os)
Definition: ov-struct.cc:1329
void make_unique(void)
Definition: ov.h:327
void setfield(const std::string &key, const octave_value &val)
Definition: oct-map.cc:178
#define DEFINE_OV_TYPEID_FUNCTIONS_AND_DATA(t, n, c)
Definition: ov-base.h:169
octave_value to_array(void)
Definition: ov-struct.cc:1614
void print_raw(std::ostream &os, bool pr_as_read_syntax=false) const
Definition: ov-struct.cc:1252
bool is_cell(void) const
Definition: ov.h:545
bool load_ascii(std::istream &is)
Definition: ov-struct.cc:1365
octave_idx_type numel(void) const
Definition: oct-map.h:371
OCTAVE_EXPORT octave_value_list return the number of command line arguments passed to Octave If called with the optional argument the function t
Definition: ov-usr-fcn.cc:935
octave_map map
Definition: ov-struct.h:160
virtual bool fast_elem_insert_self(void *where, builtin_type_t btyp) const
Definition: ov-base.cc:1410
scalar structure containing the one value The second produces an empty struct array with one field and no values since being passed an empty cell array of struct array values When the value is a cell array containing a single entry this becomes a scalar struct with that single entry as the value of the field That single entry happens to be an empty cell array Finally if the value is a non scalar cell array then ode rmfield
octave_idx_type numel(void) const
Definition: ov-struct.h:105
builtin_type_t
Definition: ov-base.h:61
bool load_binary(std::istream &is, bool swap, octave::mach_info::float_format fmt)
Definition: ov-struct.cc:1434
void newline(std::ostream &os) const
Definition: ov-base.cc:1381
const_iterator end(void) const
Definition: oct-map.h:304
bool is_empty(void) const
Definition: ov-base.h:355
octave_value arg
Definition: pr-output.cc:3440
octave_value subsasgn(const std::string &type, const std::list< octave_value_list > &idx, const octave_value &rhs)
Definition: ov.cc:1540
Cell cell_value(void) const
Definition: ovl.h:88
bool swap
Definition: load-save.cc:725
JNIEnv void * args
Definition: ov-java.cc:67
void err_indexed_cs_list(void)
Definition: errwarn.cc:62
const dim_vector & dims(void) const
Return a const-reference so that dims ()(i) works efficiently.
Definition: Array.h:439
void warn_load(const char *type) const
Definition: ov-base.cc:1151
scalar structure containing the one value The second produces an empty struct array with one field and no values since being passed an empty cell array of struct array values When the value is a cell array containing a single entry this becomes a scalar struct with that single entry as the value of the field That single entry happens to be an empty cell array Finally if the value is a non scalar cell array then ode cell2struct
bool load_binary(std::istream &is, bool swap, octave::mach_info::float_format fmt)
Definition: ov-struct.cc:801
octave_value do_index_op(const octave_value_list &idx, bool resize_ok=false)
Definition: ov-struct.cc:537
bool Vcompact_format
Definition: pr-output.cc:107
octave_map map_value(void) const
Definition: ov-struct.h:126
OCTAVE_EXPORT octave_value_list any number nd example oindent prints the prompt xample Pick a any number!nd example oindent and waits for the user to enter a value The string entered by the user is evaluated as an so it may be a literal a variable name
Definition: input.cc:871
Cell fcell
Definition: ov-struct.cc:2062
OCTAVE_EXPORT octave_value_list isdir nd deftypefn *std::string nm
Definition: utils.cc:941
static octave_value numeric_conv(const octave_value &val, const std::string &type)
Definition: ov-struct.cc:1135
void swap_bytes< 4 >(void *ptr)
Definition: byte-swap.h:60
static void err_invalid_index_type(const std::string &nm, char t)
Definition: ov-struct.cc:101
bool is_null_value(void) const
Definition: ov.h:608
OCTAVE_EXPORT octave_value_list return the number of command line arguments passed to Octave If called with the optional argument the function xample nargout(@histc)
Definition: ov-usr-fcn.cc:935
#define OCTINTERP_API
Definition: mexproto.h:69
const_iterator begin(void) const
Definition: oct-map.h:180
bool save_text_data(std::ostream &os, const octave_value &val_arg, const std::string &name, bool mark_as_global, int precision)
Definition: ls-oct-text.cc:300
std::string key(const_iterator p) const
Definition: oct-map.h:185
bool isfield(const std::string &name) const
Definition: oct-map.h:329
bool valid_identifier(const char *s)
Definition: utils.cc:74
std::string extract_keyword(std::istream &is, const char *keyword, const bool next_only)
Definition: ls-oct-text.cc:80
octave_idx_type nfields(void) const
Definition: oct-map.h:326
Cell dotref(const octave_value_list &idx, bool auto_add=false)
Definition: ov-struct.cc:73
void make_unique(void)
Definition: Array.h:185
void error_with_id(const char *id, const char *fmt,...)
Definition: error.cc:615
nd deftypefn *octave_map m
Definition: ov-struct.cc:2058
void print_raw(std::ostream &os, bool pr_as_read_syntax=false) const
Definition: ov-struct.cc:569
bool print_name_tag(std::ostream &os, const std::string &name) const
Definition: ov-struct.cc:629
const T * data(void) const
Definition: Array.h:582
octave_value subsasgn(const std::string &type, const std::list< octave_value_list > &idx, const octave_value &rhs)
Definition: ov-struct.cc:272
bool save_as_floats
Definition: load-save.cc:1581
bool fast_elem_insert(octave_idx_type n, const octave_scalar_map &rhs)
Definition: oct-map.cc:401
std::string read_binary_data(std::istream &is, bool swap, octave::mach_info::float_format fmt, const std::string &filename, bool &global, octave_value &tc, std::string &doc)
double tmp
Definition: data.cc:6300
const_iterator end(void) const
Definition: oct-map.h:181
octave_hdf5_err hdf5_h5g_iterate(octave_hdf5_id loc_id, const char *name, int *idx, void *operator_data)
Definition: ls-hdf5.cc:706
octave_value retval
Definition: data.cc:6294
#define panic_impossible()
Definition: error.h:40
void rmfield(const std::string &key)
Definition: oct-map.cc:286
bool save_hdf5(octave_hdf5_id loc_id, const char *name, bool save_as_floats)
Definition: ov-struct.cc:872
int64_t octave_hdf5_id
dim_vector redim(int n) const
Definition: dim-vector.cc:275
std::string key(const_iterator p) const
Definition: oct-map.h:308
scalar structure containing the one value The second produces an empty struct array with one field and no values since being passed an empty cell array of struct array values When the value is a cell array containing a single entry this becomes a scalar struct with that single entry as the value of the field That single entry happens to be an empty cell array Finally if the value is a non scalar cell array then ode nargin
octave_idx_type length(void) const
Definition: ov.cc:1623
octave_value subsasgn(const std::string &type, const std::list< octave_value_list > &idx, const octave_value &rhs)
Definition: ov-struct.cc:1149
idx type
Definition: ov.cc:3129
the sparsity preserving column transformation such that that defines the pivoting threshold can be given in which case it defines the c
Definition: lu.cc:138
const_iterator begin(void) const
Definition: oct-map.h:303
dim_vector dims(void) const
Definition: ov.h:486
void decrement_indent_level(void) const
Definition: ov-base.h:827
void warn_save(const char *type) const
Definition: ov-base.cc:1160
void mxArray
Definition: mex.h:55
mxArray * as_mxArray(void) const
Definition: ov-struct.cc:1581
friend class octave_value
Definition: ov-base.h:211
void setfield(const std::string &key, const Cell &val)
Definition: oct-map.cc:270
octave_value subsref(const std::string &type, const std::list< octave_value_list > &idx)
Definition: ov-struct.h:70
bool is_map(void) const
Definition: ov.h:590
void print(std::ostream &os, bool pr_as_read_syntax=false)
Definition: ov-struct.cc:563
octave::unwind_protect frame
Definition: graphics.cc:11584
static int Vstruct_levels_to_print
Definition: ov-struct.cc:55
std::string type_name(void) const
Definition: ov.h:1232
charNDArray max(char d, const charNDArray &m)
Definition: chNDArray.cc:228
bool load_hdf5(octave_hdf5_id loc_id, const char *name)
Definition: ov-struct.cc:925
octave_value undef_subsasgn(const std::string &type, const std::list< octave_value_list > &idx, const octave_value &rhs)
Definition: ov.cc:1548
octave_idx_type nfields(void) const
Definition: ov-struct.h:226
scalar structure containing the one value The second produces an empty struct array with one field and no values since being passed an empty cell array of struct array values When the value is a cell array containing a single entry this becomes a scalar struct with that single entry as the value of the field That single entry happens to be an empty cell array Finally if the value is a non scalar cell array then ode isfield
bool print_name_tag(std::ostream &os, const std::string &name) const
Definition: ov-struct.cc:1309
octave_value dotref(const octave_value_list &idx, bool auto_add=false)
Definition: ov-struct.cc:1041
std::string type_name(void) const
Definition: ov-struct.h:164
static octave_value numeric_conv(const octave_value &val, const std::string &type)
Definition: ov-struct.cc:258
bool save_binary_data(std::ostream &os, const octave_value &tc, const std::string &name, const std::string &doc, bool mark_as_global, bool save_as_floats)
=val(i)}if ode{val(i)}occurs in table i
Definition: lookup.cc:239
size_t byte_size(void) const
Definition: ov-struct.cc:544
void maybe_mutate(void)
Definition: ov.cc:1155
bool save_binary(std::ostream &os, bool &save_as_floats)
Definition: ov-struct.cc:1405
const octave_base_value & get_rep(void) const
Definition: ov.h:1270
p
Definition: lu.cc:138
bool is_cs_list(void) const
Definition: ov.h:602
octave_map map(dims)
std::string read_text_data(std::istream &is, const std::string &filename, bool &global, octave_value &tc, octave_idx_type count)
Definition: ls-oct-text.cc:236
void print_with_name(std::ostream &os, const std::string &name) const
Definition: ov.h:1225
octave_idx_type ndims(void) const
Number of dimensions.
Definition: dim-vector.h:301
b
Definition: cellfun.cc:398
Cell index(const octave_value_list &idx, bool resize_ok=false) const
Definition: Cell.cc:155
#define OCTAVE_LOCAL_BUFFER(T, buf, size)
Definition: oct-locbuf.h:200
const_iterator seek(const std::string &k) const
Definition: oct-map.h:306
mxArray * as_mxArray(void) const
Definition: ov-struct.cc:977
bool is_undefined(void) const
Definition: ov.h:539
bool load_ascii(std::istream &is)
Definition: ov-struct.cc:690
const octave_hdf5_id octave_H5P_DEFAULT
octave_value_list list_value(void) const
Definition: ov.cc:1741
octave_scalar_map checkelem(octave_idx_type n) const
Definition: oct-map.cc:358
octave_value getfield(const std::string &key) const
Definition: oct-map.cc:171
octave_idx_type index(const_iterator p) const
Definition: oct-map.h:310
octave_value subsref(const std::string &type, const std::list< octave_value_list > &idx)
Definition: ov-struct.cc:1061
octave_scalar_map map
Definition: ov-struct.h:274
bool all_scalars(void) const
Definition: ovl.cc:175
octave_fields::const_iterator const_iterator
Definition: oct-map.h:300
const_iterator seek(const std::string &k) const
Definition: oct-map.h:183
string_vector map_keys(void) const
Definition: ov-struct.h:246
octave_map map_value(void) const
Definition: ov-struct.h:242
static void maybe_warn_invalid_field_name(const std::string &key, const char *who)
Definition: ov-struct.cc:107
static const char *const keywords[]
Definition: help.cc:147
return ovl(map)
write the output to stdout if nargout is
Definition: load-save.cc:1576
bool save_binary(std::ostream &os, bool &save_as_floats)
Definition: ov-struct.cc:759
Vector representing the dimensions (size) of an Array.
Definition: dim-vector.h:87
bool add_hdf5_data(octave_hdf5_id loc_id, const octave_value &tc, const std::string &name, const std::string &doc, bool mark_as_global, bool save_as_floats)
Definition: ls-hdf5.cc:1053
octave_value storable_value(void) const
Definition: ov.cc:2166
If this string is the system will ring the terminal sometimes it is useful to be able to print the original representation of the string
Definition: utils.cc:854
string_vector fieldnames(void) const
Definition: oct-map.h:335
int first_dimensioned_value
Definition: ov-struct.cc:1731
dim_vector dv
Definition: sub2ind.cc:263
void print(std::ostream &os, bool pr_as_read_syntax=false)
Definition: ov-struct.cc:1246
bool is_zero_by_zero(void) const
Definition: ov.h:696
octave_value next_subsref(const std::string &type, const std::list< octave_value_list > &idx, size_t skip=1)
Definition: ov.cc:1462
octave_base_value * try_narrowing_conversion(void)
Definition: ov-struct.cc:62
F77_RET_T F77_REAL &F77_RET_T F77_DBLE &F77_RET_T F77_REAL &F77_RET_T F77_DBLE &F77_RET_T F77_REAL &F77_RET_T F77_DBLE &F77_RET_T const F77_REAL const F77_REAL F77_REAL &F77_RET_T const F77_DBLE const F77_DBLE F77_DBLE &F77_RET_T F77_REAL &F77_RET_T F77_DBLE &F77_RET_T F77_DBLE &F77_RET_T F77_REAL &F77_RET_T F77_REAL &F77_RET_T F77_DBLE &F77_RET_T const F77_DBLE F77_DBLE &F77_RET_T const F77_REAL F77_REAL &F77_RET_T F77_REAL F77_REAL &F77_RET_T F77_DBLE F77_DBLE &F77_RET_T const F77_DBLE * x
static octave_value empty_conv(const std::string &type, const octave_value &rhs=octave_value())
Definition: ov.cc:2882
static bool scalar(const dim_vector &dims)
Definition: ov-struct.cc:648
size_t byte_size(void) const
Definition: ov.h:506
octave_idx_type numel(void) const
Definition: ov-struct.h:221
octave_value_list fval
Definition: ov-struct.cc:2060