GNU Octave  6.2.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-2021 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 // These only appear as reference arguments or return values.
39 
40 template <typename T> class Array;
41 class Cell;
42 class octave_value;
43 class octave_value_list;
44 class string_vector;
45 
46 #include "data-conv.h"
47 #include "mach-info.h"
48 
49 namespace octave
50 {
51  class interpreter;
52 
53  // These are only needed as arguments to private functions, so they
54  // are also treated as private.
55 
56  class scanf_format_elt;
57  class scanf_format_list;
58 
59  class printf_format_elt;
60  class printf_format_list;
61 
62  // Provide an interface for Octave streams.
63 
64  class
65  OCTINTERP_API
67  {
68  friend class stream;
69 
70  public:
71 
72  base_stream (std::ios::openmode arg_md = std::ios::in | std::ios::out,
74  const std::string& encoding = "utf-8")
75  : m_mode (arg_md), m_flt_fmt (ff), m_encoding (encoding),
76  m_fail (false), m_open_state (true), m_errmsg ()
77  { }
78 
79  // No copying!
80 
81  base_stream (const base_stream&) = delete;
82 
83  base_stream& operator = (const base_stream&) = delete;
84 
85  virtual ~base_stream (void) = default;
86 
87  // The remaining functions are not specific to input or output only,
88  // and must be provided by the derived classes.
89 
90  // Position a stream at OFFSET relative to ORIGIN.
91 
92  virtual int seek (off_t offset, int origin) = 0;
93 
94  // Return current stream position.
95 
96  virtual off_t tell (void) = 0;
97 
98  // Return TRUE if EOF has been reached on this stream.
99 
100  virtual bool eof (void) const = 0;
101 
102  // The name of the file.
103 
104  virtual std::string name (void) const = 0;
105 
106  // If the derived class provides this function and it returns a
107  // pointer to a valid istream, scanf(), read(), getl(), and gets()
108  // will automatically work for this stream.
109 
110  virtual std::istream * input_stream (void) { return nullptr; }
111 
112  // If the derived class provides this function and it returns a
113  // pointer to a valid ostream, flush(), write(), and printf() will
114  // automatically work for this stream.
115 
116  virtual std::ostream * output_stream (void) { return nullptr; }
117 
118  // Return TRUE if this stream is open.
119 
120  bool is_open (void) const { return m_open_state; }
121 
122  virtual void do_close (void) { }
123 
124  void close (void)
125  {
126  if (is_open ())
127  {
128  m_open_state = false;
129  do_close ();
130  }
131  }
132 
133  virtual int file_number (void) const
134  {
135  // Kluge alert!
136 
137  if (name () == "stdin")
138  return 0;
139  else if (name () == "stdout")
140  return 1;
141  else if (name () == "stderr")
142  return 2;
143  else
144  return -1;
145  }
146 
147  bool ok (void) const { return ! m_fail; }
148 
149  // Return current error message for this stream.
150 
151  std::string error (bool clear, int& err_num);
152 
153  protected:
154 
155  int mode (void) const { return m_mode; }
156 
157  mach_info::float_format float_format (void) const { return m_flt_fmt; }
158 
159  std::string encoding (void) const { return m_encoding; }
160 
161  // Set current error state and set fail to TRUE.
162 
163  void error (const std::string& msg);
164  void error (const std::string& who, const std::string& msg);
165 
166  // Clear any error message and set fail to FALSE.
167 
168  void clear (void);
169 
170  // Clear stream state.
171 
172  void clearerr (void);
173 
174  private:
175 
176  // The permission bits for the file. Should be some combination of
177  // std::ios::open_mode bits.
178  int m_mode;
179 
180  // Data format.
182 
183  // Code page
184  std::string m_encoding;
185 
186  // TRUE if an error has occurred.
187  bool m_fail;
188 
189  // TRUE if this stream is open.
191 
192  // Should contain error message if fail is TRUE.
193  std::string m_errmsg;
194 
195  // Functions that are defined for all input streams (input streams
196  // are those that define is).
197 
198  std::string do_gets (octave_idx_type max_len, bool& err, bool strip_newline,
199  const std::string& who /* = "gets" */);
200 
201  std::string getl (octave_idx_type max_len, bool& err,
202  const std::string& who /* = "getl" */);
203  std::string gets (octave_idx_type max_len, bool& err,
204  const std::string& who /* = "gets" */);
205  off_t skipl (off_t count, bool& err, const std::string& who /* = "skipl" */);
206 
207  octave_value do_scanf (scanf_format_list& fmt_list, octave_idx_type nr,
208  octave_idx_type nc,
209  bool one_elt_size_spec, octave_idx_type& count,
210  const std::string& who /* = "scanf" */);
211 
212  octave_value scanf (const std::string& fmt, const Array<double>& size,
213  octave_idx_type& count, const std::string& who /* = "scanf" */);
214 
215  bool do_oscanf (const scanf_format_elt *elt, octave_value&,
216  const std::string& who /* = "scanf" */);
217 
218  octave_value_list oscanf (const std::string& fmt,
219  const std::string& who /* = "scanf" */);
220 
221  octave_value do_textscan (const std::string& fmt, octave_idx_type ntimes,
222  const octave_value_list& options,
223  const std::string& who, octave_idx_type& count);
224 
225  // Functions that are defined for all output streams (output streams
226  // are those that define os).
227 
228  int flush (void);
229 
230  int do_numeric_printf_conv (std::ostream& os, const printf_format_elt *elt,
231  int nsa, int sa_1, int sa_2,
232  const octave_value& val,
233  const std::string& who);
234 
235  void field_width_error (const std::string& who) const;
236 
237  int do_printf (printf_format_list& fmt_list, const octave_value_list& args,
238  const std::string& who /* = "printf" */);
239 
240  int printf (const std::string& fmt, const octave_value_list& args,
241  const std::string& who /* = "printf" */);
242 
243  int puts (const std::string& s, const std::string& who /* = "puts" */);
244 
245  // We can always do this in terms of seek(), so the derived class
246  // only has to provide that.
247 
248  void invalid_operation (const std::string& who, const char *rw);
249  };
250 
251  class
252  OCTINTERP_API
253  stream
254  {
255  public:
256 
257  // BS must be allocated with new or nullptr.
258  stream (base_stream *bs = nullptr) : m_rep (bs) { }
259 
260  stream (const stream&) = default;
261 
262  stream& operator = (const stream&) = default;
263 
264  ~stream (void) = default;
265 
266  int flush (void);
267 
268  std::string getl (octave_idx_type max_len, bool& err,
269  const std::string& who /* = "getl" */);
270  std::string getl (const octave_value& max_len, bool& err,
271  const std::string& who /* = "getl" */);
272 
273  std::string gets (octave_idx_type max_len, bool& err,
274  const std::string& who /* = "gets" */);
275  std::string gets (const octave_value& max_len, bool& err,
276  const std::string& who /* = "gets" */);
277 
278  off_t skipl (off_t count, bool& err, const std::string& who /* = "skipl" */);
279  off_t skipl (const octave_value& count, bool& err,
280  const std::string& who /* = "skipl" */);
281 
282  int seek (off_t offset, int origin);
283  int seek (const octave_value& offset, const octave_value& origin);
284 
285  off_t tell (void);
286 
287  int rewind (void);
288 
289  bool is_open (void) const;
290 
291  void close (void);
292 
293  octave_value read (const Array<double>& size, octave_idx_type block_size,
294  oct_data_conv::data_type input_type,
295  oct_data_conv::data_type output_type,
297  octave_idx_type& count);
298 
299  octave_idx_type write (const octave_value& data, octave_idx_type block_size,
300  oct_data_conv::data_type output_type,
301  octave_idx_type skip,
302  mach_info::float_format flt_fmt);
303 
304  bool write_bytes (const void *data, size_t n_elts);
305 
306  bool skip_bytes (size_t n_elts);
307 
308  template <typename T>
309  octave_idx_type write (const Array<T>& data, octave_idx_type block_size,
310  oct_data_conv::data_type output_type,
311  octave_idx_type skip,
312  mach_info::float_format flt_fmt);
313 
314  octave_value scanf (const std::string& fmt, const Array<double>& size,
315  octave_idx_type& count, const std::string& who /* = "scanf" */);
316 
317  octave_value scanf (const octave_value& fmt, const Array<double>& size,
318  octave_idx_type& count, const std::string& who /* = "scanf" */);
319 
320  octave_value_list oscanf (const std::string& fmt,
321  const std::string& who /* = "scanf" */);
322 
323  octave_value_list oscanf (const octave_value& fmt,
324  const std::string& who /* = "scanf" */);
325 
326  octave_value textscan (const std::string& fmt, octave_idx_type ntimes,
327  const octave_value_list& options,
328  const std::string& who, octave_idx_type& count);
329 
330  int printf (const std::string& fmt, const octave_value_list& args,
331  const std::string& who /* = "printf" */);
332 
333  int printf (const octave_value& fmt, const octave_value_list& args,
334  const std::string& who /* = "printf" */);
335 
336  int puts (const std::string& s, const std::string& who /* = "puts" */);
337  int puts (const octave_value& s, const std::string& who /* = "puts" */);
338 
339  bool eof (void) const;
340 
341  std::string error (bool clear, int& err_num);
342 
343  std::string error (bool clear = false)
344  {
345  int err_num;
346  return error (clear, err_num);
347  }
348 
349  // Set the error message and state.
350 
351  void error (const std::string& msg)
352  {
353  if (m_rep)
354  m_rep->error (msg);
355  }
356 
357  void error (const char *msg) { error (std::string (msg)); }
358 
359  int file_number (void) { return m_rep ? m_rep->file_number () : -1; }
360 
361  bool is_valid (void) const { return bool (m_rep); }
362 
363  bool ok (void) const { return m_rep && m_rep->ok (); }
364 
365  operator bool () const { return ok (); }
366 
367  std::string name (void) const;
368 
369  int mode (void) const;
370 
372 
373  static std::string mode_as_string (int mode);
374 
375  std::string encoding (void)
376  {
377  return m_rep ? m_rep->encoding () : std::string ();
378  }
379 
380  std::istream * input_stream (void)
381  {
382  return m_rep ? m_rep->input_stream () : nullptr;
383  }
384 
385  std::ostream * output_stream (void)
386  {
387  return m_rep ? m_rep->output_stream () : nullptr;
388  }
389 
390  void clearerr (void) { if (m_rep) m_rep->clearerr (); }
391 
392  private:
393 
394  // The actual representation of this stream.
395  std::shared_ptr<base_stream> m_rep;
396 
397  bool stream_ok (bool clear = true) const
398  {
399  bool retval = true;
400 
401  if (m_rep)
402  {
403  if (clear)
404  m_rep->clear ();
405  }
406  else
407  retval = false;
408 
409  return retval;
410  }
411 
412  void invalid_operation (const std::string& who, const char *rw)
413  {
414  if (m_rep)
415  m_rep->invalid_operation (who, rw);
416  }
417 
419  finalize_read (std::list<void *>& input_buf_list,
420  octave_idx_type input_buf_elts,
421  octave_idx_type elts_read,
423  oct_data_conv::data_type input_type,
424  oct_data_conv::data_type output_type,
426  };
427 
428  class
429  OCTINTERP_API
431  {
432  public:
433 
434  stream_list (interpreter& interp);
435 
436  stream_list (const stream_list&) = delete;
437  stream_list& operator = (const stream_list&) = delete;
438 
439  ~stream_list (void);
440 
441  int insert (stream& os);
442 
443  stream lookup (int fid, const std::string& who = "") const;
444  stream lookup (const octave_value& fid, const std::string& who = "") const;
445 
446  int remove (int fid, const std::string& who = "");
447  int remove (const octave_value& fid, const std::string& who = "");
448 
449  void clear (bool flush = true);
450 
451  string_vector get_info (int fid) const;
452  string_vector get_info (const octave_value& fid) const;
453 
454  std::string list_open_files (void) const;
455 
456  octave_value open_file_numbers (void) const;
457 
458  int get_file_number (const octave_value& fid) const;
459 
460  octave_value stdin_file (void) const;
461  octave_value stdout_file (void) const;
462  octave_value stderr_file (void) const;
463 
464  private:
465 
466  typedef std::map<int, stream> ostrl_map;
467 
469 
470  mutable ostrl_map::const_iterator m_lookup_cache;
471 
475  };
476 }
477 
478 #endif
octave_idx_type lookup(const T *x, octave_idx_type n, T y)
N Dimensional Array with copy-on-write semantics.
Definition: Array.h:128
void clear(void)
Definition: Array.cc:87
Definition: Cell.h:43
virtual bool eof(void) const =0
std::string m_encoding
Definition: oct-stream.h:184
virtual std::ostream * output_stream(void)
Definition: oct-stream.h:116
bool is_open(void) const
Definition: oct-stream.h:120
virtual void do_close(void)
Definition: oct-stream.h:122
void close(void)
Definition: oct-stream.h:124
std::string m_errmsg
Definition: oct-stream.h:193
bool ok(void) const
Definition: oct-stream.h:147
virtual int seek(off_t offset, int origin)=0
mach_info::float_format float_format(void) const
Definition: oct-stream.h:157
mach_info::float_format m_flt_fmt
Definition: oct-stream.h:181
virtual std::istream * input_stream(void)
Definition: oct-stream.h:110
base_stream(const base_stream &)=delete
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:72
int mode(void) const
Definition: oct-stream.h:155
virtual std::string name(void) const =0
std::string encoding(void) const
Definition: oct-stream.h:159
virtual ~base_stream(void)=default
virtual off_t tell(void)=0
virtual int file_number(void) const
Definition: oct-stream.h:133
ostrl_map::const_iterator m_lookup_cache
Definition: oct-stream.h:470
std::map< int, stream > ostrl_map
Definition: oct-stream.h:466
stream_list(const stream_list &)=delete
void error(const std::string &msg)
Definition: oct-stream.h:351
void invalid_operation(const std::string &who, const char *rw)
Definition: oct-stream.h:412
~stream(void)=default
bool ok(void) const
Definition: oct-stream.h:363
void clearerr(void)
Definition: oct-stream.h:390
std::istream * input_stream(void)
Definition: oct-stream.h:380
bool stream_ok(bool clear=true) const
Definition: oct-stream.h:397
std::shared_ptr< base_stream > m_rep
Definition: oct-stream.h:395
stream(base_stream *bs=nullptr)
Definition: oct-stream.h:258
std::ostream * output_stream(void)
Definition: oct-stream.h:385
bool is_valid(void) const
Definition: oct-stream.h:361
std::string encoding(void)
Definition: oct-stream.h:375
void error(const char *msg)
Definition: oct-stream.h:357
stream(const stream &)=default
int file_number(void)
Definition: oct-stream.h:359
std::string error(bool clear=false)
Definition: oct-stream.h:343
void error(const char *fmt,...)
Definition: error.cc:968
QString name
float_format native_float_format(void)
Definition: mach-info.cc:65
octave_value::octave_value(const Array< char > &chm, char type) return retval
Definition: ov.cc:811