changeset 19083:c573d9c70ae5

Better checks for valid format conversion specifiers in textscan. & strread.m * textscan.m: more rigid format conversion specifier check & test added * strread.m: more rigid format conversion specifier check & test added more to-the-point error messages
author Philip Nienhuis <prnienhuis@users.sf.net>
date Wed, 13 Aug 2014 21:29:53 +0200
parents ec28b7216501
children 2f117c4b5cb0
files scripts/io/strread.m scripts/io/textscan.m
diffstat 2 files changed, 18 insertions(+), 5 deletions(-) [+]
line wrap: on
line diff
--- a/scripts/io/strread.m	Sun Aug 24 15:25:21 2014 -0700
+++ b/scripts/io/strread.m	Wed Aug 13 21:29:53 2014 +0200
@@ -197,10 +197,12 @@
   endif
 
   ## Parse format string to compare number of conversion fields and nargout
-  nfields = length (strfind (format, "%")) - length (strfind (format, "%*"));
+  nfields = numel (regexp (format, '(%(\d*|\d*\.\d*)?[nfduscq]|%\[)', "match"));
   ## If str only has numeric fields, a (default) format ("%f") will do.
   ## Otherwise:
-  if ((max (nargout, 1) != nfields) && ! strcmp (format, "%f"))
+  if (! nfields)
+    error ("strread.m: no valid format conversion specifiers found\n");
+  elseif ((max (nargout, 1) != nfields) && ! strcmp (format, "%f"))
     error ("strread: the number of output variables must match that specified by FORMAT");
   endif
 
@@ -304,7 +306,8 @@
     fmt_words = regexp (format, '[^ ]+', "match");
     
     ## Find position of conversion specifiers (they start with %)
-    idy2 = find (! cellfun ("isempty", regexp (fmt_words, '^%')));
+    fcs_ptrn = '(%\*?(\d*|\d*\.\d*)?[nfduscq]|%\*?\[)';
+    idy2 = find (! cellfun ("isempty", regexp (fmt_words, fcs_ptrn)));
 
     ## Check for unsupported format specifiers
     errpat = '(\[.*\]|[cq]|[nfdu]8|[nfdu]16|[nfdu]32|[nfdu]64)';
@@ -1034,5 +1037,8 @@
 
 %% Illegal format specifiers
 %!test
-%!error <unknown format specifier> strread ("1.0", "%z")
+%!error <no valid format conversion specifiers> strread ("1.0", "%z");
 
+%% Test for false positives in check for non-supported format specifiers
+%!test
+%! assert (strread ("Total: 32.5 % (of cm values)","Total: %f % (of cm values)"), 32.5, 1e-5);
--- a/scripts/io/textscan.m	Sun Aug 24 15:25:21 2014 -0700
+++ b/scripts/io/textscan.m	Wed Aug 13 21:29:53 2014 +0200
@@ -98,7 +98,10 @@
   endif
 
   ## Determine the number of data fields & initialize output array
-  num_fields = numel (strfind (format, "%")) - numel (strfind (format, "%*"));
+  num_fields = numel (regexp (format, '(%(\d*|\d*\.\d*)?[nfduscq]|%\[)', "match"));
+  if (! num_fields)
+    error ("textscan.m: no valid format conversion specifiers found\n");
+  endif
   C = cell (1, num_fields);
 
   if (! (isa (fid, "double") && fid > 0) && ! ischar (fid))
@@ -681,3 +684,7 @@
 %!test
 %! assert (textscan ("1i", ""){1},  0+1i);
 %! assert (cell2mat (textscan ("3, 2-4i, NaN\n -i, 1, 23.4+2.2i", "")), [3+0i, 2-4i, NaN+0i; 0-i,  1+0i, 23.4+2.2i]);
+
+%% Illegal format specifiers
+%!test
+%!error <no valid format conversion specifiers> textscan ("1.0", "%z");