src/ov-str-mat.cc
author Benjamin Lindner <lindnerb@users.sourceforge.net>
Wed Mar 18 15:23:14 2009 +0100 (2009-03-18)
changeset 7685 34b75a47e712
parent 7017 a1dbe9d80eee
permissions -rw-r--r--
fix leaving stray '\r' in stream when reading from CRLF data file
* * *
fix CRLF issues with text-mode reading in windows when loading ascii data
     1 /*
     2 
     3 Copyright (C) 1996, 1997, 1998, 2000, 2001, 2002, 2003, 2004, 2005,
     4               2006, 2007 John W. Eaton
     5 
     6 This file is part of Octave.
     7 
     8 Octave is free software; you can redistribute it and/or modify it
     9 under the terms of the GNU General Public License as published by the
    10 Free Software Foundation; either version 3 of the License, or (at your
    11 option) any later version.
    12 
    13 Octave is distributed in the hope that it will be useful, but WITHOUT
    14 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    15 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    16 for more details.
    17 
    18 You should have received a copy of the GNU General Public License
    19 along with Octave; see the file COPYING.  If not, see
    20 <http://www.gnu.org/licenses/>.
    21 
    22 */
    23 
    24 #ifdef HAVE_CONFIG_H
    25 #include <config.h>
    26 #endif
    27 
    28 #include <iostream>
    29 #include <vector>
    30 
    31 #include "data-conv.h"
    32 #include "lo-ieee.h"
    33 #include "mach-info.h"
    34 #include "mx-base.h"
    35 
    36 #include "defun.h"
    37 #include "byte-swap.h"
    38 #include "gripes.h"
    39 #include "ls-oct-ascii.h"
    40 #include "ls-hdf5.h"
    41 #include "ls-utils.h"
    42 #include "oct-obj.h"
    43 #include "oct-stream.h"
    44 #include "ops.h"
    45 #include "ov-scalar.h"
    46 #include "ov-re-mat.h"
    47 #include "ov-str-mat.h"
    48 #include "pr-output.h"
    49 #include "pt-mat.h"
    50 #include "utils.h"
    51 #include "ls-ascii-helper.h"
    52 
    53 DEFINE_OCTAVE_ALLOCATOR (octave_char_matrix_str);
    54 DEFINE_OCTAVE_ALLOCATOR (octave_char_matrix_sq_str);
    55 
    56 DEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (octave_char_matrix_str, "string", "char");
    57 DEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (octave_char_matrix_sq_str, "sq_string", "char");
    58 
    59 static octave_base_value *
    60 default_numeric_conversion_function (const octave_base_value& a)
    61 {
    62   octave_base_value *retval = 0;
    63 
    64   CAST_CONV_ARG (const octave_char_matrix_str&);
    65 
    66   NDArray nda = v.array_value (true);
    67 
    68   if (! error_state)
    69     {
    70       if (nda.numel () == 1)
    71 	retval = new octave_scalar (nda(0));
    72       else
    73 	retval = new octave_matrix (nda);
    74     }
    75 
    76   return retval;
    77 }
    78 
    79 octave_base_value::type_conv_fcn
    80 octave_char_matrix_str::numeric_conversion_function (void) const
    81 {
    82   return default_numeric_conversion_function;
    83 }
    84 
    85 octave_value
    86 octave_char_matrix_str::do_index_op_internal (const octave_value_list& idx,
    87 					      bool resize_ok, char type)
    88 {
    89   octave_value retval;
    90 
    91   octave_idx_type len = idx.length ();
    92 
    93   switch (len)
    94     {
    95     case 0:
    96       retval = octave_value (matrix, true, type);
    97       break;
    98 
    99     case 1:
   100       {
   101 	idx_vector i = idx (0).index_vector ();
   102 
   103 	if (! error_state)
   104 	  retval = octave_value (charNDArray (matrix.index (i, resize_ok)),
   105 				 true, type);
   106       }
   107       break;
   108 
   109     case 2:
   110       {
   111 	idx_vector i = idx (0).index_vector ();
   112 	idx_vector j = idx (1).index_vector ();
   113 
   114 	if (! error_state)
   115 	  retval = octave_value (charNDArray (matrix.index (i, j, resize_ok)),
   116 				 true, type);
   117       }
   118       break;
   119 
   120     default:
   121       {
   122 	Array<idx_vector> idx_vec (len);
   123 
   124 	for (octave_idx_type i = 0; i < len; i++)
   125 	  idx_vec(i) = idx(i).index_vector ();
   126 
   127 	if (! error_state)
   128 	  retval = octave_value (charNDArray (matrix.index (idx_vec, resize_ok)),
   129 				 true, type);
   130       }
   131       break;
   132     }
   133 
   134   return retval;
   135 }
   136 
   137 void
   138 octave_char_matrix_str::assign (const octave_value_list& idx,
   139 				const charMatrix& rhs)
   140 {
   141   octave_idx_type len = idx.length ();
   142 
   143   // FIXME
   144   charMatrix tmp = rhs;
   145   if (tmp.rows () == 1 && tmp.columns () == 0)
   146     tmp.resize (0, 0);    
   147 
   148   for (octave_idx_type i = 0; i < len; i++)
   149     matrix.set_index (idx(i).index_vector ());
   150 
   151   ::assign (matrix, tmp, Vstring_fill_char);
   152 }
   153 
   154 octave_value 
   155 octave_char_matrix_str::resize (const dim_vector& dv, bool fill) const
   156 {
   157   charNDArray retval (matrix);
   158   if (fill)
   159     retval.resize (dv, charNDArray::resize_fill_value());
   160   else
   161     retval.resize (dv);
   162   return octave_value (retval, true);
   163 }
   164 
   165 bool
   166 octave_char_matrix_str::valid_as_scalar_index (void) const
   167 {
   168   bool retval = false;
   169   error ("octave_char_matrix_str::valid_as_scalar_index(): not implemented");
   170   return retval;
   171 }
   172 
   173 #define CHAR_MATRIX_CONV(T, INIT, TNAME, FCN) \
   174   T retval INIT; \
   175  \
   176   if (! force_string_conv) \
   177     gripe_invalid_conversion ("string", TNAME); \
   178   else \
   179     { \
   180       warning_with_id ("Octave:str-to-num", \
   181 		       "implicit conversion from %s to %s", \
   182 		       "string", TNAME); \
   183  \
   184       retval = octave_char_matrix::FCN (); \
   185     } \
   186  \
   187   return retval
   188 
   189 double
   190 octave_char_matrix_str::double_value (bool force_string_conv) const
   191 {
   192   CHAR_MATRIX_CONV (double, = 0, "real scalar", double_value);
   193 }
   194 
   195 Complex
   196 octave_char_matrix_str::complex_value (bool force_string_conv) const
   197 {
   198   CHAR_MATRIX_CONV (Complex, = 0, "complex scalar", complex_value);
   199 }
   200 
   201 Matrix
   202 octave_char_matrix_str::matrix_value (bool force_string_conv) const
   203 {
   204   CHAR_MATRIX_CONV (Matrix, , "real matrix", matrix_value);
   205 }
   206 
   207 ComplexMatrix
   208 octave_char_matrix_str::complex_matrix_value (bool force_string_conv) const
   209 {
   210   CHAR_MATRIX_CONV (ComplexMatrix, , "complex matrix", complex_matrix_value);
   211 }
   212 
   213 NDArray
   214 octave_char_matrix_str::array_value (bool force_string_conv) const
   215 {
   216   CHAR_MATRIX_CONV (NDArray, , "real N-d array", array_value);
   217 }
   218 
   219 ComplexNDArray
   220 octave_char_matrix_str::complex_array_value (bool force_string_conv) const
   221 {
   222   CHAR_MATRIX_CONV (ComplexNDArray, , "complex N-d array",
   223 		    complex_array_value);
   224 }
   225 
   226 string_vector
   227 octave_char_matrix_str::all_strings (bool) const
   228 {
   229   string_vector retval;
   230 
   231   if (matrix.ndims () == 2)
   232     {
   233       charMatrix chm = matrix.matrix_value ();
   234 
   235       octave_idx_type n = chm.rows ();
   236 
   237       retval.resize (n);
   238 
   239       for (octave_idx_type i = 0; i < n; i++)
   240 	retval[i] = chm.row_as_string (i);
   241     }
   242   else
   243     error ("invalid conversion of charNDArray to string_vector");
   244 
   245   return retval;
   246 }
   247 
   248 std::string
   249 octave_char_matrix_str::string_value (bool) const
   250 {
   251   std::string retval;
   252 
   253   if (matrix.ndims () == 2)
   254     {
   255       charMatrix chm = matrix.matrix_value ();
   256 
   257       retval = chm.row_as_string (0);  // FIXME???
   258     }
   259   else
   260     error ("invalid conversion of charNDArray to string");
   261 
   262   return retval;
   263 }
   264 
   265 void
   266 octave_char_matrix_str::print_raw (std::ostream& os, bool pr_as_read_syntax) const
   267 {
   268   octave_print_internal (os, matrix, pr_as_read_syntax,
   269 			 current_print_indent_level (), true);
   270 }
   271 
   272 bool 
   273 octave_char_matrix_str::save_ascii (std::ostream& os)
   274 {
   275   dim_vector d = dims ();
   276   if (d.length () > 2)
   277     {
   278       charNDArray tmp = char_array_value ();
   279       os << "# ndims: " << d.length () << "\n";
   280       for (int i=0; i < d.length (); i++)
   281 	os << " " << d (i);
   282       os << "\n";
   283       os.write (tmp.fortran_vec (), d.numel ());
   284       os << "\n";
   285     }
   286   else
   287     {
   288       // Keep this case, rather than use generic code above for
   289       // backward compatiability. Makes load_ascii much more complex!!
   290       charMatrix chm = char_matrix_value ();
   291       octave_idx_type elements = chm.rows ();
   292       os << "# elements: " << elements << "\n";
   293       for (octave_idx_type i = 0; i < elements; i++)
   294 	{
   295 	  unsigned len = chm.cols ();
   296 	  os << "# length: " << len << "\n";
   297 	  std::string tstr = chm.row_as_string (i, false, true);
   298 	  const char *tmp = tstr.data ();
   299 	  if (tstr.length () > len)
   300 	    panic_impossible ();
   301 	  os.write (tmp, len);
   302 	  os << "\n";
   303 	}
   304     }
   305 
   306   return true;
   307 }
   308 
   309 bool 
   310 octave_char_matrix_str::load_ascii (std::istream& is)
   311 {
   312   bool success = true;
   313 
   314   string_vector keywords(3);
   315 
   316   keywords[0] = "ndims";
   317   keywords[1] = "elements";
   318   keywords[2] = "length";
   319 
   320   std::string kw;
   321   int val = 0;
   322 
   323   if (extract_keyword (is, keywords, kw, val, true))
   324     {
   325       if (kw == "ndims")
   326 	{
   327 	  int mdims = val;
   328 
   329 	  if (mdims >= 0)
   330 	    {
   331 	      dim_vector dv;
   332 	      dv.resize (mdims);
   333 
   334 	      for (int i = 0; i < mdims; i++)
   335 		is >> dv(i);
   336 
   337 	      if (is)
   338 		{
   339 		  charNDArray tmp(dv);
   340 
   341 		  if (tmp.is_empty ())
   342 		    matrix = tmp;
   343 		  else
   344 		    {
   345 		      char *ftmp = tmp.fortran_vec ();
   346 
   347 		      // Skip the return line
   348 		      skip_preceeding_newline (is);
   349 
   350 		      if (! is.read (ftmp, dv.numel ()) || !is)
   351 			{
   352 			  error ("load: failed to load string constant");
   353 			  success = false;
   354 			}
   355 		      else
   356 			matrix = tmp;
   357 		    }
   358 		}
   359 	      else
   360 		{
   361 		  error ("load: failed to read dimensions");
   362 		  success = false;
   363 		}
   364 	    }
   365 	  else
   366 	    {
   367 	      error ("load: failed to extract matrix size");
   368 	      success = false;
   369 	    }
   370 	}
   371       else if (kw == "elements")
   372 	{
   373 	  int elements = val;
   374 
   375 	  if (elements >= 0)
   376 	    {
   377 	      // FIXME -- need to be able to get max length
   378 	      // before doing anything.
   379 
   380 	      charMatrix chm (elements, 0);
   381 	      int max_len = 0;
   382 	      for (int i = 0; i < elements; i++)
   383 		{
   384 		  int len;
   385 		  if (extract_keyword (is, "length", len) && len >= 0)
   386 		    {
   387 		      // Use this instead of a C-style character
   388 		      // buffer so that we can properly handle
   389 		      // embedded NUL characters.
   390 		      charMatrix tmp (1, len);
   391 		      char *ptmp = tmp.fortran_vec ();
   392 
   393 		      if (len > 0 && ! is.read (ptmp, len))
   394 			{
   395 			  error ("load: failed to load string constant");
   396 			  success = false;
   397 			  break;
   398 			}
   399 		      else
   400 			{
   401 			  if (len > max_len)
   402 			    {
   403 			      max_len = len;
   404 			      chm.resize (elements, max_len, 0);
   405 			    }
   406 
   407 			  chm.insert (tmp, i, 0);
   408 			}
   409 		    }
   410 		  else
   411 		    {
   412 		      error ("load: failed to extract string length for element %d", 
   413 			     i+1);
   414 		      success = false;
   415 		    }
   416 		}
   417 	  
   418 	      if (! error_state)
   419 		matrix = chm;
   420 	    }
   421 	  else
   422 	    {
   423 	      error ("load: failed to extract number of string elements");
   424 	      success = false;
   425 	    }
   426 	}
   427       else if (kw == "length")
   428 	{
   429 	  int len = val;
   430       
   431 	  if (len >= 0)
   432 	    {
   433 	      // This is cruft for backward compatiability, 
   434 	      // but relatively harmless.
   435 
   436 	      // Use this instead of a C-style character buffer so
   437 	      // that we can properly handle embedded NUL characters.
   438 	      charMatrix tmp (1, len);
   439 	      char *ptmp = tmp.fortran_vec ();
   440 
   441 	      if (len > 0 && ! is.read (ptmp, len))
   442 		{
   443 		  error ("load: failed to load string constant");
   444 		}
   445 	      else
   446 		{
   447 		  if (is)
   448 		    matrix = tmp;
   449 		  else
   450 		    error ("load: failed to load string constant");
   451 		}
   452 	    }
   453 	}
   454       else
   455 	panic_impossible ();
   456     }
   457   else
   458     {
   459       error ("load: failed to extract number of rows and columns");
   460       success = false;
   461     }
   462 
   463   return success;
   464 }
   465 
   466 bool 
   467 octave_char_matrix_str::save_binary (std::ostream& os,
   468 				     bool& /* save_as_floats */)
   469 {
   470   dim_vector d = dims ();
   471   if (d.length() < 1)
   472     return false;
   473 
   474   // Use negative value for ndims to differentiate with old format!!
   475   int32_t tmp = - d.length();
   476   os.write (reinterpret_cast<char *> (&tmp), 4);
   477   for (int i=0; i < d.length (); i++)
   478     {
   479       tmp = d(i);
   480       os.write (reinterpret_cast<char *> (&tmp), 4);
   481     }
   482 
   483   charNDArray m = char_array_value ();
   484   os.write (m.fortran_vec (), d.numel ());
   485   return true;
   486 }
   487 
   488 bool 
   489 octave_char_matrix_str::load_binary (std::istream& is, bool swap,
   490 				     oct_mach_info::float_format /* fmt */)
   491 {
   492   int32_t elements;
   493   if (! is.read (reinterpret_cast<char *> (&elements), 4))
   494     return false;
   495   if (swap)
   496     swap_bytes<4> (&elements);
   497 
   498   if (elements < 0)
   499     {
   500       int32_t mdims = - elements;
   501       int32_t di;
   502       dim_vector dv;
   503       dv.resize (mdims);
   504 
   505       for (int i = 0; i < mdims; i++)
   506 	{
   507 	  if (! is.read (reinterpret_cast<char *> (&di), 4))
   508 	    return false;
   509 	  if (swap)
   510 	    swap_bytes<4> (&di);
   511 	  dv(i) = di;
   512 	}
   513       
   514       // Convert an array with a single dimension to be a row vector.
   515       // Octave should never write files like this, other software
   516       // might.
   517 
   518       if (mdims == 1)
   519 	{
   520 	  mdims = 2;
   521 	  dv.resize (mdims);
   522 	  dv(1) = dv(0);
   523 	  dv(0) = 1;
   524 	}
   525 
   526       charNDArray m(dv);
   527       char *tmp = m.fortran_vec ();
   528       is.read (tmp, dv.numel ());
   529       
   530       if (error_state || ! is)
   531 	return false;
   532       matrix = m;
   533     }
   534   else
   535     {
   536       charMatrix chm (elements, 0);
   537       int max_len = 0;
   538       for (int i = 0; i < elements; i++)
   539 	{
   540 	  int32_t len;
   541 	  if (! is.read (reinterpret_cast<char *> (&len), 4))
   542 	    return false;
   543 	  if (swap)
   544 	    swap_bytes<4> (&len);
   545 	  charMatrix btmp (1, len);
   546 	  char *pbtmp = btmp.fortran_vec ();
   547 	  if (! is.read (pbtmp, len))
   548 	    return false;
   549 	  if (len > max_len)
   550 	    {
   551 	      max_len = len;
   552 	      chm.resize (elements, max_len, 0);
   553 	    }
   554 	  chm.insert (btmp, i, 0);
   555 	}
   556       matrix = chm;
   557     }
   558   return true;
   559 }
   560 
   561 #if defined (HAVE_HDF5)
   562 
   563 bool
   564 octave_char_matrix_str::save_hdf5 (hid_t loc_id, const char *name,
   565 				   bool /* save_as_floats */)
   566 {
   567   dim_vector dv = dims ();
   568   int empty = save_hdf5_empty (loc_id, name, dv);
   569   if (empty)
   570     return (empty > 0);
   571 
   572   int rank = dv.length ();
   573   hid_t space_hid = -1, data_hid = -1;
   574   bool retval = true;
   575   charNDArray m = char_array_value ();
   576 
   577   OCTAVE_LOCAL_BUFFER (hsize_t, hdims, rank);
   578 
   579   // Octave uses column-major, while HDF5 uses row-major ordering
   580   for (int i = 0; i < rank; i++)
   581     hdims[i] = dv (rank-i-1);
   582  
   583   space_hid = H5Screate_simple (rank, hdims, 0);
   584   if (space_hid < 0)
   585     return false;
   586 
   587   data_hid = H5Dcreate (loc_id, name, H5T_NATIVE_CHAR, space_hid, 
   588 			H5P_DEFAULT);
   589   if (data_hid < 0)
   590     {
   591       H5Sclose (space_hid);
   592       return false;
   593     }
   594 
   595   OCTAVE_LOCAL_BUFFER (char, s, dv.numel ());
   596 
   597   for (int i = 0; i < dv.numel (); ++i)
   598     s[i] = m(i);
   599 
   600   retval = H5Dwrite (data_hid, H5T_NATIVE_CHAR, H5S_ALL, H5S_ALL, 
   601 		     H5P_DEFAULT, s) >= 0;
   602 
   603   H5Dclose (data_hid);
   604   H5Sclose (space_hid);
   605 
   606   return retval;
   607 }
   608 
   609 bool 
   610 octave_char_matrix_str::load_hdf5 (hid_t loc_id, const char *name,
   611 				   bool /* have_h5giterate_bug */)
   612 {
   613   bool retval = false;
   614 
   615   dim_vector dv;
   616   int empty = load_hdf5_empty (loc_id, name, dv);
   617   if (empty > 0)
   618     matrix.resize(dv);
   619   if (empty)
   620     return (empty > 0);
   621 
   622   hid_t data_hid = H5Dopen (loc_id, name);
   623   hid_t space_hid = H5Dget_space (data_hid);
   624   hsize_t rank = H5Sget_simple_extent_ndims (space_hid);
   625   hid_t type_hid = H5Dget_type (data_hid);
   626   hid_t type_class_hid = H5Tget_class (type_hid);
   627 
   628   if (type_class_hid == H5T_INTEGER)
   629     {
   630       if (rank < 1)
   631 	{
   632 	  H5Tclose (type_hid);
   633 	  H5Sclose (space_hid);
   634 	  H5Dclose (data_hid);
   635 	  return false;
   636 	}
   637 
   638       OCTAVE_LOCAL_BUFFER (hsize_t, hdims, rank);
   639       OCTAVE_LOCAL_BUFFER (hsize_t, maxdims, rank);
   640 
   641       H5Sget_simple_extent_dims (space_hid, hdims, maxdims);
   642 
   643       // Octave uses column-major, while HDF5 uses row-major ordering
   644       if (rank == 1)
   645 	{
   646 	  dv.resize (2);
   647 	  dv(0) = 1;
   648 	  dv(1) = hdims[0];
   649 	}
   650       else
   651 	{
   652 	  dv.resize (rank);
   653 	  for (hsize_t i = 0, j = rank - 1; i < rank; i++, j--)
   654 	    dv(j) = hdims[i];
   655 	}
   656 
   657       charNDArray m (dv);
   658       char *str = m.fortran_vec ();
   659       if (H5Dread (data_hid, H5T_NATIVE_CHAR, H5S_ALL, H5S_ALL, 
   660 		   H5P_DEFAULT, str) >= 0) 
   661 	{
   662 	  retval = true;
   663 	  matrix = m;
   664 	}
   665 
   666       H5Tclose (type_hid);
   667       H5Sclose (space_hid);
   668       H5Dclose (data_hid);
   669       return true;
   670     }
   671   else
   672     {
   673       // This is cruft for backward compatiability and easy data
   674       // importation
   675       if (rank == 0)
   676 	{
   677 	  // a single string:
   678 	  int slen = H5Tget_size (type_hid);
   679 	  if (slen < 0)
   680 	    {
   681 	      H5Tclose (type_hid);
   682 	      H5Sclose (space_hid);
   683 	      H5Dclose (data_hid);
   684 	      return false;
   685 	    }
   686 	  else
   687 	    {
   688 	      OCTAVE_LOCAL_BUFFER (char, s, slen);
   689 	      // create datatype for (null-terminated) string
   690 	      // to read into:
   691 	      hid_t st_id = H5Tcopy (H5T_C_S1);
   692 	      H5Tset_size (st_id, slen);
   693 	      if (H5Dread (data_hid, st_id, H5S_ALL, H5S_ALL, H5P_DEFAULT, s) < 0)
   694 		{
   695 		  H5Tclose (st_id);
   696 		  H5Tclose (type_hid);
   697 		  H5Sclose (space_hid);
   698 		  H5Dclose (data_hid);
   699 		  return false;
   700 		}
   701 
   702 	      matrix = charMatrix (s);
   703 	  
   704 	      H5Tclose (st_id);
   705 	      H5Tclose (type_hid);
   706 	      H5Sclose (space_hid);
   707 	      H5Dclose (data_hid);
   708 	      return true;
   709 	    }
   710 	}
   711       else if (rank == 1)
   712 	{
   713 	  // string vector
   714 	  hsize_t elements, maxdim;
   715 	  H5Sget_simple_extent_dims (space_hid, &elements, &maxdim);
   716 	  int slen = H5Tget_size (type_hid);
   717 	  if (slen < 0)
   718 	    {
   719 	      H5Tclose (type_hid);
   720 	      H5Sclose (space_hid);
   721 	      H5Dclose (data_hid);
   722 	      return false;
   723 	    }
   724 	  else
   725 	    {
   726 	      // hdf5 string arrays store strings of all the
   727 	      // same physical length (I think), which is
   728 	      // slightly wasteful, but oh well.
   729 	  
   730 	      OCTAVE_LOCAL_BUFFER (char, s, elements * slen);
   731 
   732 	      // create datatype for (null-terminated) string
   733 	      // to read into:
   734 	      hid_t st_id = H5Tcopy (H5T_C_S1);
   735 	      H5Tset_size (st_id, slen);
   736 
   737 	      if (H5Dread (data_hid, st_id, H5S_ALL, H5S_ALL, H5P_DEFAULT, s) < 0)
   738 		{
   739 		  H5Tclose (st_id);
   740 		  H5Tclose (type_hid);
   741 		  H5Sclose (space_hid);
   742 		  H5Dclose (data_hid);
   743 		  return false;
   744 		}
   745 
   746 	      charMatrix chm (elements, slen - 1);
   747 	      for (hsize_t i = 0; i < elements; ++i)
   748 		{
   749 		  chm.insert (s + i*slen, i, 0);
   750 		}
   751 
   752 	      matrix = chm;
   753 
   754 	      H5Tclose (st_id);
   755 	      H5Tclose (type_hid);
   756 	      H5Sclose (space_hid);
   757 	      H5Dclose (data_hid);
   758 	      return true;
   759 	    }
   760 	}
   761       else
   762 	{
   763 	  H5Tclose (type_hid);
   764 	  H5Sclose (space_hid);
   765 	  H5Dclose (data_hid);
   766 	  return false;
   767 	}
   768     }
   769 
   770   return retval;
   771 }
   772 
   773 #endif
   774 
   775 /*
   776 ;;; Local Variables: ***
   777 ;;; mode: C++ ***
   778 ;;; End: ***
   779 */