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