comparison src/ov-struct.cc @ 10742:604e13a89c7f

initial code for structs rewrite
author Jaroslav Hajek <highegg@gmail.com>
date Tue, 22 Jun 2010 15:22:36 +0200
parents e0ba186b242b
children 58c1b5402588
comparison
equal deleted inserted replaced
10718:b8d76f4be94a 10742:604e13a89c7f
49 49
50 DEFINE_OCTAVE_ALLOCATOR(octave_struct); 50 DEFINE_OCTAVE_ALLOCATOR(octave_struct);
51 51
52 DEFINE_OV_TYPEID_FUNCTIONS_AND_DATA(octave_struct, "struct", "struct"); 52 DEFINE_OV_TYPEID_FUNCTIONS_AND_DATA(octave_struct, "struct", "struct");
53 53
54 octave_base_value *
55 octave_struct::try_narrowing_conversion (void)
56 {
57 octave_base_value *retval = 0;
58
59 if (numel () == 1)
60 retval = new octave_scalar_struct (map.checkelem (0));
61
62 return retval;
63 }
64
54 Cell 65 Cell
55 octave_struct::dotref (const octave_value_list& idx, bool auto_add) 66 octave_struct::dotref (const octave_value_list& idx, bool auto_add)
56 { 67 {
57 Cell retval; 68 Cell retval;
58 69
59 assert (idx.length () == 1); 70 assert (idx.length () == 1);
60 71
61 std::string nm = idx(0).string_value (); 72 std::string nm = idx(0).string_value ();
62 73
63 Octave_map::const_iterator p = map.seek (nm); 74 octave_map::const_iterator p = map.seek (nm);
64 75
65 if (p != map.end ()) 76 if (p != map.end ())
66 retval = map.contents (p); 77 retval = map.contents (p);
67 else if (auto_add) 78 else if (auto_add)
68 retval = (numel () == 0) ? Cell (dim_vector (1, 1)) : Cell (dims ()); 79 retval = (numel () == 0) ? Cell (dim_vector (1, 1)) : Cell (dims ());
129 140
130 skip++; 141 skip++;
131 } 142 }
132 } 143 }
133 else 144 else
134 retval(0) = map.index (idx.front ()); 145 retval(0) = do_index_op (idx.front ());
135 } 146 }
136 break; 147 break;
137 148
138 case '.': 149 case '.':
139 { 150 {
195 206
196 skip++; 207 skip++;
197 } 208 }
198 } 209 }
199 else 210 else
200 retval = map.index (idx.front (), auto_add); 211 retval = do_index_op (idx.front (), auto_add);
201 } 212 }
202 break; 213 break;
203 214
204 case '.': 215 case '.':
205 { 216 {
243 const std::string& type) 254 const std::string& type)
244 { 255 {
245 octave_value retval; 256 octave_value retval;
246 257
247 if (type.length () > 0 && type[0] == '.' && ! val.is_map ()) 258 if (type.length () > 0 && type[0] == '.' && ! val.is_map ())
248 retval = Octave_map (); 259 retval = octave_map ();
249 else 260 else
250 retval = val; 261 retval = val;
251 262
252 return retval; 263 return retval;
253 } 264 }
295 next_idx.erase (next_idx.begin ()); 306 next_idx.erase (next_idx.begin ());
296 307
297 std::string next_type = type.substr (2); 308 std::string next_type = type.substr (2);
298 309
299 Cell tmpc (1, 1); 310 Cell tmpc (1, 1);
300 Octave_map::iterator pkey = map.seek (key); 311 octave_map::iterator pkey = map.seek (key);
301 if (pkey != map.end ()) 312 if (pkey != map.end ())
302 { 313 {
303 pkey->second.make_unique (); 314 map.contents (pkey).make_unique ();
304 tmpc = pkey->second.index (idx.front (), true); 315 tmpc = map.contents (pkey).index (idx.front (), true);
305 } 316 }
306 317
307 // FIXME: better code reuse? cf. octave_cell::subsasgn and the case below. 318 // FIXME: better code reuse? cf. octave_cell::subsasgn and the case below.
308 if (! error_state) 319 if (! error_state)
309 { 320 {
345 next_idx.erase (next_idx.begin ()); 356 next_idx.erase (next_idx.begin ());
346 357
347 std::string next_type = type.substr (1); 358 std::string next_type = type.substr (1);
348 359
349 Cell tmpc (1, 1); 360 Cell tmpc (1, 1);
350 Octave_map::iterator pkey = map.seek (key); 361 octave_map::iterator pkey = map.seek (key);
351 if (pkey != map.end ()) 362 if (pkey != map.end ())
352 { 363 {
353 pkey->second.make_unique (); 364 map.contents (pkey).make_unique ();
354 tmpc = pkey->second; 365 tmpc = map.contents (pkey);
355 } 366 }
356 367
357 // FIXME: better code reuse? 368 // FIXME: better code reuse?
358 if (! error_state) 369 if (! error_state)
359 { 370 {
418 429
419 if (didx.numel () == tmp_cell.numel ()) 430 if (didx.numel () == tmp_cell.numel ())
420 tmp_cell = tmp_cell.reshape (didx); 431 tmp_cell = tmp_cell.reshape (didx);
421 432
422 433
423 map.assign (idxf, key, tmp_cell); 434 map.contents (key).assign (idxf, tmp_cell);
424 435
425 if (! error_state) 436 if (! error_state)
426 { 437 {
427 count++; 438 count++;
428 retval = octave_value (this); 439 retval = octave_value (this);
430 else 441 else
431 gripe_failed_assignment (); 442 gripe_failed_assignment ();
432 } 443 }
433 else 444 else
434 { 445 {
435 const Octave_map& cmap = const_cast<const Octave_map &> (map); 446 const octave_map& cmap = const_cast<const octave_map &> (map);
436 // cast map to const reference to avoid forced key insertion. 447 // cast map to const reference to avoid forced key insertion.
437 if (idxf.all_scalars () 448 if (idxf.all_scalars ()
438 || cmap.contents (key).index (idxf, true).numel () == 1) 449 || cmap.contents (key).index (idxf, true).numel () == 1)
439 { 450 {
440 map.assign (idxf, key, t_rhs.storable_value ()); 451 map.contents (key).assign (idxf, Cell (t_rhs.storable_value ()));
441 if (! error_state) 452 if (! error_state)
442 { 453 {
443 count++; 454 count++;
444 retval = octave_value (this); 455 retval = octave_value (this);
445 } 456 }
455 } 466 }
456 else 467 else
457 { 468 {
458 if (t_rhs.is_map()) 469 if (t_rhs.is_map())
459 { 470 {
460 Octave_map rhs_map = t_rhs.map_value (); 471 octave_map rhs_map = t_rhs.map_value ();
461 472
462 if (! error_state) 473 if (! error_state)
463 { 474 {
464 map.assign (idx.front (), rhs_map); 475 map.assign (idx.front (), rhs_map);
465 476
476 } 487 }
477 else 488 else
478 { 489 {
479 if (t_rhs.is_null_value()) 490 if (t_rhs.is_null_value())
480 { 491 {
481 map.maybe_delete_elements (idx.front()); 492 map.delete_elements (idx.front());
482 493
483 if (! error_state) 494 if (! error_state)
484 { 495 {
485 count++; 496 count++;
486 retval = octave_value (this); 497 retval = octave_value (this);
512 // shape of the left hand side of the assignment. 523 // shape of the left hand side of the assignment.
513 524
514 if (numel () == tmp_cell.numel ()) 525 if (numel () == tmp_cell.numel ())
515 tmp_cell = tmp_cell.reshape (dims ()); 526 tmp_cell = tmp_cell.reshape (dims ());
516 527
517 map.assign (key, tmp_cell); 528 map.setfield (key, tmp_cell);
518 } 529 }
519 else 530 else
520 // Regularize a null matrix if stored into a struct component. 531 {
521 map.assign (key, t_rhs.storable_value ()); 532 Cell tmp_cell(1, 1);
533 tmp_cell(0) = t_rhs.storable_value ();
534 map.setfield (key, tmp_cell);
535 }
522 536
523 if (! error_state) 537 if (! error_state)
524 { 538 {
525 count++; 539 count++;
526 retval = octave_value (this); 540 retval = octave_value (this);
545 } 559 }
546 560
547 octave_value 561 octave_value
548 octave_struct::do_index_op (const octave_value_list& idx, bool resize_ok) 562 octave_struct::do_index_op (const octave_value_list& idx, bool resize_ok)
549 { 563 {
550 // Octave_map handles indexing itself. 564 // octave_map handles indexing itself.
551 return map.index (idx, resize_ok); 565 return map.index (idx, resize_ok);
552 } 566 }
553 567
554 size_t 568 size_t
555 octave_struct::byte_size (void) const 569 octave_struct::byte_size (void) const
556 { 570 {
557 // Neglect the size of the fieldnames. 571 // Neglect the size of the fieldnames.
558 572
559 size_t retval = 0; 573 size_t retval = 0;
560 574
561 for (Octave_map::const_iterator p = map.begin (); p != map.end (); p++) 575 for (octave_map::const_iterator p = map.begin (); p != map.end (); p++)
562 { 576 {
563 std::string key = map.key (p); 577 std::string key = map.key (p);
564 578
565 octave_value val = octave_value (map.contents (p)); 579 octave_value val = octave_value (map.contents (p));
566 580
604 newline (os); 618 newline (os);
605 619
606 increment_indent_level (); 620 increment_indent_level ();
607 } 621 }
608 622
609 string_vector key_list = map.keys (); 623 string_vector key_list = map.fieldnames ();
610 624
611 for (octave_idx_type i = 0; i < key_list.length (); i++) 625 for (octave_idx_type i = 0; i < key_list.length (); i++)
612 { 626 {
613 std::string key = key_list[i]; 627 std::string key = key_list[i];
614 628
691 %!fail("struct('a',{1,2},'b',{1,2,3})","dimensions of parameter 2 do not match those of parameter 4") 705 %!fail("struct('a',{1,2},'b',{1,2,3})","dimensions of parameter 2 do not match those of parameter 4")
692 %!fail("struct(1,2,3,4)","struct expects alternating \"field\", VALUE pairs"); 706 %!fail("struct(1,2,3,4)","struct expects alternating \"field\", VALUE pairs");
693 %!fail("struct('1',2,'3')","struct expects alternating \"field\", VALUE pairs"); 707 %!fail("struct('1',2,'3')","struct expects alternating \"field\", VALUE pairs");
694 */ 708 */
695 709
710 bool
711 octave_struct::save_ascii (std::ostream& os)
712 {
713 octave_map m = map_value ();
714
715 octave_idx_type nf = m.nfields ();
716
717 const dim_vector dv = dims ();
718
719 os << "# ndims: " << dv.length () << "\n";
720
721 for (int i = 0; i < dv.length (); i++)
722 os << " " << dv (i);
723 os << "\n";
724
725 os << "# length: " << nf << "\n";
726
727 // Iterating over the list of keys will preserve the order of the
728 // fields.
729 string_vector keys = m.fieldnames ();
730
731 for (octave_idx_type i = 0; i < nf; i++)
732 {
733 std::string key = keys(i);
734
735 octave_value val = map.contents (key);
736
737 bool b = save_ascii_data (os, val, key, false, 0);
738
739 if (! b)
740 return os;
741 }
742
743 return true;
744 }
745
746 bool
747 octave_struct::load_ascii (std::istream& is)
748 {
749 octave_idx_type len = 0;
750 dim_vector dv (1, 1);
751 bool success = true;
752
753 // KLUGE: earlier Octave versions did not save extra dimensions with struct,
754 // and as a result did not preserve dimensions for empty structs.
755 // The default dimensions were 1x1, which we want to preserve.
756 string_vector keywords(2);
757
758 keywords[0] = "ndims";
759 keywords[1] = "length";
760
761 std::string kw;
762
763 if (extract_keyword (is, keywords, kw, len, true))
764 {
765 if (kw == keywords[0])
766 {
767 int mdims = std::max (static_cast<int> (len), 2);
768 dv.resize (mdims);
769 for (int i = 0; i < mdims; i++)
770 is >> dv(i);
771
772 success = extract_keyword (is, keywords[1], len);
773 }
774 }
775 else
776 success = false;
777
778 if (success && len >= 0)
779 {
780 if (len > 0)
781 {
782 octave_map m (dv);
783
784 for (octave_idx_type j = 0; j < len; j++)
785 {
786 octave_value t2;
787 bool dummy;
788
789 // recurse to read cell elements
790 std::string nm
791 = read_ascii_data (is, std::string (), dummy, t2, j);
792
793 if (!is)
794 break;
795
796 Cell tcell = t2.is_cell () ? t2.cell_value () : Cell (t2);
797
798 if (error_state)
799 {
800 error ("load: internal error loading struct elements");
801 return false;
802 }
803
804 m.setfield (nm, tcell);
805 }
806
807 if (is)
808 map = m;
809 else
810 {
811 error ("load: failed to load structure");
812 success = false;
813 }
814 }
815 else if (len == 0 )
816 map = octave_map (dv);
817 else
818 panic_impossible ();
819 }
820 else {
821 error ("load: failed to extract number of elements in structure");
822 success = false;
823 }
824
825 return success;
826 }
827
828 bool
829 octave_struct::save_binary (std::ostream& os, bool& save_as_floats)
830 {
831 octave_map m = map_value ();
832
833 octave_idx_type nf = m.nfields ();
834
835 dim_vector d = dims ();
836 if (d.length () < 1)
837 return false;
838
839 // Use negative value for ndims
840 int32_t di = - d.length();
841 os.write (reinterpret_cast<char *> (&di), 4);
842 for (int i = 0; i < d.length (); i++)
843 {
844 di = d(i);
845 os.write (reinterpret_cast<char *> (&di), 4);
846 }
847
848 int32_t len = nf;
849 os.write (reinterpret_cast<char *> (&len), 4);
850
851 // Iterating over the list of keys will preserve the order of the
852 // fields.
853 string_vector keys = m.fieldnames ();
854
855 for (octave_idx_type i = 0; i < nf; i++)
856 {
857 std::string key = keys(i);
858
859 octave_value val = map.contents (key);
860
861 bool b = save_binary_data (os, val, key, "", 0, save_as_floats);
862
863 if (! b)
864 return os;
865 }
866
867 return true;
868 }
869
870 bool
871 octave_struct::load_binary (std::istream& is, bool swap,
872 oct_mach_info::float_format fmt)
873 {
874 bool success = true;
875 int32_t len;
876 if (! is.read (reinterpret_cast<char *> (&len), 4))
877 return false;
878 if (swap)
879 swap_bytes<4> (&len);
880
881 dim_vector dv (1, 1);
882
883 if (len < 0)
884 {
885 // We have explicit dimensions.
886 int mdims = -len;
887
888 int32_t di;
889 dv.resize (mdims);
890
891 for (int i = 0; i < mdims; i++)
892 {
893 if (! is.read (reinterpret_cast<char *> (&di), 4))
894 return false;
895 if (swap)
896 swap_bytes<4> (&di);
897 dv(i) = di;
898 }
899
900 if (! is.read (reinterpret_cast<char *> (&len), 4))
901 return false;
902 if (swap)
903 swap_bytes<4> (&len);
904 }
905
906 if (len > 0)
907 {
908 octave_map m (dv);
909
910 for (octave_idx_type j = 0; j < len; j++)
911 {
912 octave_value t2;
913 bool dummy;
914 std::string doc;
915
916 // recurse to read cell elements
917 std::string nm = read_binary_data (is, swap, fmt, std::string (),
918 dummy, t2, doc);
919
920 if (!is)
921 break;
922
923 Cell tcell = t2.is_cell () ? t2.cell_value () : Cell (t2);
924
925 if (error_state)
926 {
927 error ("load: internal error loading struct elements");
928 return false;
929 }
930
931 m.setfield (nm, tcell);
932 }
933
934 if (is)
935 map = m;
936 else
937 {
938 error ("load: failed to load structure");
939 success = false;
940 }
941 }
942 else if (len == 0)
943 map = octave_map (dv);
944 else
945 success = false;
946
947 return success;
948 }
949
950 #if defined (HAVE_HDF5)
951
952 bool
953 octave_struct::save_hdf5 (hid_t loc_id, const char *name, bool save_as_floats)
954 {
955 hid_t data_hid = -1;
956
957 #if HAVE_HDF5_18
958 data_hid = H5Gcreate (loc_id, name, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
959 #else
960 data_hid = H5Gcreate (loc_id, name, 0);
961 #endif
962 if (data_hid < 0) return false;
963
964 // recursively add each element of the structure to this group
965 octave_map m = map_value ();
966
967 octave_idx_type nf = m.nfields ();
968
969 // Iterating over the list of keys will preserve the order of the
970 // fields.
971 string_vector keys = m.fieldnames ();
972
973 for (octave_idx_type i = 0; i < nf; i++)
974 {
975 std::string key = keys(i);
976
977 octave_value val = map.contents (key);
978
979 bool retval2 = add_hdf5_data (data_hid, val, key, "", false,
980 save_as_floats);
981
982 if (! retval2)
983 break;
984 }
985
986 H5Gclose (data_hid);
987
988 return true;
989 }
990
991 bool
992 octave_struct::load_hdf5 (hid_t loc_id, const char *name)
993 {
994 bool retval = false;
995
996 hdf5_callback_data dsub;
997
998 herr_t retval2 = 0;
999 octave_map m (dim_vector (1, 1));
1000 int current_item = 0;
1001 hsize_t num_obj = 0;
1002 #if HAVE_HDF5_18
1003 hid_t group_id = H5Gopen (loc_id, name, H5P_DEFAULT);
1004 #else
1005 hid_t group_id = H5Gopen (loc_id, name);
1006 #endif
1007 H5Gget_num_objs (group_id, &num_obj);
1008 H5Gclose (group_id);
1009
1010 // FIXME -- fields appear to be sorted alphabetically on loading.
1011 // Why is that happening?
1012
1013 while (current_item < static_cast<int> (num_obj)
1014 && (retval2 = H5Giterate (loc_id, name, &current_item,
1015 hdf5_read_next_data, &dsub)) > 0)
1016 {
1017 octave_value t2 = dsub.tc;
1018
1019 Cell tcell = t2.is_cell () ? t2.cell_value () : Cell (t2);
1020
1021 if (error_state)
1022 {
1023 error ("load: internal error loading struct elements");
1024 return false;
1025 }
1026
1027 m.setfield (dsub.name, tcell);
1028
1029 }
1030
1031 if (retval2 >= 0)
1032 {
1033 map = m;
1034 retval = true;
1035 }
1036
1037 return retval;
1038 }
1039
1040 #endif
1041
1042 mxArray *
1043 octave_struct::as_mxArray (void) const
1044 {
1045 int nf = nfields ();
1046 string_vector kv = map_keys ();
1047
1048 OCTAVE_LOCAL_BUFFER (const char *, f, nf);
1049
1050 for (int i = 0; i < nf; i++)
1051 f[i] = kv[i].c_str ();
1052
1053 mxArray *retval = new mxArray (dims (), nf, f);
1054
1055 mxArray **elts = static_cast<mxArray **> (retval->get_data ());
1056
1057 mwSize nel = numel ();
1058
1059 mwSize ntot = nf * nel;
1060
1061 for (int i = 0; i < nf; i++)
1062 {
1063 Cell c = map.contents (kv[i]);
1064
1065 const octave_value *p = c.data ();
1066
1067 mwIndex k = 0;
1068 for (mwIndex j = i; j < ntot; j += nf)
1069 elts[j] = new mxArray (p[k++]);
1070 }
1071
1072 return retval;
1073 }
1074
1075 DEFINE_OCTAVE_ALLOCATOR(octave_scalar_struct);
1076
1077 DEFINE_OV_TYPEID_FUNCTIONS_AND_DATA(octave_scalar_struct, "scalar struct", "struct");
1078
1079 octave_value
1080 octave_scalar_struct::dotref (const octave_value_list& idx, bool auto_add)
1081 {
1082 assert (idx.length () == 1);
1083
1084 std::string nm = idx(0).string_value ();
1085
1086 octave_value retval = map.getfield (nm);
1087
1088 if (! auto_add && retval.is_undefined ())
1089 error ("structure has no member `%s'", nm.c_str ());
1090
1091 return retval;
1092 }
1093
1094 octave_value
1095 octave_scalar_struct::subsref (const std::string& type,
1096 const std::list<octave_value_list>& idx)
1097 {
1098 octave_value retval;
1099
1100 if (type[0] == '.')
1101 {
1102 int skip = 1;
1103
1104 retval = dotref (idx.front ());
1105
1106 if (idx.size () > 1)
1107 retval = retval.next_subsref (type, idx, skip);
1108 }
1109 else
1110 retval = to_array ().subsref (type, idx);
1111
1112 return retval;
1113 }
1114
1115 octave_value_list
1116 octave_scalar_struct::subsref (const std::string& type,
1117 const std::list<octave_value_list>& idx,
1118 int nargout)
1119 {
1120 octave_value_list retval;
1121
1122 if (type[0] == '.')
1123 {
1124 int skip = 1;
1125
1126 retval(0) = dotref (idx.front ());
1127
1128 if (idx.size () > 1)
1129 retval = retval(0).next_subsref (nargout, type, idx, skip);
1130 }
1131 else
1132 retval = to_array ().subsref (type, idx, nargout);
1133
1134 return retval;
1135 }
1136
1137 octave_value
1138 octave_scalar_struct::subsref (const std::string& type,
1139 const std::list<octave_value_list>& idx,
1140 bool auto_add)
1141 {
1142 octave_value retval;
1143
1144 if (type[0] == '.')
1145 {
1146 int skip = 1;
1147
1148 retval = dotref (idx.front (), auto_add);
1149
1150 if (idx.size () > 1)
1151 retval = retval.next_subsref (auto_add, type, idx, skip);
1152 }
1153 else
1154 retval = to_array ().subsref (type, idx, auto_add);
1155
1156 return retval;
1157 }
1158
1159 /*
1160 %!test
1161 %! x(1).a.a = 1; x(2).a.a = 2;
1162 %! assert (size (x), [1, 2]);
1163 %! assert (x(1).a.a, 1);
1164 %! assert (x(2).a.a, 2);
1165 */
1166
1167 octave_value
1168 octave_scalar_struct::numeric_conv (const octave_value& val,
1169 const std::string& type)
1170 {
1171 octave_value retval;
1172
1173 if (type.length () > 0 && type[0] == '.' && ! val.is_map ())
1174 retval = octave_map ();
1175 else
1176 retval = val;
1177
1178 return retval;
1179 }
1180
1181 octave_value
1182 octave_scalar_struct::subsasgn (const std::string& type,
1183 const std::list<octave_value_list>& idx,
1184 const octave_value& rhs)
1185 {
1186 octave_value retval;
1187
1188 if (idx.front ().empty ())
1189 {
1190 error ("missing index in indexed assignment");
1191 return retval;
1192 }
1193
1194 if (type[0] == '.')
1195 {
1196 int n = type.length ();
1197
1198 octave_value t_rhs = rhs;
1199
1200 octave_value_list key_idx = idx.front ();
1201
1202 assert (key_idx.length () == 1);
1203
1204 std::string key = key_idx(0).string_value ();
1205
1206 if (n > 1)
1207 {
1208 std::list<octave_value_list> next_idx (idx);
1209
1210 next_idx.erase (next_idx.begin ());
1211
1212 std::string next_type = type.substr (1);
1213
1214 octave_value tmp;
1215 octave_map::iterator pkey = map.seek (key);
1216 if (pkey != map.end ())
1217 {
1218 map.contents (pkey).make_unique ();
1219 tmp = map.contents (pkey);
1220 }
1221
1222 if (! error_state)
1223 {
1224 if (! tmp.is_defined () || tmp.is_zero_by_zero ())
1225 {
1226 tmp = octave_value::empty_conv (next_type, rhs);
1227 tmp.make_unique (); // probably a no-op.
1228 }
1229 else
1230 // optimization: ignore the copy still stored inside our map.
1231 tmp.make_unique (1);
1232
1233 if (! error_state)
1234 t_rhs = tmp.subsasgn (next_type, next_idx, rhs);
1235 }
1236 }
1237
1238 if (! error_state)
1239 map.setfield (key, t_rhs.storable_value ());
1240 else
1241 gripe_failed_assignment ();
1242 }
1243 else
1244 {
1245 // Forward this case to octave_struct.
1246 octave_value tmp (new octave_struct (octave_map (map)));
1247 retval = tmp.subsasgn (type, idx, rhs);
1248 }
1249
1250 return retval;
1251 }
1252
1253 octave_value
1254 octave_scalar_struct::do_index_op (const octave_value_list& idx, bool resize_ok)
1255 {
1256 // octave_map handles indexing itself.
1257 return octave_map (map).index (idx, resize_ok);
1258 }
1259
1260 size_t
1261 octave_scalar_struct::byte_size (void) const
1262 {
1263 // Neglect the size of the fieldnames.
1264
1265 size_t retval = 0;
1266
1267 for (octave_map::const_iterator p = map.begin (); p != map.end (); p++)
1268 {
1269 std::string key = map.key (p);
1270
1271 octave_value val = octave_value (map.contents (p));
1272
1273 retval += val.byte_size ();
1274 }
1275
1276 return retval;
1277 }
1278
1279 void
1280 octave_scalar_struct::print (std::ostream& os, bool) const
1281 {
1282 print_raw (os);
1283 }
1284
1285 void
1286 octave_scalar_struct::print_raw (std::ostream& os, bool) const
1287 {
1288 unwind_protect frame;
1289
1290 frame.protect_var (Vstruct_levels_to_print);
1291
1292 if (Vstruct_levels_to_print >= 0)
1293 {
1294 bool print_keys_only = Vstruct_levels_to_print-- == 0;
1295
1296 indent (os);
1297 os << "{";
1298 newline (os);
1299
1300 increment_indent_level ();
1301
1302 octave_idx_type n = 1;
1303
1304 if (n != 1 || print_keys_only)
1305 {
1306 indent (os);
1307 dim_vector dv = dims ();
1308 os << dv.str () << " struct array containing the fields:";
1309 newline (os);
1310 newline (os);
1311
1312 increment_indent_level ();
1313 }
1314
1315 string_vector key_list = map.fieldnames ();
1316
1317 for (octave_idx_type i = 0; i < key_list.length (); i++)
1318 {
1319 std::string key = key_list[i];
1320
1321 Cell val = map.contents (key);
1322
1323 octave_value tmp = (n == 1) ? val(0) : octave_value (val, true);
1324
1325 if (n != 1 || print_keys_only)
1326 {
1327 indent (os);
1328 os << key;
1329 if (n == 1)
1330 {
1331 dim_vector dv = tmp.dims ();
1332 os << ": " << dv.str () << " " << tmp.type_name ();
1333 }
1334 newline (os);
1335 }
1336 else
1337 tmp.print_with_name (os, key);
1338 }
1339
1340 if (n != 1 || print_keys_only)
1341 decrement_indent_level ();
1342
1343 decrement_indent_level ();
1344
1345 indent (os);
1346 os << "}";
1347 newline (os);
1348 }
1349 else
1350 {
1351 indent (os);
1352 os << "<structure>";
1353 newline (os);
1354 }
1355 }
1356
1357 bool
1358 octave_scalar_struct::print_name_tag (std::ostream& os, const std::string& name) const
1359 {
1360 bool retval = false;
1361
1362 indent (os);
1363
1364 if (Vstruct_levels_to_print < 0)
1365 os << name << " = ";
1366 else
1367 {
1368 os << name << " =";
1369 newline (os);
1370 retval = true;
1371 }
1372
1373 return retval;
1374 }
1375
1376 bool
1377 octave_scalar_struct::save_ascii (std::ostream& os)
1378 {
1379 octave_map m = map_value ();
1380
1381 octave_idx_type nf = m.nfields ();
1382
1383 const dim_vector dv = dims ();
1384
1385 os << "# ndims: " << dv.length () << "\n";
1386
1387 for (int i = 0; i < dv.length (); i++)
1388 os << " " << dv (i);
1389 os << "\n";
1390
1391 os << "# length: " << nf << "\n";
1392
1393 // Iterating over the list of keys will preserve the order of the
1394 // fields.
1395 string_vector keys = m.fieldnames ();
1396
1397 for (octave_idx_type i = 0; i < nf; i++)
1398 {
1399 std::string key = keys(i);
1400
1401 octave_value val = map.contents (key);
1402
1403 bool b = save_ascii_data (os, val, key, false, 0);
1404
1405 if (! b)
1406 return os;
1407 }
1408
1409 return true;
1410 }
1411
1412 bool
1413 octave_scalar_struct::load_ascii (std::istream& is)
1414 {
1415 bool success = true;
1416 octave_idx_type len = 0;
1417
1418 if (extract_keyword (is, "length", len, true) && len >= 0)
1419 {
1420 if (len > 0)
1421 {
1422 octave_scalar_map m;
1423
1424 for (octave_idx_type j = 0; j < len; j++)
1425 {
1426 octave_value t2;
1427 bool dummy;
1428
1429 // recurse to read cell elements
1430 std::string nm
1431 = read_ascii_data (is, std::string (), dummy, t2, j);
1432
1433 if (!is)
1434 break;
1435
1436 if (error_state)
1437 {
1438 error ("load: internal error loading struct elements");
1439 return false;
1440 }
1441
1442 m.setfield (nm, t2);
1443 }
1444
1445 if (is)
1446 map = m;
1447 else
1448 {
1449 error ("load: failed to load structure");
1450 success = false;
1451 }
1452 }
1453 else if (len == 0)
1454 map = octave_scalar_map ();
1455 else
1456 panic_impossible ();
1457 }
1458 else {
1459 error ("load: failed to extract number of elements in structure");
1460 success = false;
1461 }
1462
1463 return success;
1464 }
1465
1466 bool
1467 octave_scalar_struct::save_binary (std::ostream& os, bool& save_as_floats)
1468 {
1469 octave_map m = map_value ();
1470
1471 octave_idx_type nf = m.nfields ();
1472
1473 int32_t len = nf;
1474 os.write (reinterpret_cast<char *> (&len), 4);
1475
1476 // Iterating over the list of keys will preserve the order of the
1477 // fields.
1478 string_vector keys = m.fieldnames ();
1479
1480 for (octave_idx_type i = 0; i < nf; i++)
1481 {
1482 std::string key = keys(i);
1483
1484 octave_value val = map.contents (key);
1485
1486 bool b = save_binary_data (os, val, key, "", 0, save_as_floats);
1487
1488 if (! b)
1489 return os;
1490 }
1491
1492 return true;
1493 }
1494
1495 bool
1496 octave_scalar_struct::load_binary (std::istream& is, bool swap,
1497 oct_mach_info::float_format fmt)
1498 {
1499 bool success = true;
1500 int32_t len;
1501 if (! is.read (reinterpret_cast<char *> (&len), 4))
1502 return false;
1503 if (swap)
1504 swap_bytes<4> (&len);
1505
1506 dim_vector dv (1, 1);
1507
1508 if (len > 0)
1509 {
1510 octave_scalar_map m;
1511
1512 for (octave_idx_type j = 0; j < len; j++)
1513 {
1514 octave_value t2;
1515 bool dummy;
1516 std::string doc;
1517
1518 // recurse to read cell elements
1519 std::string nm = read_binary_data (is, swap, fmt, std::string (),
1520 dummy, t2, doc);
1521
1522 if (!is)
1523 break;
1524
1525 if (error_state)
1526 {
1527 error ("load: internal error loading struct elements");
1528 return false;
1529 }
1530
1531 m.setfield (nm, t2);
1532 }
1533
1534 if (is)
1535 map = m;
1536 else
1537 {
1538 error ("load: failed to load structure");
1539 success = false;
1540 }
1541 }
1542 else if (len == 0)
1543 map = octave_scalar_map ();
1544 else
1545 success = false;
1546
1547 return success;
1548 }
1549
1550 #if defined (HAVE_HDF5)
1551
1552 bool
1553 octave_scalar_struct::save_hdf5 (hid_t loc_id, const char *name, bool save_as_floats)
1554 {
1555 hid_t data_hid = -1;
1556
1557 #if HAVE_HDF5_18
1558 data_hid = H5Gcreate (loc_id, name, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
1559 #else
1560 data_hid = H5Gcreate (loc_id, name, 0);
1561 #endif
1562 if (data_hid < 0) return false;
1563
1564 // recursively add each element of the structure to this group
1565 octave_scalar_map m = scalar_map_value ();
1566
1567 octave_idx_type nf = m.nfields ();
1568
1569 // Iterating over the list of keys will preserve the order of the
1570 // fields.
1571 string_vector keys = m.fieldnames ();
1572
1573 for (octave_idx_type i = 0; i < nf; i++)
1574 {
1575 std::string key = keys(i);
1576
1577 octave_value val = map.contents (key);
1578
1579 bool retval2 = add_hdf5_data (data_hid, val, key, "", false,
1580 save_as_floats);
1581
1582 if (! retval2)
1583 break;
1584 }
1585
1586 H5Gclose (data_hid);
1587
1588 return true;
1589 }
1590
1591 bool
1592 octave_scalar_struct::load_hdf5 (hid_t loc_id, const char *name)
1593 {
1594 bool retval = false;
1595
1596 hdf5_callback_data dsub;
1597
1598 herr_t retval2 = 0;
1599 octave_scalar_map m;
1600 int current_item = 0;
1601 hsize_t num_obj = 0;
1602 #if HAVE_HDF5_18
1603 hid_t group_id = H5Gopen (loc_id, name, H5P_DEFAULT);
1604 #else
1605 hid_t group_id = H5Gopen (loc_id, name);
1606 #endif
1607 H5Gget_num_objs (group_id, &num_obj);
1608 H5Gclose (group_id);
1609
1610 // FIXME -- fields appear to be sorted alphabetically on loading.
1611 // Why is that happening?
1612
1613 while (current_item < static_cast<int> (num_obj)
1614 && (retval2 = H5Giterate (loc_id, name, &current_item,
1615 hdf5_read_next_data, &dsub)) > 0)
1616 {
1617 octave_value t2 = dsub.tc;
1618
1619 if (error_state)
1620 {
1621 error ("load: internal error loading struct elements");
1622 return false;
1623 }
1624
1625 m.setfield (dsub.name, t2);
1626
1627 }
1628
1629 if (retval2 >= 0)
1630 {
1631 map = m;
1632 retval = true;
1633 }
1634
1635 return retval;
1636 }
1637
1638 #endif
1639
1640 mxArray *
1641 octave_scalar_struct::as_mxArray (void) const
1642 {
1643 int nf = nfields ();
1644 string_vector kv = map_keys ();
1645
1646 OCTAVE_LOCAL_BUFFER (const char *, f, nf);
1647
1648 for (int i = 0; i < nf; i++)
1649 f[i] = kv[i].c_str ();
1650
1651 mxArray *retval = new mxArray (dims (), nf, f);
1652
1653 mxArray **elts = static_cast<mxArray **> (retval->get_data ());
1654
1655 mwSize nel = numel ();
1656
1657 mwSize ntot = nf * nel;
1658
1659 for (int i = 0; i < nf; i++)
1660 {
1661 Cell c = map.contents (kv[i]);
1662
1663 const octave_value *p = c.data ();
1664
1665 mwIndex k = 0;
1666 for (mwIndex j = i; j < ntot; j += nf)
1667 elts[j] = new mxArray (p[k++]);
1668 }
1669
1670 return retval;
1671 }
1672
1673
1674 octave_value
1675 octave_scalar_struct::to_array (void)
1676 {
1677 return new octave_struct (octave_map (map));
1678 }
1679
1680 /*
1681 %!shared x
1682 %! x(1).a=1; x(2).a=2; x(1).b=3; x(2).b=3;
1683 %!assert(struct('a',1,'b',3),x(1))
1684 %!assert(isempty(x([])))
1685 %!assert(isempty(struct('a',{},'b',{})))
1686 %!assert(struct('a',{1,2},'b',{3,3}),x)
1687 %!assert(struct('a',{1,2},'b',3),x)
1688 %!assert(struct('a',{1,2},'b',{3}),x)
1689 %!assert(struct('b',3,'a',{1,2}),x)
1690 %!assert(struct('b',{3},'a',{1,2}),x)
1691 %!test x=struct([]);
1692 %!assert(size(x),[0,0]);
1693 %!assert(isstruct(x));
1694 %!assert(isempty(fieldnames(x)));
1695 %!fail("struct('a',{1,2},'b',{1,2,3})","dimensions of parameter 2 do not match those of parameter 4")
1696 %!fail("struct(1,2,3,4)","struct expects alternating \"field\", VALUE pairs");
1697 %!fail("struct('1',2,'3')","struct expects alternating \"field\", VALUE pairs");
1698 */
1699
696 DEFUN (struct, args, , 1700 DEFUN (struct, args, ,
697 "-*- texinfo -*-\n\ 1701 "-*- texinfo -*-\n\
698 @deftypefn {Built-in Function} {} struct (\"field\", @var{value}, \"field\", @var{value}, @dots{})\n\ 1702 @deftypefn {Built-in Function} {} struct (\"field\", @var{value}, \"field\", @var{value}, @dots{})\n\
699 \n\ 1703 \n\
700 Create a structure and initialize its value.\n\ 1704 Create a structure and initialize its value.\n\
720 // Note that struct () creates a 1x1 struct with no fields for 1724 // Note that struct () creates a 1x1 struct with no fields for
721 // compatibility with Matlab. 1725 // compatibility with Matlab.
722 1726
723 if (nargin == 1 && args(0).is_object ()) 1727 if (nargin == 1 && args(0).is_object ())
724 { 1728 {
725 Octave_map m = args(0).map_value (); 1729 octave_map m = args(0).map_value ();
726 retval = octave_value (new octave_struct (m)); 1730 retval = octave_value (new octave_struct (m));
727 1731
728 return retval; 1732 return retval;
729 } 1733 }
730 1734
734 Cell fields; 1738 Cell fields;
735 1739
736 if (nargin == 2) 1740 if (nargin == 2)
737 { 1741 {
738 if (args(1).is_cellstr ()) 1742 if (args(1).is_cellstr ())
739 retval = Octave_map (args(0).dims (), args(1).cell_value ()); 1743 retval = octave_map (args(0).dims (), args(1).cellstr_value ());
740 else 1744 else
741 error ("struct: expecting cell array of field names as second argument"); 1745 error ("struct: expecting cell array of field names as second argument");
742 } 1746 }
743 else 1747 else
744 retval = Octave_map (args(0).dims ()); 1748 retval = octave_map (args(0).dims ());
745 1749
746 return retval; 1750 return retval;
747 } 1751 }
748 1752
749 // Check for "field", VALUE pairs. 1753 // Check for "field", VALUE pairs.
786 } 1790 }
787 } 1791 }
788 1792
789 // Create the return value. 1793 // Create the return value.
790 1794
791 Octave_map map (dims); 1795 octave_map map (dims);
792 1796
793 for (int i = 0; i < nargin; i+= 2) 1797 for (int i = 0; i < nargin; i+= 2)
794 { 1798 {
795 // Get key. 1799 // Get key.
796 1800
817 1821
818 if (error_state) 1822 if (error_state)
819 return retval; 1823 return retval;
820 1824
821 if (scalar (c.dims ())) 1825 if (scalar (c.dims ()))
822 map.assign (key, Cell (dims, c(0))); 1826 map.setfield (key, Cell (dims, c(0)));
823 else 1827 else
824 map.assign (key, c); 1828 map.setfield (key, c);
825 } 1829 }
826 else 1830 else
827 map.assign (key, Cell (dims, args(i+1))); 1831 map.setfield (key, Cell (dims, args(i+1)));
828 1832
829 if (error_state) 1833 if (error_state)
830 return retval; 1834 return retval;
831 } 1835 }
832 1836
866 { 1870 {
867 octave_value arg = args(0); 1871 octave_value arg = args(0);
868 1872
869 if (arg.is_map () || arg.is_object ()) 1873 if (arg.is_map () || arg.is_object ())
870 { 1874 {
871 Octave_map m = arg.map_value (); 1875 octave_map m = arg.map_value ();
872 1876
873 string_vector keys = m.keys (); 1877 string_vector keys = m.fieldnames ();
874 1878
875 if (keys.length () == 0) 1879 if (keys.length () == 0)
876 retval = Cell (0, 1); 1880 retval = Cell (0, 1);
877 else 1881 else
878 retval = Cell (m.keys ()); 1882 retval = Cell (keys);
879 } 1883 }
880 else 1884 else
881 gripe_wrong_type_arg ("fieldnames", args(0)); 1885 gripe_wrong_type_arg ("fieldnames", args(0));
882 } 1886 }
883 else 1887 else
909 { 1913 {
910 retval = false; 1914 retval = false;
911 1915
912 if (args(0).is_map ()) 1916 if (args(0).is_map ())
913 { 1917 {
914 Octave_map m = args(0).map_value (); 1918 octave_map m = args(0).map_value ();
915 1919
916 // FIXME -- should this work for all types that can do 1920 // FIXME -- should this work for all types that can do
917 // structure reference operations? 1921 // structure reference operations?
918 1922
919 if (args(1).is_string ()) 1923 if (args(1).is_string ())
920 { 1924 {
921 std::string key = args(1).string_value (); 1925 std::string key = args(1).string_value ();
922 1926
923 retval = m.contains (key) != 0; 1927 retval = m.isfield (key);
924 } 1928 }
925 else if (args(1).is_cell ()) 1929 else if (args(1).is_cell ())
926 { 1930 {
927 Cell c = args(1).cell_value (); 1931 Cell c = args(1).cell_value ();
928 boolMatrix bm (c.dims ()); 1932 boolNDArray bm (c.dims ());
929 octave_idx_type n = bm.numel (); 1933 octave_idx_type n = bm.numel ();
930 1934
931 for (octave_idx_type i = 0; i < n; i++) 1935 for (octave_idx_type i = 0; i < n; i++)
932 { 1936 {
933 if (c(i).is_string ()) 1937 if (c(i).is_string ())
934 { 1938 {
935 std::string key = c(i).string_value (); 1939 std::string key = c(i).string_value ();
936 1940
937 bm(i) = m.contains (key) != 0; 1941 bm(i) = m.isfield (key);
938 } 1942 }
939 else 1943 else
940 bm(i) = false; 1944 bm(i) = false;
941 } 1945 }
942 1946
1131 } 2135 }
1132 2136
1133 // All initializing is done, we can start moving 2137 // All initializing is done, we can start moving
1134 // values. 2138 // values.
1135 2139
1136 Octave_map map; 2140 octave_map map;
1137 2141
1138 // If field is a cell array then we use all 2142 // If field is a cell array then we use all
1139 // elements in array, on the other hand when 2143 // elements in array, on the other hand when
1140 // field is a character array the number of 2144 // field is a character array the number of
1141 // elements is equals the number of rows. 2145 // elements is equals the number of rows.
1205 break; 2209 break;
1206 } 2210 }
1207 2211
1208 map.reshape (value_dv); 2212 map.reshape (value_dv);
1209 2213
1210 map.assign (field_str, c_value); 2214 map.setfield (field_str, c_value);
1211 } 2215 }
1212 2216
1213 if (! error_state) 2217 if (! error_state)
1214 retval = map; 2218 retval = map;
1215 } 2219 }
1258 2262
1259 int nargin = args.length (); 2263 int nargin = args.length ();
1260 2264
1261 if (nargin == 2) 2265 if (nargin == 2)
1262 { 2266 {
1263 Octave_map m = args(0).map_value (); 2267 octave_map m = args(0).map_value ();
1264 2268
1265 octave_value_list fval = Fcellstr (args(1), 1); 2269 octave_value_list fval = Fcellstr (args(1), 1);
1266 2270
1267 if (! error_state) 2271 if (! error_state)
1268 { 2272 {
1270 2274
1271 for (int i = 0; i < fcell.numel (); i++) 2275 for (int i = 0; i < fcell.numel (); i++)
1272 { 2276 {
1273 std::string key = fcell(i).string_value (); 2277 std::string key = fcell(i).string_value ();
1274 2278
1275 if (m.contains (key)) 2279 if (m.isfield (key))
1276 m.del (key); 2280 m.rmfield (key);
1277 else 2281 else
1278 { 2282 {
1279 error ("rmfield: structure does not contain field %s", 2283 error ("rmfield: structure does not contain field %s",
1280 key.c_str ()); 2284 key.c_str ());
1281 2285
1300 %! y = rmfield (x, {"a", "f"}); 2304 %! y = rmfield (x, {"a", "f"});
1301 %! assert (fieldnames (y), {"d"; "b"; "c"}); 2305 %! assert (fieldnames (y), {"d"; "b"; "c"});
1302 %! assert (size (y), [1, 6]); 2306 %! assert (size (y), [1, 6]);
1303 */ 2307 */
1304 2308
1305 bool
1306 octave_struct::save_ascii (std::ostream& os)
1307 {
1308 Octave_map m = map_value ();
1309
1310 octave_idx_type nf = m.nfields ();
1311
1312 const dim_vector dv = dims ();
1313
1314 os << "# ndims: " << dv.length () << "\n";
1315
1316 for (int i = 0; i < dv.length (); i++)
1317 os << " " << dv (i);
1318 os << "\n";
1319
1320 os << "# length: " << nf << "\n";
1321
1322 // Iterating over the list of keys will preserve the order of the
1323 // fields.
1324 string_vector keys = m.keys ();
1325
1326 for (octave_idx_type i = 0; i < nf; i++)
1327 {
1328 std::string key = keys(i);
1329
1330 octave_value val = map.contents (key);
1331
1332 bool b = save_ascii_data (os, val, key, false, 0);
1333
1334 if (! b)
1335 return os;
1336 }
1337
1338 return true;
1339 }
1340
1341 bool
1342 octave_struct::load_ascii (std::istream& is)
1343 {
1344 octave_idx_type len = 0;
1345 dim_vector dv (1, 1);
1346 bool success = true;
1347
1348 // KLUGE: earlier Octave versions did not save extra dimensions with struct,
1349 // and as a result did not preserve dimensions for empty structs.
1350 // The default dimensions were 1x1, which we want to preserve.
1351 string_vector keywords(2);
1352
1353 keywords[0] = "ndims";
1354 keywords[1] = "length";
1355
1356 std::string kw;
1357
1358 if (extract_keyword (is, keywords, kw, len, true))
1359 {
1360 if (kw == keywords[0])
1361 {
1362 int mdims = std::max (static_cast<int> (len), 2);
1363 dv.resize (mdims);
1364 for (int i = 0; i < mdims; i++)
1365 is >> dv(i);
1366
1367 success = extract_keyword (is, keywords[1], len);
1368 }
1369 }
1370 else
1371 success = false;
1372
1373 if (success && len >= 0)
1374 {
1375 if (len > 0)
1376 {
1377 Octave_map m (dv);
1378
1379 for (octave_idx_type j = 0; j < len; j++)
1380 {
1381 octave_value t2;
1382 bool dummy;
1383
1384 // recurse to read cell elements
1385 std::string nm
1386 = read_ascii_data (is, std::string (), dummy, t2, j);
1387
1388 if (!is)
1389 break;
1390
1391 Cell tcell = t2.is_cell () ? t2.cell_value () : Cell (t2);
1392
1393 if (error_state)
1394 {
1395 error ("load: internal error loading struct elements");
1396 return false;
1397 }
1398
1399 m.assign (nm, tcell);
1400 }
1401
1402 if (is)
1403 map = m;
1404 else
1405 {
1406 error ("load: failed to load structure");
1407 success = false;
1408 }
1409 }
1410 else if (len == 0 )
1411 map = Octave_map (dv);
1412 else
1413 panic_impossible ();
1414 }
1415 else {
1416 error ("load: failed to extract number of elements in structure");
1417 success = false;
1418 }
1419
1420 return success;
1421 }
1422
1423 bool
1424 octave_struct::save_binary (std::ostream& os, bool& save_as_floats)
1425 {
1426 Octave_map m = map_value ();
1427
1428 octave_idx_type nf = m.nfields ();
1429
1430 dim_vector d = dims ();
1431 if (d.length () < 1)
1432 return false;
1433
1434 // Use negative value for ndims
1435 int32_t di = - d.length();
1436 os.write (reinterpret_cast<char *> (&di), 4);
1437 for (int i = 0; i < d.length (); i++)
1438 {
1439 di = d(i);
1440 os.write (reinterpret_cast<char *> (&di), 4);
1441 }
1442
1443 int32_t len = nf;
1444 os.write (reinterpret_cast<char *> (&len), 4);
1445
1446 // Iterating over the list of keys will preserve the order of the
1447 // fields.
1448 string_vector keys = m.keys ();
1449
1450 for (octave_idx_type i = 0; i < nf; i++)
1451 {
1452 std::string key = keys(i);
1453
1454 octave_value val = map.contents (key);
1455
1456 bool b = save_binary_data (os, val, key, "", 0, save_as_floats);
1457
1458 if (! b)
1459 return os;
1460 }
1461
1462 return true;
1463 }
1464
1465 bool
1466 octave_struct::load_binary (std::istream& is, bool swap,
1467 oct_mach_info::float_format fmt)
1468 {
1469 bool success = true;
1470 int32_t len;
1471 if (! is.read (reinterpret_cast<char *> (&len), 4))
1472 return false;
1473 if (swap)
1474 swap_bytes<4> (&len);
1475
1476 dim_vector dv (1, 1);
1477
1478 if (len < 0)
1479 {
1480 // We have explicit dimensions.
1481 int mdims = -len;
1482
1483 int32_t di;
1484 dv.resize (mdims);
1485
1486 for (int i = 0; i < mdims; i++)
1487 {
1488 if (! is.read (reinterpret_cast<char *> (&di), 4))
1489 return false;
1490 if (swap)
1491 swap_bytes<4> (&di);
1492 dv(i) = di;
1493 }
1494
1495 if (! is.read (reinterpret_cast<char *> (&len), 4))
1496 return false;
1497 if (swap)
1498 swap_bytes<4> (&len);
1499 }
1500
1501 if (len > 0)
1502 {
1503 Octave_map m (dv);
1504
1505 for (octave_idx_type j = 0; j < len; j++)
1506 {
1507 octave_value t2;
1508 bool dummy;
1509 std::string doc;
1510
1511 // recurse to read cell elements
1512 std::string nm = read_binary_data (is, swap, fmt, std::string (),
1513 dummy, t2, doc);
1514
1515 if (!is)
1516 break;
1517
1518 Cell tcell = t2.is_cell () ? t2.cell_value () : Cell (t2);
1519
1520 if (error_state)
1521 {
1522 error ("load: internal error loading struct elements");
1523 return false;
1524 }
1525
1526 m.assign (nm, tcell);
1527 }
1528
1529 if (is)
1530 map = m;
1531 else
1532 {
1533 error ("load: failed to load structure");
1534 success = false;
1535 }
1536 }
1537 else if (len == 0)
1538 map = Octave_map (dv);
1539 else
1540 success = false;
1541
1542 return success;
1543 }
1544
1545 #if defined (HAVE_HDF5)
1546
1547 bool
1548 octave_struct::save_hdf5 (hid_t loc_id, const char *name, bool save_as_floats)
1549 {
1550 hid_t data_hid = -1;
1551
1552 #if HAVE_HDF5_18
1553 data_hid = H5Gcreate (loc_id, name, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
1554 #else
1555 data_hid = H5Gcreate (loc_id, name, 0);
1556 #endif
1557 if (data_hid < 0) return false;
1558
1559 // recursively add each element of the structure to this group
1560 Octave_map m = map_value ();
1561
1562 octave_idx_type nf = m.nfields ();
1563
1564 // Iterating over the list of keys will preserve the order of the
1565 // fields.
1566 string_vector keys = m.keys ();
1567
1568 for (octave_idx_type i = 0; i < nf; i++)
1569 {
1570 std::string key = keys(i);
1571
1572 octave_value val = map.contents (key);
1573
1574 bool retval2 = add_hdf5_data (data_hid, val, key, "", false,
1575 save_as_floats);
1576
1577 if (! retval2)
1578 break;
1579 }
1580
1581 H5Gclose (data_hid);
1582
1583 return true;
1584 }
1585
1586 bool
1587 octave_struct::load_hdf5 (hid_t loc_id, const char *name)
1588 {
1589 bool retval = false;
1590
1591 hdf5_callback_data dsub;
1592
1593 herr_t retval2 = 0;
1594 Octave_map m (dim_vector (1, 1));
1595 int current_item = 0;
1596 hsize_t num_obj = 0;
1597 #if HAVE_HDF5_18
1598 hid_t group_id = H5Gopen (loc_id, name, H5P_DEFAULT);
1599 #else
1600 hid_t group_id = H5Gopen (loc_id, name);
1601 #endif
1602 H5Gget_num_objs (group_id, &num_obj);
1603 H5Gclose (group_id);
1604
1605 // FIXME -- fields appear to be sorted alphabetically on loading.
1606 // Why is that happening?
1607
1608 while (current_item < static_cast<int> (num_obj)
1609 && (retval2 = H5Giterate (loc_id, name, &current_item,
1610 hdf5_read_next_data, &dsub)) > 0)
1611 {
1612 octave_value t2 = dsub.tc;
1613
1614 Cell tcell = t2.is_cell () ? t2.cell_value () : Cell (t2);
1615
1616 if (error_state)
1617 {
1618 error ("load: internal error loading struct elements");
1619 return false;
1620 }
1621
1622 m.assign (dsub.name, tcell);
1623
1624 }
1625
1626 if (retval2 >= 0)
1627 {
1628 map = m;
1629 retval = true;
1630 }
1631
1632 return retval;
1633 }
1634
1635 #endif
1636
1637 mxArray *
1638 octave_struct::as_mxArray (void) const
1639 {
1640 int nf = nfields ();
1641 string_vector kv = map_keys ();
1642
1643 OCTAVE_LOCAL_BUFFER (const char *, f, nf);
1644
1645 for (int i = 0; i < nf; i++)
1646 f[i] = kv[i].c_str ();
1647
1648 mxArray *retval = new mxArray (dims (), nf, f);
1649
1650 mxArray **elts = static_cast<mxArray **> (retval->get_data ());
1651
1652 mwSize nel = numel ();
1653
1654 mwSize ntot = nf * nel;
1655
1656 for (int i = 0; i < nf; i++)
1657 {
1658 Cell c = map.contents (kv[i]);
1659
1660 const octave_value *p = c.data ();
1661
1662 mwIndex k = 0;
1663 for (mwIndex j = i; j < ntot; j += nf)
1664 elts[j] = new mxArray (p[k++]);
1665 }
1666
1667 return retval;
1668 }