changeset 10187:a44d15813a39

don't skip literal text elements in scanf formats
author John W. Eaton <jwe@octave.org>
date Fri, 22 Jan 2010 12:12:21 -0500
parents 095a1e670e68
children 97ae300aa73a
files src/ChangeLog src/oct-stream.cc src/oct-stream.h
diffstat 3 files changed, 112 insertions(+), 62 deletions(-) [+]
line wrap: on
line diff
--- a/src/ChangeLog	Fri Jan 22 07:30:44 2010 -0500
+++ b/src/ChangeLog	Fri Jan 22 12:12:21 2010 -0500
@@ -1,3 +1,26 @@
+2010-01-22  John W. Eaton  <jwe@octave.org>
+
+	* oct-stream.cc (octave_base_stream::do_scanf): Don't skip
+	whitespace, literal text, and %% elements at the end of the
+	format spec.  Correctly process formats containing only literal text.
+	(scanf_format_list::finish_conversion): Don't increment nconv
+	for literal % characters.
+	(scanf_format_list::length, scanf_format_list::num_conversions):
+	Return octave_idx_type, not int.
+	(scanf_format_list::nconv, scanf_format_list::curr_idx):
+	Now octave_idx_type, not int.  Change all uses.
+	(printf_format_list::length): Return octave_idx_type, not int.
+	(scanf_format_list::nconv, scanf_format_list::curr_idx):
+	Now octave_idx_type, not int.  Change all uses.
+	(scanf_format_list::add_elt_to_list,
+	scanf_format_list::process_conversion,
+	scanf_format_list::finish_conversion,
+	printf_format_list::add_elt_to_list,
+	printf_format_list::process_conversion,
+	printf_format_list::finish_conversion):
+	Use size_t instead of int as appropriate.
+	* oct-stream.h: Update decls.
+
 2010-01-22  John W. Eaton  <jwe@octave.org>
 
 	* debug.cc (Fdbcont, Fdbquit): Call reset_debug_state.
--- a/src/oct-stream.cc	Fri Jan 22 07:30:44 2010 -0500
+++ b/src/oct-stream.cc	Fri Jan 22 12:12:21 2010 -0500
@@ -157,11 +157,11 @@
 scanf_format_list::scanf_format_list (const std::string& s)
   : nconv (0), curr_idx (0), list (16), buf (0)
 {
-  int num_elts = 0;
-
-  int n = s.length ();
-
-  int i = 0;
+  octave_idx_type num_elts = 0;
+
+  size_t n = s.length ();
+
+  size_t i = 0;
 
   int width = 0;
   bool discard = false;
@@ -183,6 +183,7 @@
 
 	  process_conversion (s, i, n, width, discard, type, modifier,
 			      num_elts);
+
 	  have_more = (buf != 0);
 	}
       else if (isspace (s[i]))
@@ -305,9 +306,10 @@
 }
 
 void
-scanf_format_list::process_conversion (const std::string& s, int& i, int n,
-				       int& width, bool& discard, char& type,
-				       char& modifier, int& num_elts)
+scanf_format_list::process_conversion (const std::string& s, size_t& i,
+                                       size_t n, int& width, bool& discard,
+                                       char& type, char& modifier,
+                                       octave_idx_type& num_elts)
 {
   width = 0;
   discard = false;
@@ -407,16 +409,17 @@
 }
 
 int
-scanf_format_list::finish_conversion (const std::string& s, int& i, int n,
-				      int& width, bool discard, char& type,
-				      char modifier, int& num_elts)
+scanf_format_list::finish_conversion (const std::string& s, size_t& i,
+                                      size_t n, int& width, bool discard,
+                                      char& type, char modifier,
+                                      octave_idx_type& num_elts)
 {
   int retval = 0;
 
   std::string char_class;
 
-  int beg_idx = -1;
-  int end_idx = -1;
+  size_t beg_idx = std::string::npos;
+  size_t end_idx = std::string::npos;
 
   if (s[i] == '%')
     {
@@ -466,13 +469,13 @@
 	}
       else
 	*buf << s[i++];
+
+      nconv++;
     }
 
-  nconv++;
-
-  if (nconv > 0)
+  if (nconv >= 0)
     {
-      if (beg_idx >= 0 && end_idx >= 0)
+      if (beg_idx != std::string::npos && end_idx != std::string::npos)
 	char_class = expand_char_class (s.substr (beg_idx,
 						  end_idx - beg_idx + 1));
 
@@ -485,9 +488,9 @@
 void
 scanf_format_list::printme (void) const
 {
-  int n = list.length ();
-
-  for (int i = 0; i < n; i++)
+  octave_idx_type n = list.length ();
+
+  for (octave_idx_type i = 0; i < n; i++)
     {
       scanf_format_elt *elt = list(i);
 
@@ -513,11 +516,11 @@
 bool
 scanf_format_list::all_character_conversions (void)
 {
-  int n = list.length ();
+  octave_idx_type n = list.length ();
 
   if (n > 0)
     {
-      for (int i = 0; i < n; i++)
+      for (octave_idx_type i = 0; i < n; i++)
 	{
 	  scanf_format_elt *elt = list(i);
 
@@ -543,11 +546,11 @@
 bool
 scanf_format_list::all_numeric_conversions (void)
 {
-  int n = list.length ();
+  octave_idx_type n = list.length ();
 
   if (n > 0)
     {
-      for (int i = 0; i < n; i++)
+      for (octave_idx_type i = 0; i < n; i++)
 	{
 	  scanf_format_elt *elt = list(i);
 
@@ -574,11 +577,11 @@
 printf_format_list::printf_format_list (const std::string& s)
   : nconv (0), curr_idx (0), list (16), buf (0)
 {
-  int num_elts = 0;
-
-  int n = s.length ();
-
-  int i = 0;
+  octave_idx_type num_elts = 0;
+
+  size_t n = s.length ();
+
+  size_t i = 0;
 
   int args = 0;
   std::string flags;
@@ -660,9 +663,9 @@
 
 printf_format_list::~printf_format_list (void)
 {
-  int n = list.length ();
-
-  for (int i = 0; i < n; i++)
+  octave_idx_type n = list.length ();
+
+  for (octave_idx_type i = 0; i < n; i++)
     {
       printf_format_elt *elt = list(i);
       delete elt;
@@ -672,7 +675,7 @@
 void
 printf_format_list::add_elt_to_list (int args, const std::string& flags,
 				     int fw, int prec, char type,
-				     char modifier, int& num_elts)
+				     char modifier, octave_idx_type& num_elts)
 {
   if (buf)
     {
@@ -697,8 +700,8 @@
 
 void
 printf_format_list::process_conversion
-  (const std::string& s, int& i, int n, int& args, std::string& flags,
-   int& fw, int& prec, char& modifier, char& type, int& num_elts)
+  (const std::string& s, size_t& i, size_t n, int& args, std::string& flags,
+   int& fw, int& prec, char& modifier, char& type, octave_idx_type& num_elts)
 {
   args = 0;
   flags = "";
@@ -800,8 +803,8 @@
 
 void
 printf_format_list::finish_conversion
-  (const std::string& s, int& i, int args, const std::string& flags,
-   int fw, int prec, char modifier, char& type, int& num_elts)
+  (const std::string& s, size_t& i, int args, const std::string& flags,
+   int fw, int prec, char modifier, char& type, octave_idx_type& num_elts)
 
 {
   switch (s[i])
@@ -1717,7 +1720,7 @@
 
   conversion_count = 0;
 
-  int nconv = fmt_list.num_conversions ();
+  octave_idx_type nconv = fmt_list.num_conversions ();
 
   octave_idx_type data_index = 0;
 
@@ -1804,13 +1807,20 @@
 
       std::ios::fmtflags flags = is.flags ();
 
+      octave_idx_type trips = 0;
+
+      octave_idx_type num_fmt_elts = fmt_list.length ();
+
       for (;;)
 	{
 	  octave_quit ();
 
 	  if (elt)
 	    {
-	      if (max_conv > 0 && conversion_count == max_conv)
+	      if (! (elt->type == scanf_format_elt::whitespace_conversion
+                     || elt->type == scanf_format_elt::literal_conversion
+                     || elt->type == '%')
+                  && max_conv > 0 && conversion_count == max_conv)
 		{
 		  if (all_char_conv && one_elt_size_spec)
 		    {
@@ -2047,7 +2057,23 @@
 	      break;
 	    }
 
-	  elt = fmt_list.next (nconv > 0);
+          if (nconv == 0 && ++trips == num_fmt_elts)
+            {
+              if (all_char_conv && one_elt_size_spec)
+                {
+                  final_nr = 1;
+                  final_nc = data_index;
+                }
+              else
+                {
+                  final_nr = nr;
+                  final_nc = (data_index - 1) / nr + 1;
+                }
+
+              break;
+            }
+          else
+            elt = fmt_list.next (nconv > 0);
 	}
     }
 
@@ -2262,7 +2288,7 @@
 
       scanf_format_list fmt_list (fmt);
 
-      int nconv = fmt_list.num_conversions ();
+      octave_idx_type nconv = fmt_list.num_conversions ();
 
       if (nconv == -1)
 	::error ("%s: invalid format specified", who.c_str ());
@@ -2270,7 +2296,7 @@
 	{
 	  is.clear ();
 
-	  int len = fmt_list.length ();
+	  octave_idx_type len = fmt_list.length ();
 
 	  retval.resize (nconv+1, Matrix ());
 
@@ -2606,7 +2632,7 @@
 {
   int retval = 0;
 
-  int nconv = fmt_list.num_conversions ();
+  octave_idx_type nconv = fmt_list.num_conversions ();
 
   std::ostream *osp = output_stream ();
 
--- a/src/oct-stream.h	Fri Jan 22 07:30:44 2010 -0500
+++ b/src/oct-stream.h	Fri Jan 22 12:12:21 2010 -0500
@@ -108,14 +108,14 @@
 
   ~scanf_format_list (void);
 
-  int num_conversions (void) { return nconv; }
+  octave_idx_type num_conversions (void) { return nconv; }
 
   // The length can be different than the number of conversions.
   // For example, "x %d y %d z" has 2 conversions but the length of
   // the list is 3 because of the characters that appear after the
   // last conversion.
 
-  int length (void) { return list.length (); }
+  octave_idx_type length (void) { return list.length (); }
 
   const scanf_format_elt *first (void)
     {
@@ -154,10 +154,10 @@
 
   // Number of conversions specified by this format string, or -1 if
   // invalid conversions have been found.
-  int nconv;
+  octave_idx_type nconv;
 
   // Index to current element;
-  int curr_idx;
+  octave_idx_type curr_idx;
 
   // List of format elements.
   Array<scanf_format_elt*> list;
@@ -166,16 +166,16 @@
   std::ostringstream *buf;
 
   void add_elt_to_list (int width, bool discard, char type, char modifier,
-			int& num_elts,
+			octave_idx_type& num_elts,
 			const std::string& char_class = std::string ()); 
 
-  void process_conversion (const std::string& s, int& i, int n, int& width,
-			   bool& discard, char& type, char& modifier,
-			   int& num_elts);
+  void process_conversion (const std::string& s, size_t& i, size_t n,
+                           int& width, bool& discard, char& type,
+                           char& modifier, octave_idx_type& num_elts);
 
-  int finish_conversion (const std::string& s, int& i, int n, int& width,
-			 bool discard, char& type, char modifier,
-			 int& num_elts);
+  int finish_conversion (const std::string& s, size_t& i, size_t n,
+                         int& width, bool discard, char& type,
+                         char modifier, octave_idx_type& num_elts);
   // No copying!
 
   scanf_format_list (const scanf_format_list&);
@@ -249,7 +249,7 @@
 
   ~printf_format_list (void);
 
-  int num_conversions (void) { return nconv; }
+  octave_idx_type num_conversions (void) { return nconv; }
 
   const printf_format_elt *first (void)
     {
@@ -287,10 +287,10 @@
 
   // Number of conversions specified by this format string, or -1 if
   // invalid conversions have been found.
-  int nconv;
+  octave_idx_type nconv;
 
   // Index to current element;
-  int curr_idx;
+  octave_idx_type curr_idx;
 
   // List of format elements.
   Array<printf_format_elt*> list;
@@ -300,16 +300,17 @@
 
   void add_elt_to_list (int args, const std::string& flags, int fw,
 			int prec, char type, char modifier,
- 			int& num_elts);
+ 			octave_idx_type& num_elts);
  
-  void process_conversion (const std::string& s, int& i, int n,
+  void process_conversion (const std::string& s, size_t& i, size_t n,
 			   int& args, std::string& flags, int& fw,
 			   int& prec, char& modifier, char& type,
-			   int& num_elts); 
+			   octave_idx_type& num_elts); 
  
-  void finish_conversion (const std::string& s, int& i, int args,
+  void finish_conversion (const std::string& s, size_t& i, int args,
 			  const std::string& flags, int fw, int prec,
-			  char modifier, char& type, int& num_elts);
+			  char modifier, char& type,
+                          octave_idx_type& num_elts);
 
   // No copying!