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