Bug Summary

File:libinterp/corefcn/oct-stream.cc
Location:line 3191, column 27
Description:Value stored to 'elts_to_read' during its initialization is never read

Annotated Source Code

1/*
2
3Copyright (C) 1996-2013 John W. Eaton
4
5This file is part of Octave.
6
7Octave is free software; you can redistribute it and/or modify it
8under the terms of the GNU General Public License as published by the
9Free Software Foundation; either version 3 of the License, or (at your
10option) any later version.
11
12Octave is distributed in the hope that it will be useful, but WITHOUT
13ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15for more details.
16
17You should have received a copy of the GNU General Public License
18along with Octave; see the file COPYING. If not, see
19<http://www.gnu.org/licenses/>.
20
21*/
22
23#ifdef HAVE_CONFIG_H1
24#include <config.h>
25#endif
26
27#include <cassert>
28#include <cctype>
29#include <cstring>
30
31#include <iomanip>
32#include <iostream>
33#include <fstream>
34#include <sstream>
35#include <string>
36
37#include <Array.h>
38
39#include "byte-swap.h"
40#include "lo-ieee.h"
41#include "lo-mappers.h"
42#include "lo-utils.h"
43#include "quit.h"
44#include "singleton-cleanup.h"
45#include "str-vec.h"
46
47#include "error.h"
48#include "gripes.h"
49#include "input.h"
50#include "oct-stdstrm.h"
51#include "oct-stream.h"
52#include "oct-obj.h"
53#include "utils.h"
54
55// Possible values for conv_err:
56//
57// 1 : not a real scalar
58// 2 : value is NaN
59// 3 : value is not an integer
60
61static int
62convert_to_valid_int (const octave_value& tc, int& conv_err)
63{
64 int retval = 0;
65
66 conv_err = 0;
67
68 double dval = tc.double_value ();
69
70 if (! error_state)
71 {
72 if (! lo_ieee_isnan (dval)(sizeof (dval) == sizeof (float) ? __lo_ieee_float_isnan (dval
) : __lo_ieee_isnan (dval))
)
73 {
74 int ival = NINT (dval);
75
76 if (ival == dval)
77 retval = ival;
78 else
79 conv_err = 3;
80 }
81 else
82 conv_err = 2;
83 }
84 else
85 conv_err = 1;
86
87 return retval;
88}
89
90static int
91get_size (double d, const std::string& who)
92{
93 int retval = -1;
94
95 if (! lo_ieee_isnan (d)(sizeof (d) == sizeof (float) ? __lo_ieee_float_isnan (d) : __lo_ieee_isnan
(d))
)
96 {
97 if (! xisinf (d))
98 {
99 if (d >= 0.0)
100 retval = NINT (d);
101 else
102 ::error ("%s: negative value invalid as size specification",
103 who.c_str ());
104 }
105 else
106 retval = -1;
107 }
108 else
109 ::error ("%s: NaN is invalid as size specification", who.c_str ());
110
111 return retval;
112}
113
114static void
115get_size (const Array<double>& size, octave_idx_type& nr, octave_idx_type& nc,
116 bool& one_elt_size_spec, const std::string& who)
117{
118 nr = -1;
119 nc = -1;
120
121 one_elt_size_spec = false;
122
123 double dnr = -1.0;
124 double dnc = -1.0;
125
126 octave_idx_type sz_len = size.length ();
127
128 if (sz_len == 1)
129 {
130 one_elt_size_spec = true;
131
132 dnr = size (0);
133
134 dnc = (dnr == 0.0) ? 0.0 : 1.0;
135 }
136 else if (sz_len == 2)
137 {
138 dnr = size (0);
139
140 if (! xisinf (dnr))
141 dnc = size (1);
142 else
143 ::error ("%s: invalid size specification", who.c_str ());
144 }
145 else
146 ::error ("%s: invalid size specification", who.c_str ());
147
148 if (! error_state)
149 {
150 nr = get_size (dnr, who);
151
152 if (! error_state && dnc >= 0.0)
153 nc = get_size (dnc, who);
154 }
155}
156
157scanf_format_list::scanf_format_list (const std::string& s)
158 : nconv (0), curr_idx (0), list (dim_vector (16, 1)), buf (0)
159{
160 octave_idx_type num_elts = 0;
161
162 size_t n = s.length ();
163
164 size_t i = 0;
165
166 int width = 0;
167 bool discard = false;
168 char modifier = '\0';
169 char type = '\0';
170
171 bool have_more = true;
172
173 while (i < n)
174 {
175 have_more = true;
176
177 if (! buf)
178 buf = new std::ostringstream ();
179
180 if (s[i] == '%')
181 {
182 // Process percent-escape conversion type.
183
184 process_conversion (s, i, n, width, discard, type, modifier,
185 num_elts);
186
187 have_more = (buf != 0);
188 }
189 else if (isspace (s[i]))
190 {
191 type = scanf_format_elt::whitespace_conversion;
192
193 width = 0;
194 discard = false;
195 modifier = '\0';
196 *buf << " ";
197
198 while (++i < n && isspace (s[i]))
199 /* skip whitespace */;
200
201 add_elt_to_list (width, discard, type, modifier, num_elts);
202
203 have_more = false;
204 }
205 else
206 {
207 type = scanf_format_elt::literal_conversion;
208
209 width = 0;
210 discard = false;
211 modifier = '\0';
212
213 while (i < n && ! isspace (s[i]) && s[i] != '%')
214 *buf << s[i++];
215
216 add_elt_to_list (width, discard, type, modifier, num_elts);
217
218 have_more = false;
219 }
220
221 if (nconv < 0)
222 {
223 have_more = false;
224 break;
225 }
226 }
227
228 if (have_more)
229 add_elt_to_list (width, discard, type, modifier, num_elts);
230
231 list.resize (dim_vector (num_elts, 1));
232
233 delete buf;
234}
235
236scanf_format_list::~scanf_format_list (void)
237{
238 octave_idx_type n = list.length ();
239
240 for (octave_idx_type i = 0; i < n; i++)
241 {
242 scanf_format_elt *elt = list(i);
243 delete elt;
244 }
245}
246
247void
248scanf_format_list::add_elt_to_list (int width, bool discard, char type,
249 char modifier, octave_idx_type& num_elts,
250 const std::string& char_class)
251{
252 if (buf)
253 {
254 std::string text = buf->str ();
255
256 if (! text.empty ())
257 {
258 scanf_format_elt *elt
259 = new scanf_format_elt (text.c_str (), width, discard, type,
260 modifier, char_class);
261
262 if (num_elts == list.length ())
263 list.resize (dim_vector (2 * num_elts, 1));
264
265 list(num_elts++) = elt;
266 }
267
268 delete buf;
269 buf = 0;
270 }
271}
272
273static std::string
274expand_char_class (const std::string& s)
275{
276 std::string retval;
277
278 size_t len = s.length ();
279
280 size_t i = 0;
281
282 while (i < len)
283 {
284 unsigned char c = s[i++];
285
286 if (c == '-' && i > 1 && i < len
287 && ( static_cast<unsigned char> (s[i-2])
288 <= static_cast<unsigned char> (s[i])))
289 {
290 // Add all characters from the range except the first (we
291 // already added it below).
292
293 for (c = s[i-2]+1; c < s[i]; c++)
294 retval += c;
295 }
296 else
297 {
298 // Add the character to the class. Only add '-' if it is
299 // the last character in the class.
300
301 if (c != '-' || i == len)
302 retval += c;
303 }
304 }
305
306 return retval;
307}
308
309void
310scanf_format_list::process_conversion (const std::string& s, size_t& i,
311 size_t n, int& width, bool& discard,
312 char& type, char& modifier,
313 octave_idx_type& num_elts)
314{
315 width = 0;
316 discard = false;
317 modifier = '\0';
318 type = '\0';
319
320 *buf << s[i++];
321
322 bool have_width = false;
323
324 while (i < n)
325 {
326 switch (s[i])
327 {
328 case '*':
329 if (discard)
330 nconv = -1;
331 else
332 {
333 discard = true;
334 *buf << s[i++];
335 }
336 break;
337
338 case '0': case '1': case '2': case '3': case '4':
339 case '5': case '6': case '7': case '8': case '9':
340 if (have_width)
341 nconv = -1;
342 else
343 {
344 char c = s[i++];
345 width = width * 10 + c - '0';
346 have_width = true;
347 *buf << c;
348 while (i < n && isdigit (s[i]))
349 {
350 c = s[i++];
351 width = width * 10 + c - '0';
352 *buf << c;
353 }
354 }
355 break;
356
357 case 'h': case 'l': case 'L':
358 if (modifier != '\0')
359 nconv = -1;
360 else
361 modifier = s[i++];
362 break;
363
364 case 'd': case 'i': case 'o': case 'u': case 'x':
365 if (modifier == 'L')
366 {
367 nconv = -1;
368 break;
369 }
370 goto fini;
371
372 case 'e': case 'f': case 'g':
373 if (modifier == 'h')
374 {
375 nconv = -1;
376 break;
377 }
378
379 // No float or long double conversions, thanks.
380 *buf << 'l';
381
382 goto fini;
383
384 case 'c': case 's': case 'p': case '%': case '[':
385 if (modifier != '\0')
386 {
387 nconv = -1;
388 break;
389 }
390 goto fini;
391
392 fini:
393 {
394 if (finish_conversion (s, i, n, width, discard, type,
395 modifier, num_elts) == 0)
396 return;
397 }
398 break;
399
400 default:
401 nconv = -1;
402 break;
403 }
404
405 if (nconv < 0)
406 break;
407 }
408
409 nconv = -1;
410}
411
412int
413scanf_format_list::finish_conversion (const std::string& s, size_t& i,
414 size_t n, int& width, bool discard,
415 char& type, char modifier,
416 octave_idx_type& num_elts)
417{
418 int retval = 0;
419
420 std::string char_class;
421
422 size_t beg_idx = std::string::npos;
423 size_t end_idx = std::string::npos;
424
425 if (s[i] == '%')
426 {
427 type = '%';
428 *buf << s[i++];
429 }
430 else
431 {
432 type = s[i];
433
434 if (s[i] == '[')
435 {
436 *buf << s[i++];
437
438 if (i < n)
439 {
440 beg_idx = i;
441
442 if (s[i] == '^')
443 {
444 type = '^';
445 *buf << s[i++];
446
447 if (i < n)
448 {
449 beg_idx = i;
450
451 if (s[i] == ']')
452 *buf << s[i++];
453 }
454 }
455 else if (s[i] == ']')
456 *buf << s[i++];
457 }
458
459 while (i < n && s[i] != ']')
460 *buf << s[i++];
461
462 if (i < n && s[i] == ']')
463 {
464 end_idx = i-1;
465 *buf << s[i++];
466 }
467
468 if (s[i-1] != ']')
469 retval = nconv = -1;
470 }
471 else
472 *buf << s[i++];
473
474 nconv++;
475 }
476
477 if (nconv >= 0)
478 {
479 if (beg_idx != std::string::npos && end_idx != std::string::npos)
480 char_class = expand_char_class (s.substr (beg_idx,
481 end_idx - beg_idx + 1));
482
483 add_elt_to_list (width, discard, type, modifier, num_elts, char_class);
484 }
485
486 return retval;
487}
488
489void
490scanf_format_list::printme (void) const
491{
492 octave_idx_type n = list.length ();
493
494 for (octave_idx_type i = 0; i < n; i++)
495 {
496 scanf_format_elt *elt = list(i);
497
498 std::cerr
499 << "width: " << elt->width << "\n"
500 << "discard: " << elt->discard << "\n"
501 << "type: ";
502
503 if (elt->type == scanf_format_elt::literal_conversion)
504 std::cerr << "literal text\n";
505 else if (elt->type == scanf_format_elt::whitespace_conversion)
506 std::cerr << "whitespace\n";
507 else
508 std::cerr << elt->type << "\n";
509
510 std::cerr
511 << "modifier: " << elt->modifier << "\n"
512 << "char_class: '" << undo_string_escapes (elt->char_class) << "'\n"
513 << "text: '" << undo_string_escapes (elt->text) << "'\n\n";
514 }
515}
516
517bool
518scanf_format_list::all_character_conversions (void)
519{
520 octave_idx_type n = list.length ();
521
522 if (n > 0)
523 {
524 for (octave_idx_type i = 0; i < n; i++)
525 {
526 scanf_format_elt *elt = list(i);
527
528 switch (elt->type)
529 {
530 case 'c': case 's': case '%': case '[': case '^':
531 case scanf_format_elt::literal_conversion:
532 case scanf_format_elt::whitespace_conversion:
533 break;
534
535 default:
536 return false;
537 break;
538 }
539 }
540
541 return true;
542 }
543 else
544 return false;
545}
546
547bool
548scanf_format_list::all_numeric_conversions (void)
549{
550 octave_idx_type n = list.length ();
551
552 if (n > 0)
553 {
554 for (octave_idx_type i = 0; i < n; i++)
555 {
556 scanf_format_elt *elt = list(i);
557
558 switch (elt->type)
559 {
560 case 'd': case 'i': case 'o': case 'u': case 'x':
561 case 'e': case 'f': case 'g':
562 break;
563
564 default:
565 return false;
566 break;
567 }
568 }
569
570 return true;
571 }
572 else
573 return false;
574}
575
576// Ugh again.
577
578printf_format_list::printf_format_list (const std::string& s)
579 : nconv (0), curr_idx (0), list (dim_vector (16, 1)), buf (0)
580{
581 octave_idx_type num_elts = 0;
582
583 size_t n = s.length ();
584
585 size_t i = 0;
586
587 int args = 0;
588 std::string flags;
589 int fw = 0;
590 int prec = 0;
591 char modifier = '\0';
592 char type = '\0';
593
594 bool have_more = true;
595 bool empty_buf = true;
596
597 if (n == 0)
598 {
599 printf_format_elt *elt
600 = new printf_format_elt ("", args, fw, prec, flags, type, modifier);
601
602 list(num_elts++) = elt;
603
604 list.resize (dim_vector (num_elts, 1));
605 }
606 else
607 {
608 while (i < n)
609 {
610 have_more = true;
611
612 if (! buf)
613 {
614 buf = new std::ostringstream ();
615 empty_buf = true;
616 }
617
618 switch (s[i])
619 {
620 case '%':
621 {
622 if (empty_buf)
623 {
624 process_conversion (s, i, n, args, flags, fw, prec,
625 type, modifier, num_elts);
626
627 have_more = (buf != 0);
628 }
629 else
630 add_elt_to_list (args, flags, fw, prec, type, modifier,
631 num_elts);
632 }
633 break;
634
635 default:
636 {
637 args = 0;
638 flags = "";
639 fw = 0;
640 prec = 0;
641 modifier = '\0';
642 type = '\0';
643 *buf << s[i++];
644 empty_buf = false;
645 }
646 break;
647 }
648
649 if (nconv < 0)
650 {
651 have_more = false;
652 break;
653 }
654 }
655
656 if (have_more)
657 add_elt_to_list (args, flags, fw, prec, type, modifier, num_elts);
658
659 list.resize (dim_vector (num_elts, 1));
660
661 delete buf;
662 }
663}
664
665printf_format_list::~printf_format_list (void)
666{
667 octave_idx_type n = list.length ();
668
669 for (octave_idx_type i = 0; i < n; i++)
670 {
671 printf_format_elt *elt = list(i);
672 delete elt;
673 }
674}
675
676void
677printf_format_list::add_elt_to_list (int args, const std::string& flags,
678 int fw, int prec, char type,
679 char modifier, octave_idx_type& num_elts)
680{
681 if (buf)
682 {
683 std::string text = buf->str ();
684
685 if (! text.empty ())
686 {
687 printf_format_elt *elt
688 = new printf_format_elt (text.c_str (), args, fw, prec, flags,
689 type, modifier);
690
691 if (num_elts == list.length ())
692 list.resize (dim_vector (2 * num_elts, 1));
693
694 list(num_elts++) = elt;
695 }
696
697 delete buf;
698 buf = 0;
699 }
700}
701
702void
703printf_format_list::process_conversion (const std::string& s, size_t& i,
704 size_t n, int& args, std::string& flags,
705 int& fw, int& prec, char& modifier,
706 char& type, octave_idx_type& num_elts)
707{
708 args = 0;
709 flags = "";
710 fw = 0;
711 prec = 0;
712 modifier = '\0';
713 type = '\0';
714
715 *buf << s[i++];
716
717 bool nxt = false;
718
719 while (i < n)
720 {
721 switch (s[i])
722 {
723 case '-': case '+': case ' ': case '0': case '#':
724 flags += s[i];
725 *buf << s[i++];
726 break;
727
728 default:
729 nxt = true;
730 break;
731 }
732
733 if (nxt)
734 break;
735 }
736
737 if (i < n)
738 {
739 if (s[i] == '*')
740 {
741 fw = -1;
742 args++;
743 *buf << s[i++];
744 }
745 else
746 {
747 if (isdigit (s[i]))
748 {
749 int nn = 0;
750 std::string tmp = s.substr (i);
751 sscanf (tmp.c_str (), "%d%n", &fw, &nn);
752 }
753
754 while (i < n && isdigit (s[i]))
755 *buf << s[i++];
756 }
757 }
758
759 if (i < n && s[i] == '.')
760 {
761 *buf << s[i++];
762
763 if (i < n)
764 {
765 if (s[i] == '*')
766 {
767 prec = -1;
768 args++;
769 *buf << s[i++];
770 }
771 else
772 {
773 if (isdigit (s[i]))
774 {
775 int nn = 0;
776 std::string tmp = s.substr (i);
777 sscanf (tmp.c_str (), "%d%n", &prec, &nn);
778 }
779
780 while (i < n && isdigit (s[i]))
781 *buf << s[i++];
782 }
783 }
784 }
785
786 if (i < n)
787 {
788 switch (s[i])
789 {
790 case 'h': case 'l': case 'L':
791 modifier = s[i];
792 *buf << s[i++];
793 break;
794
795 default:
796 break;
797 }
798 }
799
800 if (i < n)
801 finish_conversion (s, i, args, flags, fw, prec, modifier, type, num_elts);
802 else
803 nconv = -1;
804}
805
806void
807printf_format_list::finish_conversion (const std::string& s, size_t& i,
808 int args, const std::string& flags,
809 int fw, int prec, char modifier,
810 char& type, octave_idx_type& num_elts)
811{
812 switch (s[i])
813 {
814 case 'd': case 'i': case 'o': case 'x': case 'X':
815 case 'u': case 'c':
816 if (modifier == 'L')
817 {
818 nconv = -1;
819 break;
820 }
821 goto fini;
822
823 case 'f': case 'e': case 'E': case 'g': case 'G':
824 if (modifier == 'h' || modifier == 'l')
825 {
826 nconv = -1;
827 break;
828 }
829 goto fini;
830
831 case 's': case 'p': case '%':
832 if (modifier != '\0')
833 {
834 nconv = -1;
835 break;
836 }
837 goto fini;
838
839 fini:
840
841 type = s[i];
842
843 *buf << s[i++];
844
845 if (type != '%' || args != 0)
846 nconv++;
847
848 if (type != '%')
849 args++;
850
851 add_elt_to_list (args, flags, fw, prec, type, modifier, num_elts);
852
853 break;
854
855 default:
856 nconv = -1;
857 break;
858 }
859}
860
861void
862printf_format_list::printme (void) const
863{
864 int n = list.length ();
865
866 for (int i = 0; i < n; i++)
867 {
868 printf_format_elt *elt = list(i);
869
870 std::cerr
871 << "args: " << elt->args << "\n"
872 << "flags: '" << elt->flags << "'\n"
873 << "width: " << elt->fw << "\n"
874 << "prec: " << elt->prec << "\n"
875 << "type: '" << elt->type << "'\n"
876 << "modifier: '" << elt->modifier << "'\n"
877 << "text: '" << undo_string_escapes (elt->text) << "'\n\n";
878 }
879}
880
881void
882octave_base_stream::error (const std::string& msg)
883{
884 fail = true;
885 errmsg = msg;
886}
887
888void
889octave_base_stream::error (const std::string& who, const std::string& msg)
890{
891 fail = true;
892 errmsg = who + ": " + msg;
893}
894
895void
896octave_base_stream::clear (void)
897{
898 fail = false;
899 errmsg = "";
900}
901
902void
903octave_base_stream::clearerr (void)
904{
905 std::istream *is = input_stream ();
906 std::ostream *os = output_stream ();
907
908 if (is)
909 is->clear ();
910
911 if (os)
912 os->clear ();
913}
914
915// Functions that are defined for all input streams (input streams
916// are those that define is).
917
918std::string
919octave_base_stream::do_gets (octave_idx_type max_len, bool& err,
920 bool strip_newline, const std::string& who)
921{
922 std::string retval;
923
924 if ((interactive || forced_interactive) && file_number () == 0)
925 {
926 ::error ("%s: unable to read from stdin while running interactively",
927 who.c_str ());
928
929 return retval;
930 }
931
932 err = false;
933
934 std::istream *isp = input_stream ();
935
936 if (isp)
937 {
938 std::istream& is = *isp;
939
940 std::ostringstream buf;
941
942 int c = 0;
943 int char_count = 0;
944
945 if (max_len != 0)
946 {
947 while (is && (c = is.get ()) != EOF(-1))
948 {
949 char_count++;
950
951 // Handle CRLF, CR, or LF as line ending.
952
953 if (c == '\r')
954 {
955 if (! strip_newline)
956 buf << static_cast<char> (c);
957
958 c = is.get ();
959
960 if (c != EOF(-1))
961 {
962 if (c == '\n')
963 {
964 char_count++;
965
966 if (! strip_newline)
967 buf << static_cast<char> (c);
968 }
969 else
970 is.putback (c);
971 }
972
973 break;
974 }
975 else if (c == '\n')
976 {
977 if (! strip_newline)
978 buf << static_cast<char> (c);
979
980 break;
981 }
982 else
983 buf << static_cast<char> (c);
984
985 if (max_len > 0 && char_count == max_len)
986 break;
987 }
988 }
989
990 if (! is.eof () && char_count > 0)
991 {
992 // GAGME. Matlab seems to check for EOF even if the last
993 // character in a file is a newline character. This is NOT
994 // what the corresponding C-library functions do.
995 int disgusting_compatibility_hack = is.get ();
996 if (! is.eof ())
997 is.putback (disgusting_compatibility_hack);
998 }
999
1000 if (is.good () || (is.eof () && char_count > 0))
1001 retval = buf.str ();
1002 else
1003 {
1004 err = true;
1005
1006 if (is.eof () && char_count == 0)
1007 error (who, "at end of file");
1008 else
1009 error (who, "read error");
1010 }
1011 }
1012 else
1013 {
1014 err = true;
1015 invalid_operation (who, "reading");
1016 }
1017
1018 return retval;
1019}
1020
1021std::string
1022octave_base_stream::getl (octave_idx_type max_len, bool& err,
1023 const std::string& who)
1024{
1025 return do_gets (max_len, err, true, who);
1026}
1027
1028std::string
1029octave_base_stream::gets (octave_idx_type max_len, bool& err,
1030 const std::string& who)
1031{
1032 return do_gets (max_len, err, false, who);
1033}
1034
1035off_t
1036octave_base_stream::skipl (off_t num, bool& err, const std::string& who)
1037{
1038 off_t cnt = -1;
1039
1040 if ((interactive || forced_interactive) && file_number () == 0)
1041 {
1042 ::error ("%s: unable to read from stdin while running interactively",
1043 who.c_str ());
1044
1045 return count;
1046 }
1047
1048 err = false;
1049
1050 std::istream *isp = input_stream ();
1051
1052 if (isp)
1053 {
1054 std::istream& is = *isp;
1055
1056 int c = 0, lastc = -1;
1057 cnt = 0;
1058
1059 while (is && (c = is.get ()) != EOF(-1))
1060 {
1061 // Handle CRLF, CR, or LF as line ending.
1062
1063 if (c == '\r' || (c == '\n' && lastc != '\r'))
1064 {
1065 if (++cnt == num)
1066 break;
1067 }
1068
1069 lastc = c;
1070 }
1071
1072 // Maybe eat the following \n if \r was just met.
1073 if (c == '\r' && is.peek () == '\n')
1074 is.get ();
1075
1076 if (is.bad ())
1077 {
1078 err = true;
1079 error (who, "read error");
1080 }
1081
1082 if (err)
1083 cnt = -1;
1084 }
1085 else
1086 {
1087 err = true;
1088 invalid_operation (who, "reading");
1089 }
1090
1091 return cnt;
1092}
1093
1094#define OCTAVE_SCAN(is, fmt, arg)octave_scan (is, fmt, arg) octave_scan (is, fmt, arg)
1095
1096template <class T>
1097std::istream&
1098octave_scan_1 (std::istream& is, const scanf_format_elt& fmt, T* valptr)
1099{
1100 T& ref = *valptr;
1101
1102 switch (fmt.type)
1103 {
1104 case 'o':
1105 is >> std::oct >> ref >> std::dec;
1106 break;
1107
1108 case 'x':
1109 is >> std::hex >> ref >> std::dec;
1110 break;
1111
1112 case 'i':
1113 {
1114 int c1 = EOF(-1);
1115
1116 while (is && (c1 = is.get ()) != EOF(-1) && isspace (c1))
1117 /* skip whitespace */;
1118
1119 if (c1 != EOF(-1))
1120 {
1121 if (c1 == '0')
1122 {
1123 int c2 = is.peek ();
1124
1125 if (c2 == 'x' || c2 == 'X')
1126 {
1127 is.ignore ();
1128 if (std::isxdigit (is.peek ()))
1129 is >> std::hex >> ref >> std::dec;
1130 else
1131 ref = 0;
1132 }
1133 else
1134 {
1135 if (c2 == '0' || c2 == '1' || c2 == '2'
1136 || c2 == '3' || c2 == '4' || c2 == '5'
1137 || c2 == '6' || c2 == '7')
1138 is >> std::oct >> ref >> std::dec;
1139 else
1140 ref = 0;
1141 }
1142 }
1143 else
1144 {
1145 is.putback (c1);
1146
1147 is >> ref;
1148 }
1149 }
1150 }
1151 break;
1152
1153 default:
1154 is >> ref;
1155 break;
1156 }
1157
1158 return is;
1159}
1160
1161template <class T>
1162std::istream&
1163octave_scan (std::istream& is, const scanf_format_elt& fmt, T* valptr)
1164{
1165 if (fmt.width)
1166 {
1167 // Limit input to fmt.width characters by reading into a
1168 // temporary stringstream buffer.
1169
1170 std::string tmp;
1171
1172 is.width (fmt.width);
1173 is >> tmp;
1174
1175 std::istringstream ss (tmp);
1176
1177 octave_scan_1 (ss, fmt, valptr);
1178 }
1179 else
1180 octave_scan_1 (is, fmt, valptr);
1181
1182 return is;
1183}
1184
1185// Note that this specialization is only used for reading characters, not
1186// character strings. See BEGIN_S_CONVERSION for details.
1187
1188template<>
1189std::istream&
1190octave_scan<> (std::istream& is, const scanf_format_elt& /* fmt */,
1191 char* valptr)
1192{
1193 return is >> valptr;
1194}
1195
1196template<>
1197std::istream&
1198octave_scan<> (std::istream& is, const scanf_format_elt& fmt, double* valptr)
1199{
1200 double& ref = *valptr;
1201
1202 switch (fmt.type)
1203 {
1204 case 'e':
1205 case 'f':
1206 case 'g':
1207 {
1208 int c1 = EOF(-1);
1209
1210 while (is && (c1 = is.get ()) != EOF(-1) && isspace (c1))
1211 /* skip whitespace */;
1212
1213 if (c1 != EOF(-1))
1214 {
1215 is.putback (c1);
1216
1217 ref = octave_read_value<double> (is);
1218 }
1219 }
1220 break;
1221
1222 default:
1223 panic_impossible ()panic ("impossible state reached in file '%s' at line %d", "corefcn/oct-stream.cc"
, 1223)
;
1224 break;
1225 }
1226
1227 return is;
1228}
1229
1230template <class T>
1231void
1232do_scanf_conv (std::istream& is, const scanf_format_elt& fmt,
1233 T valptr, Matrix& mval, double *data, octave_idx_type& idx,
1234 octave_idx_type& conversion_count, octave_idx_type nr,
1235 octave_idx_type max_size, bool discard)
1236{
1237 OCTAVE_SCAN (is, fmt, valptr)octave_scan (is, fmt, valptr);
1238
1239 if (is)
1240 {
1241 if (idx == max_size && ! discard)
1242 {
1243 max_size *= 2;
1244
1245 if (nr > 0)
1246 mval.resize (nr, max_size / nr, 0.0);
1247 else
1248 mval.resize (max_size, 1, 0.0);
1249
1250 data = mval.fortran_vec ();
1251 }
1252
1253 if (! discard)
1254 {
1255 conversion_count++;
1256 data[idx++] = *(valptr);
1257 }
1258 }
1259}
1260
1261template void
1262do_scanf_conv (std::istream&, const scanf_format_elt&, double*,
1263 Matrix&, double*, octave_idx_type&, octave_idx_type&,
1264 octave_idx_type, octave_idx_type, bool);
1265
1266#define DO_WHITESPACE_CONVERSION()do { int c = (-1); while (is && (c = is.get ()) != (-
1) && isspace (c)) ; if (c != (-1)) is.putback (c); }
while (0)
\
1267 do \
1268 { \
1269 int c = EOF(-1); \
1270 \
1271 while (is && (c = is.get ()) != EOF(-1) && isspace (c)) \
1272 /* skip whitespace */; \
1273 \
1274 if (c != EOF(-1)) \
1275 is.putback (c); \
1276 } \
1277 while (0)
1278
1279#define DO_LITERAL_CONVERSION()do { int c = (-1); int n = strlen (fmt); int i = 0; while (i <
n && is && (c = is.get ()) != (-1)) { if (c ==
static_cast<unsigned char> (fmt[i])) { i++; continue; }
else { is.putback (c); break; } } if (i != n) is.setstate (std
::ios::failbit); } while (0)
\
1280 do \
1281 { \
1282 int c = EOF(-1); \
1283 \
1284 int n = strlen (fmt); \
1285 int i = 0; \
1286 \
1287 while (i < n && is && (c = is.get ()) != EOF(-1)) \
1288 { \
1289 if (c == static_cast<unsigned char> (fmt[i])) \
1290 { \
1291 i++; \
1292 continue; \
1293 } \
1294 else \
1295 { \
1296 is.putback (c); \
1297 break; \
1298 } \
1299 } \
1300 \
1301 if (i != n) \
1302 is.setstate (std::ios::failbit); \
1303 } \
1304 while (0)
1305
1306#define DO_PCT_CONVERSION()do { int c = is.get (); if (c != (-1)) { if (c != '%') { is.putback
(c); is.setstate (std::ios::failbit); } } else is.setstate (
std::ios::failbit); } while (0)
\
1307 do \
1308 { \
1309 int c = is.get (); \
1310 \
1311 if (c != EOF(-1)) \
1312 { \
1313 if (c != '%') \
1314 { \
1315 is.putback (c); \
1316 is.setstate (std::ios::failbit); \
1317 } \
1318 } \
1319 else \
1320 is.setstate (std::ios::failbit); \
1321 } \
1322 while (0)
1323
1324#define BEGIN_C_CONVERSION()is.unsetf (std::ios::skipws); int width = elt->width ? elt
->width : 1; std::string tmp (width, '\0'); int c = (-1); int
n = 0; while (is && n < width && (c = is.
get ()) != (-1)) tmp[n++] = static_cast<char> (c); if (
n > 0 && c == (-1)) is.clear (); tmp.resize (n)
\
1325 is.unsetf (std::ios::skipws); \
1326 \
1327 int width = elt->width ? elt->width : 1; \
1328 \
1329 std::string tmp (width, '\0'); \
1330 \
1331 int c = EOF(-1); \
1332 int n = 0; \
1333 \
1334 while (is && n < width && (c = is.get ()) != EOF(-1)) \
1335 tmp[n++] = static_cast<char> (c); \
1336 \
1337 if (n > 0 && c == EOF(-1)) \
1338 is.clear (); \
1339 \
1340 tmp.resize (n)
1341
1342// For a '%s' format, skip initial whitespace and then read until the
1343// next whitespace character or until WIDTH characters have been read.
1344#define BEGIN_S_CONVERSION()int width = elt->width; std::string tmp; do { if (width) {
tmp = std::string (width, '\0'); int c = (-1); int n = 0; while
(is && (c = is.get ()) != (-1)) { if (! isspace (c))
{ tmp[n++] = static_cast<char> (c); break; } } while (
is && n < width && (c = is.get ()) != (-1)
) { if (isspace (c)) { is.putback (c); break; } else tmp[n++]
= static_cast<char> (c); } if (n > 0 && c ==
(-1)) is.clear (); tmp.resize (n); } else { is >> std::
ws >> tmp; } } while (0)
\
1345 int width = elt->width; \
1346 \
1347 std::string tmp; \
1348 \
1349 do \
1350 { \
1351 if (width) \
1352 { \
1353 tmp = std::string (width, '\0'); \
1354 \
1355 int c = EOF(-1); \
1356 \
1357 int n = 0; \
1358 \
1359 while (is && (c = is.get ()) != EOF(-1)) \
1360 { \
1361 if (! isspace (c)) \
1362 { \
1363 tmp[n++] = static_cast<char> (c); \
1364 break; \
1365 } \
1366 } \
1367 \
1368 while (is && n < width && (c = is.get ()) != EOF(-1)) \
1369 { \
1370 if (isspace (c)) \
1371 { \
1372 is.putback (c); \
1373 break; \
1374 } \
1375 else \
1376 tmp[n++] = static_cast<char> (c); \
1377 } \
1378 \
1379 if (n > 0 && c == EOF(-1)) \
1380 is.clear (); \
1381 \
1382 tmp.resize (n); \
1383 } \
1384 else \
1385 { \
1386 is >> std::ws >> tmp; \
1387 } \
1388 } \
1389 while (0)
1390
1391// This format must match a nonempty sequence of characters.
1392#define BEGIN_CHAR_CLASS_CONVERSION()int width = elt->width; std::string tmp; do { if (! width)
width = std::numeric_limits<int>::max (); std::ostringstream
buf; std::string char_class = elt->char_class; int c = (-
1); if (elt->type == '[') { int chars_read = 0; while (is &&
chars_read++ < width && (c = is.get ()) != (-1) &&
char_class.find (c) != std::string::npos) buf << static_cast
<char> (c); } else { int chars_read = 0; while (is &&
chars_read++ < width && (c = is.get ()) != (-1) &&
char_class.find (c) == std::string::npos) buf << static_cast
<char> (c); } if (width == std::numeric_limits<int>
::max () && c != (-1)) is.putback (c); tmp = buf.str (
); if (tmp.empty ()) is.setstate (std::ios::failbit); else if
(c == (-1)) is.clear (); } while (0)
\
1393 int width = elt->width; \
1394 \
1395 std::string tmp; \
1396 \
1397 do \
1398 { \
1399 if (! width) \
1400 width = std::numeric_limits<int>::max (); \
1401 \
1402 std::ostringstream buf; \
1403 \
1404 std::string char_class = elt->char_class; \
1405 \
1406 int c = EOF(-1); \
1407 \
1408 if (elt->type == '[') \
1409 { \
1410 int chars_read = 0; \
1411 while (is && chars_read++ < width && (c = is.get ()) != EOF(-1) \
1412 && char_class.find (c) != std::string::npos) \
1413 buf << static_cast<char> (c); \
1414 } \
1415 else \
1416 { \
1417 int chars_read = 0; \
1418 while (is && chars_read++ < width && (c = is.get ()) != EOF(-1) \
1419 && char_class.find (c) == std::string::npos) \
1420 buf << static_cast<char> (c); \
1421 } \
1422 \
1423 if (width == std::numeric_limits<int>::max () && c != EOF(-1)) \
1424 is.putback (c); \
1425 \
1426 tmp = buf.str (); \
1427 \
1428 if (tmp.empty ()) \
1429 is.setstate (std::ios::failbit); \
1430 else if (c == EOF(-1)) \
1431 is.clear (); \
1432 \
1433 } \
1434 while (0)
1435
1436#define FINISH_CHARACTER_CONVERSION()do { width = tmp.length (); if (is) { int i = 0; if (! discard
) { conversion_count++; while (i < width) { if (data_index
== max_size) { max_size *= 2; if (all_char_conv) { if (one_elt_size_spec
) mval.resize (1, max_size, 0.0); else if (nr > 0) mval.resize
(nr, max_size / nr, 0.0); else panic ("impossible state reached in file '%s' at line %d"
, "corefcn/oct-stream.cc", 1436); } else if (nr > 0) mval.
resize (nr, max_size / nr, 0.0); else mval.resize (max_size, 1
, 0.0); data = mval.fortran_vec (); } data[data_index++] = tmp
[i++]; } } } } while (0)
\
1437 do \
1438 { \
1439 width = tmp.length (); \
1440 \
1441 if (is) \
1442 { \
1443 int i = 0; \
1444 \
1445 if (! discard) \
1446 { \
1447 conversion_count++; \
1448 \
1449 while (i < width) \
1450 { \
1451 if (data_index == max_size) \
1452 { \
1453 max_size *= 2; \
1454 \
1455 if (all_char_conv) \
1456 { \
1457 if (one_elt_size_spec) \
1458 mval.resize (1, max_size, 0.0); \
1459 else if (nr > 0) \
1460 mval.resize (nr, max_size / nr, 0.0); \
1461 else \
1462 panic_impossible ()panic ("impossible state reached in file '%s' at line %d", "corefcn/oct-stream.cc"
, 1462)
; \
1463 } \
1464 else if (nr > 0) \
1465 mval.resize (nr, max_size / nr, 0.0); \
1466 else \
1467 mval.resize (max_size, 1, 0.0); \
1468 \
1469 data = mval.fortran_vec (); \
1470 } \
1471 \
1472 data[data_index++] = tmp[i++]; \
1473 } \
1474 } \
1475 } \
1476 } \
1477 while (0)
1478
1479octave_value
1480octave_base_stream::do_scanf (scanf_format_list& fmt_list,
1481 octave_idx_type nr, octave_idx_type nc,
1482 bool one_elt_size_spec,
1483 octave_idx_type& conversion_count,
1484 const std::string& who)
1485{
1486 octave_value retval = Matrix ();
1487
1488 if ((interactive || forced_interactive) && file_number () == 0)
1489 {
1490 ::error ("%s: unable to read from stdin while running interactively",
1491 who.c_str ());
1492
1493 return retval;
1494 }
1495
1496 conversion_count = 0;
1497
1498 octave_idx_type nconv = fmt_list.num_conversions ();
1499
1500 octave_idx_type data_index = 0;
1501
1502 if (nr == 0 || nc == 0)
1503 {
1504 if (one_elt_size_spec)
1505 nc = 0;
1506
1507 return Matrix (nr, nc, 0.0);
1508 }
1509
1510 std::istream *isp = input_stream ();
1511
1512 bool all_char_conv = fmt_list.all_character_conversions ();
1513
1514 Matrix mval;
1515 double *data = 0;
1516 octave_idx_type max_size = 0;
1517 octave_idx_type max_conv = 0;
1518
1519 octave_idx_type final_nr = 0;
1520 octave_idx_type final_nc = 0;
1521
1522 if (all_char_conv)
1523 {
1524 // Any of these could be resized later (if we have %s
1525 // conversions, we may read more than one element for each
1526 // conversion).
1527
1528 if (one_elt_size_spec)
1529 {
1530 max_size = 512;
1531 mval.resize (1, max_size, 0.0);
1532
1533 if (nr > 0)
1534 max_conv = nr;
1535 }
1536 else if (nr > 0)
1537 {
1538 if (nc > 0)
1539 {
1540 mval.resize (nr, nc, 0.0);
1541 max_size = max_conv = nr * nc;
1542 }
1543 else
1544 {
1545 mval.resize (nr, 32, 0.0);
1546 max_size = nr * 32;
1547 }
1548 }
1549 else
1550 panic_impossible ()panic ("impossible state reached in file '%s' at line %d", "corefcn/oct-stream.cc"
, 1550)
;
1551 }
1552 else if (nr > 0)
1553 {
1554 if (nc > 0)
1555 {
1556 // Will not resize later.
1557 mval.resize (nr, nc, 0.0);
1558 max_size = nr * nc;
1559 max_conv = max_size;
1560 }
1561 else
1562 {
1563 // Maybe resize later.
1564 mval.resize (nr, 32, 0.0);
1565 max_size = nr * 32;
1566 }
1567 }
1568 else
1569 {
1570 // Maybe resize later.
1571 mval.resize (32, 1, 0.0);
1572 max_size = 32;
1573 }
1574
1575 data = mval.fortran_vec ();
1576
1577 if (isp)
1578 {
1579 std::istream& is = *isp;
1580
1581 const scanf_format_elt *elt = fmt_list.first ();
1582
1583 std::ios::fmtflags flags = is.flags ();
1584
1585 octave_idx_type trips = 0;
1586
1587 octave_idx_type num_fmt_elts = fmt_list.length ();
1588
1589 for (;;)
1590 {
1591 octave_quit ();
1592
1593 if (elt)
1594 {
1595 if (! (elt->type == scanf_format_elt::whitespace_conversion
1596 || elt->type == scanf_format_elt::literal_conversion
1597 || elt->type == '%')
1598 && max_conv > 0 && conversion_count == max_conv)
1599 {
1600 if (all_char_conv && one_elt_size_spec)
1601 {
1602 final_nr = 1;
1603 final_nc = data_index;
1604 }
1605 else
1606 {
1607 final_nr = nr;
1608 final_nc = (data_index - 1) / nr + 1;
1609 }
1610
1611 break;
1612 }
1613 else if (data_index == max_size)
1614 {
1615 max_size *= 2;
1616
1617 if (all_char_conv)
1618 {
1619 if (one_elt_size_spec)
1620 mval.resize (1, max_size, 0.0);
1621 else if (nr > 0)
1622 mval.resize (nr, max_size / nr, 0.0);
1623 else
1624 panic_impossible ()panic ("impossible state reached in file '%s' at line %d", "corefcn/oct-stream.cc"
, 1624)
;
1625 }
1626 else if (nr > 0)
1627 mval.resize (nr, max_size / nr, 0.0);
1628 else
1629 mval.resize (max_size, 1, 0.0);
1630
1631 data = mval.fortran_vec ();
1632 }
1633
1634 const char *fmt = elt->text;
1635
1636 bool discard = elt->discard;
1637
1638 switch (elt->type)
1639 {
1640 case scanf_format_elt::whitespace_conversion:
1641 DO_WHITESPACE_CONVERSION ()do { int c = (-1); while (is && (c = is.get ()) != (-
1) && isspace (c)) ; if (c != (-1)) is.putback (c); }
while (0)
;
1642 break;
1643
1644 case scanf_format_elt::literal_conversion:
1645 DO_LITERAL_CONVERSION ()do { int c = (-1); int n = strlen (fmt); int i = 0; while (i <
n && is && (c = is.get ()) != (-1)) { if (c ==
static_cast<unsigned char> (fmt[i])) { i++; continue; }
else { is.putback (c); break; } } if (i != n) is.setstate (std
::ios::failbit); } while (0)
;
1646 break;
1647
1648 case '%':
1649 DO_PCT_CONVERSION ()do { int c = is.get (); if (c != (-1)) { if (c != '%') { is.putback
(c); is.setstate (std::ios::failbit); } } else is.setstate (
std::ios::failbit); } while (0)
;
1650 break;
1651
1652 case 'd': case 'i':
1653 {
1654 switch (elt->modifier)
1655 {
1656 case 'h':
1657 {
1658 short int tmp;
1659 do_scanf_conv (is, *elt, &tmp, mval, data,
1660 data_index, conversion_count,
1661 nr, max_size, discard);
1662 }
1663 break;
1664
1665 case 'l':
1666 {
1667 long int tmp;
1668 do_scanf_conv (is, *elt, &tmp, mval, data,
1669 data_index, conversion_count,
1670 nr, max_size, discard);
1671 }
1672 break;
1673
1674 default:
1675 {
1676 int tmp;
1677 do_scanf_conv (is, *elt, &tmp, mval, data,
1678 data_index, conversion_count,
1679 nr, max_size, discard);
1680 }
1681 break;
1682 }
1683 }
1684 break;
1685
1686 case 'o': case 'u': case 'x':
1687 {
1688 switch (elt->modifier)
1689 {
1690 case 'h':
1691 {
1692 unsigned short int tmp;
1693 do_scanf_conv (is, *elt, &tmp, mval, data,
1694 data_index, conversion_count,
1695 nr, max_size, discard);
1696 }
1697 break;
1698
1699 case 'l':
1700 {
1701 unsigned long int tmp;
1702 do_scanf_conv (is, *elt, &tmp, mval, data,
1703 data_index, conversion_count,
1704 nr, max_size, discard);
1705 }
1706 break;
1707
1708 default:
1709 {
1710 unsigned int tmp;
1711 do_scanf_conv (is, *elt, &tmp, mval, data,
1712 data_index, conversion_count,
1713 nr, max_size, discard);
1714 }
1715 break;
1716 }
1717 }
1718 break;
1719
1720 case 'e': case 'f': case 'g':
1721 {
1722 double tmp;
1723
1724 do_scanf_conv (is, *elt, &tmp, mval, data,
1725 data_index, conversion_count,
1726 nr, max_size, discard);
1727 }
1728 break;
1729
1730 case 'c':
1731 {
1732 BEGIN_C_CONVERSION ()is.unsetf (std::ios::skipws); int width = elt->width ? elt
->width : 1; std::string tmp (width, '\0'); int c = (-1); int
n = 0; while (is && n < width && (c = is.
get ()) != (-1)) tmp[n++] = static_cast<char> (c); if (
n > 0 && c == (-1)) is.clear (); tmp.resize (n)
;
1733
1734 FINISH_CHARACTER_CONVERSION ()do { width = tmp.length (); if (is) { int i = 0; if (! discard
) { conversion_count++; while (i < width) { if (data_index
== max_size) { max_size *= 2; if (all_char_conv) { if (one_elt_size_spec
) mval.resize (1, max_size, 0.0); else if (nr > 0) mval.resize
(nr, max_size / nr, 0.0); else panic ("impossible state reached in file '%s' at line %d"
, "corefcn/oct-stream.cc", 1734); } else if (nr > 0) mval.
resize (nr, max_size / nr, 0.0); else mval.resize (max_size, 1
, 0.0); data = mval.fortran_vec (); } data[data_index++] = tmp
[i++]; } } } } while (0)
;
1735
1736 is.setf (flags);
1737 }
1738 break;
1739
1740 case 's':
1741 {
1742 BEGIN_S_CONVERSION ()int width = elt->width; std::string tmp; do { if (width) {
tmp = std::string (width, '\0'); int c = (-1); int n = 0; while
(is && (c = is.get ()) != (-1)) { if (! isspace (c))
{ tmp[n++] = static_cast<char> (c); break; } } while (
is && n < width && (c = is.get ()) != (-1)
) { if (isspace (c)) { is.putback (c); break; } else tmp[n++]
= static_cast<char> (c); } if (n > 0 && c ==
(-1)) is.clear (); tmp.resize (n); } else { is >> std::
ws >> tmp; } } while (0)
;
1743
1744 FINISH_CHARACTER_CONVERSION ()do { width = tmp.length (); if (is) { int i = 0; if (! discard
) { conversion_count++; while (i < width) { if (data_index
== max_size) { max_size *= 2; if (all_char_conv) { if (one_elt_size_spec
) mval.resize (1, max_size, 0.0); else if (nr > 0) mval.resize
(nr, max_size / nr, 0.0); else panic ("impossible state reached in file '%s' at line %d"
, "corefcn/oct-stream.cc", 1744); } else if (nr > 0) mval.
resize (nr, max_size / nr, 0.0); else mval.resize (max_size, 1
, 0.0); data = mval.fortran_vec (); } data[data_index++] = tmp
[i++]; } } } } while (0)
;
1745 }
1746 break;
1747
1748 case '[': case '^':
1749 {
1750 BEGIN_CHAR_CLASS_CONVERSION ()int width = elt->width; std::string tmp; do { if (! width)
width = std::numeric_limits<int>::max (); std::ostringstream
buf; std::string char_class = elt->char_class; int c = (-
1); if (elt->type == '[') { int chars_read = 0; while (is &&
chars_read++ < width && (c = is.get ()) != (-1) &&
char_class.find (c) != std::string::npos) buf << static_cast
<char> (c); } else { int chars_read = 0; while (is &&
chars_read++ < width && (c = is.get ()) != (-1) &&
char_class.find (c) == std::string::npos) buf << static_cast
<char> (c); } if (width == std::numeric_limits<int>
::max () && c != (-1)) is.putback (c); tmp = buf.str (
); if (tmp.empty ()) is.setstate (std::ios::failbit); else if
(c == (-1)) is.clear (); } while (0)
;
1751
1752 FINISH_CHARACTER_CONVERSION ()do { width = tmp.length (); if (is) { int i = 0; if (! discard
) { conversion_count++; while (i < width) { if (data_index
== max_size) { max_size *= 2; if (all_char_conv) { if (one_elt_size_spec
) mval.resize (1, max_size, 0.0); else if (nr > 0) mval.resize
(nr, max_size / nr, 0.0); else panic ("impossible state reached in file '%s' at line %d"
, "corefcn/oct-stream.cc", 1752); } else if (nr > 0) mval.
resize (nr, max_size / nr, 0.0); else mval.resize (max_size, 1
, 0.0); data = mval.fortran_vec (); } data[data_index++] = tmp
[i++]; } } } } while (0)
;
1753 }
1754 break;
1755
1756 case 'p':
1757 error ("%s: unsupported format specifier", who.c_str ());
1758 break;
1759
1760 default:
1761 error ("%s: internal format error", who.c_str ());
1762 break;
1763 }
1764
1765 if (! ok ())
1766 {
1767 break;
1768 }
1769 else if (! is)
1770 {
1771 if (all_char_conv)
1772 {
1773 if (one_elt_size_spec)
1774 {
1775 final_nr = 1;
1776 final_nc = data_index;
1777 }
1778 else if (data_index > nr)
1779 {
1780 final_nr = nr;
1781 final_nc = (data_index - 1) / nr + 1;
1782 }
1783 else
1784 {
1785 final_nr = data_index;
1786 final_nc = 1;
1787 }
1788 }
1789 else if (nr > 0)
1790 {
1791 if (data_index > nr)
1792 {
1793 final_nr = nr;
1794 final_nc = (data_index - 1) / nr + 1;
1795 }
1796 else
1797 {
1798 final_nr = data_index;
1799 final_nc = 1;
1800 }
1801 }
1802 else
1803 {
1804 final_nr = data_index;
1805 final_nc = 1;
1806 }
1807
1808 // If it looks like we have a matching failure, then
1809 // reset the failbit in the stream state.
1810
1811 if (is.rdstate () & std::ios::failbit)
1812 is.clear (is.rdstate () & (~std::ios::failbit));
1813
1814 // FIXME: is this the right thing to do?
1815
1816 if (interactive && name () == "stdin")
1817 {
1818 is.clear ();
1819
1820 // Skip to end of line.
1821
1822 bool err;
1823 do_gets (-1, err, false, who);
1824 }
1825
1826 break;
1827 }
1828 }
1829 else
1830 {
1831 error ("%s: internal format error", who.c_str ());
1832 break;
1833 }
1834
1835 if (nconv == 0 && ++trips == num_fmt_elts)
1836 {
1837 if (all_char_conv && one_elt_size_spec)
1838 {
1839 final_nr = 1;
1840 final_nc = data_index;
1841 }
1842 else
1843 {
1844 final_nr = nr;
1845 final_nc = (data_index - 1) / nr + 1;
1846 }
1847
1848 break;
1849 }
1850 else
1851 elt = fmt_list.next (nconv > 0);
1852 }
1853 }
1854
1855 if (ok ())
1856 {
1857 mval.resize (final_nr, final_nc, 0.0);
1858
1859 retval = mval;
1860
1861 if (all_char_conv)
1862 retval = retval.convert_to_str (false, true);
1863 }
1864
1865 return retval;
1866}
1867
1868octave_value
1869octave_base_stream::scanf (const std::string& fmt, const Array<double>& size,
1870 octave_idx_type& conversion_count,
1871 const std::string& who)
1872{
1873 octave_value retval = Matrix ();
1874
1875 conversion_count = 0;
1876
1877 std::istream *isp = input_stream ();
1878
1879 if (isp)
1880 {
1881 scanf_format_list fmt_list (fmt);
1882
1883 if (fmt_list.num_conversions () == -1)
1884 ::error ("%s: invalid format specified", who.c_str ());
1885 else
1886 {
1887 octave_idx_type nr = -1;
1888 octave_idx_type nc = -1;
1889
1890 bool one_elt_size_spec;
1891
1892 get_size (size, nr, nc, one_elt_size_spec, who);
1893
1894 if (! error_state)
1895 retval = do_scanf (fmt_list, nr, nc, one_elt_size_spec,
1896 conversion_count, who);
1897 }
1898 }
1899 else
1900 invalid_operation (who, "reading");
1901
1902 return retval;
1903}
1904
1905bool
1906octave_base_stream::do_oscanf (const scanf_format_elt *elt,
1907 octave_value& retval, const std::string& who)
1908{
1909 bool quit = false;
1910
1911 std::istream *isp = input_stream ();
1912
1913 if (isp)
1914 {
1915 std::istream& is = *isp;
1916
1917 std::ios::fmtflags flags = is.flags ();
1918
1919 if (elt)
1920 {
1921 const char *fmt = elt->text;
1922
1923 bool discard = elt->discard;
1924
1925 switch (elt->type)
1926 {
1927 case scanf_format_elt::whitespace_conversion:
1928 DO_WHITESPACE_CONVERSION ()do { int c = (-1); while (is && (c = is.get ()) != (-
1) && isspace (c)) ; if (c != (-1)) is.putback (c); }
while (0)
;
1929 break;
1930
1931 case scanf_format_elt::literal_conversion:
1932 DO_LITERAL_CONVERSION ()do { int c = (-1); int n = strlen (fmt); int i = 0; while (i <
n && is && (c = is.get ()) != (-1)) { if (c ==
static_cast<unsigned char> (fmt[i])) { i++; continue; }
else { is.putback (c); break; } } if (i != n) is.setstate (std
::ios::failbit); } while (0)
;
1933 break;
1934
1935 case '%':
1936 {
1937 DO_PCT_CONVERSION ()do { int c = is.get (); if (c != (-1)) { if (c != '%') { is.putback
(c); is.setstate (std::ios::failbit); } } else is.setstate (
std::ios::failbit); } while (0)
;
1938
1939 if (! is)
1940 quit = true;
1941
1942 }
1943 break;
1944
1945 case 'd': case 'i':
1946 {
1947 int tmp;
1948
1949 if (OCTAVE_SCAN (is, *elt, &tmp)octave_scan (is, *elt, &tmp))
1950 {
1951 if (! discard)
1952 retval = tmp;
1953 }
1954 else
1955 quit = true;
1956 }
1957 break;
1958
1959 case 'o': case 'u': case 'x':
1960 {
1961 long int tmp;
1962
1963 if (OCTAVE_SCAN (is, *elt, &tmp)octave_scan (is, *elt, &tmp))
1964 {
1965 if (! discard)
1966 retval = tmp;
1967 }
1968 else
1969 quit = true;
1970 }
1971 break;
1972
1973 case 'e': case 'f': case 'g':
1974 {
1975 double tmp;
1976
1977 if (OCTAVE_SCAN (is, *elt, &tmp)octave_scan (is, *elt, &tmp))
1978 {
1979 if (! discard)
1980 retval = tmp;
1981 }
1982 else
1983 quit = true;
1984 }
1985 break;
1986
1987 case 'c':
1988 {
1989 BEGIN_C_CONVERSION ()is.unsetf (std::ios::skipws); int width = elt->width ? elt
->width : 1; std::string tmp (width, '\0'); int c = (-1); int
n = 0; while (is && n < width && (c = is.
get ()) != (-1)) tmp[n++] = static_cast<char> (c); if (
n > 0 && c == (-1)) is.clear (); tmp.resize (n)
;
1990
1991 if (! discard)
1992 retval = tmp;
1993
1994 if (! is)
1995 quit = true;
1996
1997 is.setf (flags);
1998 }
1999 break;
2000
2001 case 's':
2002 {
2003 BEGIN_S_CONVERSION ()int width = elt->width; std::string tmp; do { if (width) {
tmp = std::string (width, '\0'); int c = (-1); int n = 0; while
(is && (c = is.get ()) != (-1)) { if (! isspace (c))
{ tmp[n++] = static_cast<char> (c); break; } } while (
is && n < width && (c = is.get ()) != (-1)
) { if (isspace (c)) { is.putback (c); break; } else tmp[n++]
= static_cast<char> (c); } if (n > 0 && c ==
(-1)) is.clear (); tmp.resize (n); } else { is >> std::
ws >> tmp; } } while (0)
;
2004
2005 if (! discard)
2006 retval = tmp;
2007
2008 if (! is)
2009 quit = true;
2010 }
2011 break;
2012
2013 case '[': case '^':
2014 {
2015 BEGIN_CHAR_CLASS_CONVERSION ()int width = elt->width; std::string tmp; do { if (! width)
width = std::numeric_limits<int>::max (); std::ostringstream
buf; std::string char_class = elt->char_class; int c = (-
1); if (elt->type == '[') { int chars_read = 0; while (is &&
chars_read++ < width && (c = is.get ()) != (-1) &&
char_class.find (c) != std::string::npos) buf << static_cast
<char> (c); } else { int chars_read = 0; while (is &&
chars_read++ < width && (c = is.get ()) != (-1) &&
char_class.find (c) == std::string::npos) buf << static_cast
<char> (c); } if (width == std::numeric_limits<int>
::max () && c != (-1)) is.putback (c); tmp = buf.str (
); if (tmp.empty ()) is.setstate (std::ios::failbit); else if
(c == (-1)) is.clear (); } while (0)
;
2016
2017 if (! discard)
2018 retval = tmp;
2019
2020 if (! is)
2021 quit = true;
2022 }
2023 break;
2024
2025 case 'p':
2026 error ("%s: unsupported format specifier", who.c_str ());
2027 break;
2028
2029 default:
2030 error ("%s: internal format error", who.c_str ());
2031 break;
2032 }
2033 }
2034
2035 if (ok () && is.fail ())
2036 {
2037 error ("%s: read error", who.c_str ());
2038
2039 // FIXME: is this the right thing to do?
2040
2041 if (interactive && name () == "stdin")
2042 {
2043 // Skip to end of line.
2044
2045 bool err;
2046 do_gets (-1, err, false, who);
2047 }
2048 }
2049 }
2050
2051 return quit;
2052}
2053
2054octave_value_list
2055octave_base_stream::oscanf (const std::string& fmt, const std::string& who)
2056{
2057 octave_value_list retval;
2058
2059 std::istream *isp = input_stream ();
2060
2061 if (isp)
2062 {
2063 std::istream& is = *isp;
2064
2065 scanf_format_list fmt_list (fmt);
2066
2067 octave_idx_type nconv = fmt_list.num_conversions ();
2068
2069 if (nconv == -1)
2070 ::error ("%s: invalid format specified", who.c_str ());
2071 else
2072 {
2073 is.clear ();
2074
2075 octave_idx_type len = fmt_list.length ();
2076
2077 retval.resize (nconv+2, Matrix ());
2078
2079 const scanf_format_elt *elt = fmt_list.first ();
2080
2081 int num_values = 0;
2082
2083 bool quit = false;
2084
2085 for (octave_idx_type i = 0; i < len; i++)
2086 {
2087 octave_value tmp;
2088
2089 quit = do_oscanf (elt, tmp, who);
2090
2091 if (quit)
2092 break;
2093 else
2094 {
2095 if (tmp.is_defined ())
2096 retval(num_values++) = tmp;
2097
2098 if (! ok ())
2099 break;
2100
2101 elt = fmt_list.next (nconv > 0);
2102 }
2103 }
2104
2105 retval(nconv) = num_values;
2106
2107 int err_num;
2108 retval(nconv+1) = error (false, err_num);
2109
2110 if (! quit)
2111 {
2112 // Pick up any trailing stuff.
2113 if (ok () && len > nconv)
2114 {
2115 octave_value tmp;
2116
2117 elt = fmt_list.next ();
2118
2119 do_oscanf (elt, tmp, who);
2120 }
2121 }
2122 }
2123 }
2124 else
2125 invalid_operation (who, "reading");
2126
2127 return retval;
2128}
2129
2130// Functions that are defined for all output streams (output streams
2131// are those that define os).
2132
2133int
2134octave_base_stream::flush (void)
2135{
2136 int retval = -1;
2137
2138 std::ostream *os = output_stream ();
2139
2140 if (os)
2141 {
2142 os->flush ();
2143
2144 if (os->good ())
2145 retval = 0;
2146 }
2147 else
2148 invalid_operation ("fflush", "writing");
2149
2150 return retval;
2151}
2152
2153class
2154printf_value_cache
2155{
2156public:
2157
2158 enum state { ok, conversion_error };
2159
2160 printf_value_cache (const octave_value_list& args, const std::string& who)
2161 : values (args), val_idx (0), elt_idx (0),
2162 n_vals (values.length ()), n_elts (0), data (0),
2163 curr_state (ok)
2164 {
2165 for (octave_idx_type i = 0; i < values.length (); i++)
2166 {
2167 octave_value val = values(i);
2168
2169 if (val.is_map () || val.is_cell () || val.is_object ())
2170 {
2171 gripe_wrong_type_arg (who, val);
2172 break;
2173 }
2174 }
2175 }
2176
2177 ~printf_value_cache (void) { }
2178
2179 // Get the current value as a double and advance the internal pointer.
2180 double double_value (void);
2181
2182 // Get the current value as an int and advance the internal pointer.
2183 int int_value (void);
2184
2185 // Get the current value as a string and advance the internal pointer.
2186 std::string string_value (void);
2187
2188 operator bool () const { return (curr_state == ok); }
2189
2190 bool exhausted (void) { return (val_idx >= n_vals); }
2191
2192private:
2193
2194 const octave_value_list values;
2195 int val_idx;
2196 int elt_idx;
2197 int n_vals;
2198 int n_elts;
2199 const double *data;
2200 NDArray curr_val;
2201 state curr_state;
2202
2203 // Must create value cache with values!
2204
2205 printf_value_cache (void);
2206
2207 // No copying!
2208
2209 printf_value_cache (const printf_value_cache&);
2210
2211 printf_value_cache& operator = (const printf_value_cache&);
2212};
2213
2214double
2215printf_value_cache::double_value (void)
2216{
2217 double retval = 0.0;
2218
2219 if (exhausted ())
2220 curr_state = conversion_error;
2221
2222 while (! exhausted ())
2223 {
2224 if (! data)
2225 {
2226 octave_value tmp_val = values (val_idx);
2227
2228 // Force string conversion here for compatibility.
2229
2230 curr_val = tmp_val.array_value (true);
2231
2232 if (! error_state)
2233 {
2234 elt_idx = 0;
2235 n_elts = curr_val.length ();
2236 data = curr_val.data ();
2237 }
2238 else
2239 {
2240 curr_state = conversion_error;
2241 break;
2242 }
2243 }
2244
2245 if (elt_idx < n_elts)
2246 {
2247 retval = data[elt_idx++];
2248
2249 if (elt_idx >= n_elts)
2250 {
2251 elt_idx = 0;
2252 val_idx++;
2253 data = 0;
2254 }
2255
2256 break;
2257 }
2258 else
2259 {
2260 val_idx++;
2261 data = 0;
2262
2263 if (n_elts == 0 && exhausted ())
2264 curr_state = conversion_error;
2265
2266 continue;
2267 }
2268 }
2269
2270 return retval;
2271}
2272
2273int
2274printf_value_cache::int_value (void)
2275{
2276 int retval = 0;
2277
2278 double dval = double_value ();
2279
2280 if (! error_state)
2281 {
2282 if (D_NINT (dval) == dval)
2283 retval = NINT (dval);
2284 else
2285 curr_state = conversion_error;
2286 }
2287
2288 return retval;
2289}
2290
2291std::string
2292printf_value_cache::string_value (void)
2293{
2294 std::string retval;
2295
2296 if (exhausted ())
2297 curr_state = conversion_error;
2298 else
2299 {
2300 octave_value tval = values (val_idx++);
2301
2302 if (tval.rows () == 1)
2303 retval = tval.string_value ();
2304 else
2305 {
2306 // In the name of Matlab compatibility.
2307
2308 charMatrix chm = tval.char_matrix_value ();
2309
2310 octave_idx_type nr = chm.rows ();
2311 octave_idx_type nc = chm.columns ();
2312
2313 int k = 0;
2314
2315 retval.resize (nr * nc, '\0');
2316
2317 for (octave_idx_type j = 0; j < nc; j++)
2318 for (octave_idx_type i = 0; i < nr; i++)
2319 retval[k++] = chm(i,j);
2320 }
2321
2322 if (error_state)
2323 curr_state = conversion_error;
2324 }
2325
2326 return retval;
2327}
2328
2329// Ugh again and again.
2330
2331template <class T>
2332int
2333do_printf_conv (std::ostream& os, const char *fmt, int nsa, int sa_1,
2334 int sa_2, T arg, const std::string& who)
2335{
2336 int retval = 0;
2337
2338 switch (nsa)
2339 {
2340 case 2:
2341 retval = octave_format (os, fmt, sa_1, sa_2, arg);
2342 break;
2343
2344 case 1:
2345 retval = octave_format (os, fmt, sa_1, arg);
2346 break;
2347
2348 case 0:
2349 retval = octave_format (os, fmt, arg);
2350 break;
2351
2352 default:
2353 ::error ("%s: internal error handling format", who.c_str ());
2354 break;
2355 }
2356
2357 return retval;
2358}
2359
2360#define DO_DOUBLE_CONV(TQUAL)do { if (val > std::numeric_limits<TQUAL long>::max (
) || val < std::numeric_limits<TQUAL long>::min ()) {
std::string tfmt = fmt; tfmt.replace (tfmt.rfind (elt->type
), 1, ".f"); if (elt->modifier == 'l') tfmt.replace (tfmt.
rfind (elt->modifier), 1, ""); retval += do_printf_conv (os
, tfmt.c_str (), nsa, sa_1, sa_2, val, who); } else retval +=
do_printf_conv (os, fmt, nsa, sa_1, sa_2, static_cast<TQUAL
long> (val), who); } while (0)
\
2361 do \
2362 { \
2363 if (val > std::numeric_limits<TQUAL long>::max () \
2364 || val < std::numeric_limits<TQUAL long>::min ()) \
2365 { \
2366 std::string tfmt = fmt; \
2367 \
2368 tfmt.replace (tfmt.rfind (elt->type), 1, ".f"); \
2369 \
2370 if (elt->modifier == 'l') \
2371 tfmt.replace (tfmt.rfind (elt->modifier), 1, ""); \
2372 \
2373 retval += do_printf_conv (os, tfmt.c_str (), nsa, sa_1, sa_2, \
2374 val, who); \
2375 } \
2376 else \
2377 retval += do_printf_conv (os, fmt, nsa, sa_1, sa_2, \
2378 static_cast<TQUAL long> (val), who); \
2379 } \
2380 while (0)
2381
2382int
2383octave_base_stream::do_printf (printf_format_list& fmt_list,
2384 const octave_value_list& args,
2385 const std::string& who)
2386{
2387 int retval = 0;
2388
2389 octave_idx_type nconv = fmt_list.num_conversions ();
2390
2391 std::ostream *osp = output_stream ();
2392
2393 if (osp)
2394 {
2395 std::ostream& os = *osp;
2396
2397 const printf_format_elt *elt = fmt_list.first ();
2398
2399 printf_value_cache val_cache (args, who);
2400
2401 if (error_state)
2402 return retval;
2403
2404 for (;;)
2405 {
2406 octave_quit ();
2407
2408 if (elt)
2409 {
2410 // NSA is the number of 'star' args to convert.
2411
2412 int nsa = (elt->fw < 0) + (elt->prec < 0);
2413
2414 int sa_1 = 0;
2415 int sa_2 = 0;
2416
2417 if (nsa > 0)
2418 {
2419 sa_1 = val_cache.int_value ();
2420
2421 if (! val_cache)
2422 break;
2423 else
2424 {
2425 if (nsa > 1)
2426 {
2427 sa_2 = val_cache.int_value ();
2428
2429 if (! val_cache)
2430 break;
2431 }
2432 }
2433 }
2434
2435 const char *fmt = elt->text;
2436
2437 if (elt->type == '%')
2438 {
2439 os << "%";
2440 retval++;
2441 }
2442 else if (elt->args == 0 && elt->text)
2443 {
2444 os << elt->text;
2445 retval += strlen (elt->text);
2446 }
2447 else if (elt->type == 's')
2448 {
2449 std::string val = val_cache.string_value ();
2450
2451 if (val_cache)
2452 retval += do_printf_conv (os, fmt, nsa, sa_1,
2453 sa_2, val.c_str (), who);
2454 else
2455 break;
2456 }
2457 else
2458 {
2459 double val = val_cache.double_value ();
2460
2461 if (val_cache)
2462 {
2463 if (lo_ieee_isnan (val)(sizeof (val) == sizeof (float) ? __lo_ieee_float_isnan (val)
: __lo_ieee_isnan (val))
|| xisinf (val))
2464 {
2465 std::string tfmt = fmt;
2466 std::string::size_type i1, i2;
2467
2468 tfmt.replace ((i1 = tfmt.rfind (elt->type)),
2469 1, 1, 's');
2470
2471 if ((i2 = tfmt.rfind ('.')) != std::string::npos
2472 && i2 < i1)
2473 {
2474 tfmt.erase (i2, i1-i2);
2475 if (elt->prec < 0)
2476 nsa--;
2477 }
2478
2479 const char *tval;
2480 if (xisinf (val))
2481 if (elt->flags.find ('+') != std::string::npos)
2482 tval = (val < 0 ? "-Inf" : "+Inf");
2483 else
2484 tval = (val < 0 ? "-Inf" : "Inf");
2485 else
2486 if (elt->flags.find ('+') != std::string::npos)
2487 tval = (lo_ieee_is_NA (val)(sizeof (val) == sizeof (float) ? __lo_ieee_float_is_NA (val)
: __lo_ieee_is_NA (val))
? "+NA" : "+NaN");
2488 else
2489 tval = (lo_ieee_is_NA (val)(sizeof (val) == sizeof (float) ? __lo_ieee_float_is_NA (val)
: __lo_ieee_is_NA (val))
? "NA" : "NaN");
2490
2491 retval += do_printf_conv (os, tfmt.c_str (),
2492 nsa, sa_1, sa_2,
2493 tval, who);
2494 }
2495 else
2496 {
2497 char type = elt->type;
2498
2499 switch (type)
2500 {
2501 case 'd': case 'i': case 'c':
2502 DO_DOUBLE_CONV (OCTAVE_EMPTY_CPP_ARG)do { if (val > std::numeric_limits< long>::max () ||
val < std::numeric_limits< long>::min ()) { std::string
tfmt = fmt; tfmt.replace (tfmt.rfind (elt->type), 1, ".f"
); if (elt->modifier == 'l') tfmt.replace (tfmt.rfind (elt
->modifier), 1, ""); retval += do_printf_conv (os, tfmt.c_str
(), nsa, sa_1, sa_2, val, who); } else retval += do_printf_conv
(os, fmt, nsa, sa_1, sa_2, static_cast< long> (val), who
); } while (0)
;
2503 break;
2504
2505 case 'o': case 'x': case 'X': case 'u':
2506 DO_DOUBLE_CONV (unsigned)do { if (val > std::numeric_limits<unsigned long>::max
() || val < std::numeric_limits<unsigned long>::min
()) { std::string tfmt = fmt; tfmt.replace (tfmt.rfind (elt->
type), 1, ".f"); if (elt->modifier == 'l') tfmt.replace (tfmt
.rfind (elt->modifier), 1, ""); retval += do_printf_conv (
os, tfmt.c_str (), nsa, sa_1, sa_2, val, who); } else retval +=
do_printf_conv (os, fmt, nsa, sa_1, sa_2, static_cast<unsigned
long> (val), who); } while (0)
;
2507 break;
2508
2509 case 'f': case 'e': case 'E':
2510 case 'g': case 'G':
2511 retval += do_printf_conv (os, fmt, nsa,
2512 sa_1, sa_2, val, who);
2513 break;
2514
2515 default:
2516 error ("%s: invalid format specifier",
2517 who.c_str ());
2518 return -1;
2519 break;
2520 }
2521 }
2522 }
2523 else
2524 break;
2525 }
2526
2527 if (! os)
2528 {
2529 error ("%s: write error", who.c_str ());
2530 break;
2531 }
2532 }
2533 else
2534 {
2535 ::error ("%s: internal error handling format", who.c_str ());
2536 retval = -1;
2537 break;
2538 }
2539
2540 elt = fmt_list.next (nconv > 0 && ! val_cache.exhausted ());
2541
2542 if (! elt || (val_cache.exhausted () && elt->args > 0))
2543 break;
2544 }
2545 }
2546 else
2547 invalid_operation (who, "writing");
2548
2549 return retval;
2550}
2551
2552int
2553octave_base_stream::printf (const std::string& fmt,
2554 const octave_value_list& args,
2555 const std::string& who)
2556{
2557 int retval = 0;
2558
2559 printf_format_list fmt_list (fmt);
2560
2561 if (fmt_list.num_conversions () == -1)
2562 ::error ("%s: invalid format specified", who.c_str ());
2563 else
2564 retval = do_printf (fmt_list, args, who);
2565
2566 return retval;
2567}
2568
2569int
2570octave_base_stream::puts (const std::string& s, const std::string& who)
2571{
2572 int retval = -1;
2573
2574 std::ostream *osp = output_stream ();
2575
2576 if (osp)
2577 {
2578 std::ostream& os = *osp;
2579
2580 os << s;
2581
2582 if (os)
2583 {
2584 // FIXME: why does this seem to be necessary?
2585 // Without it, output from a loop like
2586 //
2587 // for i = 1:100, fputs (stdout, "foo\n"); endfor
2588 //
2589 // doesn't seem to go to the pager immediately.
2590
2591 os.flush ();
2592
2593 if (os)
2594 retval = 0;
2595 else
2596 error ("%s: write error", who.c_str ());
2597 }
2598 else
2599 error ("%s: write error", who.c_str ());
2600 }
2601 else
2602 invalid_operation (who, "writing");
2603
2604 return retval;
2605}
2606
2607// Return current error message for this stream.
2608
2609std::string
2610octave_base_stream::error (bool clear_err, int& err_num)
2611{
2612 err_num = fail ? -1 : 0;
2613
2614 std::string tmp = errmsg;
2615
2616 if (clear_err)
2617 clear ();
2618
2619 return tmp;
2620}
2621
2622void
2623octave_base_stream::invalid_operation (const std::string& who, const char *rw)
2624{
2625 // Note that this is not ::error () !
2626
2627 error (who, std::string ("stream not open for ") + rw);
2628}
2629
2630octave_stream::octave_stream (octave_base_stream *bs)
2631 : rep (bs)
2632{
2633 if (rep)
2634 rep->count = 1;
2635}
2636
2637octave_stream::~octave_stream (void)
2638{
2639 if (rep && --rep->count == 0)
2640 delete rep;
2641}
2642
2643octave_stream::octave_stream (const octave_stream& s)
2644 : rep (s.rep)
2645{
2646 if (rep)
2647 rep->count++;
2648}
2649
2650octave_stream&
2651octave_stream::operator = (const octave_stream& s)
2652{
2653 if (rep != s.rep)
2654 {
2655 if (rep && --rep->count == 0)
2656 delete rep;
2657
2658 rep = s.rep;
2659
2660 if (rep)
2661 rep->count++;
2662 }
2663
2664 return *this;
2665}
2666
2667int
2668octave_stream::flush (void)
2669{
2670 int retval = -1;
2671
2672 if (stream_ok ())
2673 retval = rep->flush ();
2674
2675 return retval;
2676}
2677
2678std::string
2679octave_stream::getl (octave_idx_type max_len, bool& err, const std::string& who)
2680{
2681 std::string retval;
2682
2683 if (stream_ok ())
2684 retval = rep->getl (max_len, err, who);
2685
2686 return retval;
2687}
2688
2689std::string
2690octave_stream::getl (const octave_value& tc_max_len, bool& err,
2691 const std::string& who)
2692{
2693 std::string retval;
2694
2695 err = false;
2696
2697 int conv_err = 0;
2698
2699 int max_len = -1;
2700
2701 if (tc_max_len.is_defined ())
2702 {
2703 max_len = convert_to_valid_int (tc_max_len, conv_err);
2704
2705 if (conv_err || max_len < 0)
2706 {
2707 err = true;
2708 ::error ("%s: invalid maximum length specified", who.c_str ());
2709 }
2710 }
2711
2712 if (! error_state)
2713 retval = getl (max_len, err, who);
2714
2715 return retval;
2716}
2717
2718std::string
2719octave_stream::gets (octave_idx_type max_len, bool& err, const std::string& who)
2720{
2721 std::string retval;
2722
2723 if (stream_ok ())
2724 retval = rep->gets (max_len, err, who);
2725
2726 return retval;
2727}
2728
2729std::string
2730octave_stream::gets (const octave_value& tc_max_len, bool& err,
2731 const std::string& who)
2732{
2733 std::string retval;
2734
2735 err = false;
2736
2737 int conv_err = 0;
2738
2739 int max_len = -1;
2740
2741 if (tc_max_len.is_defined ())
2742 {
2743 max_len = convert_to_valid_int (tc_max_len, conv_err);
2744
2745 if (conv_err || max_len < 0)
2746 {
2747 err = true;
2748 ::error ("%s: invalid maximum length specified", who.c_str ());
2749 }
2750 }
2751
2752 if (! error_state)
2753 retval = gets (max_len, err, who);
2754
2755 return retval;
2756}
2757
2758off_t
2759octave_stream::skipl (off_t count, bool& err, const std::string& who)
2760{
2761 off_t retval = -1;
2762
2763 if (stream_ok ())
2764 retval = rep->skipl (count, err, who);
2765
2766 return retval;
2767}
2768
2769off_t
2770octave_stream::skipl (const octave_value& tc_count, bool& err,
2771 const std::string& who)
2772{
2773 off_t retval = -1;
2774
2775 err = false;
2776
2777 int conv_err = 0;
2778
2779 int count = 1;
2780
2781 if (tc_count.is_defined ())
2782 {
2783 if (tc_count.is_scalar_type () && xisinf (tc_count.scalar_value ()))
2784 count = -1;
2785 else
2786 {
2787 count = convert_to_valid_int (tc_count, conv_err);
2788
2789 if (conv_err || count < 0)
2790 {
2791 err = true;
2792 ::error ("%s: invalid number of lines specified", who.c_str ());
2793 }
2794 }
2795 }
2796
2797 if (! error_state)
2798 retval = skipl (count, err, who);
2799
2800 return retval;
2801}
2802
2803int
2804octave_stream::seek (off_t offset, int origin)
2805{
2806 int status = -1;
2807
2808 if (stream_ok ())
2809 {
2810 clearerr ();
2811
2812 // Find current position so we can return to it if needed.
2813
2814 off_t orig_pos = rep->tell ();
2815
2816 // Move to end of file. If successful, find the offset of the end.
2817
2818 status = rep->seek (0, SEEK_END2);
2819
2820 if (status == 0)
2821 {
2822 off_t eof_pos = rep->tell ();
2823
2824 if (origin == SEEK_CUR1)
2825 {
2826 // Move back to original position, otherwise we will be
2827 // seeking from the end of file which is probably not the
2828 // original location.
2829
2830 rep->seek (orig_pos, SEEK_SET0);
2831 }
2832
2833 // Attempt to move to desired position; may be outside bounds
2834 // of existing file.
2835
2836 status = rep->seek (offset, origin);
2837
2838 if (status == 0)
2839 {
2840 // Where are we after moving to desired position?
2841
2842 off_t desired_pos = rep->tell ();
2843
2844 // I don't think save_pos can be less than zero, but we'll
2845 // check anyway...
2846
2847 if (desired_pos > eof_pos || desired_pos < 0)
2848 {
2849 // Seek outside bounds of file. Failure should leave
2850 // position unchanged.
2851
2852 rep->seek (orig_pos, SEEK_SET0);
2853
2854 status = -1;
2855 }
2856 }
2857 else
2858 {
2859 // Seeking to the desired position failed. Move back to
2860 // original position and return failure status.
2861
2862 rep->seek (orig_pos, SEEK_SET0);
2863
2864 status = -1;
2865 }
2866 }
2867 }
2868
2869 return status;
2870}
2871
2872int
2873octave_stream::seek (const octave_value& tc_offset,
2874 const octave_value& tc_origin)
2875{
2876 int retval = -1;
2877
2878 // FIXME: should we have octave_value methods that handle off_t explicitly?
2879 octave_int64 val = tc_offset.int64_scalar_value ();
2880 off_t xoffset = val.value ();
2881
2882 if (! error_state)
2883 {
2884 int conv_err = 0;
2885
2886 int origin = SEEK_SET0;
2887
2888 if (tc_origin.is_string ())
2889 {
2890 std::string xorigin = tc_origin.string_value ();
2891
2892 if (xorigin == "bof")
2893 origin = SEEK_SET0;
2894 else if (xorigin == "cof")
2895 origin = SEEK_CUR1;
2896 else if (xorigin == "eof")
2897 origin = SEEK_END2;
2898 else
2899 conv_err = -1;
2900 }
2901 else
2902 {
2903 int xorigin = convert_to_valid_int (tc_origin, conv_err);
2904
2905 if (! conv_err)
2906 {
2907 if (xorigin == -1)
2908 origin = SEEK_SET0;
2909 else if (xorigin == 0)
2910 origin = SEEK_CUR1;
2911 else if (xorigin == 1)
2912 origin = SEEK_END2;
2913 else
2914 conv_err = -1;
2915 }
2916 }
2917
2918 if (! conv_err)
2919 {
2920 retval = seek (xoffset, origin);
2921
2922 if (retval != 0)
2923 error ("fseek: failed to seek to requested position");
2924 }
2925 else
2926 error ("fseek: invalid value for origin");
2927 }
2928 else
2929 error ("fseek: invalid value for offset");
2930
2931 return retval;
2932}
2933
2934off_t
2935octave_stream::tell (void)
2936{
2937 off_t retval = -1;
2938
2939 if (stream_ok ())
2940 retval = rep->tell ();
2941
2942 return retval;
2943}
2944
2945int
2946octave_stream::rewind (void)
2947{
2948 return seek (0, SEEK_SET0);
2949}
2950
2951bool
2952octave_stream::is_open (void) const
2953{
2954 bool retval = false;
2955
2956 if (stream_ok ())
2957 retval = rep->is_open ();
2958
2959 return retval;
2960}
2961
2962void
2963octave_stream::close (void)
2964{
2965 if (stream_ok ())
2966 rep->close ();
2967}
2968
2969template <class SRC_T, class DST_T>
2970static octave_value
2971convert_and_copy (std::list<void *>& input_buf_list,
2972 octave_idx_type input_buf_elts,
2973 octave_idx_type elts_read,
2974 octave_idx_type nr, octave_idx_type nc, bool swap,
2975 bool do_float_fmt_conv, bool do_NA_conv,
2976 oct_mach_info::float_format from_flt_fmt)
2977{
2978 typedef typename DST_T::element_type dst_elt_type;
2979
2980 DST_T conv (dim_vector (nr, nc));
2981
2982 dst_elt_type *conv_data = conv.fortran_vec ();
2983
2984 octave_idx_type j = 0;
2985
2986 for (std::list<void *>::const_iterator it = input_buf_list.begin ();
2987 it != input_buf_list.end (); it++)
2988 {
2989 SRC_T *data = static_cast<SRC_T *> (*it);
2990
2991 if (swap || do_float_fmt_conv)
2992 {
2993 for (octave_idx_type i = 0; i < input_buf_elts && j < elts_read;
2994 i++, j++)
2995 {
2996 if (swap)
2997 swap_bytes<sizeof (SRC_T)> (&data[i]);
2998 else if (do_float_fmt_conv)
2999 do_float_format_conversion (&data[i], sizeof (SRC_T),
3000 1, from_flt_fmt,
3001 oct_mach_info::float_format ());
3002
3003 dst_elt_type tmp (data[i]);
3004
3005 if (do_NA_conv && __lo_ieee_is_old_NA (tmp))
3006 tmp = __lo_ieee_replace_old_NA (tmp);
3007
3008 conv_data[j] = tmp;
3009 }
3010 }
3011 else
3012 {
3013 if (do_NA_conv)
3014 {
3015 for (octave_idx_type i = 0; i < input_buf_elts && j < elts_read;
3016 i++, j++)
3017 {
3018 dst_elt_type tmp (data[i]);
3019
3020 if (__lo_ieee_is_old_NA (tmp))
3021 tmp = __lo_ieee_replace_old_NA (tmp);
3022
3023 conv_data[j] = tmp;
3024 }
3025 }
3026 else
3027 {
3028 for (octave_idx_type i = 0; i < input_buf_elts && j < elts_read;
3029 i++, j++)
3030 conv_data[j] = data[i];
3031 }
3032 }
3033
3034 delete [] data;
3035 }
3036
3037 input_buf_list.clear ();
3038
3039 for (octave_idx_type i = elts_read; i < nr * nc; i++)
3040 conv_data[i] = dst_elt_type (0);
3041
3042 return conv;
3043}
3044
3045typedef octave_value (*conv_fptr)
3046 (std::list<void *>& input_buf_list, octave_idx_type input_buf_elts,
3047 octave_idx_type elts_read, octave_idx_type nr, octave_idx_type nc,
3048 bool swap, bool do_float_fmt_conv, bool do_NA_conv,
3049 oct_mach_info::float_format from_flt_fmt);
3050
3051#define TABLE_ELT(T, U, V, W)conv_fptr_table[oct_data_conv::T][oct_data_conv::U] = convert_and_copy
<V, W>
\
3052 conv_fptr_table[oct_data_conv::T][oct_data_conv::U] = convert_and_copy<V, W>
3053
3054#define FILL_TABLE_ROW(T, V)conv_fptr_table[oct_data_conv::T][oct_data_conv::dt_int8] = convert_and_copy
<V, int8NDArray>; conv_fptr_table[oct_data_conv::T][oct_data_conv
::dt_uint8] = convert_and_copy<V, uint8NDArray>; conv_fptr_table
[oct_data_conv::T][oct_data_conv::dt_int16] = convert_and_copy
<V, int16NDArray>; conv_fptr_table[oct_data_conv::T][oct_data_conv
::dt_uint16] = convert_and_copy<V, uint16NDArray>; conv_fptr_table
[oct_data_conv::T][oct_data_conv::dt_int32] = convert_and_copy
<V, int32NDArray>; conv_fptr_table[oct_data_conv::T][oct_data_conv
::dt_uint32] = convert_and_copy<V, uint32NDArray>; conv_fptr_table
[oct_data_conv::T][oct_data_conv::dt_int64] = convert_and_copy
<V, int64NDArray>; conv_fptr_table[oct_data_conv::T][oct_data_conv
::dt_uint64] = convert_and_copy<V, uint64NDArray>; conv_fptr_table
[oct_data_conv::T][oct_data_conv::dt_single] = convert_and_copy
<V, FloatNDArray>; conv_fptr_table[oct_data_conv::T][oct_data_conv
::dt_double] = convert_and_copy<V, NDArray>; conv_fptr_table
[oct_data_conv::T][oct_data_conv::dt_char] = convert_and_copy
<V, charNDArray>; conv_fptr_table[oct_data_conv::T][oct_data_conv
::dt_schar] = convert_and_copy<V, charNDArray>; conv_fptr_table
[oct_data_conv::T][oct_data_conv::dt_uchar] = convert_and_copy
<V, charNDArray>; conv_fptr_table[oct_data_conv::T][oct_data_conv
::dt_logical] = convert_and_copy<V, boolNDArray>;
\
3055 TABLE_ELT (T, dt_int8, V, int8NDArray)conv_fptr_table[oct_data_conv::T][oct_data_conv::dt_int8] = convert_and_copy
<V, int8NDArray>
; \
3056 TABLE_ELT (T, dt_uint8, V, uint8NDArray)conv_fptr_table[oct_data_conv::T][oct_data_conv::dt_uint8] = convert_and_copy
<V, uint8NDArray>
; \
3057 TABLE_ELT (T, dt_int16, V, int16NDArray)conv_fptr_table[oct_data_conv::T][oct_data_conv::dt_int16] = convert_and_copy
<V, int16NDArray>
; \
3058 TABLE_ELT (T, dt_uint16, V, uint16NDArray)conv_fptr_table[oct_data_conv::T][oct_data_conv::dt_uint16] =
convert_and_copy<V, uint16NDArray>
; \
3059 TABLE_ELT (T, dt_int32, V, int32NDArray)conv_fptr_table[oct_data_conv::T][oct_data_conv::dt_int32] = convert_and_copy
<V, int32NDArray>
; \
3060 TABLE_ELT (T, dt_uint32, V, uint32NDArray)conv_fptr_table[oct_data_conv::T][oct_data_conv::dt_uint32] =
convert_and_copy<V, uint32NDArray>
; \
3061 TABLE_ELT (T, dt_int64, V, int64NDArray)conv_fptr_table[oct_data_conv::T][oct_data_conv::dt_int64] = convert_and_copy
<V, int64NDArray>
; \
3062 TABLE_ELT (T, dt_uint64, V, uint64NDArray)conv_fptr_table[oct_data_conv::T][oct_data_conv::dt_uint64] =
convert_and_copy<V, uint64NDArray>
; \
3063 TABLE_ELT (T, dt_single, V, FloatNDArray)conv_fptr_table[oct_data_conv::T][oct_data_conv::dt_single] =
convert_and_copy<V, FloatNDArray>
; \
3064 TABLE_ELT (T, dt_double, V, NDArray)conv_fptr_table[oct_data_conv::T][oct_data_conv::dt_double] =
convert_and_copy<V, NDArray>
; \
3065 TABLE_ELT (T, dt_char, V, charNDArray)conv_fptr_table[oct_data_conv::T][oct_data_conv::dt_char] = convert_and_copy
<V, charNDArray>
; \
3066 TABLE_ELT (T, dt_schar, V, charNDArray)conv_fptr_table[oct_data_conv::T][oct_data_conv::dt_schar] = convert_and_copy
<V, charNDArray>
; \
3067 TABLE_ELT (T, dt_uchar, V, charNDArray)conv_fptr_table[oct_data_conv::T][oct_data_conv::dt_uchar] = convert_and_copy
<V, charNDArray>
; \
3068 TABLE_ELT (T, dt_logical, V, boolNDArray)conv_fptr_table[oct_data_conv::T][oct_data_conv::dt_logical] =
convert_and_copy<V, boolNDArray>
;
3069
3070octave_value
3071octave_stream::finalize_read (std::list<void *>& input_buf_list,
3072 octave_idx_type input_buf_elts,
3073 octave_idx_type elts_read,
3074 octave_idx_type nr, octave_idx_type nc,
3075 oct_data_conv::data_type input_type,
3076 oct_data_conv::data_type output_type,
3077 oct_mach_info::float_format ffmt)
3078{
3079 octave_value retval;
3080
3081 static bool initialized = false;
3082
3083 // Table function pointers for return types x read types.
3084
3085 static conv_fptr conv_fptr_table[oct_data_conv::dt_unknown][14];
3086
3087 if (! initialized)
3088 {
3089 for (int i = 0; i < oct_data_conv::dt_unknown; i++)
3090 for (int j = 0; j < 14; j++)
3091 conv_fptr_table[i][j] = 0;
3092
3093 FILL_TABLE_ROW (dt_int8, int8_t)conv_fptr_table[oct_data_conv::dt_int8][oct_data_conv::dt_int8
] = convert_and_copy<int8_t, int8NDArray>; conv_fptr_table
[oct_data_conv::dt_int8][oct_data_conv::dt_uint8] = convert_and_copy
<int8_t, uint8NDArray>; conv_fptr_table[oct_data_conv::
dt_int8][oct_data_conv::dt_int16] = convert_and_copy<int8_t
, int16NDArray>; conv_fptr_table[oct_data_conv::dt_int8][oct_data_conv
::dt_uint16] = convert_and_copy<int8_t, uint16NDArray>;
conv_fptr_table[oct_data_conv::dt_int8][oct_data_conv::dt_int32
] = convert_and_copy<int8_t, int32NDArray>; conv_fptr_table
[oct_data_conv::dt_int8][oct_data_conv::dt_uint32] = convert_and_copy
<int8_t, uint32NDArray>; conv_fptr_table[oct_data_conv::
dt_int8][oct_data_conv::dt_int64] = convert_and_copy<int8_t
, int64NDArray>; conv_fptr_table[oct_data_conv::dt_int8][oct_data_conv
::dt_uint64] = convert_and_copy<int8_t, uint64NDArray>;
conv_fptr_table[oct_data_conv::dt_int8][oct_data_conv::dt_single
] = convert_and_copy<int8_t, FloatNDArray>; conv_fptr_table
[oct_data_conv::dt_int8][oct_data_conv::dt_double] = convert_and_copy
<int8_t, NDArray>; conv_fptr_table[oct_data_conv::dt_int8
][oct_data_conv::dt_char] = convert_and_copy<int8_t, charNDArray
>; conv_fptr_table[oct_data_conv::dt_int8][oct_data_conv::
dt_schar] = convert_and_copy<int8_t, charNDArray>; conv_fptr_table
[oct_data_conv::dt_int8][oct_data_conv::dt_uchar] = convert_and_copy
<int8_t, charNDArray>; conv_fptr_table[oct_data_conv::dt_int8
][oct_data_conv::dt_logical] = convert_and_copy<int8_t, boolNDArray
>;
;
3094 FILL_TABLE_ROW (dt_uint8, uint8_t)conv_fptr_table[oct_data_conv::dt_uint8][oct_data_conv::dt_int8
] = convert_and_copy<uint8_t, int8NDArray>; conv_fptr_table
[oct_data_conv::dt_uint8][oct_data_conv::dt_uint8] = convert_and_copy
<uint8_t, uint8NDArray>; conv_fptr_table[oct_data_conv::
dt_uint8][oct_data_conv::dt_int16] = convert_and_copy<uint8_t
, int16NDArray>; conv_fptr_table[oct_data_conv::dt_uint8][
oct_data_conv::dt_uint16] = convert_and_copy<uint8_t, uint16NDArray
>; conv_fptr_table[oct_data_conv::dt_uint8][oct_data_conv::
dt_int32] = convert_and_copy<uint8_t, int32NDArray>; conv_fptr_table
[oct_data_conv::dt_uint8][oct_data_conv::dt_uint32] = convert_and_copy
<uint8_t, uint32NDArray>; conv_fptr_table[oct_data_conv
::dt_uint8][oct_data_conv::dt_int64] = convert_and_copy<uint8_t
, int64NDArray>; conv_fptr_table[oct_data_conv::dt_uint8][
oct_data_conv::dt_uint64] = convert_and_copy<uint8_t, uint64NDArray
>; conv_fptr_table[oct_data_conv::dt_uint8][oct_data_conv::
dt_single] = convert_and_copy<uint8_t, FloatNDArray>; conv_fptr_table
[oct_data_conv::dt_uint8][oct_data_conv::dt_double] = convert_and_copy
<uint8_t, NDArray>; conv_fptr_table[oct_data_conv::dt_uint8
][oct_data_conv::dt_char] = convert_and_copy<uint8_t, charNDArray
>; conv_fptr_table[oct_data_conv::dt_uint8][oct_data_conv::
dt_schar] = convert_and_copy<uint8_t, charNDArray>; conv_fptr_table
[oct_data_conv::dt_uint8][oct_data_conv::dt_uchar] = convert_and_copy
<uint8_t, charNDArray>; conv_fptr_table[oct_data_conv::
dt_uint8][oct_data_conv::dt_logical] = convert_and_copy<uint8_t
, boolNDArray>;
;
3095 FILL_TABLE_ROW (dt_int16, int16_t)conv_fptr_table[oct_data_conv::dt_int16][oct_data_conv::dt_int8
] = convert_and_copy<int16_t, int8NDArray>; conv_fptr_table
[oct_data_conv::dt_int16][oct_data_conv::dt_uint8] = convert_and_copy
<int16_t, uint8NDArray>; conv_fptr_table[oct_data_conv::
dt_int16][oct_data_conv::dt_int16] = convert_and_copy<int16_t
, int16NDArray>; conv_fptr_table[oct_data_conv::dt_int16][
oct_data_conv::dt_uint16] = convert_and_copy<int16_t, uint16NDArray
>; conv_fptr_table[oct_data_conv::dt_int16][oct_data_conv::
dt_int32] = convert_and_copy<int16_t, int32NDArray>; conv_fptr_table
[oct_data_conv::dt_int16][oct_data_conv::dt_uint32] = convert_and_copy
<int16_t, uint32NDArray>; conv_fptr_table[oct_data_conv
::dt_int16][oct_data_conv::dt_int64] = convert_and_copy<int16_t
, int64NDArray>; conv_fptr_table[oct_data_conv::dt_int16][
oct_data_conv::dt_uint64] = convert_and_copy<int16_t, uint64NDArray
>; conv_fptr_table[oct_data_conv::dt_int16][oct_data_conv::
dt_single] = convert_and_copy<int16_t, FloatNDArray>; conv_fptr_table
[oct_data_conv::dt_int16][oct_data_conv::dt_double] = convert_and_copy
<int16_t, NDArray>; conv_fptr_table[oct_data_conv::dt_int16
][oct_data_conv::dt_char] = convert_and_copy<int16_t, charNDArray
>; conv_fptr_table[oct_data_conv::dt_int16][oct_data_conv::
dt_schar] = convert_and_copy<int16_t, charNDArray>; conv_fptr_table
[oct_data_conv::dt_int16][oct_data_conv::dt_uchar] = convert_and_copy
<int16_t, charNDArray>; conv_fptr_table[oct_data_conv::
dt_int16][oct_data_conv::dt_logical] = convert_and_copy<int16_t
, boolNDArray>;
;
3096 FILL_TABLE_ROW (dt_uint16, uint16_t)conv_fptr_table[oct_data_conv::dt_uint16][oct_data_conv::dt_int8
] = convert_and_copy<uint16_t, int8NDArray>; conv_fptr_table
[oct_data_conv::dt_uint16][oct_data_conv::dt_uint8] = convert_and_copy
<uint16_t, uint8NDArray>; conv_fptr_table[oct_data_conv
::dt_uint16][oct_data_conv::dt_int16] = convert_and_copy<uint16_t
, int16NDArray>; conv_fptr_table[oct_data_conv::dt_uint16]
[oct_data_conv::dt_uint16] = convert_and_copy<uint16_t, uint16NDArray
>; conv_fptr_table[oct_data_conv::dt_uint16][oct_data_conv
::dt_int32] = convert_and_copy<uint16_t, int32NDArray>;
conv_fptr_table[oct_data_conv::dt_uint16][oct_data_conv::dt_uint32
] = convert_and_copy<uint16_t, uint32NDArray>; conv_fptr_table
[oct_data_conv::dt_uint16][oct_data_conv::dt_int64] = convert_and_copy
<uint16_t, int64NDArray>; conv_fptr_table[oct_data_conv
::dt_uint16][oct_data_conv::dt_uint64] = convert_and_copy<
uint16_t, uint64NDArray>; conv_fptr_table[oct_data_conv::dt_uint16
][oct_data_conv::dt_single] = convert_and_copy<uint16_t, FloatNDArray
>; conv_fptr_table[oct_data_conv::dt_uint16][oct_data_conv
::dt_double] = convert_and_copy<uint16_t, NDArray>; conv_fptr_table
[oct_data_conv::dt_uint16][oct_data_conv::dt_char] = convert_and_copy
<uint16_t, charNDArray>; conv_fptr_table[oct_data_conv::
dt_uint16][oct_data_conv::dt_schar] = convert_and_copy<uint16_t
, charNDArray>; conv_fptr_table[oct_data_conv::dt_uint16][
oct_data_conv::dt_uchar] = convert_and_copy<uint16_t, charNDArray
>; conv_fptr_table[oct_data_conv::dt_uint16][oct_data_conv
::dt_logical] = convert_and_copy<uint16_t, boolNDArray>
;
;
3097 FILL_TABLE_ROW (dt_int32, int32_t)conv_fptr_table[oct_data_conv::dt_int32][oct_data_conv::dt_int8
] = convert_and_copy<int32_t, int8NDArray>; conv_fptr_table
[oct_data_conv::dt_int32][oct_data_conv::dt_uint8] = convert_and_copy
<int32_t, uint8NDArray>; conv_fptr_table[oct_data_conv::
dt_int32][oct_data_conv::dt_int16] = convert_and_copy<int32_t
, int16NDArray>; conv_fptr_table[oct_data_conv::dt_int32][
oct_data_conv::dt_uint16] = convert_and_copy<int32_t, uint16NDArray
>; conv_fptr_table[oct_data_conv::dt_int32][oct_data_conv::
dt_int32] = convert_and_copy<int32_t, int32NDArray>; conv_fptr_table
[oct_data_conv::dt_int32][oct_data_conv::dt_uint32] = convert_and_copy
<int32_t, uint32NDArray>; conv_fptr_table[oct_data_conv
::dt_int32][oct_data_conv::dt_int64] = convert_and_copy<int32_t
, int64NDArray>; conv_fptr_table[oct_data_conv::dt_int32][
oct_data_conv::dt_uint64] = convert_and_copy<int32_t, uint64NDArray
>; conv_fptr_table[oct_data_conv::dt_int32][oct_data_conv::
dt_single] = convert_and_copy<int32_t, FloatNDArray>; conv_fptr_table
[oct_data_conv::dt_int32][oct_data_conv::dt_double] = convert_and_copy
<int32_t, NDArray>; conv_fptr_table[oct_data_conv::dt_int32
][oct_data_conv::dt_char] = convert_and_copy<int32_t, charNDArray
>; conv_fptr_table[oct_data_conv::dt_int32][oct_data_conv::
dt_schar] = convert_and_copy<int32_t, charNDArray>; conv_fptr_table
[oct_data_conv::dt_int32][oct_data_conv::dt_uchar] = convert_and_copy
<int32_t, charNDArray>; conv_fptr_table[oct_data_conv::
dt_int32][oct_data_conv::dt_logical] = convert_and_copy<int32_t
, boolNDArray>;
;
3098 FILL_TABLE_ROW (dt_uint32, uint32_t)conv_fptr_table[oct_data_conv::dt_uint32][oct_data_conv::dt_int8
] = convert_and_copy<uint32_t, int8NDArray>; conv_fptr_table
[oct_data_conv::dt_uint32][oct_data_conv::dt_uint8] = convert_and_copy
<uint32_t, uint8NDArray>; conv_fptr_table[oct_data_conv
::dt_uint32][oct_data_conv::dt_int16] = convert_and_copy<uint32_t
, int16NDArray>; conv_fptr_table[oct_data_conv::dt_uint32]
[oct_data_conv::dt_uint16] = convert_and_copy<uint32_t, uint16NDArray
>; conv_fptr_table[oct_data_conv::dt_uint32][oct_data_conv
::dt_int32] = convert_and_copy<uint32_t, int32NDArray>;
conv_fptr_table[oct_data_conv::dt_uint32][oct_data_conv::dt_uint32
] = convert_and_copy<uint32_t, uint32NDArray>; conv_fptr_table
[oct_data_conv::dt_uint32][oct_data_conv::dt_int64] = convert_and_copy
<uint32_t, int64NDArray>; conv_fptr_table[oct_data_conv
::dt_uint32][oct_data_conv::dt_uint64] = convert_and_copy<
uint32_t, uint64NDArray>; conv_fptr_table[oct_data_conv::dt_uint32
][oct_data_conv::dt_single] = convert_and_copy<uint32_t, FloatNDArray
>; conv_fptr_table[oct_data_conv::dt_uint32][oct_data_conv
::dt_double] = convert_and_copy<uint32_t, NDArray>; conv_fptr_table
[oct_data_conv::dt_uint32][oct_data_conv::dt_char] = convert_and_copy
<uint32_t, charNDArray>; conv_fptr_table[oct_data_conv::
dt_uint32][oct_data_conv::dt_schar] = convert_and_copy<uint32_t
, charNDArray>; conv_fptr_table[oct_data_conv::dt_uint32][
oct_data_conv::dt_uchar] = convert_and_copy<uint32_t, charNDArray
>; conv_fptr_table[oct_data_conv::dt_uint32][oct_data_conv
::dt_logical] = convert_and_copy<uint32_t, boolNDArray>
;
;
3099 FILL_TABLE_ROW (dt_int64, int64_t)conv_fptr_table[oct_data_conv::dt_int64][oct_data_conv::dt_int8
] = convert_and_copy<int64_t, int8NDArray>; conv_fptr_table
[oct_data_conv::dt_int64][oct_data_conv::dt_uint8] = convert_and_copy
<int64_t, uint8NDArray>; conv_fptr_table[oct_data_conv::
dt_int64][oct_data_conv::dt_int16] = convert_and_copy<int64_t
, int16NDArray>; conv_fptr_table[oct_data_conv::dt_int64][
oct_data_conv::dt_uint16] = convert_and_copy<int64_t, uint16NDArray
>; conv_fptr_table[oct_data_conv::dt_int64][oct_data_conv::
dt_int32] = convert_and_copy<int64_t, int32NDArray>; conv_fptr_table
[oct_data_conv::dt_int64][oct_data_conv::dt_uint32] = convert_and_copy
<int64_t, uint32NDArray>; conv_fptr_table[oct_data_conv
::dt_int64][oct_data_conv::dt_int64] = convert_and_copy<int64_t
, int64NDArray>; conv_fptr_table[oct_data_conv::dt_int64][
oct_data_conv::dt_uint64] = convert_and_copy<int64_t, uint64NDArray
>; conv_fptr_table[oct_data_conv::dt_int64][oct_data_conv::
dt_single] = convert_and_copy<int64_t, FloatNDArray>; conv_fptr_table
[oct_data_conv::dt_int64][oct_data_conv::dt_double] = convert_and_copy
<int64_t, NDArray>; conv_fptr_table[oct_data_conv::dt_int64
][oct_data_conv::dt_char] = convert_and_copy<int64_t, charNDArray
>; conv_fptr_table[oct_data_conv::dt_int64][oct_data_conv::
dt_schar] = convert_and_copy<int64_t, charNDArray>; conv_fptr_table
[oct_data_conv::dt_int64][oct_data_conv::dt_uchar] = convert_and_copy
<int64_t, charNDArray>; conv_fptr_table[oct_data_conv::
dt_int64][oct_data_conv::dt_logical] = convert_and_copy<int64_t
, boolNDArray>;
;
3100 FILL_TABLE_ROW (dt_uint64, uint64_t)conv_fptr_table[oct_data_conv::dt_uint64][oct_data_conv::dt_int8
] = convert_and_copy<uint64_t, int8NDArray>; conv_fptr_table
[oct_data_conv::dt_uint64][oct_data_conv::dt_uint8] = convert_and_copy
<uint64_t, uint8NDArray>; conv_fptr_table[oct_data_conv
::dt_uint64][oct_data_conv::dt_int16] = convert_and_copy<uint64_t
, int16NDArray>; conv_fptr_table[oct_data_conv::dt_uint64]
[oct_data_conv::dt_uint16] = convert_and_copy<uint64_t, uint16NDArray
>; conv_fptr_table[oct_data_conv::dt_uint64][oct_data_conv
::dt_int32] = convert_and_copy<uint64_t, int32NDArray>;
conv_fptr_table[oct_data_conv::dt_uint64][oct_data_conv::dt_uint32
] = convert_and_copy<uint64_t, uint32NDArray>; conv_fptr_table
[oct_data_conv::dt_uint64][oct_data_conv::dt_int64] = convert_and_copy
<uint64_t, int64NDArray>; conv_fptr_table[oct_data_conv
::dt_uint64][oct_data_conv::dt_uint64] = convert_and_copy<
uint64_t, uint64NDArray>; conv_fptr_table[oct_data_conv::dt_uint64
][oct_data_conv::dt_single] = convert_and_copy<uint64_t, FloatNDArray
>; conv_fptr_table[oct_data_conv::dt_uint64][oct_data_conv
::dt_double] = convert_and_copy<uint64_t, NDArray>; conv_fptr_table
[oct_data_conv::dt_uint64][oct_data_conv::dt_char] = convert_and_copy
<uint64_t, charNDArray>; conv_fptr_table[oct_data_conv::
dt_uint64][oct_data_conv::dt_schar] = convert_and_copy<uint64_t
, charNDArray>; conv_fptr_table[oct_data_conv::dt_uint64][
oct_data_conv::dt_uchar] = convert_and_copy<uint64_t, charNDArray
>; conv_fptr_table[oct_data_conv::dt_uint64][oct_data_conv
::dt_logical] = convert_and_copy<uint64_t, boolNDArray>
;
;
3101 FILL_TABLE_ROW (dt_single, float)conv_fptr_table[oct_data_conv::dt_single][oct_data_conv::dt_int8
] = convert_and_copy<float, int8NDArray>; conv_fptr_table
[oct_data_conv::dt_single][oct_data_conv::dt_uint8] = convert_and_copy
<float, uint8NDArray>; conv_fptr_table[oct_data_conv::dt_single
][oct_data_conv::dt_int16] = convert_and_copy<float, int16NDArray
>; conv_fptr_table[oct_data_conv::dt_single][oct_data_conv
::dt_uint16] = convert_and_copy<float, uint16NDArray>; conv_fptr_table
[oct_data_conv::dt_single][oct_data_conv::dt_int32] = convert_and_copy
<float, int32NDArray>; conv_fptr_table[oct_data_conv::dt_single
][oct_data_conv::dt_uint32] = convert_and_copy<float, uint32NDArray
>; conv_fptr_table[oct_data_conv::dt_single][oct_data_conv
::dt_int64] = convert_and_copy<float, int64NDArray>; conv_fptr_table
[oct_data_conv::dt_single][oct_data_conv::dt_uint64] = convert_and_copy
<float, uint64NDArray>; conv_fptr_table[oct_data_conv::
dt_single][oct_data_conv::dt_single] = convert_and_copy<float
, FloatNDArray>; conv_fptr_table[oct_data_conv::dt_single]
[oct_data_conv::dt_double] = convert_and_copy<float, NDArray
>; conv_fptr_table[oct_data_conv::dt_single][oct_data_conv
::dt_char] = convert_and_copy<float, charNDArray>; conv_fptr_table
[oct_data_conv::dt_single][oct_data_conv::dt_schar] = convert_and_copy
<float, charNDArray>; conv_fptr_table[oct_data_conv::dt_single
][oct_data_conv::dt_uchar] = convert_and_copy<float, charNDArray
>; conv_fptr_table[oct_data_conv::dt_single][oct_data_conv
::dt_logical] = convert_and_copy<float, boolNDArray>;
;
3102 FILL_TABLE_ROW (dt_double, double)conv_fptr_table[oct_data_conv::dt_double][oct_data_conv::dt_int8
] = convert_and_copy<double, int8NDArray>; conv_fptr_table
[oct_data_conv::dt_double][oct_data_conv::dt_uint8] = convert_and_copy
<double, uint8NDArray>; conv_fptr_table[oct_data_conv::
dt_double][oct_data_conv::dt_int16] = convert_and_copy<double
, int16NDArray>; conv_fptr_table[oct_data_conv::dt_double]
[oct_data_conv::dt_uint16] = convert_and_copy<double, uint16NDArray
>; conv_fptr_table[oct_data_conv::dt_double][oct_data_conv
::dt_int32] = convert_and_copy<double, int32NDArray>; conv_fptr_table
[oct_data_conv::dt_double][oct_data_conv::dt_uint32] = convert_and_copy
<double, uint32NDArray>; conv_fptr_table[oct_data_conv::
dt_double][oct_data_conv::dt_int64] = convert_and_copy<double
, int64NDArray>; conv_fptr_table[oct_data_conv::dt_double]
[oct_data_conv::dt_uint64] = convert_and_copy<double, uint64NDArray
>; conv_fptr_table[oct_data_conv::dt_double][oct_data_conv
::dt_single] = convert_and_copy<double, FloatNDArray>; conv_fptr_table
[oct_data_conv::dt_double][oct_data_conv::dt_double] = convert_and_copy
<double, NDArray>; conv_fptr_table[oct_data_conv::dt_double
][oct_data_conv::dt_char] = convert_and_copy<double, charNDArray
>; conv_fptr_table[oct_data_conv::dt_double][oct_data_conv
::dt_schar] = convert_and_copy<double, charNDArray>; conv_fptr_table
[oct_data_conv::dt_double][oct_data_conv::dt_uchar] = convert_and_copy
<double, charNDArray>; conv_fptr_table[oct_data_conv::dt_double
][oct_data_conv::dt_logical] = convert_and_copy<double, boolNDArray
>;
;
3103 FILL_TABLE_ROW (dt_char, char)conv_fptr_table[oct_data_conv::dt_char][oct_data_conv::dt_int8
] = convert_and_copy<char, int8NDArray>; conv_fptr_table
[oct_data_conv::dt_char][oct_data_conv::dt_uint8] = convert_and_copy
<char, uint8NDArray>; conv_fptr_table[oct_data_conv::dt_char
][oct_data_conv::dt_int16] = convert_and_copy<char, int16NDArray
>; conv_fptr_table[oct_data_conv::dt_char][oct_data_conv::
dt_uint16] = convert_and_copy<char, uint16NDArray>; conv_fptr_table
[oct_data_conv::dt_char][oct_data_conv::dt_int32] = convert_and_copy
<char, int32NDArray>; conv_fptr_table[oct_data_conv::dt_char
][oct_data_conv::dt_uint32] = convert_and_copy<char, uint32NDArray
>; conv_fptr_table[oct_data_conv::dt_char][oct_data_conv::
dt_int64] = convert_and_copy<char, int64NDArray>; conv_fptr_table
[oct_data_conv::dt_char][oct_data_conv::dt_uint64] = convert_and_copy
<char, uint64NDArray>; conv_fptr_table[oct_data_conv::dt_char
][oct_data_conv::dt_single] = convert_and_copy<char, FloatNDArray
>; conv_fptr_table[oct_data_conv::dt_char][oct_data_conv::
dt_double] = convert_and_copy<char, NDArray>; conv_fptr_table
[oct_data_conv::dt_char][oct_data_conv::dt_char] = convert_and_copy
<char, charNDArray>; conv_fptr_table[oct_data_conv::dt_char
][oct_data_conv::dt_schar] = convert_and_copy<char, charNDArray
>; conv_fptr_table[oct_data_conv::dt_char][oct_data_conv::
dt_uchar] = convert_and_copy<char, charNDArray>; conv_fptr_table
[oct_data_conv::dt_char][oct_data_conv::dt_logical] = convert_and_copy
<char, boolNDArray>;
;
3104 FILL_TABLE_ROW (dt_schar, signed char)conv_fptr_table[oct_data_conv::dt_schar][oct_data_conv::dt_int8
] = convert_and_copy<signed char, int8NDArray>; conv_fptr_table
[oct_data_conv::dt_schar][oct_data_conv::dt_uint8] = convert_and_copy
<signed char, uint8NDArray>; conv_fptr_table[oct_data_conv
::dt_schar][oct_data_conv::dt_int16] = convert_and_copy<signed
char, int16NDArray>; conv_fptr_table[oct_data_conv::dt_schar
][oct_data_conv::dt_uint16] = convert_and_copy<signed char
, uint16NDArray>; conv_fptr_table[oct_data_conv::dt_schar]
[oct_data_conv::dt_int32] = convert_and_copy<signed char, int32NDArray
>; conv_fptr_table[oct_data_conv::dt_schar][oct_data_conv::
dt_uint32] = convert_and_copy<signed char, uint32NDArray>
; conv_fptr_table[oct_data_conv::dt_schar][oct_data_conv::dt_int64
] = convert_and_copy<signed char, int64NDArray>; conv_fptr_table
[oct_data_conv::dt_schar][oct_data_conv::dt_uint64] = convert_and_copy
<signed char, uint64NDArray>; conv_fptr_table[oct_data_conv
::dt_schar][oct_data_conv::dt_single] = convert_and_copy<signed
char, FloatNDArray>; conv_fptr_table[oct_data_conv::dt_schar
][oct_data_conv::dt_double] = convert_and_copy<signed char
, NDArray>; conv_fptr_table[oct_data_conv::dt_schar][oct_data_conv
::dt_char] = convert_and_copy<signed char, charNDArray>
; conv_fptr_table[oct_data_conv::dt_schar][oct_data_conv::dt_schar
] = convert_and_copy<signed char, charNDArray>; conv_fptr_table
[oct_data_conv::dt_schar][oct_data_conv::dt_uchar] = convert_and_copy
<signed char, charNDArray>; conv_fptr_table[oct_data_conv
::dt_schar][oct_data_conv::dt_logical] = convert_and_copy<
signed char, boolNDArray>;
;
3105 FILL_TABLE_ROW (dt_uchar, unsigned char)conv_fptr_table[oct_data_conv::dt_uchar][oct_data_conv::dt_int8
] = convert_and_copy<unsigned char, int8NDArray>; conv_fptr_table
[oct_data_conv::dt_uchar][oct_data_conv::dt_uint8] = convert_and_copy
<unsigned char, uint8NDArray>; conv_fptr_table[oct_data_conv
::dt_uchar][oct_data_conv::dt_int16] = convert_and_copy<unsigned
char, int16NDArray>; conv_fptr_table[oct_data_conv::dt_uchar
][oct_data_conv::dt_uint16] = convert_and_copy<unsigned char
, uint16NDArray>; conv_fptr_table[oct_data_conv::dt_uchar]
[oct_data_conv::dt_int32] = convert_and_copy<unsigned char
, int32NDArray>; conv_fptr_table[oct_data_conv::dt_uchar][
oct_data_conv::dt_uint32] = convert_and_copy<unsigned char
, uint32NDArray>; conv_fptr_table[oct_data_conv::dt_uchar]
[oct_data_conv::dt_int64] = convert_and_copy<unsigned char
, int64NDArray>; conv_fptr_table[oct_data_conv::dt_uchar][
oct_data_conv::dt_uint64] = convert_and_copy<unsigned char
, uint64NDArray>; conv_fptr_table[oct_data_conv::dt_uchar]
[oct_data_conv::dt_single] = convert_and_copy<unsigned char
, FloatNDArray>; conv_fptr_table[oct_data_conv::dt_uchar][
oct_data_conv::dt_double] = convert_and_copy<unsigned char
, NDArray>; conv_fptr_table[oct_data_conv::dt_uchar][oct_data_conv
::dt_char] = convert_and_copy<unsigned char, charNDArray>
; conv_fptr_table[oct_data_conv::dt_uchar][oct_data_conv::dt_schar
] = convert_and_copy<unsigned char, charNDArray>; conv_fptr_table
[oct_data_conv::dt_uchar][oct_data_conv::dt_uchar] = convert_and_copy
<unsigned char, charNDArray>; conv_fptr_table[oct_data_conv
::dt_uchar][oct_data_conv::dt_logical] = convert_and_copy<
unsigned char, boolNDArray>;
;
3106 FILL_TABLE_ROW (dt_logical, bool)conv_fptr_table[oct_data_conv::dt_logical][oct_data_conv::dt_int8
] = convert_and_copy<bool, int8NDArray>; conv_fptr_table
[oct_data_conv::dt_logical][oct_data_conv::dt_uint8] = convert_and_copy
<bool, uint8NDArray>; conv_fptr_table[oct_data_conv::dt_logical
][oct_data_conv::dt_int16] = convert_and_copy<bool, int16NDArray
>; conv_fptr_table[oct_data_conv::dt_logical][oct_data_conv
::dt_uint16] = convert_and_copy<bool, uint16NDArray>; conv_fptr_table
[oct_data_conv::dt_logical][oct_data_conv::dt_int32] = convert_and_copy
<bool, int32NDArray>; conv_fptr_table[oct_data_conv::dt_logical
][oct_data_conv::dt_uint32] = convert_and_copy<bool, uint32NDArray
>; conv_fptr_table[oct_data_conv::dt_logical][oct_data_conv
::dt_int64] = convert_and_copy<bool, int64NDArray>; conv_fptr_table
[oct_data_conv::dt_logical][oct_data_conv::dt_uint64] = convert_and_copy
<bool, uint64NDArray>; conv_fptr_table[oct_data_conv::dt_logical
][oct_data_conv::dt_single] = convert_and_copy<bool, FloatNDArray
>; conv_fptr_table[oct_data_conv::dt_logical][oct_data_conv
::dt_double] = convert_and_copy<bool, NDArray>; conv_fptr_table
[oct_data_conv::dt_logical][oct_data_conv::dt_char] = convert_and_copy
<bool, charNDArray>; conv_fptr_table[oct_data_conv::dt_logical
][oct_data_conv::dt_schar] = convert_and_copy<bool, charNDArray
>; conv_fptr_table[oct_data_conv::dt_logical][oct_data_conv
::dt_uchar] = convert_and_copy<bool, charNDArray>; conv_fptr_table
[oct_data_conv::dt_logical][oct_data_conv::dt_logical] = convert_and_copy
<bool, boolNDArray>;
;
3107
3108 initialized = true;
3109 }
3110
3111 bool swap = false;
3112
3113 if (ffmt == oct_mach_info::flt_fmt_unknown)
3114 ffmt = float_format ();
3115
3116 if (oct_mach_info::words_big_endian ())
3117 swap = (ffmt == oct_mach_info::flt_fmt_ieee_little_endian);
3118 else
3119 swap = (ffmt == oct_mach_info::flt_fmt_ieee_big_endian);
3120
3121 bool do_float_fmt_conv = ((input_type == oct_data_conv::dt_double
3122 || input_type == oct_data_conv::dt_single)
3123 && ffmt != float_format ());
3124
3125 bool do_NA_conv = (output_type == oct_data_conv::dt_double);
3126
3127 switch (output_type)
3128 {
3129 case oct_data_conv::dt_int8:
3130 case oct_data_conv::dt_uint8:
3131 case oct_data_conv::dt_int16:
3132 case oct_data_conv::dt_uint16:
3133 case oct_data_conv::dt_int32:
3134 case oct_data_conv::dt_uint32:
3135 case oct_data_conv::dt_int64:
3136 case oct_data_conv::dt_uint64:
3137 case oct_data_conv::dt_single:
3138 case oct_data_conv::dt_double:
3139 case oct_data_conv::dt_char:
3140 case oct_data_conv::dt_schar:
3141 case oct_data_conv::dt_uchar:
3142 case oct_data_conv::dt_logical:
3143 {
3144 conv_fptr fptr = conv_fptr_table[input_type][output_type];
3145
3146 retval = fptr (input_buf_list, input_buf_elts, elts_read,
3147 nr, nc, swap, do_float_fmt_conv, do_NA_conv, ffmt);
3148 }
3149 break;
3150
3151 default:
3152 retval = false;
3153 (*current_liboctave_error_handler)
3154 ("read: invalid type specification");
3155 break;
3156 }
3157
3158
3159 return retval;
3160}
3161
3162octave_value
3163octave_stream::read (const Array<double>& size, octave_idx_type block_size,
3164 oct_data_conv::data_type input_type,
3165 oct_data_conv::data_type output_type,
3166 octave_idx_type skip, oct_mach_info::float_format ffmt,
3167 octave_idx_type& char_count)
3168{
3169 octave_value retval;
3170
3171 octave_idx_type nr = -1;
3172 octave_idx_type nc = -1;
3173
3174 bool one_elt_size_spec = false;
3175
3176 if (stream_ok ())
3177 {
3178 // FIXME: we may eventually want to make this extensible.
3179
3180 // FIXME: we need a better way to ensure that this
3181 // numbering stays consistent with the order of the elements in the
3182 // data_type enum in the oct_data_conv class.
3183
3184 char_count = 0;
3185
3186 get_size (size, nr, nc, one_elt_size_spec, "fread");
3187
3188 if (! error_state)
3189 {
3190
3191 octave_idx_type elts_to_read
Value stored to 'elts_to_read' during its initialization is never read
3192 = std::numeric_limits<octave_idx_type>::max ();
3193
3194 if (one_elt_size_spec)
3195 {
3196 // If NR == 0, Matlab returns [](0x0).
3197
3198 // If NR > 0, the result will be a column vector with the given
3199 // number of rows.
3200
3201 // If NR < 0, then we have Inf and the result will be a column
3202 // vector but we have to wait to see how big NR will be.
3203
3204 if (nr == 0)
3205 nr = nc = 0;
3206 else
3207 nc = 1;
3208 }
3209 else
3210 {
3211 // Matlab returns [] even if there are two elements in the size
3212 // specification and one is nonzero.
3213
3214 // If NC < 0 we have [NR, Inf] and we'll wait to decide how big NC
3215 // should be.
3216
3217 if (nr == 0 || nc == 0)
3218 nr = nc = 0;
3219 }
3220
3221 // FIXME: ensure that this does not overflow.
3222
3223 elts_to_read = nr * nc;
3224
3225 bool read_to_eof = elts_to_read < 0;
3226
3227 octave_idx_type input_buf_elts = -1;
3228
3229 if (skip == 0)
3230 {
3231 if (read_to_eof)
3232 input_buf_elts = 1024 * 1024;
3233 else
3234 input_buf_elts = elts_to_read;
3235 }
3236 else
3237 input_buf_elts = block_size;
3238
3239 octave_idx_type input_elt_size
3240 = oct_data_conv::data_type_size (input_type);
3241
3242 octave_idx_type input_buf_size = input_buf_elts * input_elt_size;
3243
3244 assert (input_buf_size >= 0)((input_buf_size >= 0) ? static_cast<void> (0) : __assert_fail
("input_buf_size >= 0", "corefcn/oct-stream.cc", 3244, __PRETTY_FUNCTION__
))
;
3245
3246 // Must also work and return correct type object
3247 // for 0 elements to read.
3248
3249 std::istream *isp = input_stream ();
3250
3251 if (isp)
3252 {
3253 std::istream& is = *isp;
3254
3255 std::list <void *> input_buf_list;
3256
3257 octave_idx_type elts_read = 0;
3258
3259 while (is && ! is.eof ()
3260 && (read_to_eof || elts_read < elts_to_read))
3261 {
3262 char *input_buf = new char [input_buf_size];
3263
3264 is.read (input_buf, input_buf_size);
3265
3266 size_t count = is.gcount ();
3267
3268 char_count += count;
3269
3270 elts_read += count / input_elt_size;
3271
3272 input_buf_list.push_back (input_buf);
3273
3274 if (is && skip != 0 && elts_read == block_size)
3275 {
3276 int seek_status = seek (skip, SEEK_CUR1);
3277
3278 if (seek_status < 0)
3279 break;
3280 }
3281 }
3282
3283 if (read_to_eof)
3284 {
3285 if (nc < 0)
3286 nc = elts_read / nr + 1;
3287 else
3288 nr = elts_read;
3289 }
3290
3291 retval = finalize_read (input_buf_list, input_buf_elts, elts_read,
3292 nr, nc, input_type, output_type, ffmt);
3293 }
3294 else
3295 error ("fread: invalid input stream");
3296 }
3297 else
3298 invalid_operation ("fread", "reading");
3299 }
3300
3301 return retval;
3302}
3303
3304octave_idx_type
3305octave_stream::write (const octave_value& data, octave_idx_type block_size,
3306 oct_data_conv::data_type output_type,
3307 octave_idx_type skip, oct_mach_info::float_format flt_fmt)
3308{
3309 octave_idx_type retval = -1;
3310
3311 if (stream_ok ())
3312 {
3313 if (! error_state)
3314 {
3315 if (flt_fmt == oct_mach_info::flt_fmt_unknown)
3316 flt_fmt = float_format ();
3317
3318 octave_idx_type status = data.write (*this, block_size, output_type,
3319 skip, flt_fmt);
3320
3321 if (status < 0)
3322 error ("fwrite: write error");
3323 else
3324 retval = status;
3325 }
3326 else
3327 invalid_operation ("fwrite", "writing");
3328 }
3329
3330 return retval;
3331}
3332
3333template <class T, class V>
3334static void
3335convert_ints (const T *data, void *conv_data, octave_idx_type n_elts,
3336 bool swap)
3337{
3338 typedef typename V::val_type val_type;
3339
3340 val_type *vt_data = static_cast <val_type *> (conv_data);
3341
3342 for (octave_idx_type i = 0; i < n_elts; i++)
3343 {
3344 V val (data[i]);
3345
3346 vt_data[i] = val.value ();
3347
3348 if (swap)
3349 swap_bytes<sizeof (val_type)> (&vt_data[i]);
3350 }
3351}
3352
3353template <class T>
3354static bool
3355convert_data (const T *data, void *conv_data, octave_idx_type n_elts,
3356 oct_data_conv::data_type output_type,
3357 oct_mach_info::float_format flt_fmt)
3358{
3359 bool retval = true;
3360
3361 bool swap
3362 = ((oct_mach_info::words_big_endian ()
3363 && flt_fmt == oct_mach_info::flt_fmt_ieee_little_endian)
3364 || flt_fmt == oct_mach_info::flt_fmt_ieee_big_endian);
3365
3366 bool do_float_conversion = flt_fmt != oct_mach_info::float_format ();
3367
3368 // We use octave_intN classes here instead of converting directly to
3369 // intN_t so that we get integer saturation semantics.
3370
3371 switch (output_type)
3372 {
3373 case oct_data_conv::dt_char:
3374 case oct_data_conv::dt_schar:
3375 case oct_data_conv::dt_int8:
3376 convert_ints<T, octave_int8> (data, conv_data, n_elts, swap);
3377 break;
3378
3379 case oct_data_conv::dt_uchar:
3380 case oct_data_conv::dt_uint8:
3381 convert_ints<T, octave_uint8> (data, conv_data, n_elts, swap);
3382 break;
3383
3384 case oct_data_conv::dt_int16:
3385 convert_ints<T, octave_int16> (data, conv_data, n_elts, swap);
3386 break;
3387
3388 case oct_data_conv::dt_uint16:
3389 convert_ints<T, octave_uint16> (data, conv_data, n_elts, swap);
3390 break;
3391
3392 case oct_data_conv::dt_int32:
3393 convert_ints<T, octave_int32> (data, conv_data, n_elts, swap);
3394 break;
3395
3396 case oct_data_conv::dt_uint32:
3397 convert_ints<T, octave_uint32> (data, conv_data, n_elts, swap);
3398 break;
3399
3400 case oct_data_conv::dt_int64:
3401 convert_ints<T, octave_int64> (data, conv_data, n_elts, swap);
3402 break;
3403
3404 case oct_data_conv::dt_uint64:
3405 convert_ints<T, octave_uint64> (data, conv_data, n_elts, swap);
3406 break;
3407
3408 case oct_data_conv::dt_single:
3409 {
3410 float *vt_data = static_cast <float *> (conv_data);
3411
3412 for (octave_idx_type i = 0; i < n_elts; i++)
3413 {
3414 vt_data[i] = data[i];
3415
3416 if (do_float_conversion)
3417 do_float_format_conversion (&vt_data[i], 1, flt_fmt);
3418 }
3419 }
3420 break;
3421
3422 case oct_data_conv::dt_double:
3423 {
3424 double *vt_data = static_cast <double *> (conv_data);
3425
3426 for (octave_idx_type i = 0; i < n_elts; i++)
3427 {
3428 vt_data[i] = data[i];
3429
3430 if (do_float_conversion)
3431 do_double_format_conversion (&vt_data[i], 1, flt_fmt);
3432 }
3433 }
3434 break;
3435
3436 default:
3437 retval = false;
3438 (*current_liboctave_error_handler)
3439 ("write: invalid type specification");
3440 break;
3441 }
3442
3443 return retval;
3444}
3445
3446bool
3447octave_stream::write_bytes (const void *data, size_t nbytes)
3448{
3449 bool status = false;
3450
3451 std::ostream *osp = output_stream ();
3452
3453 if (osp)
3454 {
3455 std::ostream& os = *osp;
3456
3457 if (os)
3458 {
3459 os.write (static_cast<const char *> (data), nbytes);
3460
3461 if (os)
3462 status = true;
3463 }
3464 }
3465
3466 return status;
3467}
3468
3469bool
3470octave_stream::skip_bytes (size_t skip)
3471{
3472 bool status = false;
3473
3474 std::ostream *osp = output_stream ();
3475
3476 if (osp)
3477 {
3478 std::ostream& os = *osp;
3479
3480 // Seek to skip when inside bounds of existing file.
3481 // Otherwise, write NUL to skip.
3482
3483 off_t orig_pos = tell ();
3484
3485 seek (0, SEEK_END2);
3486
3487 off_t eof_pos = tell ();
3488
3489 // Is it possible for this to fail to return us to the
3490 // original position?
3491 seek (orig_pos, SEEK_SET0);
3492
3493 size_t remaining = eof_pos - orig_pos;
3494
3495 if (remaining < skip)
3496 {
3497 seek (0, SEEK_END2);
3498
3499 // FIXME: probably should try to write larger blocks...
3500
3501 unsigned char zero = 0;
3502 for (size_t j = 0; j < skip - remaining; j++)
3503 os.write (reinterpret_cast<const char *> (&zero), 1);
3504 }
3505 else
3506 seek (skip, SEEK_CUR1);
3507
3508 if (os)
3509 status = true;
3510 }
3511
3512 return status;
3513}
3514
3515template <class T>
3516octave_idx_type
3517octave_stream::write (const Array<T>& data, octave_idx_type block_size,
3518 oct_data_conv::data_type output_type,
3519 octave_idx_type skip,
3520 oct_mach_info::float_format flt_fmt)
3521{
3522 bool swap = ((oct_mach_info::words_big_endian ()
3523 && flt_fmt == oct_mach_info::flt_fmt_ieee_little_endian)
3524 || flt_fmt == oct_mach_info::flt_fmt_ieee_big_endian);
3525
3526 bool do_data_conversion = (swap || ! is_equivalent_type<T> (output_type)
3527 || flt_fmt != oct_mach_info::float_format ());
3528
3529 octave_idx_type nel = data.numel ();
3530
3531 octave_idx_type chunk_size;
3532
3533 if (skip != 0)
3534 chunk_size = block_size;
3535 else if (do_data_conversion)
3536 chunk_size = 1024 * 1024;
3537 else
3538 chunk_size = nel;
3539
3540 octave_idx_type i = 0;
3541
3542 const T *pdata = data.data ();
3543
3544 while (i < nel)
3545 {
3546 if (skip != 0)
3547 {
3548 if (! skip_bytes (skip))
3549 return -1;
3550 }
3551
3552 octave_idx_type remaining_nel = nel - i;
3553
3554 if (chunk_size > remaining_nel)
3555 chunk_size = remaining_nel;
3556
3557 bool status = false;
3558
3559 if (do_data_conversion)
3560 {
3561 size_t output_size
3562 = chunk_size * oct_data_conv::data_type_size (output_type);
3563
3564 OCTAVE_LOCAL_BUFFER (unsigned char, conv_data, output_size)octave_local_buffer<unsigned char> _buffer_conv_data (output_size
); unsigned char *conv_data = _buffer_conv_data
;
3565
3566 status = convert_data (&pdata[i], conv_data, chunk_size,
3567 output_type, flt_fmt);
3568
3569 if (status)
3570 status = write_bytes (conv_data, output_size);
3571 }
3572 else
3573 status = write_bytes (pdata, sizeof (T) * chunk_size);
3574
3575 if (! status)
3576 return -1;
3577
3578 i += chunk_size;
3579 }
3580
3581 return nel;
3582}
3583
3584#define INSTANTIATE_WRITE(T)template octave_idx_type octave_stream::write (const Array<
T>& data, octave_idx_type block_size, oct_data_conv::data_type
output_type, octave_idx_type skip, oct_mach_info::float_format
flt_fmt)
\
3585 template \
3586 octave_idx_type \
3587 octave_stream::write (const Array<T>& data, octave_idx_type block_size, \
3588 oct_data_conv::data_type output_type, \
3589 octave_idx_type skip, \
3590 oct_mach_info::float_format flt_fmt)
3591
3592INSTANTIATE_WRITE (octave_int8)template octave_idx_type octave_stream::write (const Array<
octave_int8>& data, octave_idx_type block_size, oct_data_conv
::data_type output_type, octave_idx_type skip, oct_mach_info::
float_format flt_fmt)
;
3593INSTANTIATE_WRITE (octave_uint8)template octave_idx_type octave_stream::write (const Array<
octave_uint8>& data, octave_idx_type block_size, oct_data_conv
::data_type output_type, octave_idx_type skip, oct_mach_info::
float_format flt_fmt)
;
3594INSTANTIATE_WRITE (octave_int16)template octave_idx_type octave_stream::write (const Array<
octave_int16>& data, octave_idx_type block_size, oct_data_conv
::data_type output_type, octave_idx_type skip, oct_mach_info::
float_format flt_fmt)
;
3595INSTANTIATE_WRITE (octave_uint16)template octave_idx_type octave_stream::write (const Array<
octave_uint16>& data, octave_idx_type block_size, oct_data_conv
::data_type output_type, octave_idx_type skip, oct_mach_info::
float_format flt_fmt)
;
3596INSTANTIATE_WRITE (octave_int32)template octave_idx_type octave_stream::write (const Array<
octave_int32>& data, octave_idx_type block_size, oct_data_conv
::data_type output_type, octave_idx_type skip, oct_mach_info::
float_format flt_fmt)
;
3597INSTANTIATE_WRITE (octave_uint32)template octave_idx_type octave_stream::write (const Array<
octave_uint32>& data, octave_idx_type block_size, oct_data_conv
::data_type output_type, octave_idx_type skip, oct_mach_info::
float_format flt_fmt)
;
3598INSTANTIATE_WRITE (octave_int64)template octave_idx_type octave_stream::write (const Array<
octave_int64>& data, octave_idx_type block_size, oct_data_conv
::data_type output_type, octave_idx_type skip, oct_mach_info::
float_format flt_fmt)
;
3599INSTANTIATE_WRITE (octave_uint64)template octave_idx_type octave_stream::write (const Array<
octave_uint64>& data, octave_idx_type block_size, oct_data_conv
::data_type output_type, octave_idx_type skip, oct_mach_info::
float_format flt_fmt)
;
3600INSTANTIATE_WRITE (int8_t)template octave_idx_type octave_stream::write (const Array<
int8_t>& data, octave_idx_type block_size, oct_data_conv
::data_type output_type, octave_idx_type skip, oct_mach_info::
float_format flt_fmt)
;
3601INSTANTIATE_WRITE (uint8_t)template octave_idx_type octave_stream::write (const Array<
uint8_t>& data, octave_idx_type block_size, oct_data_conv
::data_type output_type, octave_idx_type skip, oct_mach_info::
float_format flt_fmt)
;
3602INSTANTIATE_WRITE (int16_t)template octave_idx_type octave_stream::write (const Array<
int16_t>& data, octave_idx_type block_size, oct_data_conv
::data_type output_type, octave_idx_type skip, oct_mach_info::
float_format flt_fmt)
;
3603INSTANTIATE_WRITE (uint16_t)template octave_idx_type octave_stream::write (const Array<
uint16_t>& data, octave_idx_type block_size, oct_data_conv
::data_type output_type, octave_idx_type skip, oct_mach_info::
float_format flt_fmt)
;
3604INSTANTIATE_WRITE (int32_t)template octave_idx_type octave_stream::write (const Array<
int32_t>& data, octave_idx_type block_size, oct_data_conv
::data_type output_type, octave_idx_type skip, oct_mach_info::
float_format flt_fmt)
;
3605INSTANTIATE_WRITE (uint32_t)template octave_idx_type octave_stream::write (const Array<
uint32_t>& data, octave_idx_type block_size, oct_data_conv
::data_type output_type, octave_idx_type skip, oct_mach_info::
float_format flt_fmt)
;
3606INSTANTIATE_WRITE (int64_t)template octave_idx_type octave_stream::write (const Array<
int64_t>& data, octave_idx_type block_size, oct_data_conv
::data_type output_type, octave_idx_type skip, oct_mach_info::
float_format flt_fmt)
;
3607INSTANTIATE_WRITE (uint64_t)template octave_idx_type octave_stream::write (const Array<
uint64_t>& data, octave_idx_type block_size, oct_data_conv
::data_type output_type, octave_idx_type skip, oct_mach_info::
float_format flt_fmt)
;
3608INSTANTIATE_WRITE (bool)template octave_idx_type octave_stream::write (const Array<
bool>& data, octave_idx_type block_size, oct_data_conv
::data_type output_type, octave_idx_type skip, oct_mach_info::
float_format flt_fmt)
;
3609INSTANTIATE_WRITE (char)template octave_idx_type octave_stream::write (const Array<
char>& data, octave_idx_type block_size, oct_data_conv
::data_type output_type, octave_idx_type skip, oct_mach_info::
float_format flt_fmt)
;
3610INSTANTIATE_WRITE (float)template octave_idx_type octave_stream::write (const Array<
float>& data, octave_idx_type block_size, oct_data_conv
::data_type output_type, octave_idx_type skip, oct_mach_info::
float_format flt_fmt)
;
3611INSTANTIATE_WRITE (double)template octave_idx_type octave_stream::write (const Array<
double>& data, octave_idx_type block_size, oct_data_conv
::data_type output_type, octave_idx_type skip, oct_mach_info::
float_format flt_fmt)
;
3612
3613octave_value
3614octave_stream::scanf (const std::string& fmt, const Array<double>& size,
3615 octave_idx_type& count, const std::string& who)
3616{
3617 octave_value retval;
3618
3619 if (stream_ok ())
3620 retval = rep->scanf (fmt, size, count, who);
3621
3622 return retval;
3623}
3624
3625octave_value
3626octave_stream::scanf (const octave_value& fmt, const Array<double>& size,
3627 octave_idx_type& count, const std::string& who)
3628{
3629 octave_value retval = Matrix ();
3630
3631 if (fmt.is_string ())
3632 {
3633 std::string sfmt = fmt.string_value ();
3634
3635 if (fmt.is_sq_string ())
3636 sfmt = do_string_escapes (sfmt);
3637
3638 retval = scanf (sfmt, size, count, who);
3639 }
3640 else
3641 {
3642 // Note that this is not ::error () !
3643
3644 error (who + ": format must be a string");
3645 }
3646
3647 return retval;
3648}
3649
3650octave_value_list
3651octave_stream::oscanf (const std::string& fmt, const std::string& who)
3652{
3653 octave_value_list retval;
3654
3655 if (stream_ok ())
3656 retval = rep->oscanf (fmt, who);
3657
3658 return retval;
3659}
3660
3661octave_value_list
3662octave_stream::oscanf (const octave_value& fmt, const std::string& who)
3663{
3664 octave_value_list retval;
3665
3666 if (fmt.is_string ())
3667 {
3668 std::string sfmt = fmt.string_value ();
3669
3670 if (fmt.is_sq_string ())
3671 sfmt = do_string_escapes (sfmt);
3672
3673 retval = oscanf (sfmt, who);
3674 }
3675 else
3676 {
3677 // Note that this is not ::error () !
3678
3679 error (who + ": format must be a string");
3680 }
3681
3682 return retval;
3683}
3684
3685int
3686octave_stream::printf (const std::string& fmt, const octave_value_list& args,
3687 const std::string& who)
3688{
3689 int retval = -1;
3690
3691 if (stream_ok ())
3692 retval = rep->printf (fmt, args, who);
3693
3694 return retval;
3695}
3696
3697int
3698octave_stream::printf (const octave_value& fmt, const octave_value_list& args,
3699 const std::string& who)
3700{
3701 int retval = 0;
3702
3703 if (fmt.is_string ())
3704 {
3705 std::string sfmt = fmt.string_value ();
3706
3707 if (fmt.is_sq_string ())
3708 sfmt = do_string_escapes (sfmt);
3709
3710 retval = printf (sfmt, args, who);
3711 }
3712 else
3713 {
3714 // Note that this is not ::error () !
3715
3716 error (who + ": format must be a string");
3717 }
3718
3719 return retval;
3720}
3721
3722int
3723octave_stream::puts (const std::string& s, const std::string& who)
3724{
3725 int retval = -1;
3726
3727 if (stream_ok ())
3728 retval = rep->puts (s, who);
3729
3730 return retval;
3731}
3732
3733// FIXME: maybe this should work for string arrays too.
3734
3735int
3736octave_stream::puts (const octave_value& tc_s, const std::string& who)
3737{
3738 int retval = -1;
3739
3740 if (tc_s.is_string ())
3741 {
3742 std::string s = tc_s.string_value ();
3743 retval = puts (s, who);
3744 }
3745 else
3746 {
3747 // Note that this is not ::error () !
3748
3749 error (who + ": argument must be a string");
3750 }
3751
3752 return retval;
3753}
3754
3755bool
3756octave_stream::eof (void) const
3757{
3758 int retval = -1;
3759
3760 if (stream_ok ())
3761 retval = rep->eof ();
3762
3763 return retval;
3764}
3765
3766std::string
3767octave_stream::error (bool clear, int& err_num)
3768{
3769 std::string retval = "invalid stream object";
3770
3771 if (stream_ok (false))
3772 retval = rep->error (clear, err_num);
3773
3774 return retval;
3775}
3776
3777std::string
3778octave_stream::name (void) const
3779{
3780 std::string retval;
3781
3782 if (stream_ok ())
3783 retval = rep->name ();
3784
3785 return retval;
3786}
3787
3788int
3789octave_stream::mode (void) const
3790{
3791 int retval = 0;
3792
3793 if (stream_ok ())
3794 retval = rep->mode ();
3795
3796 return retval;
3797}
3798
3799oct_mach_info::float_format
3800octave_stream::float_format (void) const
3801{
3802 oct_mach_info::float_format retval = oct_mach_info::flt_fmt_unknown;
3803
3804 if (stream_ok ())
3805 retval = rep->float_format ();
3806
3807 return retval;
3808}
3809
3810std::string
3811octave_stream::mode_as_string (int mode)
3812{
3813 std::string retval = "???";
3814 std::ios::openmode in_mode = static_cast<std::ios::openmode> (mode);
3815
3816 if (in_mode == std::ios::in)
3817 retval = "r";
3818 else if (in_mode == std::ios::out
3819 || in_mode == (std::ios::out | std::ios::trunc))
3820 retval = "w";
3821 else if (in_mode == (std::ios::out | std::ios::app))
3822 retval = "a";
3823 else if (in_mode == (std::ios::in | std::ios::out))
3824 retval = "r+";
3825 else if (in_mode == (std::ios::in | std::ios::out | std::ios::trunc))
3826 retval = "w+";
3827 else if (in_mode == (std::ios::in | std::ios::out | std::ios::ate))
3828 retval = "a+";
3829 else if (in_mode == (std::ios::in | std::ios::binary))
3830 retval = "rb";
3831 else if (in_mode == (std::ios::out | std::ios::binary)
3832 || in_mode == (std::ios::out | std::ios::trunc | std::ios::binary))
3833 retval = "wb";
3834 else if (in_mode == (std::ios::out | std::ios::app | std::ios::binary))
3835 retval = "ab";
3836 else if (in_mode == (std::ios::in | std::ios::out | std::ios::binary))
3837 retval = "r+b";
3838 else if (in_mode == (std::ios::in | std::ios::out | std::ios::trunc
3839 | std::ios::binary))
3840 retval = "w+b";
3841 else if (in_mode == (std::ios::in | std::ios::out | std::ios::ate
3842 | std::ios::binary))
3843 retval = "a+b";
3844
3845 return retval;
3846}
3847
3848octave_stream_list *octave_stream_list::instance = 0;
3849
3850bool
3851octave_stream_list::instance_ok (void)
3852{
3853 bool retval = true;
3854
3855 if (! instance)
3856 {
3857 instance = new octave_stream_list ();
3858
3859 if (instance)
3860 singleton_cleanup_list::add (cleanup_instance);
3861 }
3862
3863 if (! instance)
3864 {
3865 ::error ("unable to create stream list object!");
3866
3867 retval = false;
3868 }
3869
3870 return retval;
3871}
3872
3873int
3874octave_stream_list::insert (octave_stream& os)
3875{
3876 return (instance_ok ()) ? instance->do_insert (os) : -1;
3877}
3878
3879octave_stream
3880octave_stream_list::lookup (int fid, const std::string& who)
3881{
3882 return (instance_ok ()) ? instance->do_lookup (fid, who) : octave_stream ();
3883}
3884
3885octave_stream
3886octave_stream_list::lookup (const octave_value& fid, const std::string& who)
3887{
3888 return (instance_ok ()) ? instance->do_lookup (fid, who) : octave_stream ();
3889}
3890
3891int
3892octave_stream_list::remove (int fid, const std::string& who)
3893{
3894 return (instance_ok ()) ? instance->do_remove (fid, who) : -1;
3895}
3896
3897int
3898octave_stream_list::remove (const octave_value& fid, const std::string& who)
3899{
3900 return (instance_ok ()) ? instance->do_remove (fid, who) : -1;
3901}
3902
3903void
3904octave_stream_list::clear (bool flush)
3905{
3906 if (instance)
3907 instance->do_clear (flush);
3908}
3909
3910string_vector
3911octave_stream_list::get_info (int fid)
3912{
3913 return (instance_ok ()) ? instance->do_get_info (fid) : string_vector ();
3914}
3915
3916string_vector
3917octave_stream_list::get_info (const octave_value& fid)
3918{
3919 return (instance_ok ()) ? instance->do_get_info (fid) : string_vector ();
3920}
3921
3922std::string
3923octave_stream_list::list_open_files (void)
3924{
3925 return (instance_ok ()) ? instance->do_list_open_files () : std::string ();
3926}
3927
3928octave_value
3929octave_stream_list::open_file_numbers (void)
3930{
3931 return (instance_ok ())
3932 ? instance->do_open_file_numbers () : octave_value ();
3933}
3934
3935int
3936octave_stream_list::get_file_number (const octave_value& fid)
3937{
3938 return (instance_ok ()) ? instance->do_get_file_number (fid) : -1;
3939}
3940
3941int
3942octave_stream_list::do_insert (octave_stream& os)
3943{
3944 // Insert item with key corresponding to file-descriptor.
3945
3946 int stream_number;
3947
3948 if ((stream_number = os.file_number ()) == -1)
3949 return stream_number;
3950
3951 // Should we test for "(list.find (stream_number) != list.end ()) &&
3952 // list[stream_number].is_open ()" and respond with "error
3953 // ("internal error: ...")"? It should not happen except for some
3954 // bug or if the user has opened a stream with an interpreted
3955 // command, but closed it directly with a system call in an
3956 // oct-file; then the kernel knows the fd is free, but Octave does
3957 // not know. If it happens, it should not do harm here to simply
3958 // overwrite this entry, although the wrong entry might have done
3959 // harm before.
3960
3961 if (list.size () < list.max_size ())
3962 list[stream_number] = os;
3963 else
3964 {
3965 stream_number = -1;
3966 error ("could not create file id");
3967 }
3968
3969 return stream_number;
3970
3971}
3972
3973static void
3974gripe_invalid_file_id (int fid, const std::string& who)
3975{
3976 if (who.empty ())
3977 ::error ("invalid stream number = %d", fid);
3978 else
3979 ::error ("%s: invalid stream number = %d", who.c_str (), fid);
3980}
3981
3982octave_stream
3983octave_stream_list::do_lookup (int fid, const std::string& who) const
3984{
3985 octave_stream retval;
3986
3987 if (fid >= 0)
3988 {
3989 if (lookup_cache != list.end () && lookup_cache->first == fid)
3990 retval = lookup_cache->second;
3991 else
3992 {
3993 ostrl_map::const_iterator iter = list.find (fid);
3994
3995 if (iter != list.end ())
3996 {
3997 retval = iter->second;
3998 lookup_cache = iter;
3999 }
4000 else
4001 gripe_invalid_file_id (fid, who);
4002 }
4003 }
4004 else
4005 gripe_invalid_file_id (fid, who);
4006
4007 return retval;
4008}
4009
4010octave_stream
4011octave_stream_list::do_lookup (const octave_value& fid,
4012 const std::string& who) const
4013{
4014 octave_stream retval;
4015
4016 int i = get_file_number (fid);
4017
4018 if (! error_state)
4019 retval = do_lookup (i, who);
4020
4021 return retval;
4022}
4023
4024int
4025octave_stream_list::do_remove (int fid, const std::string& who)
4026{
4027 int retval = -1;
4028
4029 // Can't remove stdin (std::cin), stdout (std::cout), or stderr
4030 // (std::cerr).
4031
4032 if (fid > 2)
4033 {
4034 ostrl_map::iterator iter = list.find (fid);
4035
4036 if (iter != list.end ())
4037 {
4038 octave_stream os = iter->second;
4039 list.erase (iter);
4040 lookup_cache = list.end ();
4041
4042 // FIXME: is this check redundant?
4043 if (os.is_valid ())
4044 {
4045 os.close ();
4046 retval = 0;
4047 }
4048 else
4049 gripe_invalid_file_id (fid, who);
4050 }
4051 else
4052 gripe_invalid_file_id (fid, who);
4053 }
4054 else
4055 gripe_invalid_file_id (fid, who);
4056
4057 return retval;
4058}
4059
4060int
4061octave_stream_list::do_remove (const octave_value& fid, const std::string& who)
4062{
4063 int retval = -1;
4064
4065 if (fid.is_string () && fid.string_value () == "all")
4066 {
4067 do_clear (false);
4068
4069 retval = 0;
4070 }
4071 else
4072 {
4073 int i = get_file_number (fid);
4074
4075 if (! error_state)
4076 retval = do_remove (i, who);
4077 }
4078
4079 return retval;
4080}
4081
4082void
4083octave_stream_list::do_clear (bool flush)
4084{
4085 if (flush)
4086 {
4087 // Do flush stdout and stderr.
4088
4089 list[0].flush ();
4090 list[1].flush ();
4091 }
4092
4093 octave_stream saved_os[3];
4094 // But don't delete them or stdin.
4095 for (ostrl_map::iterator iter = list.begin (); iter != list.end (); iter++)
4096 {
4097 int fid = iter->first;
4098 octave_stream os = iter->second;
4099 if (fid < 3)
4100 saved_os[fid] = os;
4101 else if (os.is_valid ())
4102 os.close ();
4103 }
4104 list.clear ();
4105 for (int fid = 0; fid < 3; fid++) list[fid] = saved_os[fid];
4106 lookup_cache = list.end ();
4107}
4108
4109string_vector
4110octave_stream_list::do_get_info (int fid) const
4111{
4112 string_vector retval;
4113
4114 octave_stream os = do_lookup (fid);
4115
4116 if (os.is_valid ())
4117 {
4118 retval.resize (3);
4119
4120 retval(2) = oct_mach_info::float_format_as_string (os.float_format ());
4121 retval(1) = octave_stream::mode_as_string (os.mode ());
4122 retval(0) = os.name ();
4123 }
4124 else
4125 ::error ("invalid file id = %d", fid);
4126
4127 return retval;
4128}
4129
4130string_vector
4131octave_stream_list::do_get_info (const octave_value& fid) const
4132{
4133 string_vector retval;
4134
4135 int conv_err = 0;
4136
4137 int int_fid = convert_to_valid_int (fid, conv_err);
4138
4139 if (! conv_err)
4140 retval = do_get_info (int_fid);
4141 else
4142 ::error ("file id must be a file object or integer value");
4143
4144 return retval;
4145}
4146
4147std::string
4148octave_stream_list::do_list_open_files (void) const
4149{
4150 std::string retval;
4151
4152 std::ostringstream buf;
4153
4154 buf << "\n"
4155 << " number mode arch name\n"
4156 << " ------ ---- ---- ----\n";
4157
4158 for (ostrl_map::const_iterator p = list.begin (); p != list.end (); p++)
4159 {
4160 octave_stream os = p->second;
4161
4162 buf << " "
4163 << std::setiosflags (std::ios::right)
4164 << std::setw (4) << p->first << " "
4165 << std::setiosflags (std::ios::left)
4166 << std::setw (3)
4167 << octave_stream::mode_as_string (os.mode ())
4168 << " "
4169 << std::setw (9)
4170 << oct_mach_info::float_format_as_string (os.float_format ())
4171 << " "
4172 << os.name () << "\n";
4173 }
4174
4175 buf << "\n";
4176
4177 retval = buf.str ();
4178
4179 return retval;
4180}
4181
4182octave_value
4183octave_stream_list::do_open_file_numbers (void) const
4184{
4185 Matrix retval (1, list.size (), 0.0);
4186
4187 int num_open = 0;
4188
4189 for (ostrl_map::const_iterator p = list.begin (); p != list.end (); p++)
4190 {
4191 // Skip stdin, stdout, and stderr.
4192
4193 if (p->first > 2 && p->second)
4194 retval(0,num_open++) = p->first;
4195 }
4196
4197 retval.resize ((num_open > 0), num_open);
4198
4199 return retval;
4200}
4201
4202int
4203octave_stream_list::do_get_file_number (const octave_value& fid) const
4204{
4205 int retval = -1;
4206
4207 if (fid.is_string ())
4208 {
4209 std::string nm = fid.string_value ();
4210
4211 for (ostrl_map::const_iterator p = list.begin (); p != list.end (); p++)
4212 {
4213 // stdin (std::cin), stdout (std::cout), and stderr (std::cerr)
4214 // are unnamed.
4215
4216 if (p->first > 2)
4217 {
4218 octave_stream os = p->second;
4219
4220 if (os && os.name () == nm)
4221 {
4222 retval = p->first;
4223 break;
4224 }
4225 }
4226 }
4227 }
4228 else
4229 {
4230 int conv_err = 0;
4231
4232 int int_fid = convert_to_valid_int (fid, conv_err);
4233
4234 if (conv_err)
4235 ::error ("file id must be a file object, std::string, or integer value");
4236 else
4237 retval = int_fid;
4238 }
4239
4240 return retval;
4241}