oct-stream.h

Go to the documentation of this file.
00001 /*
00002 
00003 Copyright (C) 1996-2012 John W. Eaton
00004 
00005 This file is part of Octave.
00006 
00007 Octave is free software; you can redistribute it and/or modify it
00008 under the terms of the GNU General Public License as published by the
00009 Free Software Foundation; either version 3 of the License, or (at your
00010 option) any later version.
00011 
00012 Octave is distributed in the hope that it will be useful, but WITHOUT
00013 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00014 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
00015 for more details.
00016 
00017 You should have received a copy of the GNU General Public License
00018 along with Octave; see the file COPYING.  If not, see
00019 <http://www.gnu.org/licenses/>.
00020 
00021 */
00022 
00023 #if !defined (octave_octave_stream_h)
00024 #define octave_octave_stream_h 1
00025 
00026 class Matrix;
00027 class string_vector;
00028 class octave_value;
00029 class octave_value_list;
00030 
00031 #include <iosfwd>
00032 #include <sstream>
00033 #include <string>
00034 #include <map>
00035 
00036 #include "Array.h"
00037 #include "data-conv.h"
00038 #include "lo-utils.h"
00039 #include "mach-info.h"
00040 #include "oct-refcount.h"
00041 
00042 class
00043 OCTINTERP_API
00044 scanf_format_elt
00045 {
00046 public:
00047 
00048   enum special_conversion
00049     {
00050       whitespace_conversion = 1,
00051       literal_conversion = 2
00052     };
00053 
00054   scanf_format_elt (const char *txt = 0, int w = 0, bool d = false,
00055                     char typ = '\0', char mod = '\0',
00056                     const std::string& ch_class = std::string ())
00057     : text (strsave (txt)), width (w), discard (d), type (typ),
00058       modifier (mod), char_class (ch_class) { }
00059 
00060   scanf_format_elt (const scanf_format_elt& e)
00061     : text (strsave (e.text)), width (e.width), discard (e.discard),
00062       type (e.type), modifier (e.modifier), char_class (e.char_class) { }
00063 
00064   scanf_format_elt& operator = (const scanf_format_elt& e)
00065     {
00066       if (this != &e)
00067         {
00068           text = strsave (e.text);
00069           width = e.width;
00070           discard = e.discard;
00071           type = e.type;
00072           modifier = e.modifier;
00073           char_class = e.char_class;
00074         }
00075 
00076       return *this;
00077     }
00078 
00079   ~scanf_format_elt (void) { delete [] text; }
00080 
00081   // The C-style format string.
00082   const char *text;
00083 
00084   // The maximum field width.
00085   int width;
00086 
00087   // TRUE if we are not storing the result of this conversion.
00088   bool discard;
00089 
00090   // Type of conversion -- 'd', 'i', 'o', 'u', 'x', 'e', 'f', 'g',
00091   // 'c', 's', 'p', '%', or '['.
00092   char type;
00093 
00094   // A length modifier -- 'h', 'l', or 'L'.
00095   char modifier;
00096 
00097   // The class of characters in a '[' format.
00098   std::string char_class;
00099 };
00100 
00101 class
00102 OCTINTERP_API
00103 scanf_format_list
00104 {
00105 public:
00106 
00107   scanf_format_list (const std::string& fmt = std::string ());
00108 
00109   ~scanf_format_list (void);
00110 
00111   octave_idx_type num_conversions (void) { return nconv; }
00112 
00113   // The length can be different than the number of conversions.
00114   // For example, "x %d y %d z" has 2 conversions but the length of
00115   // the list is 3 because of the characters that appear after the
00116   // last conversion.
00117 
00118   octave_idx_type length (void) { return list.length (); }
00119 
00120   const scanf_format_elt *first (void)
00121     {
00122       curr_idx = 0;
00123       return current ();
00124     }
00125 
00126   const scanf_format_elt *current (void) const
00127     { return list.length () > 0 ? list.elem (curr_idx) : 0; }
00128 
00129   const scanf_format_elt *next (bool cycle = true)
00130     {
00131       curr_idx++;
00132 
00133       if (curr_idx >= list.length ())
00134         {
00135           if (cycle)
00136             curr_idx = 0;
00137           else
00138             return 0;
00139         }
00140       return current ();
00141     }
00142 
00143   void printme (void) const;
00144 
00145   bool ok (void) const { return (nconv >= 0); }
00146 
00147   operator bool () const { return ok (); }
00148 
00149   bool all_character_conversions (void);
00150 
00151   bool all_numeric_conversions (void);
00152 
00153 private:
00154 
00155   // Number of conversions specified by this format string, or -1 if
00156   // invalid conversions have been found.
00157   octave_idx_type nconv;
00158 
00159   // Index to current element;
00160   octave_idx_type curr_idx;
00161 
00162   // FIXME -- maybe LIST should be a std::list object?
00163   // List of format elements.
00164   Array<scanf_format_elt*> list;
00165 
00166   // Temporary buffer.
00167   std::ostringstream *buf;
00168 
00169   void add_elt_to_list (int width, bool discard, char type, char modifier,
00170                         octave_idx_type& num_elts,
00171                         const std::string& char_class = std::string ());
00172 
00173   void process_conversion (const std::string& s, size_t& i, size_t n,
00174                            int& width, bool& discard, char& type,
00175                            char& modifier, octave_idx_type& num_elts);
00176 
00177   int finish_conversion (const std::string& s, size_t& i, size_t n,
00178                          int& width, bool discard, char& type,
00179                          char modifier, octave_idx_type& num_elts);
00180   // No copying!
00181 
00182   scanf_format_list (const scanf_format_list&);
00183 
00184   scanf_format_list& operator = (const scanf_format_list&);
00185 };
00186 
00187 class
00188 printf_format_elt
00189 {
00190 public:
00191 
00192   printf_format_elt (const char *txt = 0, int n = 0, int w = 0,
00193                      int p = 0, const std::string& f = std::string (),
00194                      char typ = '\0', char mod = '\0')
00195     : text (strsave (txt)), args (n), fw (w), prec (p), flags (f),
00196       type (typ), modifier (mod) { }
00197 
00198   printf_format_elt (const printf_format_elt& e)
00199     : text (strsave (e.text)), args (e.args), fw (e.fw), prec (e.prec),
00200       flags (e.flags), type (e.type), modifier (e.modifier) { }
00201 
00202   printf_format_elt& operator = (const printf_format_elt& e)
00203     {
00204       if (this != &e)
00205         {
00206           text = strsave (e.text);
00207           args = e.args;
00208           fw = e.fw;
00209           prec = e.prec;
00210           flags = e.flags;
00211           type = e.type;
00212           modifier = e.modifier;
00213         }
00214 
00215       return *this;
00216     }
00217 
00218   ~printf_format_elt (void) { delete [] text; }
00219 
00220   // The C-style format string.
00221   const char *text;
00222 
00223   // How many args do we expect to consume?
00224   int args;
00225 
00226   // Field width.
00227   int fw;
00228 
00229   // Precision.
00230   int prec;
00231 
00232   // Flags -- '-', '+', ' ', '0', or '#'.
00233   std::string flags;
00234 
00235   // Type of conversion -- 'd', 'i', 'o', 'x', 'X', 'u', 'c', 's',
00236   // 'f', 'e', 'E', 'g', 'G', 'p', or '%'
00237   char type;
00238 
00239   // A length modifier -- 'h', 'l', or 'L'.
00240   char modifier;
00241 };
00242 
00243 class
00244 OCTINTERP_API
00245 printf_format_list
00246 {
00247 public:
00248 
00249   printf_format_list (const std::string& fmt = std::string ());
00250 
00251   ~printf_format_list (void);
00252 
00253   octave_idx_type num_conversions (void) { return nconv; }
00254 
00255   const printf_format_elt *first (void)
00256     {
00257       curr_idx = 0;
00258       return current ();
00259     }
00260 
00261   const printf_format_elt *current (void) const
00262     { return list.length () > 0 ? list.elem (curr_idx) : 0; }
00263 
00264   const printf_format_elt *next (bool cycle = true)
00265     {
00266       curr_idx++;
00267 
00268       if (curr_idx >= list.length ())
00269         {
00270           if (cycle)
00271             curr_idx = 0;
00272           else
00273             return 0;
00274         }
00275 
00276       return current ();
00277     }
00278 
00279   bool last_elt_p (void) { return (curr_idx + 1 == list.length ()); }
00280 
00281   void printme (void) const;
00282 
00283   bool ok (void) const { return (nconv >= 0); }
00284 
00285   operator bool () const { return ok (); }
00286 
00287 private:
00288 
00289   // Number of conversions specified by this format string, or -1 if
00290   // invalid conversions have been found.
00291   octave_idx_type nconv;
00292 
00293   // Index to current element;
00294   octave_idx_type curr_idx;
00295 
00296   // FIXME -- maybe LIST should be a std::list object?
00297   // List of format elements.
00298   Array<printf_format_elt*> list;
00299 
00300   // Temporary buffer.
00301   std::ostringstream *buf;
00302 
00303   void add_elt_to_list (int args, const std::string& flags, int fw,
00304                         int prec, char type, char modifier,
00305                         octave_idx_type& num_elts);
00306 
00307   void process_conversion (const std::string& s, size_t& i, size_t n,
00308                            int& args, std::string& flags, int& fw,
00309                            int& prec, char& modifier, char& type,
00310                            octave_idx_type& num_elts);
00311 
00312   void finish_conversion (const std::string& s, size_t& i, int args,
00313                           const std::string& flags, int fw, int prec,
00314                           char modifier, char& type,
00315                           octave_idx_type& num_elts);
00316 
00317   // No copying!
00318 
00319   printf_format_list (const printf_format_list&);
00320 
00321   printf_format_list& operator = (const printf_format_list&);
00322 };
00323 
00324 // Provide an interface for Octave streams.
00325 
00326 class
00327 OCTINTERP_API
00328 octave_base_stream
00329 {
00330 friend class octave_stream;
00331 
00332 public:
00333 
00334   octave_base_stream (std::ios::openmode arg_md = std::ios::in|std::ios::out,
00335                       oct_mach_info::float_format ff
00336                         = oct_mach_info::native_float_format ())
00337     : count (0), md (arg_md), flt_fmt (ff), fail (false), open_state (true),
00338       errmsg ()
00339   { }
00340 
00341   virtual ~octave_base_stream (void) { }
00342 
00343   // The remaining functions are not specific to input or output only,
00344   // and must be provided by the derived classes.
00345 
00346   // Position a stream at OFFSET relative to ORIGIN.
00347 
00348   virtual int seek (long offset, int origin) = 0;
00349 
00350   // Return current stream position.
00351 
00352   virtual long tell (void) = 0;
00353 
00354   // Return TRUE if EOF has been reached on this stream.
00355 
00356   virtual bool eof (void) const = 0;
00357 
00358   // The name of the file.
00359 
00360   virtual std::string name (void) const = 0;
00361 
00362   // If the derived class provides this function and it returns a
00363   // pointer to a valid istream, scanf(), read(), getl(), and gets()
00364   // will automatically work for this stream.
00365 
00366   virtual std::istream *input_stream (void) { return 0; }
00367 
00368   // If the derived class provides this function and it returns a
00369   // pointer to a valid ostream, flush(), write(), and printf() will
00370   // automatically work for this stream.
00371 
00372   virtual std::ostream *output_stream (void) { return 0; }
00373 
00374   // Return TRUE if this stream is open.
00375 
00376   bool is_open (void) const { return open_state; }
00377 
00378   virtual void do_close (void) { }
00379 
00380   void close (void)
00381     {
00382       if (is_open ())
00383         {
00384           open_state = false;
00385           do_close ();
00386         }
00387     }
00388 
00389   virtual int file_number (void) const
00390   {
00391     // Kluge alert!
00392 
00393     if (name () == "stdin")
00394       return 0;
00395     else if (name () == "stdout")
00396       return 1;
00397     else if (name () == "stderr")
00398       return 2;
00399     else
00400       return -1;
00401   }
00402 
00403   bool ok (void) const { return ! fail; }
00404 
00405   // Return current error message for this stream.
00406 
00407   std::string error (bool clear, int& err_num);
00408 
00409 protected:
00410 
00411   int mode (void) const { return md; }
00412 
00413   oct_mach_info::float_format float_format (void) const { return flt_fmt; }
00414 
00415   // Set current error state and set fail to TRUE.
00416 
00417   void error (const std::string& msg);
00418   void error (const std::string& who, const std::string& msg);
00419 
00420   // Clear any error message and set fail to FALSE.
00421 
00422   void clear (void);
00423 
00424   // Clear stream state.
00425 
00426   void clearerr (void);
00427 
00428 private:
00429 
00430   // A reference count.
00431   octave_refcount<octave_idx_type> count;
00432 
00433   // The permission bits for the file.  Should be some combination of
00434   // std::ios::open_mode bits.
00435   int md;
00436 
00437   // Data format.
00438   oct_mach_info::float_format flt_fmt;
00439 
00440   // TRUE if an error has occurred.
00441   bool fail;
00442 
00443   // TRUE if this stream is open.
00444   bool open_state;
00445 
00446   // Should contain error message if fail is TRUE.
00447   std::string errmsg;
00448 
00449   // Functions that are defined for all input streams (input streams
00450   // are those that define is).
00451 
00452   std::string do_gets (octave_idx_type max_len, bool& err, bool strip_newline,
00453                        const std::string& who /* = "gets" */);
00454 
00455   std::string getl (octave_idx_type max_len, bool& err, const std::string& who /* = "getl" */);
00456   std::string gets (octave_idx_type max_len, bool& err, const std::string& who /* = "gets" */);
00457   long skipl (long count, bool& err, const std::string& who /* = "skipl" */);
00458 
00459   octave_value do_scanf (scanf_format_list& fmt_list, octave_idx_type nr, octave_idx_type nc,
00460                          bool one_elt_size_spec, octave_idx_type& count,
00461                          const std::string& who /* = "scanf" */);
00462 
00463   octave_value scanf (const std::string& fmt, const Array<double>& size,
00464                       octave_idx_type& count, const std::string& who /* = "scanf" */);
00465 
00466   bool do_oscanf (const scanf_format_elt *elt, octave_value&,
00467                   const std::string& who /* = "scanf" */);
00468 
00469   octave_value_list oscanf (const std::string& fmt,
00470                             const std::string& who /* = "scanf" */);
00471 
00472   // Functions that are defined for all output streams (output streams
00473   // are those that define os).
00474 
00475   int flush (void);
00476 
00477   int do_printf (printf_format_list& fmt_list, const octave_value_list& args,
00478                  const std::string& who /* = "printf" */);
00479 
00480   int printf (const std::string& fmt, const octave_value_list& args,
00481               const std::string& who /* = "printf" */);
00482 
00483   int puts (const std::string& s, const std::string& who /* = "puts" */);
00484 
00485   // We can always do this in terms of seek(), so the derived class
00486   // only has to provide that.
00487 
00488   void invalid_operation (const std::string& who, const char *rw);
00489 
00490   // No copying!
00491 
00492   octave_base_stream (const octave_base_stream&);
00493 
00494   octave_base_stream& operator = (const octave_base_stream&);
00495 };
00496 
00497 class
00498 OCTINTERP_API
00499 octave_stream
00500 {
00501 public:
00502 
00503   octave_stream (octave_base_stream *bs = 0);
00504 
00505   ~octave_stream (void);
00506 
00507   octave_stream (const octave_stream&);
00508 
00509   octave_stream& operator = (const octave_stream&);
00510 
00511   int flush (void);
00512 
00513   std::string getl (octave_idx_type max_len, bool& err, const std::string& who /* = "getl" */);
00514   std::string getl (const octave_value& max_len, bool& err,
00515                     const std::string& who /* = "getl" */);
00516 
00517   std::string gets (octave_idx_type max_len, bool& err, const std::string& who /* = "gets" */);
00518   std::string gets (const octave_value& max_len, bool& err,
00519                     const std::string& who /* = "gets" */);
00520 
00521   long skipl (long count, bool& err, const std::string& who /* = "skipl" */);
00522   long skipl (const octave_value& count, bool& err, const std::string& who /* = "skipl" */);
00523 
00524   int seek (long offset, int origin);
00525   int seek (const octave_value& offset, const octave_value& origin);
00526 
00527   long tell (void);
00528 
00529   int rewind (void);
00530 
00531   bool is_open (void) const;
00532 
00533   void close (void);
00534 
00535   octave_value read (const Array<double>& size, octave_idx_type block_size,
00536                      oct_data_conv::data_type input_type,
00537                      oct_data_conv::data_type output_type,
00538                      octave_idx_type skip, oct_mach_info::float_format flt_fmt,
00539                      octave_idx_type& count);
00540 
00541   octave_idx_type write (const octave_value& data, octave_idx_type block_size,
00542              oct_data_conv::data_type output_type,
00543              octave_idx_type skip, oct_mach_info::float_format flt_fmt);
00544 
00545   template <class T>
00546   octave_idx_type write (const Array<T>&, octave_idx_type block_size,
00547              oct_data_conv::data_type output_type,
00548              octave_idx_type skip, oct_mach_info::float_format flt_fmt);
00549 
00550   octave_value scanf (const std::string& fmt, const Array<double>& size,
00551                       octave_idx_type& count, const std::string& who /* = "scanf" */);
00552 
00553   octave_value scanf (const octave_value& fmt, const Array<double>& size,
00554                       octave_idx_type& count, const std::string& who /* = "scanf" */);
00555 
00556   octave_value_list oscanf (const std::string& fmt,
00557                             const std::string& who /* = "scanf" */);
00558 
00559   octave_value_list oscanf (const octave_value& fmt,
00560                             const std::string& who /* = "scanf" */);
00561 
00562   int printf (const std::string& fmt, const octave_value_list& args,
00563               const std::string& who /* = "printf" */);
00564 
00565   int printf (const octave_value& fmt, const octave_value_list& args,
00566               const std::string& who /* = "printf" */);
00567 
00568   int puts (const std::string& s, const std::string& who /* = "puts" */);
00569   int puts (const octave_value& s, const std::string& who /* = "puts" */);
00570 
00571   bool eof (void) const;
00572 
00573   std::string error (bool clear, int& err_num);
00574 
00575   std::string error (bool clear = false)
00576     {
00577       int err_num;
00578       return error (clear, err_num);
00579     }
00580 
00581   // Set the error message and state.
00582 
00583   void error (const std::string& msg)
00584     {
00585       if (rep)
00586         rep->error (msg);
00587     }
00588 
00589   void error (const char *msg) { error (std::string (msg)); }
00590 
00591   int file_number (void) { return rep ? rep->file_number () : -1; }
00592 
00593   bool is_valid (void) const { return (rep != 0); }
00594 
00595   bool ok (void) const { return rep && rep->ok (); }
00596 
00597   operator bool () const { return ok (); }
00598 
00599   std::string name (void) const;
00600 
00601   int mode (void) const;
00602 
00603   oct_mach_info::float_format float_format (void) const;
00604 
00605   static std::string mode_as_string (int mode);
00606 
00607   std::istream *input_stream (void)
00608   {
00609     return rep ? rep->input_stream () : 0;
00610   }
00611 
00612   std::ostream *output_stream (void)
00613   {
00614     return rep ? rep->output_stream () : 0;
00615   }
00616 
00617   void clearerr (void) { if (rep) rep->clearerr (); }
00618 
00619 private:
00620 
00621   // The actual representation of this stream.
00622   octave_base_stream *rep;
00623 
00624   bool stream_ok (bool clear = true) const
00625     {
00626       bool retval = true;
00627 
00628       if (rep)
00629         {
00630           if (clear)
00631             rep->clear ();
00632         }
00633       else
00634         retval = false;
00635 
00636       return retval;
00637     }
00638 
00639   void invalid_operation (const std::string& who, const char *rw)
00640     {
00641       if (rep)
00642         rep->invalid_operation (who, rw);
00643     }
00644 };
00645 
00646 class
00647 OCTINTERP_API
00648 octave_stream_list
00649 {
00650 protected:
00651 
00652   octave_stream_list (void) : list (), lookup_cache (list.end ()) { }
00653 
00654 public:
00655 
00656   ~octave_stream_list (void) { }
00657 
00658   static bool instance_ok (void);
00659 
00660   static int insert (octave_stream& os);
00661 
00662   static octave_stream
00663   lookup (int fid, const std::string& who = std::string ());
00664 
00665   static octave_stream
00666   lookup (const octave_value& fid, const std::string& who = std::string ());
00667 
00668   static int remove (int fid, const std::string& who = std::string ());
00669   static int remove (const octave_value& fid,
00670                      const std::string& who = std::string ());
00671 
00672   static void clear (bool flush = true);
00673 
00674   static string_vector get_info (int fid);
00675   static string_vector get_info (const octave_value& fid);
00676 
00677   static std::string list_open_files (void);
00678 
00679   static octave_value open_file_numbers (void);
00680 
00681   static int get_file_number (const octave_value& fid);
00682 
00683 private:
00684 
00685   typedef std::map<int, octave_stream> ostrl_map;
00686 
00687   ostrl_map list;
00688 
00689   mutable ostrl_map::const_iterator lookup_cache;
00690 
00691   static octave_stream_list *instance;
00692 
00693   static void cleanup_instance (void) { delete instance; instance = 0; }
00694 
00695   int do_insert (octave_stream& os);
00696 
00697   octave_stream do_lookup (int fid, const std::string& who = std::string ()) const;
00698   octave_stream do_lookup (const octave_value& fid,
00699                            const std::string& who = std::string ()) const;
00700 
00701   int do_remove (int fid, const std::string& who = std::string ());
00702   int do_remove (const octave_value& fid, const std::string& who = std::string ());
00703 
00704   void do_clear (bool flush = true);
00705 
00706   string_vector do_get_info (int fid) const;
00707   string_vector do_get_info (const octave_value& fid) const;
00708 
00709   std::string do_list_open_files (void) const;
00710 
00711   octave_value do_open_file_numbers (void) const;
00712 
00713   int do_get_file_number (const octave_value& fid) const;
00714 };
00715 
00716 #endif
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Friends Defines