GNU Octave  9.1.0
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
oct-stream.h
Go to the documentation of this file.
1 ////////////////////////////////////////////////////////////////////////
2 //
3 // Copyright (C) 1996-2024 The Octave Project Developers
4 //
5 // See the file COPYRIGHT.md in the top-level directory of this
6 // distribution or <https://octave.org/copyright/>.
7 //
8 // This file is part of Octave.
9 //
10 // Octave is free software: you can redistribute it and/or modify it
11 // under the terms of the GNU General Public License as published by
12 // the Free Software Foundation, either version 3 of the License, or
13 // (at your option) any later version.
14 //
15 // Octave is distributed in the hope that it will be useful, but
16 // WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 // GNU General Public License for more details.
19 //
20 // You should have received a copy of the GNU General Public License
21 // along with Octave; see the file COPYING. If not, see
22 // <https://www.gnu.org/licenses/>.
23 //
24 ////////////////////////////////////////////////////////////////////////
25 
26 #if ! defined (octave_oct_stream_h)
27 #define octave_oct_stream_h 1
28 
29 #include "octave-config.h"
30 
31 #include <ios>
32 #include <iosfwd>
33 #include <list>
34 #include <map>
35 #include <memory>
36 #include <string>
37 
38 #include "oct-string.h"
39 
40 // These only appear as reference arguments or return values.
41 
42 class Cell;
43 class octave_value;
44 class octave_value_list;
45 class string_vector;
46 
47 #include "Array-fwd.h"
48 #include "data-conv.h"
49 #include "mach-info.h"
50 
52 
53 class interpreter;
54 
55 // These are only needed as arguments to private functions, so they
56 // are also treated as private.
57 
58 class scanf_format_elt;
59 class scanf_format_list;
60 
61 class printf_format_elt;
62 class printf_format_list;
63 
64 // Provide an interface for Octave streams.
65 
66 class
67 OCTINTERP_API
69 {
70  friend class stream;
71 
72 public:
73 
74  base_stream (std::ios::openmode arg_md = std::ios::in | std::ios::out,
76  const std::string& encoding = "utf-8")
77  : m_mode (arg_md), m_flt_fmt (ff), m_encoding (encoding),
78  m_conv_ostream (nullptr), m_fail (false), m_open_state (true),
79  m_errmsg ()
80  { }
81 
82  OCTAVE_DISABLE_COPY_MOVE (base_stream)
83 
84  virtual ~base_stream () = default;
85 
86  // The remaining functions are not specific to input or output only,
87  // and must be provided by the derived classes.
88 
89  // Position a stream at OFFSET relative to ORIGIN.
90 
91  virtual int seek (off_t offset, int origin) = 0;
92 
93  // Return current stream position.
94 
95  virtual off_t tell () = 0;
96 
97  // Return TRUE if EOF has been reached on this stream.
98 
99  virtual bool eof () const = 0;
100 
101  // The name of the file.
102 
103  virtual std::string name () const = 0;
104 
105  // If the derived class provides this function and it returns a
106  // pointer to a valid istream, scanf(), read(), getl(), and gets()
107  // will automatically work for this stream.
108 
109  virtual std::istream * input_stream () { return nullptr; }
110 
111  // If the derived class provides this function and it returns a
112  // pointer to a valid ostream, flush(), write(), and printf() will
113  // automatically work for this stream.
114 
115  virtual std::ostream * output_stream () { return nullptr; }
116 
117  // Return either the original output stream or one wrapped with the
118  // encoding facet.
119 
120  std::ostream * preferred_output_stream ()
121  {
122  if (! m_encoding.compare ("utf-8"))
123  return output_stream ();
124 
125  if (m_conv_ostream)
126  return m_conv_ostream.get ();
127 
128  // wrap the output stream with encoding conversion facet
129  std::ostream *os = output_stream ();
130  if (os && *os)
131  {
132  // FIXME: Using std::make_unique could simplify the following
133  // expressions once we require C++14.
134  m_converter
135  = std::unique_ptr<std::wbuffer_convert<convfacet_u8, char>>
136  (new std::wbuffer_convert<convfacet_u8, char>
137  (os->rdbuf (), new convfacet_u8 (m_encoding)));
138  m_conv_ostream = std::unique_ptr<std::ostream>
139  (new std::ostream (m_converter.get ()));
140  }
141 
142  return (m_conv_ostream ? m_conv_ostream.get () : output_stream ());
143  }
144 
145  // Return TRUE if this stream is open.
146 
147  bool is_open () const { return m_open_state; }
148 
149  virtual void do_close () { }
150 
151  void close ()
152  {
153  if (is_open ())
154  {
155  m_open_state = false;
156  do_close ();
157  }
158  }
159 
160  virtual int file_number () const
161  {
162  // Kluge alert!
163 
164  if (name () == "stdin")
165  return 0;
166  else if (name () == "stdout")
167  return 1;
168  else if (name () == "stderr")
169  return 2;
170  else
171  return -1;
172  }
173 
174  bool ok () const { return ! m_fail; }
175 
176  // Return current error message for this stream.
177 
178  std::string error (bool clear, int& err_num);
179 
180 protected:
181 
182  int mode () const { return m_mode; }
183 
184  mach_info::float_format float_format () const { return m_flt_fmt; }
185 
186  std::string encoding () const { return m_encoding; }
187 
188  // Set current error state and set fail to TRUE.
189 
190  OCTINTERP_API void error (const std::string& msg);
191  OCTINTERP_API void error (const std::string& who, const std::string& msg);
192 
193  // Clear any error message and set fail to FALSE.
194 
195  OCTINTERP_API void clear ();
196 
197  // Clear stream state.
198 
199  OCTINTERP_API void clearerr ();
200 
201 private:
202 
203  // The permission bits for the file. Should be some combination of
204  // std::ios::open_mode bits.
205  int m_mode;
206 
207  // Data format.
208  mach_info::float_format m_flt_fmt;
209 
210  // Code page
211  std::string m_encoding;
212 
213  // encoding conversion facet
214  typedef string::deletable_facet<string::codecvt_u8> convfacet_u8;
215 
216  std::unique_ptr<std::wbuffer_convert<convfacet_u8, char>> m_converter;
217 
218  // wrappers for encoding conversion
219  // std::unique_ptr<std::istream> m_conv_istream;
220 
221  std::unique_ptr<std::ostream> m_conv_ostream;
222 
223  // TRUE if an error has occurred.
224  bool m_fail;
225 
226  // TRUE if this stream is open.
227  bool m_open_state;
228 
229  // Should contain error message if fail is TRUE.
230  std::string m_errmsg;
231 
232  // Functions that are defined for all input streams (input streams
233  // are those that define is).
234 
235  OCTINTERP_API std::string
236  do_gets (octave_idx_type max_len, bool& err, bool strip_newline,
237  const std::string& who /* = "gets" */);
238 
239  OCTINTERP_API std::string
240  getl (octave_idx_type max_len, bool& err,
241  const std::string& who /* = "getl" */);
242  OCTINTERP_API std::string
243  gets (octave_idx_type max_len, bool& err,
244  const std::string& who /* = "gets" */);
245  OCTINTERP_API off_t
246  skipl (off_t count, bool& err, const std::string& who /* = "skipl" */);
247 
248  OCTINTERP_API octave_value
249  do_scanf (scanf_format_list& fmt_list, octave_idx_type nr,
250  octave_idx_type nc, bool one_elt_size_spec,
251  octave_idx_type& count, const std::string& who /* = "scanf" */);
252 
253  OCTINTERP_API octave_value
254  scanf (const std::string& fmt, const Array<double>& size,
255  octave_idx_type& count, const std::string& who /* = "scanf" */);
256 
257  OCTINTERP_API bool
258  do_oscanf (const scanf_format_elt *elt, octave_value&,
259  const std::string& who /* = "scanf" */);
260 
261  OCTINTERP_API octave_value_list
262  oscanf (const std::string& fmt, const std::string& who /* = "scanf" */);
263 
264  OCTINTERP_API octave_value
265  do_textscan (const std::string& fmt, octave_idx_type ntimes,
266  const octave_value_list& options,
267  const std::string& who, octave_idx_type& count);
268 
269  // Functions that are defined for all output streams (output streams
270  // are those that define os).
271 
272  OCTINTERP_API int flush ();
273 
274  OCTINTERP_API int
275  do_numeric_printf_conv (std::ostream& os, const printf_format_elt *elt,
276  int nsa, int sa_1, int sa_2,
277  const octave_value& val,
278  const std::string& who);
279 
280  OCTINTERP_API void field_width_error (const std::string& who) const;
281 
282  OCTINTERP_API int
283  do_printf (printf_format_list& fmt_list, const octave_value_list& args,
284  const std::string& who /* = "printf" */);
285 
286  OCTINTERP_API int
287  printf (const std::string& fmt, const octave_value_list& args,
288  const std::string& who /* = "printf" */);
289 
290  OCTINTERP_API int
291  puts (const std::string& s, const std::string& who /* = "puts" */);
292 
293  // We can always do this in terms of seek(), so the derived class
294  // only has to provide that.
295 
296  OCTINTERP_API void
297  invalid_operation (const std::string& who, const char *rw);
298 };
299 
300 class
301 OCTINTERP_API
302 stream
303 {
304 public:
305 
306  // BS must be allocated with new or nullptr.
307  stream (base_stream *bs = nullptr) : m_rep (bs) { }
308 
309  stream (const stream&) = default;
310 
311  stream& operator = (const stream&) = default;
312 
313  ~stream () = default;
314 
315  OCTINTERP_API int flush ();
316 
317  OCTINTERP_API std::string
318  getl (octave_idx_type max_len, bool& err,
319  const std::string& who /* = "getl" */);
320 
321  OCTINTERP_API std::string
322  getl (const octave_value& max_len, bool& err,
323  const std::string& who /* = "getl" */);
324 
325  OCTINTERP_API std::string
326  gets (octave_idx_type max_len, bool& err,
327  const std::string& who /* = "gets" */);
328 
329  OCTINTERP_API std::string
330  gets (const octave_value& max_len, bool& err,
331  const std::string& who /* = "gets" */);
332 
333  OCTINTERP_API off_t
334  skipl (off_t count, bool& err, const std::string& who /* = "skipl" */);
335 
336  OCTINTERP_API off_t
337  skipl (const octave_value& count, bool& err,
338  const std::string& who /* = "skipl" */);
339 
340  OCTINTERP_API int seek (off_t offset, int origin);
341 
342  OCTINTERP_API int
343  seek (const octave_value& offset, const octave_value& origin);
344 
345  OCTINTERP_API off_t tell ();
346 
347  OCTINTERP_API int rewind ();
348 
349  OCTINTERP_API bool is_open () const;
350 
351  OCTINTERP_API void close ();
352 
353  OCTINTERP_API octave_value
354  read (const Array<double>& size, octave_idx_type block_size,
355  oct_data_conv::data_type input_type,
356  oct_data_conv::data_type output_type,
358  octave_idx_type& count);
359 
360  OCTINTERP_API octave_idx_type
361  write (const octave_value& data, octave_idx_type block_size,
362  oct_data_conv::data_type output_type,
364 
365  OCTINTERP_API bool write_bytes (const void *data, std::size_t n_elts);
366 
367  OCTINTERP_API bool skip_bytes (std::size_t n_elts);
368 
369  template <typename T>
370  OCTINTERP_API octave_idx_type
371  write (const Array<T>& data, octave_idx_type block_size,
372  oct_data_conv::data_type output_type,
374 
375  OCTINTERP_API octave_value
376  scanf (const std::string& fmt, const Array<double>& size,
377  octave_idx_type& count, const std::string& who /* = "scanf" */);
378 
379  OCTINTERP_API octave_value
380  scanf (const octave_value& fmt, const Array<double>& size,
381  octave_idx_type& count, const std::string& who /* = "scanf" */);
382 
383  OCTINTERP_API octave_value_list
384  oscanf (const std::string& fmt, const std::string& who /* = "scanf" */);
385 
386  OCTINTERP_API octave_value_list
387  oscanf (const octave_value& fmt, const std::string& who /* = "scanf" */);
388 
389  OCTINTERP_API octave_value
390  textscan (const std::string& fmt, octave_idx_type ntimes,
391  const octave_value_list& options,
392  const std::string& who, octave_idx_type& count);
393 
394  OCTINTERP_API int
395  printf (const std::string& fmt, const octave_value_list& args,
396  const std::string& who /* = "printf" */);
397 
398  OCTINTERP_API int
399  printf (const octave_value& fmt, const octave_value_list& args,
400  const std::string& who /* = "printf" */);
401 
402  OCTINTERP_API int
403  puts (const std::string& s, const std::string& who /* = "puts" */);
404  OCTINTERP_API int
405  puts (const octave_value& s, const std::string& who /* = "puts" */);
406 
407  OCTINTERP_API bool eof () const;
408 
409  OCTINTERP_API std::string error (bool clear, int& err_num);
410 
411  std::string error (bool clear = false)
412  {
413  int err_num;
414  return error (clear, err_num);
415  }
416 
417  // Set the error message and state.
418 
419  void error (const std::string& msg)
420  {
421  if (m_rep)
422  m_rep->error (msg);
423  }
424 
425  void error (const char *msg) { error (std::string (msg)); }
426 
427  int file_number () { return m_rep ? m_rep->file_number () : -1; }
428 
429  bool is_valid () const { return bool (m_rep); }
430 
431  bool ok () const { return m_rep && m_rep->ok (); }
432 
433  operator bool () const { return ok (); }
434 
435  OCTINTERP_API std::string name () const;
436 
437  OCTINTERP_API int mode () const;
438 
439  OCTINTERP_API mach_info::float_format float_format () const;
440 
441  OCTINTERP_API static std::string mode_as_string (int mode);
442 
443  std::string encoding ()
444  {
445  return m_rep ? m_rep->encoding () : std::string ();
446  }
447 
448  std::istream * input_stream ()
449  {
450  return m_rep ? m_rep->input_stream () : nullptr;
451  }
452 
453  std::ostream * output_stream ()
454  {
455  return (m_rep ? m_rep->output_stream () : nullptr);
456  }
457 
458  std::ostream * preferred_output_stream ()
459  {
460  // return output stream with encoding facet if applicable
461  return (m_rep ? m_rep->preferred_output_stream () : nullptr);
462  }
463 
464  void clearerr () { if (m_rep) m_rep->clearerr (); }
465 
466 private:
467 
468  // The actual representation of this stream.
469  std::shared_ptr<base_stream> m_rep;
470 
471  bool stream_ok (bool clear = true) const
472  {
473  bool retval = true;
474 
475  if (m_rep)
476  {
477  if (clear)
478  m_rep->clear ();
479  }
480  else
481  retval = false;
482 
483  return retval;
484  }
485 
486  void invalid_operation (const std::string& who, const char *rw)
487  {
488  if (m_rep)
489  m_rep->invalid_operation (who, rw);
490  }
491 
492  OCTINTERP_API octave_value
493  finalize_read (std::list<void *>& input_buf_list,
494  octave_idx_type input_buf_elts,
495  octave_idx_type elts_read,
497  oct_data_conv::data_type input_type,
498  oct_data_conv::data_type output_type,
500 };
501 
502 class
503 OCTINTERP_API
505 {
506 public:
507 
508  OCTINTERP_API stream_list (interpreter& interp);
509 
510  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (stream_list)
511 
512  OCTINTERP_API ~stream_list ();
513 
514  OCTINTERP_API int insert (stream& os);
515 
516  OCTINTERP_API stream lookup (int fid, const std::string& who = "") const;
517  OCTINTERP_API stream
518  lookup (const octave_value& fid, const std::string& who = "") const;
519 
520  OCTINTERP_API int remove (int fid, const std::string& who = "");
521  OCTINTERP_API int remove (const octave_value& fid,
522  const std::string& who = "");
523 
524  OCTINTERP_API void clear (bool flush = true);
525 
526  OCTINTERP_API string_vector get_info (int fid) const;
527  OCTINTERP_API string_vector get_info (const octave_value& fid) const;
528 
529  OCTINTERP_API std::string list_open_files () const;
530 
531  OCTINTERP_API octave_value open_file_numbers () const;
532 
533  OCTINTERP_API int get_file_number (const octave_value& fid) const;
534 
535  OCTINTERP_API octave_value stdin_file () const;
536  OCTINTERP_API octave_value stdout_file () const;
537  OCTINTERP_API octave_value stderr_file () const;
538 
539 private:
540 
541  typedef std::map<int, stream> ostrl_map;
542 
543  ostrl_map m_list;
544 
545  mutable ostrl_map::const_iterator m_lookup_cache;
546 
547  int m_stdin_file;
548  int m_stdout_file;
549  int m_stderr_file;
550 };
551 
552 OCTAVE_END_NAMESPACE(octave)
553 
554 #endif
octave_idx_type lookup(const T *x, octave_idx_type n, T y)
Definition: Cell.h:43
base_stream(std::ios::openmode arg_md=std::ios::in|std::ios::out, mach_info::float_format ff=mach_info::native_float_format(), const std::string &encoding="utf-8")
Definition: oct-stream.h:74
bool is_open() const
Definition: oct-stream.h:147
void error(const std::string &who, const std::string &msg)
mach_info::float_format float_format() const
Definition: oct-stream.h:184
bool ok() const
Definition: oct-stream.h:174
void close()
Definition: oct-stream.h:151
virtual std::ostream * output_stream()
Definition: oct-stream.h:115
virtual void do_close()
Definition: oct-stream.h:149
std::string encoding() const
Definition: oct-stream.h:186
std::string error(bool clear, int &err_num)
void error(const std::string &msg)
virtual int file_number() const
Definition: oct-stream.h:160
int mode() const
Definition: oct-stream.h:182
std::ostream * preferred_output_stream()
Definition: oct-stream.h:120
std::string error(bool clear=false)
Definition: oct-stream.h:411
int file_number()
Definition: oct-stream.h:427
off_t tell()
Definition: oct-stream.cc:6367
int flush()
Definition: oct-stream.cc:6127
std::string name() const
Definition: oct-stream.cc:7314
bool is_valid() const
Definition: oct-stream.h:429
void error(const std::string &msg)
Definition: oct-stream.h:419
static std::string mode_as_string(int mode)
Definition: oct-stream.cc:7347
stream & operator=(const stream &)=default
octave_value scanf(const std::string &fmt, const Array< double > &size, octave_idx_type &count, const std::string &who)
Definition: oct-stream.cc:7144
std::istream * input_stream()
Definition: oct-stream.h:448
std::string gets(octave_idx_type max_len, bool &err, const std::string &who)
Definition: oct-stream.cc:6173
~stream()=default
int rewind()
Definition: oct-stream.cc:6378
void clearerr()
Definition: oct-stream.h:464
bool skip_bytes(std::size_t n_elts)
Definition: oct-stream.cc:6998
std::ostream * preferred_output_stream()
Definition: oct-stream.h:458
std::ostream * output_stream()
Definition: oct-stream.h:453
off_t skipl(off_t count, bool &err, const std::string &who)
Definition: oct-stream.cc:6208
octave_value textscan(const std::string &fmt, octave_idx_type ntimes, const octave_value_list &options, const std::string &who, octave_idx_type &count)
Definition: oct-stream.cc:7214
bool is_open() const
Definition: oct-stream.cc:6384
int mode() const
Definition: oct-stream.cc:7325
stream(base_stream *bs=nullptr)
Definition: oct-stream.h:307
bool eof() const
Definition: oct-stream.cc:7292
int puts(const std::string &s, const std::string &who)
Definition: oct-stream.cc:7260
int printf(const std::string &fmt, const octave_value_list &args, const std::string &who)
Definition: oct-stream.cc:7224
void error(const char *msg)
Definition: oct-stream.h:425
bool write_bytes(const void *data, std::size_t n_elts)
Definition: oct-stream.cc:6975
void close()
Definition: oct-stream.cc:6395
int seek(off_t offset, int origin)
Definition: oct-stream.cc:6250
stream(const stream &)=default
octave_value_list oscanf(const std::string &fmt, const std::string &who)
Definition: oct-stream.cc:7180
std::string getl(octave_idx_type max_len, bool &err, const std::string &who)
Definition: oct-stream.cc:6138
std::string encoding()
Definition: oct-stream.h:443
bool ok() const
Definition: oct-stream.h:431
std::string error(bool clear, int &err_num)
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, mach_info::float_format flt_fmt, octave_idx_type &count)
Definition: oct-stream.cc:6609
octave_idx_type write(const octave_value &data, octave_idx_type block_size, oct_data_conv::data_type output_type, octave_idx_type skip, mach_info::float_format flt_fmt)
Definition: oct-stream.cc:6802
OCTAVE_BEGIN_NAMESPACE(octave) static octave_value daspk_fcn
void() error(const char *fmt,...)
Definition: error.cc:988
float_format native_float_format()
Definition: mach-info.cc:67
float_format
Definition: mach-info.h:38