view src/oct-stream.h @ 2117:b240b2fce8ed

[project @ 1996-05-10 07:20:36 by jwe] Initial revision
author jwe
date Fri, 10 May 1996 07:20:36 +0000
parents
children ee08cc210438
line wrap: on
line source

/*

Copyright (C) 1996 John W. Eaton

This file is part of Octave.

Octave is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 2, or (at your option) any
later version.

Octave is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
for more details.

You should have received a copy of the GNU General Public License
along with Octave; see the file COPYING.  If not, write to the Free
Software Foundation, 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

*/

#if !defined (octave_octave_stream_h)
#define octave_octave_stream_h 1

#include <string>

#include <iostream.h>
#include <strstream.h>

#include "Array.h"

#include "oct-obj.h"
#include "str-vec.h"

struct
scanf_format_elt
{
  scanf_format_elt (const char *txt = 0, bool d = false,
		    char typ = '\0', char mod = '\0')
    : text (txt), discard (d), type (typ), modifier (mod) { }

  ~scanf_format_elt (void) { delete text; }

  const char *text;
  bool discard;
  char type;
  char modifier;
};

class
scanf_format_list
{
public:

  scanf_format_list (const string& fmt = string ());

  ~scanf_format_list (void);

  int num_conversions (void) { return nconv; }

  const scanf_format_elt *first (void)
    {
      curr_idx = 0;
      return current ();
    }

  const scanf_format_elt *current (void) const
    { return list.length () > 0 ? list.elem (curr_idx) : 0; }

  const scanf_format_elt *next (void)
    {
      curr_idx++;
      if (curr_idx >= list.length ())
	curr_idx = 0;
      return current ();
    }

  void printme (void) const;

  bool ok (void) const { return (nconv >= 0); }

  operator void* () const { return ok () ? (void *) -1 : (void *) 0; }

  bool all_character_conversions (void);

  bool all_numeric_conversions (void);

private:

  // Number of conversions specified by this format string, or -1 if
  // invalid conversions have been found.
  int nconv;

  // Index to current element;
  int curr_idx;

  // List of format elements.
  Array<scanf_format_elt*> list;

  // Temporary buffer.
  ostrstream *buf;

  void add_elt_to_list (bool discard, char type, char modifier,
			int& num_elts);

  void process_conversion (const string& s, int& i, int n, bool& discard,
			   char& type, char& modifier, int& num_elts);

  int finish_conversion (const string& s, int& i, int n, bool discard,
			 char& type, char modifier, int& num_elts);
  // No copying!

  scanf_format_list (const scanf_format_list&);

  scanf_format_list& operator = (const scanf_format_list&);
};

struct
printf_format_elt
{
  printf_format_elt (const char *txt = 0, int n = 0, char typ = '\0',
		     char mod = '\0')
    : text (txt), args (n), type (typ), modifier (mod) { }

  ~printf_format_elt (void) { delete text; }

  const char *text;
  int args;
  char type;
  char modifier;
};

class
printf_format_list
{
public:

  printf_format_list (const string& fmt = string ());

  ~printf_format_list (void);

  int num_conversions (void) { return nconv; }

  const printf_format_elt *first (void)
    {
      curr_idx = 0;
      return current ();
    }

  const printf_format_elt *current (void) const
    { return list.length () > 0 ? list.elem (curr_idx) : 0; }

  const printf_format_elt *next (void)
    {
      curr_idx++;
      if (curr_idx >= list.length ())
	curr_idx = 0;
      return current ();
    }

  void printme (void) const;

  bool ok (void) const { return (nconv >= 0); }

  operator void* () const { return ok () ? (void *) -1 : (void *) 0; }

private:

  // Number of conversions specified by this format string, or -1 if
  // invalid conversions have been found.
  int nconv;

  // Index to current element;
  int curr_idx;

  // List of format elements.
  Array<printf_format_elt*> list;

  // Temporary buffer.
  ostrstream *buf;

  void add_elt_to_list (int args, char type, char modifier,
			int& num_elts);

  void process_conversion (const string& s, int& i, int n, int& args,
			   char& modifier, char& type, int& num_elts);

  void finish_conversion (const string& s, int& i, int args,
			  char modifier, char& type, int& num_elts);

  // No copying!

  printf_format_list (const printf_format_list&);

  printf_format_list& operator = (const printf_format_list&);
};

// Provide an interface for Octave streams.

class
octave_base_stream
{
friend class octave_stream;

public:

  enum arch_type
    {
      at_unknown,
      at_native
    };

  enum data_type
    {
      dt_unknown,
      dt_char,
      dt_schar,
      dt_uchar,
      dt_short,
      dt_ushort,
      dt_int,
      dt_uint,
      dt_long,
      dt_ulong,
      dt_float,
      dt_double,
      dt_float_complex,
      dt_double_complex
    };

  octave_base_stream (ios::openmode arg_md = ios::in|ios::out,
		      arch_type arg_at = at_native)
    : md (arg_md), at (arg_at), fail (false) { }

  virtual ~octave_base_stream (void) { }

  // The remaining functions are not specific to input or output only,
  // and must be provided by the derived classes.

  // Position a stream at OFFSET relative to ORIGIN.

  virtual int seek (streampos offset, ios::seek_dir origin) = 0;

  // Return current stream position.

  virtual long tell (void) const = 0;

  // Return non-zero if EOF has been reached on this stream.

  virtual bool eof (void) const = 0;

  // The name of the file.

  virtual string name (void) = 0;

  // If the derived class provides this function and it returns a
  // pointer to a valid istream, scanf(), read(), getl(), and gets()
  // will automatically work for this stream.

  virtual istream *input_stream (void) { return 0; }

  // If the derived class provides this function and it returns a
  // pointer to a valid ostream, flush(), write(), and printf() will
  // automatically work for this stream.

  virtual ostream *output_stream (void) { return 0; }

  bool ok (void) const { return ! fail; }

  // Return current error message for this stream.

  string error (bool clear, int& errno);

protected:

  int mode (void) { return md; }

  arch_type architecture (void) { return at; }

  // Set current error state and set fail to TRUE.

  void error (const string& msg);

  // Clear any error message and set fail to FALSE.

  void clear (void);

private:

  // The permission bits for the file.  Should be some combination of
  // ios::open_mode bits.
  int md;

  // Data format.
  arch_type at;

  // TRUE if an error has occurred.
  bool fail;

  // Should contain error message if fail is TRUE.
  string errmsg;

  // Functions that are defined for all input streams (input streams
  // are those that define is).

  string do_gets (int max_len, bool& err, bool strip_newline, const char *fcn);

  string getl (int max_len, bool& err);
  string gets (int max_len, bool& err);

  octave_value do_read (int nr, int nc, data_type dt, int skip,
			arch_type at, int& count);

  octave_value read (const Matrix& size, data_type dt, int skip,
		     arch_type at, int& count);

  octave_value do_char_scanf (scanf_format_list& fmt_list,
			      int nr, int nc, int& count);

  octave_value do_real_scanf (scanf_format_list& fmt_list,
			      int nr, int nc, int& count);

  octave_value do_scanf (scanf_format_list& fmt_list, int nr, int nc,
			 int& count);

  octave_value scanf (const string& fmt, const Matrix& size, int& count);

  // Functions that are defined for all output streams (output streams
  // are those that define os).

  int flush (void);

  int do_write (const double *d, int n, data_type dt, int skip,
		arch_type at);

  int write (const octave_value& data, data_type dt, int skip,
	     arch_type at);

  int do_printf (printf_format_list& fmt_list, const octave_value_list& args);

  int printf (const string& fmt, const octave_value_list& args);

  int puts (const string& s);

  // We can always do this in terms of seek(), so the derived class
  // only has to provide that.

  int rewind (void);

  void invalid_operation (const char *op, const char *rw);

  // No copying!

  octave_base_stream (const octave_base_stream&);

  octave_base_stream& operator = (const octave_base_stream&);
};

class
octave_stream
{
public:

  octave_stream (octave_base_stream *bs = 0) : rep (bs) { }

  ~octave_stream (void) { delete rep; }

  int flush (void);

  string getl (int max_len, bool& err);
  string getl (const octave_value& max_len, bool& err);

  string gets (int max_len, bool& err);
  string gets (const octave_value& max_len, bool& err);

  int seek (streampos offset, ios::seek_dir origin);
  int seek (const octave_value& offset, const octave_value& origin);

  long tell (void) const;

  int rewind (void);

  octave_value read (const Matrix& size,
		     octave_base_stream::data_type dt,
		     int skip, octave_base_stream::arch_type at,
		     int& count);

  int write (const octave_value& data,
	     octave_base_stream::data_type dt, int skip,
	     octave_base_stream::arch_type at);

  octave_value scanf (const string& fmt, const Matrix& size, int& count);

  int printf (const string& fmt, const octave_value_list& args);

  int puts (const string& s);
  int puts (const octave_value& s);

  bool eof (void) const;

  string error (bool clear, int& errno);

  string error (bool clear = false)
    {
      int errno;
      return error (clear, errno);
    }

  bool ok (void) const { return rep && rep->ok (); }

  operator void* () const { return ok () ? (void *) -1 : (void *) 0; }

  string name (void);

  int mode (void);

  octave_base_stream::arch_type architecture (void);

  static string mode_as_string (int mode);

  static string arch_as_string (octave_base_stream::arch_type at);

  static octave_base_stream::data_type string_to_data_type (const string& s);
  static octave_base_stream::arch_type string_to_arch_type (const string& s);

private:

  // The actual representation of this stream.
  octave_base_stream *rep;

  void invalid_stream_error (const char *op) const;

  bool stream_ok (const char *op, bool clear = true) const
    {
      bool retval = true;

      if (rep)
	{
	  if (clear)
	    rep->clear ();
	}
      else
	{
	  retval = false;
	  invalid_stream_error (op);
	}

      return retval;
    }

  void error (const string& msg)
    {
      if (rep)
	rep->error (msg);
    }

  // Must create named streams.

  octave_stream (void);

  // No copying!

  octave_stream (const octave_stream&);

  octave_stream& operator = (const octave_stream&);
};

class
octave_stream_list
{
protected:

  octave_stream_list (void) : list (32), curr_len (0) { }

public:

  ~octave_stream_list (void) { }

  static int insert (octave_base_stream *obs);

  static octave_stream *lookup (int fid);
  static octave_stream *lookup (const octave_value& fid);

  static int remove (int fid);
  static int remove (const octave_value& fid);

  static void clear (void);

  static string_vector get_info (int fid);
  static string_vector get_info (const octave_value& fid);

  static string list_open_files (void);

  static octave_value open_file_numbers (void);

private:

  Array<octave_stream*> list;

  int curr_len;

  static octave_stream_list *instance;

  int do_insert (octave_base_stream *obs);

  octave_stream *do_lookup (int fid) const;
  octave_stream *do_lookup (const octave_value& fid) const;

  int do_remove (int fid);
  int do_remove (const octave_value& fid);

  void do_clear (void);

  string_vector do_get_info (int fid) const;
  string_vector do_get_info (const octave_value& fid) const;

  string do_list_open_files (void) const;

  octave_value do_open_file_numbers (void) const;

  int get_file_number (const octave_value& fid) const;
};

#endif

/*
;;; Local Variables: ***
;;; mode: C++ ***
;;; End: ***
*/