GNU Octave  4.0.0
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
oct-stream.cc
Go to the documentation of this file.
1 /*
2 
3 Copyright (C) 1996-2015 John W. Eaton
4 
5 This file is part of Octave.
6 
7 Octave is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by the
9 Free Software Foundation; either version 3 of the License, or (at your
10 option) any later version.
11 
12 Octave is distributed in the hope that it will be useful, but WITHOUT
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 for more details.
16 
17 You should have received a copy of the GNU General Public License
18 along with Octave; see the file COPYING. If not, see
19 <http://www.gnu.org/licenses/>.
20 
21 */
22 
23 #ifdef HAVE_CONFIG_H
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 #include "byte-swap.h"
39 #include "lo-ieee.h"
40 #include "lo-mappers.h"
41 #include "lo-utils.h"
42 #include "oct-locbuf.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 
61 static int
62 convert_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))
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 
90 static int
91 get_size (double d, const std::string& who)
92 {
93  int retval = -1;
94 
95  if (! 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 
114 static void
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 
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  {
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  {
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 
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 
247 void
248 scanf_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 
273 static std::string
274 expand_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 
309 void
310 scanf_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 
412 int
413 scanf_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 
489 void
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 
504  std::cerr << "literal text\n";
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 
517 bool
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 '^':
533  break;
534 
535  default:
536  return false;
537  break;
538  }
539  }
540 
541  return true;
542  }
543  else
544  return false;
545 }
546 
547 bool
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 
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 = -1;
590  int prec = -1;
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 = -1;
640  prec = -1;
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 
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 
676 void
677 printf_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 
702 void
703 printf_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 = -1;
711  prec = -1;
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 = -2;
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  // nothing before the . means 0.
762  if (fw == -1)
763  fw = 0;
764 
765  // . followed by nothing is 0.
766  prec = 0;
767 
768  *buf << s[i++];
769 
770  if (i < n)
771  {
772  if (s[i] == '*')
773  {
774  prec = -2;
775  args++;
776  *buf << s[i++];
777  }
778  else
779  {
780  if (isdigit (s[i]))
781  {
782  int nn = 0;
783  std::string tmp = s.substr (i);
784  sscanf (tmp.c_str (), "%d%n", &prec, &nn);
785  }
786 
787  while (i < n && isdigit (s[i]))
788  *buf << s[i++];
789  }
790  }
791  }
792 
793  if (i < n)
794  {
795  // Accept and record modifier, but don't place it in the format
796  // item text. All integer conversions are handled as 64-bit
797  // integers.
798 
799  switch (s[i])
800  {
801  case 'h': case 'l': case 'L':
802  modifier = s[i++];
803  break;
804 
805  default:
806  break;
807  }
808  }
809 
810  if (i < n)
811  finish_conversion (s, i, args, flags, fw, prec, modifier, type, num_elts);
812  else
813  nconv = -1;
814 }
815 
816 void
817 printf_format_list::finish_conversion (const std::string& s, size_t& i,
818  int args, const std::string& flags,
819  int fw, int prec, char modifier,
820  char& type, octave_idx_type& num_elts)
821 {
822  switch (s[i])
823  {
824  case 'd': case 'i': case 'o': case 'x': case 'X':
825  case 'u': case 'c':
826  if (modifier == 'L')
827  {
828  nconv = -1;
829  break;
830  }
831  goto fini;
832 
833  case 'f': case 'e': case 'E': case 'g': case 'G':
834  if (modifier == 'h' || modifier == 'l')
835  {
836  nconv = -1;
837  break;
838  }
839  goto fini;
840 
841  case 's': case 'p': case '%':
842  if (modifier != '\0')
843  {
844  nconv = -1;
845  break;
846  }
847  goto fini;
848 
849  fini:
850 
851  type = s[i];
852 
853  *buf << s[i++];
854 
855  if (type != '%' || args != 0)
856  nconv++;
857 
858  if (type != '%')
859  args++;
860 
861  add_elt_to_list (args, flags, fw, prec, type, modifier, num_elts);
862 
863  break;
864 
865  default:
866  nconv = -1;
867  break;
868  }
869 }
870 
871 void
873 {
874  int n = list.length ();
875 
876  for (int i = 0; i < n; i++)
877  {
878  printf_format_elt *elt = list(i);
879 
880  std::cerr
881  << "args: " << elt->args << "\n"
882  << "flags: '" << elt->flags << "'\n"
883  << "width: " << elt->fw << "\n"
884  << "prec: " << elt->prec << "\n"
885  << "type: '" << elt->type << "'\n"
886  << "modifier: '" << elt->modifier << "'\n"
887  << "text: '" << undo_string_escapes (elt->text) << "'\n\n";
888  }
889 }
890 
891 void
892 octave_base_stream::error (const std::string& msg)
893 {
894  fail = true;
895  errmsg = msg;
896 }
897 
898 void
899 octave_base_stream::error (const std::string& who, const std::string& msg)
900 {
901  fail = true;
902  errmsg = who + ": " + msg;
903 }
904 
905 void
907 {
908  fail = false;
909  errmsg = "";
910 }
911 
912 void
914 {
915  std::istream *is = input_stream ();
916  std::ostream *os = output_stream ();
917 
918  if (is)
919  is->clear ();
920 
921  if (os)
922  os->clear ();
923 }
924 
925 // Functions that are defined for all input streams (input streams
926 // are those that define is).
927 
928 std::string
930  bool strip_newline, const std::string& who)
931 {
932  std::string retval;
933 
934  if (interactive && file_number () == 0)
935  {
936  ::error ("%s: unable to read from stdin while running interactively",
937  who.c_str ());
938 
939  return retval;
940  }
941 
942  err = false;
943 
944  std::istream *isp = input_stream ();
945 
946  if (isp)
947  {
948  std::istream& is = *isp;
949 
950  std::ostringstream buf;
951 
952  int c = 0;
953  int char_count = 0;
954 
955  if (max_len != 0)
956  {
957  while (is && (c = is.get ()) != EOF)
958  {
959  char_count++;
960 
961  // Handle CRLF, CR, or LF as line ending.
962 
963  if (c == '\r')
964  {
965  if (! strip_newline)
966  buf << static_cast<char> (c);
967 
968  c = is.get ();
969 
970  if (c != EOF)
971  {
972  if (c == '\n')
973  {
974  char_count++;
975 
976  if (! strip_newline)
977  buf << static_cast<char> (c);
978  }
979  else
980  is.putback (c);
981  }
982 
983  break;
984  }
985  else if (c == '\n')
986  {
987  if (! strip_newline)
988  buf << static_cast<char> (c);
989 
990  break;
991  }
992  else
993  buf << static_cast<char> (c);
994 
995  if (max_len > 0 && char_count == max_len)
996  break;
997  }
998  }
999 
1000  if (! is.eof () && char_count > 0)
1001  {
1002  // GAGME. Matlab seems to check for EOF even if the last
1003  // character in a file is a newline character. This is NOT
1004  // what the corresponding C-library functions do.
1005  int disgusting_compatibility_hack = is.get ();
1006  if (! is.eof ())
1007  is.putback (disgusting_compatibility_hack);
1008  }
1009 
1010  if (is.good () || (is.eof () && char_count > 0))
1011  retval = buf.str ();
1012  else
1013  {
1014  err = true;
1015 
1016  if (is.eof () && char_count == 0)
1017  error (who, "at end of file");
1018  else
1019  error (who, "read error");
1020  }
1021  }
1022  else
1023  {
1024  err = true;
1025  invalid_operation (who, "reading");
1026  }
1027 
1028  return retval;
1029 }
1030 
1031 std::string
1033  const std::string& who)
1034 {
1035  return do_gets (max_len, err, true, who);
1036 }
1037 
1038 std::string
1040  const std::string& who)
1041 {
1042  return do_gets (max_len, err, false, who);
1043 }
1044 
1045 off_t
1046 octave_base_stream::skipl (off_t num, bool& err, const std::string& who)
1047 {
1048  off_t cnt = -1;
1049 
1050  if (interactive && file_number () == 0)
1051  {
1052  ::error ("%s: unable to read from stdin while running interactively",
1053  who.c_str ());
1054 
1055  return count;
1056  }
1057 
1058  err = false;
1059 
1060  std::istream *isp = input_stream ();
1061 
1062  if (isp)
1063  {
1064  std::istream& is = *isp;
1065 
1066  int c = 0;
1067  int lastc = -1;
1068  cnt = 0;
1069 
1070  while (is && (c = is.get ()) != EOF)
1071  {
1072  // Handle CRLF, CR, or LF as line ending.
1073 
1074  if (c == '\r' || (c == '\n' && lastc != '\r'))
1075  {
1076  if (++cnt == num)
1077  break;
1078  }
1079 
1080  lastc = c;
1081  }
1082 
1083  // Maybe eat the following \n if \r was just met.
1084  if (c == '\r' && is.peek () == '\n')
1085  is.get ();
1086 
1087  if (is.bad ())
1088  {
1089  err = true;
1090  error (who, "read error");
1091  }
1092 
1093  if (err)
1094  cnt = -1;
1095  }
1096  else
1097  {
1098  err = true;
1099  invalid_operation (who, "reading");
1100  }
1101 
1102  return cnt;
1103 }
1104 
1105 #define OCTAVE_SCAN(is, fmt, arg) octave_scan (is, fmt, arg)
1106 
1107 template <class T>
1108 std::istream&
1109 octave_scan_1 (std::istream& is, const scanf_format_elt& fmt, T* valptr)
1110 {
1111  T& ref = *valptr;
1112 
1113  switch (fmt.type)
1114  {
1115  case 'o':
1116  is >> std::oct >> ref >> std::dec;
1117  break;
1118 
1119  case 'x':
1120  is >> std::hex >> ref >> std::dec;
1121  break;
1122 
1123  case 'i':
1124  {
1125  int c1 = EOF;
1126 
1127  while (is && (c1 = is.get ()) != EOF && isspace (c1))
1128  /* skip whitespace */;
1129 
1130  if (c1 != EOF)
1131  {
1132  if (c1 == '0')
1133  {
1134  int c2 = is.peek ();
1135 
1136  if (c2 == 'x' || c2 == 'X')
1137  {
1138  is.ignore ();
1139  if (std::isxdigit (is.peek ()))
1140  is >> std::hex >> ref >> std::dec;
1141  else
1142  ref = 0;
1143  }
1144  else
1145  {
1146  if (c2 == '0' || c2 == '1' || c2 == '2'
1147  || c2 == '3' || c2 == '4' || c2 == '5'
1148  || c2 == '6' || c2 == '7')
1149  is >> std::oct >> ref >> std::dec;
1150  else
1151  ref = 0;
1152  }
1153  }
1154  else
1155  {
1156  is.putback (c1);
1157 
1158  is >> ref;
1159  }
1160  }
1161  }
1162  break;
1163 
1164  default:
1165  is >> ref;
1166  break;
1167  }
1168 
1169  return is;
1170 }
1171 
1172 template <class T>
1173 std::istream&
1174 octave_scan (std::istream& is, const scanf_format_elt& fmt, T* valptr)
1175 {
1176  if (fmt.width)
1177  {
1178  // Limit input to fmt.width characters by reading into a
1179  // temporary stringstream buffer.
1180 
1181  std::string tmp;
1182 
1183  is.width (fmt.width);
1184  is >> tmp;
1185 
1186  std::istringstream ss (tmp);
1187 
1188  octave_scan_1 (ss, fmt, valptr);
1189  }
1190  else
1191  octave_scan_1 (is, fmt, valptr);
1192 
1193  return is;
1194 }
1195 
1196 // Note that this specialization is only used for reading characters, not
1197 // character strings. See BEGIN_S_CONVERSION for details.
1198 
1199 template<>
1200 std::istream&
1201 octave_scan<> (std::istream& is, const scanf_format_elt& /* fmt */,
1202  char* valptr)
1203 {
1204  return is >> valptr;
1205 }
1206 
1207 template<>
1208 std::istream&
1209 octave_scan<> (std::istream& is, const scanf_format_elt& fmt, double* valptr)
1210 {
1211  double& ref = *valptr;
1212 
1213  switch (fmt.type)
1214  {
1215  case 'e':
1216  case 'f':
1217  case 'g':
1218  {
1219  int c1 = EOF;
1220 
1221  while (is && (c1 = is.get ()) != EOF && isspace (c1))
1222  /* skip whitespace */;
1223 
1224  if (c1 != EOF)
1225  {
1226  is.putback (c1);
1227 
1228  ref = octave_read_value<double> (is);
1229  }
1230  }
1231  break;
1232 
1233  default:
1234  panic_impossible ();
1235  break;
1236  }
1237 
1238  return is;
1239 }
1240 
1241 template <class T>
1242 void
1243 do_scanf_conv (std::istream& is, const scanf_format_elt& fmt,
1244  T valptr, Matrix& mval, double *data, octave_idx_type& idx,
1245  octave_idx_type& conversion_count, octave_idx_type nr,
1246  octave_idx_type max_size, bool discard)
1247 {
1248  OCTAVE_SCAN (is, fmt, valptr);
1249 
1250  if (is)
1251  {
1252  if (idx == max_size && ! discard)
1253  {
1254  max_size *= 2;
1255 
1256  if (nr > 0)
1257  mval.resize (nr, max_size / nr, 0.0);
1258  else
1259  mval.resize (max_size, 1, 0.0);
1260 
1261  data = mval.fortran_vec ();
1262  }
1263 
1264  if (! discard)
1265  {
1266  conversion_count++;
1267  data[idx++] = *(valptr);
1268  }
1269  }
1270 }
1271 
1272 template void
1273 do_scanf_conv (std::istream&, const scanf_format_elt&, double*,
1274  Matrix&, double*, octave_idx_type&, octave_idx_type&,
1276 
1277 #define DO_WHITESPACE_CONVERSION() \
1278  do \
1279  { \
1280  int c = EOF; \
1281  \
1282  while (is && (c = is.get ()) != EOF && isspace (c)) \
1283  /* skip whitespace */; \
1284  \
1285  if (c != EOF) \
1286  is.putback (c); \
1287  } \
1288  while (0)
1289 
1290 #define DO_LITERAL_CONVERSION() \
1291  do \
1292  { \
1293  int c = EOF; \
1294  \
1295  int n = strlen (fmt); \
1296  int i = 0; \
1297  \
1298  while (i < n && is && (c = is.get ()) != EOF) \
1299  { \
1300  if (c == static_cast<unsigned char> (fmt[i])) \
1301  { \
1302  i++; \
1303  continue; \
1304  } \
1305  else \
1306  { \
1307  is.putback (c); \
1308  break; \
1309  } \
1310  } \
1311  \
1312  if (i != n) \
1313  is.setstate (std::ios::failbit); \
1314  } \
1315  while (0)
1316 
1317 #define DO_PCT_CONVERSION() \
1318  do \
1319  { \
1320  int c = is.get (); \
1321  \
1322  if (c != EOF) \
1323  { \
1324  if (c != '%') \
1325  { \
1326  is.putback (c); \
1327  is.setstate (std::ios::failbit); \
1328  } \
1329  } \
1330  else \
1331  is.setstate (std::ios::failbit); \
1332  } \
1333  while (0)
1334 
1335 #define BEGIN_C_CONVERSION() \
1336  is.unsetf (std::ios::skipws); \
1337  \
1338  int width = elt->width ? elt->width : 1; \
1339  \
1340  std::string tmp (width, '\0'); \
1341  \
1342  int c = EOF; \
1343  int n = 0; \
1344  \
1345  while (is && n < width && (c = is.get ()) != EOF) \
1346  tmp[n++] = static_cast<char> (c); \
1347  \
1348  if (n > 0 && c == EOF) \
1349  is.clear (); \
1350  \
1351  tmp.resize (n)
1352 
1353 // For a '%s' format, skip initial whitespace and then read until the
1354 // next whitespace character or until WIDTH characters have been read.
1355 #define BEGIN_S_CONVERSION() \
1356  int width = elt->width; \
1357  \
1358  std::string tmp; \
1359  \
1360  do \
1361  { \
1362  if (width) \
1363  { \
1364  tmp = std::string (width, '\0'); \
1365  \
1366  int c = EOF; \
1367  \
1368  int n = 0; \
1369  \
1370  while (is && (c = is.get ()) != EOF) \
1371  { \
1372  if (! isspace (c)) \
1373  { \
1374  tmp[n++] = static_cast<char> (c); \
1375  break; \
1376  } \
1377  } \
1378  \
1379  while (is && n < width && (c = is.get ()) != EOF) \
1380  { \
1381  if (isspace (c)) \
1382  { \
1383  is.putback (c); \
1384  break; \
1385  } \
1386  else \
1387  tmp[n++] = static_cast<char> (c); \
1388  } \
1389  \
1390  if (n > 0 && c == EOF) \
1391  is.clear (); \
1392  \
1393  tmp.resize (n); \
1394  } \
1395  else \
1396  { \
1397  is >> std::ws >> tmp; \
1398  } \
1399  } \
1400  while (0)
1401 
1402 // This format must match a nonempty sequence of characters.
1403 #define BEGIN_CHAR_CLASS_CONVERSION() \
1404  int width = elt->width; \
1405  \
1406  std::string tmp; \
1407  \
1408  do \
1409  { \
1410  if (! width) \
1411  width = std::numeric_limits<int>::max (); \
1412  \
1413  std::ostringstream buf; \
1414  \
1415  std::string char_class = elt->char_class; \
1416  \
1417  int c = EOF; \
1418  \
1419  if (elt->type == '[') \
1420  { \
1421  int chars_read = 0; \
1422  while (is && chars_read++ < width && (c = is.get ()) != EOF \
1423  && char_class.find (c) != std::string::npos) \
1424  buf << static_cast<char> (c); \
1425  } \
1426  else \
1427  { \
1428  int chars_read = 0; \
1429  while (is && chars_read++ < width && (c = is.get ()) != EOF \
1430  && char_class.find (c) == std::string::npos) \
1431  buf << static_cast<char> (c); \
1432  } \
1433  \
1434  if (width == std::numeric_limits<int>::max () && c != EOF) \
1435  is.putback (c); \
1436  \
1437  tmp = buf.str (); \
1438  \
1439  if (tmp.empty ()) \
1440  is.setstate (std::ios::failbit); \
1441  else if (c == EOF) \
1442  is.clear (); \
1443  \
1444  } \
1445  while (0)
1446 
1447 #define FINISH_CHARACTER_CONVERSION() \
1448  do \
1449  { \
1450  width = tmp.length (); \
1451  \
1452  if (is) \
1453  { \
1454  int i = 0; \
1455  \
1456  if (! discard) \
1457  { \
1458  conversion_count++; \
1459  \
1460  while (i < width) \
1461  { \
1462  if (data_index == max_size) \
1463  { \
1464  max_size *= 2; \
1465  \
1466  if (all_char_conv) \
1467  { \
1468  if (one_elt_size_spec) \
1469  mval.resize (1, max_size, 0.0); \
1470  else if (nr > 0) \
1471  mval.resize (nr, max_size / nr, 0.0); \
1472  else \
1473  panic_impossible (); \
1474  } \
1475  else if (nr > 0) \
1476  mval.resize (nr, max_size / nr, 0.0); \
1477  else \
1478  mval.resize (max_size, 1, 0.0); \
1479  \
1480  data = mval.fortran_vec (); \
1481  } \
1482  \
1483  data[data_index++] = tmp[i++]; \
1484  } \
1485  } \
1486  } \
1487  } \
1488  while (0)
1489 
1493  bool one_elt_size_spec,
1494  octave_idx_type& conversion_count,
1495  const std::string& who)
1496 {
1497  octave_value retval = Matrix ();
1498 
1499  if (interactive && file_number () == 0)
1500  {
1501  ::error ("%s: unable to read from stdin while running interactively",
1502  who.c_str ());
1503 
1504  return retval;
1505  }
1506 
1507  conversion_count = 0;
1508 
1509  octave_idx_type nconv = fmt_list.num_conversions ();
1510 
1511  octave_idx_type data_index = 0;
1512 
1513  if (nr == 0 || nc == 0)
1514  {
1515  if (one_elt_size_spec)
1516  nc = 0;
1517 
1518  return Matrix (nr, nc, 0.0);
1519  }
1520 
1521  std::istream *isp = input_stream ();
1522 
1523  bool all_char_conv = fmt_list.all_character_conversions ();
1524 
1525  Matrix mval;
1526  double *data = 0;
1527  octave_idx_type max_size = 0;
1528  octave_idx_type max_conv = 0;
1529 
1530  octave_idx_type final_nr = 0;
1531  octave_idx_type final_nc = 0;
1532 
1533  if (all_char_conv)
1534  {
1535  // Any of these could be resized later (if we have %s
1536  // conversions, we may read more than one element for each
1537  // conversion).
1538 
1539  if (one_elt_size_spec)
1540  {
1541  max_size = 512;
1542  mval.resize (1, max_size, 0.0);
1543 
1544  if (nr > 0)
1545  max_conv = nr;
1546  }
1547  else if (nr > 0)
1548  {
1549  if (nc > 0)
1550  {
1551  mval.resize (nr, nc, 0.0);
1552  max_size = max_conv = nr * nc;
1553  }
1554  else
1555  {
1556  mval.resize (nr, 32, 0.0);
1557  max_size = nr * 32;
1558  }
1559  }
1560  else
1561  panic_impossible ();
1562  }
1563  else if (nr > 0)
1564  {
1565  if (nc > 0)
1566  {
1567  // Will not resize later.
1568  mval.resize (nr, nc, 0.0);
1569  max_size = nr * nc;
1570  max_conv = max_size;
1571  }
1572  else
1573  {
1574  // Maybe resize later.
1575  mval.resize (nr, 32, 0.0);
1576  max_size = nr * 32;
1577  }
1578  }
1579  else
1580  {
1581  // Maybe resize later.
1582  mval.resize (32, 1, 0.0);
1583  max_size = 32;
1584  }
1585 
1586  data = mval.fortran_vec ();
1587 
1588  if (isp)
1589  {
1590  std::istream& is = *isp;
1591 
1592  const scanf_format_elt *elt = fmt_list.first ();
1593 
1594  std::ios::fmtflags flags = is.flags ();
1595 
1596  octave_idx_type trips = 0;
1597 
1598  octave_idx_type num_fmt_elts = fmt_list.length ();
1599 
1600  for (;;)
1601  {
1602  octave_quit ();
1603 
1604  if (elt)
1605  {
1608  || elt->type == '%')
1609  && max_conv > 0 && conversion_count == max_conv)
1610  {
1611  if (all_char_conv && one_elt_size_spec)
1612  {
1613  final_nr = 1;
1614  final_nc = data_index;
1615  }
1616  else
1617  {
1618  final_nr = nr;
1619  final_nc = (data_index - 1) / nr + 1;
1620  }
1621 
1622  break;
1623  }
1624  else if (data_index == max_size)
1625  {
1626  max_size *= 2;
1627 
1628  if (all_char_conv)
1629  {
1630  if (one_elt_size_spec)
1631  mval.resize (1, max_size, 0.0);
1632  else if (nr > 0)
1633  mval.resize (nr, max_size / nr, 0.0);
1634  else
1635  panic_impossible ();
1636  }
1637  else if (nr > 0)
1638  mval.resize (nr, max_size / nr, 0.0);
1639  else
1640  mval.resize (max_size, 1, 0.0);
1641 
1642  data = mval.fortran_vec ();
1643  }
1644 
1645  const char *fmt = elt->text;
1646 
1647  bool discard = elt->discard;
1648 
1649  switch (elt->type)
1650  {
1653  break;
1654 
1657  break;
1658 
1659  case '%':
1660  DO_PCT_CONVERSION ();
1661  break;
1662 
1663  case 'd': case 'i':
1664  {
1665  switch (elt->modifier)
1666  {
1667  case 'h':
1668  {
1669  short int tmp;
1670  do_scanf_conv (is, *elt, &tmp, mval, data,
1671  data_index, conversion_count,
1672  nr, max_size, discard);
1673  }
1674  break;
1675 
1676  case 'l':
1677  {
1678  long int tmp;
1679  do_scanf_conv (is, *elt, &tmp, mval, data,
1680  data_index, conversion_count,
1681  nr, max_size, discard);
1682  }
1683  break;
1684 
1685  default:
1686  {
1687  int tmp;
1688  do_scanf_conv (is, *elt, &tmp, mval, data,
1689  data_index, conversion_count,
1690  nr, max_size, discard);
1691  }
1692  break;
1693  }
1694  }
1695  break;
1696 
1697  case 'o': case 'u': case 'x':
1698  {
1699  switch (elt->modifier)
1700  {
1701  case 'h':
1702  {
1703  unsigned short int tmp;
1704  do_scanf_conv (is, *elt, &tmp, mval, data,
1705  data_index, conversion_count,
1706  nr, max_size, discard);
1707  }
1708  break;
1709 
1710  case 'l':
1711  {
1712  unsigned long int tmp;
1713  do_scanf_conv (is, *elt, &tmp, mval, data,
1714  data_index, conversion_count,
1715  nr, max_size, discard);
1716  }
1717  break;
1718 
1719  default:
1720  {
1721  unsigned int tmp;
1722  do_scanf_conv (is, *elt, &tmp, mval, data,
1723  data_index, conversion_count,
1724  nr, max_size, discard);
1725  }
1726  break;
1727  }
1728  }
1729  break;
1730 
1731  case 'e': case 'f': case 'g':
1732  {
1733  double tmp;
1734 
1735  do_scanf_conv (is, *elt, &tmp, mval, data,
1736  data_index, conversion_count,
1737  nr, max_size, discard);
1738  }
1739  break;
1740 
1741  case 'c':
1742  {
1743  BEGIN_C_CONVERSION ();
1744 
1746 
1747  is.setf (flags);
1748  }
1749  break;
1750 
1751  case 's':
1752  {
1753  BEGIN_S_CONVERSION ();
1754 
1756  }
1757  break;
1758 
1759  case '[': case '^':
1760  {
1762 
1764  }
1765  break;
1766 
1767  case 'p':
1768  error ("%s: unsupported format specifier", who.c_str ());
1769  break;
1770 
1771  default:
1772  error ("%s: internal format error", who.c_str ());
1773  break;
1774  }
1775 
1776  if (! ok ())
1777  {
1778  break;
1779  }
1780  else if (! is)
1781  {
1782  if (all_char_conv)
1783  {
1784  if (one_elt_size_spec)
1785  {
1786  final_nr = 1;
1787  final_nc = data_index;
1788  }
1789  else if (data_index > nr)
1790  {
1791  final_nr = nr;
1792  final_nc = (data_index - 1) / nr + 1;
1793  }
1794  else
1795  {
1796  final_nr = data_index;
1797  final_nc = 1;
1798  }
1799  }
1800  else if (nr > 0)
1801  {
1802  if (data_index > nr)
1803  {
1804  final_nr = nr;
1805  final_nc = (data_index - 1) / nr + 1;
1806  }
1807  else
1808  {
1809  final_nr = data_index;
1810  final_nc = 1;
1811  }
1812  }
1813  else
1814  {
1815  final_nr = data_index;
1816  final_nc = 1;
1817  }
1818 
1819  // If it looks like we have a matching failure, then
1820  // reset the failbit in the stream state.
1821 
1822  if (is.rdstate () & std::ios::failbit)
1823  is.clear (is.rdstate () & (~std::ios::failbit));
1824 
1825  // FIXME: is this the right thing to do?
1826 
1827  if (interactive && ! forced_interactive && name () == "stdin")
1828  {
1829  is.clear ();
1830 
1831  // Skip to end of line.
1832 
1833  bool err;
1834  do_gets (-1, err, false, who);
1835  }
1836 
1837  break;
1838  }
1839  }
1840  else
1841  {
1842  error ("%s: internal format error", who.c_str ());
1843  break;
1844  }
1845 
1846  if (nconv == 0 && ++trips == num_fmt_elts)
1847  {
1848  if (all_char_conv && one_elt_size_spec)
1849  {
1850  final_nr = 1;
1851  final_nc = data_index;
1852  }
1853  else
1854  {
1855  final_nr = nr;
1856  final_nc = (data_index - 1) / nr + 1;
1857  }
1858 
1859  break;
1860  }
1861  else
1862  elt = fmt_list.next (nconv > 0);
1863  }
1864  }
1865 
1866  if (ok ())
1867  {
1868  mval.resize (final_nr, final_nc, 0.0);
1869 
1870  retval = mval;
1871 
1872  if (all_char_conv)
1873  retval = retval.convert_to_str (false, true);
1874  }
1875 
1876  return retval;
1877 }
1878 
1880 octave_base_stream::scanf (const std::string& fmt, const Array<double>& size,
1881  octave_idx_type& conversion_count,
1882  const std::string& who)
1883 {
1884  octave_value retval = Matrix ();
1885 
1886  conversion_count = 0;
1887 
1888  std::istream *isp = input_stream ();
1889 
1890  if (isp)
1891  {
1892  scanf_format_list fmt_list (fmt);
1893 
1894  if (fmt_list.num_conversions () == -1)
1895  ::error ("%s: invalid format specified", who.c_str ());
1896  else
1897  {
1898  octave_idx_type nr = -1;
1899  octave_idx_type nc = -1;
1900 
1901  bool one_elt_size_spec;
1902 
1903  get_size (size, nr, nc, one_elt_size_spec, who);
1904 
1905  if (! error_state)
1906  retval = do_scanf (fmt_list, nr, nc, one_elt_size_spec,
1907  conversion_count, who);
1908  }
1909  }
1910  else
1911  invalid_operation (who, "reading");
1912 
1913  return retval;
1914 }
1915 
1916 bool
1918  octave_value& retval, const std::string& who)
1919 {
1920  bool quit = false;
1921 
1922  std::istream *isp = input_stream ();
1923 
1924  if (isp)
1925  {
1926  std::istream& is = *isp;
1927 
1928  std::ios::fmtflags flags = is.flags ();
1929 
1930  if (elt)
1931  {
1932  const char *fmt = elt->text;
1933 
1934  bool discard = elt->discard;
1935 
1936  switch (elt->type)
1937  {
1940  break;
1941 
1944  break;
1945 
1946  case '%':
1947  {
1948  DO_PCT_CONVERSION ();
1949 
1950  if (! is)
1951  quit = true;
1952 
1953  }
1954  break;
1955 
1956  case 'd': case 'i':
1957  {
1958  int tmp;
1959 
1960  if (OCTAVE_SCAN (is, *elt, &tmp))
1961  {
1962  if (! discard)
1963  retval = tmp;
1964  }
1965  else
1966  quit = true;
1967  }
1968  break;
1969 
1970  case 'o': case 'u': case 'x':
1971  {
1972  long int tmp;
1973 
1974  if (OCTAVE_SCAN (is, *elt, &tmp))
1975  {
1976  if (! discard)
1977  retval = tmp;
1978  }
1979  else
1980  quit = true;
1981  }
1982  break;
1983 
1984  case 'e': case 'f': case 'g':
1985  {
1986  double tmp;
1987 
1988  if (OCTAVE_SCAN (is, *elt, &tmp))
1989  {
1990  if (! discard)
1991  retval = tmp;
1992  }
1993  else
1994  quit = true;
1995  }
1996  break;
1997 
1998  case 'c':
1999  {
2000  BEGIN_C_CONVERSION ();
2001 
2002  if (! discard)
2003  retval = tmp;
2004 
2005  if (! is)
2006  quit = true;
2007 
2008  is.setf (flags);
2009  }
2010  break;
2011 
2012  case 's':
2013  {
2014  BEGIN_S_CONVERSION ();
2015 
2016  if (! discard)
2017  retval = tmp;
2018 
2019  if (! is)
2020  quit = true;
2021  }
2022  break;
2023 
2024  case '[': case '^':
2025  {
2027 
2028  if (! discard)
2029  retval = tmp;
2030 
2031  if (! is)
2032  quit = true;
2033  }
2034  break;
2035 
2036  case 'p':
2037  error ("%s: unsupported format specifier", who.c_str ());
2038  break;
2039 
2040  default:
2041  error ("%s: internal format error", who.c_str ());
2042  break;
2043  }
2044  }
2045 
2046  if (ok () && is.fail ())
2047  {
2048  error ("%s: read error", who.c_str ());
2049 
2050  // FIXME: is this the right thing to do?
2051 
2052  if (interactive && ! forced_interactive && name () == "stdin")
2053  {
2054  // Skip to end of line.
2055 
2056  bool err;
2057  do_gets (-1, err, false, who);
2058  }
2059  }
2060  }
2061 
2062  return quit;
2063 }
2064 
2066 octave_base_stream::oscanf (const std::string& fmt, const std::string& who)
2067 {
2068  octave_value_list retval;
2069 
2070  std::istream *isp = input_stream ();
2071 
2072  if (isp)
2073  {
2074  std::istream& is = *isp;
2075 
2076  scanf_format_list fmt_list (fmt);
2077 
2078  octave_idx_type nconv = fmt_list.num_conversions ();
2079 
2080  if (nconv == -1)
2081  ::error ("%s: invalid format specified", who.c_str ());
2082  else
2083  {
2084  is.clear ();
2085 
2086  octave_idx_type len = fmt_list.length ();
2087 
2088  retval.resize (nconv+2, Matrix ());
2089 
2090  const scanf_format_elt *elt = fmt_list.first ();
2091 
2092  int num_values = 0;
2093 
2094  bool quit = false;
2095 
2096  for (octave_idx_type i = 0; i < len; i++)
2097  {
2098  octave_value tmp;
2099 
2100  quit = do_oscanf (elt, tmp, who);
2101 
2102  if (quit)
2103  break;
2104  else
2105  {
2106  if (tmp.is_defined ())
2107  retval(num_values++) = tmp;
2108 
2109  if (! ok ())
2110  break;
2111 
2112  elt = fmt_list.next (nconv > 0);
2113  }
2114  }
2115 
2116  retval(nconv) = num_values;
2117 
2118  int err_num;
2119  retval(nconv+1) = error (false, err_num);
2120 
2121  if (! quit)
2122  {
2123  // Pick up any trailing stuff.
2124  if (ok () && len > nconv)
2125  {
2126  octave_value tmp;
2127 
2128  elt = fmt_list.next ();
2129 
2130  do_oscanf (elt, tmp, who);
2131  }
2132  }
2133  }
2134  }
2135  else
2136  invalid_operation (who, "reading");
2137 
2138  return retval;
2139 }
2140 
2141 // Functions that are defined for all output streams (output streams
2142 // are those that define os).
2143 
2144 int
2146 {
2147  int retval = -1;
2148 
2149  std::ostream *os = output_stream ();
2150 
2151  if (os)
2152  {
2153  os->flush ();
2154 
2155  if (os->good ())
2156  retval = 0;
2157  }
2158  else
2159  invalid_operation ("fflush", "writing");
2160 
2161  return retval;
2162 }
2163 
2164 class
2166 {
2167 public:
2168 
2169  enum state { ok, conversion_error };
2170 
2171  printf_value_cache (const octave_value_list& args, const std::string& who)
2172  : values (args), val_idx (0), elt_idx (0),
2173  n_vals (values.length ()), n_elts (0), have_data (false),
2174  curr_state (ok)
2175  {
2176  for (octave_idx_type i = 0; i < values.length (); i++)
2177  {
2178  octave_value val = values(i);
2179 
2180  if (val.is_map () || val.is_cell () || val.is_object ())
2181  {
2182  gripe_wrong_type_arg (who, val);
2183  break;
2184  }
2185  }
2186  }
2187 
2189 
2190  // Get the current value as a double and advance the internal pointer.
2191  octave_value get_next_value (char type = 0);
2192 
2193  // Get the current value as an int and advance the internal pointer.
2194  int int_value (void);
2195 
2196  operator bool () const { return (curr_state == ok); }
2197 
2198  bool exhausted (void) { return (val_idx >= n_vals); }
2199 
2200 private:
2201 
2203  int val_idx;
2204  int elt_idx;
2205  int n_vals;
2206  int n_elts;
2210 
2211  // Must create value cache with values!
2212 
2213  printf_value_cache (void);
2214 
2215  // No copying!
2216 
2218 
2219  printf_value_cache& operator = (const printf_value_cache&);
2220 };
2221 
2224 {
2225  octave_value retval;
2226 
2227  if (exhausted ())
2229 
2230  while (! exhausted ())
2231  {
2232  if (! have_data)
2233  {
2234  curr_val = values (val_idx);
2235 
2236  // Force string conversion here for compatibility.
2237 
2238  if (! error_state)
2239  {
2240  elt_idx = 0;
2241  n_elts = curr_val.numel ();
2242  have_data = true;
2243  }
2244  else
2245  {
2247  break;
2248  }
2249  }
2250 
2251  if (elt_idx < n_elts)
2252  {
2253  if (type == 's')
2254  {
2255  if (curr_val.is_string ())
2256  {
2257  std::string sval = curr_val.string_value ();
2258 
2259  retval = sval.substr (elt_idx);
2260 
2261  // We've consumed the rest of the value.
2262  elt_idx = n_elts;
2263  }
2264  else
2265  {
2266  // Convert to character string while values are
2267  // integers in the range [0 : char max]
2268 
2269  const NDArray val = curr_val.array_value ();
2270 
2271  octave_idx_type idx = elt_idx;
2272 
2273  for (; idx < n_elts; idx++)
2274  {
2275  double dval = val(idx);
2276 
2277  if (D_NINT (dval) != dval || dval < 0 || dval > 255)
2278  break;
2279  }
2280 
2281  octave_idx_type n = idx - elt_idx;
2282 
2283  if (n > 0)
2284  {
2285  std::string sval (n, '\0');
2286 
2287  for (octave_idx_type i = 0; i < n; i++)
2288  sval[i] = val(elt_idx++);
2289 
2290  retval = sval;
2291  }
2292  else
2293  retval = curr_val.fast_elem_extract (elt_idx++);
2294  }
2295  }
2296  else
2297  {
2298  retval = curr_val.fast_elem_extract (elt_idx++);
2299 
2300  if (type == 'c' && ! retval.is_string ())
2301  {
2302  double dval = retval.double_value ();
2303 
2304  if (D_NINT (dval) == dval && dval >= 0 && dval < 256)
2305  retval = static_cast<char> (dval);
2306  }
2307  }
2308 
2309  if (elt_idx >= n_elts)
2310  {
2311  elt_idx = 0;
2312  val_idx++;
2313  have_data = false;
2314  }
2315 
2316  break;
2317  }
2318  else
2319  {
2320  val_idx++;
2321  have_data = false;
2322 
2323  if (n_elts == 0)
2324  {
2325  if (elt_idx == 0 && (type == 's' || type == 'c'))
2326  {
2327  retval = "";
2328  break;
2329  }
2330 
2331  if (exhausted ())
2333  }
2334  }
2335  }
2336 
2337  return retval;
2338 }
2339 
2340 int
2342 {
2343  int retval = 0;
2344 
2345  octave_value val = get_next_value ();
2346 
2347  if (! error_state)
2348  {
2349  double dval = val.double_value (true);
2350 
2351  if (! error_state)
2352  {
2353  if (D_NINT (dval) == dval)
2354  retval = NINT (dval);
2355  else
2357  }
2358  }
2359 
2360  return retval;
2361 }
2362 
2363 // Ugh again and again.
2364 
2365 template <class T>
2366 int
2367 do_printf_conv (std::ostream& os, const char *fmt, int nsa, int sa_1,
2368  int sa_2, T arg, const std::string& who)
2369 {
2370  int retval = 0;
2371 
2372  switch (nsa)
2373  {
2374  case 2:
2375  retval = octave_format (os, fmt, sa_1, sa_2, arg);
2376  break;
2377 
2378  case 1:
2379  retval = octave_format (os, fmt, sa_1, arg);
2380  break;
2381 
2382  case 0:
2383  retval = octave_format (os, fmt, arg);
2384  break;
2385 
2386  default:
2387  ::error ("%s: internal error handling format", who.c_str ());
2388  break;
2389  }
2390 
2391  return retval;
2392 }
2393 
2394 static size_t
2395 do_printf_string (std::ostream& os, const printf_format_elt *elt,
2396  int nsa, int sa_1, int sa_2, const std::string& arg,
2397  const std::string& who)
2398 {
2399  size_t retval = 0;
2400 
2401  if (nsa > 2)
2402  {
2403  ::error ("%s: internal error handling format", who.c_str ());
2404  return retval;
2405  }
2406 
2407  std::string flags = elt->flags;
2408 
2409  bool left = flags.find ('-') != std::string::npos;
2410 
2411  size_t len = arg.length ();
2412 
2413  size_t fw = nsa > 0 ? sa_1 : (elt->fw == -1 ? len : elt->fw);
2414  size_t prec = nsa > 1 ? sa_2 : (elt->prec == -1 ? len : elt->prec);
2415 
2416  os << std::setw (fw)
2417  << (left ? std::left : std::right)
2418  << (prec < len ? arg.substr (0, prec) : arg);
2419 
2420  return len > fw ? len : fw;
2421 }
2422 
2423 static bool
2425 {
2426  octave_value ov_isnan = val.isnan ();
2427  octave_value ov_isinf = val.isinf ();
2428 
2429  return (ov_isnan.is_true () || ov_isinf.is_true ());
2430 }
2431 
2432 static bool
2434 {
2435  uint64_t limit = std::numeric_limits<int64_t>::max ();
2436 
2437  if (val.is_string ())
2438  return false;
2439  else if (val.is_integer_type ())
2440  {
2441  if (val.is_uint64_type ())
2442  {
2443  octave_uint64 ival = val.uint64_scalar_value ();
2444 
2445  if (ival.value () <= limit)
2446  return true;
2447  }
2448  else
2449  return true;
2450  }
2451  else
2452  {
2453  double dval = val.double_value (true);
2454 
2455  if (dval == xround (dval) && dval <= limit)
2456  return true;
2457  }
2458 
2459  return false;
2460 }
2461 
2462 static bool
2464 {
2465  if (val.is_string ())
2466  return false;
2467  else if (val.is_integer_type ())
2468  {
2469  // Easier than dispatching here...
2470 
2471  octave_value ov_is_ge_zero
2473 
2474  return ov_is_ge_zero.is_true ();
2475  }
2476  else
2477  {
2478  double dval = val.double_value (true);
2479 
2480  uint64_t limit = std::numeric_limits<uint64_t>::max ();
2481 
2482  if (dval == xround (dval) && dval >= 0 && dval <= limit)
2483  return true;
2484  }
2485 
2486  return false;
2487 }
2488 
2489 static std::string
2491 {
2492  std::string tfmt = elt->text;
2493 
2494  tfmt.replace (tfmt.rfind (elt->type), 1, "g");
2495 
2496  return tfmt;
2497 }
2498 
2499 int
2501  const printf_format_elt *elt,
2502  int nsa, int sa_1, int sa_2,
2503  const octave_value& val,
2504  const std::string& who)
2505 {
2506  int retval = 0;
2507 
2508  const char *fmt = elt->text;
2509 
2510  if (is_nan_or_inf (val))
2511  {
2512  double dval = val.double_value ();
2513 
2514  std::string tfmt = fmt;
2515  std::string::size_type i1, i2;
2516 
2517  tfmt.replace ((i1 = tfmt.rfind (elt->type)),
2518  1, 1, 's');
2519 
2520  if ((i2 = tfmt.rfind ('.')) != std::string::npos
2521  && i2 < i1)
2522  {
2523  tfmt.erase (i2, i1-i2);
2524  if (elt->prec == -2)
2525  nsa--;
2526  }
2527 
2528  const char *tval;
2529  if (lo_ieee_isinf (dval))
2530  {
2531  if (elt->flags.find ('+') != std::string::npos)
2532  tval = (dval < 0 ? "-Inf" : "+Inf");
2533  else
2534  tval = (dval < 0 ? "-Inf" : "Inf");
2535  }
2536  else
2537  {
2538  if (elt->flags.find ('+') != std::string::npos)
2539  tval = (lo_ieee_is_NA (dval) ? "+NA" : "+NaN");
2540  else
2541  tval = (lo_ieee_is_NA (dval) ? "NA" : "NaN");
2542  }
2543 
2544  retval += do_printf_conv (os, tfmt.c_str (), nsa, sa_1, sa_2, tval, who);
2545  }
2546  else
2547  {
2548  static std::string llmod
2549  = sizeof (long) == sizeof (int64_t) ? "l" : "ll";
2550 
2551  char type = elt->type;
2552 
2553  switch (type)
2554  {
2555  case 'd': case 'i': case 'c':
2556  if (ok_for_signed_int_conv (val))
2557  {
2558  octave_int64 tval = val.int64_scalar_value ();
2559 
2560  // Insert "long" modifier.
2561  std::string tfmt = fmt;
2562  tfmt.replace (tfmt.rfind (type), 1, llmod + type);
2563 
2564  retval += do_printf_conv (os, tfmt.c_str (), nsa, sa_1, sa_2,
2565  tval.value (), who);
2566  }
2567  else
2568  {
2569  std::string tfmt = switch_to_g_format (elt);
2570 
2571  double dval = val.double_value (true);
2572 
2573  if (! error_state)
2574  retval += do_printf_conv (os, tfmt.c_str (), nsa,
2575  sa_1, sa_2, dval, who);
2576  }
2577  break;
2578 
2579  case 'o': case 'x': case 'X': case 'u':
2580  if (ok_for_unsigned_int_conv (val))
2581  {
2582  octave_uint64 tval = val.uint64_scalar_value ();
2583 
2584  // Insert "long" modifier.
2585  std::string tfmt = fmt;
2586  tfmt.replace (tfmt.rfind (type), 1, llmod + type);
2587 
2588  retval += do_printf_conv (os, tfmt.c_str (), nsa, sa_1, sa_2,
2589  tval.value (), who);
2590  }
2591  else
2592  {
2593  std::string tfmt = switch_to_g_format (elt);
2594 
2595  double dval = val.double_value (true);
2596 
2597  if (! error_state)
2598  retval += do_printf_conv (os, tfmt.c_str (), nsa,
2599  sa_1, sa_2, dval, who);
2600  }
2601  break;
2602 
2603  case 'f': case 'e': case 'E':
2604  case 'g': case 'G':
2605  {
2606  double dval = val.double_value (true);
2607 
2608  if (! error_state)
2609  retval += do_printf_conv (os, fmt, nsa, sa_1, sa_2, dval, who);
2610  }
2611  break;
2612 
2613  default:
2614  error ("%s: invalid format specifier",
2615  who.c_str ());
2616  return -1;
2617  break;
2618  }
2619  }
2620 
2621  return retval;
2622 }
2623 
2624 int
2626  const octave_value_list& args,
2627  const std::string& who)
2628 {
2629  int retval = 0;
2630 
2631  octave_idx_type nconv = fmt_list.num_conversions ();
2632 
2633  std::ostream *osp = output_stream ();
2634 
2635  if (osp)
2636  {
2637  std::ostream& os = *osp;
2638 
2639  const printf_format_elt *elt = fmt_list.first ();
2640 
2641  printf_value_cache val_cache (args, who);
2642 
2643  if (error_state)
2644  return retval;
2645 
2646  for (;;)
2647  {
2648  octave_quit ();
2649 
2650  if (elt)
2651  {
2652  // NSA is the number of 'star' args to convert.
2653 
2654  int nsa = (elt->fw == -2) + (elt->prec == -2);
2655 
2656  int sa_1 = 0;
2657  int sa_2 = 0;
2658 
2659  if (nsa > 0)
2660  {
2661  sa_1 = val_cache.int_value ();
2662 
2663  if (! val_cache)
2664  break;
2665  else
2666  {
2667  if (nsa > 1)
2668  {
2669  sa_2 = val_cache.int_value ();
2670 
2671  if (! val_cache)
2672  break;
2673  }
2674  }
2675  }
2676 
2677  if (elt->type == '%')
2678  {
2679  os << "%";
2680  retval++;
2681  }
2682  else if (elt->args == 0 && elt->text)
2683  {
2684  os << elt->text;
2685  retval += strlen (elt->text);
2686  }
2687  else if (elt->type == 's' || elt->type == 'c')
2688  {
2689  octave_value val = val_cache.get_next_value (elt->type);
2690 
2691  if (val_cache)
2692  {
2693  if (val.is_string ())
2694  {
2695  std::string sval = val.string_value ();
2696 
2697  retval += do_printf_string (os, elt, nsa, sa_1,
2698  sa_2, sval, who);
2699  }
2700  else
2701  retval += do_numeric_printf_conv (os, elt, nsa, sa_1,
2702  sa_2, val, who);
2703  }
2704  else
2705  break;
2706  }
2707  else
2708  {
2709  octave_value val = val_cache.get_next_value ();
2710 
2711  if (val_cache)
2712  retval += do_numeric_printf_conv (os, elt, nsa, sa_1,
2713  sa_2, val, who);
2714  else
2715  break;
2716  }
2717 
2718  if (! os)
2719  {
2720  error ("%s: write error", who.c_str ());
2721  break;
2722  }
2723  }
2724  else
2725  {
2726  ::error ("%s: internal error handling format", who.c_str ());
2727  retval = -1;
2728  break;
2729  }
2730 
2731  elt = fmt_list.next (nconv > 0 && ! val_cache.exhausted ());
2732 
2733  if (! elt || (val_cache.exhausted () && elt->args > 0))
2734  break;
2735  }
2736  }
2737  else
2738  invalid_operation (who, "writing");
2739 
2740  return retval;
2741 }
2742 
2743 int
2744 octave_base_stream::printf (const std::string& fmt,
2745  const octave_value_list& args,
2746  const std::string& who)
2747 {
2748  int retval = 0;
2749 
2750  printf_format_list fmt_list (fmt);
2751 
2752  if (fmt_list.num_conversions () == -1)
2753  ::error ("%s: invalid format specified", who.c_str ());
2754  else
2755  retval = do_printf (fmt_list, args, who);
2756 
2757  return retval;
2758 }
2759 
2760 int
2761 octave_base_stream::puts (const std::string& s, const std::string& who)
2762 {
2763  int retval = -1;
2764 
2765  std::ostream *osp = output_stream ();
2766 
2767  if (osp)
2768  {
2769  std::ostream& os = *osp;
2770 
2771  os << s;
2772 
2773  if (os)
2774  {
2775  // FIXME: why does this seem to be necessary?
2776  // Without it, output from a loop like
2777  //
2778  // for i = 1:100, fputs (stdout, "foo\n"); endfor
2779  //
2780  // doesn't seem to go to the pager immediately.
2781 
2782  os.flush ();
2783 
2784  if (os)
2785  retval = 0;
2786  else
2787  error ("%s: write error", who.c_str ());
2788  }
2789  else
2790  error ("%s: write error", who.c_str ());
2791  }
2792  else
2793  invalid_operation (who, "writing");
2794 
2795  return retval;
2796 }
2797 
2798 // Return current error message for this stream.
2799 
2800 std::string
2801 octave_base_stream::error (bool clear_err, int& err_num)
2802 {
2803  err_num = fail ? -1 : 0;
2804 
2805  std::string tmp = errmsg;
2806 
2807  if (clear_err)
2808  clear ();
2809 
2810  return tmp;
2811 }
2812 
2813 void
2814 octave_base_stream::invalid_operation (const std::string& who, const char *rw)
2815 {
2816  // Note that this is not ::error () !
2817 
2818  error (who, std::string ("stream not open for ") + rw);
2819 }
2820 
2822  : rep (bs)
2823 {
2824  if (rep)
2825  rep->count = 1;
2826 }
2827 
2829 {
2830  if (rep && --rep->count == 0)
2831  delete rep;
2832 }
2833 
2835  : rep (s.rep)
2836 {
2837  if (rep)
2838  rep->count++;
2839 }
2840 
2843 {
2844  if (rep != s.rep)
2845  {
2846  if (rep && --rep->count == 0)
2847  delete rep;
2848 
2849  rep = s.rep;
2850 
2851  if (rep)
2852  rep->count++;
2853  }
2854 
2855  return *this;
2856 }
2857 
2858 int
2860 {
2861  int retval = -1;
2862 
2863  if (stream_ok ())
2864  retval = rep->flush ();
2865 
2866  return retval;
2867 }
2868 
2869 std::string
2870 octave_stream::getl (octave_idx_type max_len, bool& err, const std::string& who)
2871 {
2872  std::string retval;
2873 
2874  if (stream_ok ())
2875  retval = rep->getl (max_len, err, who);
2876 
2877  return retval;
2878 }
2879 
2880 std::string
2881 octave_stream::getl (const octave_value& tc_max_len, bool& err,
2882  const std::string& who)
2883 {
2884  std::string retval;
2885 
2886  err = false;
2887 
2888  int conv_err = 0;
2889 
2890  int max_len = -1;
2891 
2892  if (tc_max_len.is_defined ())
2893  {
2894  max_len = convert_to_valid_int (tc_max_len, conv_err);
2895 
2896  if (conv_err || max_len < 0)
2897  {
2898  err = true;
2899  ::error ("%s: invalid maximum length specified", who.c_str ());
2900  }
2901  }
2902 
2903  if (! error_state)
2904  retval = getl (max_len, err, who);
2905 
2906  return retval;
2907 }
2908 
2909 std::string
2910 octave_stream::gets (octave_idx_type max_len, bool& err, const std::string& who)
2911 {
2912  std::string retval;
2913 
2914  if (stream_ok ())
2915  retval = rep->gets (max_len, err, who);
2916 
2917  return retval;
2918 }
2919 
2920 std::string
2921 octave_stream::gets (const octave_value& tc_max_len, bool& err,
2922  const std::string& who)
2923 {
2924  std::string retval;
2925 
2926  err = false;
2927 
2928  int conv_err = 0;
2929 
2930  int max_len = -1;
2931 
2932  if (tc_max_len.is_defined ())
2933  {
2934  max_len = convert_to_valid_int (tc_max_len, conv_err);
2935 
2936  if (conv_err || max_len < 0)
2937  {
2938  err = true;
2939  ::error ("%s: invalid maximum length specified", who.c_str ());
2940  }
2941  }
2942 
2943  if (! error_state)
2944  retval = gets (max_len, err, who);
2945 
2946  return retval;
2947 }
2948 
2949 off_t
2950 octave_stream::skipl (off_t count, bool& err, const std::string& who)
2951 {
2952  off_t retval = -1;
2953 
2954  if (stream_ok ())
2955  retval = rep->skipl (count, err, who);
2956 
2957  return retval;
2958 }
2959 
2960 off_t
2961 octave_stream::skipl (const octave_value& tc_count, bool& err,
2962  const std::string& who)
2963 {
2964  off_t retval = -1;
2965 
2966  err = false;
2967 
2968  int conv_err = 0;
2969 
2970  int count = 1;
2971 
2972  if (tc_count.is_defined ())
2973  {
2974  if (tc_count.is_scalar_type () && xisinf (tc_count.scalar_value ()))
2975  count = -1;
2976  else
2977  {
2978  count = convert_to_valid_int (tc_count, conv_err);
2979 
2980  if (conv_err || count < 0)
2981  {
2982  err = true;
2983  ::error ("%s: invalid number of lines specified", who.c_str ());
2984  }
2985  }
2986  }
2987 
2988  if (! error_state)
2989  retval = skipl (count, err, who);
2990 
2991  return retval;
2992 }
2993 
2994 int
2995 octave_stream::seek (off_t offset, int origin)
2996 {
2997  int status = -1;
2998 
2999  if (stream_ok ())
3000  {
3001  clearerr ();
3002 
3003  // Find current position so we can return to it if needed.
3004 
3005  off_t orig_pos = rep->tell ();
3006 
3007  // Move to end of file. If successful, find the offset of the end.
3008 
3009  status = rep->seek (0, SEEK_END);
3010 
3011  if (status == 0)
3012  {
3013  off_t eof_pos = rep->tell ();
3014 
3015  if (origin == SEEK_CUR)
3016  {
3017  // Move back to original position, otherwise we will be
3018  // seeking from the end of file which is probably not the
3019  // original location.
3020 
3021  rep->seek (orig_pos, SEEK_SET);
3022  }
3023 
3024  // Attempt to move to desired position; may be outside bounds
3025  // of existing file.
3026 
3027  status = rep->seek (offset, origin);
3028 
3029  if (status == 0)
3030  {
3031  // Where are we after moving to desired position?
3032 
3033  off_t desired_pos = rep->tell ();
3034 
3035  // I don't think save_pos can be less than zero, but we'll
3036  // check anyway...
3037 
3038  if (desired_pos > eof_pos || desired_pos < 0)
3039  {
3040  // Seek outside bounds of file. Failure should leave
3041  // position unchanged.
3042 
3043  rep->seek (orig_pos, SEEK_SET);
3044 
3045  status = -1;
3046  }
3047  }
3048  else
3049  {
3050  // Seeking to the desired position failed. Move back to
3051  // original position and return failure status.
3052 
3053  rep->seek (orig_pos, SEEK_SET);
3054 
3055  status = -1;
3056  }
3057  }
3058  }
3059 
3060  return status;
3061 }
3062 
3063 int
3065  const octave_value& tc_origin)
3066 {
3067  int retval = -1;
3068 
3069  // FIXME: should we have octave_value methods that handle off_t explicitly?
3070  octave_int64 val = tc_offset.int64_scalar_value ();
3071  off_t xoffset = val.value ();
3072 
3073  if (! error_state)
3074  {
3075  int conv_err = 0;
3076 
3077  int origin = SEEK_SET;
3078 
3079  if (tc_origin.is_string ())
3080  {
3081  std::string xorigin = tc_origin.string_value ();
3082 
3083  if (xorigin == "bof")
3084  origin = SEEK_SET;
3085  else if (xorigin == "cof")
3086  origin = SEEK_CUR;
3087  else if (xorigin == "eof")
3088  origin = SEEK_END;
3089  else
3090  conv_err = -1;
3091  }
3092  else
3093  {
3094  int xorigin = convert_to_valid_int (tc_origin, conv_err);
3095 
3096  if (! conv_err)
3097  {
3098  if (xorigin == -1)
3099  origin = SEEK_SET;
3100  else if (xorigin == 0)
3101  origin = SEEK_CUR;
3102  else if (xorigin == 1)
3103  origin = SEEK_END;
3104  else
3105  conv_err = -1;
3106  }
3107  }
3108 
3109  if (! conv_err)
3110  {
3111  retval = seek (xoffset, origin);
3112 
3113  if (retval != 0)
3114  error ("fseek: failed to seek to requested position");
3115  }
3116  else
3117  error ("fseek: invalid value for origin");
3118  }
3119  else
3120  error ("fseek: invalid value for offset");
3121 
3122  return retval;
3123 }
3124 
3125 off_t
3127 {
3128  off_t retval = -1;
3129 
3130  if (stream_ok ())
3131  retval = rep->tell ();
3132 
3133  return retval;
3134 }
3135 
3136 int
3138 {
3139  return seek (0, SEEK_SET);
3140 }
3141 
3142 bool
3144 {
3145  bool retval = false;
3146 
3147  if (stream_ok ())
3148  retval = rep->is_open ();
3149 
3150  return retval;
3151 }
3152 
3153 void
3155 {
3156  if (stream_ok ())
3157  rep->close ();
3158 }
3159 
3160 template <class SRC_T, class DST_T>
3161 static octave_value
3162 convert_and_copy (std::list<void *>& input_buf_list,
3163  octave_idx_type input_buf_elts,
3164  octave_idx_type elts_read,
3165  octave_idx_type nr, octave_idx_type nc, bool swap,
3166  bool do_float_fmt_conv, bool do_NA_conv,
3167  oct_mach_info::float_format from_flt_fmt)
3168 {
3169  typedef typename DST_T::element_type dst_elt_type;
3170 
3171  DST_T conv (dim_vector (nr, nc));
3172 
3173  dst_elt_type *conv_data = conv.fortran_vec ();
3174 
3175  octave_idx_type j = 0;
3176 
3177  for (std::list<void *>::const_iterator it = input_buf_list.begin ();
3178  it != input_buf_list.end (); it++)
3179  {
3180  SRC_T *data = static_cast<SRC_T *> (*it);
3181 
3182  if (swap || do_float_fmt_conv)
3183  {
3184  for (octave_idx_type i = 0; i < input_buf_elts && j < elts_read;
3185  i++, j++)
3186  {
3187  if (swap)
3188  swap_bytes<sizeof (SRC_T)> (&data[i]);
3189  else if (do_float_fmt_conv)
3190  do_float_format_conversion (&data[i], sizeof (SRC_T),
3191  1, from_flt_fmt,
3193 
3194  dst_elt_type tmp (data[i]);
3195 
3196  if (do_NA_conv && __lo_ieee_is_old_NA (tmp))
3197  tmp = __lo_ieee_replace_old_NA (tmp);
3198 
3199  conv_data[j] = tmp;
3200  }
3201  }
3202  else
3203  {
3204  if (do_NA_conv)
3205  {
3206  for (octave_idx_type i = 0; i < input_buf_elts && j < elts_read;
3207  i++, j++)
3208  {
3209  dst_elt_type tmp (data[i]);
3210 
3211  if (__lo_ieee_is_old_NA (tmp))
3212  tmp = __lo_ieee_replace_old_NA (tmp);
3213 
3214  conv_data[j] = tmp;
3215  }
3216  }
3217  else
3218  {
3219  for (octave_idx_type i = 0; i < input_buf_elts && j < elts_read;
3220  i++, j++)
3221  conv_data[j] = data[i];
3222  }
3223  }
3224 
3225  delete [] data;
3226  }
3227 
3228  input_buf_list.clear ();
3229 
3230  for (octave_idx_type i = elts_read; i < nr * nc; i++)
3231  conv_data[i] = dst_elt_type (0);
3232 
3233  return conv;
3234 }
3235 
3236 typedef octave_value (*conv_fptr)
3237  (std::list<void *>& input_buf_list, octave_idx_type input_buf_elts,
3239  bool swap, bool do_float_fmt_conv, bool do_NA_conv,
3240  oct_mach_info::float_format from_flt_fmt);
3241 
3242 #define TABLE_ELT(T, U, V, W) \
3243  conv_fptr_table[oct_data_conv::T][oct_data_conv::U] = convert_and_copy<V, W>
3244 
3245 #define FILL_TABLE_ROW(T, V) \
3246  TABLE_ELT (T, dt_int8, V, int8NDArray); \
3247  TABLE_ELT (T, dt_uint8, V, uint8NDArray); \
3248  TABLE_ELT (T, dt_int16, V, int16NDArray); \
3249  TABLE_ELT (T, dt_uint16, V, uint16NDArray); \
3250  TABLE_ELT (T, dt_int32, V, int32NDArray); \
3251  TABLE_ELT (T, dt_uint32, V, uint32NDArray); \
3252  TABLE_ELT (T, dt_int64, V, int64NDArray); \
3253  TABLE_ELT (T, dt_uint64, V, uint64NDArray); \
3254  TABLE_ELT (T, dt_single, V, FloatNDArray); \
3255  TABLE_ELT (T, dt_double, V, NDArray); \
3256  TABLE_ELT (T, dt_char, V, charNDArray); \
3257  TABLE_ELT (T, dt_schar, V, charNDArray); \
3258  TABLE_ELT (T, dt_uchar, V, charNDArray); \
3259  TABLE_ELT (T, dt_logical, V, boolNDArray);
3260 
3262 octave_stream::finalize_read (std::list<void *>& input_buf_list,
3263  octave_idx_type input_buf_elts,
3264  octave_idx_type elts_read,
3266  oct_data_conv::data_type input_type,
3267  oct_data_conv::data_type output_type,
3269 {
3270  octave_value retval;
3271 
3272  static bool initialized = false;
3273 
3274  // Table function pointers for return types x read types.
3275 
3276  static conv_fptr conv_fptr_table[oct_data_conv::dt_unknown][14];
3277 
3278  if (! initialized)
3279  {
3280  for (int i = 0; i < oct_data_conv::dt_unknown; i++)
3281  for (int j = 0; j < 14; j++)
3282  conv_fptr_table[i][j] = 0;
3283 
3284  FILL_TABLE_ROW (dt_int8, int8_t);
3285  FILL_TABLE_ROW (dt_uint8, uint8_t);
3286  FILL_TABLE_ROW (dt_int16, int16_t);
3287  FILL_TABLE_ROW (dt_uint16, uint16_t);
3288  FILL_TABLE_ROW (dt_int32, int32_t);
3289  FILL_TABLE_ROW (dt_uint32, uint32_t);
3290  FILL_TABLE_ROW (dt_int64, int64_t);
3291  FILL_TABLE_ROW (dt_uint64, uint64_t);
3292  FILL_TABLE_ROW (dt_single, float);
3293  FILL_TABLE_ROW (dt_double, double);
3294  FILL_TABLE_ROW (dt_char, char);
3295  FILL_TABLE_ROW (dt_schar, signed char);
3296  FILL_TABLE_ROW (dt_uchar, unsigned char);
3297  FILL_TABLE_ROW (dt_logical, bool);
3298 
3299  initialized = true;
3300  }
3301 
3302  bool swap = false;
3303 
3304  if (ffmt == oct_mach_info::flt_fmt_unknown)
3305  ffmt = float_format ();
3306 
3309  else
3310  swap = (ffmt == oct_mach_info::flt_fmt_ieee_big_endian);
3311 
3312  bool do_float_fmt_conv = ((input_type == oct_data_conv::dt_double
3313  || input_type == oct_data_conv::dt_single)
3314  && ffmt != float_format ());
3315 
3316  bool do_NA_conv = (output_type == oct_data_conv::dt_double);
3317 
3318  switch (output_type)
3319  {
3334  {
3335  conv_fptr fptr = conv_fptr_table[input_type][output_type];
3336 
3337  retval = fptr (input_buf_list, input_buf_elts, elts_read,
3338  nr, nc, swap, do_float_fmt_conv, do_NA_conv, ffmt);
3339  }
3340  break;
3341 
3342  default:
3343  retval = false;
3344  (*current_liboctave_error_handler)
3345  ("read: invalid type specification");
3346  break;
3347  }
3348 
3349 
3350  return retval;
3351 }
3352 
3355  oct_data_conv::data_type input_type,
3356  oct_data_conv::data_type output_type,
3358  octave_idx_type& count)
3359 {
3360  octave_value retval;
3361 
3362  octave_idx_type nr = -1;
3363  octave_idx_type nc = -1;
3364 
3365  bool one_elt_size_spec = false;
3366 
3367  if (stream_ok ())
3368  {
3369  // FIXME: we may eventually want to make this extensible.
3370 
3371  // FIXME: we need a better way to ensure that this
3372  // numbering stays consistent with the order of the elements in the
3373  // data_type enum in the oct_data_conv class.
3374 
3375  // Expose this in a future version?
3376  octave_idx_type char_count = 0;
3377 
3378  count = 0;
3379 
3380  get_size (size, nr, nc, one_elt_size_spec, "fread");
3381 
3382  if (! error_state)
3383  {
3384 
3385  octave_idx_type elts_to_read;
3386 
3387  if (one_elt_size_spec)
3388  {
3389  // If NR == 0, Matlab returns [](0x0).
3390 
3391  // If NR > 0, the result will be a column vector with the given
3392  // number of rows.
3393 
3394  // If NR < 0, then we have Inf and the result will be a column
3395  // vector but we have to wait to see how big NR will be.
3396 
3397  if (nr == 0)
3398  nr = nc = 0;
3399  else
3400  nc = 1;
3401  }
3402  else
3403  {
3404  // Matlab returns [] even if there are two elements in the size
3405  // specification and one is nonzero.
3406 
3407  // If NC < 0 we have [NR, Inf] and we'll wait to decide how big NC
3408  // should be.
3409 
3410  if (nr == 0 || nc == 0)
3411  nr = nc = 0;
3412  }
3413 
3414  // FIXME: Ensure that this does not overflow.
3415  // Maybe try comparing nr * nc computed in double with
3416  // std::numeric_limits<octave_idx_type>::max ();
3417 
3418  elts_to_read = nr * nc;
3419 
3420  bool read_to_eof = elts_to_read < 0;
3421 
3422  octave_idx_type input_buf_elts = -1;
3423 
3424  if (skip == 0)
3425  {
3426  if (read_to_eof)
3427  input_buf_elts = 1024 * 1024;
3428  else
3429  input_buf_elts = elts_to_read;
3430  }
3431  else
3432  input_buf_elts = block_size;
3433 
3434  octave_idx_type input_elt_size
3435  = oct_data_conv::data_type_size (input_type);
3436 
3437  octave_idx_type input_buf_size = input_buf_elts * input_elt_size;
3438 
3439  assert (input_buf_size >= 0);
3440 
3441  // Must also work and return correct type object
3442  // for 0 elements to read.
3443 
3444  std::istream *isp = input_stream ();
3445 
3446  if (isp)
3447  {
3448  std::istream& is = *isp;
3449 
3450  std::list <void *> input_buf_list;
3451 
3452  while (is && ! is.eof ()
3453  && (read_to_eof || count < elts_to_read))
3454  {
3455  if (! read_to_eof)
3456  {
3457  octave_idx_type remaining_elts = elts_to_read - count;
3458 
3459  if (remaining_elts < input_buf_elts)
3460  input_buf_size = remaining_elts * input_elt_size;
3461  }
3462 
3463  char *input_buf = new char [input_buf_size];
3464 
3465  is.read (input_buf, input_buf_size);
3466 
3467  size_t gcount = is.gcount ();
3468 
3469  char_count += gcount;
3470 
3471  octave_idx_type nel = gcount / input_elt_size;
3472 
3473  count += nel;
3474 
3475  input_buf_list.push_back (input_buf);
3476 
3477  if (is && skip != 0 && nel == block_size)
3478  {
3479  // Seek to skip. If skip would move past EOF,
3480  // position at EOF.
3481 
3482  off_t orig_pos = tell ();
3483 
3484  seek (0, SEEK_END);
3485 
3486  off_t eof_pos = tell ();
3487 
3488  // Is it possible for this to fail to return us to
3489  // the original position?
3490  seek (orig_pos, SEEK_SET);
3491 
3492  off_t remaining = eof_pos - orig_pos;
3493 
3494  if (remaining < skip)
3495  seek (0, SEEK_END);
3496  else
3497  seek (skip, SEEK_CUR);
3498 
3499  if (! is)
3500  break;
3501  }
3502  }
3503 
3504  if (read_to_eof)
3505  {
3506  if (nc < 0)
3507  {
3508  nc = count / nr;
3509 
3510  if (count % nr != 0)
3511  nc ++;
3512  }
3513  else
3514  nr = count;
3515  }
3516  else if (count == 0)
3517  {
3518  nr = 0;
3519  nc = 0;
3520  }
3521  else if (count != nr * nc)
3522  {
3523  if (count % nr != 0)
3524  nc = count / nr + 1;
3525  else
3526  nc = count / nr;
3527 
3528  if (count < nr)
3529  nr = count;
3530  }
3531 
3532  retval = finalize_read (input_buf_list, input_buf_elts, count,
3533  nr, nc, input_type, output_type, ffmt);
3534  }
3535  else
3536  error ("fread: invalid input stream");
3537  }
3538  else
3539  invalid_operation ("fread", "reading");
3540  }
3541 
3542  return retval;
3543 }
3544 
3547  oct_data_conv::data_type output_type,
3549 {
3550  octave_idx_type retval = -1;
3551 
3552  if (stream_ok ())
3553  {
3554  if (! error_state)
3555  {
3556  if (flt_fmt == oct_mach_info::flt_fmt_unknown)
3557  flt_fmt = float_format ();
3558 
3559  octave_idx_type status = data.write (*this, block_size, output_type,
3560  skip, flt_fmt);
3561 
3562  if (status < 0)
3563  error ("fwrite: write error");
3564  else
3565  retval = status;
3566  }
3567  else
3568  invalid_operation ("fwrite", "writing");
3569  }
3570 
3571  return retval;
3572 }
3573 
3574 template <class T, class V>
3575 static void
3576 convert_chars (const void *data, void *conv_data, octave_idx_type n_elts)
3577 {
3578  const T *tt_data = static_cast<const T *> (data);
3579 
3580  V *vt_data = static_cast<V *> (conv_data);
3581 
3582  for (octave_idx_type i = 0; i < n_elts; i++)
3583  vt_data[i] = tt_data[i];
3584 }
3585 
3586 template <class T, class V>
3587 static void
3588 convert_ints (const T *data, void *conv_data, octave_idx_type n_elts,
3589  bool swap)
3590 {
3591  typedef typename V::val_type val_type;
3592 
3593  val_type *vt_data = static_cast<val_type *> (conv_data);
3594 
3595  for (octave_idx_type i = 0; i < n_elts; i++)
3596  {
3597  // Yes, we want saturation semantics when converting to an integer
3598  // type.
3599 
3600  V val (data[i]);
3601 
3602  vt_data[i] = val.value ();
3603 
3604  if (swap)
3605  swap_bytes<sizeof (val_type)> (&vt_data[i]);
3606  }
3607 }
3608 
3609 template <class T>
3611 {
3612 public:
3613  typedef T type;
3614 };
3615 
3616 template <class T>
3618 {
3619 public:
3620  typedef T type;
3621 };
3622 
3623 template <class T>
3624 static bool
3625 convert_data (const T *data, void *conv_data, octave_idx_type n_elts,
3626  oct_data_conv::data_type output_type,
3628 {
3629  bool retval = true;
3630 
3631  bool swap
3635 
3636  bool do_float_conversion = flt_fmt != oct_mach_info::float_format ();
3637 
3638  typedef typename ultimate_element_type<T>::type ult_elt_type;
3639 
3640  switch (output_type)
3641  {
3643  convert_chars<ult_elt_type, char> (data, conv_data, n_elts);
3644  break;
3645 
3647  convert_chars<ult_elt_type, signed char> (data, conv_data, n_elts);
3648  break;
3649 
3651  convert_chars<ult_elt_type, unsigned char> (data, conv_data, n_elts);
3652  break;
3653 
3655  convert_ints<T, octave_int8> (data, conv_data, n_elts, swap);
3656  break;
3657 
3659  convert_ints<T, octave_uint8> (data, conv_data, n_elts, swap);
3660  break;
3661 
3663  convert_ints<T, octave_int16> (data, conv_data, n_elts, swap);
3664  break;
3665 
3667  convert_ints<T, octave_uint16> (data, conv_data, n_elts, swap);
3668  break;
3669 
3671  convert_ints<T, octave_int32> (data, conv_data, n_elts, swap);
3672  break;
3673 
3675  convert_ints<T, octave_uint32> (data, conv_data, n_elts, swap);
3676  break;
3677 
3679  convert_ints<T, octave_int64> (data, conv_data, n_elts, swap);
3680  break;
3681 
3683  convert_ints<T, octave_uint64> (data, conv_data, n_elts, swap);
3684  break;
3685 
3687  {
3688  float *vt_data = static_cast<float *> (conv_data);
3689 
3690  for (octave_idx_type i = 0; i < n_elts; i++)
3691  {
3692  vt_data[i] = data[i];
3693 
3694  if (do_float_conversion)
3695  do_float_format_conversion (&vt_data[i], 1, flt_fmt);
3696  }
3697  }
3698  break;
3699 
3701  {
3702  double *vt_data = static_cast<double *> (conv_data);
3703 
3704  for (octave_idx_type i = 0; i < n_elts; i++)
3705  {
3706  vt_data[i] = data[i];
3707 
3708  if (do_float_conversion)
3709  do_double_format_conversion (&vt_data[i], 1, flt_fmt);
3710  }
3711  }
3712  break;
3713 
3714  default:
3715  retval = false;
3716  (*current_liboctave_error_handler)
3717  ("write: invalid type specification");
3718  break;
3719  }
3720 
3721  return retval;
3722 }
3723 
3724 bool
3725 octave_stream::write_bytes (const void *data, size_t nbytes)
3726 {
3727  bool status = false;
3728 
3729  std::ostream *osp = output_stream ();
3730 
3731  if (osp)
3732  {
3733  std::ostream& os = *osp;
3734 
3735  if (os)
3736  {
3737  os.write (static_cast<const char *> (data), nbytes);
3738 
3739  if (os)
3740  status = true;
3741  }
3742  }
3743 
3744  return status;
3745 }
3746 
3747 bool
3749 {
3750  bool status = false;
3751 
3752  std::ostream *osp = output_stream ();
3753 
3754  if (osp)
3755  {
3756  std::ostream& os = *osp;
3757 
3758  // Seek to skip when inside bounds of existing file.
3759  // Otherwise, write NUL to skip.
3760 
3761  off_t orig_pos = tell ();
3762 
3763  seek (0, SEEK_END);
3764 
3765  off_t eof_pos = tell ();
3766 
3767  // Is it possible for this to fail to return us to the
3768  // original position?
3769  seek (orig_pos, SEEK_SET);
3770 
3771  size_t remaining = eof_pos - orig_pos;
3772 
3773  if (remaining < skip)
3774  {
3775  seek (0, SEEK_END);
3776 
3777  // FIXME: probably should try to write larger blocks...
3778 
3779  unsigned char zero = 0;
3780  for (size_t j = 0; j < skip - remaining; j++)
3781  os.write (reinterpret_cast<const char *> (&zero), 1);
3782  }
3783  else
3784  seek (skip, SEEK_CUR);
3785 
3786  if (os)
3787  status = true;
3788  }
3789 
3790  return status;
3791 }
3792 
3793 template <class T>
3796  oct_data_conv::data_type output_type,
3797  octave_idx_type skip,
3799 {
3800  bool swap = ((oct_mach_info::words_big_endian ()
3803 
3804  bool do_data_conversion = (swap || ! is_equivalent_type<T> (output_type)
3805  || flt_fmt != oct_mach_info::float_format ());
3806 
3807  octave_idx_type nel = data.numel ();
3808 
3809  octave_idx_type chunk_size;
3810 
3811  if (skip != 0)
3812  chunk_size = block_size;
3813  else if (do_data_conversion)
3814  chunk_size = 1024 * 1024;
3815  else
3816  chunk_size = nel;
3817 
3818  octave_idx_type i = 0;
3819 
3820  const T *pdata = data.data ();
3821 
3822  while (i < nel)
3823  {
3824  if (skip != 0)
3825  {
3826  if (! skip_bytes (skip))
3827  return -1;
3828  }
3829 
3830  octave_idx_type remaining_nel = nel - i;
3831 
3832  if (chunk_size > remaining_nel)
3833  chunk_size = remaining_nel;
3834 
3835  bool status = false;
3836 
3837  if (do_data_conversion)
3838  {
3839  size_t output_size
3840  = chunk_size * oct_data_conv::data_type_size (output_type);
3841 
3842  OCTAVE_LOCAL_BUFFER (unsigned char, conv_data, output_size);
3843 
3844  status = convert_data (&pdata[i], conv_data, chunk_size,
3845  output_type, flt_fmt);
3846 
3847  if (status)
3848  status = write_bytes (conv_data, output_size);
3849  }
3850  else
3851  status = write_bytes (pdata, sizeof (T) * chunk_size);
3852 
3853  if (! status)
3854  return -1;
3855 
3856  i += chunk_size;
3857  }
3858 
3859  return nel;
3860 }
3861 
3862 #define INSTANTIATE_WRITE(T) \
3863  template \
3864  octave_idx_type \
3865  octave_stream::write (const Array<T>& data, octave_idx_type block_size, \
3866  oct_data_conv::data_type output_type, \
3867  octave_idx_type skip, \
3868  oct_mach_info::float_format flt_fmt)
3869 
3878 INSTANTIATE_WRITE (int8_t);
3879 INSTANTIATE_WRITE (uint8_t);
3880 INSTANTIATE_WRITE (int16_t);
3881 INSTANTIATE_WRITE (uint16_t);
3882 INSTANTIATE_WRITE (int32_t);
3883 INSTANTIATE_WRITE (uint32_t);
3884 INSTANTIATE_WRITE (int64_t);
3885 INSTANTIATE_WRITE (uint64_t);
3886 INSTANTIATE_WRITE (bool);
3887 INSTANTIATE_WRITE (char);
3888 INSTANTIATE_WRITE (float);
3889 INSTANTIATE_WRITE (double);
3890 
3892 octave_stream::scanf (const std::string& fmt, const Array<double>& size,
3893  octave_idx_type& count, const std::string& who)
3894 {
3895  octave_value retval;
3896 
3897  if (stream_ok ())
3898  retval = rep->scanf (fmt, size, count, who);
3899 
3900  return retval;
3901 }
3902 
3905  octave_idx_type& count, const std::string& who)
3906 {
3907  octave_value retval = Matrix ();
3908 
3909  if (fmt.is_string ())
3910  {
3911  std::string sfmt = fmt.string_value ();
3912 
3913  if (fmt.is_sq_string ())
3914  sfmt = do_string_escapes (sfmt);
3915 
3916  retval = scanf (sfmt, size, count, who);
3917  }
3918  else
3919  {
3920  // Note that this is not ::error () !
3921 
3922  error (who + ": format must be a string");
3923  }
3924 
3925  return retval;
3926 }
3927 
3929 octave_stream::oscanf (const std::string& fmt, const std::string& who)
3930 {
3931  octave_value_list retval;
3932 
3933  if (stream_ok ())
3934  retval = rep->oscanf (fmt, who);
3935 
3936  return retval;
3937 }
3938 
3940 octave_stream::oscanf (const octave_value& fmt, const std::string& who)
3941 {
3942  octave_value_list retval;
3943 
3944  if (fmt.is_string ())
3945  {
3946  std::string sfmt = fmt.string_value ();
3947 
3948  if (fmt.is_sq_string ())
3949  sfmt = do_string_escapes (sfmt);
3950 
3951  retval = oscanf (sfmt, who);
3952  }
3953  else
3954  {
3955  // Note that this is not ::error () !
3956 
3957  error (who + ": format must be a string");
3958  }
3959 
3960  return retval;
3961 }
3962 
3963 int
3964 octave_stream::printf (const std::string& fmt, const octave_value_list& args,
3965  const std::string& who)
3966 {
3967  int retval = -1;
3968 
3969  if (stream_ok ())
3970  retval = rep->printf (fmt, args, who);
3971 
3972  return retval;
3973 }
3974 
3975 int
3977  const std::string& who)
3978 {
3979  int retval = 0;
3980 
3981  if (fmt.is_string ())
3982  {
3983  std::string sfmt = fmt.string_value ();
3984 
3985  if (fmt.is_sq_string ())
3986  sfmt = do_string_escapes (sfmt);
3987 
3988  retval = printf (sfmt, args, who);
3989  }
3990  else
3991  {
3992  // Note that this is not ::error () !
3993 
3994  error (who + ": format must be a string");
3995  }
3996 
3997  return retval;
3998 }
3999 
4000 int
4001 octave_stream::puts (const std::string& s, const std::string& who)
4002 {
4003  int retval = -1;
4004 
4005  if (stream_ok ())
4006  retval = rep->puts (s, who);
4007 
4008  return retval;
4009 }
4010 
4011 // FIXME: maybe this should work for string arrays too.
4012 
4013 int
4014 octave_stream::puts (const octave_value& tc_s, const std::string& who)
4015 {
4016  int retval = -1;
4017 
4018  if (tc_s.is_string ())
4019  {
4020  std::string s = tc_s.string_value ();
4021  retval = puts (s, who);
4022  }
4023  else
4024  {
4025  // Note that this is not ::error () !
4026 
4027  error (who + ": argument must be a string");
4028  }
4029 
4030  return retval;
4031 }
4032 
4033 bool
4035 {
4036  int retval = -1;
4037 
4038  if (stream_ok ())
4039  retval = rep->eof ();
4040 
4041  return retval;
4042 }
4043 
4044 std::string
4045 octave_stream::error (bool clear, int& err_num)
4046 {
4047  std::string retval = "invalid stream object";
4048 
4049  if (stream_ok (false))
4050  retval = rep->error (clear, err_num);
4051 
4052  return retval;
4053 }
4054 
4055 std::string
4057 {
4058  std::string retval;
4059 
4060  if (stream_ok ())
4061  retval = rep->name ();
4062 
4063  return retval;
4064 }
4065 
4066 int
4068 {
4069  int retval = 0;
4070 
4071  if (stream_ok ())
4072  retval = rep->mode ();
4073 
4074  return retval;
4075 }
4076 
4079 {
4081 
4082  if (stream_ok ())
4083  retval = rep->float_format ();
4084 
4085  return retval;
4086 }
4087 
4088 std::string
4090 {
4091  std::string retval = "???";
4092  std::ios::openmode in_mode = static_cast<std::ios::openmode> (mode);
4093 
4094  if (in_mode == std::ios::in)
4095  retval = "r";
4096  else if (in_mode == std::ios::out
4097  || in_mode == (std::ios::out | std::ios::trunc))
4098  retval = "w";
4099  else if (in_mode == (std::ios::out | std::ios::app))
4100  retval = "a";
4101  else if (in_mode == (std::ios::in | std::ios::out))
4102  retval = "r+";
4103  else if (in_mode == (std::ios::in | std::ios::out | std::ios::trunc))
4104  retval = "w+";
4105  else if (in_mode == (std::ios::in | std::ios::out | std::ios::ate))
4106  retval = "a+";
4107  else if (in_mode == (std::ios::in | std::ios::binary))
4108  retval = "rb";
4109  else if (in_mode == (std::ios::out | std::ios::binary)
4110  || in_mode == (std::ios::out | std::ios::trunc | std::ios::binary))
4111  retval = "wb";
4112  else if (in_mode == (std::ios::out | std::ios::app | std::ios::binary))
4113  retval = "ab";
4114  else if (in_mode == (std::ios::in | std::ios::out | std::ios::binary))
4115  retval = "r+b";
4116  else if (in_mode == (std::ios::in | std::ios::out | std::ios::trunc
4117  | std::ios::binary))
4118  retval = "w+b";
4119  else if (in_mode == (std::ios::in | std::ios::out | std::ios::ate
4120  | std::ios::binary))
4121  retval = "a+b";
4122 
4123  return retval;
4124 }
4125 
4127 
4128 bool
4130 {
4131  bool retval = true;
4132 
4133  if (! instance)
4134  {
4135  instance = new octave_stream_list ();
4136 
4137  if (instance)
4139  }
4140 
4141  if (! instance)
4142  {
4143  ::error ("unable to create stream list object!");
4144 
4145  retval = false;
4146  }
4147 
4148  return retval;
4149 }
4150 
4151 int
4153 {
4154  return (instance_ok ()) ? instance->do_insert (os) : -1;
4155 }
4156 
4158 octave_stream_list::lookup (int fid, const std::string& who)
4159 {
4160  return (instance_ok ()) ? instance->do_lookup (fid, who) : octave_stream ();
4161 }
4162 
4164 octave_stream_list::lookup (const octave_value& fid, const std::string& who)
4165 {
4166  return (instance_ok ()) ? instance->do_lookup (fid, who) : octave_stream ();
4167 }
4168 
4169 int
4170 octave_stream_list::remove (int fid, const std::string& who)
4171 {
4172  return (instance_ok ()) ? instance->do_remove (fid, who) : -1;
4173 }
4174 
4175 int
4176 octave_stream_list::remove (const octave_value& fid, const std::string& who)
4177 {
4178  return (instance_ok ()) ? instance->do_remove (fid, who) : -1;
4179 }
4180 
4181 void
4183 {
4184  if (instance)
4185  instance->do_clear (flush);
4186 }
4187 
4190 {
4191  return (instance_ok ()) ? instance->do_get_info (fid) : string_vector ();
4192 }
4193 
4196 {
4197  return (instance_ok ()) ? instance->do_get_info (fid) : string_vector ();
4198 }
4199 
4200 std::string
4202 {
4203  return (instance_ok ()) ? instance->do_list_open_files () : std::string ();
4204 }
4205 
4208 {
4209  return (instance_ok ())
4211 }
4212 
4213 int
4215 {
4216  return (instance_ok ()) ? instance->do_get_file_number (fid) : -1;
4217 }
4218 
4219 int
4221 {
4222  // Insert item with key corresponding to file-descriptor.
4223 
4224  int stream_number;
4225 
4226  if ((stream_number = os.file_number ()) == -1)
4227  return stream_number;
4228 
4229  // Should we test for
4230  //
4231  // (list.find (stream_number) != list.end ()
4232  // && list[stream_number].is_open ())
4233  //
4234  // and respond with "error ("internal error: ...")"? It should not
4235  // happen except for some bug or if the user has opened a stream with
4236  // an interpreted command, but closed it directly with a system call
4237  // in an oct-file; then the kernel knows the fd is free, but Octave
4238  // does not know. If it happens, it should not do harm here to simply
4239  // overwrite this entry, although the wrong entry might have done harm
4240  // before.
4241 
4242  if (list.size () < list.max_size ())
4243  list[stream_number] = os;
4244  else
4245  {
4246  stream_number = -1;
4247  error ("could not create file id");
4248  }
4249 
4250  return stream_number;
4251 
4252 }
4253 
4254 static void
4255 gripe_invalid_file_id (int fid, const std::string& who)
4256 {
4257  if (who.empty ())
4258  ::error ("invalid stream number = %d", fid);
4259  else
4260  ::error ("%s: invalid stream number = %d", who.c_str (), fid);
4261 }
4262 
4264 octave_stream_list::do_lookup (int fid, const std::string& who) const
4265 {
4266  octave_stream retval;
4267 
4268  if (fid >= 0)
4269  {
4270  if (lookup_cache != list.end () && lookup_cache->first == fid)
4271  retval = lookup_cache->second;
4272  else
4273  {
4274  ostrl_map::const_iterator iter = list.find (fid);
4275 
4276  if (iter != list.end ())
4277  {
4278  retval = iter->second;
4279  lookup_cache = iter;
4280  }
4281  else
4282  gripe_invalid_file_id (fid, who);
4283  }
4284  }
4285  else
4286  gripe_invalid_file_id (fid, who);
4287 
4288  return retval;
4289 }
4290 
4293  const std::string& who) const
4294 {
4295  octave_stream retval;
4296 
4297  int i = get_file_number (fid);
4298 
4299  if (! error_state)
4300  retval = do_lookup (i, who);
4301 
4302  return retval;
4303 }
4304 
4305 int
4306 octave_stream_list::do_remove (int fid, const std::string& who)
4307 {
4308  int retval = -1;
4309 
4310  // Can't remove stdin (std::cin), stdout (std::cout), or stderr
4311  // (std::cerr).
4312 
4313  if (fid > 2)
4314  {
4315  ostrl_map::iterator iter = list.find (fid);
4316 
4317  if (iter != list.end ())
4318  {
4319  octave_stream os = iter->second;
4320  list.erase (iter);
4321  lookup_cache = list.end ();
4322 
4323  // FIXME: is this check redundant?
4324  if (os.is_valid ())
4325  {
4326  os.close ();
4327  retval = 0;
4328  }
4329  else
4330  gripe_invalid_file_id (fid, who);
4331  }
4332  else
4333  gripe_invalid_file_id (fid, who);
4334  }
4335  else
4336  gripe_invalid_file_id (fid, who);
4337 
4338  return retval;
4339 }
4340 
4341 int
4342 octave_stream_list::do_remove (const octave_value& fid, const std::string& who)
4343 {
4344  int retval = -1;
4345 
4346  if (fid.is_string () && fid.string_value () == "all")
4347  {
4348  do_clear (false);
4349 
4350  retval = 0;
4351  }
4352  else
4353  {
4354  int i = get_file_number (fid);
4355 
4356  if (! error_state)
4357  retval = do_remove (i, who);
4358  }
4359 
4360  return retval;
4361 }
4362 
4363 void
4365 {
4366  if (flush)
4367  {
4368  // Do flush stdout and stderr.
4369 
4370  list[0].flush ();
4371  list[1].flush ();
4372  }
4373 
4374  octave_stream saved_os[3];
4375  // But don't delete them or stdin.
4376  for (ostrl_map::iterator iter = list.begin (); iter != list.end (); iter++)
4377  {
4378  int fid = iter->first;
4379  octave_stream os = iter->second;
4380  if (fid < 3)
4381  saved_os[fid] = os;
4382  else if (os.is_valid ())
4383  os.close ();
4384  }
4385  list.clear ();
4386  for (int fid = 0; fid < 3; fid++) list[fid] = saved_os[fid];
4387  lookup_cache = list.end ();
4388 }
4389 
4392 {
4393  string_vector retval;
4394 
4395  octave_stream os = do_lookup (fid);
4396 
4397  if (os.is_valid ())
4398  {
4399  retval.resize (3);
4400 
4402  retval(1) = octave_stream::mode_as_string (os.mode ());
4403  retval(0) = os.name ();
4404  }
4405  else
4406  ::error ("invalid file id = %d", fid);
4407 
4408  return retval;
4409 }
4410 
4413 {
4414  string_vector retval;
4415 
4416  int conv_err = 0;
4417 
4418  int int_fid = convert_to_valid_int (fid, conv_err);
4419 
4420  if (! conv_err)
4421  retval = do_get_info (int_fid);
4422  else
4423  ::error ("file id must be a file object or integer value");
4424 
4425  return retval;
4426 }
4427 
4428 std::string
4430 {
4431  std::string retval;
4432 
4433  std::ostringstream buf;
4434 
4435  buf << "\n"
4436  << " number mode arch name\n"
4437  << " ------ ---- ---- ----\n";
4438 
4439  for (ostrl_map::const_iterator p = list.begin (); p != list.end (); p++)
4440  {
4441  octave_stream os = p->second;
4442 
4443  buf << " "
4444  << std::setiosflags (std::ios::right)
4445  << std::setw (4) << p->first << " "
4446  // reset necessary in addition to setiosflags since this is one stmt.
4447  << std::resetiosflags (std::ios::adjustfield)
4448  << std::setiosflags (std::ios::left)
4449  << std::setw (3)
4451  << " "
4452  << std::setw (9)
4454  << " "
4455  << os.name () << "\n";
4456  }
4457 
4458  buf << "\n";
4459 
4460  retval = buf.str ();
4461 
4462  return retval;
4463 }
4464 
4467 {
4468  Matrix retval (1, list.size (), 0.0);
4469 
4470  int num_open = 0;
4471 
4472  for (ostrl_map::const_iterator p = list.begin (); p != list.end (); p++)
4473  {
4474  // Skip stdin, stdout, and stderr.
4475 
4476  if (p->first > 2 && p->second)
4477  retval(0,num_open++) = p->first;
4478  }
4479 
4480  retval.resize ((num_open > 0), num_open);
4481 
4482  return retval;
4483 }
4484 
4485 int
4487 {
4488  int retval = -1;
4489 
4490  if (fid.is_string ())
4491  {
4492  std::string nm = fid.string_value ();
4493 
4494  for (ostrl_map::const_iterator p = list.begin (); p != list.end (); p++)
4495  {
4496  // stdin (std::cin), stdout (std::cout), and stderr (std::cerr)
4497  // are unnamed.
4498 
4499  if (p->first > 2)
4500  {
4501  octave_stream os = p->second;
4502 
4503  if (os && os.name () == nm)
4504  {
4505  retval = p->first;
4506  break;
4507  }
4508  }
4509  }
4510  }
4511  else
4512  {
4513  int conv_err = 0;
4514 
4515  int int_fid = convert_to_valid_int (fid, conv_err);
4516 
4517  if (conv_err)
4518  ::error ("file id must be a file object, std::string, or integer value");
4519  else
4520  retval = int_fid;
4521  }
4522 
4523  return retval;
4524 }
int bool
Definition: mex.h:56
bool is_object(void) const
Definition: ov.h:577
void invalid_operation(const std::string &who, const char *rw)
Definition: oct-stream.h:657
static void clear(octave_shlib &oct_file)
Definition: dynamic-ld.cc:236
bool skip_bytes(size_t n_elts)
Definition: oct-stream.cc:3748
static octave_stream lookup(int fid, const std::string &who=std::string())
Definition: oct-stream.cc:4158
#define DO_LITERAL_CONVERSION()
Definition: oct-stream.cc:1290
#define DO_PCT_CONVERSION()
Definition: oct-stream.cc:1317
#define lo_ieee_is_NA(x)
Definition: lo-ieee.h:109
octave_value read(const Array< double > &size, octave_idx_type block_size, oct_data_conv::data_type input_type, oct_data_conv::data_type output_type, octave_idx_type skip, oct_mach_info::float_format flt_fmt, octave_idx_type &count)
Definition: oct-stream.cc:3354
static std::string expand_char_class(const std::string &s)
Definition: oct-stream.cc:274
const printf_format_elt * first(void)
Definition: oct-stream.h:256
void gripe_wrong_type_arg(const char *name, const char *s, bool is_error)
Definition: gripes.cc:135
void printme(void) const
Definition: oct-stream.cc:490
static std::string float_format_as_string(float_format)
Definition: mach-info.cc:205
void do_float_format_conversion(void *data, octave_idx_type len, oct_mach_info::float_format from_fmt, oct_mach_info::float_format to_fmt)
Definition: data-conv.cc:708
double xround(double x)
Definition: lo-mappers.cc:63
bool is_open(void) const
Definition: oct-stream.h:377
double __lo_ieee_replace_old_NA(double x)
Definition: lo-ieee.cc:101
int rewind(void)
Definition: oct-stream.cc:3137
void resize(octave_idx_type nr, octave_idx_type nc, double rfv=0)
Definition: dMatrix.h:130
virtual off_t tell(void)=0
static string_vector get_info(int fid)
Definition: oct-stream.cc:4189
octave_idx_type numel(void) const
Number of elements in the array.
Definition: Array.h:275
static octave_idx_type nn
Definition: DASPK.cc:71
static octave_stream_list * instance
Definition: oct-stream.h:718
std::string gets(octave_idx_type max_len, bool &err, const std::string &who)
Definition: oct-stream.cc:2910
bool is_scalar_type(void) const
Definition: ov.h:657
bool is_open(void) const
Definition: oct-stream.cc:3143
int seek(off_t offset, int origin)
Definition: oct-stream.cc:2995
void do_clear(bool flush=true)
Definition: oct-stream.cc:4364
void add_elt_to_list(int args, const std::string &flags, int fw, int prec, char type, char modifier, octave_idx_type &num_elts)
Definition: oct-stream.cc:677
bool is_defined(void) const
Definition: ov.h:520
octave_value(* conv_fptr)(std::list< void * > &input_buf_list, octave_idx_type input_buf_elts, octave_idx_type elts_read, octave_idx_type nr, octave_idx_type nc, bool swap, bool do_float_fmt_conv, bool do_NA_conv, oct_mach_info::float_format from_flt_fmt)
Definition: oct-stream.cc:3237
virtual std::istream * input_stream(void)
Definition: oct-stream.h:367
static std::string switch_to_g_format(const printf_format_elt *elt)
Definition: oct-stream.cc:2490
octave_stream do_lookup(int fid, const std::string &who=std::string()) const
Definition: oct-stream.cc:4264
octave_base_stream * rep
Definition: oct-stream.h:640
octave_stream_list(void)
Definition: oct-stream.h:679
FloatComplex(* fptr)(const FloatComplex &, float, int, octave_idx_type &)
Definition: lo-specfun.cc:1732
~scanf_format_list(void)
Definition: oct-stream.cc:236
static bool convert_data(const T *data, void *conv_data, octave_idx_type n_elts, oct_data_conv::data_type output_type, oct_mach_info::float_format flt_fmt)
Definition: oct-stream.cc:3625
void error(const char *fmt,...)
Definition: error.cc:476
bool forced_interactive
Definition: input.cc:107
octave_value get_next_value(char type=0)
Definition: oct-stream.cc:2223
octave_idx_type nconv
Definition: oct-stream.h:158
static bool instance_ok(void)
Definition: oct-stream.cc:4129
bool exhausted(void)
Definition: oct-stream.cc:2198
void finish_conversion(const std::string &s, size_t &i, int args, const std::string &flags, int fw, int prec, char modifier, char &type, octave_idx_type &num_elts)
Definition: oct-stream.cc:817
STL namespace.
virtual std::string name(void) const =0
octave_value scanf(const std::string &fmt, const Array< double > &size, octave_idx_type &count, const std::string &who)
Definition: oct-stream.cc:1880
const char * text
Definition: oct-stream.h:83
bool xisinf(double x)
Definition: lo-mappers.cc:160
off_t skipl(off_t count, bool &err, const std::string &who)
Definition: oct-stream.cc:2950
printf_value_cache(const octave_value_list &args, const std::string &who)
Definition: oct-stream.cc:2171
bool ok(void) const
Definition: oct-stream.h:404
octave_value do_scanf(scanf_format_list &fmt_list, octave_idx_type nr, octave_idx_type nc, bool one_elt_size_spec, octave_idx_type &count, const std::string &who)
Definition: oct-stream.cc:1491
octave_value isinf(void) const
Definition: ov.h:1186
bool is_cell(void) const
Definition: ov.h:529
#define lo_ieee_isinf(x)
Definition: lo-ieee.h:105
static int left
Definition: randmtzig.c:189
int mode(void) const
Definition: oct-stream.cc:4067
int do_remove(int fid, const std::string &who=std::string())
Definition: oct-stream.cc:4306
double scalar_value(bool frc_str_conv=false) const
Definition: ov.h:765
std::string char_class
Definition: oct-stream.h:99
#define BEGIN_S_CONVERSION()
Definition: oct-stream.cc:1355
#define DO_WHITESPACE_CONVERSION()
Definition: oct-stream.cc:1277
int do_get_file_number(const octave_value &fid) const
Definition: oct-stream.cc:4486
#define OCTAVE_SCAN(is, fmt, arg)
Definition: oct-stream.cc:1105
const octave_value_list values
Definition: oct-stream.cc:2202
std::string flags
Definition: oct-stream.h:234
std::istream * input_stream(void)
Definition: oct-stream.h:625
#define SEEK_CUR
octave_idx_type nconv
Definition: oct-stream.h:292
scanf_format_list(const std::string &fmt=std::string())
Definition: oct-stream.cc:157
bool all_numeric_conversions(void)
Definition: oct-stream.cc:548
void do_double_format_conversion(void *data, octave_idx_type len, oct_mach_info::float_format from_fmt, oct_mach_info::float_format to_fmt)
Definition: data-conv.cc:661
static size_t do_printf_string(std::ostream &os, const printf_format_elt *elt, int nsa, int sa_1, int sa_2, const std::string &arg, const std::string &who)
Definition: oct-stream.cc:2395
static bool ok_for_signed_int_conv(const octave_value &val)
Definition: oct-stream.cc:2433
F77_RET_T const double const double double * d
Array< printf_format_elt * > list
Definition: oct-stream.h:299
#define lo_ieee_isnan(x)
Definition: lo-ieee.h:101
size_t octave_format(std::ostream &os, const char *fmt,...)
Definition: utils.cc:1286
virtual std::ostream * output_stream(void)
Definition: oct-stream.h:373
printf_format_list(const std::string &fmt=std::string())
Definition: oct-stream.cc:578
int printf(const std::string &fmt, const octave_value_list &args, const std::string &who)
Definition: oct-stream.cc:3964
static int insert(octave_stream &os)
Definition: oct-stream.cc:4152
std::istream & octave_scan_1(std::istream &is, const scanf_format_elt &fmt, T *valptr)
Definition: oct-stream.cc:1109
std::istream & octave_scan(std::istream &is, const scanf_format_elt &fmt, T *valptr)
Definition: oct-stream.cc:1174
const scanf_format_elt * next(bool cycle=true)
Definition: oct-stream.h:130
static int remove(int fid, const std::string &who=std::string())
Definition: oct-stream.cc:4170
static octave_value convert_and_copy(std::list< void * > &input_buf_list, octave_idx_type input_buf_elts, octave_idx_type elts_read, octave_idx_type nr, octave_idx_type nc, bool swap, bool do_float_fmt_conv, bool do_NA_conv, oct_mach_info::float_format from_flt_fmt)
Definition: oct-stream.cc:3162
static void gripe_invalid_file_id(int fid, const std::string &who)
Definition: oct-stream.cc:4255
bool interactive
Definition: input.cc:103
octave_value convert_to_str(bool pad=false, bool force=false, char type= '\'') const
Definition: ov.h:1017
octave_idx_type numel(const octave_value_list &idx)
Definition: ov.h:395
static int convert_to_valid_int(const octave_value &tc, int &conv_err)
Definition: oct-stream.cc:62
std::string string_value(bool force=false) const
Definition: ov.h:897
int do_numeric_printf_conv(std::ostream &os, const printf_format_elt *elt, int nsa, int sa_1, int sa_2, const octave_value &val, const std::string &who)
Definition: oct-stream.cc:2500
void clear(void)
Definition: oct-stream.cc:906
bool all_character_conversions(void)
Definition: oct-stream.cc:518
static void add(fptr f)
std::string errmsg
Definition: oct-stream.h:448
void resize(octave_idx_type n, const std::string &rfv=std::string())
Definition: str-vec.h:91
bool write_bytes(const void *data, size_t n_elts)
Definition: oct-stream.cc:3725
static void convert_chars(const void *data, void *conv_data, octave_idx_type n_elts)
Definition: oct-stream.cc:3576
bool is_string(void) const
Definition: ov.h:562
std::string do_gets(octave_idx_type max_len, bool &err, bool strip_newline, const std::string &who)
Definition: oct-stream.cc:929
const T * data(void) const
Definition: Array.h:479
int do_printf_conv(std::ostream &os, const char *fmt, int nsa, int sa_1, int sa_2, T arg, const std::string &who)
Definition: oct-stream.cc:2367
int error_state
Definition: error.cc:101
int mode(void) const
Definition: oct-stream.h:412
bool do_oscanf(const scanf_format_elt *elt, octave_value &, const std::string &who)
Definition: oct-stream.cc:1917
void resize(const dim_vector &dv, const T &rfv)
Definition: Array.cc:1033
#define SEEK_END
int puts(const std::string &s, const std::string &who)
Definition: oct-stream.cc:4001
static void clear(bool flush=true)
Definition: oct-stream.cc:4182
#define panic_impossible()
Definition: error.h:33
int do_printf(printf_format_list &fmt_list, const octave_value_list &args, const std::string &who)
Definition: oct-stream.cc:2625
int flush(void)
Definition: oct-stream.cc:2859
int puts(const std::string &s, const std::string &who)
Definition: oct-stream.cc:2761
std::string error(bool clear, int &err_num)
Definition: oct-stream.cc:4045
std::ostream * output_stream(void)
Definition: oct-stream.h:630
virtual int file_number(void) const
Definition: oct-stream.h:390
static void cleanup_instance(void)
Definition: oct-stream.h:720
octave_value_list oscanf(const std::string &fmt, const std::string &who)
Definition: oct-stream.cc:3929
static bool words_big_endian(void)
Definition: mach-info.cc:171
static bool ok_for_unsigned_int_conv(const octave_value &val)
Definition: oct-stream.cc:2463
Definition: dMatrix.h:35
size_t size(T const (&)[z])
Definition: help.cc:103
OCTAVE_API double D_NINT(double x)
Definition: lo-mappers.h:240
void process_conversion(const std::string &s, size_t &i, size_t n, int &args, std::string &flags, int &fw, int &prec, char &modifier, char &type, octave_idx_type &num_elts)
Definition: oct-stream.cc:703
octave_value scanf(const std::string &fmt, const Array< double > &size, octave_idx_type &count, const std::string &who)
Definition: oct-stream.cc:3892
int NINT(double x)
Definition: lo-mappers.cc:657
oct_mach_info::float_format float_format(void) const
Definition: oct-stream.h:414
const scanf_format_elt * first(void)
Definition: oct-stream.h:121
off_t tell(void)
Definition: oct-stream.cc:3126
int write(octave_stream &os, int block_size, oct_data_conv::data_type output_type, int skip, oct_mach_info::float_format flt_fmt) const
Definition: ov.cc:1956
octave_idx_type num_conversions(void)
Definition: oct-stream.h:112
std::ostringstream * buf
Definition: oct-stream.h:302
T value(void) const
Definition: oct-inttypes.h:870
std::string error(bool clear, int &err_num)
Definition: oct-stream.cc:2801
bool stream_ok(bool clear=true) const
Definition: oct-stream.h:642
double arg(double x)
Definition: lo-mappers.h:37
static bool is_nan_or_inf(const octave_value &val)
Definition: oct-stream.cc:2424
~octave_stream(void)
Definition: oct-stream.cc:2828
bool is_map(void) const
Definition: ov.h:574
bool is_true(void) const
Definition: ov.h:671
int do_insert(octave_stream &os)
Definition: oct-stream.cc:4220
Handles the reference counting for all the derived classes.
Definition: Array.h:45
octave_value curr_val
Definition: oct-stream.cc:2208
charNDArray max(char d, const charNDArray &m)
Definition: chNDArray.cc:233
void add_elt_to_list(int width, bool discard, char type, char modifier, octave_idx_type &num_elts, const std::string &char_class=std::string())
Definition: oct-stream.cc:248
octave_stream(octave_base_stream *bs=0)
Definition: oct-stream.cc:2821
octave_idx_type length(void) const
Number of elements in the array.
Definition: Array.h:267
bool is_sq_string(void) const
Definition: ov.h:565
NDArray array_value(bool frc_str_conv=false) const
Definition: ov.h:779
std::string undo_string_escapes(const std::string &s)
Definition: utils.cc:802
const char * text
Definition: oct-stream.h:222
const printf_format_elt * next(bool cycle=true)
Definition: oct-stream.h:265
octave_value_list oscanf(const std::string &fmt, const std::string &who)
Definition: oct-stream.cc:2066
F77_RET_T const octave_idx_type const octave_idx_type const octave_idx_type const double const double octave_idx_type double * V
Definition: CmplxGEPBAL.cc:49
bool is_valid(void) const
Definition: oct-stream.h:611
octave_stream & operator=(const octave_stream &)
Definition: oct-stream.cc:2842
bool eof(void) const
Definition: oct-stream.cc:4034
std::string getl(octave_idx_type max_len, bool &err, const std::string &who)
Definition: oct-stream.cc:1032
octave_idx_type num_conversions(void)
Definition: oct-stream.h:254
static std::string list_open_files(void)
Definition: oct-stream.cc:4201
octave_idx_type write(const octave_value &data, octave_idx_type block_size, oct_data_conv::data_type output_type, octave_idx_type skip, oct_mach_info::float_format flt_fmt)
Definition: oct-stream.cc:3546
static octave_value open_file_numbers(void)
Definition: oct-stream.cc:4207
int __lo_ieee_is_old_NA(double x)
Definition: lo-ieee.cc:92
octave_refcount< octave_idx_type > count
Definition: oct-stream.h:432
std::string do_string_escapes(const std::string &s)
Definition: utils.cc:618
#define BEGIN_C_CONVERSION()
Definition: oct-stream.cc:1335
octave_value finalize_read(std::list< void * > &input_buf_list, octave_idx_type input_buf_elts, octave_idx_type elts_read, octave_idx_type nr, octave_idx_type nc, oct_data_conv::data_type input_type, oct_data_conv::data_type output_type, oct_mach_info::float_format ffmt)
Definition: oct-stream.cc:3262
int finish_conversion(const std::string &s, size_t &i, size_t n, int &width, bool discard, char &type, char modifier, octave_idx_type &num_elts)
Definition: oct-stream.cc:413
octave_int64 int64_scalar_value(void) const
Definition: ov.h:855
#define SEEK_SET
string_vector do_get_info(int fid) const
Definition: oct-stream.cc:4391
#define OCTAVE_LOCAL_BUFFER(T, buf, size)
Definition: oct-locbuf.h:197
oct_mach_info::float_format float_format(void) const
Definition: oct-stream.cc:4078
static int get_size(double d, const std::string &who)
Definition: oct-stream.cc:91
bool is_uint64_type(void) const
Definition: ov.h:640
ostrl_map::const_iterator lookup_cache
Definition: oct-stream.h:716
void resize(octave_idx_type n, const octave_value &rfv=octave_value())
Definition: oct-obj.h:93
#define FILL_TABLE_ROW(T, V)
Definition: oct-stream.cc:3245
Array< scanf_format_elt * > list
Definition: oct-stream.h:165
void close(void)
Definition: oct-stream.cc:3154
octave_uint64 uint64_scalar_value(void) const
Definition: ov.h:867
octave_value fast_elem_extract(octave_idx_type n) const
Definition: ov.h:1232
std::ostringstream * buf
Definition: oct-stream.h:168
int file_number(void)
Definition: oct-stream.h:609
void clearerr(void)
Definition: oct-stream.cc:913
void do_scanf_conv(std::istream &is, const scanf_format_elt &fmt, T valptr, Matrix &mval, double *data, octave_idx_type &idx, octave_idx_type &conversion_count, octave_idx_type nr, octave_idx_type max_size, bool discard)
Definition: oct-stream.cc:1243
octave_idx_type length(void)
Definition: oct-stream.h:119
static MArray< double > const octave_idx_type const octave_idx_type octave_idx_type octave_idx_type octave_idx_type c1
#define FINISH_CHARACTER_CONVERSION()
Definition: oct-stream.cc:1447
const T * fortran_vec(void) const
Definition: Array.h:481
void printme(void) const
Definition: oct-stream.cc:872
std::string name(void) const
Definition: oct-stream.cc:4056
void process_conversion(const std::string &s, size_t &i, size_t n, int &width, bool &discard, char &type, char &modifier, octave_idx_type &num_elts)
Definition: oct-stream.cc:310
std::string gets(octave_idx_type max_len, bool &err, const std::string &who)
Definition: oct-stream.cc:1039
virtual bool eof(void) const =0
void invalid_operation(const std::string &who, const char *rw)
Definition: oct-stream.cc:2814
int printf(const std::string &fmt, const octave_value_list &args, const std::string &who)
Definition: oct-stream.cc:2744
double double_value(bool frc_str_conv=false) const
Definition: ov.h:759
virtual int seek(off_t offset, int origin)=0
std::string getl(octave_idx_type max_len, bool &err, const std::string &who)
Definition: oct-stream.cc:2870
static int get_file_number(const octave_value &fid)
Definition: oct-stream.cc:4214
static size_t data_type_size(data_type dt)
Definition: data-conv.cc:178
octave_value isnan(void) const
Definition: ov.h:1188
void close(void)
Definition: oct-stream.h:381
static std::string mode_as_string(int mode)
Definition: oct-stream.cc:4089
std::string do_list_open_files(void) const
Definition: oct-stream.cc:4429
#define BEGIN_CHAR_CLASS_CONVERSION()
Definition: oct-stream.cc:1403
#define INSTANTIATE_WRITE(T)
Definition: oct-stream.cc:3862
return octave_value(v1.char_array_value().concat(v2.char_array_value(), ra_idx),((a1.is_sq_string()||a2.is_sq_string())? '\'': '"'))
static void convert_ints(const T *data, void *conv_data, octave_idx_type n_elts, bool swap)
Definition: oct-stream.cc:3588
octave_value do_binary_op(octave_value::binary_op op, const octave_value &v1, const octave_value &v2)
Definition: ov.cc:1978
octave_value do_open_file_numbers(void) const
Definition: oct-stream.cc:4466
void clearerr(void)
Definition: oct-stream.h:635
off_t skipl(off_t count, bool &err, const std::string &who)
Definition: oct-stream.cc:1046
bool is_integer_type(void) const
Definition: ov.h:648