00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #ifdef HAVE_CONFIG_H
00025 #include <config.h>
00026 #endif
00027
00028 #include <iomanip>
00029 #include <iostream>
00030 #include <sstream>
00031 #include <vector>
00032 #include <queue>
00033
00034 #include "Array-util.h"
00035 #include "byte-swap.h"
00036 #include "lo-utils.h"
00037 #include "quit.h"
00038 #include "oct-locbuf.h"
00039
00040 #include "defun.h"
00041 #include "error.h"
00042 #include "ov-cell.h"
00043 #include "oct-obj.h"
00044 #include "unwind-prot.h"
00045 #include "utils.h"
00046 #include "ov-base-mat.h"
00047 #include "ov-base-mat.cc"
00048 #include "ov-re-mat.h"
00049 #include "ov-scalar.h"
00050 #include "pr-output.h"
00051 #include "ov-scalar.h"
00052 #include "gripes.h"
00053
00054 #include "ls-oct-ascii.h"
00055 #include "ls-oct-binary.h"
00056 #include "ls-hdf5.h"
00057 #include "ls-utils.h"
00058
00059
00060
00061
00062 template <>
00063 octave_value
00064 octave_base_matrix<Cell>::do_index_op (const octave_value_list& idx,
00065 bool resize_ok)
00066 {
00067 return matrix.index (idx, resize_ok);
00068 }
00069
00070 template <>
00071 void
00072 octave_base_matrix<Cell>::assign (const octave_value_list& idx, const Cell& rhs)
00073 {
00074 matrix.assign (idx, rhs);
00075 }
00076
00077 template <>
00078 void
00079 octave_base_matrix<Cell>::assign (const octave_value_list& idx, octave_value rhs)
00080 {
00081
00082 if (rhs.is_cell ())
00083 matrix.assign (idx, rhs.cell_value ());
00084 else
00085 matrix.assign (idx, Cell (rhs));
00086 }
00087
00088 template <>
00089 void
00090 octave_base_matrix<Cell>::delete_elements (const octave_value_list& idx)
00091 {
00092 matrix.delete_elements (idx);
00093 }
00094
00095
00096
00097
00098 template <>
00099 octave_value
00100 octave_base_matrix<Cell>::fast_elem_extract (octave_idx_type n) const
00101 {
00102 if (n < matrix.numel ())
00103 return Cell (matrix(n));
00104 else
00105 return octave_value ();
00106 }
00107
00108 template <>
00109 bool
00110 octave_base_matrix<Cell>::fast_elem_insert (octave_idx_type n,
00111 const octave_value& x)
00112 {
00113 const octave_cell *xrep =
00114 dynamic_cast<const octave_cell *> (&x.get_rep ());
00115
00116 bool retval = xrep && xrep->matrix.numel () == 1 && n < matrix.numel ();
00117 if (retval)
00118 matrix(n) = xrep->matrix(0);
00119
00120 return retval;
00121 }
00122
00123 template class octave_base_matrix<Cell>;
00124
00125 DEFINE_OCTAVE_ALLOCATOR (octave_cell);
00126
00127 DEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (octave_cell, "cell", "cell");
00128
00129 static void
00130 gripe_failed_assignment (void)
00131 {
00132 error ("assignment to cell array failed");
00133 }
00134
00135 octave_value_list
00136 octave_cell::subsref (const std::string& type,
00137 const std::list<octave_value_list>& idx,
00138 int nargout)
00139 {
00140 octave_value_list retval;
00141
00142 switch (type[0])
00143 {
00144 case '(':
00145 retval(0) = do_index_op (idx.front ());
00146 break;
00147
00148 case '{':
00149 {
00150 octave_value tmp = do_index_op (idx.front ());
00151
00152 if (! error_state)
00153 {
00154 Cell tcell = tmp.cell_value ();
00155
00156 if (tcell.length () == 1)
00157 retval(0) = tcell(0,0);
00158 else
00159 retval = octave_value (octave_value_list (tcell), true);
00160 }
00161 }
00162 break;
00163
00164 case '.':
00165 {
00166 std::string nm = type_name ();
00167 error ("%s cannot be indexed with %c", nm.c_str (), type[0]);
00168 }
00169 break;
00170
00171 default:
00172 panic_impossible ();
00173 }
00174
00175
00176
00177
00178
00179 if (idx.size () > 1)
00180 retval = retval(0).next_subsref (nargout, type, idx);
00181
00182 return retval;
00183 }
00184
00185 octave_value
00186 octave_cell::subsref (const std::string& type,
00187 const std::list<octave_value_list>& idx,
00188 bool auto_add)
00189 {
00190 octave_value retval;
00191
00192 switch (type[0])
00193 {
00194 case '(':
00195 retval = do_index_op (idx.front (), auto_add);
00196 break;
00197
00198 case '{':
00199 {
00200 octave_value tmp = do_index_op (idx.front (), auto_add);
00201
00202 if (! error_state)
00203 {
00204 const Cell tcell = tmp.cell_value ();
00205
00206 if (tcell.length () == 1)
00207 retval = tcell(0,0);
00208 else
00209 retval = octave_value (octave_value_list (tcell), true);
00210 }
00211 }
00212 break;
00213
00214 case '.':
00215 {
00216 std::string nm = type_name ();
00217 error ("%s cannot be indexed with %c", nm.c_str (), type[0]);
00218 }
00219 break;
00220
00221 default:
00222 panic_impossible ();
00223 }
00224
00225
00226
00227
00228
00229 if (idx.size () > 1)
00230 retval = retval.next_subsref (auto_add, type, idx);
00231
00232 return retval;
00233 }
00234
00235 octave_value
00236 octave_cell::subsasgn (const std::string& type,
00237 const std::list<octave_value_list>& idx,
00238 const octave_value& rhs)
00239 {
00240 octave_value retval;
00241
00242 int n = type.length ();
00243
00244 octave_value t_rhs = rhs;
00245
00246 clear_cellstr_cache ();
00247
00248 if (idx.front ().empty ())
00249 {
00250 error ("missing index in indexed assignment");
00251 return retval;
00252 }
00253
00254 if (n > 1)
00255 {
00256 switch (type[0])
00257 {
00258 case '(':
00259 {
00260 if (is_empty () && type[1] == '.')
00261 {
00262
00263
00264
00265
00266
00267 octave_value tmp = octave_value::empty_conv (type, rhs);
00268
00269 return tmp.subsasgn (type, idx, rhs);
00270 }
00271 else
00272 {
00273 octave_value tmp = do_index_op (idx.front (), true);
00274
00275 if (! tmp.is_defined ())
00276 tmp = octave_value::empty_conv (type.substr (1), rhs);
00277
00278 if (! error_state)
00279 {
00280 std::list<octave_value_list> next_idx (idx);
00281
00282 next_idx.erase (next_idx.begin ());
00283
00284 tmp.make_unique ();
00285
00286 t_rhs = tmp.subsasgn (type.substr (1), next_idx, rhs);
00287 }
00288 }
00289 }
00290 break;
00291
00292 case '{':
00293 {
00294 matrix.make_unique ();
00295 Cell tmpc = matrix.index (idx.front (), true);
00296
00297 if (! error_state)
00298 {
00299 std::list<octave_value_list> next_idx (idx);
00300
00301 next_idx.erase (next_idx.begin ());
00302
00303 std::string next_type = type.substr (1);
00304
00305 if (tmpc.numel () == 1)
00306 {
00307 octave_value tmp = tmpc(0);
00308 tmpc = Cell ();
00309
00310 if (! tmp.is_defined () || tmp.is_zero_by_zero ())
00311 {
00312 tmp = octave_value::empty_conv (type.substr (1), rhs);
00313 tmp.make_unique ();
00314 }
00315 else
00316
00317 tmp.make_unique (1);
00318
00319 if (! error_state)
00320 t_rhs = tmp.subsasgn (next_type, next_idx, rhs);
00321 }
00322 else
00323 gripe_indexed_cs_list ();
00324 }
00325 }
00326 break;
00327
00328 case '.':
00329 {
00330 if (is_empty ())
00331 {
00332
00333 }
00334 else
00335 {
00336 std::string nm = type_name ();
00337 error ("%s cannot be indexed with %c", nm.c_str (), type[0]);
00338 }
00339 }
00340 break;
00341
00342 default:
00343 panic_impossible ();
00344 }
00345 }
00346
00347 if (! error_state)
00348 {
00349 switch (type[0])
00350 {
00351 case '(':
00352 {
00353 octave_value_list i = idx.front ();
00354
00355 if (t_rhs.is_cell ())
00356 octave_base_matrix<Cell>::assign (i, t_rhs.cell_value ());
00357 else
00358 if (t_rhs.is_null_value ())
00359 octave_base_matrix<Cell>::delete_elements (i);
00360 else
00361 octave_base_matrix<Cell>::assign (i, Cell (t_rhs));
00362
00363 if (! error_state)
00364 {
00365 count++;
00366 retval = octave_value (this);
00367 }
00368 else
00369 gripe_failed_assignment ();
00370 }
00371 break;
00372
00373 case '{':
00374 {
00375 octave_value_list idxf = idx.front ();
00376
00377 if (t_rhs.is_cs_list ())
00378 {
00379 Cell tmp_cell = Cell (t_rhs.list_value ());
00380
00381
00382
00383 dim_vector didx = dims ().redim (idxf.length ());
00384 for (octave_idx_type k = 0; k < idxf.length (); k++)
00385 if (! idxf(k).is_magic_colon ()) didx(k) = idxf(k).numel ();
00386
00387 if (didx.numel () == tmp_cell.numel ())
00388 tmp_cell = tmp_cell.reshape (didx);
00389
00390
00391 octave_base_matrix<Cell>::assign (idxf, tmp_cell);
00392 }
00393 else if (idxf.all_scalars () || do_index_op (idxf, true).numel () == 1)
00394
00395 octave_base_matrix<Cell>::assign (idxf, Cell (t_rhs.storable_value ()));
00396 else if (! error_state)
00397 gripe_nonbraced_cs_list_assignment ();
00398
00399 if (! error_state)
00400 {
00401 count++;
00402 retval = octave_value (this);
00403 }
00404 else
00405 gripe_failed_assignment ();
00406 }
00407 break;
00408
00409 case '.':
00410 {
00411 if (is_empty ())
00412 {
00413
00414
00415
00416
00417
00418 octave_value tmp = octave_value::empty_conv (type, rhs);
00419
00420 return tmp.subsasgn (type, idx, rhs);
00421 }
00422 else
00423 {
00424 std::string nm = type_name ();
00425 error ("%s cannot be indexed with %c", nm.c_str (), type[0]);
00426 }
00427 }
00428 break;
00429
00430 default:
00431 panic_impossible ();
00432 }
00433 }
00434
00435 return retval;
00436 }
00437
00438 bool
00439 octave_cell::is_cellstr (void) const
00440 {
00441 bool retval;
00442 if (cellstr_cache.get ())
00443 retval = true;
00444 else
00445 {
00446 retval = matrix.is_cellstr ();
00447
00448 if (retval)
00449 cellstr_cache.reset (new Array<std::string> ());
00450 }
00451
00452 return retval;
00453 }
00454
00455 void
00456 octave_cell::assign (const octave_value_list& idx, const Cell& rhs)
00457 {
00458 clear_cellstr_cache ();
00459 octave_base_matrix<Cell>::assign (idx, rhs);
00460 }
00461
00462 void
00463 octave_cell::assign (const octave_value_list& idx, const octave_value& rhs)
00464 {
00465 clear_cellstr_cache ();
00466 octave_base_matrix<Cell>::assign (idx, rhs);
00467 }
00468
00469
00470 void
00471 octave_cell::delete_elements (const octave_value_list& idx)
00472 {
00473 clear_cellstr_cache ();
00474 octave_base_matrix<Cell>::delete_elements (idx);
00475 }
00476
00477 size_t
00478 octave_cell::byte_size (void) const
00479 {
00480 size_t retval = 0;
00481
00482 for (octave_idx_type i = 0; i < numel (); i++)
00483 retval += matrix(i).byte_size ();
00484
00485 return retval;
00486 }
00487
00488 octave_value
00489 octave_cell::sort (octave_idx_type dim, sortmode mode) const
00490 {
00491 octave_value retval;
00492
00493 if (is_cellstr ())
00494 {
00495 Array<std::string> tmp = cellstr_value ();
00496
00497 tmp = tmp.sort (dim, mode);
00498
00499
00500 retval = new octave_cell (tmp);
00501 }
00502 else
00503 error ("sort: only cell arrays of character strings may be sorted");
00504
00505 return retval;
00506 }
00507
00508 octave_value
00509 octave_cell::sort (Array<octave_idx_type> &sidx, octave_idx_type dim,
00510 sortmode mode) const
00511 {
00512 octave_value retval;
00513
00514 if (is_cellstr ())
00515 {
00516 Array<std::string> tmp = cellstr_value ();
00517
00518 tmp = tmp.sort (sidx, dim, mode);
00519
00520
00521 retval = new octave_cell (tmp);
00522 }
00523 else
00524 error ("sort: only cell arrays of character strings may be sorted");
00525
00526 return retval;
00527 }
00528
00529 sortmode
00530 octave_cell::is_sorted (sortmode mode) const
00531 {
00532 sortmode retval = UNSORTED;
00533
00534 if (is_cellstr ())
00535 {
00536 Array<std::string> tmp = cellstr_value ();
00537
00538 retval = tmp.is_sorted (mode);
00539 }
00540 else
00541 error ("issorted: A is not a cell array of strings");
00542
00543 return retval;
00544 }
00545
00546
00547 Array<octave_idx_type>
00548 octave_cell::sort_rows_idx (sortmode mode) const
00549 {
00550 Array<octave_idx_type> retval;
00551
00552 if (is_cellstr ())
00553 {
00554 Array<std::string> tmp = cellstr_value ();
00555
00556 retval = tmp.sort_rows_idx (mode);
00557 }
00558 else
00559 error ("sortrows: only cell arrays of character strings may be sorted");
00560
00561 return retval;
00562 }
00563
00564 sortmode
00565 octave_cell::is_sorted_rows (sortmode mode) const
00566 {
00567 sortmode retval = UNSORTED;
00568
00569 if (is_cellstr ())
00570 {
00571 Array<std::string> tmp = cellstr_value ();
00572
00573 retval = tmp.is_sorted_rows (mode);
00574 }
00575 else
00576 error ("issorted: A is not a cell array of strings");
00577
00578 return retval;
00579 }
00580
00581 bool
00582 octave_cell::is_true (void) const
00583 {
00584 error ("invalid conversion from cell array to logical value");
00585 return false;
00586 }
00587
00588 octave_value_list
00589 octave_cell::list_value (void) const
00590 {
00591 return octave_value_list (matrix);
00592 }
00593
00594 string_vector
00595 octave_cell::all_strings (bool pad) const
00596 {
00597 string_vector retval;
00598
00599 octave_idx_type nel = numel ();
00600
00601 int n_elts = 0;
00602
00603 octave_idx_type max_len = 0;
00604
00605 std::queue<string_vector> strvec_queue;
00606
00607 for (octave_idx_type i = 0; i < nel; i++)
00608 {
00609 string_vector s = matrix(i).all_strings ();
00610
00611 if (error_state)
00612 return retval;
00613
00614 octave_idx_type s_len = s.length ();
00615
00616 n_elts += s_len ? s_len : 1;
00617
00618 octave_idx_type s_max_len = s.max_length ();
00619
00620 if (s_max_len > max_len)
00621 max_len = s_max_len;
00622
00623 strvec_queue.push (s);
00624 }
00625
00626 retval = string_vector (n_elts);
00627
00628 octave_idx_type k = 0;
00629
00630 for (octave_idx_type i = 0; i < nel; i++)
00631 {
00632 const string_vector s = strvec_queue.front ();
00633 strvec_queue.pop ();
00634
00635 octave_idx_type s_len = s.length ();
00636
00637 if (s_len)
00638 {
00639 for (octave_idx_type j = 0; j < s_len; j++)
00640 {
00641 std::string t = s[j];
00642 int t_len = t.length ();
00643
00644 if (pad && max_len > t_len)
00645 t += std::string (max_len - t_len, ' ');
00646
00647 retval[k++] = t;
00648 }
00649 }
00650 else if (pad)
00651 retval[k++] = std::string (max_len, ' ');
00652 else
00653 retval[k++] = std::string ();
00654 }
00655
00656 return retval;
00657 }
00658
00659 Array<std::string>
00660 octave_cell::cellstr_value (void) const
00661 {
00662 Array<std::string> retval;
00663
00664 if (is_cellstr ())
00665 {
00666 if (cellstr_cache->is_empty ())
00667 *cellstr_cache = matrix.cellstr_value ();
00668
00669 return *cellstr_cache;
00670 }
00671 else
00672 error ("invalid conversion from cell array to array of strings");
00673
00674 return retval;
00675 }
00676
00677 bool
00678 octave_cell::print_as_scalar (void) const
00679 {
00680 return true;
00681 }
00682
00683 void
00684 octave_cell::print (std::ostream& os, bool) const
00685 {
00686 print_raw (os);
00687 }
00688
00689 void
00690 octave_cell::print_raw (std::ostream& os, bool) const
00691 {
00692 int nd = matrix.ndims ();
00693
00694 if (nd == 2)
00695 {
00696 octave_idx_type nr = rows ();
00697 octave_idx_type nc = columns ();
00698
00699 if (nr > 0 && nc > 0)
00700 {
00701 newline (os);
00702 indent (os);
00703 os << "{";
00704 newline (os);
00705
00706 increment_indent_level ();
00707
00708 for (octave_idx_type j = 0; j < nc; j++)
00709 {
00710 for (octave_idx_type i = 0; i < nr; i++)
00711 {
00712 octave_quit ();
00713
00714 std::ostringstream buf;
00715 buf << "[" << i+1 << "," << j+1 << "]";
00716
00717 octave_value val = matrix(i,j);
00718
00719 val.print_with_name (os, buf.str ());
00720 }
00721 }
00722
00723 decrement_indent_level ();
00724
00725 indent (os);
00726 os << "}";
00727 newline (os);
00728 }
00729 else
00730 {
00731 indent (os);
00732 os << "{}";
00733 if (Vprint_empty_dimensions)
00734 os << "(" << nr << "x" << nc << ")";
00735 newline (os);
00736 }
00737 }
00738 else
00739 {
00740 indent (os);
00741 dim_vector dv = matrix.dims ();
00742 os << "{" << dv.str () << " Cell Array}";
00743 newline (os);
00744 }
00745 }
00746
00747 #define CELL_ELT_TAG "<cell-element>"
00748
00749 bool
00750 octave_cell::save_ascii (std::ostream& os)
00751 {
00752 dim_vector d = dims ();
00753 if (d.length () > 2)
00754 {
00755 os << "# ndims: " << d.length () << "\n";
00756
00757 for (int i = 0; i < d.length (); i++)
00758 os << " " << d (i);
00759 os << "\n";
00760
00761 Cell tmp = cell_value ();
00762
00763 for (octave_idx_type i = 0; i < d.numel (); i++)
00764 {
00765 octave_value o_val = tmp.elem (i);
00766
00767
00768 bool b = save_ascii_data (os, o_val, CELL_ELT_TAG, false, 0);
00769
00770 if (! b)
00771 return os;
00772 }
00773 }
00774 else
00775 {
00776
00777
00778 os << "# rows: " << rows () << "\n"
00779 << "# columns: " << columns () << "\n";
00780
00781 Cell tmp = cell_value ();
00782
00783 for (octave_idx_type j = 0; j < tmp.cols (); j++)
00784 {
00785 for (octave_idx_type i = 0; i < tmp.rows (); i++)
00786 {
00787 octave_value o_val = tmp.elem (i, j);
00788
00789
00790 bool b = save_ascii_data (os, o_val, CELL_ELT_TAG, false, 0);
00791
00792 if (! b)
00793 return os;
00794 }
00795
00796 os << "\n";
00797 }
00798 }
00799
00800 return true;
00801 }
00802
00803 bool
00804 octave_cell::load_ascii (std::istream& is)
00805 {
00806 bool success = true;
00807
00808 clear_cellstr_cache ();
00809
00810 string_vector keywords(2);
00811
00812 keywords[0] = "ndims";
00813 keywords[1] = "rows";
00814
00815 std::string kw;
00816 octave_idx_type val = 0;
00817
00818 if (extract_keyword (is, keywords, kw, val, true))
00819 {
00820 if (kw == "ndims")
00821 {
00822 int mdims = static_cast<int> (val);
00823
00824 if (mdims >= 0)
00825 {
00826 dim_vector dv;
00827 dv.resize (mdims);
00828
00829 for (int i = 0; i < mdims; i++)
00830 is >> dv(i);
00831
00832 Cell tmp(dv);
00833
00834 for (octave_idx_type i = 0; i < dv.numel (); i++)
00835 {
00836 octave_value t2;
00837 bool dummy;
00838
00839
00840 std::string nm = read_ascii_data (is, std::string (),
00841 dummy, t2, i);
00842
00843 if (nm == CELL_ELT_TAG)
00844 {
00845 if (is)
00846 tmp.elem (i) = t2;
00847 }
00848 else
00849 {
00850 error ("load: cell array element had unexpected name");
00851 success = false;
00852 break;
00853 }
00854 }
00855
00856 if (is)
00857 matrix = tmp;
00858 else
00859 {
00860 error ("load: failed to load matrix constant");
00861 success = false;
00862 }
00863 }
00864 else
00865 {
00866 error ("load: failed to extract number of rows and columns");
00867 success = false;
00868 }
00869 }
00870 else if (kw == "rows")
00871 {
00872 octave_idx_type nr = val;
00873 octave_idx_type nc = 0;
00874
00875 if (nr >= 0 && extract_keyword (is, "columns", nc) && nc >= 0)
00876 {
00877 if (nr > 0 && nc > 0)
00878 {
00879 Cell tmp (nr, nc);
00880
00881 for (octave_idx_type j = 0; j < nc; j++)
00882 {
00883 for (octave_idx_type i = 0; i < nr; i++)
00884 {
00885 octave_value t2;
00886 bool dummy;
00887
00888
00889 std::string nm = read_ascii_data (is, std::string (),
00890 dummy, t2, i);
00891
00892 if (nm == CELL_ELT_TAG)
00893 {
00894 if (is)
00895 tmp.elem (i, j) = t2;
00896 }
00897 else
00898 {
00899 error ("load: cell array element had unexpected name");
00900 success = false;
00901 goto cell_read_error;
00902 }
00903 }
00904 }
00905
00906 cell_read_error:
00907
00908 if (is)
00909 matrix = tmp;
00910 else
00911 {
00912 error ("load: failed to load cell element");
00913 success = false;
00914 }
00915 }
00916 else if (nr == 0 || nc == 0)
00917 matrix = Cell (nr, nc);
00918 else
00919 panic_impossible ();
00920 }
00921 else
00922 {
00923 error ("load: failed to extract number of rows and columns for cell array");
00924 success = false;
00925 }
00926 }
00927 else
00928 panic_impossible ();
00929 }
00930 else
00931 {
00932 error ("load: failed to extract number of rows and columns");
00933 success = false;
00934 }
00935
00936 return success;
00937 }
00938
00939 bool
00940 octave_cell::save_binary (std::ostream& os, bool& save_as_floats)
00941 {
00942 dim_vector d = dims ();
00943 if (d.length () < 1)
00944 return false;
00945
00946
00947 int32_t di = - d.length();
00948 os.write (reinterpret_cast<char *> (&di), 4);
00949 for (int i = 0; i < d.length (); i++)
00950 {
00951 di = d(i);
00952 os.write (reinterpret_cast<char *> (&di), 4);
00953 }
00954
00955 Cell tmp = cell_value ();
00956
00957 for (octave_idx_type i = 0; i < d.numel (); i++)
00958 {
00959 octave_value o_val = tmp.elem (i);
00960
00961
00962 bool b = save_binary_data (os, o_val, CELL_ELT_TAG, "", 0,
00963 save_as_floats);
00964
00965 if (! b)
00966 return false;
00967 }
00968
00969 return true;
00970 }
00971
00972 bool
00973 octave_cell::load_binary (std::istream& is, bool swap,
00974 oct_mach_info::float_format fmt)
00975 {
00976 clear_cellstr_cache ();
00977
00978 bool success = true;
00979 int32_t mdims;
00980 if (! is.read (reinterpret_cast<char *> (&mdims), 4))
00981 return false;
00982 if (swap)
00983 swap_bytes<4> (&mdims);
00984 if (mdims >= 0)
00985 return false;
00986
00987 mdims = -mdims;
00988 int32_t di;
00989 dim_vector dv;
00990 dv.resize (mdims);
00991
00992 for (int i = 0; i < mdims; i++)
00993 {
00994 if (! is.read (reinterpret_cast<char *> (&di), 4))
00995 return false;
00996 if (swap)
00997 swap_bytes<4> (&di);
00998 dv(i) = di;
00999 }
01000
01001
01002
01003
01004
01005 if (mdims == 1)
01006 {
01007 mdims = 2;
01008 dv.resize (mdims);
01009 dv(1) = dv(0);
01010 dv(0) = 1;
01011 }
01012
01013 octave_idx_type nel = dv.numel ();
01014 Cell tmp(dv);
01015
01016 for (octave_idx_type i = 0; i < nel; i++)
01017 {
01018 octave_value t2;
01019 bool dummy;
01020 std::string doc;
01021
01022
01023 std::string nm = read_binary_data (is, swap, fmt, std::string (),
01024 dummy, t2, doc);
01025
01026 if (nm == CELL_ELT_TAG)
01027 {
01028 if (is)
01029 tmp.elem (i) = t2;
01030 }
01031 else
01032 {
01033 error ("load: cell array element had unexpected name");
01034 success = false;
01035 break;
01036 }
01037 }
01038
01039 if (is)
01040 matrix = tmp;
01041 else
01042 {
01043 error ("load: failed to load matrix constant");
01044 success = false;
01045 }
01046
01047 return success;
01048 }
01049
01050 void *
01051 octave_cell::mex_get_data (void) const
01052 {
01053 clear_cellstr_cache ();
01054 return matrix.mex_get_data ();
01055 }
01056
01057 #if defined (HAVE_HDF5)
01058
01059 bool
01060 octave_cell::save_hdf5 (hid_t loc_id, const char *name, bool save_as_floats)
01061 {
01062 dim_vector dv = dims ();
01063 int empty = save_hdf5_empty (loc_id, name, dv);
01064 if (empty)
01065 return (empty > 0);
01066
01067 hsize_t rank = dv.length ();
01068 hid_t space_hid = -1, data_hid = -1, size_hid = -1;
01069
01070 #if HAVE_HDF5_18
01071 data_hid = H5Gcreate (loc_id, name, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
01072 #else
01073 data_hid = H5Gcreate (loc_id, name, 0);
01074 #endif
01075
01076 if (data_hid < 0)
01077 return false;
01078
01079
01080
01081
01082 space_hid = H5Screate_simple (1, &rank, 0);
01083
01084 if (space_hid < 0)
01085 {
01086 H5Gclose (data_hid);
01087 return false;
01088 }
01089
01090 OCTAVE_LOCAL_BUFFER (octave_idx_type, hdims, rank);
01091
01092
01093 for (hsize_t i = 0; i < rank; i++)
01094 hdims[i] = dv(rank-i-1);
01095
01096 #if HAVE_HDF5_18
01097 size_hid = H5Dcreate (data_hid, "dims", H5T_NATIVE_IDX, space_hid,
01098 H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
01099 #else
01100 size_hid = H5Dcreate (data_hid, "dims", H5T_NATIVE_IDX, space_hid,
01101 H5P_DEFAULT);
01102 #endif
01103 if (size_hid < 0)
01104 {
01105 H5Sclose (space_hid);
01106 H5Gclose (data_hid);
01107 return false;
01108 }
01109
01110 if (H5Dwrite (size_hid, H5T_NATIVE_IDX, H5S_ALL, H5S_ALL,
01111 H5P_DEFAULT, hdims) < 0)
01112 {
01113 H5Dclose (size_hid);
01114 H5Sclose (space_hid);
01115 H5Gclose (data_hid);
01116 return false;
01117 }
01118
01119 H5Dclose (size_hid);
01120 H5Sclose (space_hid);
01121
01122
01123
01124 Cell tmp = cell_value ();
01125
01126 octave_idx_type nel = dv.numel ();
01127
01128 for (octave_idx_type i = 0; i < nel; i++)
01129 {
01130 std::ostringstream buf;
01131 int digits = static_cast<int> (gnulib::floor (::log10 (static_cast<double> (nel)) + 1.0));
01132 buf << "_" << std::setw (digits) << std::setfill ('0') << i;
01133 std::string s = buf.str ();
01134
01135 if (! add_hdf5_data (data_hid, tmp.elem (i), s.c_str (), "", false,
01136 save_as_floats))
01137 {
01138 H5Gclose (data_hid);
01139 return false;
01140 }
01141 }
01142
01143 H5Gclose (data_hid);
01144
01145 return true;
01146 }
01147
01148 bool
01149 octave_cell::load_hdf5 (hid_t loc_id, const char *name)
01150 {
01151 clear_cellstr_cache ();
01152
01153 bool retval = false;
01154
01155 dim_vector dv;
01156 int empty = load_hdf5_empty (loc_id, name, dv);
01157 if (empty > 0)
01158 matrix.resize(dv);
01159 if (empty)
01160 return (empty > 0);
01161
01162 #if HAVE_HDF5_18
01163 hid_t group_id = H5Gopen (loc_id, name, H5P_DEFAULT);
01164 #else
01165 hid_t group_id = H5Gopen (loc_id, name);
01166 #endif
01167
01168 if (group_id < 0)
01169 return false;
01170
01171 #if HAVE_HDF5_18
01172 hid_t data_hid = H5Dopen (group_id, "dims", H5P_DEFAULT);
01173 #else
01174 hid_t data_hid = H5Dopen (group_id, "dims");
01175 #endif
01176 hid_t space_hid = H5Dget_space (data_hid);
01177 hsize_t rank = H5Sget_simple_extent_ndims (space_hid);
01178 if (rank != 1)
01179 {
01180 H5Dclose (data_hid);
01181 H5Gclose (group_id);
01182 return false;
01183 }
01184
01185 OCTAVE_LOCAL_BUFFER (hsize_t, hdims, rank);
01186 OCTAVE_LOCAL_BUFFER (hsize_t, maxdims, rank);
01187
01188 H5Sget_simple_extent_dims (space_hid, hdims, maxdims);
01189
01190
01191
01192 dv.resize (hdims[0]);
01193
01194 OCTAVE_LOCAL_BUFFER (octave_idx_type, tmp, hdims[0]);
01195
01196 if (H5Dread (data_hid, H5T_NATIVE_IDX, H5S_ALL, H5S_ALL,
01197 H5P_DEFAULT, tmp) < 0)
01198 {
01199 H5Dclose (data_hid);
01200 H5Gclose (group_id);
01201 return false;
01202 }
01203
01204 H5Dclose (data_hid);
01205 H5Gclose (group_id);
01206
01207 for (hsize_t i = 0, j = hdims[0] - 1; i < hdims[0]; i++, j--)
01208 dv(j) = tmp[i];
01209
01210 hdf5_callback_data dsub;
01211
01212 herr_t retval2 = -1;
01213
01214 Cell m (dv);
01215
01216 int current_item = 0;
01217
01218 hsize_t num_obj = 0;
01219 #if HAVE_HDF5_18
01220 group_id = H5Gopen (loc_id, name, H5P_DEFAULT);
01221 #else
01222 group_id = H5Gopen (loc_id, name);
01223 #endif
01224 H5Gget_num_objs (group_id, &num_obj);
01225 H5Gclose (group_id);
01226
01227 for (octave_idx_type i = 0; i < dv.numel (); i++)
01228 {
01229
01230 if (current_item >= static_cast<int> (num_obj))
01231 retval2 = -1;
01232 else
01233 retval2 = H5Giterate (loc_id, name, ¤t_item,
01234 hdf5_read_next_data, &dsub);
01235
01236 if (retval2 <= 0)
01237 break;
01238
01239 octave_value ov = dsub.tc;
01240 m.elem (i) = ov;
01241
01242 }
01243
01244 if (retval2 >= 0)
01245 {
01246 matrix = m;
01247 retval = true;
01248 }
01249
01250 return retval;
01251 }
01252
01253 #endif
01254
01255 DEFUN (iscell, args, ,
01256 "-*- texinfo -*-\n\
01257 @deftypefn {Built-in Function} {} iscell (@var{x})\n\
01258 Return true if @var{x} is a cell array object.\n\
01259 @seealso{ismatrix, isstruct, iscellstr, isa}\n\
01260 @end deftypefn")
01261 {
01262 octave_value retval;
01263
01264 if (args.length () == 1)
01265 retval = args(0).is_cell ();
01266 else
01267 print_usage ();
01268
01269 return retval;
01270 }
01271
01272 DEFUN (cell, args, ,
01273 "-*- texinfo -*-\n\
01274 @deftypefn {Built-in Function} {} cell (@var{n})\n\
01275 @deftypefnx {Built-in Function} {} cell (@var{m}, @var{n})\n\
01276 @deftypefnx {Built-in Function} {} cell (@var{m}, @var{n}, @var{k}, @dots{})\n\
01277 @deftypefnx {Built-in Function} {} cell ([@var{m} @var{n} @dots{}])\n\
01278 Create a new cell array object.\n\
01279 If invoked with a single scalar integer argument, return a square\n\
01280 @nospell{NxN} cell array. If invoked with two or more scalar\n\
01281 integer arguments, or a vector of integer values, return an array with\n\
01282 the given dimensions.\n\
01283 @end deftypefn")
01284 {
01285 octave_value retval;
01286
01287 int nargin = args.length ();
01288
01289 dim_vector dims;
01290
01291 switch (nargin)
01292 {
01293 case 0:
01294 dims = dim_vector (0, 0);
01295 break;
01296
01297 case 1:
01298 get_dimensions (args(0), "cell", dims);
01299 break;
01300
01301 default:
01302 {
01303 dims.resize (nargin);
01304
01305 for (int i = 0; i < nargin; i++)
01306 {
01307 dims(i) = args(i).is_empty () ? 0 : args(i).nint_value ();
01308
01309 if (error_state)
01310 {
01311 error ("cell: expecting scalar arguments");
01312 break;
01313 }
01314 }
01315 }
01316 break;
01317 }
01318
01319 if (! error_state)
01320 {
01321 dims.chop_trailing_singletons ();
01322
01323 check_dimensions (dims, "cell");
01324
01325 if (! error_state)
01326 retval = Cell (dims, Matrix ());
01327 }
01328
01329 return retval;
01330 }
01331
01332 DEFUN (iscellstr, args, ,
01333 "-*- texinfo -*-\n\
01334 @deftypefn {Built-in Function} {} iscellstr (@var{cell})\n\
01335 Return true if every element of the cell array @var{cell} is a\n\
01336 character string.\n\
01337 @seealso{ischar}\n\
01338 @end deftypefn")
01339 {
01340 octave_value retval;
01341
01342 if (args.length () == 1)
01343 retval = args(0).is_cellstr ();
01344 else
01345 print_usage ();
01346
01347 return retval;
01348 }
01349
01350
01351
01352
01353
01354
01355 DEFUN (cellstr, args, ,
01356 "-*- texinfo -*-\n\
01357 @deftypefn {Built-in Function} {} cellstr (@var{string})\n\
01358 Create a new cell array object from the elements of the string\n\
01359 array @var{string}.\n\
01360 @end deftypefn")
01361 {
01362 octave_value retval;
01363
01364 if (args.length () == 1)
01365 {
01366 octave_value_list tmp = Fiscellstr (args, 1);
01367
01368 if (tmp(0).is_true ())
01369 retval = args(0);
01370 else
01371 {
01372 string_vector s = args(0).all_strings ();
01373
01374 if (! error_state)
01375 retval = (s.is_empty ()
01376 ? Cell (octave_value (std::string ()))
01377 : Cell (s, true));
01378 else
01379 error ("cellstr: argument STRING must be a 2-D character array");
01380 }
01381 }
01382 else
01383 print_usage ();
01384
01385 return retval;
01386 }
01387
01388 DEFUN (struct2cell, args, ,
01389 "-*- texinfo -*-\n\
01390 @deftypefn {Built-in Function} {} struct2cell (@var{S})\n\
01391 Create a new cell array from the objects stored in the struct object.\n\
01392 If @var{f} is the number of fields in the structure, the resulting\n\
01393 cell array will have a dimension vector corresponding to\n\
01394 @code{[@var{F} size(@var{S})]}. For example:\n\
01395 \n\
01396 @example\n\
01397 @group\n\
01398 s = struct('name', @{'Peter', 'Hannah', 'Robert'@},\n\
01399 'age', @{23, 16, 3@});\n\
01400 c = struct2cell(s)\n\
01401 @result{} c = @{1x1x3 Cell Array@}\n\
01402 c(1,1,:)(:)\n\
01403 @result{} ans =\n\
01404 @{\n\
01405 [1,1] = Peter\n\
01406 [2,1] = Hannah\n\
01407 [3,1] = Robert\n\
01408 @}\n\
01409 c(2,1,:)(:)\n\
01410 @result{} ans =\n\
01411 @{\n\
01412 [1,1] = 23\n\
01413 [2,1] = 16\n\
01414 [3,1] = 3\n\
01415 @}\n\
01416 @end group\n\
01417 @end example\n\
01418 \n\
01419 @seealso{cell2struct, fieldnames}\n\
01420 @end deftypefn")
01421 {
01422 octave_value retval;
01423
01424 int nargin = args.length ();
01425
01426 if (nargin == 1)
01427 {
01428 const octave_map m = args(0).map_value ();
01429
01430 if (! error_state)
01431 {
01432 const dim_vector m_dv = m.dims ();
01433
01434 octave_idx_type num_fields = m.nfields ();
01435
01436
01437
01438
01439
01440 dim_vector result_dv;
01441 if (m_dv (m_dv.length () - 1) == 1)
01442 result_dv.resize (m_dv.length ());
01443 else
01444 result_dv.resize (m_dv.length () + 1);
01445
01446 result_dv(0) = num_fields;
01447
01448 for (int i = 1; i < result_dv.length (); i++)
01449 result_dv(i) = m_dv(i-1);
01450
01451 NoAlias<Cell> c (result_dv);
01452
01453 octave_idx_type n_elts = m.numel ();
01454
01455
01456
01457 for (octave_idx_type j = 0; j < n_elts; j++)
01458 for (octave_idx_type i = 0; i < num_fields; i++)
01459 c(i,j) = m.contents(i)(j);
01460
01461 retval = c;
01462 }
01463 else
01464 error ("struct2cell: argument S must be a structure");
01465 }
01466 else
01467 print_usage ();
01468
01469 return retval;
01470 }
01471
01472
01473
01474
01475
01476
01477
01478
01479
01480
01481
01482
01483
01484 mxArray *
01485 octave_cell::as_mxArray (void) const
01486 {
01487 mxArray *retval = new mxArray (dims ());
01488
01489 mxArray **elts = static_cast<mxArray **> (retval->get_data ());
01490
01491 mwSize nel = numel ();
01492
01493 const octave_value *p = matrix.data ();
01494
01495 for (mwIndex i = 0; i < nel; i++)
01496 elts[i] = new mxArray (p[i]);
01497
01498 return retval;
01499 }
01500
01501 octave_value
01502 octave_cell::map (unary_mapper_t umap) const
01503 {
01504 switch (umap)
01505 {
01506 #define FORWARD_MAPPER(UMAP) \
01507 case umap_ ## UMAP: \
01508 return matrix.UMAP ()
01509 FORWARD_MAPPER (xisalnum);
01510 FORWARD_MAPPER (xisalpha);
01511 FORWARD_MAPPER (xisascii);
01512 FORWARD_MAPPER (xiscntrl);
01513 FORWARD_MAPPER (xisdigit);
01514 FORWARD_MAPPER (xisgraph);
01515 FORWARD_MAPPER (xislower);
01516 FORWARD_MAPPER (xisprint);
01517 FORWARD_MAPPER (xispunct);
01518 FORWARD_MAPPER (xisspace);
01519 FORWARD_MAPPER (xisupper);
01520 FORWARD_MAPPER (xisxdigit);
01521 FORWARD_MAPPER (xtoascii);
01522 FORWARD_MAPPER (xtolower);
01523 FORWARD_MAPPER (xtoupper);
01524
01525 default:
01526 return octave_base_value::map (umap);
01527 }
01528 }