changeset 9701:531280b07625

implement fskipl
author Jaroslav Hajek <highegg@gmail.com>
date Wed, 07 Oct 2009 11:08:54 +0200
parents 95a30d00f779
children 9ecd35a606e3
files doc/ChangeLog doc/interpreter/io.txi src/ChangeLog src/file-io.cc src/oct-stream.cc src/oct-stream.h
diffstat 6 files changed, 162 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/doc/ChangeLog	Wed Oct 07 10:08:37 2009 +0200
+++ b/doc/ChangeLog	Wed Oct 07 11:08:54 2009 +0200
@@ -1,3 +1,7 @@
+2009-10-07  Jaroslav Hajek  <highegg@gmail.com>
+
+	* interpreter/io.txi: Add reference to fskipl.
+
 2009-09-30  John W. Eaton  <jwe@octave.org>
 
 	* interpreter/data.txi (Built-in Data Types):
--- a/doc/interpreter/io.txi	Wed Oct 07 10:08:37 2009 +0200
+++ b/doc/interpreter/io.txi	Wed Oct 07 11:08:54 2009 +0200
@@ -369,6 +369,8 @@
 
 @DOCSTRING(fgets)
 
+@DOCSTRING(fskipl)
+
 @node Formatted Output
 @subsection Formatted Output
 
--- a/src/ChangeLog	Wed Oct 07 10:08:37 2009 +0200
+++ b/src/ChangeLog	Wed Oct 07 11:08:54 2009 +0200
@@ -1,3 +1,11 @@
+2009-10-07  Jaroslav Hajek  <highegg@gmail.com>
+
+	* oct-stream.cc (octave_base_stream::skipl,
+	octave_stream::skipl (long, ...), octave_stream::skipl (const
+	octave_value&, ...)): New methods.
+	* oct-stream.h: Declare them.
+	* file-io.cc (Ffskipl): New DEFUN.
+
 2009-10-07  John W. Eaton  <jwe@octave.org>
 
 	* OPERATORS/op-str-str.cc (DEFUNOP (transpose, char_matrix_str)):
--- a/src/file-io.cc	Wed Oct 07 10:08:37 2009 +0200
+++ b/src/file-io.cc	Wed Oct 07 11:08:54 2009 +0200
@@ -396,6 +396,47 @@
   return retval;
 }
 
+DEFUN (fskipl, args, ,
+  "-*- texinfo -*-\n\
+@deftypefn {Built-in Function} {} fskipl (@var{fid}, @var{count})\n\
+Skips a given number of lines, i.e. discards characters until an end-of-line\n\
+is met exactly @var{count}-times, or end-of-file occurs.\n\
+Returns the number of lines skipped (end-of-line sequences encountered).\n\
+If @var{count} is omitted, it defaults to 1. @var{count} may also be\n\
+@code{Inf}, in which case lines are skipped to the end of file.\n\
+This form is suitable for counting lines in a file.\n\
+@seealso{fgetl, fgets}\n\
+@end deftypefn")
+{
+  static std::string who = "fskipl";
+
+  octave_value retval;
+
+  int nargin = args.length ();
+
+  if (nargin == 1 || nargin == 2)
+    {
+      octave_stream os = octave_stream_list::lookup (args(0), who);
+
+      if (! error_state)
+	{
+	  octave_value count_arg = (nargin == 2) ? args(1) : octave_value ();
+
+	  bool err = false;
+
+	  long tmp = os.skipl (count_arg, err, who);
+
+	  if (! (error_state || err))
+            retval = tmp;
+	}
+    }
+  else
+    print_usage ();
+
+  return retval;
+}
+
+
 static octave_stream
 do_stream_open (const std::string& name, const std::string& mode,
 		const std::string& arch, int& fid)
--- a/src/oct-stream.cc	Wed Oct 07 10:08:37 2009 +0200
+++ b/src/oct-stream.cc	Wed Oct 07 11:08:54 2009 +0200
@@ -1070,6 +1070,65 @@
   return do_gets (max_len, err, false, who);
 }
 
+long
+octave_base_stream::skipl (long num, bool& err, const std::string& who)
+{
+  long cnt = -1;
+
+  if ((interactive || forced_interactive) && file_number () == 0)
+    {
+      ::error ("%s: unable to read from stdin while running interactively",
+	       who.c_str ());
+	     
+      return count;
+    }
+
+  err = false;
+
+  std::istream *isp = input_stream ();
+
+  if (isp)
+    {
+      std::istream& is = *isp;
+
+      int c = 0, lastc = -1;
+      cnt = 0;
+
+      while (is && (c = is.get ()) != EOF)
+        {
+          // Handle CRLF, CR, or LF as line ending.
+
+          if (c == '\r' || (c == '\n' && lastc != '\r'))
+            {
+              if (++cnt == num)
+                break;
+            }
+
+          lastc = c;
+        }
+
+      // Maybe eat the following \n if \r was just met.
+      if (c == '\r' && is.peek () == '\n')
+       is.get ();
+
+      if (is.bad ())
+        {
+          err = true;
+          error (who, "read error");
+        }
+
+      if (err)
+        cnt = -1;
+    }
+  else
+    {
+      err = true;
+      invalid_operation (who, "reading");
+    }
+
+  return cnt;
+}
+
 #define OCTAVE_SCAN(is, fmt, arg) octave_scan (is, fmt, arg)
 
 template <class T>
@@ -2918,6 +2977,50 @@
   return retval;
 }
 
+long
+octave_stream::skipl (long count, bool& err, const std::string& who)
+{
+  long retval = -1;
+
+  if (stream_ok ())
+    retval = rep->skipl (count, err, who);
+
+  return retval;
+}
+
+long
+octave_stream::skipl (const octave_value& tc_count, bool& err, const std::string& who)
+{
+  long retval = -1;
+
+  err = false;
+
+  int conv_err = 0;
+
+  int count = 1;
+
+  if (tc_count.is_defined ())
+    {
+      if (tc_count.is_scalar_type () && xisinf (tc_count.scalar_value ()))
+        count = -1;
+      else
+        {
+          count = convert_to_valid_int (tc_count, conv_err);
+
+          if (conv_err || count < 0)
+            {
+              err = true;
+              ::error ("%s: invalid number of lines specified", who.c_str ());
+            }
+        }
+    }
+
+  if (! error_state)
+    retval = skipl (count, err, who);
+
+  return retval;
+}
+
 int
 octave_stream::seek (long offset, int origin)
 {
--- a/src/oct-stream.h	Wed Oct 07 10:08:37 2009 +0200
+++ b/src/oct-stream.h	Wed Oct 07 11:08:54 2009 +0200
@@ -438,6 +438,7 @@
 
   std::string getl (octave_idx_type max_len, bool& err, const std::string& who /* = "getl" */);
   std::string gets (octave_idx_type max_len, bool& err, const std::string& who /* = "gets" */);
+  long skipl (long count, bool& err, const std::string& who /* = "skipl" */);
 
   octave_value do_scanf (scanf_format_list& fmt_list, octave_idx_type nr, octave_idx_type nc,
 			 bool one_elt_size_spec, octave_idx_type& count,
@@ -501,6 +502,9 @@
   std::string gets (const octave_value& max_len, bool& err,
 		    const std::string& who /* = "gets" */);
 
+  long skipl (long count, bool& err, const std::string& who /* = "skipl" */);
+  long skipl (const octave_value& count, bool& err, const std::string& who /* = "skipl" */);
+
   int seek (long offset, int origin);
   int seek (const octave_value& offset, const octave_value& origin);