Mercurial > hg > octave-nkf
diff src/oct-stream.cc @ 2215:ab0e1fd337f5
[project @ 1996-05-16 15:56:40 by jwe]
author | jwe |
---|---|
date | Thu, 16 May 1996 15:56:40 +0000 |
parents | c4a887694274 |
children | 59740768906f |
line wrap: on
line diff
--- a/src/oct-stream.cc +++ b/src/oct-stream.cc @@ -24,6 +24,8 @@ #include <config.h> #endif +#include <cstring> + #include <iomanip.h> #include <strstream.h> @@ -149,6 +151,7 @@ int i = 0; + int width = 0; bool discard = false; char modifier = '\0'; char type = '\0'; @@ -164,11 +167,13 @@ if (s[i] == '%') { - process_conversion (s, i, n, discard, type, modifier, num_elts); + process_conversion (s, i, n, width, discard, type, modifier, + num_elts); have_more = (buf != 0); } else { + width = 0; discard = false; modifier = '\0'; type = '\0'; @@ -183,7 +188,7 @@ } if (have_more) - add_elt_to_list (discard, type, modifier, num_elts); + add_elt_to_list (width, discard, type, modifier, num_elts); list.resize (num_elts); @@ -202,7 +207,7 @@ } void -scanf_format_list::add_elt_to_list (bool discard, char type, +scanf_format_list::add_elt_to_list (int width, bool discard, char type, char modifier, int& num_elts) { if (buf) @@ -216,7 +221,7 @@ if (*text) { scanf_format_elt *elt - = new scanf_format_elt (text, discard, type, modifier); + = new scanf_format_elt (text, width, discard, type, modifier); if (num_elts == list.length ()) list.resize (2 * num_elts); @@ -234,10 +239,11 @@ void scanf_format_list::process_conversion (const string& s, int& i, int n, - bool& discard, char& type, + int& width, bool& discard, char& type, char& modifier, int& num_elts) { + width = 0; discard = false; modifier = '\0'; type = '\0'; @@ -266,10 +272,16 @@ nconv = -1; else { + char c = s[i++]; + width = width * 10 + c - '0'; have_width = true; - *buf << s[i++]; + *buf << c; while (i < n && isdigit (s[i])) - *buf << s[i++]; + { + c = s[i++]; + width = width * 10 + c - '0'; + *buf << c; + } } break; @@ -309,7 +321,7 @@ fini: { - if (finish_conversion (s, i, n, discard, type, + if (finish_conversion (s, i, n, width, discard, type, modifier, num_elts) == 0) return; } @@ -329,7 +341,7 @@ int scanf_format_list::finish_conversion (const string& s, int& i, int n, - bool discard, char& type, + int& width, bool discard, char& type, char modifier, int& num_elts) { int retval = 0; @@ -365,23 +377,12 @@ retval = nconv = -1; } else - { - // XXX FIXME XXX -- this is a kludge, and probably not the - // right thing to do here. - - if (type == 's') - { - *buf << 'c'; - i++; - } - else - *buf << s[i++]; - } + *buf << s[i++]; nconv++; if (nconv > 0) - add_elt_to_list (discard, type, modifier, num_elts); + add_elt_to_list (width, discard, type, modifier, num_elts); } return retval; @@ -396,7 +397,8 @@ { scanf_format_elt *elt = list.elem (i); - cerr << elt->discard << "\t" + cerr << elt->width << "\t" + << elt->discard << "\t" << elt->type << "\t" << elt->modifier << "\t" << undo_string_escapes (elt->text) << "\n"; @@ -742,7 +744,7 @@ if (isp) { - istream is = *isp; + istream& is = *isp; // XXX FIXME XXX -- this should probably be converted to use // sstream when that is available. @@ -867,7 +869,7 @@ if (isp) { - istream is = *isp; + istream& is = *isp; for (;;) { @@ -1037,8 +1039,6 @@ #define do_scanf_conv(is, fmt, valptr, mval, data, idx, max_size, discard) \ do \ { \ - is.clear (); \ - \ is.scan (fmt, valptr); \ \ if (is) \ @@ -1104,7 +1104,7 @@ if (isp) { - istream is = *isp; + istream& is = *isp; const scanf_format_elt *elt = fmt_list.first (); @@ -1112,11 +1112,6 @@ for (;;) { - // Restore format flags in case we had to change them (note - // 'c' conversion below). - - is.setf (flags); - if (elt) { if (nr > 0 && nc > 0 && count == max_size) @@ -1137,8 +1132,7 @@ { int dummy; - do_scanf_conv (is, fmt, &dummy, mval, data, count, - max_size, discard); + is.scan (fmt, &dummy); } break; @@ -1176,15 +1170,55 @@ case 's': { - char tmp; - - do_scanf_conv (is, fmt, &tmp, mval, data, count, - max_size, discard); + int len = strlen (fmt); + char *tmp_fmt = new char [len+1]; + strcpy (tmp_fmt, fmt); + if (tmp_fmt[len-1] == 's') + tmp_fmt[len-1] = 'c'; + + int width = elt->width ? elt->width : 1; + + char *tmp = new char [width+1]; + + is.scan (tmp_fmt, tmp); + + delete [] tmp_fmt; + + tmp[width] = '\0'; + + if (is) + { + int i = 0; + + if (! discard) + { + while (i < width && tmp[i] != '\0') + { + if (count == max_size) + { + max_size *= 2; + + if (nr > 0) + mval.resize (nr, max_size / nr, 0.0); + else + mval.resize (max_size, 1, 0.0); + + data = mval.fortran_vec (); + } + + data[count++] = tmp[i++]; + } + } + } + + delete [] tmp; + + is.setf (flags); } break; case 'p': case '[': - error ("fscanf: unrecognized format specifier"); + error ("fscanf: unsupported format specifier"); break; default: @@ -1273,10 +1307,6 @@ octave_base_stream::scanf (const string& fmt, const Matrix& size, int& count) { - // XXX FIXME XXX -- is this the right thing to do? - if (name () == "stdin") - fail = false; - octave_value retval = Matrix (); count = 0; @@ -1285,7 +1315,7 @@ if (isp) { - istream is = *isp; + istream& is = *isp; scanf_format_list fmt_list (fmt); @@ -1310,6 +1340,221 @@ error ("fscanf: read error"); // XXX FIXME XXX -- is this the right thing to do? + + if (name () == "stdin") + { + is.clear (); + + // Skip to end of line. + + bool err; + do_gets (-1, err, false, "fscanf"); + } + } + } + } + break; + + default: + { + int nr = -1; + int nc = -1; + + get_size (size, nr, nc, "fscanf"); + + if (! error_state) + retval = do_scanf (fmt_list, nr, nc, count); + } + break; + } + } + else + invalid_operation ("fscanf", "writing"); + + return retval; +} + +#define do_oscanf_num_conv(is, fmt, valptr) \ + do \ + { \ + streambuf *isb = is.rdbuf (); \ + \ + if (isb->scan (fmt, valptr) > 0) \ + { \ + if (! discard && is) \ + retval = (double) (*valptr); \ + } \ + else \ + error ("fscanf: conversion failed"); \ + } \ + while (0) + +#define do_oscanf_str_conv(is, fmt, sptr, maxlen) \ + do \ + { \ + streambuf *isb = is.rdbuf (); \ + \ + if (isb->scan (fmt, sptr) > 0) \ + { \ + if (! discard && is) \ + { \ + sptr[maxlen] = '\0'; \ + retval = sptr; \ + } \ + } \ + else \ + error ("fscanf: conversion failed"); \ + } \ + while (0) + +octave_value +octave_base_stream::do_oscanf (const scanf_format_elt *elt) +{ + octave_value retval = Matrix (); + + istream *isp = input_stream (); + + if (isp) + { + istream& is = *isp; + + ios::fmtflags flags = is.flags (); + + if (elt) + { + const char *fmt = elt->text; + + bool discard = elt->discard; + + switch (elt->type) + { + case '%': + { + int dummy; + + is.scan (fmt, &dummy); + } + break; + + case 'd': case 'i': case 'o': case 'u': case 'x': + { + int tmp; + + do_oscanf_num_conv (is, fmt, &tmp); + } + break; + + case 'e': case 'f': case 'g': + { + if (elt->modifier == 'l') + { + double tmp; + + do_oscanf_num_conv (is, fmt, &tmp); + } + else + { + float tmp; + + do_oscanf_num_conv (is, fmt, &tmp); + } + } + break; + + case 'c': + { + is.unsetf (ios::skipws); + + int width = elt->width ? elt->width : 1; + + char *tmp = new char[width + 1]; + + do_oscanf_str_conv (is, fmt, tmp, width); + + is.setf (flags); + + delete [] tmp; + } + break; + + case 's': + { + // XXX FIXME XXX -- this must be fixed! + + int width = 65535; + char *tmp = new char [width+1]; + do_oscanf_str_conv (is, fmt, tmp, width); + delete [] tmp; + } + break; + + case 'p': case '[': + error ("fscanf: unsupported format specifier"); + break; + + default: + error ("fscanf: internal format error"); + break; + } + } + + if (ok () && is.fail ()) + { + error ("fscanf: read error"); + + // XXX FIXME XXX -- is this the right thing to do? + // What about other streams? + if (name () == "stdin") + { + is.clear (); + + // Skip to end of line. + + bool err; + do_gets (-1, err, false, "fscanf"); + } + } + } + + return retval; +} + +octave_value_list +octave_base_stream::oscanf (const string& fmt) +{ + octave_value_list retval; + + istream *isp = input_stream (); + + if (isp) + { + istream& is = *isp; + + scanf_format_list fmt_list (fmt); + + int nconv = fmt_list.num_conversions (); + + switch (nconv) + { + case -1: + ::error ("fscanf: invalid format specified"); + break; + + case 0: + { + const scanf_format_elt *elt = fmt_list.first (); + + if (elt) + { + is.clear (); + + is.scan (elt->text); + + if (! is) + { + error ("fscanf: read error"); + + // XXX FIXME XXX -- is this the right thing to do? // Maybe. We should probably also arrange to // flush the pending input prior to printing a // prompt. Or maybe just blow off scanf for stdin @@ -1331,13 +1576,25 @@ default: { - int nr = -1; - int nc = -1; - - get_size (size, nr, nc, "fscanf"); - - if (! error_state) - retval = do_scanf (fmt_list, nr, nc, count); + int len = fmt_list.length (); + + retval.resize (nconv, Matrix ()); + + const scanf_format_elt *elt = fmt_list.first (); + + for (int i = 0; i < nconv; i++) + { + retval (i) = do_oscanf (elt); + + if (! ok ()) + break; + + elt = fmt_list.next (); + } + + // Pick up any trailing stuff. + if (ok () && len > nconv) + do_oscanf (elt); } break; } @@ -1393,7 +1650,7 @@ if (osp) { - ostream os = *osp; + ostream& os = *osp; // XXX FIXME XXX -- maybe there should be a special case for // skip == 0. @@ -1714,7 +1971,7 @@ if (osp) { - ostream os = *osp; + ostream& os = *osp; const printf_format_elt *elt = fmt_list.first (); @@ -1844,7 +2101,7 @@ if (osp) { - ostream os = *osp; + ostream& os = *osp; printf_format_list fmt_list (fmt); @@ -1895,7 +2152,7 @@ if (osp) { - ostream os = *osp; + ostream& os = *osp; os << s; @@ -2146,6 +2403,17 @@ return retval; } +octave_value_list +octave_stream::oscanf (const string& fmt) +{ + octave_value_list retval; + + if (stream_ok ("fscanf")) + retval = rep->oscanf (fmt); + + return retval; +} + int octave_stream::printf (const string& fmt, const octave_value_list& args) { @@ -2205,8 +2473,6 @@ if (stream_ok ("ferror", false)) retval = rep->error (clear, errno); - cerr << retval; - return retval; }