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