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