00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #ifdef HAVE_CONFIG_H
00024 #include <config.h>
00025 #endif
00026
00027 #include <iostream>
00028
00029 #include "Cell.h"
00030 #include "defun.h"
00031 #include "error.h"
00032 #include "gripes.h"
00033 #include "oct-lvalue.h"
00034 #include "ov-struct.h"
00035 #include "unwind-prot.h"
00036 #include "utils.h"
00037 #include "variables.h"
00038
00039 #include "Array-util.h"
00040 #include "oct-locbuf.h"
00041
00042 #include "byte-swap.h"
00043 #include "ls-oct-ascii.h"
00044 #include "ls-oct-binary.h"
00045 #include "ls-hdf5.h"
00046 #include "ls-utils.h"
00047 #include "pr-output.h"
00048
00049 DEFINE_OCTAVE_ALLOCATOR(octave_struct);
00050
00051 DEFINE_OV_TYPEID_FUNCTIONS_AND_DATA(octave_struct, "struct", "struct");
00052
00053
00054 static int Vstruct_levels_to_print = 2;
00055
00056
00057
00058 static bool Vprint_struct_array_contents = false;
00059
00060 octave_base_value *
00061 octave_struct::try_narrowing_conversion (void)
00062 {
00063 octave_base_value *retval = 0;
00064
00065 if (numel () == 1)
00066 retval = new octave_scalar_struct (map.checkelem (0));
00067
00068 return retval;
00069 }
00070
00071 Cell
00072 octave_struct::dotref (const octave_value_list& idx, bool auto_add)
00073 {
00074 Cell retval;
00075
00076 assert (idx.length () == 1);
00077
00078 std::string nm = idx(0).string_value ();
00079
00080 octave_map::const_iterator p = map.seek (nm);
00081
00082 if (p != map.end ())
00083 retval = map.contents (p);
00084 else if (auto_add)
00085 retval = (numel () == 0) ? Cell (dim_vector (1, 1)) : Cell (dims ());
00086 else
00087 error ("structure has no member '%s'", nm.c_str ());
00088
00089 return retval;
00090 }
00091
00092 #if 0
00093 static void
00094 gripe_invalid_index1 (void)
00095 {
00096 error ("invalid index for structure array");
00097 }
00098 #endif
00099
00100 static void
00101 gripe_invalid_index_for_assignment (void)
00102 {
00103 error ("invalid index for structure array assignment");
00104 }
00105
00106 static void
00107 gripe_invalid_index_type (const std::string& nm, char t)
00108 {
00109 error ("%s cannot be indexed with %c", nm.c_str (), t);
00110 }
00111
00112 static void
00113 gripe_failed_assignment (void)
00114 {
00115 error ("assignment to structure element failed");
00116 }
00117
00118 octave_value_list
00119 octave_struct::subsref (const std::string& type,
00120 const std::list<octave_value_list>& idx,
00121 int nargout)
00122 {
00123 octave_value_list retval;
00124
00125 int skip = 1;
00126
00127 switch (type[0])
00128 {
00129 case '(':
00130 {
00131 if (type.length () > 1 && type[1] == '.')
00132 {
00133 std::list<octave_value_list>::const_iterator p = idx.begin ();
00134 octave_value_list key_idx = *++p;
00135
00136 const Cell tmp = dotref (key_idx);
00137
00138 if (! error_state)
00139 {
00140 const Cell t = tmp.index (idx.front ());
00141
00142 retval(0) = (t.length () == 1) ? t(0) : octave_value (t, true);
00143
00144
00145
00146
00147 skip++;
00148 }
00149 }
00150 else
00151 retval(0) = do_index_op (idx.front ());
00152 }
00153 break;
00154
00155 case '.':
00156 {
00157 if (map.numel() > 0)
00158 {
00159 const Cell t = dotref (idx.front ());
00160
00161 retval(0) = (t.length () == 1) ? t(0) : octave_value (t, true);
00162 }
00163 }
00164 break;
00165
00166 case '{':
00167 gripe_invalid_index_type (type_name (), type[0]);
00168 break;
00169
00170 default:
00171 panic_impossible ();
00172 }
00173
00174
00175
00176
00177
00178 if (idx.size () > 1)
00179 retval = retval(0).next_subsref (nargout, type, idx, skip);
00180
00181 return retval;
00182 }
00183
00184 octave_value
00185 octave_struct::subsref (const std::string& type,
00186 const std::list<octave_value_list>& idx,
00187 bool auto_add)
00188 {
00189 octave_value retval;
00190
00191 int skip = 1;
00192
00193 switch (type[0])
00194 {
00195 case '(':
00196 {
00197 if (type.length () > 1 && type[1] == '.')
00198 {
00199 std::list<octave_value_list>::const_iterator p = idx.begin ();
00200 octave_value_list key_idx = *++p;
00201
00202 const Cell tmp = dotref (key_idx, auto_add);
00203
00204 if (! error_state)
00205 {
00206 const Cell t = tmp.index (idx.front (), auto_add);
00207
00208 retval = (t.length () == 1) ? t(0) : octave_value (t, true);
00209
00210
00211
00212
00213 skip++;
00214 }
00215 }
00216 else
00217 retval = do_index_op (idx.front (), auto_add);
00218 }
00219 break;
00220
00221 case '.':
00222 {
00223 if (map.numel() > 0)
00224 {
00225 const Cell t = dotref (idx.front (), auto_add);
00226
00227 retval = (t.length () == 1) ? t(0) : octave_value (t, true);
00228 }
00229 }
00230 break;
00231
00232 case '{':
00233 gripe_invalid_index_type (type_name (), type[0]);
00234 break;
00235
00236 default:
00237 panic_impossible ();
00238 }
00239
00240
00241
00242
00243
00244 if (idx.size () > 1)
00245 retval = retval.next_subsref (auto_add, type, idx, skip);
00246
00247 return retval;
00248 }
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258 octave_value
00259 octave_struct::numeric_conv (const octave_value& val,
00260 const std::string& type)
00261 {
00262 octave_value retval;
00263
00264 if (type.length () > 0 && type[0] == '.' && ! val.is_map ())
00265 retval = octave_map ();
00266 else
00267 retval = val;
00268
00269 return retval;
00270 }
00271
00272 octave_value
00273 octave_struct::subsasgn (const std::string& type,
00274 const std::list<octave_value_list>& idx,
00275 const octave_value& rhs)
00276 {
00277 octave_value retval;
00278
00279 int n = type.length ();
00280
00281 octave_value t_rhs = rhs;
00282
00283 if (idx.front ().empty ())
00284 {
00285 error ("missing index in indexed assignment");
00286 return retval;
00287 }
00288
00289 if (n > 1 && ! (type.length () == 2 && type[0] == '(' && type[1] == '.'))
00290 {
00291 switch (type[0])
00292 {
00293 case '(':
00294 {
00295 if (type.length () > 1 && type[1] == '.')
00296 {
00297 std::list<octave_value_list>::const_iterator p = idx.begin ();
00298 octave_value_list t_idx = *p;
00299
00300 octave_value_list key_idx = *++p;
00301
00302 assert (key_idx.length () == 1);
00303
00304 std::string key = key_idx(0).string_value ();
00305
00306 std::list<octave_value_list> next_idx (idx);
00307
00308
00309
00310
00311 next_idx.erase (next_idx.begin ());
00312 next_idx.erase (next_idx.begin ());
00313
00314 std::string next_type = type.substr (2);
00315
00316 Cell tmpc (1, 1);
00317 octave_map::iterator pkey = map.seek (key);
00318 if (pkey != map.end ())
00319 {
00320 map.contents (pkey).make_unique ();
00321 tmpc = map.contents (pkey).index (idx.front (), true);
00322 }
00323
00324
00325 if (! error_state)
00326 {
00327 if (tmpc.numel () == 1)
00328 {
00329 octave_value& tmp = tmpc(0);
00330
00331 bool orig_undefined = tmp.is_undefined ();
00332
00333 if (orig_undefined || tmp.is_zero_by_zero ())
00334 {
00335 tmp = octave_value::empty_conv (next_type, rhs);
00336 tmp.make_unique ();
00337 }
00338 else
00339
00340 tmp.make_unique (1);
00341
00342 if (! error_state)
00343 t_rhs = (orig_undefined
00344 ? tmp.undef_subsasgn (next_type, next_idx, rhs)
00345 : tmp.subsasgn (next_type, next_idx, rhs));
00346 }
00347 else
00348 gripe_indexed_cs_list ();
00349 }
00350 }
00351 else
00352 gripe_invalid_index_for_assignment ();
00353 }
00354 break;
00355
00356 case '.':
00357 {
00358 octave_value_list key_idx = idx.front ();
00359
00360 assert (key_idx.length () == 1);
00361
00362 std::string key = key_idx(0).string_value ();
00363
00364 std::list<octave_value_list> next_idx (idx);
00365
00366 next_idx.erase (next_idx.begin ());
00367
00368 std::string next_type = type.substr (1);
00369
00370 Cell tmpc (1, 1);
00371 octave_map::iterator pkey = map.seek (key);
00372 if (pkey != map.end ())
00373 {
00374 map.contents (pkey).make_unique ();
00375 tmpc = map.contents (pkey);
00376 }
00377
00378
00379 if (! error_state)
00380 {
00381 if (tmpc.numel () == 1)
00382 {
00383 octave_value& tmp = tmpc(0);
00384
00385 bool orig_undefined = tmp.is_undefined ();
00386
00387 if (orig_undefined || tmp.is_zero_by_zero ())
00388 {
00389 tmp = octave_value::empty_conv (next_type, rhs);
00390 tmp.make_unique ();
00391 }
00392 else
00393
00394 tmp.make_unique (1);
00395
00396 if (! error_state)
00397 t_rhs = (orig_undefined
00398 ? tmp.undef_subsasgn (next_type, next_idx, rhs)
00399 : tmp.subsasgn (next_type, next_idx, rhs));
00400 }
00401 else
00402 gripe_indexed_cs_list ();
00403 }
00404 }
00405 break;
00406
00407 case '{':
00408 gripe_invalid_index_type (type_name (), type[0]);
00409 break;
00410
00411 default:
00412 panic_impossible ();
00413 }
00414 }
00415
00416 if (! error_state)
00417 {
00418 switch (type[0])
00419 {
00420 case '(':
00421 {
00422 if (n > 1 && type[1] == '.')
00423 {
00424 std::list<octave_value_list>::const_iterator p = idx.begin ();
00425 octave_value_list key_idx = *++p;
00426 octave_value_list idxf = idx.front ();
00427
00428 assert (key_idx.length () == 1);
00429
00430 std::string key = key_idx(0).string_value ();
00431
00432 if (! error_state)
00433 {
00434 if (t_rhs.is_cs_list ())
00435 {
00436 Cell tmp_cell = Cell (t_rhs.list_value ());
00437
00438
00439
00440 dim_vector didx = dims ().redim (idxf.length ());
00441 for (octave_idx_type k = 0; k < idxf.length (); k++)
00442 if (! idxf(k).is_magic_colon ()) didx(k) = idxf(k).numel ();
00443
00444 if (didx.numel () == tmp_cell.numel ())
00445 tmp_cell = tmp_cell.reshape (didx);
00446
00447
00448 map.assign (idxf, key, tmp_cell);
00449
00450 if (! error_state)
00451 {
00452 count++;
00453 retval = octave_value (this);
00454 }
00455 else
00456 gripe_failed_assignment ();
00457 }
00458 else
00459 {
00460 const octave_map& cmap = const_cast<const octave_map &> (map);
00461
00462 if (idxf.all_scalars ()
00463 || cmap.contents (key).index (idxf, true).numel () == 1)
00464 {
00465 map.assign (idxf, key, Cell (t_rhs.storable_value ()));
00466 if (! error_state)
00467 {
00468 count++;
00469 retval = octave_value (this);
00470 }
00471 else
00472 gripe_failed_assignment ();
00473 }
00474 else if (! error_state)
00475 gripe_nonbraced_cs_list_assignment ();
00476 }
00477 }
00478 else
00479 gripe_failed_assignment ();
00480 }
00481 else
00482 {
00483 if (t_rhs.is_map() || t_rhs.is_object ())
00484 {
00485 octave_map rhs_map = t_rhs.map_value ();
00486
00487 if (! error_state)
00488 {
00489 map.assign (idx.front (), rhs_map);
00490
00491 if (! error_state)
00492 {
00493 count++;
00494 retval = octave_value (this);
00495 }
00496 else
00497 gripe_failed_assignment ();
00498 }
00499 else
00500 error ("invalid structure assignment");
00501 }
00502 else
00503 {
00504 if (t_rhs.is_null_value())
00505 {
00506 map.delete_elements (idx.front());
00507
00508 if (! error_state)
00509 {
00510 count++;
00511 retval = octave_value (this);
00512 }
00513 else
00514 gripe_failed_assignment ();
00515 }
00516 else
00517 error ("invalid structure assignment");
00518 }
00519 }
00520 }
00521 break;
00522
00523 case '.':
00524 {
00525 octave_value_list key_idx = idx.front ();
00526
00527 assert (key_idx.length () == 1);
00528
00529 std::string key = key_idx(0).string_value ();
00530
00531 if (t_rhs.is_cs_list ())
00532 {
00533 Cell tmp_cell = Cell (t_rhs.list_value ());
00534
00535
00536
00537
00538
00539 if (numel () == tmp_cell.numel ())
00540 tmp_cell = tmp_cell.reshape (dims ());
00541
00542 map.setfield (key, tmp_cell);
00543 }
00544 else
00545 {
00546 Cell tmp_cell(1, 1);
00547 tmp_cell(0) = t_rhs.storable_value ();
00548 map.setfield (key, tmp_cell);
00549 }
00550
00551 if (! error_state)
00552 {
00553 count++;
00554 retval = octave_value (this);
00555 }
00556 else
00557 gripe_failed_assignment ();
00558 }
00559 break;
00560
00561 case '{':
00562 gripe_invalid_index_type (type_name (), type[0]);
00563 break;
00564
00565 default:
00566 panic_impossible ();
00567 }
00568 }
00569 else
00570 gripe_failed_assignment ();
00571
00572 retval.maybe_mutate ();
00573
00574 return retval;
00575 }
00576
00577 octave_value
00578 octave_struct::do_index_op (const octave_value_list& idx, bool resize_ok)
00579 {
00580
00581 return map.index (idx, resize_ok);
00582 }
00583
00584 size_t
00585 octave_struct::byte_size (void) const
00586 {
00587
00588
00589 size_t retval = 0;
00590
00591 for (octave_map::const_iterator p = map.begin (); p != map.end (); p++)
00592 {
00593 std::string key = map.key (p);
00594
00595 octave_value val = octave_value (map.contents (p));
00596
00597 retval += val.byte_size ();
00598 }
00599
00600 return retval;
00601 }
00602
00603 void
00604 octave_struct::print (std::ostream& os, bool) const
00605 {
00606 print_raw (os);
00607 }
00608
00609 void
00610 octave_struct::print_raw (std::ostream& os, bool) const
00611 {
00612 unwind_protect frame;
00613
00614 frame.protect_var (Vstruct_levels_to_print);
00615
00616 if (Vstruct_levels_to_print >= 0)
00617 {
00618 bool max_depth_reached = Vstruct_levels_to_print-- == 0;
00619
00620 bool print_fieldnames_only
00621 = (max_depth_reached || ! Vprint_struct_array_contents);
00622
00623 increment_indent_level ();
00624
00625 newline (os);
00626 indent (os);
00627 dim_vector dv = dims ();
00628 os << dv.str () << " struct array containing the fields:";
00629 newline (os);
00630
00631 increment_indent_level ();
00632
00633 string_vector key_list = map.fieldnames ();
00634
00635 for (octave_idx_type i = 0; i < key_list.length (); i++)
00636 {
00637 std::string key = key_list[i];
00638
00639 Cell val = map.contents (key);
00640
00641 newline (os);
00642
00643 if (print_fieldnames_only)
00644 {
00645 indent (os);
00646 os << key;
00647 }
00648 else
00649 {
00650 octave_value tmp (val);
00651 tmp.print_with_name (os, key);
00652 }
00653 }
00654
00655 if (print_fieldnames_only)
00656 newline (os);
00657
00658 decrement_indent_level ();
00659 decrement_indent_level ();
00660 }
00661 else
00662 {
00663 indent (os);
00664 os << "<structure>";
00665 newline (os);
00666 }
00667 }
00668
00669 bool
00670 octave_struct::print_name_tag (std::ostream& os, const std::string& name) const
00671 {
00672 bool retval = false;
00673
00674 indent (os);
00675
00676 if (Vstruct_levels_to_print < 0)
00677 os << name << " = ";
00678 else
00679 {
00680 os << name << " =";
00681 newline (os);
00682 retval = true;
00683 }
00684
00685 return retval;
00686 }
00687
00688 static bool
00689 scalar (const dim_vector& dims)
00690 {
00691 return dims.length () == 2 && dims (0) == 1 && dims (1) == 1;
00692 }
00693
00694
00695
00696
00697
00698
00699
00700
00701
00702
00703
00704
00705
00706
00707
00708
00709
00710
00711
00712
00713
00714 bool
00715 octave_struct::save_ascii (std::ostream& os)
00716 {
00717 octave_map m = map_value ();
00718
00719 octave_idx_type nf = m.nfields ();
00720
00721 const dim_vector dv = dims ();
00722
00723 os << "# ndims: " << dv.length () << "\n";
00724
00725 for (int i = 0; i < dv.length (); i++)
00726 os << " " << dv (i);
00727 os << "\n";
00728
00729 os << "# length: " << nf << "\n";
00730
00731
00732
00733 string_vector keys = m.fieldnames ();
00734
00735 for (octave_idx_type i = 0; i < nf; i++)
00736 {
00737 std::string key = keys(i);
00738
00739 octave_value val = map.contents (key);
00740
00741 bool b = save_ascii_data (os, val, key, false, 0);
00742
00743 if (! b)
00744 return os;
00745 }
00746
00747 return true;
00748 }
00749
00750 bool
00751 octave_struct::load_ascii (std::istream& is)
00752 {
00753 octave_idx_type len = 0;
00754 dim_vector dv (1, 1);
00755 bool success = true;
00756
00757
00758
00759
00760 string_vector keywords(2);
00761
00762 keywords[0] = "ndims";
00763 keywords[1] = "length";
00764
00765 std::string kw;
00766
00767 if (extract_keyword (is, keywords, kw, len, true))
00768 {
00769 if (kw == keywords[0])
00770 {
00771 int mdims = std::max (static_cast<int> (len), 2);
00772 dv.resize (mdims);
00773 for (int i = 0; i < mdims; i++)
00774 is >> dv(i);
00775
00776 success = extract_keyword (is, keywords[1], len);
00777 }
00778 }
00779 else
00780 success = false;
00781
00782 if (success && len >= 0)
00783 {
00784 if (len > 0)
00785 {
00786 octave_map m (dv);
00787
00788 for (octave_idx_type j = 0; j < len; j++)
00789 {
00790 octave_value t2;
00791 bool dummy;
00792
00793
00794 std::string nm
00795 = read_ascii_data (is, std::string (), dummy, t2, j);
00796
00797 if (!is)
00798 break;
00799
00800 Cell tcell = t2.is_cell () ? t2.cell_value () : Cell (t2);
00801
00802 if (error_state)
00803 {
00804 error ("load: internal error loading struct elements");
00805 return false;
00806 }
00807
00808 m.setfield (nm, tcell);
00809 }
00810
00811 if (is)
00812 map = m;
00813 else
00814 {
00815 error ("load: failed to load structure");
00816 success = false;
00817 }
00818 }
00819 else if (len == 0 )
00820 map = octave_map (dv);
00821 else
00822 panic_impossible ();
00823 }
00824 else {
00825 error ("load: failed to extract number of elements in structure");
00826 success = false;
00827 }
00828
00829 return success;
00830 }
00831
00832 bool
00833 octave_struct::save_binary (std::ostream& os, bool& save_as_floats)
00834 {
00835 octave_map m = map_value ();
00836
00837 octave_idx_type nf = m.nfields ();
00838
00839 dim_vector d = dims ();
00840 if (d.length () < 1)
00841 return false;
00842
00843
00844 int32_t di = - d.length();
00845 os.write (reinterpret_cast<char *> (&di), 4);
00846 for (int i = 0; i < d.length (); i++)
00847 {
00848 di = d(i);
00849 os.write (reinterpret_cast<char *> (&di), 4);
00850 }
00851
00852 int32_t len = nf;
00853 os.write (reinterpret_cast<char *> (&len), 4);
00854
00855
00856
00857 string_vector keys = m.fieldnames ();
00858
00859 for (octave_idx_type i = 0; i < nf; i++)
00860 {
00861 std::string key = keys(i);
00862
00863 octave_value val = map.contents (key);
00864
00865 bool b = save_binary_data (os, val, key, "", 0, save_as_floats);
00866
00867 if (! b)
00868 return os;
00869 }
00870
00871 return true;
00872 }
00873
00874 bool
00875 octave_struct::load_binary (std::istream& is, bool swap,
00876 oct_mach_info::float_format fmt)
00877 {
00878 bool success = true;
00879 int32_t len;
00880 if (! is.read (reinterpret_cast<char *> (&len), 4))
00881 return false;
00882 if (swap)
00883 swap_bytes<4> (&len);
00884
00885 dim_vector dv (1, 1);
00886
00887 if (len < 0)
00888 {
00889
00890 int mdims = -len;
00891
00892 int32_t di;
00893 dv.resize (mdims);
00894
00895 for (int i = 0; i < mdims; i++)
00896 {
00897 if (! is.read (reinterpret_cast<char *> (&di), 4))
00898 return false;
00899 if (swap)
00900 swap_bytes<4> (&di);
00901 dv(i) = di;
00902 }
00903
00904 if (! is.read (reinterpret_cast<char *> (&len), 4))
00905 return false;
00906 if (swap)
00907 swap_bytes<4> (&len);
00908 }
00909
00910 if (len > 0)
00911 {
00912 octave_map m (dv);
00913
00914 for (octave_idx_type j = 0; j < len; j++)
00915 {
00916 octave_value t2;
00917 bool dummy;
00918 std::string doc;
00919
00920
00921 std::string nm = read_binary_data (is, swap, fmt, std::string (),
00922 dummy, t2, doc);
00923
00924 if (!is)
00925 break;
00926
00927 Cell tcell = t2.is_cell () ? t2.cell_value () : Cell (t2);
00928
00929 if (error_state)
00930 {
00931 error ("load: internal error loading struct elements");
00932 return false;
00933 }
00934
00935 m.setfield (nm, tcell);
00936 }
00937
00938 if (is)
00939 map = m;
00940 else
00941 {
00942 error ("load: failed to load structure");
00943 success = false;
00944 }
00945 }
00946 else if (len == 0)
00947 map = octave_map (dv);
00948 else
00949 success = false;
00950
00951 return success;
00952 }
00953
00954 #if defined (HAVE_HDF5)
00955
00956 bool
00957 octave_struct::save_hdf5 (hid_t loc_id, const char *name, bool save_as_floats)
00958 {
00959 hid_t data_hid = -1;
00960
00961 #if HAVE_HDF5_18
00962 data_hid = H5Gcreate (loc_id, name, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
00963 #else
00964 data_hid = H5Gcreate (loc_id, name, 0);
00965 #endif
00966 if (data_hid < 0) return false;
00967
00968
00969 octave_map m = map_value ();
00970
00971 octave_idx_type nf = m.nfields ();
00972
00973
00974
00975 string_vector keys = m.fieldnames ();
00976
00977 for (octave_idx_type i = 0; i < nf; i++)
00978 {
00979 std::string key = keys(i);
00980
00981 octave_value val = map.contents (key);
00982
00983 bool retval2 = add_hdf5_data (data_hid, val, key, "", false,
00984 save_as_floats);
00985
00986 if (! retval2)
00987 break;
00988 }
00989
00990 H5Gclose (data_hid);
00991
00992 return true;
00993 }
00994
00995 bool
00996 octave_struct::load_hdf5 (hid_t loc_id, const char *name)
00997 {
00998 bool retval = false;
00999
01000 hdf5_callback_data dsub;
01001
01002 herr_t retval2 = 0;
01003 octave_map m (dim_vector (1, 1));
01004 int current_item = 0;
01005 hsize_t num_obj = 0;
01006 #if HAVE_HDF5_18
01007 hid_t group_id = H5Gopen (loc_id, name, H5P_DEFAULT);
01008 #else
01009 hid_t group_id = H5Gopen (loc_id, name);
01010 #endif
01011 H5Gget_num_objs (group_id, &num_obj);
01012 H5Gclose (group_id);
01013
01014
01015
01016
01017 while (current_item < static_cast<int> (num_obj)
01018 && (retval2 = H5Giterate (loc_id, name, ¤t_item,
01019 hdf5_read_next_data, &dsub)) > 0)
01020 {
01021 octave_value t2 = dsub.tc;
01022
01023 Cell tcell = t2.is_cell () ? t2.cell_value () : Cell (t2);
01024
01025 if (error_state)
01026 {
01027 error ("load: internal error loading struct elements");
01028 return false;
01029 }
01030
01031 m.setfield (dsub.name, tcell);
01032
01033 }
01034
01035 if (retval2 >= 0)
01036 {
01037 map = m;
01038 retval = true;
01039 }
01040
01041 return retval;
01042 }
01043
01044 #endif
01045
01046 mxArray *
01047 octave_struct::as_mxArray (void) const
01048 {
01049 int nf = nfields ();
01050 string_vector kv = map_keys ();
01051
01052 OCTAVE_LOCAL_BUFFER (const char *, f, nf);
01053
01054 for (int i = 0; i < nf; i++)
01055 f[i] = kv[i].c_str ();
01056
01057 mxArray *retval = new mxArray (dims (), nf, f);
01058
01059 mxArray **elts = static_cast<mxArray **> (retval->get_data ());
01060
01061 mwSize nel = numel ();
01062
01063 mwSize ntot = nf * nel;
01064
01065 for (int i = 0; i < nf; i++)
01066 {
01067 Cell c = map.contents (kv[i]);
01068
01069 const octave_value *p = c.data ();
01070
01071 mwIndex k = 0;
01072 for (mwIndex j = i; j < ntot; j += nf)
01073 elts[j] = new mxArray (p[k++]);
01074 }
01075
01076 return retval;
01077 }
01078
01079 octave_value
01080 octave_struct::fast_elem_extract (octave_idx_type n) const
01081 {
01082 if (n < map.numel ())
01083 return map.checkelem (n);
01084 else
01085 return octave_value ();
01086 }
01087
01088 bool
01089 octave_struct::fast_elem_insert (octave_idx_type n,
01090 const octave_value& x)
01091 {
01092 bool retval = false;
01093
01094 if (n < map.numel ())
01095 {
01096
01097
01098 const octave_scalar_map *sm_ptr;
01099 void *here = reinterpret_cast<void *>(&sm_ptr);
01100 return (x.get_rep().fast_elem_insert_self (here, btyp_struct)
01101 && map.fast_elem_insert (n, *sm_ptr));
01102 }
01103
01104 return retval;
01105 }
01106 DEFINE_OCTAVE_ALLOCATOR(octave_scalar_struct);
01107
01108 DEFINE_OV_TYPEID_FUNCTIONS_AND_DATA(octave_scalar_struct, "scalar struct", "struct");
01109
01110 octave_value
01111 octave_scalar_struct::dotref (const octave_value_list& idx, bool auto_add)
01112 {
01113 assert (idx.length () == 1);
01114
01115 std::string nm = idx(0).string_value ();
01116
01117 octave_value retval = map.getfield (nm);
01118
01119 if (! auto_add && retval.is_undefined ())
01120 error ("structure has no member '%s'", nm.c_str ());
01121
01122 return retval;
01123 }
01124
01125 octave_value
01126 octave_scalar_struct::subsref (const std::string& type,
01127 const std::list<octave_value_list>& idx)
01128 {
01129 octave_value retval;
01130
01131 if (type[0] == '.')
01132 {
01133 int skip = 1;
01134
01135 retval = dotref (idx.front ());
01136
01137 if (idx.size () > 1)
01138 retval = retval.next_subsref (type, idx, skip);
01139 }
01140 else
01141 retval = to_array ().subsref (type, idx);
01142
01143 return retval;
01144 }
01145
01146 octave_value_list
01147 octave_scalar_struct::subsref (const std::string& type,
01148 const std::list<octave_value_list>& idx,
01149 int nargout)
01150 {
01151 octave_value_list retval;
01152
01153 if (type[0] == '.')
01154 {
01155 int skip = 1;
01156
01157 retval(0) = dotref (idx.front ());
01158
01159 if (idx.size () > 1)
01160 retval = retval(0).next_subsref (nargout, type, idx, skip);
01161 }
01162 else
01163 retval = to_array ().subsref (type, idx, nargout);
01164
01165 return retval;
01166 }
01167
01168 octave_value
01169 octave_scalar_struct::subsref (const std::string& type,
01170 const std::list<octave_value_list>& idx,
01171 bool auto_add)
01172 {
01173 octave_value retval;
01174
01175 if (type[0] == '.')
01176 {
01177 int skip = 1;
01178
01179 retval = dotref (idx.front (), auto_add);
01180
01181 if (idx.size () > 1)
01182 retval = retval.next_subsref (auto_add, type, idx, skip);
01183 }
01184 else
01185 retval = to_array ().subsref (type, idx, auto_add);
01186
01187 return retval;
01188 }
01189
01190
01191
01192
01193
01194
01195
01196
01197
01198 octave_value
01199 octave_scalar_struct::numeric_conv (const octave_value& val,
01200 const std::string& type)
01201 {
01202 octave_value retval;
01203
01204 if (type.length () > 0 && type[0] == '.' && ! val.is_map ())
01205 retval = octave_map ();
01206 else
01207 retval = val;
01208
01209 return retval;
01210 }
01211
01212 octave_value
01213 octave_scalar_struct::subsasgn (const std::string& type,
01214 const std::list<octave_value_list>& idx,
01215 const octave_value& rhs)
01216 {
01217 octave_value retval;
01218
01219 if (idx.front ().empty ())
01220 {
01221 error ("missing index in indexed assignment");
01222 return retval;
01223 }
01224
01225 if (type[0] == '.')
01226 {
01227 int n = type.length ();
01228
01229 octave_value t_rhs = rhs;
01230
01231 octave_value_list key_idx = idx.front ();
01232
01233 assert (key_idx.length () == 1);
01234
01235 std::string key = key_idx(0).string_value ();
01236
01237 if (n > 1)
01238 {
01239 std::list<octave_value_list> next_idx (idx);
01240
01241 next_idx.erase (next_idx.begin ());
01242
01243 std::string next_type = type.substr (1);
01244
01245 octave_value tmp;
01246 octave_map::iterator pkey = map.seek (key);
01247 if (pkey != map.end ())
01248 {
01249 map.contents (pkey).make_unique ();
01250 tmp = map.contents (pkey);
01251 }
01252
01253 if (! error_state)
01254 {
01255 bool orig_undefined = tmp.is_undefined ();
01256
01257 if (orig_undefined || tmp.is_zero_by_zero ())
01258 {
01259 tmp = octave_value::empty_conv (next_type, rhs);
01260 tmp.make_unique ();
01261 }
01262 else
01263
01264 tmp.make_unique (1);
01265
01266 if (! error_state)
01267 t_rhs = (orig_undefined
01268 ? tmp.undef_subsasgn (next_type, next_idx, rhs)
01269 : tmp.subsasgn (next_type, next_idx, rhs));
01270 }
01271 }
01272
01273 if (! error_state)
01274 map.setfield (key, t_rhs.storable_value ());
01275 else
01276 gripe_failed_assignment ();
01277
01278 count++;
01279 retval = this;
01280 }
01281 else
01282 {
01283
01284 octave_value tmp (new octave_struct (octave_map (map)));
01285 retval = tmp.subsasgn (type, idx, rhs);
01286 }
01287
01288 return retval;
01289 }
01290
01291 octave_value
01292 octave_scalar_struct::do_index_op (const octave_value_list& idx, bool resize_ok)
01293 {
01294
01295 return octave_map (map).index (idx, resize_ok);
01296 }
01297
01298 size_t
01299 octave_scalar_struct::byte_size (void) const
01300 {
01301
01302
01303 size_t retval = 0;
01304
01305 for (octave_map::const_iterator p = map.begin (); p != map.end (); p++)
01306 {
01307 std::string key = map.key (p);
01308
01309 octave_value val = octave_value (map.contents (p));
01310
01311 retval += val.byte_size ();
01312 }
01313
01314 return retval;
01315 }
01316
01317 void
01318 octave_scalar_struct::print (std::ostream& os, bool) const
01319 {
01320 print_raw (os);
01321 }
01322
01323 void
01324 octave_scalar_struct::print_raw (std::ostream& os, bool) const
01325 {
01326 unwind_protect frame;
01327
01328 frame.protect_var (Vstruct_levels_to_print);
01329
01330 if (Vstruct_levels_to_print >= 0)
01331 {
01332 bool max_depth_reached = Vstruct_levels_to_print-- == 0;
01333
01334 bool print_fieldnames_only = max_depth_reached;
01335
01336 increment_indent_level ();
01337
01338 if (! Vcompact_format)
01339 newline (os);
01340
01341 indent (os);
01342 os << "scalar structure containing the fields:";
01343 newline (os);
01344 if (! Vcompact_format)
01345 newline (os);
01346
01347 increment_indent_level ();
01348
01349 string_vector key_list = map.fieldnames ();
01350
01351 for (octave_idx_type i = 0; i < key_list.length (); i++)
01352 {
01353 std::string key = key_list[i];
01354
01355 octave_value val = map.contents (key);
01356
01357 if (print_fieldnames_only)
01358 {
01359 indent (os);
01360 os << key;
01361 dim_vector dv = val.dims ();
01362 os << ": " << dv.str () << " " << val.type_name ();
01363 newline (os);
01364 }
01365 else
01366 val.print_with_name (os, key);
01367 }
01368
01369 decrement_indent_level ();
01370 decrement_indent_level ();
01371 }
01372 else
01373 {
01374 indent (os);
01375 os << "<structure>";
01376 newline (os);
01377 }
01378 }
01379
01380 bool
01381 octave_scalar_struct::print_name_tag (std::ostream& os, const std::string& name) const
01382 {
01383 bool retval = false;
01384
01385 indent (os);
01386
01387 if (Vstruct_levels_to_print < 0)
01388 os << name << " = ";
01389 else
01390 {
01391 os << name << " =";
01392 newline (os);
01393 retval = true;
01394 }
01395
01396 return retval;
01397 }
01398
01399 bool
01400 octave_scalar_struct::save_ascii (std::ostream& os)
01401 {
01402 octave_map m = map_value ();
01403
01404 octave_idx_type nf = m.nfields ();
01405
01406 const dim_vector dv = dims ();
01407
01408 os << "# ndims: " << dv.length () << "\n";
01409
01410 for (int i = 0; i < dv.length (); i++)
01411 os << " " << dv (i);
01412 os << "\n";
01413
01414 os << "# length: " << nf << "\n";
01415
01416
01417
01418 string_vector keys = m.fieldnames ();
01419
01420 for (octave_idx_type i = 0; i < nf; i++)
01421 {
01422 std::string key = keys(i);
01423
01424 octave_value val = map.contents (key);
01425
01426 bool b = save_ascii_data (os, val, key, false, 0);
01427
01428 if (! b)
01429 return os;
01430 }
01431
01432 return true;
01433 }
01434
01435 bool
01436 octave_scalar_struct::load_ascii (std::istream& is)
01437 {
01438 bool success = true;
01439 octave_idx_type len = 0;
01440
01441 if (extract_keyword (is, "length", len) && len >= 0)
01442 {
01443 if (len > 0)
01444 {
01445 octave_scalar_map m;
01446
01447 for (octave_idx_type j = 0; j < len; j++)
01448 {
01449 octave_value t2;
01450 bool dummy;
01451
01452
01453 std::string nm
01454 = read_ascii_data (is, std::string (), dummy, t2, j);
01455
01456 if (!is)
01457 break;
01458
01459 if (error_state)
01460 {
01461 error ("load: internal error loading struct elements");
01462 return false;
01463 }
01464
01465 m.setfield (nm, t2);
01466 }
01467
01468 if (is)
01469 map = m;
01470 else
01471 {
01472 error ("load: failed to load structure");
01473 success = false;
01474 }
01475 }
01476 else if (len == 0)
01477 map = octave_scalar_map ();
01478 else
01479 panic_impossible ();
01480 }
01481 else {
01482 error ("load: failed to extract number of elements in structure");
01483 success = false;
01484 }
01485
01486 return success;
01487 }
01488
01489 bool
01490 octave_scalar_struct::save_binary (std::ostream& os, bool& save_as_floats)
01491 {
01492 octave_map m = map_value ();
01493
01494 octave_idx_type nf = m.nfields ();
01495
01496 int32_t len = nf;
01497 os.write (reinterpret_cast<char *> (&len), 4);
01498
01499
01500
01501 string_vector keys = m.fieldnames ();
01502
01503 for (octave_idx_type i = 0; i < nf; i++)
01504 {
01505 std::string key = keys(i);
01506
01507 octave_value val = map.contents (key);
01508
01509 bool b = save_binary_data (os, val, key, "", 0, save_as_floats);
01510
01511 if (! b)
01512 return os;
01513 }
01514
01515 return true;
01516 }
01517
01518 bool
01519 octave_scalar_struct::load_binary (std::istream& is, bool swap,
01520 oct_mach_info::float_format fmt)
01521 {
01522 bool success = true;
01523 int32_t len;
01524 if (! is.read (reinterpret_cast<char *> (&len), 4))
01525 return false;
01526 if (swap)
01527 swap_bytes<4> (&len);
01528
01529 dim_vector dv (1, 1);
01530
01531 if (len > 0)
01532 {
01533 octave_scalar_map m;
01534
01535 for (octave_idx_type j = 0; j < len; j++)
01536 {
01537 octave_value t2;
01538 bool dummy;
01539 std::string doc;
01540
01541
01542 std::string nm = read_binary_data (is, swap, fmt, std::string (),
01543 dummy, t2, doc);
01544
01545 if (!is)
01546 break;
01547
01548 if (error_state)
01549 {
01550 error ("load: internal error loading struct elements");
01551 return false;
01552 }
01553
01554 m.setfield (nm, t2);
01555 }
01556
01557 if (is)
01558 map = m;
01559 else
01560 {
01561 error ("load: failed to load structure");
01562 success = false;
01563 }
01564 }
01565 else if (len == 0)
01566 map = octave_scalar_map ();
01567 else
01568 success = false;
01569
01570 return success;
01571 }
01572
01573 #if defined (HAVE_HDF5)
01574
01575 bool
01576 octave_scalar_struct::save_hdf5 (hid_t loc_id, const char *name, bool save_as_floats)
01577 {
01578 hid_t data_hid = -1;
01579
01580 #if HAVE_HDF5_18
01581 data_hid = H5Gcreate (loc_id, name, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
01582 #else
01583 data_hid = H5Gcreate (loc_id, name, 0);
01584 #endif
01585 if (data_hid < 0) return false;
01586
01587
01588 octave_scalar_map m = scalar_map_value ();
01589
01590 octave_idx_type nf = m.nfields ();
01591
01592
01593
01594 string_vector keys = m.fieldnames ();
01595
01596 for (octave_idx_type i = 0; i < nf; i++)
01597 {
01598 std::string key = keys(i);
01599
01600 octave_value val = map.contents (key);
01601
01602 bool retval2 = add_hdf5_data (data_hid, val, key, "", false,
01603 save_as_floats);
01604
01605 if (! retval2)
01606 break;
01607 }
01608
01609 H5Gclose (data_hid);
01610
01611 return true;
01612 }
01613
01614 bool
01615 octave_scalar_struct::load_hdf5 (hid_t loc_id, const char *name)
01616 {
01617 bool retval = false;
01618
01619 hdf5_callback_data dsub;
01620
01621 herr_t retval2 = 0;
01622 octave_scalar_map m;
01623 int current_item = 0;
01624 hsize_t num_obj = 0;
01625 #if HAVE_HDF5_18
01626 hid_t group_id = H5Gopen (loc_id, name, H5P_DEFAULT);
01627 #else
01628 hid_t group_id = H5Gopen (loc_id, name);
01629 #endif
01630 H5Gget_num_objs (group_id, &num_obj);
01631 H5Gclose (group_id);
01632
01633
01634
01635
01636 while (current_item < static_cast<int> (num_obj)
01637 && (retval2 = H5Giterate (loc_id, name, ¤t_item,
01638 hdf5_read_next_data, &dsub)) > 0)
01639 {
01640 octave_value t2 = dsub.tc;
01641
01642 if (error_state)
01643 {
01644 error ("load: internal error loading struct elements");
01645 return false;
01646 }
01647
01648 m.setfield (dsub.name, t2);
01649
01650 }
01651
01652 if (retval2 >= 0)
01653 {
01654 map = m;
01655 retval = true;
01656 }
01657
01658 return retval;
01659 }
01660
01661 #endif
01662
01663 mxArray *
01664 octave_scalar_struct::as_mxArray (void) const
01665 {
01666 int nf = nfields ();
01667 string_vector kv = map_keys ();
01668
01669 OCTAVE_LOCAL_BUFFER (const char *, f, nf);
01670
01671 for (int i = 0; i < nf; i++)
01672 f[i] = kv[i].c_str ();
01673
01674 mxArray *retval = new mxArray (dims (), nf, f);
01675
01676 mxArray **elts = static_cast<mxArray **> (retval->get_data ());
01677
01678 mwSize nel = numel ();
01679
01680 mwSize ntot = nf * nel;
01681
01682 for (int i = 0; i < nf; i++)
01683 {
01684 Cell c = map.contents (kv[i]);
01685
01686 const octave_value *p = c.data ();
01687
01688 mwIndex k = 0;
01689 for (mwIndex j = i; j < ntot; j += nf)
01690 elts[j] = new mxArray (p[k++]);
01691 }
01692
01693 return retval;
01694 }
01695
01696
01697 octave_value
01698 octave_scalar_struct::to_array (void)
01699 {
01700 return new octave_struct (octave_map (map));
01701 }
01702
01703 bool
01704 octave_scalar_struct::fast_elem_insert_self (void *where, builtin_type_t btyp) const
01705 {
01706
01707 if (btyp == btyp_struct)
01708 {
01709 *(reinterpret_cast<const octave_scalar_map **>(where)) = ↦
01710 return true;
01711 }
01712 else
01713 return false;
01714 }
01715
01716
01717
01718
01719
01720
01721
01722
01723
01724
01725
01726
01727
01728
01729
01730
01731
01732
01733
01734
01735 DEFUN (struct, args, ,
01736 "-*- texinfo -*-\n\
01737 @deftypefn {Built-in Function} {} struct (\"field\", @var{value}, \"field\", @var{value}, @dots{})\n\
01738 \n\
01739 Create a structure and initialize its value.\n\
01740 \n\
01741 If the values are cell arrays, create a structure array and initialize\n\
01742 its values. The dimensions of each cell array of values must match.\n\
01743 Singleton cells and non-cell values are repeated so that they fill\n\
01744 the entire array. If the cells are empty, create an empty structure\n\
01745 array with the specified field names.\n\
01746 \n\
01747 If the argument is an object, return the underlying struct.\n\
01748 @end deftypefn")
01749 {
01750 octave_value retval;
01751
01752 int nargin = args.length ();
01753
01754
01755
01756
01757
01758
01759
01760
01761
01762 if (nargin == 1 && args(0).is_map ())
01763 return args(0);
01764
01765 if (nargin == 1 && args(0).is_object ())
01766 {
01767 retval = args(0).map_value ();
01768
01769 return retval;
01770 }
01771
01772 if ((nargin == 1 || nargin == 2)
01773 && args(0).is_empty () && args(0).is_real_matrix ())
01774 {
01775 Cell fields;
01776
01777 if (nargin == 2)
01778 {
01779 if (args(1).is_cellstr ())
01780 retval = octave_map (args(0).dims (), args(1).cellstr_value ());
01781 else
01782 error ("struct: expecting cell array of field names as second argument");
01783 }
01784 else
01785 retval = octave_map (args(0).dims ());
01786
01787 return retval;
01788 }
01789
01790
01791
01792 for (int i = 0; i < nargin; i += 2)
01793 {
01794 if (! args(i).is_string () || i + 1 >= nargin)
01795 {
01796 error ("struct: expecting alternating \"field\", VALUE pairs");
01797 return retval;
01798 }
01799 }
01800
01801
01802
01803 dim_vector dims (1, 1);
01804
01805 int first_dimensioned_value = 0;
01806
01807 for (int i = 1; i < nargin; i += 2)
01808 {
01809 if (args(i).is_cell ())
01810 {
01811 dim_vector argdims (args(i).dims ());
01812
01813 if (! scalar (argdims))
01814 {
01815 if (! first_dimensioned_value)
01816 {
01817 dims = argdims;
01818 first_dimensioned_value = i + 1;
01819 }
01820 else if (dims != argdims)
01821 {
01822 error ("struct: dimensions of parameter %d do not match those of parameter %d",
01823 first_dimensioned_value, i+1);
01824 return retval;
01825 }
01826 }
01827 }
01828 }
01829
01830
01831
01832 octave_map map (dims);
01833
01834 for (int i = 0; i < nargin; i+= 2)
01835 {
01836
01837
01838 std::string key (args(i).string_value ());
01839
01840 if (error_state)
01841 return retval;
01842
01843 if (! valid_identifier (key))
01844 {
01845 error ("struct: invalid structure field name '%s'", key.c_str ());
01846 return retval;
01847 }
01848
01849
01850
01851
01852
01853
01854
01855 if (args(i+1).is_cell ())
01856 {
01857 const Cell c (args(i+1).cell_value ());
01858
01859 if (error_state)
01860 return retval;
01861
01862 if (scalar (c.dims ()))
01863 map.setfield (key, Cell (dims, c(0)));
01864 else
01865 map.setfield (key, c);
01866 }
01867 else
01868 map.setfield (key, Cell (dims, args(i+1)));
01869
01870 if (error_state)
01871 return retval;
01872 }
01873
01874 return octave_value (map);
01875 }
01876
01877 DEFUN (isstruct, args, ,
01878 "-*- texinfo -*-\n\
01879 @deftypefn {Built-in Function} {} isstruct (@var{x})\n\
01880 Return true if @var{x} is a structure or a structure array.\n\
01881 @seealso{ismatrix, iscell, isa}\n\
01882 @end deftypefn")
01883 {
01884 octave_value retval;
01885
01886 if (args.length () == 1)
01887 retval = args(0).is_map ();
01888 else
01889 print_usage ();
01890
01891 return retval;
01892 }
01893
01894 DEFUN (fieldnames, args, ,
01895 "-*- texinfo -*-\n\
01896 @deftypefn {Built-in Function} {} fieldnames (@var{struct})\n\
01897 Return a cell array of strings naming the elements of the structure\n\
01898 @var{struct}. It is an error to call @code{fieldnames} with an\n\
01899 argument that is not a structure.\n\
01900 @end deftypefn")
01901 {
01902 octave_value retval;
01903
01904 int nargin = args.length ();
01905
01906 if (nargin == 1)
01907 {
01908 octave_value arg = args(0);
01909
01910 if (arg.is_map () || arg.is_object ())
01911 {
01912 octave_map m = arg.map_value ();
01913
01914 string_vector keys = m.fieldnames ();
01915
01916 if (keys.length () == 0)
01917 retval = Cell (0, 1);
01918 else
01919 retval = Cell (keys);
01920 }
01921 else
01922 gripe_wrong_type_arg ("fieldnames", args(0));
01923 }
01924 else
01925 print_usage ();
01926
01927 return retval;
01928 }
01929
01930
01931
01932
01933
01934
01935
01936
01937 DEFUN (isfield, args, ,
01938 "-*- texinfo -*-\n\
01939 @deftypefn {Built-in Function} {} isfield (@var{x}, @var{name})\n\
01940 Return true if the @var{x} is a structure and it\n\
01941 includes an element named @var{name}. If @var{name} is a cell\n\
01942 array of strings then a logical array of equal dimension is returned.\n\
01943 @end deftypefn")
01944 {
01945 octave_value retval;
01946
01947 int nargin = args.length ();
01948
01949 if (nargin == 2)
01950 {
01951 retval = false;
01952
01953 if (args(0).is_map ())
01954 {
01955 octave_map m = args(0).map_value ();
01956
01957
01958
01959
01960 if (args(1).is_string ())
01961 {
01962 std::string key = args(1).string_value ();
01963
01964 retval = m.isfield (key);
01965 }
01966 else if (args(1).is_cell ())
01967 {
01968 Cell c = args(1).cell_value ();
01969 boolNDArray bm (c.dims ());
01970 octave_idx_type n = bm.numel ();
01971
01972 for (octave_idx_type i = 0; i < n; i++)
01973 {
01974 if (c(i).is_string ())
01975 {
01976 std::string key = c(i).string_value ();
01977
01978 bm(i) = m.isfield (key);
01979 }
01980 else
01981 bm(i) = false;
01982 }
01983
01984 retval = bm;
01985 }
01986 }
01987 }
01988 else
01989 print_usage ();
01990
01991 return retval;
01992 }
01993
01994 DEFUN (nfields, args, ,
01995 "-*- texinfo -*-\n\
01996 @deftypefn {Built-in Function} {} nfields (@var{s})\n\
01997 Return the number of fields of the structure @var{s}.\n\
01998 @end deftypefn")
01999 {
02000 octave_value retval;
02001
02002 int nargin = args.length ();
02003
02004 if (nargin == 1 && args(0).is_map ())
02005 {
02006 retval = static_cast<double> (args(0).nfields ());
02007 }
02008 else
02009 print_usage ();
02010
02011 return retval;
02012 }
02013
02014
02015
02016
02017
02018
02019
02020
02021
02022
02023
02024
02025
02026 DEFUN (cell2struct, args, ,
02027 "-*- texinfo -*-\n\
02028 @deftypefn {Built-in Function} {} cell2struct (@var{cell}, @var{fields}, @var{dim})\n\
02029 Convert @var{cell} to a structure. The number of fields in @var{fields}\n\
02030 must match the number of elements in @var{cell} along dimension @var{dim},\n\
02031 that is @code{numel (@var{fields}) == size (@var{cell}, @var{dim})}.\n\
02032 If @var{dim} is omitted, a value of 1 is assumed.\n\
02033 \n\
02034 @example\n\
02035 @group\n\
02036 A = cell2struct (@{'Peter', 'Hannah', 'Robert';\n\
02037 185, 170, 168@},\n\
02038 @{'Name','Height'@}, 1);\n\
02039 A(1)\n\
02040 @result{} ans =\n\
02041 @{\n\
02042 Name = Peter\n\
02043 Height = 185\n\
02044 @}\n\
02045 \n\
02046 @end group\n\
02047 @end example\n\
02048 @end deftypefn")
02049 {
02050 octave_value retval;
02051
02052 int nargin = args.length ();
02053
02054 if (nargin == 2 || nargin == 3)
02055 {
02056 if (! args(0).is_cell ())
02057 {
02058 error ("cell2struct: argument CELL must be of type cell");
02059 return retval;
02060 }
02061
02062 if (! (args(1).is_cellstr () || args(1).is_char_matrix ()))
02063 {
02064 error ("cell2struct: FIELDS must be a cell array of strings or a character matrix");
02065 return retval;
02066 }
02067
02068 const Cell vals = args(0).cell_value ();
02069 const Array<std::string> fields = args(1).cellstr_value ();
02070
02071 octave_idx_type ext = 0;
02072
02073 int dim = 0;
02074
02075 if (nargin == 3)
02076 {
02077 if (args(2).is_real_scalar ())
02078 {
02079 dim = nargin == 2 ? 0 : args(2).int_value () - 1;
02080
02081 if (error_state)
02082 return retval;
02083 }
02084 else
02085 {
02086 error ("cell2struct: DIM must be a real scalar");
02087 return retval;
02088 }
02089 }
02090
02091 if (dim < 0)
02092 {
02093 error ("cell2struct: DIM must be a valid dimension");
02094 return retval;
02095 }
02096
02097 ext = vals.ndims () > dim ? vals.dims ()(dim) : 1;
02098
02099 if (ext != fields.numel ())
02100 {
02101 error ("cell2struct: number of FIELDS does not match dimension");
02102 return retval;
02103 }
02104
02105 int nd = std::max (dim+1, vals.ndims ());
02106
02107 dim_vector rdv = vals.dims ().redim (nd);
02108
02109 assert (ext == rdv(dim));
02110 if (nd == 2)
02111 {
02112 rdv(0) = rdv(1-dim);
02113 rdv(1) = 1;
02114 }
02115 else
02116 {
02117 for (int i = dim + 1; i < nd; i++)
02118 rdv(i-1) = rdv(i);
02119
02120 rdv.resize (nd-1);
02121 }
02122
02123 octave_map map (rdv);
02124 Array<idx_vector> ia (dim_vector (nd, 1), idx_vector::colon);
02125
02126 for (octave_idx_type i = 0; i < ext; i++)
02127 {
02128 ia(dim) = i;
02129 map.setfield (fields(i), vals.index (ia).reshape (rdv));
02130 }
02131
02132 retval = map;
02133 }
02134 else
02135 print_usage ();
02136
02137 return retval;
02138 }
02139
02140
02141
02142
02143
02144
02145
02146
02147
02148
02149
02150
02151
02152
02153
02154
02155
02156
02157
02158 extern octave_value_list Fcellstr (const octave_value_list& args, int);
02159
02160 DEFUN (rmfield, args, ,
02161 "-*- texinfo -*-\n\
02162 @deftypefn {Built-in Function} {} rmfield (@var{s}, @var{f})\n\
02163 Return a copy of the structure (array) @var{s} with the field @var{f}\n\
02164 removed. If @var{f} is a cell array of strings or a character array, remove\n\
02165 the named fields.\n\
02166 @seealso{cellstr, iscellstr, setfield}\n\
02167 @end deftypefn")
02168 {
02169 octave_value retval;
02170
02171 int nargin = args.length ();
02172
02173 if (nargin == 2)
02174 {
02175 octave_map m = args(0).map_value ();
02176
02177 octave_value_list fval = Fcellstr (args(1), 1);
02178
02179 if (! error_state)
02180 {
02181 Cell fcell = fval(0).cell_value ();
02182
02183 for (int i = 0; i < fcell.numel (); i++)
02184 {
02185 std::string key = fcell(i).string_value ();
02186
02187 if (m.isfield (key))
02188 m.rmfield (key);
02189 else
02190 {
02191 error ("rmfield: structure does not contain field %s",
02192 key.c_str ());
02193
02194 break;
02195 }
02196 }
02197
02198 if (! error_state)
02199 retval = m;
02200 }
02201 }
02202 else
02203 print_usage ();
02204
02205 return retval;
02206 }
02207
02208
02209
02210
02211
02212
02213
02214
02215
02216
02217 DEFUN (struct_levels_to_print, args, nargout,
02218 "-*- texinfo -*-\n\
02219 @deftypefn {Built-in Function} {@var{val} =} struct_levels_to_print ()\n\
02220 @deftypefnx {Built-in Function} {@var{old_val} =} struct_levels_to_print (@var{new_val})\n\
02221 @deftypefnx {Built-in Function} {} struct_levels_to_print (@var{new_val}, \"local\")\n\
02222 Query or set the internal variable that specifies the number of\n\
02223 structure levels to display.\n\
02224 \n\
02225 When called from inside a function with the \"local\" option, the variable is\n\
02226 changed locally for the function and any subroutines it calls. The original\n\
02227 variable value is restored when exiting the function.\n\
02228 @end deftypefn")
02229 {
02230 return SET_INTERNAL_VARIABLE_WITH_LIMITS (struct_levels_to_print,
02231 -1, INT_MAX);
02232 }
02233
02234 DEFUN (print_struct_array_contents, args, nargout,
02235 "-*- texinfo -*-\n\
02236 @deftypefn {Built-in Function} {@var{val} =} print_struct_array_contents ()\n\
02237 @deftypefnx {Built-in Function} {@var{old_val} =} print_struct_array_contents (@var{new_val})\n\
02238 @deftypefnx {Built-in Function} {} print_struct_array_contents (@var{new_val}, \"local\")\n\
02239 Query or set the internal variable that specifies whether to print struct\n\
02240 array contents. If true, values of struct array elements are printed.\n\
02241 This variable does not affect scalar structures. Their elements\n\
02242 are always printed. In both cases, however, printing will be limited to\n\
02243 the number of levels specified by @var{struct_levels_to_print}.\n\
02244 \n\
02245 When called from inside a function with the \"local\" option, the variable is\n\
02246 changed locally for the function and any subroutines it calls. The original\n\
02247 variable value is restored when exiting the function.\n\
02248 @end deftypefn")
02249 {
02250 return SET_INTERNAL_VARIABLE (print_struct_array_contents);
02251 }