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 66 base_stream 67 { 68 friend class stream; 69 70 public: 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") m_mode(arg_md)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 input_stream(void)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 output_stream(void)116 virtual std::ostream * output_stream (void) { return nullptr; } 117 118 // Return TRUE if this stream is open. 119 is_open(void)120 bool is_open (void) const { return m_open_state; } 121 do_close(void)122 virtual void do_close (void) { } 123 close(void)124 void close (void) 125 { 126 if (is_open ()) 127 { 128 m_open_state = false; 129 do_close (); 130 } 131 } 132 file_number(void)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 ok(void)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 mode(void)155 int mode (void) const { return m_mode; } 156 float_format(void)157 mach_info::float_format float_format (void) const { return m_flt_fmt; } 158 encoding(void)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. 181 mach_info::float_format m_flt_fmt; 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. 190 bool m_open_state; 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. m_rep(bs)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, 296 octave_idx_type skip, mach_info::float_format flt_fmt, 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, std::size_t n_elts); 305 306 bool skip_bytes (std::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 error(const std::string & msg)351 void error (const std::string& msg) 352 { 353 if (m_rep) 354 m_rep->error (msg); 355 } 356 error(const char * msg)357 void error (const char *msg) { error (std::string (msg)); } 358 file_number(void)359 int file_number (void) { return m_rep ? m_rep->file_number () : -1; } 360 is_valid(void)361 bool is_valid (void) const { return bool (m_rep); } 362 ok(void)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 371 mach_info::float_format float_format (void) const; 372 373 static std::string mode_as_string (int mode); 374 encoding(void)375 std::string encoding (void) 376 { 377 return m_rep ? m_rep->encoding () : std::string (); 378 } 379 input_stream(void)380 std::istream * input_stream (void) 381 { 382 return m_rep ? m_rep->input_stream () : nullptr; 383 } 384 output_stream(void)385 std::ostream * output_stream (void) 386 { 387 return m_rep ? m_rep->output_stream () : nullptr; 388 } 389 clearerr(void)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 invalid_operation(const std::string & who,const char * rw)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 418 octave_value 419 finalize_read (std::list<void *>& input_buf_list, 420 octave_idx_type input_buf_elts, 421 octave_idx_type elts_read, 422 octave_idx_type nr, octave_idx_type nc, 423 oct_data_conv::data_type input_type, 424 oct_data_conv::data_type output_type, 425 mach_info::float_format ffmt); 426 }; 427 428 class 429 OCTINTERP_API 430 stream_list 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 468 ostrl_map m_list; 469 470 mutable ostrl_map::const_iterator m_lookup_cache; 471 472 int m_stdin_file; 473 int m_stdout_file; 474 int m_stderr_file; 475 }; 476 } 477 478 #endif 479