GNU Octave  3.8.0
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
oct-stream.h
Go to the documentation of this file.
1 /*
2 
3 Copyright (C) 1996-2013 John W. Eaton
4 
5 This file is part of Octave.
6 
7 Octave is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by the
9 Free Software Foundation; either version 3 of the License, or (at your
10 option) any later version.
11 
12 Octave is distributed in the hope that it will be useful, but WITHOUT
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 for more details.
16 
17 You should have received a copy of the GNU General Public License
18 along with Octave; see the file COPYING. If not, see
19 <http://www.gnu.org/licenses/>.
20 
21 */
22 
23 #if !defined (octave_oct_stream_h)
24 #define octave_oct_stream_h 1
25 
26 class Matrix;
27 class string_vector;
28 class octave_value;
29 class octave_value_list;
30 
31 #include <iosfwd>
32 #include <sstream>
33 #include <string>
34 #include <list>
35 #include <map>
36 
37 #include "Array.h"
38 #include "data-conv.h"
39 #include "lo-utils.h"
40 #include "mach-info.h"
41 #include "oct-locbuf.h"
42 #include "oct-refcount.h"
43 
44 class
47 {
48 public:
49 
51  {
52  whitespace_conversion = 1,
53  literal_conversion = 2
54  };
55 
56  scanf_format_elt (const char *txt = 0, int w = 0, bool d = false,
57  char typ = '\0', char mod = '\0',
58  const std::string& ch_class = std::string ())
59  : text (strsave (txt)), width (w), discard (d), type (typ),
60  modifier (mod), char_class (ch_class) { }
61 
63  : text (strsave (e.text)), width (e.width), discard (e.discard),
64  type (e.type), modifier (e.modifier), char_class (e.char_class) { }
65 
67  {
68  if (this != &e)
69  {
70  text = strsave (e.text);
71  width = e.width;
72  discard = e.discard;
73  type = e.type;
74  modifier = e.modifier;
75  char_class = e.char_class;
76  }
77 
78  return *this;
79  }
80 
81  ~scanf_format_elt (void) { delete [] text; }
82 
83  // The C-style format string.
84  const char *text;
85 
86  // The maximum field width.
87  int width;
88 
89  // TRUE if we are not storing the result of this conversion.
90  bool discard;
91 
92  // Type of conversion -- 'd', 'i', 'o', 'u', 'x', 'e', 'f', 'g',
93  // 'c', 's', 'p', '%', or '['.
94  char type;
95 
96  // A length modifier -- 'h', 'l', or 'L'.
97  char modifier;
98 
99  // The class of characters in a '[' format.
100  std::string char_class;
101 };
102 
103 class
106 {
107 public:
108 
109  scanf_format_list (const std::string& fmt = std::string ());
110 
111  ~scanf_format_list (void);
112 
113  octave_idx_type num_conversions (void) { return nconv; }
114 
115  // The length can be different than the number of conversions.
116  // For example, "x %d y %d z" has 2 conversions but the length of
117  // the list is 3 because of the characters that appear after the
118  // last conversion.
119 
120  octave_idx_type length (void) { return list.length (); }
121 
122  const scanf_format_elt *first (void)
123  {
124  curr_idx = 0;
125  return current ();
126  }
127 
128  const scanf_format_elt *current (void) const
129  { return list.length () > 0 ? list.elem (curr_idx) : 0; }
130 
131  const scanf_format_elt *next (bool cycle = true)
132  {
133  curr_idx++;
134 
135  if (curr_idx >= list.length ())
136  {
137  if (cycle)
138  curr_idx = 0;
139  else
140  return 0;
141  }
142  return current ();
143  }
144 
145  void printme (void) const;
146 
147  bool ok (void) const { return (nconv >= 0); }
148 
149  operator bool () const { return ok (); }
150 
151  bool all_character_conversions (void);
152 
153  bool all_numeric_conversions (void);
154 
155 private:
156 
157  // Number of conversions specified by this format string, or -1 if
158  // invalid conversions have been found.
160 
161  // Index to current element;
163 
164  // FIXME: maybe LIST should be a std::list object?
165  // List of format elements.
167 
168  // Temporary buffer.
169  std::ostringstream *buf;
170 
171  void add_elt_to_list (int width, bool discard, char type, char modifier,
172  octave_idx_type& num_elts,
173  const std::string& char_class = std::string ());
174 
175  void process_conversion (const std::string& s, size_t& i, size_t n,
176  int& width, bool& discard, char& type,
177  char& modifier, octave_idx_type& num_elts);
178 
179  int finish_conversion (const std::string& s, size_t& i, size_t n,
180  int& width, bool discard, char& type,
181  char modifier, octave_idx_type& num_elts);
182  // No copying!
183 
185 
187 };
188 
189 class
191 {
192 public:
193 
194  printf_format_elt (const char *txt = 0, int n = 0, int w = 0,
195  int p = 0, const std::string& f = std::string (),
196  char typ = '\0', char mod = '\0')
197  : text (strsave (txt)), args (n), fw (w), prec (p), flags (f),
198  type (typ), modifier (mod) { }
199 
201  : text (strsave (e.text)), args (e.args), fw (e.fw), prec (e.prec),
202  flags (e.flags), type (e.type), modifier (e.modifier) { }
203 
205  {
206  if (this != &e)
207  {
208  text = strsave (e.text);
209  args = e.args;
210  fw = e.fw;
211  prec = e.prec;
212  flags = e.flags;
213  type = e.type;
214  modifier = e.modifier;
215  }
216 
217  return *this;
218  }
219 
220  ~printf_format_elt (void) { delete [] text; }
221 
222  // The C-style format string.
223  const char *text;
224 
225  // How many args do we expect to consume?
226  int args;
227 
228  // Field width.
229  int fw;
230 
231  // Precision.
232  int prec;
233 
234  // Flags -- '-', '+', ' ', '0', or '#'.
235  std::string flags;
236 
237  // Type of conversion -- 'd', 'i', 'o', 'x', 'X', 'u', 'c', 's',
238  // 'f', 'e', 'E', 'g', 'G', 'p', or '%'
239  char type;
240 
241  // A length modifier -- 'h', 'l', or 'L'.
242  char modifier;
243 };
244 
245 class
248 {
249 public:
250 
251  printf_format_list (const std::string& fmt = std::string ());
252 
253  ~printf_format_list (void);
254 
255  octave_idx_type num_conversions (void) { return nconv; }
256 
257  const printf_format_elt *first (void)
258  {
259  curr_idx = 0;
260  return current ();
261  }
262 
263  const printf_format_elt *current (void) const
264  { return list.length () > 0 ? list.elem (curr_idx) : 0; }
265 
266  const printf_format_elt *next (bool cycle = true)
267  {
268  curr_idx++;
269 
270  if (curr_idx >= list.length ())
271  {
272  if (cycle)
273  curr_idx = 0;
274  else
275  return 0;
276  }
277 
278  return current ();
279  }
280 
281  bool last_elt_p (void) { return (curr_idx + 1 == list.length ()); }
282 
283  void printme (void) const;
284 
285  bool ok (void) const { return (nconv >= 0); }
286 
287  operator bool () const { return ok (); }
288 
289 private:
290 
291  // Number of conversions specified by this format string, or -1 if
292  // invalid conversions have been found.
294 
295  // Index to current element;
297 
298  // FIXME: maybe LIST should be a std::list object?
299  // List of format elements.
301 
302  // Temporary buffer.
303  std::ostringstream *buf;
304 
305  void add_elt_to_list (int args, const std::string& flags, int fw,
306  int prec, char type, char modifier,
307  octave_idx_type& num_elts);
308 
309  void process_conversion (const std::string& s, size_t& i, size_t n,
310  int& args, std::string& flags, int& fw,
311  int& prec, char& modifier, char& type,
312  octave_idx_type& num_elts);
313 
314  void finish_conversion (const std::string& s, size_t& i, int args,
315  const std::string& flags, int fw, int prec,
316  char modifier, char& type,
317  octave_idx_type& num_elts);
318 
319  // No copying!
320 
322 
324 };
325 
326 // Provide an interface for Octave streams.
327 
328 class
331 {
332  friend class octave_stream;
333 
334 public:
335 
336  octave_base_stream (std::ios::openmode arg_md = std::ios::in|std::ios::out,
339  : count (0), md (arg_md), flt_fmt (ff), fail (false), open_state (true),
340  errmsg ()
341  { }
342 
343  virtual ~octave_base_stream (void) { }
344 
345  // The remaining functions are not specific to input or output only,
346  // and must be provided by the derived classes.
347 
348  // Position a stream at OFFSET relative to ORIGIN.
349 
350  virtual int seek (off_t offset, int origin) = 0;
351 
352  // Return current stream position.
353 
354  virtual off_t tell (void) = 0;
355 
356  // Return TRUE if EOF has been reached on this stream.
357 
358  virtual bool eof (void) const = 0;
359 
360  // The name of the file.
361 
362  virtual std::string name (void) const = 0;
363 
364  // If the derived class provides this function and it returns a
365  // pointer to a valid istream, scanf(), read(), getl(), and gets()
366  // will automatically work for this stream.
367 
368  virtual std::istream *input_stream (void) { return 0; }
369 
370  // If the derived class provides this function and it returns a
371  // pointer to a valid ostream, flush(), write(), and printf() will
372  // automatically work for this stream.
373 
374  virtual std::ostream *output_stream (void) { return 0; }
375 
376  // Return TRUE if this stream is open.
377 
378  bool is_open (void) const { return open_state; }
379 
380  virtual void do_close (void) { }
381 
382  void close (void)
383  {
384  if (is_open ())
385  {
386  open_state = false;
387  do_close ();
388  }
389  }
390 
391  virtual int file_number (void) const
392  {
393  // Kluge alert!
394 
395  if (name () == "stdin")
396  return 0;
397  else if (name () == "stdout")
398  return 1;
399  else if (name () == "stderr")
400  return 2;
401  else
402  return -1;
403  }
404 
405  bool ok (void) const { return ! fail; }
406 
407  // Return current error message for this stream.
408 
409  std::string error (bool clear, int& err_num);
410 
411 protected:
412 
413  int mode (void) const { return md; }
414 
415  oct_mach_info::float_format float_format (void) const { return flt_fmt; }
416 
417  // Set current error state and set fail to TRUE.
418 
419  void error (const std::string& msg);
420  void error (const std::string& who, const std::string& msg);
421 
422  // Clear any error message and set fail to FALSE.
423 
424  void clear (void);
425 
426  // Clear stream state.
427 
428  void clearerr (void);
429 
430 private:
431 
432  // A reference count.
434 
435  // The permission bits for the file. Should be some combination of
436  // std::ios::open_mode bits.
437  int md;
438 
439  // Data format.
441 
442  // TRUE if an error has occurred.
443  bool fail;
444 
445  // TRUE if this stream is open.
447 
448  // Should contain error message if fail is TRUE.
449  std::string errmsg;
450 
451  // Functions that are defined for all input streams (input streams
452  // are those that define is).
453 
454  std::string do_gets (octave_idx_type max_len, bool& err, bool strip_newline,
455  const std::string& who /* = "gets" */);
456 
457  std::string getl (octave_idx_type max_len, bool& err,
458  const std::string& who /* = "getl" */);
459  std::string gets (octave_idx_type max_len, bool& err,
460  const std::string& who /* = "gets" */);
461  off_t skipl (off_t count, bool& err, const std::string& who /* = "skipl" */);
462 
463  octave_value do_scanf (scanf_format_list& fmt_list, octave_idx_type nr,
464  octave_idx_type nc,
465  bool one_elt_size_spec, octave_idx_type& count,
466  const std::string& who /* = "scanf" */);
467 
468  octave_value scanf (const std::string& fmt, const Array<double>& size,
469  octave_idx_type& count, const std::string& who /* = "scanf" */);
470 
471  bool do_oscanf (const scanf_format_elt *elt, octave_value&,
472  const std::string& who /* = "scanf" */);
473 
474  octave_value_list oscanf (const std::string& fmt,
475  const std::string& who /* = "scanf" */);
476 
477  // Functions that are defined for all output streams (output streams
478  // are those that define os).
479 
480  int flush (void);
481 
482  int do_printf (printf_format_list& fmt_list, const octave_value_list& args,
483  const std::string& who /* = "printf" */);
484 
485  int printf (const std::string& fmt, const octave_value_list& args,
486  const std::string& who /* = "printf" */);
487 
488  int puts (const std::string& s, const std::string& who /* = "puts" */);
489 
490  // We can always do this in terms of seek(), so the derived class
491  // only has to provide that.
492 
493  void invalid_operation (const std::string& who, const char *rw);
494 
495  // No copying!
496 
498 
500 };
501 
502 class
505 {
506 public:
507 
509 
510  ~octave_stream (void);
511 
512  octave_stream (const octave_stream&);
513 
515 
516  int flush (void);
517 
518  std::string getl (octave_idx_type max_len, bool& err,
519  const std::string& who /* = "getl" */);
520  std::string getl (const octave_value& max_len, bool& err,
521  const std::string& who /* = "getl" */);
522 
523  std::string gets (octave_idx_type max_len, bool& err,
524  const std::string& who /* = "gets" */);
525  std::string gets (const octave_value& max_len, bool& err,
526  const std::string& who /* = "gets" */);
527 
528  off_t skipl (off_t count, bool& err, const std::string& who /* = "skipl" */);
529  off_t skipl (const octave_value& count, bool& err,
530  const std::string& who /* = "skipl" */);
531 
532  int seek (off_t offset, int origin);
533  int seek (const octave_value& offset, const octave_value& origin);
534 
535  off_t tell (void);
536 
537  int rewind (void);
538 
539  bool is_open (void) const;
540 
541  void close (void);
542 
543  octave_value read (const Array<double>& size, octave_idx_type block_size,
544  oct_data_conv::data_type input_type,
545  oct_data_conv::data_type output_type,
547  octave_idx_type& count);
548 
549  octave_idx_type write (const octave_value& data, octave_idx_type block_size,
550  oct_data_conv::data_type output_type,
551  octave_idx_type skip,
553 
554  bool write_bytes (const void *data, size_t n_elts);
555 
556  bool skip_bytes (size_t n_elts);
557 
558  template <class T>
559  octave_idx_type write (const Array<T>& data, octave_idx_type block_size,
560  oct_data_conv::data_type output_type,
561  octave_idx_type skip,
563 
564  octave_value scanf (const std::string& fmt, const Array<double>& size,
565  octave_idx_type& count, const std::string& who /* = "scanf" */);
566 
567  octave_value scanf (const octave_value& fmt, const Array<double>& size,
568  octave_idx_type& count, const std::string& who /* = "scanf" */);
569 
570  octave_value_list oscanf (const std::string& fmt,
571  const std::string& who /* = "scanf" */);
572 
574  const std::string& who /* = "scanf" */);
575 
576  int printf (const std::string& fmt, const octave_value_list& args,
577  const std::string& who /* = "printf" */);
578 
579  int printf (const octave_value& fmt, const octave_value_list& args,
580  const std::string& who /* = "printf" */);
581 
582  int puts (const std::string& s, const std::string& who /* = "puts" */);
583  int puts (const octave_value& s, const std::string& who /* = "puts" */);
584 
585  bool eof (void) const;
586 
587  std::string error (bool clear, int& err_num);
588 
589  std::string error (bool clear = false)
590  {
591  int err_num;
592  return error (clear, err_num);
593  }
594 
595  // Set the error message and state.
596 
597  void error (const std::string& msg)
598  {
599  if (rep)
600  rep->error (msg);
601  }
602 
603  void error (const char *msg) { error (std::string (msg)); }
604 
605  int file_number (void) { return rep ? rep->file_number () : -1; }
606 
607  bool is_valid (void) const { return (rep != 0); }
608 
609  bool ok (void) const { return rep && rep->ok (); }
610 
611  operator bool () const { return ok (); }
612 
613  std::string name (void) const;
614 
615  int mode (void) const;
616 
618 
619  static std::string mode_as_string (int mode);
620 
621  std::istream *input_stream (void)
622  {
623  return rep ? rep->input_stream () : 0;
624  }
625 
626  std::ostream *output_stream (void)
627  {
628  return rep ? rep->output_stream () : 0;
629  }
630 
631  void clearerr (void) { if (rep) rep->clearerr (); }
632 
633 private:
634 
635  // The actual representation of this stream.
637 
638  bool stream_ok (bool clear = true) const
639  {
640  bool retval = true;
641 
642  if (rep)
643  {
644  if (clear)
645  rep->clear ();
646  }
647  else
648  retval = false;
649 
650  return retval;
651  }
652 
653  void invalid_operation (const std::string& who, const char *rw)
654  {
655  if (rep)
656  rep->invalid_operation (who, rw);
657  }
658 
660  finalize_read (std::list<void *>& input_buf_list,
661  octave_idx_type input_buf_elts,
662  octave_idx_type elts_read,
664  oct_data_conv::data_type input_type,
665  oct_data_conv::data_type output_type,
667 };
668 
669 class
672 {
673 protected:
674 
675  octave_stream_list (void) : list (), lookup_cache (list.end ()) { }
676 
677 public:
678 
680 
681  static bool instance_ok (void);
682 
683  static int insert (octave_stream& os);
684 
685  static octave_stream
686  lookup (int fid, const std::string& who = std::string ());
687 
688  static octave_stream
689  lookup (const octave_value& fid, const std::string& who = std::string ());
690 
691  static int remove (int fid, const std::string& who = std::string ());
692  static int remove (const octave_value& fid,
693  const std::string& who = std::string ());
694 
695  static void clear (bool flush = true);
696 
697  static string_vector get_info (int fid);
698  static string_vector get_info (const octave_value& fid);
699 
700  static std::string list_open_files (void);
701 
702  static octave_value open_file_numbers (void);
703 
704  static int get_file_number (const octave_value& fid);
705 
706 private:
707 
708  typedef std::map<int, octave_stream> ostrl_map;
709 
710  ostrl_map list;
711 
712  mutable ostrl_map::const_iterator lookup_cache;
713 
715 
716  static void cleanup_instance (void) { delete instance; instance = 0; }
717 
718  int do_insert (octave_stream& os);
719 
720  octave_stream do_lookup (int fid,
721  const std::string& who = std::string ()) const;
722  octave_stream do_lookup (const octave_value& fid,
723  const std::string& who = std::string ()) const;
724 
725  int do_remove (int fid, const std::string& who = std::string ());
726  int do_remove (const octave_value& fid,
727  const std::string& who = std::string ());
728 
729  void do_clear (bool flush = true);
730 
731  string_vector do_get_info (int fid) const;
732  string_vector do_get_info (const octave_value& fid) const;
733 
734  std::string do_list_open_files (void) const;
735 
736  octave_value do_open_file_numbers (void) const;
737 
738  int do_get_file_number (const octave_value& fid) const;
739 };
740 
741 #endif