00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #ifdef HAVE_CONFIG_H
00024 #include <config.h>
00025 #endif
00026
00027 #include <cassert>
00028 #include <cctype>
00029 #include <cstring>
00030
00031 #include <iomanip>
00032 #include <iostream>
00033 #include <fstream>
00034 #include <sstream>
00035 #include <string>
00036
00037 #include <Array.h>
00038
00039 #include "byte-swap.h"
00040 #include "lo-ieee.h"
00041 #include "lo-mappers.h"
00042 #include "lo-utils.h"
00043 #include "quit.h"
00044 #include "singleton-cleanup.h"
00045 #include "str-vec.h"
00046
00047 #include "error.h"
00048 #include "gripes.h"
00049 #include "input.h"
00050 #include "oct-stdstrm.h"
00051 #include "oct-stream.h"
00052 #include "oct-obj.h"
00053 #include "utils.h"
00054
00055
00056
00057
00058
00059
00060
00061 static int
00062 convert_to_valid_int (const octave_value& tc, int& conv_err)
00063 {
00064 int retval = 0;
00065
00066 conv_err = 0;
00067
00068 double dval = tc.double_value ();
00069
00070 if (! error_state)
00071 {
00072 if (! lo_ieee_isnan (dval))
00073 {
00074 int ival = NINT (dval);
00075
00076 if (ival == dval)
00077 retval = ival;
00078 else
00079 conv_err = 3;
00080 }
00081 else
00082 conv_err = 2;
00083 }
00084 else
00085 conv_err = 1;
00086
00087 return retval;
00088 }
00089
00090 static int
00091 get_size (double d, const std::string& who)
00092 {
00093 int retval = -1;
00094
00095 if (! lo_ieee_isnan (d))
00096 {
00097 if (! xisinf (d))
00098 {
00099 if (d >= 0.0)
00100 retval = NINT (d);
00101 else
00102 ::error ("%s: negative value invalid as size specification",
00103 who.c_str ());
00104 }
00105 else
00106 retval = -1;
00107 }
00108 else
00109 ::error ("%s: NaN is invalid as size specification", who.c_str ());
00110
00111 return retval;
00112 }
00113
00114 static void
00115 get_size (const Array<double>& size, octave_idx_type& nr, octave_idx_type& nc, bool& one_elt_size_spec,
00116 const std::string& who)
00117 {
00118 nr = -1;
00119 nc = -1;
00120
00121 one_elt_size_spec = false;
00122
00123 double dnr = -1.0;
00124 double dnc = -1.0;
00125
00126 octave_idx_type sz_len = size.length ();
00127
00128 if (sz_len == 1)
00129 {
00130 one_elt_size_spec = true;
00131
00132 dnr = size (0);
00133
00134 dnc = (dnr == 0.0) ? 0.0 : 1.0;
00135 }
00136 else if (sz_len == 2)
00137 {
00138 dnr = size (0);
00139
00140 if (! xisinf (dnr))
00141 dnc = size (1);
00142 else
00143 ::error ("%s: invalid size specification", who.c_str ());
00144 }
00145 else
00146 ::error ("%s: invalid size specification", who.c_str ());
00147
00148 if (! error_state)
00149 {
00150 nr = get_size (dnr, who);
00151
00152 if (! error_state && dnc >= 0.0)
00153 nc = get_size (dnc, who);
00154 }
00155 }
00156
00157 scanf_format_list::scanf_format_list (const std::string& s)
00158 : nconv (0), curr_idx (0), list (dim_vector (16, 1)), buf (0)
00159 {
00160 octave_idx_type num_elts = 0;
00161
00162 size_t n = s.length ();
00163
00164 size_t i = 0;
00165
00166 int width = 0;
00167 bool discard = false;
00168 char modifier = '\0';
00169 char type = '\0';
00170
00171 bool have_more = true;
00172
00173 while (i < n)
00174 {
00175 have_more = true;
00176
00177 if (! buf)
00178 buf = new std::ostringstream ();
00179
00180 if (s[i] == '%')
00181 {
00182
00183
00184 process_conversion (s, i, n, width, discard, type, modifier,
00185 num_elts);
00186
00187 have_more = (buf != 0);
00188 }
00189 else if (isspace (s[i]))
00190 {
00191 type = scanf_format_elt::whitespace_conversion;
00192
00193 width = 0;
00194 discard = false;
00195 modifier = '\0';
00196 *buf << " ";
00197
00198 while (++i < n && isspace (s[i]))
00199 ;
00200
00201 add_elt_to_list (width, discard, type, modifier, num_elts);
00202
00203 have_more = false;
00204 }
00205 else
00206 {
00207 type = scanf_format_elt::literal_conversion;
00208
00209 width = 0;
00210 discard = false;
00211 modifier = '\0';
00212
00213 while (i < n && ! isspace (s[i]) && s[i] != '%')
00214 *buf << s[i++];
00215
00216 add_elt_to_list (width, discard, type, modifier, num_elts);
00217
00218 have_more = false;
00219 }
00220
00221 if (nconv < 0)
00222 {
00223 have_more = false;
00224 break;
00225 }
00226 }
00227
00228 if (have_more)
00229 add_elt_to_list (width, discard, type, modifier, num_elts);
00230
00231 list.resize (dim_vector (num_elts, 1));
00232
00233 delete buf;
00234 }
00235
00236 scanf_format_list::~scanf_format_list (void)
00237 {
00238 octave_idx_type n = list.length ();
00239
00240 for (octave_idx_type i = 0; i < n; i++)
00241 {
00242 scanf_format_elt *elt = list(i);
00243 delete elt;
00244 }
00245 }
00246
00247 void
00248 scanf_format_list::add_elt_to_list (int width, bool discard, char type,
00249 char modifier, octave_idx_type& num_elts,
00250 const std::string& char_class)
00251 {
00252 if (buf)
00253 {
00254 std::string text = buf->str ();
00255
00256 if (! text.empty ())
00257 {
00258 scanf_format_elt *elt
00259 = new scanf_format_elt (text.c_str (), width, discard, type,
00260 modifier, char_class);
00261
00262 if (num_elts == list.length ())
00263 list.resize (dim_vector (2 * num_elts, 1));
00264
00265 list(num_elts++) = elt;
00266 }
00267
00268 delete buf;
00269 buf = 0;
00270 }
00271 }
00272
00273 static std::string
00274 expand_char_class (const std::string& s)
00275 {
00276 std::string retval;
00277
00278 size_t len = s.length ();
00279
00280 size_t i = 0;
00281
00282 while (i < len)
00283 {
00284 unsigned char c = s[i++];
00285
00286 if (c == '-' && i > 1 && i < len
00287 && static_cast<unsigned char> (s[i-2]) <= static_cast<unsigned char> (s[i]))
00288 {
00289
00290
00291
00292 for (c = s[i-2]+1; c < s[i]; c++)
00293 retval += c;
00294 }
00295 else
00296 {
00297
00298
00299
00300 if (c != '-' || i == len)
00301 retval += c;
00302 }
00303 }
00304
00305 return retval;
00306 }
00307
00308 void
00309 scanf_format_list::process_conversion (const std::string& s, size_t& i,
00310 size_t n, int& width, bool& discard,
00311 char& type, char& modifier,
00312 octave_idx_type& num_elts)
00313 {
00314 width = 0;
00315 discard = false;
00316 modifier = '\0';
00317 type = '\0';
00318
00319 *buf << s[i++];
00320
00321 bool have_width = false;
00322
00323 while (i < n)
00324 {
00325 switch (s[i])
00326 {
00327 case '*':
00328 if (discard)
00329 nconv = -1;
00330 else
00331 {
00332 discard = true;
00333 *buf << s[i++];
00334 }
00335 break;
00336
00337 case '0': case '1': case '2': case '3': case '4':
00338 case '5': case '6': case '7': case '8': case '9':
00339 if (have_width)
00340 nconv = -1;
00341 else
00342 {
00343 char c = s[i++];
00344 width = width * 10 + c - '0';
00345 have_width = true;
00346 *buf << c;
00347 while (i < n && isdigit (s[i]))
00348 {
00349 c = s[i++];
00350 width = width * 10 + c - '0';
00351 *buf << c;
00352 }
00353 }
00354 break;
00355
00356 case 'h': case 'l': case 'L':
00357 if (modifier != '\0')
00358 nconv = -1;
00359 else
00360 modifier = s[i++];
00361 break;
00362
00363 case 'd': case 'i': case 'o': case 'u': case 'x':
00364 if (modifier == 'L')
00365 {
00366 nconv = -1;
00367 break;
00368 }
00369 goto fini;
00370
00371 case 'e': case 'f': case 'g':
00372 if (modifier == 'h')
00373 {
00374 nconv = -1;
00375 break;
00376 }
00377
00378
00379 *buf << 'l';
00380
00381 goto fini;
00382
00383 case 'c': case 's': case 'p': case '%': case '[':
00384 if (modifier != '\0')
00385 {
00386 nconv = -1;
00387 break;
00388 }
00389 goto fini;
00390
00391 fini:
00392 {
00393 if (finish_conversion (s, i, n, width, discard, type,
00394 modifier, num_elts) == 0)
00395 return;
00396 }
00397 break;
00398
00399 default:
00400 nconv = -1;
00401 break;
00402 }
00403
00404 if (nconv < 0)
00405 break;
00406 }
00407
00408 nconv = -1;
00409 }
00410
00411 int
00412 scanf_format_list::finish_conversion (const std::string& s, size_t& i,
00413 size_t n, int& width, bool discard,
00414 char& type, char modifier,
00415 octave_idx_type& num_elts)
00416 {
00417 int retval = 0;
00418
00419 std::string char_class;
00420
00421 size_t beg_idx = std::string::npos;
00422 size_t end_idx = std::string::npos;
00423
00424 if (s[i] == '%')
00425 {
00426 type = '%';
00427 *buf << s[i++];
00428 }
00429 else
00430 {
00431 type = s[i];
00432
00433 if (s[i] == '[')
00434 {
00435 *buf << s[i++];
00436
00437 if (i < n)
00438 {
00439 beg_idx = i;
00440
00441 if (s[i] == '^')
00442 {
00443 type = '^';
00444 *buf << s[i++];
00445
00446 if (i < n)
00447 {
00448 beg_idx = i;
00449
00450 if (s[i] == ']')
00451 *buf << s[i++];
00452 }
00453 }
00454 else if (s[i] == ']')
00455 *buf << s[i++];
00456 }
00457
00458 while (i < n && s[i] != ']')
00459 *buf << s[i++];
00460
00461 if (i < n && s[i] == ']')
00462 {
00463 end_idx = i-1;
00464 *buf << s[i++];
00465 }
00466
00467 if (s[i-1] != ']')
00468 retval = nconv = -1;
00469 }
00470 else
00471 *buf << s[i++];
00472
00473 nconv++;
00474 }
00475
00476 if (nconv >= 0)
00477 {
00478 if (beg_idx != std::string::npos && end_idx != std::string::npos)
00479 char_class = expand_char_class (s.substr (beg_idx,
00480 end_idx - beg_idx + 1));
00481
00482 add_elt_to_list (width, discard, type, modifier, num_elts, char_class);
00483 }
00484
00485 return retval;
00486 }
00487
00488 void
00489 scanf_format_list::printme (void) const
00490 {
00491 octave_idx_type n = list.length ();
00492
00493 for (octave_idx_type i = 0; i < n; i++)
00494 {
00495 scanf_format_elt *elt = list(i);
00496
00497 std::cerr
00498 << "width: " << elt->width << "\n"
00499 << "discard: " << elt->discard << "\n"
00500 << "type: ";
00501
00502 if (elt->type == scanf_format_elt::literal_conversion)
00503 std::cerr << "literal text\n";
00504 else if (elt->type == scanf_format_elt::whitespace_conversion)
00505 std::cerr << "whitespace\n";
00506 else
00507 std::cerr << elt->type << "\n";
00508
00509 std::cerr
00510 << "modifier: " << elt->modifier << "\n"
00511 << "char_class: '" << undo_string_escapes (elt->char_class) << "'\n"
00512 << "text: '" << undo_string_escapes (elt->text) << "'\n\n";
00513 }
00514 }
00515
00516 bool
00517 scanf_format_list::all_character_conversions (void)
00518 {
00519 octave_idx_type n = list.length ();
00520
00521 if (n > 0)
00522 {
00523 for (octave_idx_type i = 0; i < n; i++)
00524 {
00525 scanf_format_elt *elt = list(i);
00526
00527 switch (elt->type)
00528 {
00529 case 'c': case 's': case '%': case '[': case '^':
00530 case scanf_format_elt::literal_conversion:
00531 case scanf_format_elt::whitespace_conversion:
00532 break;
00533
00534 default:
00535 return false;
00536 break;
00537 }
00538 }
00539
00540 return true;
00541 }
00542 else
00543 return false;
00544 }
00545
00546 bool
00547 scanf_format_list::all_numeric_conversions (void)
00548 {
00549 octave_idx_type n = list.length ();
00550
00551 if (n > 0)
00552 {
00553 for (octave_idx_type i = 0; i < n; i++)
00554 {
00555 scanf_format_elt *elt = list(i);
00556
00557 switch (elt->type)
00558 {
00559 case 'd': case 'i': case 'o': case 'u': case 'x':
00560 case 'e': case 'f': case 'g':
00561 break;
00562
00563 default:
00564 return false;
00565 break;
00566 }
00567 }
00568
00569 return true;
00570 }
00571 else
00572 return false;
00573 }
00574
00575
00576
00577 printf_format_list::printf_format_list (const std::string& s)
00578 : nconv (0), curr_idx (0), list (dim_vector (16, 1)), buf (0)
00579 {
00580 octave_idx_type num_elts = 0;
00581
00582 size_t n = s.length ();
00583
00584 size_t i = 0;
00585
00586 int args = 0;
00587 std::string flags;
00588 int fw = 0;
00589 int prec = 0;
00590 char modifier = '\0';
00591 char type = '\0';
00592
00593 bool have_more = true;
00594 bool empty_buf = true;
00595
00596 if (n == 0)
00597 {
00598 printf_format_elt *elt
00599 = new printf_format_elt ("", args, fw, prec, flags, type, modifier);
00600
00601 list(num_elts++) = elt;
00602
00603 list.resize (dim_vector (num_elts, 1));
00604 }
00605 else
00606 {
00607 while (i < n)
00608 {
00609 have_more = true;
00610
00611 if (! buf)
00612 {
00613 buf = new std::ostringstream ();
00614 empty_buf = true;
00615 }
00616
00617 switch (s[i])
00618 {
00619 case '%':
00620 {
00621 if (empty_buf)
00622 {
00623 process_conversion (s, i, n, args, flags, fw, prec,
00624 type, modifier, num_elts);
00625
00626 have_more = (buf != 0);
00627 }
00628 else
00629 add_elt_to_list (args, flags, fw, prec, type, modifier,
00630 num_elts);
00631 }
00632 break;
00633
00634 default:
00635 {
00636 args = 0;
00637 flags = "";
00638 fw = 0;
00639 prec = 0;
00640 modifier = '\0';
00641 type = '\0';
00642 *buf << s[i++];
00643 empty_buf = false;
00644 }
00645 break;
00646 }
00647
00648 if (nconv < 0)
00649 {
00650 have_more = false;
00651 break;
00652 }
00653 }
00654
00655 if (have_more)
00656 add_elt_to_list (args, flags, fw, prec, type, modifier, num_elts);
00657
00658 list.resize (dim_vector (num_elts, 1));
00659
00660 delete buf;
00661 }
00662 }
00663
00664 printf_format_list::~printf_format_list (void)
00665 {
00666 octave_idx_type n = list.length ();
00667
00668 for (octave_idx_type i = 0; i < n; i++)
00669 {
00670 printf_format_elt *elt = list(i);
00671 delete elt;
00672 }
00673 }
00674
00675 void
00676 printf_format_list::add_elt_to_list (int args, const std::string& flags,
00677 int fw, int prec, char type,
00678 char modifier, octave_idx_type& num_elts)
00679 {
00680 if (buf)
00681 {
00682 std::string text = buf->str ();
00683
00684 if (! text.empty ())
00685 {
00686 printf_format_elt *elt
00687 = new printf_format_elt (text.c_str (), args, fw, prec, flags,
00688 type, modifier);
00689
00690 if (num_elts == list.length ())
00691 list.resize (dim_vector (2 * num_elts, 1));
00692
00693 list(num_elts++) = elt;
00694 }
00695
00696 delete buf;
00697 buf = 0;
00698 }
00699 }
00700
00701 void
00702 printf_format_list::process_conversion
00703 (const std::string& s, size_t& i, size_t n, int& args, std::string& flags,
00704 int& fw, int& prec, char& modifier, char& type, octave_idx_type& num_elts)
00705 {
00706 args = 0;
00707 flags = "";
00708 fw = 0;
00709 prec = 0;
00710 modifier = '\0';
00711 type = '\0';
00712
00713 *buf << s[i++];
00714
00715 bool nxt = false;
00716
00717 while (i < n)
00718 {
00719 switch (s[i])
00720 {
00721 case '-': case '+': case ' ': case '0': case '#':
00722 flags += s[i];
00723 *buf << s[i++];
00724 break;
00725
00726 default:
00727 nxt = true;
00728 break;
00729 }
00730
00731 if (nxt)
00732 break;
00733 }
00734
00735 if (i < n)
00736 {
00737 if (s[i] == '*')
00738 {
00739 fw = -1;
00740 args++;
00741 *buf << s[i++];
00742 }
00743 else
00744 {
00745 if (isdigit (s[i]))
00746 {
00747 int nn = 0;
00748 std::string tmp = s.substr (i);
00749 sscanf (tmp.c_str (), "%d%n", &fw, &nn);
00750 }
00751
00752 while (i < n && isdigit (s[i]))
00753 *buf << s[i++];
00754 }
00755 }
00756
00757 if (i < n && s[i] == '.')
00758 {
00759 *buf << s[i++];
00760
00761 if (i < n)
00762 {
00763 if (s[i] == '*')
00764 {
00765 prec = -1;
00766 args++;
00767 *buf << s[i++];
00768 }
00769 else
00770 {
00771 if (isdigit (s[i]))
00772 {
00773 int nn = 0;
00774 std::string tmp = s.substr (i);
00775 sscanf (tmp.c_str (), "%d%n", &prec, &nn);
00776 }
00777
00778 while (i < n && isdigit (s[i]))
00779 *buf << s[i++];
00780 }
00781 }
00782 }
00783
00784 if (i < n)
00785 {
00786 switch (s[i])
00787 {
00788 case 'h': case 'l': case 'L':
00789 modifier = s[i];
00790 *buf << s[i++];
00791 break;
00792
00793 default:
00794 break;
00795 }
00796 }
00797
00798 if (i < n)
00799 finish_conversion (s, i, args, flags, fw, prec, modifier, type, num_elts);
00800 else
00801 nconv = -1;
00802 }
00803
00804 void
00805 printf_format_list::finish_conversion
00806 (const std::string& s, size_t& i, int args, const std::string& flags,
00807 int fw, int prec, char modifier, char& type, octave_idx_type& num_elts)
00808
00809 {
00810 switch (s[i])
00811 {
00812 case 'd': case 'i': case 'o': case 'x': case 'X':
00813 case 'u': case 'c':
00814 if (modifier == 'L')
00815 {
00816 nconv = -1;
00817 break;
00818 }
00819 goto fini;
00820
00821 case 'f': case 'e': case 'E': case 'g': case 'G':
00822 if (modifier == 'h' || modifier == 'l')
00823 {
00824 nconv = -1;
00825 break;
00826 }
00827 goto fini;
00828
00829 case 's': case 'p': case '%':
00830 if (modifier != '\0')
00831 {
00832 nconv = -1;
00833 break;
00834 }
00835 goto fini;
00836
00837 fini:
00838
00839 type = s[i];
00840
00841 *buf << s[i++];
00842
00843 if (type != '%' || args != 0)
00844 nconv++;
00845
00846 if (type != '%')
00847 args++;
00848
00849 add_elt_to_list (args, flags, fw, prec, type, modifier, num_elts);
00850
00851 break;
00852
00853 default:
00854 nconv = -1;
00855 break;
00856 }
00857 }
00858
00859 void
00860 printf_format_list::printme (void) const
00861 {
00862 int n = list.length ();
00863
00864 for (int i = 0; i < n; i++)
00865 {
00866 printf_format_elt *elt = list(i);
00867
00868 std::cerr
00869 << "args: " << elt->args << "\n"
00870 << "flags: '" << elt->flags << "'\n"
00871 << "width: " << elt->fw << "\n"
00872 << "prec: " << elt->prec << "\n"
00873 << "type: '" << elt->type << "'\n"
00874 << "modifier: '" << elt->modifier << "'\n"
00875 << "text: '" << undo_string_escapes (elt->text) << "'\n\n";
00876 }
00877 }
00878
00879 void
00880 octave_base_stream::error (const std::string& msg)
00881 {
00882 fail = true;
00883 errmsg = msg;
00884 }
00885
00886 void
00887 octave_base_stream::error (const std::string& who, const std::string& msg)
00888 {
00889 fail = true;
00890 errmsg = who + ": " + msg;
00891 }
00892
00893 void
00894 octave_base_stream::clear (void)
00895 {
00896 fail = false;
00897 errmsg = "";
00898 }
00899
00900 void
00901 octave_base_stream::clearerr (void)
00902 {
00903 std::istream *is = input_stream ();
00904 std::ostream *os = output_stream ();
00905
00906 if (is)
00907 is->clear ();
00908
00909 if (os)
00910 os->clear ();
00911 }
00912
00913
00914
00915
00916 std::string
00917 octave_base_stream::do_gets (octave_idx_type max_len, bool& err,
00918 bool strip_newline, const std::string& who)
00919 {
00920 std::string retval;
00921
00922 if ((interactive || forced_interactive) && file_number () == 0)
00923 {
00924 ::error ("%s: unable to read from stdin while running interactively",
00925 who.c_str ());
00926
00927 return retval;
00928 }
00929
00930 err = false;
00931
00932 std::istream *isp = input_stream ();
00933
00934 if (isp)
00935 {
00936 std::istream& is = *isp;
00937
00938 std::ostringstream buf;
00939
00940 int c = 0;
00941 int char_count = 0;
00942
00943 if (max_len != 0)
00944 {
00945 while (is && (c = is.get ()) != EOF)
00946 {
00947 char_count++;
00948
00949
00950
00951 if (c == '\r')
00952 {
00953 if (! strip_newline)
00954 buf << static_cast<char> (c);
00955
00956 c = is.get ();
00957
00958 if (c != EOF)
00959 {
00960 if (c == '\n')
00961 {
00962 char_count++;
00963
00964 if (! strip_newline)
00965 buf << static_cast<char> (c);
00966 }
00967 else
00968 is.putback (c);
00969 }
00970
00971 break;
00972 }
00973 else if (c == '\n')
00974 {
00975 if (! strip_newline)
00976 buf << static_cast<char> (c);
00977
00978 break;
00979 }
00980 else
00981 buf << static_cast<char> (c);
00982
00983 if (max_len > 0 && char_count == max_len)
00984 break;
00985 }
00986 }
00987
00988 if (! is.eof () && char_count > 0)
00989 {
00990
00991
00992
00993 int disgusting_compatibility_hack = is.get ();
00994 if (! is.eof ())
00995 is.putback (disgusting_compatibility_hack);
00996 }
00997
00998 if (is.good () || (is.eof () && char_count > 0))
00999 retval = buf.str ();
01000 else
01001 {
01002 err = true;
01003
01004 if (is.eof () && char_count == 0)
01005 error (who, "at end of file");
01006 else
01007 error (who, "read error");
01008 }
01009 }
01010 else
01011 {
01012 err = true;
01013 invalid_operation (who, "reading");
01014 }
01015
01016 return retval;
01017 }
01018
01019 std::string
01020 octave_base_stream::getl (octave_idx_type max_len, bool& err, const std::string& who)
01021 {
01022 return do_gets (max_len, err, true, who);
01023 }
01024
01025 std::string
01026 octave_base_stream::gets (octave_idx_type max_len, bool& err, const std::string& who)
01027 {
01028 return do_gets (max_len, err, false, who);
01029 }
01030
01031 long
01032 octave_base_stream::skipl (long num, bool& err, const std::string& who)
01033 {
01034 long cnt = -1;
01035
01036 if ((interactive || forced_interactive) && file_number () == 0)
01037 {
01038 ::error ("%s: unable to read from stdin while running interactively",
01039 who.c_str ());
01040
01041 return count;
01042 }
01043
01044 err = false;
01045
01046 std::istream *isp = input_stream ();
01047
01048 if (isp)
01049 {
01050 std::istream& is = *isp;
01051
01052 int c = 0, lastc = -1;
01053 cnt = 0;
01054
01055 while (is && (c = is.get ()) != EOF)
01056 {
01057
01058
01059 if (c == '\r' || (c == '\n' && lastc != '\r'))
01060 {
01061 if (++cnt == num)
01062 break;
01063 }
01064
01065 lastc = c;
01066 }
01067
01068
01069 if (c == '\r' && is.peek () == '\n')
01070 is.get ();
01071
01072 if (is.bad ())
01073 {
01074 err = true;
01075 error (who, "read error");
01076 }
01077
01078 if (err)
01079 cnt = -1;
01080 }
01081 else
01082 {
01083 err = true;
01084 invalid_operation (who, "reading");
01085 }
01086
01087 return cnt;
01088 }
01089
01090 #define OCTAVE_SCAN(is, fmt, arg) octave_scan (is, fmt, arg)
01091
01092 template <class T>
01093 std::istream&
01094 octave_scan_1 (std::istream& is, const scanf_format_elt& fmt, T* valptr)
01095 {
01096 T& ref = *valptr;
01097
01098 switch (fmt.type)
01099 {
01100 case 'o':
01101 is >> std::oct >> ref >> std::dec;
01102 break;
01103
01104 case 'x':
01105 is >> std::hex >> ref >> std::dec;
01106 break;
01107
01108 case 'i':
01109 {
01110 int c1 = is.get ();
01111
01112 if (! is.eof ())
01113 {
01114 if (c1 == '0')
01115 {
01116 int c2 = is.peek ();
01117
01118 if (c2 == 'x' || c2 == 'X')
01119 {
01120 is.ignore ();
01121 if (std::isxdigit (is.peek ()))
01122 is >> std::hex >> ref >> std::dec;
01123 else
01124 ref = 0;
01125 }
01126 else
01127 {
01128 if (c2 == '0' || c2 == '1' || c2 == '2'
01129 || c2 == '3' || c2 == '4' || c2 == '5'
01130 || c2 == '6' || c2 == '7')
01131 is >> std::oct >> ref >> std::dec;
01132 else
01133 ref = 0;
01134 }
01135 }
01136 else
01137 {
01138 is.putback (c1);
01139
01140 is >> ref;
01141 }
01142 }
01143 }
01144 break;
01145
01146 default:
01147 is >> ref;
01148 break;
01149 }
01150
01151 return is;
01152 }
01153
01154 template <class T>
01155 std::istream&
01156 octave_scan (std::istream& is, const scanf_format_elt& fmt, T* valptr)
01157 {
01158 if (fmt.width)
01159 {
01160
01161
01162
01163 std::string tmp;
01164
01165 is.width (fmt.width);
01166 is >> tmp;
01167
01168 std::istringstream ss (tmp);
01169
01170 octave_scan_1 (ss, fmt, valptr);
01171 }
01172 else
01173 octave_scan_1 (is, fmt, valptr);
01174
01175 return is;
01176 }
01177
01178
01179
01180
01181 template<>
01182 std::istream&
01183 octave_scan<> (std::istream& is, const scanf_format_elt& ,
01184 char* valptr)
01185 {
01186 return is >> valptr;
01187 }
01188
01189 template std::istream&
01190 octave_scan (std::istream&, const scanf_format_elt&, int*);
01191
01192 template std::istream&
01193 octave_scan (std::istream&, const scanf_format_elt&, long int*);
01194
01195 template std::istream&
01196 octave_scan (std::istream&, const scanf_format_elt&, short int*);
01197
01198 template std::istream&
01199 octave_scan (std::istream&, const scanf_format_elt&, unsigned int*);
01200
01201 template std::istream&
01202 octave_scan (std::istream&, const scanf_format_elt&, unsigned long int*);
01203
01204 template std::istream&
01205 octave_scan (std::istream&, const scanf_format_elt&, unsigned short int*);
01206
01207 #if 0
01208 template std::istream&
01209 octave_scan (std::istream&, const scanf_format_elt&, float*);
01210 #endif
01211
01212 template<>
01213 std::istream&
01214 octave_scan<> (std::istream& is, const scanf_format_elt& fmt, double* valptr)
01215 {
01216 double& ref = *valptr;
01217
01218 switch (fmt.type)
01219 {
01220 case 'e':
01221 case 'f':
01222 case 'g':
01223 {
01224 int c1 = EOF;
01225
01226 while (is && (c1 = is.get ()) != EOF && isspace (c1))
01227 ;
01228
01229 if (c1 != EOF)
01230 {
01231 is.putback (c1);
01232
01233 ref = octave_read_value<double> (is);
01234 }
01235 }
01236 break;
01237
01238 default:
01239 panic_impossible ();
01240 break;
01241 }
01242
01243 return is;
01244 }
01245
01246 template <class T>
01247 void
01248 do_scanf_conv (std::istream& is, const scanf_format_elt& fmt,
01249 T valptr, Matrix& mval, double *data, octave_idx_type& idx,
01250 octave_idx_type& conversion_count, octave_idx_type nr, octave_idx_type max_size,
01251 bool discard)
01252 {
01253 OCTAVE_SCAN (is, fmt, valptr);
01254
01255 if (is)
01256 {
01257 if (idx == max_size && ! discard)
01258 {
01259 max_size *= 2;
01260
01261 if (nr > 0)
01262 mval.resize (nr, max_size / nr, 0.0);
01263 else
01264 mval.resize (max_size, 1, 0.0);
01265
01266 data = mval.fortran_vec ();
01267 }
01268
01269 if (! discard)
01270 {
01271 conversion_count++;
01272 data[idx++] = *(valptr);
01273 }
01274 }
01275 }
01276
01277 template void
01278 do_scanf_conv (std::istream&, const scanf_format_elt&, int*,
01279 Matrix&, double*, octave_idx_type&, octave_idx_type&, octave_idx_type, octave_idx_type, bool);
01280
01281 template void
01282 do_scanf_conv (std::istream&, const scanf_format_elt&, long int*,
01283 Matrix&, double*, octave_idx_type&, octave_idx_type&, octave_idx_type, octave_idx_type, bool);
01284
01285 template void
01286 do_scanf_conv (std::istream&, const scanf_format_elt&, short int*,
01287 Matrix&, double*, octave_idx_type&, octave_idx_type&, octave_idx_type, octave_idx_type, bool);
01288
01289 template void
01290 do_scanf_conv (std::istream&, const scanf_format_elt&, unsigned int*,
01291 Matrix&, double*, octave_idx_type&, octave_idx_type&, octave_idx_type, octave_idx_type, bool);
01292
01293 template void
01294 do_scanf_conv (std::istream&, const scanf_format_elt&, unsigned long int*,
01295 Matrix&, double*, octave_idx_type&, octave_idx_type&, octave_idx_type, octave_idx_type, bool);
01296
01297 template void
01298 do_scanf_conv (std::istream&, const scanf_format_elt&, unsigned short int*,
01299 Matrix&, double*, octave_idx_type&, octave_idx_type&, octave_idx_type, octave_idx_type, bool);
01300
01301 #if 0
01302 template void
01303 do_scanf_conv (std::istream&, const scanf_format_elt&, float*,
01304 Matrix&, double*, octave_idx_type&, octave_idx_type&, octave_idx_type, octave_idx_type, bool);
01305 #endif
01306
01307 template void
01308 do_scanf_conv (std::istream&, const scanf_format_elt&, double*,
01309 Matrix&, double*, octave_idx_type&, octave_idx_type&, octave_idx_type, octave_idx_type, bool);
01310
01311 #define DO_WHITESPACE_CONVERSION() \
01312 do \
01313 { \
01314 int c = EOF; \
01315 \
01316 while (is && (c = is.get ()) != EOF && isspace (c)) \
01317 ; \
01318 \
01319 if (c != EOF) \
01320 is.putback (c); \
01321 } \
01322 while (0)
01323
01324 #define DO_LITERAL_CONVERSION() \
01325 do \
01326 { \
01327 int c = EOF; \
01328 \
01329 int n = strlen (fmt); \
01330 int i = 0; \
01331 \
01332 while (i < n && is && (c = is.get ()) != EOF) \
01333 { \
01334 if (c == static_cast<unsigned char> (fmt[i])) \
01335 { \
01336 i++; \
01337 continue; \
01338 } \
01339 else \
01340 { \
01341 is.putback (c); \
01342 break; \
01343 } \
01344 } \
01345 \
01346 if (i != n) \
01347 is.setstate (std::ios::failbit); \
01348 } \
01349 while (0)
01350
01351 #define DO_PCT_CONVERSION() \
01352 do \
01353 { \
01354 int c = is.get (); \
01355 \
01356 if (c != EOF) \
01357 { \
01358 if (c != '%') \
01359 { \
01360 is.putback (c); \
01361 is.setstate (std::ios::failbit); \
01362 } \
01363 } \
01364 else \
01365 is.setstate (std::ios::failbit); \
01366 } \
01367 while (0)
01368
01369 #define BEGIN_C_CONVERSION() \
01370 is.unsetf (std::ios::skipws); \
01371 \
01372 int width = elt->width ? elt->width : 1; \
01373 \
01374 std::string tmp (width, '\0'); \
01375 \
01376 int c = EOF; \
01377 int n = 0; \
01378 \
01379 while (is && n < width && (c = is.get ()) != EOF) \
01380 tmp[n++] = static_cast<char> (c); \
01381 \
01382 if (n > 0 && c == EOF) \
01383 is.clear (); \
01384 \
01385 tmp.resize (n)
01386
01387
01388
01389 #define BEGIN_S_CONVERSION() \
01390 int width = elt->width; \
01391 \
01392 std::string tmp; \
01393 \
01394 do \
01395 { \
01396 if (width) \
01397 { \
01398 tmp = std::string (width, '\0'); \
01399 \
01400 int c = EOF; \
01401 \
01402 int n = 0; \
01403 \
01404 while (is && (c = is.get ()) != EOF) \
01405 { \
01406 if (! isspace (c)) \
01407 { \
01408 tmp[n++] = static_cast<char> (c); \
01409 break; \
01410 } \
01411 } \
01412 \
01413 while (is && n < width && (c = is.get ()) != EOF) \
01414 { \
01415 if (isspace (c)) \
01416 { \
01417 is.putback (c); \
01418 break; \
01419 } \
01420 else \
01421 tmp[n++] = static_cast<char> (c); \
01422 } \
01423 \
01424 if (n > 0 && c == EOF) \
01425 is.clear (); \
01426 \
01427 tmp.resize (n); \
01428 } \
01429 else \
01430 { \
01431 is >> std::ws >> tmp; \
01432 } \
01433 } \
01434 while (0)
01435
01436
01437 #define BEGIN_CHAR_CLASS_CONVERSION() \
01438 int width = elt->width; \
01439 \
01440 std::string tmp; \
01441 \
01442 do \
01443 { \
01444 if (! width) \
01445 width = INT_MAX; \
01446 \
01447 std::ostringstream buf; \
01448 \
01449 std::string char_class = elt->char_class; \
01450 \
01451 int c = EOF; \
01452 \
01453 if (elt->type == '[') \
01454 { \
01455 int chars_read = 0; \
01456 while (is && chars_read++ < width && (c = is.get ()) != EOF \
01457 && char_class.find (c) != std::string::npos) \
01458 buf << static_cast<char> (c); \
01459 } \
01460 else \
01461 { \
01462 int chars_read = 0; \
01463 while (is && chars_read++ < width && (c = is.get ()) != EOF \
01464 && char_class.find (c) == std::string::npos) \
01465 buf << static_cast<char> (c); \
01466 } \
01467 \
01468 if (width == INT_MAX && c != EOF) \
01469 is.putback (c); \
01470 \
01471 tmp = buf.str (); \
01472 \
01473 if (tmp.empty ()) \
01474 is.setstate (std::ios::failbit); \
01475 else if (c == EOF) \
01476 is.clear (); \
01477 \
01478 } \
01479 while (0)
01480
01481 #define FINISH_CHARACTER_CONVERSION() \
01482 do \
01483 { \
01484 width = tmp.length (); \
01485 \
01486 if (is) \
01487 { \
01488 int i = 0; \
01489 \
01490 if (! discard) \
01491 { \
01492 conversion_count++; \
01493 \
01494 while (i < width) \
01495 { \
01496 if (data_index == max_size) \
01497 { \
01498 max_size *= 2; \
01499 \
01500 if (all_char_conv) \
01501 { \
01502 if (one_elt_size_spec) \
01503 mval.resize (1, max_size, 0.0); \
01504 else if (nr > 0) \
01505 mval.resize (nr, max_size / nr, 0.0); \
01506 else \
01507 panic_impossible (); \
01508 } \
01509 else if (nr > 0) \
01510 mval.resize (nr, max_size / nr, 0.0); \
01511 else \
01512 mval.resize (max_size, 1, 0.0); \
01513 \
01514 data = mval.fortran_vec (); \
01515 } \
01516 \
01517 data[data_index++] = tmp[i++]; \
01518 } \
01519 } \
01520 } \
01521 } \
01522 while (0)
01523
01524 octave_value
01525 octave_base_stream::do_scanf (scanf_format_list& fmt_list,
01526 octave_idx_type nr, octave_idx_type nc, bool one_elt_size_spec,
01527 octave_idx_type& conversion_count, const std::string& who)
01528 {
01529 octave_value retval = Matrix ();
01530
01531 if ((interactive || forced_interactive) && file_number () == 0)
01532 {
01533 ::error ("%s: unable to read from stdin while running interactively",
01534 who.c_str ());
01535
01536 return retval;
01537 }
01538
01539 conversion_count = 0;
01540
01541 octave_idx_type nconv = fmt_list.num_conversions ();
01542
01543 octave_idx_type data_index = 0;
01544
01545 if (nr == 0 || nc == 0)
01546 {
01547 if (one_elt_size_spec)
01548 nc = 0;
01549
01550 return Matrix (nr, nc, 0.0);
01551 }
01552
01553 std::istream *isp = input_stream ();
01554
01555 bool all_char_conv = fmt_list.all_character_conversions ();
01556
01557 Matrix mval;
01558 double *data = 0;
01559 octave_idx_type max_size = 0;
01560 octave_idx_type max_conv = 0;
01561
01562 octave_idx_type final_nr = 0;
01563 octave_idx_type final_nc = 0;
01564
01565 if (all_char_conv)
01566 {
01567
01568
01569
01570
01571 if (one_elt_size_spec)
01572 {
01573 max_size = 512;
01574 mval.resize (1, max_size, 0.0);
01575
01576 if (nr > 0)
01577 max_conv = nr;
01578 }
01579 else if (nr > 0)
01580 {
01581 if (nc > 0)
01582 {
01583 mval.resize (nr, nc, 0.0);
01584 max_size = max_conv = nr * nc;
01585 }
01586 else
01587 {
01588 mval.resize (nr, 32, 0.0);
01589 max_size = nr * 32;
01590 }
01591 }
01592 else
01593 panic_impossible ();
01594 }
01595 else if (nr > 0)
01596 {
01597 if (nc > 0)
01598 {
01599
01600 mval.resize (nr, nc, 0.0);
01601 max_size = nr * nc;
01602 max_conv = max_size;
01603 }
01604 else
01605 {
01606
01607 mval.resize (nr, 32, 0.0);
01608 max_size = nr * 32;
01609 }
01610 }
01611 else
01612 {
01613
01614 mval.resize (32, 1, 0.0);
01615 max_size = 32;
01616 }
01617
01618 data = mval.fortran_vec ();
01619
01620 if (isp)
01621 {
01622 std::istream& is = *isp;
01623
01624 const scanf_format_elt *elt = fmt_list.first ();
01625
01626 std::ios::fmtflags flags = is.flags ();
01627
01628 octave_idx_type trips = 0;
01629
01630 octave_idx_type num_fmt_elts = fmt_list.length ();
01631
01632 for (;;)
01633 {
01634 octave_quit ();
01635
01636 if (elt)
01637 {
01638 if (! (elt->type == scanf_format_elt::whitespace_conversion
01639 || elt->type == scanf_format_elt::literal_conversion
01640 || elt->type == '%')
01641 && max_conv > 0 && conversion_count == max_conv)
01642 {
01643 if (all_char_conv && one_elt_size_spec)
01644 {
01645 final_nr = 1;
01646 final_nc = data_index;
01647 }
01648 else
01649 {
01650 final_nr = nr;
01651 final_nc = (data_index - 1) / nr + 1;
01652 }
01653
01654 break;
01655 }
01656 else if (data_index == max_size)
01657 {
01658 max_size *= 2;
01659
01660 if (all_char_conv)
01661 {
01662 if (one_elt_size_spec)
01663 mval.resize (1, max_size, 0.0);
01664 else if (nr > 0)
01665 mval.resize (nr, max_size / nr, 0.0);
01666 else
01667 panic_impossible ();
01668 }
01669 else if (nr > 0)
01670 mval.resize (nr, max_size / nr, 0.0);
01671 else
01672 mval.resize (max_size, 1, 0.0);
01673
01674 data = mval.fortran_vec ();
01675 }
01676
01677 const char *fmt = elt->text;
01678
01679 bool discard = elt->discard;
01680
01681 switch (elt->type)
01682 {
01683 case scanf_format_elt::whitespace_conversion:
01684 DO_WHITESPACE_CONVERSION ();
01685 break;
01686
01687 case scanf_format_elt::literal_conversion:
01688 DO_LITERAL_CONVERSION ();
01689 break;
01690
01691 case '%':
01692 DO_PCT_CONVERSION ();
01693 break;
01694
01695 case 'd': case 'i':
01696 {
01697 switch (elt->modifier)
01698 {
01699 case 'h':
01700 {
01701 short int tmp;
01702 do_scanf_conv (is, *elt, &tmp, mval, data,
01703 data_index, conversion_count,
01704 nr, max_size, discard);
01705 }
01706 break;
01707
01708 case 'l':
01709 {
01710 long int tmp;
01711 do_scanf_conv (is, *elt, &tmp, mval, data,
01712 data_index, conversion_count,
01713 nr, max_size, discard);
01714 }
01715 break;
01716
01717 default:
01718 {
01719 int tmp;
01720 do_scanf_conv (is, *elt, &tmp, mval, data,
01721 data_index, conversion_count,
01722 nr, max_size, discard);
01723 }
01724 break;
01725 }
01726 }
01727 break;
01728
01729 case 'o': case 'u': case 'x':
01730 {
01731 switch (elt->modifier)
01732 {
01733 case 'h':
01734 {
01735 unsigned short int tmp;
01736 do_scanf_conv (is, *elt, &tmp, mval, data,
01737 data_index, conversion_count,
01738 nr, max_size, discard);
01739 }
01740 break;
01741
01742 case 'l':
01743 {
01744 unsigned long int tmp;
01745 do_scanf_conv (is, *elt, &tmp, mval, data,
01746 data_index, conversion_count,
01747 nr, max_size, discard);
01748 }
01749 break;
01750
01751 default:
01752 {
01753 unsigned int tmp;
01754 do_scanf_conv (is, *elt, &tmp, mval, data,
01755 data_index, conversion_count,
01756 nr, max_size, discard);
01757 }
01758 break;
01759 }
01760 }
01761 break;
01762
01763 case 'e': case 'f': case 'g':
01764 {
01765 double tmp;
01766
01767 do_scanf_conv (is, *elt, &tmp, mval, data,
01768 data_index, conversion_count,
01769 nr, max_size, discard);
01770 }
01771 break;
01772
01773 case 'c':
01774 {
01775 BEGIN_C_CONVERSION ();
01776
01777 FINISH_CHARACTER_CONVERSION ();
01778
01779 is.setf (flags);
01780 }
01781 break;
01782
01783 case 's':
01784 {
01785 BEGIN_S_CONVERSION ();
01786
01787 FINISH_CHARACTER_CONVERSION ();
01788 }
01789 break;
01790
01791 case '[': case '^':
01792 {
01793 BEGIN_CHAR_CLASS_CONVERSION ();
01794
01795 FINISH_CHARACTER_CONVERSION ();
01796 }
01797 break;
01798
01799 case 'p':
01800 error ("%s: unsupported format specifier", who.c_str ());
01801 break;
01802
01803 default:
01804 error ("%s: internal format error", who.c_str ());
01805 break;
01806 }
01807
01808 if (! ok ())
01809 {
01810 break;
01811 }
01812 else if (! is)
01813 {
01814 if (all_char_conv)
01815 {
01816 if (one_elt_size_spec)
01817 {
01818 final_nr = 1;
01819 final_nc = data_index;
01820 }
01821 else if (data_index > nr)
01822 {
01823 final_nr = nr;
01824 final_nc = (data_index - 1) / nr + 1;
01825 }
01826 else
01827 {
01828 final_nr = data_index;
01829 final_nc = 1;
01830 }
01831 }
01832 else if (nr > 0)
01833 {
01834 if (data_index > nr)
01835 {
01836 final_nr = nr;
01837 final_nc = (data_index - 1) / nr + 1;
01838 }
01839 else
01840 {
01841 final_nr = data_index;
01842 final_nc = 1;
01843 }
01844 }
01845 else
01846 {
01847 final_nr = data_index;
01848 final_nc = 1;
01849 }
01850
01851
01852
01853
01854 if (is.rdstate () & std::ios::failbit)
01855 is.clear (is.rdstate () & (~std::ios::failbit));
01856
01857
01858
01859 if (interactive && name () == "stdin")
01860 {
01861 is.clear ();
01862
01863
01864
01865 bool err;
01866 do_gets (-1, err, false, who);
01867 }
01868
01869 break;
01870 }
01871 }
01872 else
01873 {
01874 error ("%s: internal format error", who.c_str ());
01875 break;
01876 }
01877
01878 if (nconv == 0 && ++trips == num_fmt_elts)
01879 {
01880 if (all_char_conv && one_elt_size_spec)
01881 {
01882 final_nr = 1;
01883 final_nc = data_index;
01884 }
01885 else
01886 {
01887 final_nr = nr;
01888 final_nc = (data_index - 1) / nr + 1;
01889 }
01890
01891 break;
01892 }
01893 else
01894 elt = fmt_list.next (nconv > 0);
01895 }
01896 }
01897
01898 if (ok ())
01899 {
01900 mval.resize (final_nr, final_nc, 0.0);
01901
01902 retval = mval;
01903
01904 if (all_char_conv)
01905 retval = retval.convert_to_str (false, true);
01906 }
01907
01908 return retval;
01909 }
01910
01911 octave_value
01912 octave_base_stream::scanf (const std::string& fmt, const Array<double>& size,
01913 octave_idx_type& conversion_count, const std::string& who)
01914 {
01915 octave_value retval = Matrix ();
01916
01917 conversion_count = 0;
01918
01919 std::istream *isp = input_stream ();
01920
01921 if (isp)
01922 {
01923 scanf_format_list fmt_list (fmt);
01924
01925 if (fmt_list.num_conversions () == -1)
01926 ::error ("%s: invalid format specified", who.c_str ());
01927 else
01928 {
01929 octave_idx_type nr = -1;
01930 octave_idx_type nc = -1;
01931
01932 bool one_elt_size_spec;
01933
01934 get_size (size, nr, nc, one_elt_size_spec, who);
01935
01936 if (! error_state)
01937 retval = do_scanf (fmt_list, nr, nc, one_elt_size_spec,
01938 conversion_count, who);
01939 }
01940 }
01941 else
01942 invalid_operation (who, "reading");
01943
01944 return retval;
01945 }
01946
01947 bool
01948 octave_base_stream::do_oscanf (const scanf_format_elt *elt,
01949 octave_value& retval, const std::string& who)
01950 {
01951 bool quit = false;
01952
01953 std::istream *isp = input_stream ();
01954
01955 if (isp)
01956 {
01957 std::istream& is = *isp;
01958
01959 std::ios::fmtflags flags = is.flags ();
01960
01961 if (elt)
01962 {
01963 const char *fmt = elt->text;
01964
01965 bool discard = elt->discard;
01966
01967 switch (elt->type)
01968 {
01969 case scanf_format_elt::whitespace_conversion:
01970 DO_WHITESPACE_CONVERSION ();
01971 break;
01972
01973 case scanf_format_elt::literal_conversion:
01974 DO_LITERAL_CONVERSION ();
01975 break;
01976
01977 case '%':
01978 {
01979 DO_PCT_CONVERSION ();
01980
01981 if (! is)
01982 quit = true;
01983
01984 }
01985 break;
01986
01987 case 'd': case 'i':
01988 {
01989 int tmp;
01990
01991 if (OCTAVE_SCAN (is, *elt, &tmp))
01992 {
01993 if (! discard)
01994 retval = tmp;
01995 }
01996 else
01997 quit = true;
01998 }
01999 break;
02000
02001 case 'o': case 'u': case 'x':
02002 {
02003 long int tmp;
02004
02005 if (OCTAVE_SCAN (is, *elt, &tmp))
02006 {
02007 if (! discard)
02008 retval = tmp;
02009 }
02010 else
02011 quit = true;
02012 }
02013 break;
02014
02015 case 'e': case 'f': case 'g':
02016 {
02017 double tmp;
02018
02019 if (OCTAVE_SCAN (is, *elt, &tmp))
02020 {
02021 if (! discard)
02022 retval = tmp;
02023 }
02024 else
02025 quit = true;
02026 }
02027 break;
02028
02029 case 'c':
02030 {
02031 BEGIN_C_CONVERSION ();
02032
02033 if (! discard)
02034 retval = tmp;
02035
02036 if (! is)
02037 quit = true;
02038
02039 is.setf (flags);
02040 }
02041 break;
02042
02043 case 's':
02044 {
02045 BEGIN_S_CONVERSION ();
02046
02047 if (! discard)
02048 retval = tmp;
02049
02050 if (! is)
02051 quit = true;
02052 }
02053 break;
02054
02055 case '[': case '^':
02056 {
02057 BEGIN_CHAR_CLASS_CONVERSION ();
02058
02059 if (! discard)
02060 retval = tmp;
02061
02062 if (! is)
02063 quit = true;
02064 }
02065 break;
02066
02067 case 'p':
02068 error ("%s: unsupported format specifier", who.c_str ());
02069 break;
02070
02071 default:
02072 error ("%s: internal format error", who.c_str ());
02073 break;
02074 }
02075 }
02076
02077 if (ok () && is.fail ())
02078 {
02079 error ("%s: read error", who.c_str ());
02080
02081
02082
02083 if (interactive && name () == "stdin")
02084 {
02085
02086
02087 bool err;
02088 do_gets (-1, err, false, who);
02089 }
02090 }
02091 }
02092
02093 return quit;
02094 }
02095
02096 octave_value_list
02097 octave_base_stream::oscanf (const std::string& fmt, const std::string& who)
02098 {
02099 octave_value_list retval;
02100
02101 std::istream *isp = input_stream ();
02102
02103 if (isp)
02104 {
02105 std::istream& is = *isp;
02106
02107 scanf_format_list fmt_list (fmt);
02108
02109 octave_idx_type nconv = fmt_list.num_conversions ();
02110
02111 if (nconv == -1)
02112 ::error ("%s: invalid format specified", who.c_str ());
02113 else
02114 {
02115 is.clear ();
02116
02117 octave_idx_type len = fmt_list.length ();
02118
02119 retval.resize (nconv+2, Matrix ());
02120
02121 const scanf_format_elt *elt = fmt_list.first ();
02122
02123 int num_values = 0;
02124
02125 bool quit = false;
02126
02127 for (octave_idx_type i = 0; i < len; i++)
02128 {
02129 octave_value tmp;
02130
02131 quit = do_oscanf (elt, tmp, who);
02132
02133 if (quit)
02134 break;
02135 else
02136 {
02137 if (tmp.is_defined ())
02138 retval (num_values++) = tmp;
02139
02140 if (! ok ())
02141 break;
02142
02143 elt = fmt_list.next (nconv > 0);
02144 }
02145 }
02146
02147 retval(nconv) = num_values;
02148
02149 int err_num;
02150 retval(nconv+1) = error (false, err_num);
02151
02152 if (! quit)
02153 {
02154
02155 if (ok () && len > nconv)
02156 {
02157 octave_value tmp;
02158
02159 elt = fmt_list.next ();
02160
02161 do_oscanf (elt, tmp, who);
02162 }
02163 }
02164 }
02165 }
02166 else
02167 invalid_operation (who, "reading");
02168
02169 return retval;
02170 }
02171
02172
02173
02174
02175 int
02176 octave_base_stream::flush (void)
02177 {
02178 int retval = -1;
02179
02180 std::ostream *os = output_stream ();
02181
02182 if (os)
02183 {
02184 os->flush ();
02185
02186 if (os->good ())
02187 retval = 0;
02188 }
02189 else
02190 invalid_operation ("fflush", "writing");
02191
02192 return retval;
02193 }
02194
02195 class
02196 printf_value_cache
02197 {
02198 public:
02199
02200 enum state { ok, conversion_error };
02201
02202 printf_value_cache (const octave_value_list& args, const std::string& who)
02203 : values (args), val_idx (0), elt_idx (0),
02204 n_vals (values.length ()), n_elts (0), data (0),
02205 curr_state (ok)
02206 {
02207 for (octave_idx_type i = 0; i < values.length (); i++)
02208 {
02209 octave_value val = values(i);
02210
02211 if (val.is_map () || val.is_cell () || val.is_object ())
02212 {
02213 gripe_wrong_type_arg (who, val);
02214 break;
02215 }
02216 }
02217 }
02218
02219 ~printf_value_cache (void) { }
02220
02221
02222 double double_value (void);
02223
02224
02225 int int_value (void);
02226
02227
02228 std::string string_value (void);
02229
02230 operator bool () const { return (curr_state == ok); }
02231
02232 bool exhausted (void) { return (val_idx >= n_vals); }
02233
02234 private:
02235
02236 const octave_value_list values;
02237 int val_idx;
02238 int elt_idx;
02239 int n_vals;
02240 int n_elts;
02241 const double *data;
02242 NDArray curr_val;
02243 state curr_state;
02244
02245
02246
02247 printf_value_cache (void);
02248
02249
02250
02251 printf_value_cache (const printf_value_cache&);
02252
02253 printf_value_cache& operator = (const printf_value_cache&);
02254 };
02255
02256 double
02257 printf_value_cache::double_value (void)
02258 {
02259 double retval = 0.0;
02260
02261 if (exhausted ())
02262 curr_state = conversion_error;
02263
02264 while (! exhausted ())
02265 {
02266 if (! data)
02267 {
02268 octave_value tmp_val = values (val_idx);
02269
02270
02271
02272 curr_val = tmp_val.array_value (true);
02273
02274 if (! error_state)
02275 {
02276 elt_idx = 0;
02277 n_elts = curr_val.length ();
02278 data = curr_val.data ();
02279 }
02280 else
02281 {
02282 curr_state = conversion_error;
02283 break;
02284 }
02285 }
02286
02287 if (elt_idx < n_elts)
02288 {
02289 retval = data[elt_idx++];
02290
02291 if (elt_idx >= n_elts)
02292 {
02293 elt_idx = 0;
02294 val_idx++;
02295 data = 0;
02296 }
02297
02298 break;
02299 }
02300 else
02301 {
02302 val_idx++;
02303 data = 0;
02304
02305 if (n_elts == 0 && exhausted ())
02306 curr_state = conversion_error;
02307
02308 continue;
02309 }
02310 }
02311
02312 return retval;
02313 }
02314
02315 int
02316 printf_value_cache::int_value (void)
02317 {
02318 int retval = 0;
02319
02320 double dval = double_value ();
02321
02322 if (! error_state)
02323 {
02324 if (D_NINT (dval) == dval)
02325 retval = NINT (dval);
02326 else
02327 curr_state = conversion_error;
02328 }
02329
02330 return retval;
02331 }
02332
02333 std::string
02334 printf_value_cache::string_value (void)
02335 {
02336 std::string retval;
02337
02338 if (exhausted ())
02339 curr_state = conversion_error;
02340 else
02341 {
02342 octave_value tval = values (val_idx++);
02343
02344 if (tval.rows () == 1)
02345 retval = tval.string_value ();
02346 else
02347 {
02348
02349
02350 charMatrix chm = tval.char_matrix_value ();
02351
02352 octave_idx_type nr = chm.rows ();
02353 octave_idx_type nc = chm.columns ();
02354
02355 int k = 0;
02356
02357 retval.resize (nr * nc, '\0');
02358
02359 for (octave_idx_type j = 0; j < nc; j++)
02360 for (octave_idx_type i = 0; i < nr; i++)
02361 retval[k++] = chm(i,j);
02362 }
02363
02364 if (error_state)
02365 curr_state = conversion_error;
02366 }
02367
02368 return retval;
02369 }
02370
02371
02372
02373 template <class T>
02374 int
02375 do_printf_conv (std::ostream& os, const char *fmt, int nsa, int sa_1,
02376 int sa_2, T arg, const std::string& who)
02377 {
02378 int retval = 0;
02379
02380 switch (nsa)
02381 {
02382 case 2:
02383 retval = octave_format (os, fmt, sa_1, sa_2, arg);
02384 break;
02385
02386 case 1:
02387 retval = octave_format (os, fmt, sa_1, arg);
02388 break;
02389
02390 case 0:
02391 retval = octave_format (os, fmt, arg);
02392 break;
02393
02394 default:
02395 ::error ("%s: internal error handling format", who.c_str ());
02396 break;
02397 }
02398
02399 return retval;
02400 }
02401
02402 template int
02403 do_printf_conv (std::ostream&, const char*, int, int, int, int,
02404 const std::string&);
02405
02406 template int
02407 do_printf_conv (std::ostream&, const char*, int, int, int, long,
02408 const std::string&);
02409
02410 template int
02411 do_printf_conv (std::ostream&, const char*, int, int, int, unsigned int,
02412 const std::string&);
02413
02414 template int
02415 do_printf_conv (std::ostream&, const char*, int, int, int, unsigned long,
02416 const std::string&);
02417
02418 template int
02419 do_printf_conv (std::ostream&, const char*, int, int, int, double,
02420 const std::string&);
02421
02422 template int
02423 do_printf_conv (std::ostream&, const char*, int, int, int, const char*,
02424 const std::string&);
02425
02426 #define DO_DOUBLE_CONV(TQUAL) \
02427 do \
02428 { \
02429 if (val > std::numeric_limits<TQUAL long>::max () \
02430 || val < std::numeric_limits<TQUAL long>::min ()) \
02431 { \
02432 std::string tfmt = fmt; \
02433 \
02434 tfmt.replace (tfmt.rfind (elt->type), 1, ".f"); \
02435 \
02436 if (elt->modifier == 'l') \
02437 tfmt.replace (tfmt.rfind (elt->modifier), 1, ""); \
02438 \
02439 retval += do_printf_conv (os, tfmt.c_str (), nsa, sa_1, sa_2, \
02440 val, who); \
02441 } \
02442 else \
02443 retval += do_printf_conv (os, fmt, nsa, sa_1, sa_2, \
02444 static_cast<TQUAL long> (val), who); \
02445 } \
02446 while (0)
02447
02448 int
02449 octave_base_stream::do_printf (printf_format_list& fmt_list,
02450 const octave_value_list& args,
02451 const std::string& who)
02452 {
02453 int retval = 0;
02454
02455 octave_idx_type nconv = fmt_list.num_conversions ();
02456
02457 std::ostream *osp = output_stream ();
02458
02459 if (osp)
02460 {
02461 std::ostream& os = *osp;
02462
02463 const printf_format_elt *elt = fmt_list.first ();
02464
02465 printf_value_cache val_cache (args, who);
02466
02467 if (error_state)
02468 return retval;
02469
02470 for (;;)
02471 {
02472 octave_quit ();
02473
02474 if (elt)
02475 {
02476
02477
02478 int nsa = (elt->fw < 0) + (elt->prec < 0);
02479
02480 int sa_1 = 0;
02481 int sa_2 = 0;
02482
02483 if (nsa > 0)
02484 {
02485 sa_1 = val_cache.int_value ();
02486
02487 if (! val_cache)
02488 break;
02489 else
02490 {
02491 if (nsa > 1)
02492 {
02493 sa_2 = val_cache.int_value ();
02494
02495 if (! val_cache)
02496 break;
02497 }
02498 }
02499 }
02500
02501 const char *fmt = elt->text;
02502
02503 if (elt->type == '%')
02504 {
02505 os << "%";
02506 retval++;
02507 }
02508 else if (elt->args == 0 && elt->text)
02509 {
02510 os << elt->text;
02511 retval += strlen (elt->text);
02512 }
02513 else if (elt->type == 's')
02514 {
02515 std::string val = val_cache.string_value ();
02516
02517 if (val_cache)
02518 retval += do_printf_conv (os, fmt, nsa, sa_1,
02519 sa_2, val.c_str (), who);
02520 else
02521 break;
02522 }
02523 else
02524 {
02525 double val = val_cache.double_value ();
02526
02527 if (val_cache)
02528 {
02529 if (lo_ieee_isnan (val) || xisinf (val))
02530 {
02531 std::string tfmt = fmt;
02532 std::string::size_type i1, i2;
02533
02534 tfmt.replace ((i1 = tfmt.rfind (elt->type)),
02535 1, 1, 's');
02536
02537 if ((i2 = tfmt.rfind ('.')) != std::string::npos && i2 < i1)
02538 {
02539 tfmt.erase (i2, i1-i2);
02540 if (elt->prec < 0)
02541 nsa--;
02542 }
02543
02544 const char *tval = xisinf (val)
02545 ? (val < 0 ? "-Inf" : "Inf")
02546 : (lo_ieee_is_NA (val) ? "NA" : "NaN");
02547
02548 retval += do_printf_conv (os, tfmt.c_str (),
02549 nsa, sa_1, sa_2,
02550 tval, who);
02551 }
02552 else
02553 {
02554 char type = elt->type;
02555
02556 switch (type)
02557 {
02558 case 'd': case 'i': case 'c':
02559 DO_DOUBLE_CONV (OCTAVE_EMPTY_CPP_ARG);
02560 break;
02561
02562 case 'o': case 'x': case 'X': case 'u':
02563 DO_DOUBLE_CONV (unsigned);
02564 break;
02565
02566 case 'f': case 'e': case 'E':
02567 case 'g': case 'G':
02568 retval
02569 += do_printf_conv (os, fmt, nsa, sa_1, sa_2,
02570 val, who);
02571 break;
02572
02573 default:
02574 error ("%s: invalid format specifier",
02575 who.c_str ());
02576 return -1;
02577 break;
02578 }
02579 }
02580 }
02581 else
02582 break;
02583 }
02584
02585 if (! os)
02586 {
02587 error ("%s: write error", who.c_str ());
02588 break;
02589 }
02590 }
02591 else
02592 {
02593 ::error ("%s: internal error handling format", who.c_str ());
02594 retval = -1;
02595 break;
02596 }
02597
02598 elt = fmt_list.next (nconv > 0 && ! val_cache.exhausted ());
02599
02600 if (! elt || (val_cache.exhausted () && elt->args > 0))
02601 break;
02602 }
02603 }
02604 else
02605 invalid_operation (who, "writing");
02606
02607 return retval;
02608 }
02609
02610 int
02611 octave_base_stream::printf (const std::string& fmt,
02612 const octave_value_list& args,
02613 const std::string& who)
02614 {
02615 int retval = 0;
02616
02617 printf_format_list fmt_list (fmt);
02618
02619 if (fmt_list.num_conversions () == -1)
02620 ::error ("%s: invalid format specified", who.c_str ());
02621 else
02622 retval = do_printf (fmt_list, args, who);
02623
02624 return retval;
02625 }
02626
02627 int
02628 octave_base_stream::puts (const std::string& s, const std::string& who)
02629 {
02630 int retval = -1;
02631
02632 std::ostream *osp = output_stream ();
02633
02634 if (osp)
02635 {
02636 std::ostream& os = *osp;
02637
02638 os << s;
02639
02640 if (os)
02641 {
02642
02643
02644
02645
02646
02647
02648
02649 os.flush ();
02650
02651 if (os)
02652 retval = 0;
02653 else
02654 error ("%s: write error", who.c_str ());
02655 }
02656 else
02657 error ("%s: write error", who.c_str ());
02658 }
02659 else
02660 invalid_operation (who, "writing");
02661
02662 return retval;
02663 }
02664
02665
02666
02667 std::string
02668 octave_base_stream::error (bool clear_err, int& err_num)
02669 {
02670 err_num = fail ? -1 : 0;
02671
02672 std::string tmp = errmsg;
02673
02674 if (clear_err)
02675 clear ();
02676
02677 return tmp;
02678 }
02679
02680 void
02681 octave_base_stream::invalid_operation (const std::string& who, const char *rw)
02682 {
02683
02684
02685 error (who, std::string ("stream not open for ") + rw);
02686 }
02687
02688 octave_stream::octave_stream (octave_base_stream *bs)
02689 : rep (bs)
02690 {
02691 if (rep)
02692 rep->count = 1;
02693 }
02694
02695 octave_stream::~octave_stream (void)
02696 {
02697 if (rep && --rep->count == 0)
02698 delete rep;
02699 }
02700
02701 octave_stream::octave_stream (const octave_stream& s)
02702 : rep (s.rep)
02703 {
02704 if (rep)
02705 rep->count++;
02706 }
02707
02708 octave_stream&
02709 octave_stream::operator = (const octave_stream& s)
02710 {
02711 if (rep != s.rep)
02712 {
02713 if (rep && --rep->count == 0)
02714 delete rep;
02715
02716 rep = s.rep;
02717
02718 if (rep)
02719 rep->count++;
02720 }
02721
02722 return *this;
02723 }
02724
02725 int
02726 octave_stream::flush (void)
02727 {
02728 int retval = -1;
02729
02730 if (stream_ok ())
02731 retval = rep->flush ();
02732
02733 return retval;
02734 }
02735
02736 std::string
02737 octave_stream::getl (octave_idx_type max_len, bool& err, const std::string& who)
02738 {
02739 std::string retval;
02740
02741 if (stream_ok ())
02742 retval = rep->getl (max_len, err, who);
02743
02744 return retval;
02745 }
02746
02747 std::string
02748 octave_stream::getl (const octave_value& tc_max_len, bool& err,
02749 const std::string& who)
02750 {
02751 std::string retval;
02752
02753 err = false;
02754
02755 int conv_err = 0;
02756
02757 int max_len = -1;
02758
02759 if (tc_max_len.is_defined ())
02760 {
02761 max_len = convert_to_valid_int (tc_max_len, conv_err);
02762
02763 if (conv_err || max_len < 0)
02764 {
02765 err = true;
02766 ::error ("%s: invalid maximum length specified", who.c_str ());
02767 }
02768 }
02769
02770 if (! error_state)
02771 retval = getl (max_len, err, who);
02772
02773 return retval;
02774 }
02775
02776 std::string
02777 octave_stream::gets (octave_idx_type max_len, bool& err, const std::string& who)
02778 {
02779 std::string retval;
02780
02781 if (stream_ok ())
02782 retval = rep->gets (max_len, err, who);
02783
02784 return retval;
02785 }
02786
02787 std::string
02788 octave_stream::gets (const octave_value& tc_max_len, bool& err,
02789 const std::string& who)
02790 {
02791 std::string retval;
02792
02793 err = false;
02794
02795 int conv_err = 0;
02796
02797 int max_len = -1;
02798
02799 if (tc_max_len.is_defined ())
02800 {
02801 max_len = convert_to_valid_int (tc_max_len, conv_err);
02802
02803 if (conv_err || max_len < 0)
02804 {
02805 err = true;
02806 ::error ("%s: invalid maximum length specified", who.c_str ());
02807 }
02808 }
02809
02810 if (! error_state)
02811 retval = gets (max_len, err, who);
02812
02813 return retval;
02814 }
02815
02816 long
02817 octave_stream::skipl (long count, bool& err, const std::string& who)
02818 {
02819 long retval = -1;
02820
02821 if (stream_ok ())
02822 retval = rep->skipl (count, err, who);
02823
02824 return retval;
02825 }
02826
02827 long
02828 octave_stream::skipl (const octave_value& tc_count, bool& err, const std::string& who)
02829 {
02830 long retval = -1;
02831
02832 err = false;
02833
02834 int conv_err = 0;
02835
02836 int count = 1;
02837
02838 if (tc_count.is_defined ())
02839 {
02840 if (tc_count.is_scalar_type () && xisinf (tc_count.scalar_value ()))
02841 count = -1;
02842 else
02843 {
02844 count = convert_to_valid_int (tc_count, conv_err);
02845
02846 if (conv_err || count < 0)
02847 {
02848 err = true;
02849 ::error ("%s: invalid number of lines specified", who.c_str ());
02850 }
02851 }
02852 }
02853
02854 if (! error_state)
02855 retval = skipl (count, err, who);
02856
02857 return retval;
02858 }
02859
02860 int
02861 octave_stream::seek (long offset, int origin)
02862 {
02863 int status = -1;
02864
02865 if (stream_ok ())
02866 {
02867 clearerr ();
02868
02869
02870
02871 long orig_pos = rep->tell ();
02872
02873
02874
02875 status = rep->seek (0, SEEK_END);
02876
02877 if (status == 0)
02878 {
02879 long eof_pos = rep->tell ();
02880
02881 if (origin == SEEK_CUR)
02882 {
02883
02884
02885
02886
02887 rep->seek (orig_pos, SEEK_SET);
02888 }
02889
02890
02891
02892
02893 status = rep->seek (offset, origin);
02894
02895 if (status == 0)
02896 {
02897
02898
02899 long desired_pos = rep->tell ();
02900
02901
02902
02903
02904 if (desired_pos > eof_pos || desired_pos < 0)
02905 {
02906
02907
02908
02909 rep->seek (orig_pos, SEEK_SET);
02910
02911 status = -1;
02912 }
02913 }
02914 else
02915 {
02916
02917
02918
02919 rep->seek (orig_pos, SEEK_SET);
02920
02921 status = -1;
02922 }
02923 }
02924 }
02925
02926 return status;
02927 }
02928
02929 int
02930 octave_stream::seek (const octave_value& tc_offset,
02931 const octave_value& tc_origin)
02932 {
02933 int retval = -1;
02934
02935 long xoffset = tc_offset.long_value (true);
02936
02937 if (! error_state)
02938 {
02939 int conv_err = 0;
02940
02941 int origin = SEEK_SET;
02942
02943 if (tc_origin.is_string ())
02944 {
02945 std::string xorigin = tc_origin.string_value ();
02946
02947 if (xorigin == "bof")
02948 origin = SEEK_SET;
02949 else if (xorigin == "cof")
02950 origin = SEEK_CUR;
02951 else if (xorigin == "eof")
02952 origin = SEEK_END;
02953 else
02954 conv_err = -1;
02955 }
02956 else
02957 {
02958 int xorigin = convert_to_valid_int (tc_origin, conv_err);
02959
02960 if (! conv_err)
02961 {
02962 if (xorigin == -1)
02963 origin = SEEK_SET;
02964 else if (xorigin == 0)
02965 origin = SEEK_CUR;
02966 else if (xorigin == 1)
02967 origin = SEEK_END;
02968 else
02969 conv_err = -1;
02970 }
02971 }
02972
02973 if (! conv_err)
02974 {
02975 retval = seek (xoffset, origin);
02976
02977 if (retval != 0)
02978 error ("fseek: failed to seek to requested position");
02979 }
02980 else
02981 error ("fseek: invalid value for origin");
02982 }
02983 else
02984 error ("fseek: invalid value for offset");
02985
02986 return retval;
02987 }
02988
02989 long
02990 octave_stream::tell (void)
02991 {
02992 long retval = -1;
02993
02994 if (stream_ok ())
02995 retval = rep->tell ();
02996
02997 return retval;
02998 }
02999
03000 int
03001 octave_stream::rewind (void)
03002 {
03003 return seek (0, SEEK_SET);
03004 }
03005
03006 bool
03007 octave_stream::is_open (void) const
03008 {
03009 bool retval = false;
03010
03011 if (stream_ok ())
03012 retval = rep->is_open ();
03013
03014 return retval;
03015 }
03016
03017 void
03018 octave_stream::close (void)
03019 {
03020 if (stream_ok ())
03021 rep->close ();
03022 }
03023
03024 template <class RET_T, class READ_T>
03025 octave_value
03026 do_read (octave_stream& strm, octave_idx_type nr, octave_idx_type nc, octave_idx_type block_size,
03027 octave_idx_type skip, bool do_float_fmt_conv, bool do_NA_conv,
03028 oct_mach_info::float_format from_flt_fmt, octave_idx_type& count)
03029 {
03030 octave_value retval;
03031
03032 RET_T nda;
03033
03034 count = 0;
03035
03036 typedef typename RET_T::element_type ELMT;
03037 ELMT elt_zero = ELMT ();
03038
03039 ELMT *dat = 0;
03040
03041 octave_idx_type max_size = 0;
03042
03043 octave_idx_type final_nr = 0;
03044 octave_idx_type final_nc = 1;
03045
03046 if (nr > 0)
03047 {
03048 if (nc > 0)
03049 {
03050 nda.resize (dim_vector (nr, nc), elt_zero);
03051 dat = nda.fortran_vec ();
03052 max_size = nr * nc;
03053 }
03054 else
03055 {
03056 nda.resize (dim_vector (nr, 32), elt_zero);
03057 dat = nda.fortran_vec ();
03058 max_size = nr * 32;
03059 }
03060 }
03061 else
03062 {
03063 nda.resize (dim_vector (32, 1), elt_zero);
03064 dat = nda.fortran_vec ();
03065 max_size = 32;
03066 }
03067
03068
03069
03070 bool swap = false;
03071
03072 if (oct_mach_info::words_big_endian ())
03073 swap = (from_flt_fmt == oct_mach_info::flt_fmt_ieee_little_endian
03074 || from_flt_fmt == oct_mach_info::flt_fmt_vax_g
03075 || from_flt_fmt == oct_mach_info::flt_fmt_vax_g);
03076 else
03077 swap = (from_flt_fmt == oct_mach_info::flt_fmt_ieee_big_endian);
03078
03079 union
03080 {
03081 char buf[sizeof (typename strip_template_param<octave_int, READ_T>::type)];
03082 typename strip_template_param<octave_int, READ_T>::type val;
03083 } u;
03084
03085 std::istream *isp = strm.input_stream ();
03086
03087 if (isp)
03088 {
03089 std::istream& is = *isp;
03090
03091 octave_idx_type elts_read = 0;
03092
03093 for (;;)
03094 {
03095
03096
03097
03098 if (is)
03099 {
03100 if (nr > 0 && nc > 0 && count == max_size)
03101 {
03102 final_nr = nr;
03103 final_nc = nc;
03104
03105 break;
03106 }
03107
03108 is.read (u.buf, sizeof (typename strip_template_param<octave_int, READ_T>::type));
03109
03110
03111
03112
03113
03114 if (swap)
03115 swap_bytes<sizeof (typename strip_template_param<octave_int, READ_T>::type)> (u.buf);
03116 else if (do_float_fmt_conv)
03117 do_float_format_conversion
03118 (u.buf,
03119 sizeof (typename strip_template_param<octave_int, READ_T>::type),
03120 1, from_flt_fmt, oct_mach_info::float_format ());
03121
03122 typename RET_T::element_type tmp
03123 = static_cast <typename RET_T::element_type> (u.val);
03124
03125 if (is)
03126 {
03127 if (count == max_size)
03128 {
03129 max_size *= 2;
03130
03131 if (nr > 0)
03132 nda.resize (dim_vector (nr, max_size / nr),
03133 elt_zero);
03134 else
03135 nda.resize (dim_vector (max_size, 1), elt_zero);
03136
03137 dat = nda.fortran_vec ();
03138 }
03139
03140 if (do_NA_conv && __lo_ieee_is_old_NA (tmp))
03141 tmp = __lo_ieee_replace_old_NA (tmp);
03142
03143 dat[count++] = tmp;
03144
03145 elts_read++;
03146 }
03147
03148 int seek_status = 0;
03149
03150 if (skip != 0 && elts_read == block_size)
03151 {
03152 seek_status = strm.seek (skip, SEEK_CUR);
03153 elts_read = 0;
03154 }
03155
03156 if (is.eof () || seek_status < 0)
03157 {
03158 if (nr > 0)
03159 {
03160 if (count > nr)
03161 {
03162 final_nr = nr;
03163 final_nc = (count - 1) / nr + 1;
03164 }
03165 else
03166 {
03167 final_nr = count;
03168 final_nc = 1;
03169 }
03170 }
03171 else
03172 {
03173 final_nr = count;
03174 final_nc = 1;
03175 }
03176
03177 break;
03178 }
03179 }
03180 else if (is.eof ())
03181 break;
03182 }
03183 }
03184
03185 nda.resize (dim_vector (final_nr, final_nc), elt_zero);
03186
03187 retval = nda;
03188
03189 return retval;
03190 }
03191
03192 #define DO_READ_VAL_TEMPLATE(RET_T, READ_T) \
03193 template octave_value \
03194 do_read<RET_T, READ_T> (octave_stream&, octave_idx_type, octave_idx_type, octave_idx_type, octave_idx_type, bool, bool, \
03195 oct_mach_info::float_format, octave_idx_type&)
03196
03197
03198
03199
03200 #define INSTANTIATE_DO_READ(VAL_T) \
03201 DO_READ_VAL_TEMPLATE (VAL_T, octave_int8); \
03202 DO_READ_VAL_TEMPLATE (VAL_T, octave_uint8); \
03203 DO_READ_VAL_TEMPLATE (VAL_T, octave_int16); \
03204 DO_READ_VAL_TEMPLATE (VAL_T, octave_uint16); \
03205 DO_READ_VAL_TEMPLATE (VAL_T, octave_int32); \
03206 DO_READ_VAL_TEMPLATE (VAL_T, octave_uint32); \
03207 DO_READ_VAL_TEMPLATE (VAL_T, octave_int64); \
03208 DO_READ_VAL_TEMPLATE (VAL_T, octave_uint64); \
03209 DO_READ_VAL_TEMPLATE (VAL_T, float); \
03210 DO_READ_VAL_TEMPLATE (VAL_T, double); \
03211 DO_READ_VAL_TEMPLATE (VAL_T, char); \
03212 DO_READ_VAL_TEMPLATE (VAL_T, signed char); \
03213 DO_READ_VAL_TEMPLATE (VAL_T, unsigned char)
03214
03215 INSTANTIATE_DO_READ (int8NDArray);
03216 INSTANTIATE_DO_READ (uint8NDArray);
03217 INSTANTIATE_DO_READ (int16NDArray);
03218 INSTANTIATE_DO_READ (uint16NDArray);
03219 INSTANTIATE_DO_READ (int32NDArray);
03220 INSTANTIATE_DO_READ (uint32NDArray);
03221 INSTANTIATE_DO_READ (int64NDArray);
03222 INSTANTIATE_DO_READ (uint64NDArray);
03223 INSTANTIATE_DO_READ (FloatNDArray);
03224 INSTANTIATE_DO_READ (NDArray);
03225 INSTANTIATE_DO_READ (charNDArray);
03226 INSTANTIATE_DO_READ (boolNDArray);
03227
03228 typedef octave_value (*read_fptr) (octave_stream&, octave_idx_type, octave_idx_type, octave_idx_type, octave_idx_type, bool, bool,
03229 oct_mach_info::float_format ffmt, octave_idx_type&);
03230
03231 #define FILL_TABLE_ROW(R, VAL_T) \
03232 read_fptr_table[R][oct_data_conv::dt_int8] = do_read<VAL_T, octave_int8>; \
03233 read_fptr_table[R][oct_data_conv::dt_uint8] = do_read<VAL_T, octave_uint8>; \
03234 read_fptr_table[R][oct_data_conv::dt_int16] = do_read<VAL_T, octave_int16>; \
03235 read_fptr_table[R][oct_data_conv::dt_uint16] = do_read<VAL_T, octave_uint16>; \
03236 read_fptr_table[R][oct_data_conv::dt_int32] = do_read<VAL_T, octave_int32>; \
03237 read_fptr_table[R][oct_data_conv::dt_uint32] = do_read<VAL_T, octave_uint32>; \
03238 read_fptr_table[R][oct_data_conv::dt_int64] = do_read<VAL_T, octave_int64>; \
03239 read_fptr_table[R][oct_data_conv::dt_uint64] = do_read<VAL_T, octave_uint64>; \
03240 read_fptr_table[R][oct_data_conv::dt_single] = do_read<VAL_T, float>; \
03241 read_fptr_table[R][oct_data_conv::dt_double] = do_read<VAL_T, double>; \
03242 read_fptr_table[R][oct_data_conv::dt_char] = do_read<VAL_T, char>; \
03243 read_fptr_table[R][oct_data_conv::dt_schar] = do_read<VAL_T, signed char>; \
03244 read_fptr_table[R][oct_data_conv::dt_uchar] = do_read<VAL_T, unsigned char>; \
03245 read_fptr_table[R][oct_data_conv::dt_logical] = do_read<VAL_T, unsigned char>
03246
03247 octave_value
03248 octave_stream::read (const Array<double>& size, octave_idx_type block_size,
03249 oct_data_conv::data_type input_type,
03250 oct_data_conv::data_type output_type,
03251 octave_idx_type skip, oct_mach_info::float_format ffmt,
03252 octave_idx_type& char_count)
03253 {
03254 static bool initialized = false;
03255
03256
03257
03258 static read_fptr read_fptr_table[oct_data_conv::dt_unknown][14];
03259
03260 if (! initialized)
03261 {
03262 for (int i = 0; i < oct_data_conv::dt_unknown; i++)
03263 for (int j = 0; j < 14; j++)
03264 read_fptr_table[i][j] = 0;
03265
03266 FILL_TABLE_ROW (oct_data_conv::dt_int8, int8NDArray);
03267 FILL_TABLE_ROW (oct_data_conv::dt_uint8, uint8NDArray);
03268 FILL_TABLE_ROW (oct_data_conv::dt_int16, int16NDArray);
03269 FILL_TABLE_ROW (oct_data_conv::dt_uint16, uint16NDArray);
03270 FILL_TABLE_ROW (oct_data_conv::dt_int32, int32NDArray);
03271 FILL_TABLE_ROW (oct_data_conv::dt_uint32, uint32NDArray);
03272 FILL_TABLE_ROW (oct_data_conv::dt_int64, int64NDArray);
03273 FILL_TABLE_ROW (oct_data_conv::dt_uint64, uint64NDArray);
03274 FILL_TABLE_ROW (oct_data_conv::dt_single, FloatNDArray);
03275 FILL_TABLE_ROW (oct_data_conv::dt_double, NDArray);
03276 FILL_TABLE_ROW (oct_data_conv::dt_char, charNDArray);
03277 FILL_TABLE_ROW (oct_data_conv::dt_schar, charNDArray);
03278 FILL_TABLE_ROW (oct_data_conv::dt_uchar, charNDArray);
03279 FILL_TABLE_ROW (oct_data_conv::dt_logical, boolNDArray);
03280
03281 initialized = true;
03282 }
03283
03284 octave_value retval;
03285
03286 if (stream_ok ())
03287 {
03288
03289
03290
03291
03292
03293
03294 char_count = 0;
03295
03296 octave_idx_type nr = -1;
03297 octave_idx_type nc = -1;
03298
03299 bool ignore;
03300
03301 get_size (size, nr, nc, ignore, "fread");
03302
03303 if (! error_state)
03304 {
03305 if (nr == 0 || nc == 0)
03306 retval = Matrix (nr, nc);
03307 else
03308 {
03309 if (ffmt == oct_mach_info::flt_fmt_unknown)
03310 ffmt = float_format ();
03311
03312 read_fptr fcn = read_fptr_table[output_type][input_type];
03313
03314 bool do_float_fmt_conv = ((input_type == oct_data_conv::dt_double
03315 || input_type == oct_data_conv::dt_single)
03316 && ffmt != float_format ());
03317
03318 bool do_NA_conv = (output_type == oct_data_conv::dt_double);
03319
03320 if (fcn)
03321 {
03322 retval = (*fcn) (*this, nr, nc, block_size, skip,
03323 do_float_fmt_conv, do_NA_conv,
03324 ffmt, char_count);
03325
03326
03327
03328 if (! error_state
03329 && (output_type == oct_data_conv::dt_char
03330 || output_type == oct_data_conv::dt_schar
03331 || output_type == oct_data_conv::dt_uchar))
03332 retval = retval.char_matrix_value ();
03333 }
03334 else
03335 error ("fread: unable to read and convert requested types");
03336 }
03337 }
03338 else
03339 invalid_operation ("fread", "reading");
03340 }
03341
03342 return retval;
03343 }
03344
03345 octave_idx_type
03346 octave_stream::write (const octave_value& data, octave_idx_type block_size,
03347 oct_data_conv::data_type output_type, octave_idx_type skip,
03348 oct_mach_info::float_format flt_fmt)
03349 {
03350 octave_idx_type retval = -1;
03351
03352 if (stream_ok ())
03353 {
03354 if (! error_state)
03355 {
03356 if (flt_fmt == oct_mach_info::flt_fmt_unknown)
03357 flt_fmt = float_format ();
03358
03359 octave_idx_type status = data.write (*this, block_size, output_type,
03360 skip, flt_fmt);
03361
03362 if (status < 0)
03363 error ("fwrite: write error");
03364 else
03365 retval = status;
03366 }
03367 else
03368 invalid_operation ("fwrite", "writing");
03369 }
03370
03371 return retval;
03372 }
03373
03374 template <class T>
03375 void
03376 write_int (std::ostream& os, bool swap, const T& val)
03377 {
03378 typename T::val_type tmp = val.value ();
03379
03380 if (swap)
03381 swap_bytes<sizeof (typename T::val_type)> (&tmp);
03382
03383 os.write (reinterpret_cast<const char *> (&tmp),
03384 sizeof (typename T::val_type));
03385 }
03386
03387 template void write_int (std::ostream&, bool, const octave_int8&);
03388 template void write_int (std::ostream&, bool, const octave_uint8&);
03389 template void write_int (std::ostream&, bool, const octave_int16&);
03390 template void write_int (std::ostream&, bool, const octave_uint16&);
03391 template void write_int (std::ostream&, bool, const octave_int32&);
03392 template void write_int (std::ostream&, bool, const octave_uint32&);
03393 template void write_int (std::ostream&, bool, const octave_int64&);
03394 template void write_int (std::ostream&, bool, const octave_uint64&);
03395
03396 template <class T>
03397 static inline bool
03398 do_write (std::ostream& os, const T& val, oct_data_conv::data_type output_type,
03399 oct_mach_info::float_format flt_fmt, bool swap,
03400 bool do_float_conversion)
03401 {
03402 bool retval = true;
03403
03404
03405
03406
03407
03408
03409
03410
03411
03412
03413
03414
03415
03416 switch (output_type)
03417 {
03418 case oct_data_conv::dt_char:
03419 case oct_data_conv::dt_schar:
03420 case oct_data_conv::dt_int8:
03421 write_int (os, swap, octave_int8 (val));
03422 break;
03423
03424 case oct_data_conv::dt_uchar:
03425 case oct_data_conv::dt_uint8:
03426 write_int (os, swap, octave_uint8 (val));
03427 break;
03428
03429 case oct_data_conv::dt_int16:
03430 write_int (os, swap, octave_int16 (val));
03431 break;
03432
03433 case oct_data_conv::dt_uint16:
03434 write_int (os, swap, octave_uint16 (val));
03435 break;
03436
03437 case oct_data_conv::dt_int32:
03438 write_int (os, swap, octave_int32 (val));
03439 break;
03440
03441 case oct_data_conv::dt_uint32:
03442 write_int (os, swap, octave_uint32 (val));
03443 break;
03444
03445 case oct_data_conv::dt_int64:
03446 write_int (os, swap, octave_int64 (val));
03447 break;
03448
03449 case oct_data_conv::dt_uint64:
03450 write_int (os, swap, octave_uint64 (val));
03451 break;
03452
03453 case oct_data_conv::dt_single:
03454 {
03455 float f = static_cast<float> (val);
03456
03457 if (do_float_conversion)
03458 do_float_format_conversion (&f, 1, flt_fmt);
03459
03460 os.write (reinterpret_cast<const char *> (&f), sizeof (float));
03461 }
03462 break;
03463
03464 case oct_data_conv::dt_double:
03465 {
03466 double d = static_cast<double> (val);
03467 if (do_float_conversion)
03468 do_double_format_conversion (&d, 1, flt_fmt);
03469
03470 os.write (reinterpret_cast<const char *> (&d), sizeof (double));
03471 }
03472 break;
03473
03474 default:
03475 retval = false;
03476 (*current_liboctave_error_handler)
03477 ("write: invalid type specification");
03478 break;
03479 }
03480
03481 return retval;
03482 }
03483
03484 template bool
03485 do_write (std::ostream&, const octave_int8&, oct_data_conv::data_type,
03486 oct_mach_info::float_format, bool, bool);
03487
03488 template bool
03489 do_write (std::ostream&, const octave_uint8&, oct_data_conv::data_type,
03490 oct_mach_info::float_format, bool, bool);
03491
03492 template bool
03493 do_write (std::ostream&, const octave_int16&, oct_data_conv::data_type,
03494 oct_mach_info::float_format, bool, bool);
03495
03496 template bool
03497 do_write (std::ostream&, const octave_uint16&, oct_data_conv::data_type,
03498 oct_mach_info::float_format, bool, bool);
03499
03500 template bool
03501 do_write (std::ostream&, const octave_int32&, oct_data_conv::data_type,
03502 oct_mach_info::float_format, bool, bool);
03503
03504 template bool
03505 do_write (std::ostream&, const octave_uint32&, oct_data_conv::data_type,
03506 oct_mach_info::float_format, bool, bool);
03507
03508 template bool
03509 do_write (std::ostream&, const octave_int64&, oct_data_conv::data_type,
03510 oct_mach_info::float_format, bool, bool);
03511
03512 template bool
03513 do_write (std::ostream&, const octave_uint64&, oct_data_conv::data_type,
03514 oct_mach_info::float_format, bool, bool);
03515
03516 template <class T>
03517 octave_idx_type
03518 octave_stream::write (const Array<T>& data, octave_idx_type block_size,
03519 oct_data_conv::data_type output_type,
03520 octave_idx_type skip, oct_mach_info::float_format flt_fmt)
03521 {
03522 octave_idx_type retval = -1;
03523
03524 bool status = true;
03525
03526 octave_idx_type count = 0;
03527
03528 const T *d = data.data ();
03529
03530 octave_idx_type n = data.length ();
03531
03532 oct_mach_info::float_format native_flt_fmt
03533 = oct_mach_info::float_format ();
03534
03535 bool do_float_conversion = (flt_fmt != native_flt_fmt);
03536
03537
03538
03539 bool swap = false;
03540
03541 if (oct_mach_info::words_big_endian ())
03542 swap = (flt_fmt == oct_mach_info::flt_fmt_ieee_little_endian
03543 || flt_fmt == oct_mach_info::flt_fmt_vax_g
03544 || flt_fmt == oct_mach_info::flt_fmt_vax_g);
03545 else
03546 swap = (flt_fmt == oct_mach_info::flt_fmt_ieee_big_endian);
03547
03548 for (octave_idx_type i = 0; i < n; i++)
03549 {
03550 std::ostream *osp = output_stream ();
03551
03552 if (osp)
03553 {
03554 std::ostream& os = *osp;
03555
03556 if (skip != 0 && (i % block_size) == 0)
03557 {
03558
03559
03560
03561 long orig_pos = tell ();
03562
03563 seek (0, SEEK_END);
03564
03565 long eof_pos = tell ();
03566
03567
03568
03569 seek (orig_pos, SEEK_SET);
03570
03571 long remaining = eof_pos - orig_pos;
03572
03573 if (remaining < skip)
03574 {
03575 seek (0, SEEK_END);
03576
03577
03578
03579
03580 unsigned char zero = 0;
03581 for (octave_idx_type j = 0; j < skip - remaining; j++)
03582 os.write (reinterpret_cast<const char *> (&zero), 1);
03583 }
03584 else
03585 seek (skip, SEEK_CUR);
03586 }
03587
03588 if (os)
03589 {
03590 status = do_write (os, d[i], output_type, flt_fmt, swap,
03591 do_float_conversion);
03592
03593 if (os && status)
03594 count++;
03595 else
03596 break;
03597 }
03598 else
03599 {
03600 status = false;
03601 break;
03602 }
03603 }
03604 else
03605 {
03606 status = false;
03607 break;
03608 }
03609 }
03610
03611 if (status)
03612 retval = count;
03613
03614 return retval;
03615 }
03616
03617 template octave_idx_type
03618 octave_stream::write (const Array<char>&, octave_idx_type,
03619 oct_data_conv::data_type,
03620 octave_idx_type, oct_mach_info::float_format);
03621
03622 template octave_idx_type
03623 octave_stream::write (const Array<bool>&, octave_idx_type,
03624 oct_data_conv::data_type,
03625 octave_idx_type, oct_mach_info::float_format);
03626
03627 template octave_idx_type
03628 octave_stream::write (const Array<double>&, octave_idx_type,
03629 oct_data_conv::data_type,
03630 octave_idx_type, oct_mach_info::float_format);
03631
03632 template octave_idx_type
03633 octave_stream::write (const Array<float>&, octave_idx_type,
03634 oct_data_conv::data_type,
03635 octave_idx_type, oct_mach_info::float_format);
03636
03637 template octave_idx_type
03638 octave_stream::write (const Array<octave_int8>&, octave_idx_type,
03639 oct_data_conv::data_type,
03640 octave_idx_type, oct_mach_info::float_format);
03641
03642 template octave_idx_type
03643 octave_stream::write (const Array<octave_uint8>&, octave_idx_type,
03644 oct_data_conv::data_type,
03645 octave_idx_type, oct_mach_info::float_format);
03646
03647 template octave_idx_type
03648 octave_stream::write (const Array<octave_int16>&, octave_idx_type,
03649 oct_data_conv::data_type,
03650 octave_idx_type, oct_mach_info::float_format);
03651
03652 template octave_idx_type
03653 octave_stream::write (const Array<octave_uint16>&, octave_idx_type,
03654 oct_data_conv::data_type,
03655 octave_idx_type, oct_mach_info::float_format);
03656
03657 template octave_idx_type
03658 octave_stream::write (const Array<octave_int32>&, octave_idx_type,
03659 oct_data_conv::data_type,
03660 octave_idx_type, oct_mach_info::float_format);
03661
03662 template octave_idx_type
03663 octave_stream::write (const Array<octave_uint32>&, octave_idx_type,
03664 oct_data_conv::data_type,
03665 octave_idx_type, oct_mach_info::float_format);
03666
03667 template octave_idx_type
03668 octave_stream::write (const Array<octave_int64>&, octave_idx_type,
03669 oct_data_conv::data_type,
03670 octave_idx_type, oct_mach_info::float_format);
03671
03672 template octave_idx_type
03673 octave_stream::write (const Array<octave_uint64>&, octave_idx_type,
03674 oct_data_conv::data_type,
03675 octave_idx_type, oct_mach_info::float_format);
03676
03677 octave_value
03678 octave_stream::scanf (const std::string& fmt, const Array<double>& size,
03679 octave_idx_type& count, const std::string& who)
03680 {
03681 octave_value retval;
03682
03683 if (stream_ok ())
03684 retval = rep->scanf (fmt, size, count, who);
03685
03686 return retval;
03687 }
03688
03689 octave_value
03690 octave_stream::scanf (const octave_value& fmt, const Array<double>& size,
03691 octave_idx_type& count, const std::string& who)
03692 {
03693 octave_value retval = Matrix ();
03694
03695 if (fmt.is_string ())
03696 {
03697 std::string sfmt = fmt.string_value ();
03698
03699 if (fmt.is_sq_string ())
03700 sfmt = do_string_escapes (sfmt);
03701
03702 retval = scanf (sfmt, size, count, who);
03703 }
03704 else
03705 {
03706
03707
03708 error (who + ": format must be a string");
03709 }
03710
03711 return retval;
03712 }
03713
03714 octave_value_list
03715 octave_stream::oscanf (const std::string& fmt, const std::string& who)
03716 {
03717 octave_value_list retval;
03718
03719 if (stream_ok ())
03720 retval = rep->oscanf (fmt, who);
03721
03722 return retval;
03723 }
03724
03725 octave_value_list
03726 octave_stream::oscanf (const octave_value& fmt, const std::string& who)
03727 {
03728 octave_value_list retval;
03729
03730 if (fmt.is_string ())
03731 {
03732 std::string sfmt = fmt.string_value ();
03733
03734 if (fmt.is_sq_string ())
03735 sfmt = do_string_escapes (sfmt);
03736
03737 retval = oscanf (sfmt, who);
03738 }
03739 else
03740 {
03741
03742
03743 error (who + ": format must be a string");
03744 }
03745
03746 return retval;
03747 }
03748
03749 int
03750 octave_stream::printf (const std::string& fmt, const octave_value_list& args,
03751 const std::string& who)
03752 {
03753 int retval = -1;
03754
03755 if (stream_ok ())
03756 retval = rep->printf (fmt, args, who);
03757
03758 return retval;
03759 }
03760
03761 int
03762 octave_stream::printf (const octave_value& fmt, const octave_value_list& args,
03763 const std::string& who)
03764 {
03765 int retval = 0;
03766
03767 if (fmt.is_string ())
03768 {
03769 std::string sfmt = fmt.string_value ();
03770
03771 if (fmt.is_sq_string ())
03772 sfmt = do_string_escapes (sfmt);
03773
03774 retval = printf (sfmt, args, who);
03775 }
03776 else
03777 {
03778
03779
03780 error (who + ": format must be a string");
03781 }
03782
03783 return retval;
03784 }
03785
03786 int
03787 octave_stream::puts (const std::string& s, const std::string& who)
03788 {
03789 int retval = -1;
03790
03791 if (stream_ok ())
03792 retval = rep->puts (s, who);
03793
03794 return retval;
03795 }
03796
03797
03798
03799 int
03800 octave_stream::puts (const octave_value& tc_s, const std::string& who)
03801 {
03802 int retval = -1;
03803
03804 if (tc_s.is_string ())
03805 {
03806 std::string s = tc_s.string_value ();
03807 retval = puts (s, who);
03808 }
03809 else
03810 {
03811
03812
03813 error (who + ": argument must be a string");
03814 }
03815
03816 return retval;
03817 }
03818
03819 bool
03820 octave_stream::eof (void) const
03821 {
03822 int retval = -1;
03823
03824 if (stream_ok ())
03825 retval = rep->eof ();
03826
03827 return retval;
03828 }
03829
03830 std::string
03831 octave_stream::error (bool clear, int& err_num)
03832 {
03833 std::string retval = "invalid stream object";
03834
03835 if (stream_ok (false))
03836 retval = rep->error (clear, err_num);
03837
03838 return retval;
03839 }
03840
03841 std::string
03842 octave_stream::name (void) const
03843 {
03844 std::string retval;
03845
03846 if (stream_ok ())
03847 retval = rep->name ();
03848
03849 return retval;
03850 }
03851
03852 int
03853 octave_stream::mode (void) const
03854 {
03855 int retval = 0;
03856
03857 if (stream_ok ())
03858 retval = rep->mode ();
03859
03860 return retval;
03861 }
03862
03863 oct_mach_info::float_format
03864 octave_stream::float_format (void) const
03865 {
03866 oct_mach_info::float_format retval = oct_mach_info::flt_fmt_unknown;
03867
03868 if (stream_ok ())
03869 retval = rep->float_format ();
03870
03871 return retval;
03872 }
03873
03874 std::string
03875 octave_stream::mode_as_string (int mode)
03876 {
03877 std::string retval = "???";
03878 std::ios::openmode in_mode = static_cast<std::ios::openmode> (mode);
03879
03880 if (in_mode == std::ios::in)
03881 retval = "r";
03882 else if (in_mode == std::ios::out
03883 || in_mode == (std::ios::out | std::ios::trunc))
03884 retval = "w";
03885 else if (in_mode == (std::ios::out | std::ios::app))
03886 retval = "a";
03887 else if (in_mode == (std::ios::in | std::ios::out))
03888 retval = "r+";
03889 else if (in_mode == (std::ios::in | std::ios::out | std::ios::trunc))
03890 retval = "w+";
03891 else if (in_mode == (std::ios::in | std::ios::out | std::ios::ate))
03892 retval = "a+";
03893 else if (in_mode == (std::ios::in | std::ios::binary))
03894 retval = "rb";
03895 else if (in_mode == (std::ios::out | std::ios::binary)
03896 || in_mode == (std::ios::out | std::ios::trunc | std::ios::binary))
03897 retval = "wb";
03898 else if (in_mode == (std::ios::out | std::ios::app | std::ios::binary))
03899 retval = "ab";
03900 else if (in_mode == (std::ios::in | std::ios::out | std::ios::binary))
03901 retval = "r+b";
03902 else if (in_mode == (std::ios::in | std::ios::out | std::ios::trunc
03903 | std::ios::binary))
03904 retval = "w+b";
03905 else if (in_mode == (std::ios::in | std::ios::out | std::ios::ate
03906 | std::ios::binary))
03907 retval = "a+b";
03908
03909 return retval;
03910 }
03911
03912 octave_stream_list *octave_stream_list::instance = 0;
03913
03914 bool
03915 octave_stream_list::instance_ok (void)
03916 {
03917 bool retval = true;
03918
03919 if (! instance)
03920 {
03921 instance = new octave_stream_list ();
03922
03923 if (instance)
03924 singleton_cleanup_list::add (cleanup_instance);
03925 }
03926
03927 if (! instance)
03928 {
03929 ::error ("unable to create stream list object!");
03930
03931 retval = false;
03932 }
03933
03934 return retval;
03935 }
03936
03937 int
03938 octave_stream_list::insert (octave_stream& os)
03939 {
03940 return (instance_ok ()) ? instance->do_insert (os) : -1;
03941 }
03942
03943 octave_stream
03944 octave_stream_list::lookup (int fid, const std::string& who)
03945 {
03946 return (instance_ok ()) ? instance->do_lookup (fid, who) : octave_stream ();
03947 }
03948
03949 octave_stream
03950 octave_stream_list::lookup (const octave_value& fid, const std::string& who)
03951 {
03952 return (instance_ok ()) ? instance->do_lookup (fid, who) : octave_stream ();
03953 }
03954
03955 int
03956 octave_stream_list::remove (int fid, const std::string& who)
03957 {
03958 return (instance_ok ()) ? instance->do_remove (fid, who) : -1;
03959 }
03960
03961 int
03962 octave_stream_list::remove (const octave_value& fid, const std::string& who)
03963 {
03964 return (instance_ok ()) ? instance->do_remove (fid, who) : -1;
03965 }
03966
03967 void
03968 octave_stream_list::clear (bool flush)
03969 {
03970 if (instance)
03971 instance->do_clear (flush);
03972 }
03973
03974 string_vector
03975 octave_stream_list::get_info (int fid)
03976 {
03977 return (instance_ok ()) ? instance->do_get_info (fid) : string_vector ();
03978 }
03979
03980 string_vector
03981 octave_stream_list::get_info (const octave_value& fid)
03982 {
03983 return (instance_ok ()) ? instance->do_get_info (fid) : string_vector ();
03984 }
03985
03986 std::string
03987 octave_stream_list::list_open_files (void)
03988 {
03989 return (instance_ok ()) ? instance->do_list_open_files () : std::string ();
03990 }
03991
03992 octave_value
03993 octave_stream_list::open_file_numbers (void)
03994 {
03995 return (instance_ok ())
03996 ? instance->do_open_file_numbers () : octave_value ();
03997 }
03998
03999 int
04000 octave_stream_list::get_file_number (const octave_value& fid)
04001 {
04002 return (instance_ok ()) ? instance->do_get_file_number (fid) : -1;
04003 }
04004
04005 int
04006 octave_stream_list::do_insert (octave_stream& os)
04007 {
04008
04009
04010 int stream_number;
04011
04012 if ((stream_number = os.file_number ()) == -1)
04013 return stream_number;
04014
04015
04016
04017
04018
04019
04020
04021
04022
04023
04024
04025 if (list.size () < list.max_size ())
04026 list[stream_number] = os;
04027 else
04028 {
04029 stream_number = -1;
04030 error ("could not create file id");
04031 }
04032
04033 return stream_number;
04034
04035 }
04036
04037 static void
04038 gripe_invalid_file_id (int fid, const std::string& who)
04039 {
04040 if (who.empty ())
04041 ::error ("invalid stream number = %d", fid);
04042 else
04043 ::error ("%s: invalid stream number = %d", who.c_str (), fid);
04044 }
04045
04046 octave_stream
04047 octave_stream_list::do_lookup (int fid, const std::string& who) const
04048 {
04049 octave_stream retval;
04050
04051 if (fid >= 0)
04052 {
04053 if (lookup_cache != list.end () && lookup_cache->first == fid)
04054 retval = lookup_cache->second;
04055 else
04056 {
04057 ostrl_map::const_iterator iter = list.find (fid);
04058
04059 if (iter != list.end ())
04060 {
04061 retval = iter->second;
04062 lookup_cache = iter;
04063 }
04064 else
04065 gripe_invalid_file_id (fid, who);
04066 }
04067 }
04068 else
04069 gripe_invalid_file_id (fid, who);
04070
04071 return retval;
04072 }
04073
04074 octave_stream
04075 octave_stream_list::do_lookup (const octave_value& fid,
04076 const std::string& who) const
04077 {
04078 octave_stream retval;
04079
04080 int i = get_file_number (fid);
04081
04082 if (! error_state)
04083 retval = do_lookup (i, who);
04084
04085 return retval;
04086 }
04087
04088 int
04089 octave_stream_list::do_remove (int fid, const std::string& who)
04090 {
04091 int retval = -1;
04092
04093
04094
04095
04096 if (fid > 2)
04097 {
04098 ostrl_map::iterator iter = list.find (fid);
04099
04100 if (iter != list.end ())
04101 {
04102 octave_stream os = iter->second;
04103 list.erase (iter);
04104 lookup_cache = list.end ();
04105
04106
04107 if (os.is_valid ())
04108 {
04109 os.close ();
04110 retval = 0;
04111 }
04112 else
04113 gripe_invalid_file_id (fid, who);
04114 }
04115 else
04116 gripe_invalid_file_id (fid, who);
04117 }
04118 else
04119 gripe_invalid_file_id (fid, who);
04120
04121 return retval;
04122 }
04123
04124 int
04125 octave_stream_list::do_remove (const octave_value& fid, const std::string& who)
04126 {
04127 int retval = -1;
04128
04129 if (fid.is_string () && fid.string_value () == "all")
04130 {
04131 do_clear (false);
04132
04133 retval = 0;
04134 }
04135 else
04136 {
04137 int i = get_file_number (fid);
04138
04139 if (! error_state)
04140 retval = do_remove (i, who);
04141 }
04142
04143 return retval;
04144 }
04145
04146 void
04147 octave_stream_list::do_clear (bool flush)
04148 {
04149 if (flush)
04150 {
04151
04152
04153 list[0].flush ();
04154 list[1].flush ();
04155 }
04156
04157 octave_stream saved_os[3];
04158
04159 for (ostrl_map::iterator iter = list.begin (); iter != list.end (); iter++)
04160 {
04161 int fid = iter->first;
04162 octave_stream os = iter->second;
04163 if (fid < 3)
04164 saved_os[fid] = os;
04165 else if (os.is_valid ())
04166 os.close ();
04167 }
04168 list.clear ();
04169 for (int fid = 0; fid < 3; fid++) list[fid] = saved_os[fid];
04170 lookup_cache = list.end ();
04171 }
04172
04173 string_vector
04174 octave_stream_list::do_get_info (int fid) const
04175 {
04176 string_vector retval;
04177
04178 octave_stream os = do_lookup (fid);
04179
04180 if (os.is_valid ())
04181 {
04182 retval.resize (3);
04183
04184 retval(2) = oct_mach_info::float_format_as_string (os.float_format ());
04185 retval(1) = octave_stream::mode_as_string (os.mode ());
04186 retval(0) = os.name ();
04187 }
04188 else
04189 ::error ("invalid file id = %d", fid);
04190
04191 return retval;
04192 }
04193
04194 string_vector
04195 octave_stream_list::do_get_info (const octave_value& fid) const
04196 {
04197 string_vector retval;
04198
04199 int conv_err = 0;
04200
04201 int int_fid = convert_to_valid_int (fid, conv_err);
04202
04203 if (! conv_err)
04204 retval = do_get_info (int_fid);
04205 else
04206 ::error ("file id must be a file object or integer value");
04207
04208 return retval;
04209 }
04210
04211 std::string
04212 octave_stream_list::do_list_open_files (void) const
04213 {
04214 std::string retval;
04215
04216 std::ostringstream buf;
04217
04218 buf << "\n"
04219 << " number mode arch name\n"
04220 << " ------ ---- ---- ----\n";
04221
04222 for (ostrl_map::const_iterator p = list.begin (); p != list.end (); p++)
04223 {
04224 octave_stream os = p->second;
04225
04226 buf << " "
04227 << std::setiosflags (std::ios::right)
04228 << std::setw (4) << p->first << " "
04229 << std::setiosflags (std::ios::left)
04230 << std::setw (3)
04231 << octave_stream::mode_as_string (os.mode ())
04232 << " "
04233 << std::setw (9)
04234 << oct_mach_info::float_format_as_string (os.float_format ())
04235 << " "
04236 << os.name () << "\n";
04237 }
04238
04239 buf << "\n";
04240
04241 retval = buf.str ();
04242
04243 return retval;
04244 }
04245
04246 octave_value
04247 octave_stream_list::do_open_file_numbers (void) const
04248 {
04249 Matrix retval (1, list.size (), 0.0);
04250
04251 int num_open = 0;
04252
04253 for (ostrl_map::const_iterator p = list.begin (); p != list.end (); p++)
04254 {
04255
04256
04257 if (p->first > 2 && p->second)
04258 retval(0,num_open++) = p->first;
04259 }
04260
04261 retval.resize ((num_open > 0), num_open);
04262
04263 return retval;
04264 }
04265
04266 int
04267 octave_stream_list::do_get_file_number (const octave_value& fid) const
04268 {
04269 int retval = -1;
04270
04271 if (fid.is_string ())
04272 {
04273 std::string nm = fid.string_value ();
04274
04275 for (ostrl_map::const_iterator p = list.begin (); p != list.end (); p++)
04276 {
04277
04278
04279
04280 if (p->first > 2)
04281 {
04282 octave_stream os = p->second;
04283
04284 if (os && os.name () == nm)
04285 {
04286 retval = p->first;
04287 break;
04288 }
04289 }
04290 }
04291 }
04292 else
04293 {
04294 int conv_err = 0;
04295
04296 int int_fid = convert_to_valid_int (fid, conv_err);
04297
04298 if (conv_err)
04299 ::error ("file id must be a file object, std::string, or integer value");
04300 else
04301 retval = int_fid;
04302 }
04303
04304 return retval;
04305 }