00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #ifdef HAVE_CONFIG_H
00026 #include <config.h>
00027 #endif
00028
00029 #include <cfloat>
00030 #include <cstring>
00031 #include <cctype>
00032
00033 #include <fstream>
00034 #include <iomanip>
00035 #include <iostream>
00036 #include <sstream>
00037 #include <string>
00038 #include <vector>
00039
00040 #include "byte-swap.h"
00041 #include "data-conv.h"
00042 #include "file-ops.h"
00043 #include "glob-match.h"
00044 #include "lo-mappers.h"
00045 #include "mach-info.h"
00046 #include "oct-env.h"
00047 #include "oct-time.h"
00048 #include "quit.h"
00049 #include "str-vec.h"
00050 #include "file-stat.h"
00051 #include "oct-locbuf.h"
00052
00053 #include "Cell.h"
00054 #include "defun.h"
00055 #include "error.h"
00056 #include "gripes.h"
00057 #include "load-save.h"
00058 #include "load-path.h"
00059 #include "oct-obj.h"
00060 #include "oct-map.h"
00061 #include "ov-cell.h"
00062 #include "ov-class.h"
00063 #include "ov-fcn-inline.h"
00064 #include "pager.h"
00065 #include "pt-exp.h"
00066 #include "sysdep.h"
00067 #include "toplev.h"
00068 #include "unwind-prot.h"
00069 #include "utils.h"
00070 #include "variables.h"
00071 #include "version.h"
00072 #include "dMatrix.h"
00073
00074 #include "ls-utils.h"
00075 #include "ls-mat5.h"
00076
00077 #include "parse.h"
00078 #include "defaults.h"
00079
00080 #ifdef HAVE_ZLIB
00081 #include <zlib.h>
00082 #endif
00083
00084 #define PAD(l) (((l) > 0 && (l) <= 4) ? 4 : (((l)+7)/8)*8)
00085
00086
00087
00088 static octave_value subsys_ov;
00089
00090
00091
00092
00093
00094
00095
00096
00097 enum arrayclasstype
00098 {
00099 MAT_FILE_CELL_CLASS=1,
00100 MAT_FILE_STRUCT_CLASS,
00101 MAT_FILE_OBJECT_CLASS,
00102 MAT_FILE_CHAR_CLASS,
00103 MAT_FILE_SPARSE_CLASS,
00104 MAT_FILE_DOUBLE_CLASS,
00105 MAT_FILE_SINGLE_CLASS,
00106 MAT_FILE_INT8_CLASS,
00107 MAT_FILE_UINT8_CLASS,
00108 MAT_FILE_INT16_CLASS,
00109 MAT_FILE_UINT16_CLASS,
00110 MAT_FILE_INT32_CLASS,
00111 MAT_FILE_UINT32_CLASS,
00112 MAT_FILE_INT64_CLASS,
00113 MAT_FILE_UINT64_CLASS,
00114 MAT_FILE_FUNCTION_CLASS,
00115 MAT_FILE_WORKSPACE_CLASS
00116 };
00117
00118
00119
00120
00121
00122
00123 static void
00124 read_mat5_binary_data (std::istream& is, double *data,
00125 octave_idx_type count, bool swap, mat5_data_type type,
00126 oct_mach_info::float_format flt_fmt)
00127 {
00128
00129 switch (type)
00130 {
00131 case miINT8:
00132 read_doubles (is, data, LS_CHAR, count, swap, flt_fmt);
00133 break;
00134
00135 case miUTF8:
00136 case miUINT8:
00137 read_doubles (is, data, LS_U_CHAR, count, swap, flt_fmt);
00138 break;
00139
00140 case miINT16:
00141 read_doubles (is, data, LS_SHORT, count, swap, flt_fmt);
00142 break;
00143
00144 case miUTF16:
00145 case miUINT16:
00146 read_doubles (is, data, LS_U_SHORT, count, swap, flt_fmt);
00147 break;
00148
00149 case miINT32:
00150 read_doubles (is, data, LS_INT, count, swap, flt_fmt);
00151 break;
00152
00153 case miUTF32:
00154 case miUINT32:
00155 read_doubles (is, data, LS_U_INT, count, swap, flt_fmt);
00156 break;
00157
00158 case miSINGLE:
00159 read_doubles (is, data, LS_FLOAT, count, swap, flt_fmt);
00160 break;
00161
00162 case miRESERVE1:
00163 break;
00164
00165 case miDOUBLE:
00166 read_doubles (is, data, LS_DOUBLE, count, swap, flt_fmt);
00167 break;
00168
00169 case miRESERVE2:
00170 case miRESERVE3:
00171 break;
00172
00173
00174 case miINT64:
00175 read_doubles (is, data, LS_LONG, count, swap, flt_fmt);
00176 break;
00177
00178 case miUINT64:
00179 read_doubles (is, data, LS_U_LONG, count, swap, flt_fmt);
00180 break;
00181
00182 case miMATRIX:
00183 default:
00184 break;
00185 }
00186 }
00187
00188 static void
00189 read_mat5_binary_data (std::istream& is, float *data,
00190 octave_idx_type count, bool swap, mat5_data_type type,
00191 oct_mach_info::float_format flt_fmt)
00192 {
00193
00194 switch (type)
00195 {
00196 case miINT8:
00197 read_floats (is, data, LS_CHAR, count, swap, flt_fmt);
00198 break;
00199
00200 case miUTF8:
00201 case miUINT8:
00202 read_floats (is, data, LS_U_CHAR, count, swap, flt_fmt);
00203 break;
00204
00205 case miINT16:
00206 read_floats (is, data, LS_SHORT, count, swap, flt_fmt);
00207 break;
00208
00209 case miUTF16:
00210 case miUINT16:
00211 read_floats (is, data, LS_U_SHORT, count, swap, flt_fmt);
00212 break;
00213
00214 case miINT32:
00215 read_floats (is, data, LS_INT, count, swap, flt_fmt);
00216 break;
00217
00218 case miUTF32:
00219 case miUINT32:
00220 read_floats (is, data, LS_U_INT, count, swap, flt_fmt);
00221 break;
00222
00223 case miSINGLE:
00224 read_floats (is, data, LS_FLOAT, count, swap, flt_fmt);
00225 break;
00226
00227 case miRESERVE1:
00228 break;
00229
00230 case miDOUBLE:
00231 read_floats (is, data, LS_DOUBLE, count, swap, flt_fmt);
00232 break;
00233
00234 case miRESERVE2:
00235 case miRESERVE3:
00236 break;
00237
00238
00239 case miINT64:
00240 read_floats (is, data, LS_LONG, count, swap, flt_fmt);
00241 break;
00242
00243 case miUINT64:
00244 read_floats (is, data, LS_U_LONG, count, swap, flt_fmt);
00245 break;
00246
00247 case miMATRIX:
00248 default:
00249 break;
00250 }
00251 }
00252
00253 template <class T>
00254 void
00255 read_mat5_integer_data (std::istream& is, T *m, octave_idx_type count,
00256 bool swap, mat5_data_type type)
00257 {
00258
00259 #define READ_INTEGER_DATA(TYPE, swap, data, size, len, stream) \
00260 do \
00261 { \
00262 if (len > 0) \
00263 { \
00264 OCTAVE_LOCAL_BUFFER (TYPE, ptr, len); \
00265 stream.read (reinterpret_cast<char *> (ptr), size * len); \
00266 if (swap) \
00267 swap_bytes< size > (ptr, len); \
00268 for (octave_idx_type i = 0; i < len; i++) \
00269 data[i] = ptr[i]; \
00270 } \
00271 } \
00272 while (0)
00273
00274 switch (type)
00275 {
00276 case miINT8:
00277 READ_INTEGER_DATA (int8_t, swap, m, 1, count, is);
00278 break;
00279
00280 case miUINT8:
00281 READ_INTEGER_DATA (uint8_t, swap, m, 1, count, is);
00282 break;
00283
00284 case miINT16:
00285 READ_INTEGER_DATA (int16_t, swap, m, 2, count, is);
00286 break;
00287
00288 case miUINT16:
00289 READ_INTEGER_DATA (uint16_t, swap, m, 2, count, is);
00290 break;
00291
00292 case miINT32:
00293 READ_INTEGER_DATA (int32_t, swap, m, 4, count, is);
00294 break;
00295
00296 case miUINT32:
00297 READ_INTEGER_DATA (uint32_t, swap, m, 4, count, is);
00298 break;
00299
00300 case miSINGLE:
00301 case miRESERVE1:
00302 case miDOUBLE:
00303 case miRESERVE2:
00304 case miRESERVE3:
00305 break;
00306
00307 case miINT64:
00308 READ_INTEGER_DATA (int64_t, swap, m, 8, count, is);
00309 break;
00310
00311 case miUINT64:
00312 READ_INTEGER_DATA (uint64_t, swap, m, 8, count, is);
00313 break;
00314
00315 case miMATRIX:
00316 default:
00317 break;
00318 }
00319
00320 #undef READ_INTEGER_DATA
00321
00322 }
00323
00324 template void
00325 read_mat5_integer_data (std::istream& is, octave_int8 *m,
00326 octave_idx_type count, bool swap,
00327 mat5_data_type type);
00328
00329 template void
00330 read_mat5_integer_data (std::istream& is, octave_int16 *m,
00331 octave_idx_type count, bool swap,
00332 mat5_data_type type);
00333
00334 template void
00335 read_mat5_integer_data (std::istream& is, octave_int32 *m,
00336 octave_idx_type count, bool swap,
00337 mat5_data_type type);
00338
00339 template void
00340 read_mat5_integer_data (std::istream& is, octave_int64 *m,
00341 octave_idx_type count, bool swap,
00342 mat5_data_type type);
00343
00344 template void
00345 read_mat5_integer_data (std::istream& is, octave_uint8 *m,
00346 octave_idx_type count, bool swap,
00347 mat5_data_type type);
00348
00349 template void
00350 read_mat5_integer_data (std::istream& is, octave_uint16 *m,
00351 octave_idx_type count, bool swap,
00352 mat5_data_type type);
00353
00354 template void
00355 read_mat5_integer_data (std::istream& is, octave_uint32 *m,
00356 octave_idx_type count, bool swap,
00357 mat5_data_type type);
00358
00359 template void
00360 read_mat5_integer_data (std::istream& is, octave_uint64 *m,
00361 octave_idx_type count, bool swap,
00362 mat5_data_type type);
00363
00364 template void
00365 read_mat5_integer_data (std::istream& is, int *m,
00366 octave_idx_type count, bool swap,
00367 mat5_data_type type);
00368
00369 #define OCTAVE_MAT5_INTEGER_READ(TYP) \
00370 { \
00371 TYP re (dims); \
00372 \
00373 std::streampos tmp_pos; \
00374 \
00375 if (read_mat5_tag (is, swap, type, len)) \
00376 { \
00377 error ("load: reading matrix data for '%s'", retval.c_str ()); \
00378 goto data_read_error; \
00379 } \
00380 \
00381 octave_idx_type n = re.numel (); \
00382 tmp_pos = is.tellg (); \
00383 read_mat5_integer_data (is, re.fortran_vec (), n, swap, \
00384 static_cast<enum mat5_data_type> (type)); \
00385 \
00386 if (! is || error_state) \
00387 { \
00388 error ("load: reading matrix data for '%s'", retval.c_str ()); \
00389 goto data_read_error; \
00390 } \
00391 \
00392 is.seekg (tmp_pos + static_cast<std::streamoff> (PAD (len))); \
00393 \
00394 if (imag) \
00395 { \
00396 \
00397 NDArray im (dims); \
00398 \
00399 if (read_mat5_tag (is, swap, type, len)) \
00400 { \
00401 error ("load: reading matrix data for '%s'", \
00402 retval.c_str ()); \
00403 goto data_read_error; \
00404 } \
00405 \
00406 n = im.numel (); \
00407 read_mat5_binary_data (is, im.fortran_vec (), n, swap, \
00408 static_cast<enum mat5_data_type> (type), flt_fmt); \
00409 \
00410 if (! is || error_state) \
00411 { \
00412 error ("load: reading imaginary matrix data for '%s'", \
00413 retval.c_str ()); \
00414 goto data_read_error; \
00415 } \
00416 \
00417 ComplexNDArray ctmp (dims); \
00418 \
00419 for (octave_idx_type i = 0; i < n; i++) \
00420 ctmp(i) = Complex (re(i).double_value (), im(i)); \
00421 \
00422 tc = ctmp; \
00423 } \
00424 else \
00425 tc = re; \
00426 }
00427
00428
00429
00430
00431 static int
00432 read_mat5_tag (std::istream& is, bool swap, int32_t& type, int32_t& bytes)
00433 {
00434 unsigned int upper;
00435 int32_t temp;
00436
00437 if (! is.read (reinterpret_cast<char *> (&temp), 4 ))
00438 goto data_read_error;
00439
00440 if (swap)
00441 swap_bytes<4> (&temp);
00442
00443 upper = (temp >> 16) & 0xffff;
00444 type = temp & 0xffff;
00445
00446 if (upper)
00447 {
00448
00449 bytes = upper;
00450 }
00451 else
00452 {
00453 if (! is.read (reinterpret_cast<char *> (&temp), 4 ))
00454 goto data_read_error;
00455 if (swap)
00456 swap_bytes<4> (&temp);
00457 bytes = temp;
00458 }
00459
00460 return 0;
00461
00462 data_read_error:
00463 return 1;
00464 }
00465
00466 static void
00467 read_int (std::istream& is, bool swap, int32_t& val)
00468 {
00469 is.read (reinterpret_cast<char *> (&val), 4);
00470
00471 if (swap)
00472 swap_bytes<4> (&val);
00473 }
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483 std::string
00484 read_mat5_binary_element (std::istream& is, const std::string& filename,
00485 bool swap, bool& global, octave_value& tc)
00486 {
00487 std::string retval;
00488
00489 global = false;
00490
00491
00492
00493
00494
00495 bool imag;
00496 bool isclass = false;
00497 bool logicalvar;
00498 dim_vector dims;
00499 enum arrayclasstype arrayclass;
00500 int16_t number = *(reinterpret_cast<const int16_t *>("\x00\x01"));
00501 octave_idx_type nzmax;
00502 std::string classname;
00503
00504
00505 oct_mach_info::float_format flt_fmt = oct_mach_info::flt_fmt_unknown;
00506 if ((number == 1) ^ swap)
00507 flt_fmt = oct_mach_info::flt_fmt_ieee_big_endian;
00508 else
00509 flt_fmt = oct_mach_info::flt_fmt_ieee_little_endian;
00510
00511
00512 int32_t type = 0;
00513 int32_t element_length;
00514 if (read_mat5_tag (is, swap, type, element_length))
00515 return retval;
00516
00517 #ifdef HAVE_ZLIB
00518 if (type == miCOMPRESSED)
00519 {
00520
00521
00522
00523
00524
00525 OCTAVE_LOCAL_BUFFER (char, inbuf, element_length);
00526 is.read (inbuf, element_length);
00527
00528
00529
00530 uLongf destLen = 8;
00531 OCTAVE_LOCAL_BUFFER (unsigned int, tmp, 2);
00532 if (uncompress (reinterpret_cast<Bytef *> (tmp), &destLen,
00533 reinterpret_cast<Bytef *> (inbuf), element_length)
00534 != Z_MEM_ERROR)
00535 {
00536
00537 if (swap)
00538 swap_bytes<4> (tmp, 2);
00539
00540 destLen = tmp[1] + 8;
00541 std::string outbuf (destLen, ' ');
00542
00543
00544
00545 int err = uncompress (reinterpret_cast<Bytef *> (const_cast<char *> (outbuf.c_str ())),
00546 &destLen, reinterpret_cast<Bytef *> (inbuf),
00547 element_length);
00548
00549 if (err != Z_OK)
00550 {
00551 std::string msg;
00552 switch (err)
00553 {
00554 case Z_STREAM_END:
00555 msg = "stream end";
00556 break;
00557
00558 case Z_NEED_DICT:
00559 msg = "need dict";
00560 break;
00561
00562 case Z_ERRNO:
00563 msg = "errno case";
00564 break;
00565
00566 case Z_STREAM_ERROR:
00567 msg = "stream error";
00568 break;
00569
00570 case Z_DATA_ERROR:
00571 msg = "data error";
00572 break;
00573
00574 case Z_MEM_ERROR:
00575 msg = "mem error";
00576 break;
00577
00578 case Z_BUF_ERROR:
00579 msg = "buf error";
00580 break;
00581
00582 case Z_VERSION_ERROR:
00583 msg = "version error";
00584 break;
00585 }
00586
00587 error ("load: error uncompressing data element (%s from zlib)",
00588 msg.c_str ());
00589 }
00590 else
00591 {
00592 std::istringstream gz_is (outbuf);
00593 retval = read_mat5_binary_element (gz_is, filename,
00594 swap, global, tc);
00595 }
00596 }
00597 else
00598 error ("load: error probing size of compressed data element");
00599
00600 return retval;
00601 }
00602 #endif
00603
00604 std::streampos pos;
00605
00606 if (type != miMATRIX)
00607 {
00608 pos = is.tellg ();
00609 error ("load: invalid element type = %d", type);
00610 goto early_read_error;
00611 }
00612
00613 if (element_length == 0)
00614 {
00615 tc = Matrix ();
00616 return retval;
00617 }
00618
00619 pos = is.tellg ();
00620
00621
00622 int32_t len;
00623 if (read_mat5_tag (is, swap, type, len) || type != miUINT32 || len != 8)
00624 {
00625 error ("load: invalid array flags subelement");
00626 goto early_read_error;
00627 }
00628
00629 int32_t flags;
00630 read_int (is, swap, flags);
00631
00632 imag = (flags & 0x0800) != 0;
00633
00634 global = (flags & 0x0400) != 0;
00635
00636 logicalvar = (flags & 0x0200) != 0;
00637
00638 arrayclass = static_cast<arrayclasstype> (flags & 0xff);
00639
00640 int32_t tmp_nzmax;
00641 read_int (is, swap, tmp_nzmax);
00642 nzmax = tmp_nzmax;
00643
00644
00645 if (arrayclass != MAT_FILE_WORKSPACE_CLASS)
00646 {
00647 int32_t dim_len;
00648
00649 if (read_mat5_tag (is, swap, type, dim_len) || type != miINT32)
00650 {
00651 error ("load: invalid dimensions array subelement");
00652 goto early_read_error;
00653 }
00654
00655 int ndims = dim_len / 4;
00656 dims.resize (ndims);
00657 for (int i = 0; i < ndims; i++)
00658 {
00659 int32_t n;
00660 read_int (is, swap, n);
00661 dims(i) = n;
00662 }
00663
00664 std::streampos tmp_pos = is.tellg ();
00665 is.seekg (tmp_pos + static_cast<std::streamoff> (PAD (dim_len) - dim_len));
00666 }
00667 else
00668 {
00669
00670 dims.resize(2);
00671 dims(0) = 1;
00672 dims(1) = 1;
00673 }
00674
00675 if (read_mat5_tag (is, swap, type, len) || type != miINT8)
00676 {
00677 error ("load: invalid array name subelement");
00678 goto early_read_error;
00679 }
00680
00681 {
00682 OCTAVE_LOCAL_BUFFER (char, name, len+1);
00683
00684
00685
00686 std::streampos tmp_pos = is.tellg ();
00687
00688 if (len)
00689 {
00690 if (! is.read (name, len ))
00691 goto data_read_error;
00692
00693 is.seekg (tmp_pos + static_cast<std::streamoff> (PAD (len)));
00694 }
00695
00696 name[len] = '\0';
00697 retval = name;
00698 }
00699
00700 switch (arrayclass)
00701 {
00702 case MAT_FILE_CELL_CLASS:
00703 {
00704 Cell cell_array (dims);
00705
00706 octave_idx_type n = cell_array.numel ();
00707
00708 for (octave_idx_type i = 0; i < n; i++)
00709 {
00710 octave_value tc2;
00711
00712 std::string nm
00713 = read_mat5_binary_element (is, filename, swap, global, tc2);
00714
00715 if (! is || error_state)
00716 {
00717 error ("load: reading cell data for '%s'", nm.c_str ());
00718 goto data_read_error;
00719 }
00720
00721 cell_array(i) = tc2;
00722 }
00723
00724 tc = cell_array;
00725 }
00726 break;
00727
00728 case MAT_FILE_SPARSE_CLASS:
00729 {
00730 octave_idx_type nr = dims(0);
00731 octave_idx_type nc = dims(1);
00732 SparseMatrix sm;
00733 SparseComplexMatrix scm;
00734 octave_idx_type *ridx;
00735 octave_idx_type *cidx;
00736 double *data;
00737
00738
00739 if (imag)
00740 {
00741 scm = SparseComplexMatrix (nr, nc, nzmax);
00742 ridx = scm.ridx ();
00743 cidx = scm.cidx ();
00744 data = 0;
00745 }
00746 else
00747 {
00748 sm = SparseMatrix (nr, nc, nzmax);
00749 ridx = sm.ridx ();
00750 cidx = sm.cidx ();
00751 data = sm.data ();
00752 }
00753
00754
00755 std::streampos tmp_pos;
00756
00757 if (read_mat5_tag (is, swap, type, len))
00758 {
00759 error ("load: reading sparse row data for '%s'", retval.c_str ());
00760 goto data_read_error;
00761 }
00762
00763 tmp_pos = is.tellg ();
00764
00765 read_mat5_integer_data (is, ridx, nzmax, swap,
00766 static_cast<enum mat5_data_type> (type));
00767
00768 if (! is || error_state)
00769 {
00770 error ("load: reading sparse row data for '%s'", retval.c_str ());
00771 goto data_read_error;
00772 }
00773
00774 is.seekg (tmp_pos + static_cast<std::streamoff> (PAD (len)));
00775
00776
00777 if (read_mat5_tag (is, swap, type, len))
00778 {
00779 error ("load: reading sparse column data for '%s'", retval.c_str ());
00780 goto data_read_error;
00781 }
00782
00783 tmp_pos = is.tellg ();
00784
00785 read_mat5_integer_data (is, cidx, nc + 1, swap,
00786 static_cast<enum mat5_data_type> (type));
00787
00788 if (! is || error_state)
00789 {
00790 error ("load: reading sparse column data for '%s'", retval.c_str ());
00791 goto data_read_error;
00792 }
00793
00794 is.seekg (tmp_pos + static_cast<std::streamoff> (PAD (len)));
00795
00796
00797 if (read_mat5_tag (is, swap, type, len))
00798 {
00799 error ("load: reading sparse matrix data for '%s'", retval.c_str ());
00800 goto data_read_error;
00801 }
00802
00803 octave_idx_type nnz = cidx[nc];
00804 NDArray re;
00805 if (imag)
00806 {
00807 re = NDArray (dim_vector (nnz, 1));
00808 data = re.fortran_vec ();
00809 }
00810
00811 tmp_pos = is.tellg ();
00812 read_mat5_binary_data (is, data, nnz, swap,
00813 static_cast<enum mat5_data_type> (type), flt_fmt);
00814
00815 if (! is || error_state)
00816 {
00817 error ("load: reading sparse matrix data for '%s'", retval.c_str ());
00818 goto data_read_error;
00819 }
00820
00821 is.seekg (tmp_pos + static_cast<std::streamoff> (PAD (len)));
00822
00823
00824 if (imag)
00825 {
00826 NDArray im (dim_vector (static_cast<int> (nnz), 1));
00827
00828 if (read_mat5_tag (is, swap, type, len))
00829 {
00830 error ("load: reading sparse matrix data for '%s'", retval.c_str ());
00831 goto data_read_error;
00832 }
00833
00834 read_mat5_binary_data (is, im.fortran_vec (), nnz, swap,
00835 static_cast<enum mat5_data_type> (type), flt_fmt);
00836
00837 if (! is || error_state)
00838 {
00839 error ("load: reading imaginary sparse matrix data for '%s'",
00840 retval.c_str ());
00841 goto data_read_error;
00842 }
00843
00844 for (octave_idx_type i = 0; i < nnz; i++)
00845 scm.xdata (i) = Complex (re (i), im (i));
00846
00847 tc = scm;
00848 }
00849 else
00850 tc = sm;
00851 }
00852 break;
00853
00854 case MAT_FILE_FUNCTION_CLASS:
00855 {
00856 octave_value tc2;
00857 std::string nm
00858 = read_mat5_binary_element (is, filename, swap, global, tc2);
00859
00860 if (! is || error_state)
00861 goto data_read_error;
00862
00863
00864
00865
00866 Octave_map m0 = tc2.map_value();
00867 Octave_map m1 = m0.contents("function_handle")(0).map_value();
00868 std::string ftype = m1.contents("type")(0).string_value();
00869 std::string fname = m1.contents("function")(0).string_value();
00870 std::string fpath = m1.contents("file")(0).string_value();
00871
00872 if (ftype == "simple" || ftype == "scopedfunction")
00873 {
00874 if (fpath.length() == 0)
00875
00876 tc = make_fcn_handle (fname);
00877 else
00878 {
00879 std::string mroot =
00880 m0.contents("matlabroot")(0).string_value();
00881
00882 if ((fpath.length () >= mroot.length ()) &&
00883 fpath.substr(0, mroot.length()) == mroot &&
00884 OCTAVE_EXEC_PREFIX != mroot)
00885 {
00886
00887
00888
00889
00890
00891
00892
00893
00894 std::string str = OCTAVE_EXEC_PREFIX +
00895 fpath.substr (mroot.length ());
00896 file_stat fs (str);
00897
00898 if (fs.exists ())
00899 {
00900 size_t xpos
00901 = str.find_last_of (file_ops::dir_sep_chars ());
00902
00903 std::string dir_name = str.substr (0, xpos);
00904
00905 octave_function *fcn
00906 = load_fcn_from_file (str, dir_name, "", fname);
00907
00908 if (fcn)
00909 {
00910 octave_value tmp (fcn);
00911
00912 tc = octave_value (new octave_fcn_handle (tmp, fname));
00913 }
00914 }
00915 else
00916 {
00917
00918
00919 string_vector names(3);
00920 names(0) = fname + ".oct";
00921 names(1) = fname + ".mex";
00922 names(2) = fname + ".m";
00923
00924 dir_path p (load_path::system_path ());
00925
00926 str = octave_env::make_absolute (p.find_first_of (names));
00927
00928 size_t xpos
00929 = str.find_last_of (file_ops::dir_sep_chars ());
00930
00931 std::string dir_name = str.substr (0, xpos);
00932
00933 octave_function *fcn
00934 = load_fcn_from_file (str, dir_name, "", fname);
00935
00936 if (fcn)
00937 {
00938 octave_value tmp (fcn);
00939
00940 tc = octave_value (new octave_fcn_handle (tmp, fname));
00941 }
00942 else
00943 {
00944 warning ("load: can't find the file %s",
00945 fpath.c_str());
00946 goto skip_ahead;
00947 }
00948 }
00949 }
00950 else
00951 {
00952 size_t xpos
00953 = fpath.find_last_of (file_ops::dir_sep_chars ());
00954
00955 std::string dir_name = fpath.substr (0, xpos);
00956
00957 octave_function *fcn
00958 = load_fcn_from_file (fpath, dir_name, "", fname);
00959
00960 if (fcn)
00961 {
00962 octave_value tmp (fcn);
00963
00964 tc = octave_value (new octave_fcn_handle (tmp, fname));
00965 }
00966 else
00967 {
00968 warning ("load: can't find the file %s",
00969 fpath.c_str());
00970 goto skip_ahead;
00971 }
00972 }
00973 }
00974 }
00975 else if (ftype == "nested")
00976 {
00977 warning ("load: can't load nested function");
00978 goto skip_ahead;
00979 }
00980 else if (ftype == "anonymous")
00981 {
00982 Octave_map m2 = m1.contents("workspace")(0).map_value();
00983 uint32NDArray MCOS = m2.contents("MCOS")(0).uint32_array_value();
00984 octave_idx_type off = static_cast<octave_idx_type>(MCOS(4).double_value ());
00985 m2 = subsys_ov.map_value();
00986 m2 = m2.contents("MCOS")(0).map_value();
00987 tc2 = m2.contents("MCOS")(0).cell_value()(1 + off).cell_value()(1);
00988 m2 = tc2.map_value();
00989
00990 unwind_protect_safe frame;
00991
00992
00993
00994
00995 symbol_table::scope_id local_scope = symbol_table::alloc_scope ();
00996 frame.add_fcn (symbol_table::erase_scope, local_scope);
00997
00998 symbol_table::set_scope (local_scope);
00999
01000 octave_call_stack::push (local_scope, 0);
01001 frame.add_fcn (octave_call_stack::pop);
01002
01003 if (m2.nfields() > 0)
01004 {
01005 octave_value tmp;
01006
01007 for (Octave_map::iterator p0 = m2.begin() ;
01008 p0 != m2.end(); p0++)
01009 {
01010 std::string key = m2.key(p0);
01011 octave_value val = m2.contents(p0)(0);
01012
01013 symbol_table::varref (key, local_scope, 0) = val;
01014 }
01015 }
01016
01017 int parse_status;
01018 octave_value anon_fcn_handle =
01019 eval_string (fname.substr (4), true, parse_status);
01020
01021 if (parse_status == 0)
01022 {
01023 octave_fcn_handle *fh =
01024 anon_fcn_handle.fcn_handle_value ();
01025
01026 if (fh)
01027 tc = new octave_fcn_handle (fh->fcn_val (), "@<anonymous>");
01028 else
01029 {
01030 error ("load: failed to load anonymous function handle");
01031 goto skip_ahead;
01032 }
01033 }
01034 else
01035 {
01036 error ("load: failed to load anonymous function handle");
01037 goto skip_ahead;
01038 }
01039
01040 frame.run ();
01041 }
01042 else
01043 {
01044 error ("load: invalid function handle type");
01045 goto skip_ahead;
01046 }
01047 }
01048 break;
01049
01050 case MAT_FILE_WORKSPACE_CLASS:
01051 {
01052 Octave_map m (dim_vector (1, 1));
01053 int n_fields = 2;
01054 string_vector field (n_fields);
01055
01056 for (int i = 0; i < n_fields; i++)
01057 {
01058 int32_t fn_type;
01059 int32_t fn_len;
01060 if (read_mat5_tag (is, swap, fn_type, fn_len) || fn_type != miINT8)
01061 {
01062 error ("load: invalid field name subelement");
01063 goto data_read_error;
01064 }
01065
01066 OCTAVE_LOCAL_BUFFER (char, elname, fn_len + 1);
01067
01068 std::streampos tmp_pos = is.tellg ();
01069
01070 if (fn_len)
01071 {
01072 if (! is.read (elname, fn_len))
01073 goto data_read_error;
01074
01075 is.seekg (tmp_pos +
01076 static_cast<std::streamoff> (PAD (fn_len)));
01077 }
01078
01079 elname[fn_len] = '\0';
01080
01081 field(i) = elname;
01082 }
01083
01084 std::vector<Cell> elt (n_fields);
01085
01086 for (octave_idx_type i = 0; i < n_fields; i++)
01087 elt[i] = Cell (dims);
01088
01089 octave_idx_type n = dims.numel ();
01090
01091
01092 for (octave_idx_type j = 0; j < n; j++)
01093 {
01094 for (octave_idx_type i = 0; i < n_fields; i++)
01095 {
01096 if (field(i) == "MCOS")
01097 {
01098 octave_value fieldtc;
01099 read_mat5_binary_element (is, filename, swap, global,
01100 fieldtc);
01101 if (! is || error_state)
01102 goto data_read_error;
01103
01104 elt[i](j) = fieldtc;
01105 }
01106 else
01107 elt[i](j) = octave_value ();
01108 }
01109 }
01110
01111 for (octave_idx_type i = 0; i < n_fields; i++)
01112 m.assign (field (i), elt[i]);
01113 tc = m;
01114 }
01115 break;
01116
01117 case MAT_FILE_OBJECT_CLASS:
01118 {
01119 isclass = true;
01120
01121 if (read_mat5_tag (is, swap, type, len) || type != miINT8)
01122 {
01123 error ("load: invalid class name");
01124 goto skip_ahead;
01125 }
01126
01127 {
01128 OCTAVE_LOCAL_BUFFER (char, name, len+1);
01129
01130 std::streampos tmp_pos = is.tellg ();
01131
01132 if (len)
01133 {
01134 if (! is.read (name, len ))
01135 goto data_read_error;
01136
01137 is.seekg (tmp_pos + static_cast<std::streamoff> (PAD (len)));
01138 }
01139
01140 name[len] = '\0';
01141 classname = name;
01142 }
01143 }
01144
01145 case MAT_FILE_STRUCT_CLASS:
01146 {
01147 Octave_map m (dim_vector (1, 1));
01148 int32_t fn_type;
01149 int32_t fn_len;
01150 int32_t field_name_length;
01151
01152
01153
01154
01155
01156
01157 if (read_mat5_tag (is, swap, fn_type, fn_len) || fn_type != miINT32)
01158 {
01159 error ("load: invalid field name length subelement");
01160 goto data_read_error;
01161 }
01162
01163 if (! is.read (reinterpret_cast<char *> (&field_name_length), fn_len ))
01164 goto data_read_error;
01165
01166 if (swap)
01167 swap_bytes<4> (&field_name_length);
01168
01169
01170
01171 if (read_mat5_tag (is, swap, fn_type, fn_len) || fn_type != miINT8)
01172 {
01173 error ("load: invalid field name subelement");
01174 goto data_read_error;
01175 }
01176
01177 octave_idx_type n_fields = fn_len/field_name_length;
01178
01179 if (n_fields > 0)
01180 {
01181 fn_len = PAD (fn_len);
01182
01183 OCTAVE_LOCAL_BUFFER (char, elname, fn_len);
01184
01185 if (! is.read (elname, fn_len))
01186 goto data_read_error;
01187
01188 std::vector<Cell> elt (n_fields);
01189
01190 for (octave_idx_type i = 0; i < n_fields; i++)
01191 elt[i] = Cell (dims);
01192
01193 octave_idx_type n = dims.numel ();
01194
01195
01196 for (octave_idx_type j = 0; j < n; j++)
01197 {
01198 for (octave_idx_type i = 0; i < n_fields; i++)
01199 {
01200 octave_value fieldtc;
01201 read_mat5_binary_element (is, filename, swap, global,
01202 fieldtc);
01203 elt[i](j) = fieldtc;
01204 }
01205 }
01206
01207 for (octave_idx_type i = 0; i < n_fields; i++)
01208 {
01209 const char *key = elname + i*field_name_length;
01210
01211 m.assign (key, elt[i]);
01212 }
01213 }
01214
01215 if (isclass)
01216 {
01217 if (classname == "inline")
01218 {
01219
01220
01221 tc =
01222 new octave_fcn_inline (m.contents("expr")(0).string_value(),
01223 m.contents("args")(0).string_value());
01224 }
01225 else
01226 {
01227 octave_class* cls
01228 = new octave_class (m, classname,
01229 std::list<std::string> ());
01230
01231 if (cls->reconstruct_exemplar ())
01232 {
01233
01234 if (! cls->reconstruct_parents ())
01235 warning ("load: unable to reconstruct object inheritance");
01236
01237 tc = cls;
01238 if (load_path::find_method (classname, "loadobj") !=
01239 std::string())
01240 {
01241 octave_value_list tmp = feval ("loadobj", tc, 1);
01242
01243 if (! error_state)
01244 tc = tmp(0);
01245 else
01246 goto data_read_error;
01247 }
01248 }
01249 else
01250 {
01251 tc = m;
01252 warning ("load: element has been converted to a structure");
01253 }
01254 }
01255 }
01256 else
01257 tc = m;
01258 }
01259 break;
01260
01261 case MAT_FILE_INT8_CLASS:
01262 OCTAVE_MAT5_INTEGER_READ (int8NDArray);
01263 break;
01264
01265 case MAT_FILE_UINT8_CLASS:
01266 {
01267 OCTAVE_MAT5_INTEGER_READ (uint8NDArray);
01268
01269
01270
01271
01272
01273 if (logicalvar)
01274 {
01275 uint8NDArray in = tc.uint8_array_value ();
01276 octave_idx_type nel = in.numel ();
01277 boolNDArray out (dims);
01278
01279 for (octave_idx_type i = 0; i < nel; i++)
01280 out (i) = in(i).bool_value ();
01281
01282 tc = out;
01283 }
01284 }
01285 break;
01286
01287 case MAT_FILE_INT16_CLASS:
01288 OCTAVE_MAT5_INTEGER_READ (int16NDArray);
01289 break;
01290
01291 case MAT_FILE_UINT16_CLASS:
01292 OCTAVE_MAT5_INTEGER_READ (uint16NDArray);
01293 break;
01294
01295 case MAT_FILE_INT32_CLASS:
01296 OCTAVE_MAT5_INTEGER_READ (int32NDArray);
01297 break;
01298
01299 case MAT_FILE_UINT32_CLASS:
01300 OCTAVE_MAT5_INTEGER_READ (uint32NDArray);
01301 break;
01302
01303 case MAT_FILE_INT64_CLASS:
01304 OCTAVE_MAT5_INTEGER_READ (int64NDArray);
01305 break;
01306
01307 case MAT_FILE_UINT64_CLASS:
01308 OCTAVE_MAT5_INTEGER_READ (uint64NDArray);
01309 break;
01310
01311
01312 case MAT_FILE_SINGLE_CLASS:
01313 {
01314 FloatNDArray re (dims);
01315
01316
01317
01318 std::streampos tmp_pos;
01319
01320 if (read_mat5_tag (is, swap, type, len))
01321 {
01322 error ("load: reading matrix data for '%s'", retval.c_str ());
01323 goto data_read_error;
01324 }
01325
01326 octave_idx_type n = re.numel ();
01327 tmp_pos = is.tellg ();
01328 read_mat5_binary_data (is, re.fortran_vec (), n, swap,
01329 static_cast<enum mat5_data_type> (type), flt_fmt);
01330
01331 if (! is || error_state)
01332 {
01333 error ("load: reading matrix data for '%s'", retval.c_str ());
01334 goto data_read_error;
01335 }
01336
01337 is.seekg (tmp_pos + static_cast<std::streamoff> (PAD (len)));
01338
01339 if (imag)
01340 {
01341
01342
01343 FloatNDArray im (dims);
01344
01345 if (read_mat5_tag (is, swap, type, len))
01346 {
01347 error ("load: reading matrix data for '%s'", retval.c_str ());
01348 goto data_read_error;
01349 }
01350
01351 n = im.numel ();
01352 read_mat5_binary_data (is, im.fortran_vec (), n, swap,
01353 static_cast<enum mat5_data_type> (type), flt_fmt);
01354
01355 if (! is || error_state)
01356 {
01357 error ("load: reading imaginary matrix data for '%s'",
01358 retval.c_str ());
01359 goto data_read_error;
01360 }
01361
01362 FloatComplexNDArray ctmp (dims);
01363
01364 for (octave_idx_type i = 0; i < n; i++)
01365 ctmp(i) = FloatComplex (re(i), im(i));
01366
01367 tc = ctmp;
01368 }
01369 else
01370 tc = re;
01371 }
01372 break;
01373
01374 case MAT_FILE_CHAR_CLASS:
01375
01376
01377 case MAT_FILE_DOUBLE_CLASS:
01378 default:
01379 {
01380 NDArray re (dims);
01381
01382
01383
01384 std::streampos tmp_pos;
01385
01386 if (read_mat5_tag (is, swap, type, len))
01387 {
01388 error ("load: reading matrix data for '%s'", retval.c_str ());
01389 goto data_read_error;
01390 }
01391
01392 octave_idx_type n = re.numel ();
01393 tmp_pos = is.tellg ();
01394 read_mat5_binary_data (is, re.fortran_vec (), n, swap,
01395 static_cast<enum mat5_data_type> (type), flt_fmt);
01396
01397 if (! is || error_state)
01398 {
01399 error ("load: reading matrix data for '%s'", retval.c_str ());
01400 goto data_read_error;
01401 }
01402
01403 is.seekg (tmp_pos + static_cast<std::streamoff> (PAD (len)));
01404
01405 if (logicalvar)
01406 {
01407
01408
01409
01410
01411 boolNDArray out (dims);
01412
01413 for (octave_idx_type i = 0; i < n; i++)
01414 out (i) = static_cast<bool> (re (i));
01415
01416 tc = out;
01417 }
01418 else if (imag)
01419 {
01420
01421
01422 NDArray im (dims);
01423
01424 if (read_mat5_tag (is, swap, type, len))
01425 {
01426 error ("load: reading matrix data for '%s'", retval.c_str ());
01427 goto data_read_error;
01428 }
01429
01430 n = im.numel ();
01431 read_mat5_binary_data (is, im.fortran_vec (), n, swap,
01432 static_cast<enum mat5_data_type> (type), flt_fmt);
01433
01434 if (! is || error_state)
01435 {
01436 error ("load: reading imaginary matrix data for '%s'",
01437 retval.c_str ());
01438 goto data_read_error;
01439 }
01440
01441 ComplexNDArray ctmp (dims);
01442
01443 for (octave_idx_type i = 0; i < n; i++)
01444 ctmp(i) = Complex (re(i), im(i));
01445
01446 tc = ctmp;
01447 }
01448 else
01449 {
01450 if (arrayclass == MAT_FILE_CHAR_CLASS)
01451 {
01452 if (type == miUTF16 || type == miUTF32)
01453 {
01454 bool found_big_char = false;
01455 for (octave_idx_type i = 0; i < n; i++)
01456 {
01457 if (re(i) > 127) {
01458 re(i) = '?';
01459 found_big_char = true;
01460 }
01461 }
01462
01463 if (found_big_char)
01464 warning ("load: can not read non-ASCII portions of UTF characters; replacing unreadable characters with '?'");
01465 }
01466 else if (type == miUTF8)
01467 {
01468
01469
01470
01471 bool utf8_multi_byte = false;
01472 for (octave_idx_type i = 0; i < n; i++)
01473 {
01474 unsigned char a = static_cast<unsigned char> (re(i));
01475 if (a > 0x7f)
01476 utf8_multi_byte = true;
01477 }
01478
01479 if (utf8_multi_byte)
01480 {
01481 warning ("load: can not read multi-byte encoded UTF8 characters; replacing unreadable characters with '?'");
01482 for (octave_idx_type i = 0; i < n; i++)
01483 {
01484 unsigned char a = static_cast<unsigned char> (re(i));
01485 if (a > 0x7f)
01486 re(i) = '?';
01487 }
01488 }
01489 }
01490 tc = re;
01491 tc = tc.convert_to_str (false, true, '\'');
01492 }
01493 else
01494 tc = re;
01495 }
01496 }
01497 }
01498
01499 is.seekg (pos + static_cast<std::streamoff> (element_length));
01500
01501 if (is.eof ())
01502 is.clear ();
01503
01504 return retval;
01505
01506 data_read_error:
01507 early_read_error:
01508 error ("load: trouble reading binary file '%s'", filename.c_str ());
01509 return std::string ();
01510
01511 skip_ahead:
01512 warning ("skipping over '%s'", retval.c_str ());
01513 is.seekg (pos + static_cast<std::streamoff> (element_length));
01514 return read_mat5_binary_element (is, filename, swap, global, tc);
01515 }
01516
01517 int
01518 read_mat5_binary_file_header (std::istream& is, bool& swap, bool quiet,
01519 const std::string& filename)
01520 {
01521 int16_t version=0, magic=0;
01522 uint64_t subsys_offset;
01523
01524 is.seekg (116, std::ios::beg);
01525 is.read (reinterpret_cast<char *> (&subsys_offset), 8);
01526
01527 is.seekg (124, std::ios::beg);
01528 is.read (reinterpret_cast<char *> (&version), 2);
01529 is.read (reinterpret_cast<char *> (&magic), 2);
01530
01531 if (magic == 0x4d49)
01532 swap = 0;
01533 else if (magic == 0x494d)
01534 swap = 1;
01535 else
01536 {
01537 if (! quiet)
01538 error ("load: can't read binary file");
01539 return -1;
01540 }
01541
01542 if (! swap)
01543 version = ((version >> 8) & 0xff) + ((version & 0xff) << 8);
01544
01545 if (version != 1 && !quiet)
01546 warning ("load: found version %d binary MAT file, "
01547 "but only prepared for version 1", version);
01548
01549 if (swap)
01550 swap_bytes<8> (&subsys_offset, 1);
01551
01552 if (subsys_offset != 0x2020202020202020ULL && subsys_offset != 0ULL)
01553 {
01554
01555 is.seekg (subsys_offset, std::ios::beg);
01556
01557 octave_value tc;
01558 bool global;
01559 read_mat5_binary_element (is, filename, swap, global, tc);
01560
01561 if (!is || error_state)
01562 return -1;
01563
01564 if (tc.is_uint8_type ())
01565 {
01566 const uint8NDArray itmp = tc.uint8_array_value();
01567 octave_idx_type ilen = itmp.numel ();
01568
01569
01570 std::string outbuf (ilen - 7, ' ');
01571
01572
01573 char *ctmp = const_cast<char *> (outbuf.c_str ());
01574 for (octave_idx_type j = 8; j < ilen; j++)
01575 ctmp[j-8] = itmp(j).char_value ();
01576
01577 std::istringstream fh_ws (outbuf);
01578
01579 read_mat5_binary_element (fh_ws, filename, swap, global, subsys_ov);
01580
01581 if (error_state)
01582 return -1;
01583 }
01584 else
01585 return -1;
01586
01587
01588 is.seekg (128, std::ios::beg);
01589 }
01590
01591 return 0;
01592 }
01593
01594 static int
01595 write_mat5_tag (std::ostream& is, int type, octave_idx_type bytes)
01596 {
01597 int32_t temp;
01598
01599 if (bytes > 0 && bytes <= 4)
01600 temp = (bytes << 16) + type;
01601 else
01602 {
01603 temp = type;
01604 if (! is.write (reinterpret_cast<char *> (&temp), 4))
01605 goto data_write_error;
01606 temp = bytes;
01607 }
01608
01609 if (! is.write (reinterpret_cast<char *> (&temp), 4))
01610 goto data_write_error;
01611
01612 return 0;
01613
01614 data_write_error:
01615 return 1;
01616 }
01617
01618
01619
01620
01621 #define MAT5_DO_WRITE(TYPE, data, count, stream) \
01622 do \
01623 { \
01624 OCTAVE_LOCAL_BUFFER (TYPE, ptr, count); \
01625 for (octave_idx_type i = 0; i < count; i++) \
01626 ptr[i] = static_cast<TYPE> (data[i]); \
01627 stream.write (reinterpret_cast<char *> (ptr), count * sizeof (TYPE)); \
01628 } \
01629 while (0)
01630
01631
01632
01633 static void
01634 write_mat5_array (std::ostream& os, const NDArray& m, bool save_as_floats)
01635 {
01636 save_type st = LS_DOUBLE;
01637 const double *data = m.data ();
01638
01639 if (save_as_floats)
01640 {
01641 if (m.too_large_for_float ())
01642 {
01643 warning ("save: some values too large to save as floats --");
01644 warning ("save: saving as doubles instead");
01645 }
01646 else
01647 st = LS_FLOAT;
01648 }
01649
01650 double max_val, min_val;
01651 if (m.all_integers (max_val, min_val))
01652 st = get_save_type (max_val, min_val);
01653
01654 mat5_data_type mst;
01655 int size;
01656 switch (st)
01657 {
01658 default:
01659 case LS_DOUBLE: mst = miDOUBLE; size = 8; break;
01660 case LS_FLOAT: mst = miSINGLE; size = 4; break;
01661 case LS_U_CHAR: mst = miUINT8; size = 1; break;
01662 case LS_U_SHORT: mst = miUINT16; size = 2; break;
01663 case LS_U_INT: mst = miUINT32; size = 4; break;
01664 case LS_CHAR: mst = miINT8; size = 1; break;
01665 case LS_SHORT: mst = miINT16; size = 2; break;
01666 case LS_INT: mst = miINT32; size = 4; break;
01667 }
01668
01669 octave_idx_type nel = m.numel ();
01670 octave_idx_type len = nel*size;
01671
01672 write_mat5_tag (os, mst, len);
01673
01674 {
01675 switch (st)
01676 {
01677 case LS_U_CHAR:
01678 MAT5_DO_WRITE (uint8_t, data, nel, os);
01679 break;
01680
01681 case LS_U_SHORT:
01682 MAT5_DO_WRITE (uint16_t, data, nel, os);
01683 break;
01684
01685 case LS_U_INT:
01686 MAT5_DO_WRITE (uint32_t, data, nel, os);
01687 break;
01688
01689 case LS_U_LONG:
01690 MAT5_DO_WRITE (uint64_t, data, nel, os);
01691 break;
01692
01693 case LS_CHAR:
01694 MAT5_DO_WRITE (int8_t, data, nel, os);
01695 break;
01696
01697 case LS_SHORT:
01698 MAT5_DO_WRITE (int16_t, data, nel, os);
01699 break;
01700
01701 case LS_INT:
01702 MAT5_DO_WRITE (int32_t, data, nel, os);
01703 break;
01704
01705 case LS_LONG:
01706 MAT5_DO_WRITE (int64_t, data, nel, os);
01707 break;
01708
01709 case LS_FLOAT:
01710 MAT5_DO_WRITE (float, data, nel, os);
01711 break;
01712
01713 case LS_DOUBLE:
01714 os.write (reinterpret_cast<const char *> (data), len);
01715 break;
01716
01717 default:
01718 (*current_liboctave_error_handler)
01719 ("unrecognized data format requested");
01720 break;
01721 }
01722 }
01723 if (PAD (len) > len)
01724 {
01725 static char buf[9]="\x00\x00\x00\x00\x00\x00\x00\x00";
01726 os.write (buf, PAD (len) - len);
01727 }
01728 }
01729
01730 static void
01731 write_mat5_array (std::ostream& os, const FloatNDArray& m, bool)
01732 {
01733 save_type st = LS_FLOAT;
01734 const float *data = m.data ();
01735
01736 float max_val, min_val;
01737 if (m.all_integers (max_val, min_val))
01738 st = get_save_type (max_val, min_val);
01739
01740 mat5_data_type mst;
01741 int size;
01742 switch (st)
01743 {
01744 default:
01745 case LS_DOUBLE: mst = miDOUBLE; size = 8; break;
01746 case LS_FLOAT: mst = miSINGLE; size = 4; break;
01747 case LS_U_CHAR: mst = miUINT8; size = 1; break;
01748 case LS_U_SHORT: mst = miUINT16; size = 2; break;
01749 case LS_U_INT: mst = miUINT32; size = 4; break;
01750 case LS_CHAR: mst = miINT8; size = 1; break;
01751 case LS_SHORT: mst = miINT16; size = 2; break;
01752 case LS_INT: mst = miINT32; size = 4; break;
01753 }
01754
01755 octave_idx_type nel = m.numel ();
01756 octave_idx_type len = nel*size;
01757
01758 write_mat5_tag (os, mst, len);
01759
01760 {
01761 switch (st)
01762 {
01763 case LS_U_CHAR:
01764 MAT5_DO_WRITE (uint8_t, data, nel, os);
01765 break;
01766
01767 case LS_U_SHORT:
01768 MAT5_DO_WRITE (uint16_t, data, nel, os);
01769 break;
01770
01771 case LS_U_INT:
01772 MAT5_DO_WRITE (uint32_t, data, nel, os);
01773 break;
01774
01775 case LS_U_LONG:
01776 MAT5_DO_WRITE (uint64_t, data, nel, os);
01777 break;
01778
01779 case LS_CHAR:
01780 MAT5_DO_WRITE (int8_t, data, nel, os);
01781 break;
01782
01783 case LS_SHORT:
01784 MAT5_DO_WRITE (int16_t, data, nel, os);
01785 break;
01786
01787 case LS_INT:
01788 MAT5_DO_WRITE (int32_t, data, nel, os);
01789 break;
01790
01791 case LS_LONG:
01792 MAT5_DO_WRITE (int64_t, data, nel, os);
01793 break;
01794
01795 case LS_FLOAT:
01796 os.write (reinterpret_cast<const char *> (data), len);
01797 break;
01798
01799 case LS_DOUBLE:
01800 MAT5_DO_WRITE (double, data, nel, os);
01801 break;
01802
01803 default:
01804 (*current_liboctave_error_handler)
01805 ("unrecognized data format requested");
01806 break;
01807 }
01808 }
01809 if (PAD (len) > len)
01810 {
01811 static char buf[9]="\x00\x00\x00\x00\x00\x00\x00\x00";
01812 os.write (buf, PAD (len) - len);
01813 }
01814 }
01815
01816 template <class T>
01817 void
01818 write_mat5_integer_data (std::ostream& os, const T *m, int size,
01819 octave_idx_type nel)
01820 {
01821 mat5_data_type mst;
01822 unsigned len;
01823
01824 switch (size)
01825 {
01826 case 1:
01827 mst = miUINT8;
01828 break;
01829 case 2:
01830 mst = miUINT16;
01831 break;
01832 case 4:
01833 mst = miUINT32;
01834 break;
01835 case 8:
01836 mst = miUINT64;
01837 break;
01838 case -1:
01839 mst = miINT8;
01840 size = - size;
01841 break;
01842 case -2:
01843 mst = miINT16;
01844 size = - size;
01845 break;
01846 case -4:
01847 mst = miINT32;
01848 size = - size;
01849 break;
01850 case -8:
01851 default:
01852 mst = miINT64;
01853 size = - size;
01854 break;
01855 }
01856
01857 len = nel*size;
01858 write_mat5_tag (os, mst, len);
01859
01860 os.write (reinterpret_cast<const char *> (m), len);
01861
01862 if (PAD (len) > len)
01863 {
01864 static char buf[9]="\x00\x00\x00\x00\x00\x00\x00\x00";
01865 os.write (buf, PAD (len) - len);
01866 }
01867 }
01868
01869 template void
01870 write_mat5_integer_data (std::ostream& os, const octave_int8 *m,
01871 int size, octave_idx_type nel);
01872
01873 template void
01874 write_mat5_integer_data (std::ostream& os, const octave_int16 *m,
01875 int size, octave_idx_type nel);
01876
01877 template void
01878 write_mat5_integer_data (std::ostream& os, const octave_int32 *m,
01879 int size, octave_idx_type nel);
01880
01881 template void
01882 write_mat5_integer_data (std::ostream& os, const octave_int64 *m,
01883 int size, octave_idx_type nel);
01884
01885 template void
01886 write_mat5_integer_data (std::ostream& os, const octave_uint8 *m,
01887 int size, octave_idx_type nel);
01888
01889 template void
01890 write_mat5_integer_data (std::ostream& os, const octave_uint16 *m,
01891 int size, octave_idx_type nel);
01892
01893 template void
01894 write_mat5_integer_data (std::ostream& os, const octave_uint32 *m,
01895 int size, octave_idx_type nel);
01896
01897 template void
01898 write_mat5_integer_data (std::ostream& os, const octave_uint64 *m,
01899 int size, octave_idx_type nel);
01900
01901 template void
01902 write_mat5_integer_data (std::ostream& os, const int *m,
01903 int size, octave_idx_type nel);
01904
01905
01906
01907
01908 static bool
01909 write_mat5_cell_array (std::ostream& os, const Cell& cell,
01910 bool mark_as_global, bool save_as_floats)
01911 {
01912 octave_idx_type nel = cell.numel ();
01913
01914 for (octave_idx_type i = 0; i < nel; i++)
01915 {
01916 octave_value ov = cell(i);
01917
01918 if (! save_mat5_binary_element (os, ov, "", mark_as_global,
01919 false, save_as_floats))
01920 return false;
01921 }
01922
01923 return true;
01924 }
01925
01926 int
01927 save_mat5_array_length (const double* val, octave_idx_type nel,
01928 bool save_as_floats)
01929 {
01930 if (nel > 0)
01931 {
01932 int size = 8;
01933
01934 if (save_as_floats)
01935 {
01936 bool too_large_for_float = false;
01937 for (octave_idx_type i = 0; i < nel; i++)
01938 {
01939 double tmp = val [i];
01940
01941 if (! (xisnan (tmp) || xisinf (tmp))
01942 && fabs (tmp) > FLT_MAX)
01943 {
01944 too_large_for_float = true;
01945 break;
01946 }
01947 }
01948
01949 if (!too_large_for_float)
01950 size = 4;
01951 }
01952
01953
01954
01955
01956
01957
01958
01959
01960
01961
01962
01963
01964
01965
01966
01967
01968
01969
01970
01971
01972
01973
01974
01975
01976
01977
01978
01979
01980
01981
01982
01983
01984
01985
01986
01987
01988
01989
01990
01991
01992
01993
01994 return 8 + nel * size;
01995 }
01996 else
01997 return 8;
01998 }
01999
02000 int
02001 save_mat5_array_length (const float* , octave_idx_type nel, bool)
02002 {
02003 if (nel > 0)
02004 {
02005 int size = 4;
02006
02007
02008
02009
02010
02011
02012
02013
02014
02015
02016
02017
02018
02019
02020
02021
02022
02023
02024
02025
02026
02027
02028
02029
02030
02031
02032
02033
02034
02035
02036
02037
02038
02039
02040
02041
02042
02043
02044
02045
02046
02047
02048
02049
02050
02051 return PAD ((nel > 0 && nel * size <= 4 ? 4 : 8) + nel * size);
02052 }
02053 else
02054 return 8;
02055 }
02056
02057 int
02058 save_mat5_array_length (const Complex* val, octave_idx_type nel,
02059 bool save_as_floats)
02060 {
02061 int ret;
02062
02063 OCTAVE_LOCAL_BUFFER (double, tmp, nel);
02064
02065 for (octave_idx_type i = 1; i < nel; i++)
02066 tmp[i] = std::real (val[i]);
02067
02068 ret = save_mat5_array_length (tmp, nel, save_as_floats);
02069
02070 for (octave_idx_type i = 1; i < nel; i++)
02071 tmp[i] = std::imag (val[i]);
02072
02073 ret += save_mat5_array_length (tmp, nel, save_as_floats);
02074
02075 return ret;
02076 }
02077
02078 int
02079 save_mat5_array_length (const FloatComplex* val, octave_idx_type nel,
02080 bool save_as_floats)
02081 {
02082 int ret;
02083
02084 OCTAVE_LOCAL_BUFFER (float, tmp, nel);
02085
02086 for (octave_idx_type i = 1; i < nel; i++)
02087 tmp[i] = std::real (val[i]);
02088
02089 ret = save_mat5_array_length (tmp, nel, save_as_floats);
02090
02091 for (octave_idx_type i = 1; i < nel; i++)
02092 tmp[i] = std::imag (val[i]);
02093
02094 ret += save_mat5_array_length (tmp, nel, save_as_floats);
02095
02096 return ret;
02097 }
02098
02099 int
02100 save_mat5_element_length (const octave_value& tc, const std::string& name,
02101 bool save_as_floats, bool mat7_format)
02102 {
02103 size_t max_namelen = (mat7_format ? 63 : 31);
02104 size_t len = name.length ();
02105 std::string cname = tc.class_name ();
02106 int ret = 32;
02107
02108 if (len > 4)
02109 ret += PAD (len > max_namelen ? max_namelen : len);
02110
02111 ret += PAD (4 * tc.ndims ());
02112
02113 if (tc.is_string ())
02114 {
02115 charNDArray chm = tc.char_array_value ();
02116 ret += 8;
02117 if (chm.numel () > 2)
02118 ret += PAD (2 * chm.numel ());
02119 }
02120 else if (tc.is_sparse_type ())
02121 {
02122 if (tc.is_complex_type ())
02123 {
02124 const SparseComplexMatrix m = tc.sparse_complex_matrix_value ();
02125 octave_idx_type nc = m.cols ();
02126 octave_idx_type nnz = m.nnz ();
02127
02128 ret += 16 + save_mat5_array_length (m.data (), nnz, save_as_floats);
02129 if (nnz > 1)
02130 ret += PAD (nnz * sizeof (int32_t));
02131 if (nc > 0)
02132 ret += PAD ((nc + 1) * sizeof (int32_t));
02133 }
02134 else
02135 {
02136 const SparseMatrix m = tc.sparse_matrix_value ();
02137 octave_idx_type nc = m.cols ();
02138 octave_idx_type nnz = m.nnz ();
02139
02140 ret += 16 + save_mat5_array_length (m.data (), nnz, save_as_floats);
02141 if (nnz > 1)
02142 ret += PAD (nnz * sizeof (int32_t));
02143 if (nc > 0)
02144 ret += PAD ((nc + 1) * sizeof (int32_t));
02145 }
02146 }
02147
02148 #define INT_LEN(nel, size) \
02149 { \
02150 ret += 8; \
02151 octave_idx_type sz = nel * size; \
02152 if (sz > 4) \
02153 ret += PAD (sz); \
02154 }
02155
02156 else if (cname == "int8")
02157 INT_LEN (tc.int8_array_value ().numel (), 1)
02158 else if (cname == "int16")
02159 INT_LEN (tc.int16_array_value ().numel (), 2)
02160 else if (cname == "int32")
02161 INT_LEN (tc.int32_array_value ().numel (), 4)
02162 else if (cname == "int64")
02163 INT_LEN (tc.int64_array_value ().numel (), 8)
02164 else if (cname == "uint8")
02165 INT_LEN (tc.uint8_array_value ().numel (), 1)
02166 else if (cname == "uint16")
02167 INT_LEN (tc.uint16_array_value ().numel (), 2)
02168 else if (cname == "uint32")
02169 INT_LEN (tc.uint32_array_value ().numel (), 4)
02170 else if (cname == "uint64")
02171 INT_LEN (tc.uint64_array_value ().numel (), 8)
02172 else if (tc.is_bool_type ())
02173 INT_LEN (tc.bool_array_value ().numel (), 1)
02174 else if (tc.is_real_scalar () || tc.is_real_matrix () || tc.is_range ())
02175 {
02176 if (tc.is_single_type ())
02177 {
02178 const FloatNDArray m = tc.float_array_value ();
02179 ret += save_mat5_array_length (m.fortran_vec (), m.numel (),
02180 save_as_floats);
02181 }
02182 else
02183 {
02184 const NDArray m = tc.array_value ();
02185 ret += save_mat5_array_length (m.fortran_vec (), m.numel (),
02186 save_as_floats);
02187 }
02188 }
02189 else if (tc.is_cell ())
02190 {
02191 Cell cell = tc.cell_value ();
02192 octave_idx_type nel = cell.numel ();
02193
02194 for (int i = 0; i < nel; i++)
02195 ret += 8 +
02196 save_mat5_element_length (cell (i), "", save_as_floats, mat7_format);
02197 }
02198 else if (tc.is_complex_scalar () || tc.is_complex_matrix ())
02199 {
02200 if (tc.is_single_type ())
02201 {
02202 const FloatComplexNDArray m = tc.float_complex_array_value ();
02203 ret += save_mat5_array_length (m.fortran_vec (), m.numel (),
02204 save_as_floats);
02205 }
02206 else
02207 {
02208 const ComplexNDArray m = tc.complex_array_value ();
02209 ret += save_mat5_array_length (m.fortran_vec (), m.numel (),
02210 save_as_floats);
02211 }
02212 }
02213 else if (tc.is_map () || tc.is_inline_function () || tc.is_object ())
02214 {
02215 int fieldcnt = 0;
02216 const Octave_map m = tc.map_value ();
02217 octave_idx_type nel = m.numel ();
02218
02219 if (tc.is_inline_function ())
02220
02221 ret += 8 + PAD (6 > max_namelen ? max_namelen : 6);
02222 else if (tc.is_object ())
02223 {
02224 size_t classlen = tc.class_name (). length ();
02225
02226 ret += 8 + PAD (classlen > max_namelen ? max_namelen : classlen);
02227 }
02228
02229 for (Octave_map::const_iterator i = m.begin (); i != m.end (); i++)
02230 fieldcnt++;
02231
02232 ret += 16 + fieldcnt * (max_namelen + 1);
02233
02234
02235 for (octave_idx_type j = 0; j < nel; j++)
02236 {
02237
02238 for (Octave_map::const_iterator i = m.begin (); i != m.end (); i++)
02239 {
02240 const Cell elts = m.contents (i);
02241
02242 ret += 8 + save_mat5_element_length (elts(j), "",
02243 save_as_floats, mat7_format);
02244 }
02245 }
02246 }
02247 else
02248 ret = -1;
02249
02250 return ret;
02251 }
02252
02253 static void
02254 write_mat5_sparse_index_vector (std::ostream& os,
02255 const octave_idx_type *idx,
02256 octave_idx_type nel)
02257 {
02258 int tmp = sizeof (int32_t);
02259
02260 OCTAVE_LOCAL_BUFFER (int32_t, tmp_idx, nel);
02261
02262 for (octave_idx_type i = 0; i < nel; i++)
02263 tmp_idx[i] = idx[i];
02264
02265 write_mat5_integer_data (os, tmp_idx, -tmp, nel);
02266 }
02267
02268 static void
02269 gripe_dim_too_large (const std::string& name)
02270 {
02271 warning ("save: skipping %s: dimension too large for MAT format",
02272 name.c_str ());
02273 }
02274
02275
02276
02277
02278 bool
02279 save_mat5_binary_element (std::ostream& os,
02280 const octave_value& tc, const std::string& name,
02281 bool mark_as_global, bool mat7_format,
02282 bool save_as_floats, bool compressing)
02283 {
02284 int32_t flags = 0;
02285 int32_t nnz_32 = 0;
02286 std::string cname = tc.class_name ();
02287 size_t max_namelen = (mat7_format ? 63 : 31);
02288
02289 dim_vector dv = tc.dims ();
02290 int nd = tc.ndims ();
02291 int dim_len = 4*nd;
02292
02293 static octave_idx_type max_dim_val = std::numeric_limits<int32_t>::max ();
02294
02295 for (int i = 0; i < nd; i++)
02296 {
02297 if (dv(i) > max_dim_val)
02298 {
02299 gripe_dim_too_large (name);
02300 goto skip_to_next;
02301 }
02302 }
02303
02304 if (tc.is_sparse_type ())
02305 {
02306 octave_idx_type nnz;
02307 octave_idx_type nc;
02308
02309 if (tc.is_complex_type ())
02310 {
02311 SparseComplexMatrix scm = tc.sparse_complex_matrix_value ();
02312 nnz = scm.nzmax ();
02313 nc = scm.cols ();
02314 }
02315 else
02316 {
02317 SparseMatrix sm = tc.sparse_matrix_value ();
02318 nnz = sm.nzmax ();
02319 nc = sm.cols ();
02320 }
02321
02322 if (nnz > max_dim_val || nc + 1 > max_dim_val)
02323 {
02324 gripe_dim_too_large (name);
02325 goto skip_to_next;
02326 }
02327
02328 nnz_32 = nnz;
02329 }
02330 else if (dv.numel () > max_dim_val)
02331 {
02332 gripe_dim_too_large (name);
02333 goto skip_to_next;
02334 }
02335
02336 #ifdef HAVE_ZLIB
02337 if (mat7_format && !compressing)
02338 {
02339 bool ret = false;
02340
02341 std::ostringstream buf;
02342
02343
02344
02345 ret = save_mat5_binary_element (buf, tc, name, mark_as_global, true,
02346 save_as_floats, true);
02347
02348 if (ret)
02349 {
02350
02351
02352 std::string buf_str = buf.str ();
02353 uLongf srcLen = buf_str.length ();
02354 uLongf destLen = srcLen * 101 / 100 + 12;
02355 OCTAVE_LOCAL_BUFFER (char, out_buf, destLen);
02356
02357 if (compress (reinterpret_cast<Bytef *> (out_buf), &destLen,
02358 reinterpret_cast<const Bytef *> (buf_str.c_str ()), srcLen) == Z_OK)
02359 {
02360 write_mat5_tag (os, miCOMPRESSED,
02361 static_cast<octave_idx_type> (destLen));
02362
02363 os.write (out_buf, destLen);
02364 }
02365 else
02366 {
02367 error ("save: error compressing data element");
02368 ret = false;
02369 }
02370 }
02371
02372 return ret;
02373 }
02374 #endif
02375
02376 write_mat5_tag (os, miMATRIX, save_mat5_element_length
02377 (tc, name, save_as_floats, mat7_format));
02378
02379
02380 write_mat5_tag (os, miUINT32, 8);
02381
02382 if (tc.is_bool_type ())
02383 flags |= 0x0200;
02384
02385 if (mark_as_global)
02386 flags |= 0x0400;
02387
02388 if (tc.is_complex_scalar () || tc.is_complex_matrix ())
02389 flags |= 0x0800;
02390
02391 if (tc.is_string ())
02392 flags |= MAT_FILE_CHAR_CLASS;
02393 else if (cname == "int8")
02394 flags |= MAT_FILE_INT8_CLASS;
02395 else if (cname == "int16")
02396 flags |= MAT_FILE_INT16_CLASS;
02397 else if (cname == "int32")
02398 flags |= MAT_FILE_INT32_CLASS;
02399 else if (cname == "int64")
02400 flags |= MAT_FILE_INT64_CLASS;
02401 else if (cname == "uint8" || tc.is_bool_type ())
02402 flags |= MAT_FILE_UINT8_CLASS;
02403 else if (cname == "uint16")
02404 flags |= MAT_FILE_UINT16_CLASS;
02405 else if (cname == "uint32")
02406 flags |= MAT_FILE_UINT32_CLASS;
02407 else if (cname == "uint64")
02408 flags |= MAT_FILE_UINT64_CLASS;
02409 else if (tc.is_sparse_type ())
02410 flags |= MAT_FILE_SPARSE_CLASS;
02411 else if (tc.is_real_scalar () || tc.is_real_matrix () || tc.is_range ()
02412 || tc.is_complex_scalar () || tc.is_complex_matrix ())
02413 {
02414 if (tc.is_single_type ())
02415 flags |= MAT_FILE_SINGLE_CLASS;
02416 else
02417 flags |= MAT_FILE_DOUBLE_CLASS;
02418 }
02419 else if (tc.is_map ())
02420 flags |= MAT_FILE_STRUCT_CLASS;
02421 else if (tc.is_cell ())
02422 flags |= MAT_FILE_CELL_CLASS;
02423 else if (tc.is_inline_function () || tc.is_object ())
02424 flags |= MAT_FILE_OBJECT_CLASS;
02425 else
02426 {
02427 gripe_wrong_type_arg ("save", tc, false);
02428 goto error_cleanup;
02429 }
02430
02431 os.write (reinterpret_cast<char *> (&flags), 4);
02432 os.write (reinterpret_cast<char *> (&nnz_32), 4);
02433
02434 write_mat5_tag (os, miINT32, dim_len);
02435
02436 for (int i = 0; i < nd; i++)
02437 {
02438 int32_t n = dv(i);
02439 os.write (reinterpret_cast<char *> (&n), 4);
02440 }
02441
02442 if (PAD (dim_len) > dim_len)
02443 {
02444 static char buf[9]="\x00\x00\x00\x00\x00\x00\x00\x00";
02445 os.write (buf, PAD (dim_len) - dim_len);
02446 }
02447
02448
02449 {
02450 size_t namelen = name.length ();
02451
02452 if (namelen > max_namelen)
02453 namelen = max_namelen;
02454
02455 int paddedlength = PAD (namelen);
02456
02457 write_mat5_tag (os, miINT8, namelen);
02458 OCTAVE_LOCAL_BUFFER (char, paddedname, paddedlength);
02459 memset (paddedname, 0, paddedlength);
02460 strncpy (paddedname, name.c_str (), namelen);
02461 os.write (paddedname, paddedlength);
02462 }
02463
02464
02465 if (tc.is_string ())
02466 {
02467 charNDArray chm = tc.char_array_value ();
02468 octave_idx_type nel = chm.numel ();
02469 octave_idx_type len = nel*2;
02470 octave_idx_type paddedlength = PAD (len);
02471
02472 OCTAVE_LOCAL_BUFFER (int16_t, buf, nel+3);
02473 write_mat5_tag (os, miUINT16, len);
02474
02475 const char *s = chm.data ();
02476
02477 for (octave_idx_type i = 0; i < nel; i++)
02478 buf[i] = *s++ & 0x00FF;
02479
02480 os.write (reinterpret_cast<char *> (buf), len);
02481
02482 if (paddedlength > len)
02483 {
02484 static char padbuf[9]="\x00\x00\x00\x00\x00\x00\x00\x00";
02485 os.write (padbuf, paddedlength - len);
02486 }
02487 }
02488 else if (tc.is_sparse_type ())
02489 {
02490 if (tc.is_complex_type ())
02491 {
02492 const SparseComplexMatrix m = tc.sparse_complex_matrix_value ();
02493 octave_idx_type nnz = m.nnz ();
02494 octave_idx_type nc = m.cols ();
02495
02496 write_mat5_sparse_index_vector (os, m.ridx (), nnz);
02497 write_mat5_sparse_index_vector (os, m.cidx (), nc + 1);
02498
02499 NDArray buf (dim_vector (nnz, 1));
02500
02501 for (octave_idx_type i = 0; i < nnz; i++)
02502 buf (i) = std::real (m.data (i));
02503
02504 write_mat5_array (os, buf, save_as_floats);
02505
02506 for (octave_idx_type i = 0; i < nnz; i++)
02507 buf (i) = std::imag (m.data (i));
02508
02509 write_mat5_array (os, buf, save_as_floats);
02510 }
02511 else
02512 {
02513 const SparseMatrix m = tc.sparse_matrix_value ();
02514 octave_idx_type nnz = m.nnz ();
02515 octave_idx_type nc = m.cols ();
02516
02517 write_mat5_sparse_index_vector (os, m.ridx (), nnz);
02518 write_mat5_sparse_index_vector (os, m.cidx (), nc + 1);
02519
02520
02521
02522 NDArray buf (dim_vector (nnz, 1));
02523
02524 for (int i = 0; i < nnz; i++)
02525 buf (i) = m.data (i);
02526
02527 write_mat5_array (os, buf, save_as_floats);
02528 }
02529 }
02530 else if (cname == "int8")
02531 {
02532 int8NDArray m = tc.int8_array_value ();
02533
02534 write_mat5_integer_data (os, m.fortran_vec (), -1, m.numel ());
02535 }
02536 else if (cname == "int16")
02537 {
02538 int16NDArray m = tc.int16_array_value ();
02539
02540 write_mat5_integer_data (os, m.fortran_vec (), -2, m.numel ());
02541 }
02542 else if (cname == "int32")
02543 {
02544 int32NDArray m = tc.int32_array_value ();
02545
02546 write_mat5_integer_data (os, m.fortran_vec (), -4, m.numel ());
02547 }
02548 else if (cname == "int64")
02549 {
02550 int64NDArray m = tc.int64_array_value ();
02551
02552 write_mat5_integer_data (os, m.fortran_vec (), -8, m.numel ());
02553 }
02554 else if (cname == "uint8")
02555 {
02556 uint8NDArray m = tc.uint8_array_value ();
02557
02558 write_mat5_integer_data (os, m.fortran_vec (), 1, m.numel ());
02559 }
02560 else if (cname == "uint16")
02561 {
02562 uint16NDArray m = tc.uint16_array_value ();
02563
02564 write_mat5_integer_data (os, m.fortran_vec (), 2, m.numel ());
02565 }
02566 else if (cname == "uint32")
02567 {
02568 uint32NDArray m = tc.uint32_array_value ();
02569
02570 write_mat5_integer_data (os, m.fortran_vec (), 4, m.numel ());
02571 }
02572 else if (cname == "uint64")
02573 {
02574 uint64NDArray m = tc.uint64_array_value ();
02575
02576 write_mat5_integer_data (os, m.fortran_vec (), 8, m.numel ());
02577 }
02578 else if (tc.is_bool_type ())
02579 {
02580 uint8NDArray m (tc.bool_array_value ());
02581
02582 write_mat5_integer_data (os, m.fortran_vec (), 1, m.numel ());
02583 }
02584 else if (tc.is_real_scalar () || tc.is_real_matrix () || tc.is_range ())
02585 {
02586 if (tc.is_single_type ())
02587 {
02588 FloatNDArray m = tc.float_array_value ();
02589
02590 write_mat5_array (os, m, save_as_floats);
02591 }
02592 else
02593 {
02594 NDArray m = tc.array_value ();
02595
02596 write_mat5_array (os, m, save_as_floats);
02597 }
02598 }
02599 else if (tc.is_cell ())
02600 {
02601 Cell cell = tc.cell_value ();
02602
02603 if (! write_mat5_cell_array (os, cell, mark_as_global, save_as_floats))
02604 goto error_cleanup;
02605 }
02606 else if (tc.is_complex_scalar () || tc.is_complex_matrix ())
02607 {
02608 if (tc.is_single_type ())
02609 {
02610 FloatComplexNDArray m_cmplx = tc.float_complex_array_value ();
02611
02612 write_mat5_array (os, ::real (m_cmplx), save_as_floats);
02613 write_mat5_array (os, ::imag (m_cmplx), save_as_floats);
02614 }
02615 else
02616 {
02617 ComplexNDArray m_cmplx = tc.complex_array_value ();
02618
02619 write_mat5_array (os, ::real (m_cmplx), save_as_floats);
02620 write_mat5_array (os, ::imag (m_cmplx), save_as_floats);
02621 }
02622 }
02623 else if (tc.is_map () || tc.is_inline_function() || tc.is_object ())
02624 {
02625 if (tc.is_inline_function () || tc.is_object ())
02626 {
02627 std::string classname = tc.is_object() ? tc.class_name () : "inline";
02628 size_t namelen = classname.length ();
02629
02630 if (namelen > max_namelen)
02631 namelen = max_namelen;
02632
02633 int paddedlength = PAD (namelen);
02634
02635 write_mat5_tag (os, miINT8, namelen);
02636 OCTAVE_LOCAL_BUFFER (char, paddedname, paddedlength);
02637 memset (paddedname, 0, paddedlength);
02638 strncpy (paddedname, classname.c_str (), namelen);
02639 os.write (paddedname, paddedlength);
02640 }
02641
02642 Octave_map m;
02643
02644 if (tc.is_object () &&
02645 load_path::find_method (tc.class_name (), "saveobj") != std::string())
02646 {
02647 octave_value_list tmp = feval ("saveobj", tc, 1);
02648 if (! error_state)
02649 m = tmp(0).map_value ();
02650 else
02651 goto error_cleanup;
02652 }
02653 else
02654 m = tc.map_value ();
02655
02656
02657
02658 {
02659 char buf[64];
02660 int32_t maxfieldnamelength = max_namelen + 1;
02661
02662 octave_idx_type nf = m.nfields ();
02663
02664 write_mat5_tag (os, miINT32, 4);
02665 os.write (reinterpret_cast<char *> (&maxfieldnamelength), 4);
02666 write_mat5_tag (os, miINT8, nf*maxfieldnamelength);
02667
02668
02669
02670 string_vector keys = m.keys ();
02671
02672 for (octave_idx_type i = 0; i < nf; i++)
02673 {
02674 std::string key = keys(i);
02675
02676
02677 memset (buf, 0, max_namelen + 1);
02678
02679 strncpy (buf, key.c_str (), max_namelen);
02680 os.write (buf, max_namelen + 1);
02681 }
02682
02683 octave_idx_type len = m.numel ();
02684
02685
02686
02687 std::vector<const octave_value *> elts (nf);
02688 for (octave_idx_type i = 0; i < nf; i++)
02689 elts[i] = m.contents (keys(i)).data ();
02690
02691 for (octave_idx_type j = 0; j < len; j++)
02692 {
02693
02694
02695
02696
02697 for (octave_idx_type i = 0; i < nf; i++)
02698 {
02699 bool retval2 = save_mat5_binary_element (os, elts[i][j], "",
02700 mark_as_global,
02701 false,
02702 save_as_floats);
02703 if (! retval2)
02704 goto error_cleanup;
02705 }
02706 }
02707 }
02708 }
02709 else
02710 gripe_wrong_type_arg ("save", tc, false);
02711
02712 skip_to_next:
02713 return true;
02714
02715 error_cleanup:
02716 error ("save: error while writing '%s' to MAT file", name.c_str ());
02717
02718 return false;
02719 }