GNU Octave  8.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-2023 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  // No copying!
83 
84  base_stream (const base_stream&) = delete;
85 
86  base_stream& operator = (const base_stream&) = delete;
87 
88  virtual ~base_stream (void) = default;
89 
90  // The remaining functions are not specific to input or output only,
91  // and must be provided by the derived classes.
92 
93  // Position a stream at OFFSET relative to ORIGIN.
94 
95  virtual int seek (off_t offset, int origin) = 0;
96 
97  // Return current stream position.
98 
99  virtual off_t tell (void) = 0;
100 
101  // Return TRUE if EOF has been reached on this stream.
102 
103  virtual bool eof (void) const = 0;
104 
105  // The name of the file.
106 
107  virtual std::string name (void) const = 0;
108 
109  // If the derived class provides this function and it returns a
110  // pointer to a valid istream, scanf(), read(), getl(), and gets()
111  // will automatically work for this stream.
112 
113  virtual std::istream * input_stream (void) { return nullptr; }
114 
115  // If the derived class provides this function and it returns a
116  // pointer to a valid ostream, flush(), write(), and printf() will
117  // automatically work for this stream.
118 
119  virtual std::ostream * output_stream (void) { return nullptr; }
120 
121  // Return either the original output stream or one wrapped with the
122  // encoding facet.
123 
124  std::ostream * preferred_output_stream (void)
125  {
126  if (! m_encoding.compare ("utf-8"))
127  return output_stream ();
128 
129  if (m_conv_ostream)
130  return m_conv_ostream;
131 
132  // wrap the output stream with encoding conversion facet
133  std::ostream *os = output_stream ();
134  if (os && *os)
135  {
136  convfacet_u8 *facet = new convfacet_u8 (m_encoding);
137  std::wbuffer_convert<convfacet_u8, char> *converter
138  = new std::wbuffer_convert<convfacet_u8, char> (os->rdbuf (),
139  facet);
140  m_conv_ostream = new std::ostream (converter);
141  }
142 
143  return (m_conv_ostream ? m_conv_ostream : output_stream ());
144  }
145 
146  // Return TRUE if this stream is open.
147 
148  bool is_open (void) const { return m_open_state; }
149 
150  virtual void do_close (void) { }
151 
152  void close (void)
153  {
154  if (is_open ())
155  {
156  m_open_state = false;
157  do_close ();
158  }
159  }
160 
161  virtual int file_number (void) const
162  {
163  // Kluge alert!
164 
165  if (name () == "stdin")
166  return 0;
167  else if (name () == "stdout")
168  return 1;
169  else if (name () == "stderr")
170  return 2;
171  else
172  return -1;
173  }
174 
175  bool ok (void) const { return ! m_fail; }
176 
177  // Return current error message for this stream.
178 
179  std::string error (bool clear, int& err_num);
180 
181 protected:
182 
183  int mode (void) const { return m_mode; }
184 
185  mach_info::float_format float_format (void) const { return m_flt_fmt; }
186 
187  std::string encoding (void) const { return m_encoding; }
188 
189  // Set current error state and set fail to TRUE.
190 
191  OCTINTERP_API void error (const std::string& msg);
192  OCTINTERP_API void error (const std::string& who, const std::string& msg);
193 
194  // Clear any error message and set fail to FALSE.
195 
196  OCTINTERP_API void clear (void);
197 
198  // Clear stream state.
199 
200  OCTINTERP_API void clearerr (void);
201 
202 private:
203 
204  // The permission bits for the file. Should be some combination of
205  // std::ios::open_mode bits.
206  int m_mode;
207 
208  // Data format.
210 
211  // Code page
212  std::string m_encoding;
213 
214  // encoding conversion facet
215  typedef string::deletable_facet<string::codecvt_u8> convfacet_u8;
216 
217  // FIXME: Identified by compiler as unused private field.
218  // Commented out 10/29/2022.
219  // If there are no repercussions, delete entirely.
220  // std::wbuffer_convert<convfacet_u8, char> *m_converter;
221 
222  // wrappers for encoding conversion
223  // std::istream *m_conv_istream;
224 
225  std::ostream *m_conv_ostream;
226 
227  // TRUE if an error has occurred.
228  bool m_fail;
229 
230  // TRUE if this stream is open.
232 
233  // Should contain error message if fail is TRUE.
234  std::string m_errmsg;
235 
236  // Functions that are defined for all input streams (input streams
237  // are those that define is).
238 
239  OCTINTERP_API std::string
240  do_gets (octave_idx_type max_len, bool& err, bool strip_newline,
241  const std::string& who /* = "gets" */);
242 
243  OCTINTERP_API std::string
244  getl (octave_idx_type max_len, bool& err,
245  const std::string& who /* = "getl" */);
246  OCTINTERP_API std::string
247  gets (octave_idx_type max_len, bool& err,
248  const std::string& who /* = "gets" */);
249  OCTINTERP_API off_t
250  skipl (off_t count, bool& err, const std::string& who /* = "skipl" */);
251 
252  OCTINTERP_API octave_value
253  do_scanf (scanf_format_list& fmt_list, octave_idx_type nr,
254  octave_idx_type nc, bool one_elt_size_spec,
255  octave_idx_type& count, const std::string& who /* = "scanf" */);
256 
257  OCTINTERP_API octave_value
258  scanf (const std::string& fmt, const Array<double>& size,
259  octave_idx_type& count, const std::string& who /* = "scanf" */);
260 
261  OCTINTERP_API bool
262  do_oscanf (const scanf_format_elt *elt, octave_value&,
263  const std::string& who /* = "scanf" */);
264 
265  OCTINTERP_API octave_value_list
266  oscanf (const std::string& fmt, const std::string& who /* = "scanf" */);
267 
268  OCTINTERP_API octave_value
269  do_textscan (const std::string& fmt, octave_idx_type ntimes,
270  const octave_value_list& options,
271  const std::string& who, octave_idx_type& count);
272 
273  // Functions that are defined for all output streams (output streams
274  // are those that define os).
275 
276  OCTINTERP_API int flush (void);
277 
278  OCTINTERP_API int
279  do_numeric_printf_conv (std::ostream& os, const printf_format_elt *elt,
280  int nsa, int sa_1, int sa_2,
281  const octave_value& val,
282  const std::string& who);
283 
284  OCTINTERP_API void field_width_error (const std::string& who) const;
285 
286  OCTINTERP_API int
287  do_printf (printf_format_list& fmt_list, const octave_value_list& args,
288  const std::string& who /* = "printf" */);
289 
290  OCTINTERP_API int
291  printf (const std::string& fmt, const octave_value_list& args,
292  const std::string& who /* = "printf" */);
293 
294  OCTINTERP_API int
295  puts (const std::string& s, const std::string& who /* = "puts" */);
296 
297  // We can always do this in terms of seek(), so the derived class
298  // only has to provide that.
299 
300  OCTINTERP_API void
301  invalid_operation (const std::string& who, const char *rw);
302 };
303 
304 class
305 OCTINTERP_API
306 stream
307 {
308 public:
309 
310  // BS must be allocated with new or nullptr.
311  stream (base_stream *bs = nullptr) : m_rep (bs) { }
312 
313  stream (const stream&) = default;
314 
315  stream& operator = (const stream&) = default;
316 
317  ~stream (void) = default;
318 
319  OCTINTERP_API int flush (void);
320 
321  OCTINTERP_API std::string
322  getl (octave_idx_type max_len, bool& err,
323  const std::string& who /* = "getl" */);
324 
325  OCTINTERP_API std::string
326  getl (const octave_value& max_len, bool& err,
327  const std::string& who /* = "getl" */);
328 
329  OCTINTERP_API std::string
330  gets (octave_idx_type max_len, bool& err,
331  const std::string& who /* = "gets" */);
332 
333  OCTINTERP_API std::string
334  gets (const octave_value& max_len, bool& err,
335  const std::string& who /* = "gets" */);
336 
337  OCTINTERP_API off_t
338  skipl (off_t count, bool& err, const std::string& who /* = "skipl" */);
339 
340  OCTINTERP_API off_t
341  skipl (const octave_value& count, bool& err,
342  const std::string& who /* = "skipl" */);
343 
344  OCTINTERP_API int seek (off_t offset, int origin);
345 
346  OCTINTERP_API int
347  seek (const octave_value& offset, const octave_value& origin);
348 
349  OCTINTERP_API off_t tell (void);
350 
351  OCTINTERP_API int rewind (void);
352 
353  OCTINTERP_API bool is_open (void) const;
354 
355  OCTINTERP_API void close (void);
356 
357  OCTINTERP_API octave_value
358  read (const Array<double>& size, octave_idx_type block_size,
359  oct_data_conv::data_type input_type,
360  oct_data_conv::data_type output_type,
362  octave_idx_type& count);
363 
364  OCTINTERP_API octave_idx_type
365  write (const octave_value& data, octave_idx_type block_size,
366  oct_data_conv::data_type output_type,
368 
369  OCTINTERP_API bool write_bytes (const void *data, std::size_t n_elts);
370 
371  OCTINTERP_API bool skip_bytes (std::size_t n_elts);
372 
373  template <typename T>
374  OCTINTERP_API octave_idx_type
375  write (const Array<T>& data, octave_idx_type block_size,
376  oct_data_conv::data_type output_type,
378 
379  OCTINTERP_API octave_value
380  scanf (const std::string& fmt, const Array<double>& size,
381  octave_idx_type& count, const std::string& who /* = "scanf" */);
382 
383  OCTINTERP_API octave_value
384  scanf (const octave_value& fmt, const Array<double>& size,
385  octave_idx_type& count, const std::string& who /* = "scanf" */);
386 
387  OCTINTERP_API octave_value_list
388  oscanf (const std::string& fmt, const std::string& who /* = "scanf" */);
389 
390  OCTINTERP_API octave_value_list
391  oscanf (const octave_value& fmt, const std::string& who /* = "scanf" */);
392 
393  OCTINTERP_API octave_value
394  textscan (const std::string& fmt, octave_idx_type ntimes,
395  const octave_value_list& options,
396  const std::string& who, octave_idx_type& count);
397 
398  OCTINTERP_API int
399  printf (const std::string& fmt, const octave_value_list& args,
400  const std::string& who /* = "printf" */);
401 
402  OCTINTERP_API int
403  printf (const octave_value& fmt, const octave_value_list& args,
404  const std::string& who /* = "printf" */);
405 
406  OCTINTERP_API int
407  puts (const std::string& s, const std::string& who /* = "puts" */);
408  OCTINTERP_API int
409  puts (const octave_value& s, const std::string& who /* = "puts" */);
410 
411  OCTINTERP_API bool eof (void) const;
412 
413  OCTINTERP_API std::string error (bool clear, int& err_num);
414 
415  std::string error (bool clear = false)
416  {
417  int err_num;
418  return error (clear, err_num);
419  }
420 
421  // Set the error message and state.
422 
423  void error (const std::string& msg)
424  {
425  if (m_rep)
426  m_rep->error (msg);
427  }
428 
429  void error (const char *msg) { error (std::string (msg)); }
430 
431  int file_number (void) { return m_rep ? m_rep->file_number () : -1; }
432 
433  bool is_valid (void) const { return bool (m_rep); }
434 
435  bool ok (void) const { return m_rep && m_rep->ok (); }
436 
437  operator bool () const { return ok (); }
438 
439  OCTINTERP_API std::string name (void) const;
440 
441  OCTINTERP_API int mode (void) const;
442 
443  OCTINTERP_API mach_info::float_format float_format (void) const;
444 
445  OCTINTERP_API static std::string mode_as_string (int mode);
446 
447  std::string encoding (void)
448  {
449  return m_rep ? m_rep->encoding () : std::string ();
450  }
451 
452  std::istream * input_stream (void)
453  {
454  return m_rep ? m_rep->input_stream () : nullptr;
455  }
456 
457  std::ostream * output_stream (void)
458  {
459  return (m_rep ? m_rep->preferred_output_stream () : nullptr);
460  }
461 
462  void clearerr (void) { if (m_rep) m_rep->clearerr (); }
463 
464 private:
465 
466  // The actual representation of this stream.
467  std::shared_ptr<base_stream> m_rep;
468 
469  bool stream_ok (bool clear = true) const
470  {
471  bool retval = true;
472 
473  if (m_rep)
474  {
475  if (clear)
476  m_rep->clear ();
477  }
478  else
479  retval = false;
480 
481  return retval;
482  }
483 
484  void invalid_operation (const std::string& who, const char *rw)
485  {
486  if (m_rep)
487  m_rep->invalid_operation (who, rw);
488  }
489 
490  OCTINTERP_API octave_value
491  finalize_read (std::list<void *>& input_buf_list,
492  octave_idx_type input_buf_elts,
493  octave_idx_type elts_read,
495  oct_data_conv::data_type input_type,
496  oct_data_conv::data_type output_type,
498 };
499 
500 class
501 OCTINTERP_API
503 {
504 public:
505 
506  OCTINTERP_API stream_list (interpreter& interp);
507 
508  stream_list (const stream_list&) = delete;
510 
511  OCTINTERP_API ~stream_list (void);
512 
513  OCTINTERP_API int insert (stream& os);
514 
515  OCTINTERP_API stream lookup (int fid, const std::string& who = "") const;
516  OCTINTERP_API stream
517  lookup (const octave_value& fid, const std::string& who = "") const;
518 
519  OCTINTERP_API int remove (int fid, const std::string& who = "");
520  OCTINTERP_API int remove (const octave_value& fid,
521  const std::string& who = "");
522 
523  OCTINTERP_API void clear (bool flush = true);
524 
525  OCTINTERP_API string_vector get_info (int fid) const;
526  OCTINTERP_API string_vector get_info (const octave_value& fid) const;
527 
528  OCTINTERP_API std::string list_open_files (void) const;
529 
530  OCTINTERP_API octave_value open_file_numbers (void) const;
531 
532  OCTINTERP_API int get_file_number (const octave_value& fid) const;
533 
534  OCTINTERP_API octave_value stdin_file (void) const;
535  OCTINTERP_API octave_value stdout_file (void) const;
536  OCTINTERP_API octave_value stderr_file (void) const;
537 
538 private:
539 
540  typedef std::map<int, stream> ostrl_map;
541 
543 
544  mutable ostrl_map::const_iterator m_lookup_cache;
545 
549 };
550 
552 
553 #endif
OCTAVE_END_NAMESPACE(octave)
octave_idx_type lookup(const T *x, octave_idx_type n, T y)
Definition: Cell.h:43
base_stream(const base_stream &)=delete
virtual int file_number(void) const
Definition: oct-stream.h:161
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
virtual ~base_stream(void)=default
std::ostream * m_conv_ostream
Definition: oct-stream.h:225
virtual std::string name(void) const =0
mach_info::float_format float_format(void) const
Definition: oct-stream.h:185
virtual off_t tell(void)=0
int mode(void) const
Definition: oct-stream.h:183
bool m_open_state
Definition: oct-stream.h:231
void close(void)
Definition: oct-stream.h:152
virtual int seek(off_t offset, int origin)=0
std::string m_errmsg
Definition: oct-stream.h:234
virtual bool eof(void) const =0
bool is_open(void) const
Definition: oct-stream.h:148
std::string m_encoding
Definition: oct-stream.h:212
virtual void do_close(void)
Definition: oct-stream.h:150
virtual std::istream * input_stream(void)
Definition: oct-stream.h:113
virtual std::ostream * output_stream(void)
Definition: oct-stream.h:119
bool ok(void) const
Definition: oct-stream.h:175
std::ostream * preferred_output_stream(void)
Definition: oct-stream.h:124
mach_info::float_format m_flt_fmt
Definition: oct-stream.h:209
std::string encoding(void) const
Definition: oct-stream.h:187
string::deletable_facet< string::codecvt_u8 > convfacet_u8
Definition: oct-stream.h:215
std::map< int, stream > ostrl_map
Definition: oct-stream.h:540
ostrl_map::const_iterator m_lookup_cache
Definition: oct-stream.h:544
ostrl_map m_list
Definition: oct-stream.h:542
stream_list(const stream_list &)=delete
int m_stdout_file
Definition: oct-stream.h:547
int m_stdin_file
Definition: oct-stream.h:546
int m_stderr_file
Definition: oct-stream.h:548
int file_number(void)
Definition: oct-stream.h:431
std::string error(bool clear=false)
Definition: oct-stream.h:415
void clearerr(void)
Definition: oct-stream.h:462
OCTINTERP_API 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, mach_info::float_format ffmt)
Definition: oct-stream.cc:6529
void error(const std::string &msg)
Definition: oct-stream.h:423
static OCTINTERP_API std::string mode_as_string(int mode)
Definition: oct-stream.cc:7355
stream & operator=(const stream &)=default
OCTINTERP_API octave_value scanf(const std::string &fmt, const Array< double > &size, octave_idx_type &count, const std::string &who)
Definition: oct-stream.cc:7152
std::istream * input_stream(void)
Definition: oct-stream.h:452
OCTINTERP_API std::string gets(octave_idx_type max_len, bool &err, const std::string &who)
Definition: oct-stream.cc:6181
std::ostream * output_stream(void)
Definition: oct-stream.h:457
bool is_valid(void) const
Definition: oct-stream.h:433
OCTINTERP_API bool skip_bytes(std::size_t n_elts)
Definition: oct-stream.cc:7006
OCTINTERP_API bool eof(void) const
Definition: oct-stream.cc:7300
OCTINTERP_API int rewind(void)
Definition: oct-stream.cc:6386
OCTINTERP_API std::string name(void) const
Definition: oct-stream.cc:7322
bool stream_ok(bool clear=true) const
Definition: oct-stream.h:469
std::shared_ptr< base_stream > m_rep
Definition: oct-stream.h:467
OCTINTERP_API off_t skipl(off_t count, bool &err, const std::string &who)
Definition: oct-stream.cc:6216
OCTINTERP_API 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:7222
stream(base_stream *bs=nullptr)
Definition: oct-stream.h:311
OCTINTERP_API int puts(const std::string &s, const std::string &who)
Definition: oct-stream.cc:7268
OCTINTERP_API int printf(const std::string &fmt, const octave_value_list &args, const std::string &who)
Definition: oct-stream.cc:7232
OCTINTERP_API octave_idx_type write(const Array< T > &data, octave_idx_type block_size, oct_data_conv::data_type output_type, octave_idx_type skip, mach_info::float_format flt_fmt)
void error(const char *msg)
Definition: oct-stream.h:429
OCTINTERP_API int flush(void)
Definition: oct-stream.cc:6135
bool ok(void) const
Definition: oct-stream.h:435
OCTINTERP_API bool write_bytes(const void *data, std::size_t n_elts)
Definition: oct-stream.cc:6983
OCTINTERP_API bool is_open(void) const
Definition: oct-stream.cc:6392
OCTINTERP_API int mode(void) const
Definition: oct-stream.cc:7333
OCTINTERP_API int seek(off_t offset, int origin)
Definition: oct-stream.cc:6258
void invalid_operation(const std::string &who, const char *rw)
Definition: oct-stream.h:484
stream(const stream &)=default
OCTINTERP_API octave_value_list oscanf(const std::string &fmt, const std::string &who)
Definition: oct-stream.cc:7188
OCTINTERP_API off_t tell(void)
Definition: oct-stream.cc:6375
OCTINTERP_API std::string getl(octave_idx_type max_len, bool &err, const std::string &who)
Definition: oct-stream.cc:6146
std::string encoding(void)
Definition: oct-stream.h:447
OCTINTERP_API void close(void)
Definition: oct-stream.cc:6403
~stream(void)=default
OCTINTERP_API 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:6617
OCTINTERP_API 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:6810
OCTAVE_BEGIN_NAMESPACE(octave) static octave_value daspk_fcn
void error(const char *fmt,...)
Definition: error.cc:979
float_format native_float_format(void)
Definition: mach-info.cc:65
float_format
Definition: mach-info.h:38