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