GNU Octave 7.1.0
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
dlmread.cc
Go to the documentation of this file.
1////////////////////////////////////////////////////////////////////////
2//
3// Copyright (C) 2008-2022 The Octave Project Developers
4//
5// See the file COPYRIGHT.md in the top-level directory of this
6// distribution or <https://octave.org/copyright/>.
7//
8// This file is part of Octave.
9//
10// Octave is free software: you can redistribute it and/or modify it
11// under the terms of the GNU General Public License as published by
12// the Free Software Foundation, either version 3 of the License, or
13// (at your option) any later version.
14//
15// Octave is distributed in the hope that it will be useful, but
16// WITHOUT ANY WARRANTY; without even the implied warranty of
17// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18// GNU General Public License for more details.
19//
20// You should have received a copy of the GNU General Public License
21// along with Octave; see the file COPYING. If not, see
22// <https://www.gnu.org/licenses/>.
23//
24////////////////////////////////////////////////////////////////////////
25
26// Adapted from previous version of dlmread.occ as authored by Kai
27// Habel, but core code has been completely re-written.
28
29#if defined (HAVE_CONFIG_H)
30# include "config.h"
31#endif
32
33#include <clocale>
34#include <cmath>
35#include <cctype>
36#include <fstream>
37#include <limits>
38
39#include "file-ops.h"
40#include "lo-ieee.h"
41#include "lo-sysdep.h"
42
43#include "defun.h"
44#include "interpreter.h"
45#include "oct-stream.h"
46#include "error.h"
47#include "ovl.h"
48#include "utils.h"
49
52
53static const double idx_max_dbl = double (idx_max);
54
55static bool
56read_cell_spec (std::istream& is, octave_idx_type& row, octave_idx_type& col)
57{
58 bool stat = false;
59
60 if (is.peek () == std::istream::traits_type::eof ())
61 stat = true;
62 else
63 {
64 if (::isalpha (is.peek ()))
65 {
66 col = 0;
67 while (is && ::isalpha (is.peek ()))
68 {
69 char ch = is.get ();
70 col *= 26;
71 if (ch >= 'a')
72 col += ch - 'a' + 1;
73 else
74 col += ch - 'A' + 1;
75 }
76 col--;
77
78 if (is)
79 {
80 is >> row;
81 row--;
82 if (is)
83 stat = true;
84 }
85 }
86 }
87
88 return stat;
89}
90
91static bool
92parse_range_spec (const octave_value& range_spec,
95{
96 bool stat = true;
97
98 if (range_spec.is_string ())
99 {
100 std::istringstream is (range_spec.string_value ());
101 char ch = is.peek ();
102
103 if (ch == '.' || ch == ':')
104 {
105 rlo = 0;
106 clo = 0;
107 ch = is.get ();
108 if (ch == '.')
109 {
110 ch = is.get ();
111 if (ch != '.')
112 stat = false;
113 }
114 }
115 else
116 {
117 stat = read_cell_spec (is, rlo, clo);
118
119 if (stat)
120 {
121 ch = is.peek ();
122
123 if (ch == '.' || ch == ':')
124 {
125 ch = is.get ();
126 if (ch == '.')
127 {
128 ch = is.get ();
129 if (! is || ch != '.')
130 stat = false;
131 }
132
133 rup = idx_max;
134 cup = idx_max;
135 }
136 else
137 {
138 rup = rlo;
139 cup = clo;
140 if (! is || ! is.eof ())
141 stat = false;
142 }
143 }
144 }
145
146 if (stat && is && ! is.eof ())
147 stat = read_cell_spec (is, rup, cup);
148
149 if (! is || ! is.eof ())
150 stat = false;
151 }
152 else if (range_spec.is_real_matrix () && range_spec.numel () == 4)
153 {
154 NDArray range (range_spec.array_value ());
155 if (range.any_element_is_nan ())
156 error ("dlmread: NaN is not a valid row or column specifier");
157
158 // double --> unsigned int avoiding any overflow
159 rlo = static_cast<octave_idx_type> (std::min (range(0), idx_max_dbl));
160 clo = static_cast<octave_idx_type> (std::min (range(1), idx_max_dbl));
161 rup = static_cast<octave_idx_type> (std::min (range(2), idx_max_dbl));
162 cup = static_cast<octave_idx_type> (std::min (range(3), idx_max_dbl));
163 }
164 else
165 stat = false;
166
167 return stat;
168}
169
170OCTAVE_NAMESPACE_BEGIN
171
172DEFMETHOD (dlmread, interp, args, ,
173 doc: /* -*- texinfo -*-
174@deftypefn {} {@var{data} =} dlmread (@var{file})
175@deftypefnx {} {@var{data} =} dlmread (@var{file}, @var{sep})
176@deftypefnx {} {@var{data} =} dlmread (@var{file}, @var{sep}, @var{r0}, @var{c0})
177@deftypefnx {} {@var{data} =} dlmread (@var{file}, @var{sep}, @var{range})
178@deftypefnx {} {@var{data} =} dlmread (@dots{}, "emptyvalue", @var{EMPTYVAL})
179Read numeric data from the text file @var{file} which uses the delimiter
180@var{sep} between data values.
181
182If @var{sep} is not defined the separator between fields is determined from
183the file itself.
184
185The optional scalar arguments @var{r0} and @var{c0} define the starting row
186and column of the data to be read. These values are indexed from zero,
187i.e., the first data row corresponds to an index of zero.
188
189The @var{range} parameter specifies exactly which data elements are read.
190The first form of the parameter is a 4-element vector containing the upper
191left and lower right corners @code{[@var{R0},@var{C0},@var{R1},@var{C1}]}
192where the indices are zero-based. To specify the last column---the equivalent
193of @code{end} when indexing---use the specifier @code{Inf}. Alternatively, a
194spreadsheet style form such as @qcode{"A2..Q15"} or @qcode{"T1:AA5"} can be
195used. The lowest alphabetical index @qcode{'A'} refers to the first column.
196The lowest row index is 1.
197
198@var{file} should be a filename or a file id given by @code{fopen}. In the
199latter case, the file is read until end of file is reached.
200
201The @qcode{"emptyvalue"} option may be used to specify the value used to
202fill empty fields. The default is zero. Note that any non-numeric values,
203such as text, are also replaced by the @qcode{"emptyvalue"}.
204@seealso{csvread, textscan, dlmwrite}
205@end deftypefn */)
206{
207 int nargin = args.length ();
208
209 double empty_value = 0.0;
210
211 if (nargin > 2 && args(nargin-2).is_string ()
212 && args(nargin-2).string_value () == "emptyvalue")
213 {
214 empty_value = args(nargin-1).double_value ();
215
216 nargin -= 2;
217 }
218
219 if (nargin < 1 || nargin > 4)
220 print_usage ();
221
222 std::istream *input = nullptr;
223 std::ifstream input_file;
224
225 if (args(0).is_string ())
226 {
227 // Filename.
228 std::string fname (args(0).string_value ());
229
230 std::string tname = sys::file_ops::tilde_expand (fname);
231
232 tname = find_data_file_in_load_path ("dlmread", tname);
233
234#if defined (OCTAVE_USE_WINDOWS_API)
235 std::wstring wname = sys::u8_to_wstring (tname);
236 input_file.open (wname.c_str (), std::ios::in);
237#else
238 input_file.open (tname.c_str (), std::ios::in);
239#endif
240
241 if (! input_file)
242 error ("dlmread: unable to open file '%s'", fname.c_str ());
243
244 input = &input_file;
245 }
246 else if (args(0).is_scalar_type ())
247 {
248 stream_list& streams = interp.get_stream_list ();
249
250 stream is = streams.lookup (args(0), "dlmread");
251
252 input = is.input_stream ();
253
254 if (! input)
255 error ("dlmread: stream FILE not open for input");
256 }
257 else
258 error ("dlmread: FILE argument must be a string or file id");
259
260 // Set default separator.
261 std::string sep;
262 if (nargin > 1)
263 {
264 if (args(1).is_sq_string ())
265 sep = do_string_escapes (args(1).string_value ());
266 else
267 sep = args(1).string_value ();
268 }
269
270 // Take a subset if a range was given.
271 octave_idx_type r0 = 0;
272 octave_idx_type c0 = 0;
275 if (nargin > 2)
276 {
277 if (nargin == 3)
278 {
279 if (! parse_range_spec (args(2), r0, c0, r1, c1))
280 error ("dlmread: error parsing RANGE");
281 }
282 else if (nargin == 4)
283 {
284 r0 = args(2).idx_type_value ();
285 c0 = args(3).idx_type_value ();
286 }
287
288 if (r0 < 0 || c0 < 0)
289 error ("dlmread: left (R0) and top (C0) must be positive");
290
291 // Short-circuit and return if range is empty
292 if (r1 < r0 || c1 < c0)
293 return ovl (Matrix (0, 0));
294 }
295
296 octave_idx_type i = 0;
297 octave_idx_type j = 0;
298 octave_idx_type r = 1;
299 octave_idx_type c = 1;
300 // Start with a reasonable size to avoid constant resizing of matrix.
301 octave_idx_type rmax = 32;
302 octave_idx_type cmax = 0;
303
304 Matrix rdata (rmax, cmax, empty_value);
305 ComplexMatrix cdata;
306
307 bool iscmplx = false;
308 bool sep_is_wspace = (sep.find_first_of (" \t") != std::string::npos);
309 bool auto_sep_is_wspace = false;
310
311 if (r0 == 0)
312 {
313 // Peek into stream and potentially strip Byte Order Mark (BOM)
314 const char BOM[3] = {'\xEF', '\xBB', '\xBF'};
315 char buf[3];
316 int i_bom;
317 bool found_bom = true;
318 for (i_bom = 0; i_bom < 3; i_bom++)
319 {
320 char ch_p = input->peek ();
321 if (ch_p == BOM[i_bom])
322 buf[i_bom] = input->get ();
323 else
324 {
325 found_bom = false;
326 break;
327 }
328 }
329 // Put back read characters if it wasn't a BOM
330 if (! found_bom)
331 {
332 for (int i_ret = i_bom-1; i_ret >= 0; i_ret--)
333 input->putback (buf[i_ret]);
334 }
335 }
336
337 // Set "C" locale for the remainder of this function to avoid the performance
338 // panelty of frequently switching the locale when reading floating point
339 // values from the stream.
340 char *prev_locale = std::setlocale (LC_ALL, nullptr);
341 std::string old_locale (prev_locale ? prev_locale : "");
342 std::setlocale (LC_ALL, "C");
343 unwind_action act
344 ([old_locale] () { std::setlocale (LC_ALL, old_locale.c_str ()); });
345
346 std::string line;
347
348 // Skip the r0 leading lines
349 octave_idx_type rcnt = r0;
350 while (rcnt > 0 && getline (*input, line))
351 rcnt--;
352
353 if (rcnt > 0)
354 return ovl (Matrix (0, 0)); // Not enough lines in file to satisfy RANGE
355 else
356 r1 -= r0;
357
358 std::istringstream tmp_stream;
359
360 // Read the data one field at a time, growing the data matrix as needed.
361 while (getline (*input, line))
362 {
363 // Skip blank lines for compatibility.
364 if ((! sep_is_wspace || auto_sep_is_wspace)
365 && line.find_first_not_of (" \t") == std::string::npos)
366 continue;
367
368 // Infer separator from file if delimiter is blank.
369 if (sep.empty ())
370 {
371 // Skip leading whitespace.
372 std::size_t pos1 = line.find_first_not_of (" \t");
373
374 // For Matlab compatibility, blank delimiter should
375 // correspond to whitespace (space and tab).
376 std::size_t n = line.find_first_of (",:; \t", pos1);
377 if (n == std::string::npos)
378 {
379 sep = " \t";
380 auto_sep_is_wspace = true;
381 }
382 else
383 {
384 char ch = line.at (n);
385
386 switch (line.at (n))
387 {
388 case ' ':
389 case '\t':
390 sep = " \t";
391 auto_sep_is_wspace = true;
392 break;
393
394 default:
395 sep = ch;
396 break;
397 }
398 }
399 }
400
401 // Estimate the number of columns from first line of data.
402 if (cmax == 0)
403 {
404 std::size_t pos1, pos2;
405 if (auto_sep_is_wspace)
406 pos1 = line.find_first_not_of (" \t");
407 else
408 pos1 = 0;
409
410 do
411 {
412 pos2 = line.find_first_of (sep, pos1);
413
414 if (auto_sep_is_wspace && pos2 != std::string::npos)
415 {
416 // Treat consecutive separators as one.
417 pos2 = line.find_first_not_of (sep, pos2);
418 if (pos2 != std::string::npos)
419 pos2 -= 1;
420 }
421
422 // Separator followed by EOL doesn't generate extra column
423 if (pos2 != std::string::npos)
424 cmax++;
425
426 pos1 = pos2 + 1;
427 }
428 while (pos2 != std::string::npos);
429
430 // FIXME: Should always be the case that iscmplx == false.
431 // Flag is initialized that way and no data has been read.
432 if (iscmplx)
433 cdata.resize (rmax, cmax, empty_value);
434 else
435 rdata.resize (rmax, cmax, empty_value);
436 }
437
438 r = (r > i + 1 ? r : i + 1);
439 j = 0;
440
441 std::size_t pos1, pos2;
442 if (auto_sep_is_wspace)
443 pos1 = line.find_first_not_of (" \t"); // Skip leading whitespace.
444 else
445 pos1 = 0;
446
447 do
448 {
449 octave_quit ();
450
451 pos2 = line.find_first_of (sep, pos1);
452 std::string str = line.substr (pos1, pos2 - pos1);
453
454 if (auto_sep_is_wspace && pos2 != std::string::npos)
455 {
456 // Treat consecutive separators as one.
457 pos2 = line.find_first_not_of (sep, pos2);
458 if (pos2 != std::string::npos)
459 pos2 -= 1;
460 else
461 pos2 = line.length () - 1;
462 }
463
464 // Separator followed by EOL doesn't generate extra column
465 if (pos2 == std::string::npos && str.empty ())
466 break;
467
468 c = (c > j + 1 ? c : j + 1);
469 if (r > rmax || c > cmax)
470 {
471 // Use resize_and_fill for the case of unequal length rows.
472 // Keep rmax a power of 2.
473 rmax = std::max (2*(r-1), rmax);
474 cmax = std::max (c, cmax);
475 if (iscmplx)
476 cdata.resize (rmax, cmax, empty_value);
477 else
478 rdata.resize (rmax, cmax, empty_value);
479 }
480
481 tmp_stream.str (str);
482 tmp_stream.clear ();
483
484 double x = read_value<double> (tmp_stream);
485 if (tmp_stream)
486 {
487 if (tmp_stream.eof ())
488 {
489 if (iscmplx)
490 cdata(i, j++) = x;
491 else
492 rdata(i, j++) = x;
493 }
494 else
495 {
496 int next_char = tmp_stream.peek ();
497 if (next_char == 'i' || next_char == 'j'
498 || next_char == 'I' || next_char == 'J')
499 {
500 // Process pure imaginary numbers.
501 tmp_stream.get ();
502 next_char = tmp_stream.peek ();
503 if (next_char == std::istringstream::traits_type::eof ())
504 {
505 if (! iscmplx)
506 {
507 iscmplx = true;
508 cdata = ComplexMatrix (rdata);
509 }
510
511 cdata(i, j++) = Complex (0, x);
512 }
513 else
514 {
515 // Parsing failed, <number>i|j<extra text>
516 j++; // Leave data initialized to empty_value
517 }
518 }
519 else if (std::isalpha (next_char) && ! std::isfinite (x))
520 {
521 // Parsing failed, <Inf|NA|NaN><extra text>
522 j++; // Leave data initialized to empty_value
523 }
524 else
525 {
526 double y = read_value<double> (tmp_stream);
527
528 if (! iscmplx && y != 0.0)
529 {
530 iscmplx = true;
531 cdata = ComplexMatrix (rdata);
532 }
533
534 if (iscmplx)
535 cdata(i, j++) = Complex (x, y);
536 else
537 rdata(i, j++) = x;
538 }
539 }
540 }
541 else
542 {
543 // read_value<double>() parsing failed
544 j++; // Leave data initialized to empty_value
545 }
546
547 pos1 = pos2 + 1;
548 }
549 while (pos2 != std::string::npos);
550
551 if (i == r1)
552 break; // Stop early if the desired range has been read.
553
554 i++;
555 }
556
557 // Clip selection indices to actual size of data
558 if (r1 >= r)
559 r1 = r - 1;
560 if (c1 >= c)
561 c1 = c - 1;
562
563 if (iscmplx)
564 {
565 if ((i == 0 && j == 0) || (c0 > c1))
566 return ovl (ComplexMatrix (0, 0));
567
568 cdata = cdata.extract (0, c0, r1, c1);
569 return ovl (cdata);
570 }
571 else
572 {
573 if ((i == 0 && j == 0) || (c0 > c1))
574 return ovl (Matrix (0, 0));
575
576 rdata = rdata.extract (0, c0, r1, c1);
577 return ovl (rdata);
578 }
579}
580
581/*
582%!test
583%! file = tempname ();
584%! unwind_protect
585%! fid = fopen (file, "wt");
586%! fwrite (fid, "1, 2, 3\n4, 5, 6\n7, 8, 9\n10, 11, 12");
587%! fclose (fid);
588%!
589%! assert (dlmread (file), [1, 2, 3; 4, 5, 6; 7, 8, 9;10, 11, 12]);
590%! assert (dlmread (file, ","), [1, 2, 3; 4, 5, 6; 7, 8, 9; 10, 11, 12]);
591%! assert (dlmread (file, ",", [1, 0, 2, 1]), [4, 5; 7, 8]);
592%! assert (dlmread (file, ",", "B1..C2"), [2, 3; 5, 6]);
593%! assert (dlmread (file, ",", "B1:C2"), [2, 3; 5, 6]);
594%! assert (dlmread (file, ",", "..C2"), [1, 2, 3; 4, 5, 6]);
595%! assert (dlmread (file, ",", 0, 1), [2, 3; 5, 6; 8, 9; 11, 12]);
596%! assert (dlmread (file, ",", "B1.."), [2, 3; 5, 6; 8, 9; 11, 12]);
597%! assert (dlmread (file, ",", 10, 0), []);
598%! assert (dlmread (file, ",", 0, 10), []);
599%! fail ('dlmread (file, ",", [0 1])', "error parsing RANGE");
600%! unwind_protect_cleanup
601%! unlink (file);
602%! end_unwind_protect
603
604%!testif ; ! ismac ()
605%! file = tempname ();
606%! unwind_protect
607%! fid = fopen (file, "wt");
608%! fwrite (fid, "1, 2, 3\n4+4i, 5, 6\n7, 8, 9\n10, 11, 12");
609%! fclose (fid);
610%!
611%! assert (dlmread (file), [1, 2, 3; 4 + 4i, 5, 6; 7, 8, 9; 10, 11, 12]);
612%! assert (dlmread (file, ","), [1,2,3; 4 + 4i, 5, 6; 7, 8, 9; 10, 11, 12]);
613%! assert (dlmread (file, ",", [1, 0, 2, 1]), [4 + 4i, 5; 7, 8]);
614%! assert (dlmread (file, ",", "A2..B3"), [4 + 4i, 5; 7, 8]);
615%! assert (dlmread (file, ",", "A2:B3"), [4 + 4i, 5; 7, 8]);
616%! assert (dlmread (file, ",", "..B3"), [1, 2; 4 + 4i, 5; 7, 8]);
617%! assert (dlmread (file, ",", 1, 0), [4 + 4i, 5, 6; 7, 8, 9; 10, 11, 12]);
618%! assert (dlmread (file, ",", "A2.."), [4 + 4i, 5, 6; 7, 8, 9; 10, 11, 12]);
619%! assert (dlmread (file, ",", 10, 0), []);
620%! assert (dlmread (file, ",", 0, 10), []);
621%! unwind_protect_cleanup
622%! unlink (file);
623%! end_unwind_protect
624
625%!test <47413>
626%! ## Same test code as above, but intended only for test statistics on Mac.
627%! if (! ismac ()), return; endif
628%! file = tempname ();
629%! unwind_protect
630%! fid = fopen (file, "wt");
631%! fwrite (fid, "1, 2, 3\n4+4i, 5, 6\n7, 8, 9\n10, 11, 12");
632%! fclose (fid);
633%!
634%! assert (dlmread (file), [1, 2, 3; 4 + 4i, 5, 6; 7, 8, 9; 10, 11, 12]);
635%! assert (dlmread (file, ","), [1,2,3; 4 + 4i, 5, 6; 7, 8, 9; 10, 11, 12]);
636%! assert (dlmread (file, ",", [1, 0, 2, 1]), [4 + 4i, 5; 7, 8]);
637%! assert (dlmread (file, ",", "A2..B3"), [4 + 4i, 5; 7, 8]);
638%! assert (dlmread (file, ",", "A2:B3"), [4 + 4i, 5; 7, 8]);
639%! assert (dlmread (file, ",", "..B3"), [1, 2; 4 + 4i, 5; 7, 8]);
640%! assert (dlmread (file, ",", 1, 0), [4 + 4i, 5, 6; 7, 8, 9; 10, 11, 12]);
641%! assert (dlmread (file, ",", "A2.."), [4 + 4i, 5, 6; 7, 8, 9; 10, 11, 12]);
642%! assert (dlmread (file, ",", 10, 0), []);
643%! assert (dlmread (file, ",", 0, 10), []);
644%! unwind_protect_cleanup
645%! unlink (file);
646%! end_unwind_protect
647
648%!test <*42025>
649%! file = tempname ();
650%! unwind_protect
651%! fid = fopen (file, "wt");
652%! fwrite (fid, " \n 1 2\n11 22\n ");
653%! fclose (fid);
654%!
655%! assert (dlmread (file), [1, 2; 11, 22]);
656%! assert (dlmread (file, " "), [ 0, 0, 0, 0
657%! 0, 1, 2, 0
658%! 11, 22, 0, 0
659%! 0, 0, 0, 0]);
660%! unwind_protect_cleanup
661%! unlink (file);
662%! end_unwind_protect
663
664%!testif ; ! ismac () <*50589>
665%! file = tempname ();
666%! unwind_protect
667%! fid = fopen (file, "wt");
668%! fwrite (fid, "1;2;3\n");
669%! fwrite (fid, "1i;2I;3j;4J\n");
670%! fwrite (fid, "4;5;6\n");
671%! fwrite (fid, "-4i;+5I;-6j;+7J\n");
672%! fclose (fid);
673%!
674%! assert (dlmread (file), [1, 2, 3, 0; 1i, 2i, 3i, 4i;
675%! 4, 5, 6, 0; -4i, 5i, -6i, 7i]);
676%! assert (dlmread (file, "", [0 0 0 3]), [1, 2, 3]);
677%! assert (dlmread (file, "", [1 0 1 3]), [1i, 2i, 3i, 4i]);
678%! unwind_protect_cleanup
679%! unlink (file);
680%! end_unwind_protect
681
682%!test <47413>
683%! ## Same test code as above, but intended only for test statistics on Mac.
684%! if (! ismac ()), return; endif
685%! file = tempname ();
686%! unwind_protect
687%! fid = fopen (file, "wt");
688%! fwrite (fid, "1;2;3\n");
689%! fwrite (fid, "1i;2I;3j;4J\n");
690%! fwrite (fid, "4;5;6\n");
691%! fwrite (fid, "-4i;+5I;-6j;+7J\n");
692%! fclose (fid);
693%!
694%! assert (dlmread (file), [1, 2, 3, 0; 1i, 2i, 3i, 4i;
695%! 4, 5, 6, 0; -4i, 5i, -6i, 7i]);
696%! assert (dlmread (file, "", [0 0 0 3]), [1, 2, 3]);
697%! assert (dlmread (file, "", [1 0 1 3]), [1i, 2i, 3i, 4i]);
698%! unwind_protect_cleanup
699%! unlink (file);
700%! end_unwind_protect
701
702## NA was not properly read from a file
703%!test
704%! file = tempname ();
705%! unwind_protect
706%! fid = fopen (file, "wt");
707%! fwrite (fid, "1,NA,3");
708%! fclose (fid);
709%!
710%! assert (dlmread (file), [1, NA, 3]);
711%! unwind_protect_cleanup
712%! unlink (file);
713%! end_unwind_protect
714
715## "Name" was read as NA rather than parse error
716%!test <*54029>
717%! file = tempname ();
718%! unwind_protect
719%! fid = fopen (file, "wt");
720%! fwrite (fid, "NaNe,bNa,Name,c\n1,NaN,3,Inftest\n-Inf,6,NA,8");
721%! fclose (fid);
722%!
723%! assert (dlmread (file), [0, 0, 0, 0; 1, NaN, 3, 0; -Inf, 6, NA, 8]);
724%! unwind_protect_cleanup
725%! unlink (file);
726%! end_unwind_protect
727
728## Infinity incorrectly changed matrix to complex, rather than parse error
729%!test
730%! file = tempname ();
731%! unwind_protect
732%! fid = fopen (file, "wt");
733%! fwrite (fid, "1,Infinity,3");
734%! fclose (fid);
735%!
736%! assert (dlmread (file), [1, 0, 3]);
737%! unwind_protect_cleanup
738%! unlink (file);
739%! end_unwind_protect
740
741## Purely complex numbers with trailing garbage produced complex matrix
742%!test
743%! file = tempname ();
744%! unwind_protect
745%! fid = fopen (file, "wt");
746%! fwrite (fid, "1,2jack,3");
747%! fclose (fid);
748%!
749%! assert (dlmread (file), [1, 0, 3]);
750%! unwind_protect_cleanup
751%! unlink (file);
752%! end_unwind_protect
753
754## Verify UTF-8 Byte Order Mark does not cause problems with reading
755%!test <*58813>
756%! file = tempname ();
757%! unwind_protect
758%! fid = fopen (file, "wt");
759%! fwrite (fid, char ([0xEF, 0xBB, 0xBF])); # UTF-8 BOM
760%! fwrite (fid, "1,2\n3,4");
761%! fclose (fid);
762%!
763%! assert (dlmread (file), [1, 2; 3, 4]);
764%! unwind_protect_cleanup
765%! unlink (file);
766%! end_unwind_protect
767
768*/
769
770OCTAVE_NAMESPACE_END
charNDArray max(char d, const charNDArray &m)
Definition: chNDArray.cc:230
charNDArray min(char d, const charNDArray &m)
Definition: chNDArray.cc:207
OCTAVE_API ComplexMatrix extract(octave_idx_type r1, octave_idx_type c1, octave_idx_type r2, octave_idx_type c2) const
Definition: CMatrix.cc:683
void resize(octave_idx_type nr, octave_idx_type nc, const Complex &rfv=Complex(0))
Definition: CMatrix.h:193
Definition: dMatrix.h:42
OCTAVE_API Matrix extract(octave_idx_type r1, octave_idx_type c1, octave_idx_type r2, octave_idx_type c2) const
Definition: dMatrix.cc:397
void resize(octave_idx_type nr, octave_idx_type nc, double rfv=0)
Definition: dMatrix.h:158
octave_idx_type numel(void) const
Definition: ov.h:604
bool is_string(void) const
Definition: ov.h:682
std::string string_value(bool force=false) const
Definition: ov.h:1019
NDArray array_value(bool frc_str_conv=false) const
Definition: ov.h:904
bool is_real_matrix(void) const
Definition: ov.h:658
OCTINTERP_API void print_usage(void)
Definition: defun-int.h:72
#define DEFMETHOD(name, interp_name, args_name, nargout_name, doc)
Macro to define a builtin method.
Definition: defun.h:111
static bool read_cell_spec(std::istream &is, octave_idx_type &row, octave_idx_type &col)
Definition: dlmread.cc:56
static bool parse_range_spec(const octave_value &range_spec, octave_idx_type &rlo, octave_idx_type &clo, octave_idx_type &rup, octave_idx_type &cup)
Definition: dlmread.cc:92
static const double idx_max_dbl
Definition: dlmread.cc:53
static const octave_idx_type idx_max
Definition: dlmread.cc:51
void error(const char *fmt,...)
Definition: error.cc:980
F77_RET_T const F77_DBLE * x
class OCTAVE_API ComplexMatrix
Definition: mx-fwd.h:32
bool isfinite(double x)
Definition: lo-mappers.h:192
std::string tilde_expand(const std::string &name)
Definition: file-ops.cc:281
std::ifstream ifstream(const std::string &filename, const std::ios::openmode mode)
Definition: lo-sysdep.cc:400
std::wstring u8_to_wstring(const std::string &utf8_string)
Definition: lo-sysdep.cc:490
class OCTAVE_API range
Definition: range-fwd.h:33
std::complex< double > Complex
Definition: oct-cmplx.h:33
static int input(yyscan_t yyscanner)
octave_value_list ovl(const OV_Args &... args)
Construct an octave_value_list with less typing.
Definition: ovl.h:211
subroutine stat(x, n, av, var, xmin, xmax)
Definition: tstgmn.for:112
std::string do_string_escapes(const std::string &s)
Definition: utils.cc:801
std::string find_data_file_in_load_path(const std::string &fcn, const std::string &file, bool require_regular_file)
Definition: utils.cc:700