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 #if defined (HAVE_HDF5)
00030
00031 #include <cfloat>
00032 #include <cstring>
00033 #include <cctype>
00034
00035 #include <fstream>
00036 #include <iomanip>
00037 #include <iostream>
00038 #include <string>
00039 #include <vector>
00040
00041 #include "byte-swap.h"
00042 #include "data-conv.h"
00043 #include "file-ops.h"
00044 #include "glob-match.h"
00045 #include "lo-mappers.h"
00046 #include "mach-info.h"
00047 #include "oct-env.h"
00048 #include "oct-time.h"
00049 #include "quit.h"
00050 #include "str-vec.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 "oct-obj.h"
00059 #include "oct-map.h"
00060 #include "ov-cell.h"
00061 #include "pager.h"
00062 #include "pt-exp.h"
00063 #include "sysdep.h"
00064 #include "unwind-prot.h"
00065 #include "utils.h"
00066 #include "variables.h"
00067 #include "version.h"
00068 #include "dMatrix.h"
00069 #include "ov-lazy-idx.h"
00070
00071 #include "ls-utils.h"
00072 #include "ls-hdf5.h"
00073
00074 static std::string
00075 make_valid_identifier (const std::string& nm)
00076 {
00077 std::string retval;
00078
00079 size_t nm_len = nm.length ();
00080
00081 if (nm_len > 0)
00082 {
00083 if (! isalpha (nm[0]))
00084 retval += '_';
00085
00086 for (size_t i = 0; i < nm_len; i++)
00087 {
00088 char c = nm[i];
00089 retval += (isalnum (c) || c == '_') ? c : '_';
00090 }
00091 }
00092
00093 return retval;
00094 }
00095
00096
00097
00098 #define HAVE_HDF5_INT2FLOAT_CONVERSIONS 0
00099
00100
00101
00102
00103
00104
00105 bool
00106 hdf5_types_compatible (hid_t t1, hid_t t2)
00107 {
00108 int n;
00109 if ((n = H5Tget_nmembers (t1)) != H5Tget_nmembers (t2))
00110 return false;
00111
00112 for (int i = 0; i < n; ++i)
00113 {
00114 hid_t mt1 = H5Tget_member_type (t1, i);
00115 hid_t mt2 = H5Tget_member_type (t2, i);
00116
00117 if (H5Tget_class (mt1) != H5Tget_class (mt2))
00118 return false;
00119
00120 H5Tclose (mt2);
00121 H5Tclose (mt1);
00122 }
00123
00124 return true;
00125 }
00126
00127
00128
00129
00130 bool
00131 hdf5_check_attr (hid_t loc_id, const char *attr_name)
00132 {
00133 bool retval = false;
00134
00135
00136
00137
00138
00139 H5E_auto_t err_func;
00140 void *err_func_data;
00141
00142
00143
00144
00145 #if HAVE_HDF5_18
00146 H5Eget_auto (H5E_DEFAULT, &err_func, &err_func_data);
00147 H5Eset_auto (H5E_DEFAULT, 0, 0);
00148 #else
00149 H5Eget_auto (&err_func, &err_func_data);
00150 H5Eset_auto (0, 0);
00151 #endif
00152
00153 hid_t attr_id = H5Aopen_name (loc_id, attr_name);
00154
00155 if (attr_id >= 0)
00156 {
00157
00158 retval = true;
00159 H5Aclose (attr_id);
00160 }
00161
00162
00163 #if HAVE_HDF5_18
00164 H5Eset_auto (H5E_DEFAULT, err_func, err_func_data);
00165 #else
00166 H5Eset_auto (err_func, err_func_data);
00167 #endif
00168 return retval;
00169 }
00170
00171 bool
00172 hdf5_get_scalar_attr (hid_t loc_id, hid_t type_id,
00173 const char *attr_name, void *buf)
00174 {
00175 bool retval = false;
00176
00177
00178
00179
00180
00181 H5E_auto_t err_func;
00182 void *err_func_data;
00183
00184
00185
00186
00187 #if HAVE_HDF5_18
00188 H5Eget_auto (H5E_DEFAULT, &err_func, &err_func_data);
00189 H5Eset_auto (H5E_DEFAULT, 0, 0);
00190 #else
00191 H5Eget_auto (&err_func, &err_func_data);
00192 H5Eset_auto (0, 0);
00193 #endif
00194
00195 hid_t attr_id = H5Aopen_name (loc_id, attr_name);
00196
00197 if (attr_id >= 0)
00198 {
00199 hid_t space_id = H5Aget_space (attr_id);
00200
00201 hsize_t rank = H5Sget_simple_extent_ndims (space_id);
00202
00203 if (rank == 0)
00204 retval = H5Aread (attr_id, type_id, buf) >= 0;
00205 H5Aclose (attr_id);
00206 }
00207
00208
00209 #if HAVE_HDF5_18
00210 H5Eset_auto (H5E_DEFAULT, err_func, err_func_data);
00211 #else
00212 H5Eset_auto (err_func, err_func_data);
00213 #endif
00214 return retval;
00215 }
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226 hid_t
00227 hdf5_make_complex_type (hid_t num_type)
00228 {
00229 hid_t type_id = H5Tcreate (H5T_COMPOUND, sizeof (double) * 2);
00230
00231 H5Tinsert (type_id, "real", 0 * sizeof (double), num_type);
00232 H5Tinsert (type_id, "imag", 1 * sizeof (double), num_type);
00233
00234 return type_id;
00235 }
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247 herr_t
00248 hdf5_read_next_data (hid_t group_id, const char *name, void *dv)
00249 {
00250 hdf5_callback_data *d = static_cast <hdf5_callback_data *> (dv);
00251 hid_t type_id = -1, type_class_id = -1, data_id = -1, subgroup_id = -1,
00252 space_id = -1;
00253
00254 H5G_stat_t info;
00255 herr_t retval = 0;
00256 bool ident_valid = valid_identifier (name);
00257
00258 std::string vname = name;
00259
00260
00261
00262
00263 if (! ident_valid )
00264 {
00265
00266 vname = make_valid_identifier (vname);
00267
00268
00269 ident_valid = valid_identifier (vname);
00270 }
00271
00272 H5Gget_objinfo (group_id, name, 1, &info);
00273
00274 if (info.type == H5G_GROUP && ident_valid)
00275 {
00276 #if HAVE_HDF5_18
00277 subgroup_id = H5Gopen (group_id, name, H5P_DEFAULT);
00278 #else
00279 subgroup_id = H5Gopen (group_id, name);
00280 #endif
00281
00282 if (subgroup_id < 0)
00283 {
00284 retval = subgroup_id;
00285 goto done;
00286 }
00287
00288 if (hdf5_check_attr (subgroup_id, "OCTAVE_NEW_FORMAT"))
00289 {
00290 #if HAVE_HDF5_18
00291 data_id = H5Dopen (subgroup_id, "type", H5P_DEFAULT);
00292 #else
00293 data_id = H5Dopen (subgroup_id, "type");
00294 #endif
00295
00296 if (data_id < 0)
00297 {
00298 retval = data_id;
00299 goto done;
00300 }
00301
00302 type_id = H5Dget_type (data_id);
00303
00304 type_class_id = H5Tget_class (type_id);
00305
00306 if (type_class_id != H5T_STRING)
00307 goto done;
00308
00309 space_id = H5Dget_space (data_id);
00310 hsize_t rank = H5Sget_simple_extent_ndims (space_id);
00311
00312 if (rank != 0)
00313 goto done;
00314
00315 int slen = H5Tget_size (type_id);
00316 if (slen < 0)
00317 goto done;
00318
00319 OCTAVE_LOCAL_BUFFER (char, typ, slen);
00320
00321
00322 hid_t st_id = H5Tcopy (H5T_C_S1);
00323 H5Tset_size (st_id, slen);
00324
00325 if (H5Dread (data_id, st_id, H5S_ALL, H5S_ALL, H5P_DEFAULT,
00326 typ) < 0)
00327 goto done;
00328
00329 H5Tclose (st_id);
00330 H5Dclose (data_id);
00331
00332 d->tc = octave_value_typeinfo::lookup_type (typ);
00333
00334 retval = (d->tc.load_hdf5 (subgroup_id, "value") ? 1 : -1);
00335
00336
00337 d->global = hdf5_check_attr (subgroup_id, "OCTAVE_GLOBAL");
00338
00339 H5Gclose (subgroup_id);
00340 }
00341 else
00342 {
00343
00344
00345
00346
00347 if (hdf5_check_attr (subgroup_id, "OCTAVE_LIST"))
00348 d->tc = octave_value_typeinfo::lookup_type ("list");
00349 else
00350 d->tc = octave_value_typeinfo::lookup_type ("struct");
00351
00352
00353 d->global = hdf5_check_attr (subgroup_id, "OCTAVE_GLOBAL");
00354
00355 H5Gclose (subgroup_id);
00356
00357 retval = (d->tc.load_hdf5 (group_id, name) ? 1 : -1);
00358 }
00359
00360 }
00361 else if (info.type == H5G_DATASET && ident_valid)
00362 {
00363
00364 #if HAVE_HDF5_18
00365 data_id = H5Dopen (group_id, name, H5P_DEFAULT);
00366 #else
00367 data_id = H5Dopen (group_id, name);
00368 #endif
00369
00370 if (data_id < 0)
00371 {
00372 retval = data_id;
00373 goto done;
00374 }
00375
00376 type_id = H5Dget_type (data_id);
00377
00378 type_class_id = H5Tget_class (type_id);
00379
00380 if (type_class_id == H5T_FLOAT)
00381 {
00382 space_id = H5Dget_space (data_id);
00383
00384 hsize_t rank = H5Sget_simple_extent_ndims (space_id);
00385
00386 if (rank == 0)
00387 d->tc = octave_value_typeinfo::lookup_type ("scalar");
00388 else
00389 d->tc = octave_value_typeinfo::lookup_type ("matrix");
00390
00391 H5Sclose (space_id);
00392 }
00393 else if (type_class_id == H5T_INTEGER)
00394 {
00395
00396 std::string int_typ;
00397 #ifdef HAVE_H5T_GET_NATIVE_TYPE
00398
00399
00400
00401 switch (H5Tget_native_type (type_id, H5T_DIR_ASCEND))
00402 {
00403 case H5T_NATIVE_CHAR:
00404 int_typ = "int8 ";
00405 break;
00406
00407 case H5T_NATIVE_SHORT:
00408 int_typ = "int16 ";
00409 break;
00410
00411 case H5T_NATIVE_INT:
00412 case H5T_NATIVE_LONG:
00413 int_typ = "int32 ";
00414 break;
00415
00416 case H5T_NATIVE_LLONG:
00417 int_typ = "int64 ";
00418 break;
00419
00420 case H5T_NATIVE_UCHAR:
00421 int_typ = "uint8 ";
00422 break;
00423
00424 case H5T_NATIVE_USHORT:
00425 int_typ = "uint16 ";
00426 break;
00427
00428 case H5T_NATIVE_UINT:
00429 case H5T_NATIVE_ULONG:
00430 int_typ = "uint32 ";
00431 break;
00432
00433 case H5T_NATIVE_ULLONG:
00434 int_typ = "uint64 ";
00435 break;
00436 }
00437 #else
00438 hid_t int_sign = H5Tget_sign (type_id);
00439
00440 if (int_sign == H5T_SGN_ERROR)
00441 warning ("load: can't read '%s' (unknown datatype)", name);
00442 else
00443 {
00444 if (int_sign == H5T_SGN_NONE)
00445 int_typ.append ("u");
00446 int_typ.append ("int");
00447
00448 int slen = H5Tget_size (type_id);
00449 if (slen < 0)
00450 warning ("load: can't read '%s' (unknown datatype)", name);
00451 else
00452 {
00453 switch (slen)
00454 {
00455 case 1:
00456 int_typ.append ("8 ");
00457 break;
00458
00459 case 2:
00460 int_typ.append ("16 ");
00461 break;
00462
00463 case 4:
00464 int_typ.append ("32 ");
00465 break;
00466
00467 case 8:
00468 int_typ.append ("64 ");
00469 break;
00470
00471 default:
00472 warning ("load: can't read '%s' (unknown datatype)",
00473 name);
00474 int_typ = "";
00475 break;
00476 }
00477 }
00478 }
00479 #endif
00480 if (int_typ == "")
00481 warning ("load: can't read '%s' (unknown datatype)", name);
00482 else
00483 {
00484
00485 space_id = H5Dget_space (data_id);
00486
00487 hsize_t rank = H5Sget_simple_extent_ndims (space_id);
00488
00489 if (rank == 0)
00490 int_typ.append ("scalar");
00491 else
00492 int_typ.append ("matrix");
00493
00494 d->tc = octave_value_typeinfo::lookup_type (int_typ);
00495 H5Sclose (space_id);
00496 }
00497 }
00498 else if (type_class_id == H5T_STRING)
00499 d->tc = octave_value_typeinfo::lookup_type ("string");
00500 else if (type_class_id == H5T_COMPOUND)
00501 {
00502 hid_t complex_type = hdf5_make_complex_type (H5T_NATIVE_DOUBLE);
00503
00504 if (hdf5_types_compatible (type_id, complex_type))
00505 {
00506
00507 space_id = H5Dget_space (data_id);
00508 hsize_t rank = H5Sget_simple_extent_ndims (space_id);
00509
00510 if (rank == 0)
00511 d->tc = octave_value_typeinfo::lookup_type ("complex scalar");
00512 else
00513 d->tc = octave_value_typeinfo::lookup_type ("complex matrix");
00514
00515 H5Sclose (space_id);
00516 }
00517 else
00518
00519
00520 d->tc = octave_value_typeinfo::lookup_type ("range");
00521
00522 H5Tclose (complex_type);
00523 }
00524 else
00525 {
00526 warning ("load: can't read '%s' (unknown datatype)", name);
00527 retval = 0;
00528 }
00529
00530
00531 d->global = hdf5_check_attr (data_id, "OCTAVE_GLOBAL");
00532
00533 H5Tclose (type_id);
00534 H5Dclose (data_id);
00535
00536 retval = (d->tc.load_hdf5 (group_id, name) ? 1 : -1);
00537 }
00538
00539 if (!ident_valid)
00540 {
00541
00542
00543 warning ("load: skipping invalid identifier '%s' in hdf5 file",
00544 name);
00545 }
00546
00547 done:
00548 if (retval < 0)
00549 error ("load: error while reading hdf5 item %s", name);
00550
00551 if (retval > 0)
00552 {
00553
00554 int comment_length = H5Gget_comment (group_id, name, 0, 0);
00555
00556 if (comment_length > 1)
00557 {
00558 OCTAVE_LOCAL_BUFFER (char, tdoc, comment_length);
00559 H5Gget_comment (group_id, name, comment_length, tdoc);
00560 d->doc = tdoc;
00561 }
00562 else if (vname != name)
00563 {
00564
00565
00566 d->doc = name;
00567 }
00568
00569
00570 d->name = vname;
00571 }
00572
00573 return retval;
00574 }
00575
00576
00577
00578
00579
00580
00581 std::string
00582 read_hdf5_data (std::istream& is, const std::string& ,
00583 bool& global, octave_value& tc, std::string& doc)
00584 {
00585 std::string retval;
00586
00587 doc.resize (0);
00588
00589 hdf5_ifstream& hs = dynamic_cast<hdf5_ifstream&> (is);
00590 hdf5_callback_data d;
00591
00592 herr_t H5Giterate_retval = -1;
00593
00594 hsize_t num_obj = 0;
00595 #if HAVE_HDF5_18
00596 hid_t group_id = H5Gopen (hs.file_id, "/", H5P_DEFAULT);
00597 #else
00598 hid_t group_id = H5Gopen (hs.file_id, "/");
00599 #endif
00600 H5Gget_num_objs (group_id, &num_obj);
00601 H5Gclose (group_id);
00602 if (hs.current_item < static_cast<int> (num_obj))
00603 H5Giterate_retval = H5Giterate (hs.file_id, "/", &hs.current_item,
00604 hdf5_read_next_data, &d);
00605
00606 if (H5Giterate_retval > 0)
00607 {
00608 global = d.global;
00609 tc = d.tc;
00610 doc = d.doc;
00611 }
00612 else
00613 {
00614
00615
00616
00617 }
00618
00619 if (! d.name.empty ())
00620 retval = d.name;
00621
00622 return retval;
00623 }
00624
00625
00626
00627 herr_t
00628 hdf5_add_attr (hid_t loc_id, const char *attr_name)
00629 {
00630 herr_t retval = 0;
00631
00632 hid_t as_id = H5Screate (H5S_SCALAR);
00633
00634 if (as_id >= 0)
00635 {
00636 #if HAVE_HDF5_18
00637 hid_t a_id = H5Acreate (loc_id, attr_name, H5T_NATIVE_UCHAR,
00638 as_id, H5P_DEFAULT, H5P_DEFAULT);
00639 #else
00640 hid_t a_id = H5Acreate (loc_id, attr_name,
00641 H5T_NATIVE_UCHAR, as_id, H5P_DEFAULT);
00642 #endif
00643 if (a_id >= 0)
00644 {
00645 unsigned char attr_val = 1;
00646
00647 retval = H5Awrite (a_id, H5T_NATIVE_UCHAR, &attr_val);
00648
00649 H5Aclose (a_id);
00650 }
00651 else
00652 retval = a_id;
00653
00654 H5Sclose (as_id);
00655 }
00656 else
00657 retval = as_id;
00658
00659 return retval;
00660 }
00661
00662 herr_t
00663 hdf5_add_scalar_attr (hid_t loc_id, hid_t type_id,
00664 const char *attr_name, void *buf)
00665 {
00666 herr_t retval = 0;
00667
00668 hid_t as_id = H5Screate (H5S_SCALAR);
00669
00670 if (as_id >= 0)
00671 {
00672 #if HAVE_HDF5_18
00673 hid_t a_id = H5Acreate (loc_id, attr_name, type_id,
00674 as_id, H5P_DEFAULT, H5P_DEFAULT);
00675 #else
00676 hid_t a_id = H5Acreate (loc_id, attr_name,
00677 type_id, as_id, H5P_DEFAULT);
00678 #endif
00679 if (a_id >= 0)
00680 {
00681 retval = H5Awrite (a_id, type_id, buf);
00682
00683 H5Aclose (a_id);
00684 }
00685 else
00686 retval = a_id;
00687
00688 H5Sclose (as_id);
00689 }
00690 else
00691 retval = as_id;
00692
00693 return retval;
00694 }
00695
00696
00697
00698
00699
00700 int
00701 save_hdf5_empty (hid_t loc_id, const char *name, const dim_vector d)
00702 {
00703 hsize_t sz = d.length ();
00704 OCTAVE_LOCAL_BUFFER (octave_idx_type, dims, sz);
00705 bool empty = false;
00706 hid_t space_hid = -1, data_hid = -1;
00707 int retval;
00708 for (hsize_t i = 0; i < sz; i++)
00709 {
00710 dims[i] = d(i);
00711 if (dims[i] < 1)
00712 empty = true;
00713 }
00714
00715 if (!empty)
00716 return 0;
00717
00718 space_hid = H5Screate_simple (1, &sz, 0);
00719 if (space_hid < 0) return space_hid;
00720 #if HAVE_HDF5_18
00721 data_hid = H5Dcreate (loc_id, name, H5T_NATIVE_IDX, space_hid,
00722 H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
00723 #else
00724 data_hid = H5Dcreate (loc_id, name, H5T_NATIVE_IDX, space_hid,
00725 H5P_DEFAULT);
00726 #endif
00727 if (data_hid < 0)
00728 {
00729 H5Sclose (space_hid);
00730 return data_hid;
00731 }
00732
00733 retval = H5Dwrite (data_hid, H5T_NATIVE_IDX, H5S_ALL, H5S_ALL,
00734 H5P_DEFAULT, dims) >= 0;
00735
00736 H5Dclose (data_hid);
00737 H5Sclose (space_hid);
00738
00739 if (retval >= 0)
00740 retval = hdf5_add_attr (loc_id, "OCTAVE_EMPTY_MATRIX");
00741
00742 return (retval == 0 ? 1 : retval);
00743 }
00744
00745
00746
00747
00748
00749 int
00750 load_hdf5_empty (hid_t loc_id, const char *name, dim_vector &d)
00751 {
00752 if (!hdf5_check_attr(loc_id, "OCTAVE_EMPTY_MATRIX"))
00753 return 0;
00754
00755 hsize_t hdims, maxdims;
00756 #if HAVE_HDF5_18
00757 hid_t data_hid = H5Dopen (loc_id, name, H5P_DEFAULT);
00758 #else
00759 hid_t data_hid = H5Dopen (loc_id, name);
00760 #endif
00761 hid_t space_id = H5Dget_space (data_hid);
00762 H5Sget_simple_extent_dims (space_id, &hdims, &maxdims);
00763 int retval;
00764
00765 OCTAVE_LOCAL_BUFFER (octave_idx_type, dims, hdims);
00766
00767 retval = H5Dread (data_hid, H5T_NATIVE_IDX, H5S_ALL, H5S_ALL,
00768 H5P_DEFAULT, dims);
00769 if (retval >= 0)
00770 {
00771 d.resize (hdims);
00772 for (hsize_t i = 0; i < hdims; i++)
00773 d(i) = dims[i];
00774 }
00775
00776 H5Sclose (space_id);
00777 H5Dclose (data_hid);
00778
00779 return (retval == 0 ? hdims : retval);
00780 }
00781
00782
00783
00784
00785 #if HAVE_HDF5_INT2FLOAT_CONVERSIONS
00786
00787
00788
00789 hid_t
00790 save_type_to_hdf5 (save_type st)
00791 {
00792 switch (st)
00793 {
00794 case LS_U_CHAR:
00795 return H5T_NATIVE_UCHAR;
00796
00797 case LS_U_SHORT:
00798 return H5T_NATIVE_USHORT;
00799
00800 case LS_U_INT:
00801 return H5T_NATIVE_UINT;
00802
00803 case LS_CHAR:
00804 return H5T_NATIVE_CHAR;
00805
00806 case LS_SHORT:
00807 return H5T_NATIVE_SHORT;
00808
00809 case LS_INT:
00810 return H5T_NATIVE_INT;
00811
00812 case LS_FLOAT:
00813 return H5T_NATIVE_FLOAT;
00814
00815 case LS_DOUBLE:
00816 default:
00817 return H5T_NATIVE_DOUBLE;
00818 }
00819 }
00820 #endif
00821
00822
00823
00824
00825
00826
00827 bool
00828 add_hdf5_data (hid_t loc_id, const octave_value& tc,
00829 const std::string& name, const std::string& doc,
00830 bool mark_as_global, bool save_as_floats)
00831 {
00832 hsize_t dims[3];
00833 hid_t type_id = -1, space_id = -1, data_id = -1, data_type_id = -1;
00834 bool retval = false;
00835 octave_value val = tc;
00836
00837
00838
00839 if (val.is_diag_matrix () || val.is_perm_matrix ()
00840 || val.type_id () == octave_lazy_index::static_type_id ())
00841 val = val.full_value ();
00842
00843 std::string t = val.type_name();
00844 #if HAVE_HDF5_18
00845 data_id = H5Gcreate (loc_id, name.c_str (), H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
00846 #else
00847 data_id = H5Gcreate (loc_id, name.c_str (), 0);
00848 #endif
00849 if (data_id < 0)
00850 goto error_cleanup;
00851
00852
00853 type_id = H5Tcopy (H5T_C_S1); H5Tset_size (type_id, t.length () + 1);
00854 if (type_id < 0)
00855 goto error_cleanup;
00856
00857 dims[0] = 0;
00858 space_id = H5Screate_simple (0 , dims, 0);
00859 if (space_id < 0)
00860 goto error_cleanup;
00861 #if HAVE_HDF5_18
00862 data_type_id = H5Dcreate (data_id, "type", type_id, space_id,
00863 H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
00864 #else
00865 data_type_id = H5Dcreate (data_id, "type", type_id, space_id, H5P_DEFAULT);
00866 #endif
00867 if (data_type_id < 0 || H5Dwrite (data_type_id, type_id, H5S_ALL, H5S_ALL,
00868 H5P_DEFAULT, t.c_str ()) < 0)
00869 goto error_cleanup;
00870
00871
00872 retval = val.save_hdf5 (data_id, "value", save_as_floats);
00873
00874
00875 if (retval && doc.length () > 0
00876 && H5Gset_comment (loc_id, name.c_str (), doc.c_str ()) < 0)
00877 retval = false;
00878
00879
00880 if (retval && mark_as_global)
00881 retval = hdf5_add_attr (data_id, "OCTAVE_GLOBAL") >= 0;
00882
00883
00884 if (retval)
00885 retval = hdf5_add_attr (data_id, "OCTAVE_NEW_FORMAT") >= 0;
00886
00887 error_cleanup:
00888
00889 if (data_type_id >= 0)
00890 H5Dclose (data_type_id);
00891
00892 if (type_id >= 0)
00893 H5Tclose (type_id);
00894
00895 if (space_id >= 0)
00896 H5Sclose (space_id);
00897
00898 if (data_id >= 0)
00899 H5Gclose (data_id);
00900
00901 if (! retval)
00902 error ("save: error while writing '%s' to hdf5 file", name.c_str ());
00903
00904 return retval;
00905 }
00906
00907
00908
00909
00910 bool
00911 save_hdf5_data (std::ostream& os, const octave_value& tc,
00912 const std::string& name, const std::string& doc,
00913 bool mark_as_global, bool save_as_floats)
00914 {
00915 hdf5_ofstream& hs = dynamic_cast<hdf5_ofstream&> (os);
00916
00917 return add_hdf5_data (hs.file_id, tc, name, doc,
00918 mark_as_global, save_as_floats);
00919 }
00920
00921 #endif