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