Mercurial > octave-nkf
annotate src/oct-stream.cc @ 7538:2c4b0cbda85a
oct-stream.cc (do_read): stop reading if seek fails
author | John W. Eaton <jwe@octave.org> |
---|---|
date | Wed, 27 Feb 2008 22:47:58 -0500 |
parents | 402168152bb9 |
children | fa41af732801 |
rev | line source |
---|---|
2117 | 1 /* |
2 | |
7017 | 3 Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, |
4 2005, 2006, 2007 John W. Eaton | |
2117 | 5 |
6 This file is part of Octave. | |
7 | |
8 Octave is free software; you can redistribute it and/or modify it | |
9 under the terms of the GNU General Public License as published by the | |
7016 | 10 Free Software Foundation; either version 3 of the License, or (at your |
11 option) any later version. | |
2117 | 12 |
13 Octave is distributed in the hope that it will be useful, but WITHOUT | |
14 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
16 for more details. | |
17 | |
18 You should have received a copy of the GNU General Public License | |
7016 | 19 along with Octave; see the file COPYING. If not, see |
20 <http://www.gnu.org/licenses/>. | |
2117 | 21 |
22 */ | |
23 | |
24 #ifdef HAVE_CONFIG_H | |
25 #include <config.h> | |
26 #endif | |
27 | |
3268 | 28 #include <cassert> |
2215 | 29 #include <cstring> |
30 | |
3503 | 31 #include <iomanip> |
3559 | 32 #include <fstream> |
5765 | 33 #include <sstream> |
3535 | 34 #include <string> |
2117 | 35 |
4944 | 36 #include <Array.h> |
37 #include <Array2.h> | |
38 #include <Array3.h> | |
39 | |
40 #include <Array.cc> | |
41 | |
42 #include "byte-swap.h" | |
2117 | 43 #include "lo-ieee.h" |
44 #include "lo-mappers.h" | |
45 #include "lo-utils.h" | |
46 #include "str-vec.h" | |
4153 | 47 #include "quit.h" |
2117 | 48 |
49 #include "error.h" | |
7352 | 50 #include "gripes.h" |
3342 | 51 #include "input.h" |
3775 | 52 #include "oct-stdstrm.h" |
2117 | 53 #include "oct-stream.h" |
2877 | 54 #include "oct-obj.h" |
2117 | 55 #include "utils.h" |
56 | |
57 // Possible values for conv_err: | |
58 // | |
59 // 1 : not a real scalar | |
2902 | 60 // 2 : value is NaN |
61 // 3 : value is not an integer | |
2117 | 62 |
63 static int | |
64 convert_to_valid_int (const octave_value& tc, int& conv_err) | |
65 { | |
66 int retval = 0; | |
67 | |
68 conv_err = 0; | |
69 | |
2902 | 70 double dval = tc.double_value (); |
71 | |
72 if (! error_state) | |
2117 | 73 { |
5389 | 74 if (! lo_ieee_isnan (dval)) |
2117 | 75 { |
2902 | 76 int ival = NINT (dval); |
77 | |
78 if (ival == dval) | |
79 retval = ival; | |
2117 | 80 else |
81 conv_err = 3; | |
82 } | |
83 else | |
84 conv_err = 2; | |
85 } | |
86 else | |
87 conv_err = 1; | |
88 | |
89 return retval; | |
90 } | |
91 | |
92 static int | |
4468 | 93 get_size (double d, const std::string& who) |
2117 | 94 { |
95 int retval = -1; | |
96 | |
5389 | 97 if (! lo_ieee_isnan (d)) |
2117 | 98 { |
99 if (! xisinf (d)) | |
100 { | |
3268 | 101 if (d >= 0.0) |
2117 | 102 retval = NINT (d); |
103 else | |
104 ::error ("%s: negative value invalid as size specification", | |
4468 | 105 who.c_str ()); |
2117 | 106 } |
107 else | |
108 retval = -1; | |
109 } | |
110 else | |
4468 | 111 ::error ("%s: NaN is invalid as size specification", who.c_str ()); |
2117 | 112 |
113 return retval; | |
114 } | |
115 | |
116 static void | |
5275 | 117 get_size (const Array<double>& size, octave_idx_type& nr, octave_idx_type& nc, bool& one_elt_size_spec, |
4468 | 118 const std::string& who) |
2117 | 119 { |
120 nr = -1; | |
121 nc = -1; | |
122 | |
3268 | 123 one_elt_size_spec = false; |
124 | |
2117 | 125 double dnr = -1.0; |
126 double dnc = -1.0; | |
127 | |
5275 | 128 octave_idx_type sz_len = size.length (); |
3810 | 129 |
130 if (sz_len == 1) | |
2601 | 131 { |
3268 | 132 one_elt_size_spec = true; |
133 | |
3810 | 134 dnr = size (0); |
4293 | 135 |
136 dnc = (dnr == 0.0) ? 0.0 : 1.0; | |
2601 | 137 } |
3810 | 138 else if (sz_len == 2) |
2117 | 139 { |
3810 | 140 dnr = size (0); |
141 | |
142 if (! xisinf (dnr)) | |
143 dnc = size (1); | |
144 else | |
4468 | 145 ::error ("%s: invalid size specification", who.c_str ()); |
2117 | 146 } |
147 else | |
4468 | 148 ::error ("%s: invalid size specification", who.c_str ()); |
2117 | 149 |
150 if (! error_state) | |
151 { | |
4468 | 152 nr = get_size (dnr, who); |
2117 | 153 |
3268 | 154 if (! error_state && dnc >= 0.0) |
4468 | 155 nc = get_size (dnc, who); |
2117 | 156 } |
157 } | |
158 | |
3523 | 159 scanf_format_list::scanf_format_list (const std::string& s) |
2117 | 160 : nconv (0), curr_idx (0), list (16), buf (0) |
161 { | |
162 int num_elts = 0; | |
163 | |
164 int n = s.length (); | |
165 | |
166 int i = 0; | |
167 | |
2215 | 168 int width = 0; |
2117 | 169 bool discard = false; |
170 char modifier = '\0'; | |
171 char type = '\0'; | |
172 | |
173 bool have_more = true; | |
174 | |
175 while (i < n) | |
176 { | |
177 have_more = true; | |
178 | |
179 if (! buf) | |
5765 | 180 buf = new std::ostringstream (); |
2117 | 181 |
182 if (s[i] == '%') | |
183 { | |
3483 | 184 // Process percent-escape conversion type. |
185 | |
2215 | 186 process_conversion (s, i, n, width, discard, type, modifier, |
187 num_elts); | |
2117 | 188 have_more = (buf != 0); |
189 } | |
3483 | 190 else if (isspace (s[i])) |
2117 | 191 { |
3483 | 192 type = scanf_format_elt::whitespace_conversion; |
193 | |
2215 | 194 width = 0; |
2117 | 195 discard = false; |
196 modifier = '\0'; | |
3483 | 197 *buf << " "; |
198 | |
199 while (++i < n && isspace (s[i])) | |
200 /* skip whitespace */; | |
201 | |
202 add_elt_to_list (width, discard, type, modifier, num_elts); | |
203 | |
204 have_more = false; | |
205 } | |
206 else | |
207 { | |
208 type = scanf_format_elt::literal_conversion; | |
209 | |
210 width = 0; | |
211 discard = false; | |
212 modifier = '\0'; | |
213 | |
214 while (i < n && ! isspace (s[i]) && s[i] != '%') | |
215 *buf << s[i++]; | |
216 | |
217 add_elt_to_list (width, discard, type, modifier, num_elts); | |
218 | |
219 have_more = false; | |
2117 | 220 } |
221 | |
222 if (nconv < 0) | |
223 { | |
224 have_more = false; | |
225 break; | |
226 } | |
227 } | |
228 | |
229 if (have_more) | |
2215 | 230 add_elt_to_list (width, discard, type, modifier, num_elts); |
2117 | 231 |
232 list.resize (num_elts); | |
233 | |
234 delete buf; | |
235 } | |
236 | |
237 scanf_format_list::~scanf_format_list (void) | |
238 { | |
5275 | 239 octave_idx_type n = list.length (); |
240 | |
241 for (octave_idx_type i = 0; i < n; i++) | |
2117 | 242 { |
3340 | 243 scanf_format_elt *elt = list(i); |
2117 | 244 delete elt; |
245 } | |
246 } | |
247 | |
248 void | |
2215 | 249 scanf_format_list::add_elt_to_list (int width, bool discard, char type, |
3483 | 250 char modifier, int& num_elts, |
3523 | 251 const std::string& char_class) |
2117 | 252 { |
253 if (buf) | |
254 { | |
5765 | 255 std::string text = buf->str (); |
4051 | 256 |
257 if (! text.empty ()) | |
2117 | 258 { |
4051 | 259 scanf_format_elt *elt |
260 = new scanf_format_elt (text.c_str (), width, discard, type, | |
261 modifier, char_class); | |
262 | |
263 if (num_elts == list.length ()) | |
264 list.resize (2 * num_elts); | |
265 | |
266 list(num_elts++) = elt; | |
2117 | 267 } |
268 | |
269 delete buf; | |
270 buf = 0; | |
271 } | |
272 } | |
273 | |
3535 | 274 static std::string |
3523 | 275 expand_char_class (const std::string& s) |
3483 | 276 { |
3523 | 277 std::string retval; |
3483 | 278 |
279 size_t len = s.length (); | |
280 | |
281 size_t i = 0; | |
282 | |
283 while (i < len) | |
284 { | |
285 unsigned char c = s[i++]; | |
286 | |
287 if (c == '-' && i > 1 && i < len | |
5760 | 288 && static_cast<unsigned char> (s[i-2]) <= static_cast<unsigned char> (s[i])) |
3483 | 289 { |
290 // Add all characters from the range except the first (we | |
291 // already added it below). | |
292 | |
293 for (c = s[i-2]+1; c < s[i]; c++) | |
294 retval += c; | |
295 } | |
296 else | |
297 { | |
298 // Add the character to the class. Only add '-' if it is | |
299 // the last character in the class. | |
300 | |
301 if (c != '-' || i == len) | |
302 retval += c; | |
303 } | |
304 } | |
305 | |
306 return retval; | |
307 } | |
308 | |
2117 | 309 void |
3523 | 310 scanf_format_list::process_conversion (const std::string& s, int& i, int n, |
2215 | 311 int& width, bool& discard, char& type, |
2117 | 312 char& modifier, int& num_elts) |
313 { | |
2215 | 314 width = 0; |
2117 | 315 discard = false; |
316 modifier = '\0'; | |
317 type = '\0'; | |
318 | |
319 *buf << s[i++]; | |
320 | |
321 bool have_width = false; | |
322 | |
323 while (i < n) | |
324 { | |
325 switch (s[i]) | |
326 { | |
327 case '*': | |
328 if (discard) | |
329 nconv = -1; | |
330 else | |
331 { | |
332 discard = true; | |
333 *buf << s[i++]; | |
334 } | |
335 break; | |
336 | |
337 case '0': case '1': case '2': case '3': case '4': | |
338 case '5': case '6': case '7': case '8': case '9': | |
339 if (have_width) | |
340 nconv = -1; | |
341 else | |
342 { | |
2215 | 343 char c = s[i++]; |
344 width = width * 10 + c - '0'; | |
2117 | 345 have_width = true; |
2215 | 346 *buf << c; |
2117 | 347 while (i < n && isdigit (s[i])) |
2215 | 348 { |
349 c = s[i++]; | |
350 width = width * 10 + c - '0'; | |
351 *buf << c; | |
352 } | |
2117 | 353 } |
354 break; | |
355 | |
356 case 'h': case 'l': case 'L': | |
357 if (modifier != '\0') | |
358 nconv = -1; | |
359 else | |
2663 | 360 modifier = s[i++]; |
2117 | 361 break; |
362 | |
363 case 'd': case 'i': case 'o': case 'u': case 'x': | |
364 if (modifier == 'L') | |
365 { | |
366 nconv = -1; | |
367 break; | |
368 } | |
369 goto fini; | |
370 | |
371 case 'e': case 'f': case 'g': | |
372 if (modifier == 'h') | |
373 { | |
374 nconv = -1; | |
375 break; | |
376 } | |
2663 | 377 |
378 // No float or long double conversions, thanks. | |
379 *buf << 'l'; | |
380 | |
2117 | 381 goto fini; |
382 | |
383 case 'c': case 's': case 'p': case '%': case '[': | |
384 if (modifier != '\0') | |
385 { | |
386 nconv = -1; | |
387 break; | |
388 } | |
389 goto fini; | |
390 | |
391 fini: | |
392 { | |
2215 | 393 if (finish_conversion (s, i, n, width, discard, type, |
2117 | 394 modifier, num_elts) == 0) |
395 return; | |
396 } | |
397 break; | |
398 | |
399 default: | |
400 nconv = -1; | |
401 break; | |
402 } | |
403 | |
404 if (nconv < 0) | |
405 break; | |
406 } | |
407 | |
408 nconv = -1; | |
409 } | |
410 | |
411 int | |
3523 | 412 scanf_format_list::finish_conversion (const std::string& s, int& i, int n, |
2215 | 413 int& width, bool discard, char& type, |
2117 | 414 char modifier, int& num_elts) |
415 { | |
416 int retval = 0; | |
417 | |
3523 | 418 std::string char_class; |
3483 | 419 |
3640 | 420 int beg_idx = -1; |
421 int end_idx = -1; | |
422 | |
2117 | 423 if (s[i] == '%') |
3640 | 424 { |
425 type = '%'; | |
426 *buf << s[i++]; | |
427 } | |
2117 | 428 else |
429 { | |
430 type = s[i]; | |
431 | |
432 if (s[i] == '[') | |
433 { | |
434 *buf << s[i++]; | |
435 | |
436 if (i < n) | |
437 { | |
3483 | 438 beg_idx = i; |
439 | |
2117 | 440 if (s[i] == '^') |
441 { | |
442 type = '^'; | |
443 *buf << s[i++]; | |
3483 | 444 |
445 if (i < n) | |
446 { | |
447 beg_idx = i; | |
448 | |
449 if (s[i] == ']') | |
450 *buf << s[i++]; | |
451 } | |
2117 | 452 } |
453 else if (s[i] == ']') | |
454 *buf << s[i++]; | |
455 } | |
456 | |
457 while (i < n && s[i] != ']') | |
458 *buf << s[i++]; | |
459 | |
460 if (i < n && s[i] == ']') | |
3483 | 461 { |
462 end_idx = i-1; | |
463 *buf << s[i++]; | |
464 } | |
2117 | 465 |
466 if (s[i-1] != ']') | |
467 retval = nconv = -1; | |
468 } | |
469 else | |
2215 | 470 *buf << s[i++]; |
3640 | 471 } |
472 | |
473 nconv++; | |
474 | |
475 if (nconv > 0) | |
476 { | |
477 if (beg_idx >= 0 && end_idx >= 0) | |
478 char_class = expand_char_class (s.substr (beg_idx, | |
479 end_idx - beg_idx + 1)); | |
480 | |
481 add_elt_to_list (width, discard, type, modifier, num_elts, char_class); | |
2117 | 482 } |
483 | |
484 return retval; | |
485 } | |
486 | |
487 void | |
488 scanf_format_list::printme (void) const | |
489 { | |
490 int n = list.length (); | |
491 | |
492 for (int i = 0; i < n; i++) | |
493 { | |
3340 | 494 scanf_format_elt *elt = list(i); |
2117 | 495 |
3531 | 496 std::cerr |
497 << "width: " << elt->width << "\n" | |
498 << "discard: " << elt->discard << "\n" | |
499 << "type: "; | |
3483 | 500 |
501 if (elt->type == scanf_format_elt::literal_conversion) | |
3531 | 502 std::cerr << "literal text\n"; |
3483 | 503 else if (elt->type == scanf_format_elt::whitespace_conversion) |
3531 | 504 std::cerr << "whitespace\n"; |
3483 | 505 else |
3531 | 506 std::cerr << elt->type << "\n"; |
507 | |
508 std::cerr | |
509 << "modifier: " << elt->modifier << "\n" | |
510 << "char_class: `" << undo_string_escapes (elt->char_class) << "'\n" | |
511 << "text: `" << undo_string_escapes (elt->text) << "'\n\n"; | |
2117 | 512 } |
513 } | |
514 | |
515 bool | |
516 scanf_format_list::all_character_conversions (void) | |
517 { | |
518 int n = list.length (); | |
519 | |
520 if (n > 0) | |
521 { | |
522 for (int i = 0; i < n; i++) | |
523 { | |
3340 | 524 scanf_format_elt *elt = list(i); |
2117 | 525 |
526 switch (elt->type) | |
527 { | |
3483 | 528 case 'c': case 's': case '%': case '[': case '^': |
529 case scanf_format_elt::literal_conversion: | |
530 case scanf_format_elt::whitespace_conversion: | |
2117 | 531 break; |
532 | |
533 default: | |
534 return false; | |
535 break; | |
536 } | |
537 } | |
538 | |
539 return true; | |
540 } | |
541 else | |
542 return false; | |
543 } | |
544 | |
545 bool | |
546 scanf_format_list::all_numeric_conversions (void) | |
547 { | |
548 int n = list.length (); | |
549 | |
550 if (n > 0) | |
551 { | |
552 for (int i = 0; i < n; i++) | |
553 { | |
3340 | 554 scanf_format_elt *elt = list(i); |
2117 | 555 |
556 switch (elt->type) | |
557 { | |
558 case 'd': case 'i': case 'o': case 'u': case 'x': | |
559 case 'e': case 'f': case 'g': | |
560 break; | |
561 | |
562 default: | |
563 return false; | |
564 break; | |
565 } | |
566 } | |
567 | |
568 return true; | |
569 } | |
570 else | |
571 return false; | |
572 } | |
573 | |
574 // Ugh again. | |
575 | |
3523 | 576 printf_format_list::printf_format_list (const std::string& s) |
2117 | 577 : nconv (0), curr_idx (0), list (16), buf (0) |
578 { | |
579 int num_elts = 0; | |
580 | |
581 int n = s.length (); | |
582 | |
583 int i = 0; | |
584 | |
585 int args = 0; | |
3643 | 586 std::string flags; |
3640 | 587 int fw = 0; |
588 int prec = 0; | |
2117 | 589 char modifier = '\0'; |
590 char type = '\0'; | |
591 | |
592 bool have_more = true; | |
3640 | 593 bool empty_buf = true; |
2117 | 594 |
4223 | 595 if (n == 0) |
2117 | 596 { |
4223 | 597 printf_format_elt *elt |
598 = new printf_format_elt ("", args, fw, prec, flags, type, modifier); | |
599 | |
600 list(num_elts++) = elt; | |
601 | |
602 list.resize (num_elts); | |
603 } | |
604 else | |
605 { | |
606 while (i < n) | |
3640 | 607 { |
4223 | 608 have_more = true; |
609 | |
610 if (! buf) | |
611 { | |
5765 | 612 buf = new std::ostringstream (); |
4223 | 613 empty_buf = true; |
614 } | |
615 | |
616 switch (s[i]) | |
617 { | |
618 case '%': | |
3640 | 619 { |
4223 | 620 if (empty_buf) |
621 { | |
622 process_conversion (s, i, n, args, flags, fw, prec, | |
623 type, modifier, num_elts); | |
624 | |
625 have_more = (buf != 0); | |
626 } | |
627 else | |
628 add_elt_to_list (args, flags, fw, prec, type, modifier, | |
629 num_elts); | |
3640 | 630 } |
4223 | 631 break; |
632 | |
633 default: | |
634 { | |
635 args = 0; | |
636 flags = ""; | |
637 fw = 0; | |
638 prec = 0; | |
639 modifier = '\0'; | |
640 type = '\0'; | |
641 *buf << s[i++]; | |
642 empty_buf = false; | |
643 } | |
644 break; | |
645 } | |
646 | |
647 if (nconv < 0) | |
648 { | |
649 have_more = false; | |
650 break; | |
651 } | |
2117 | 652 } |
653 | |
4223 | 654 if (have_more) |
655 add_elt_to_list (args, flags, fw, prec, type, modifier, num_elts); | |
656 | |
657 list.resize (num_elts); | |
658 | |
659 delete buf; | |
2117 | 660 } |
661 } | |
662 | |
663 printf_format_list::~printf_format_list (void) | |
664 { | |
665 int n = list.length (); | |
666 | |
667 for (int i = 0; i < n; i++) | |
668 { | |
3340 | 669 printf_format_elt *elt = list(i); |
2117 | 670 delete elt; |
671 } | |
672 } | |
673 | |
674 void | |
3640 | 675 printf_format_list::add_elt_to_list (int args, const std::string& flags, |
676 int fw, int prec, char type, | |
677 char modifier, int& num_elts) | |
2117 | 678 { |
679 if (buf) | |
680 { | |
5765 | 681 std::string text = buf->str (); |
4051 | 682 |
683 if (! text.empty ()) | |
2117 | 684 { |
4051 | 685 printf_format_elt *elt |
686 = new printf_format_elt (text.c_str (), args, fw, prec, flags, | |
687 type, modifier); | |
688 | |
689 if (num_elts == list.length ()) | |
690 list.resize (2 * num_elts); | |
691 | |
692 list(num_elts++) = elt; | |
2117 | 693 } |
694 | |
695 delete buf; | |
696 buf = 0; | |
697 } | |
698 } | |
699 | |
700 void | |
3640 | 701 printf_format_list::process_conversion |
702 (const std::string& s, int& i, int n, int& args, std::string& flags, | |
703 int& fw, int& prec, char& modifier, char& type, int& num_elts) | |
2117 | 704 { |
705 args = 0; | |
3640 | 706 flags = ""; |
707 fw = 0; | |
708 prec = 0; | |
2117 | 709 modifier = '\0'; |
710 type = '\0'; | |
711 | |
712 *buf << s[i++]; | |
713 | |
4587 | 714 bool nxt = false; |
2117 | 715 |
716 while (i < n) | |
717 { | |
718 switch (s[i]) | |
719 { | |
720 case '-': case '+': case ' ': case '0': case '#': | |
3640 | 721 flags += s[i]; |
2117 | 722 *buf << s[i++]; |
723 break; | |
724 | |
725 default: | |
4587 | 726 nxt = true; |
2117 | 727 break; |
728 } | |
729 | |
4587 | 730 if (nxt) |
2117 | 731 break; |
732 } | |
733 | |
734 if (i < n) | |
735 { | |
736 if (s[i] == '*') | |
737 { | |
3640 | 738 fw = -1; |
2117 | 739 args++; |
740 *buf << s[i++]; | |
741 } | |
742 else | |
743 { | |
3640 | 744 if (isdigit (s[i])) |
745 { | |
4587 | 746 int nn = 0; |
3643 | 747 std::string tmp = s.substr (i); |
4587 | 748 sscanf (tmp.c_str (), "%d%n", &fw, &nn); |
3640 | 749 } |
750 | |
2117 | 751 while (i < n && isdigit (s[i])) |
752 *buf << s[i++]; | |
753 } | |
754 } | |
755 | |
756 if (i < n && s[i] == '.') | |
757 { | |
758 *buf << s[i++]; | |
759 | |
760 if (i < n) | |
761 { | |
762 if (s[i] == '*') | |
763 { | |
3640 | 764 prec = -1; |
2117 | 765 args++; |
766 *buf << s[i++]; | |
767 } | |
768 else | |
769 { | |
3640 | 770 if (isdigit (s[i])) |
771 { | |
4587 | 772 int nn = 0; |
3643 | 773 std::string tmp = s.substr (i); |
4587 | 774 sscanf (tmp.c_str (), "%d%n", &prec, &nn); |
3640 | 775 } |
776 | |
2117 | 777 while (i < n && isdigit (s[i])) |
778 *buf << s[i++]; | |
779 } | |
780 } | |
781 } | |
782 | |
783 if (i < n) | |
784 { | |
785 switch (s[i]) | |
786 { | |
787 case 'h': case 'l': case 'L': | |
788 modifier = s[i]; | |
789 *buf << s[i++]; | |
790 break; | |
791 | |
792 default: | |
793 break; | |
794 } | |
795 } | |
796 | |
797 if (i < n) | |
3640 | 798 finish_conversion (s, i, args, flags, fw, prec, modifier, type, num_elts); |
2117 | 799 else |
800 nconv = -1; | |
801 } | |
802 | |
803 void | |
3640 | 804 printf_format_list::finish_conversion |
805 (const std::string& s, int& i, int args, const std::string& flags, | |
806 int fw, int prec, char modifier, char& type, int& num_elts) | |
2117 | 807 |
808 { | |
809 switch (s[i]) | |
810 { | |
811 case 'd': case 'i': case 'o': case 'x': case 'X': | |
812 case 'u': case 'c': | |
813 if (modifier == 'L') | |
814 { | |
815 nconv = -1; | |
816 break; | |
817 } | |
818 goto fini; | |
819 | |
820 case 'f': case 'e': case 'E': case 'g': case 'G': | |
821 if (modifier == 'h' || modifier == 'l') | |
822 { | |
823 nconv = -1; | |
824 break; | |
825 } | |
826 goto fini; | |
827 | |
828 case 's': case 'p': case '%': | |
829 if (modifier != '\0') | |
830 { | |
831 nconv = -1; | |
832 break; | |
833 } | |
834 goto fini; | |
835 | |
836 fini: | |
837 | |
3640 | 838 type = s[i]; |
839 | |
840 *buf << s[i++]; | |
841 | |
842 if (type != '%' || args != 0) | |
843 nconv++; | |
844 | |
845 if (type != '%') | |
846 args++; | |
847 | |
848 add_elt_to_list (args, flags, fw, prec, type, modifier, num_elts); | |
849 | |
2117 | 850 break; |
851 | |
852 default: | |
853 nconv = -1; | |
854 break; | |
855 } | |
856 } | |
857 | |
858 void | |
859 printf_format_list::printme (void) const | |
860 { | |
861 int n = list.length (); | |
862 | |
863 for (int i = 0; i < n; i++) | |
864 { | |
3340 | 865 printf_format_elt *elt = list(i); |
2117 | 866 |
3640 | 867 std::cerr |
868 << "args: " << elt->args << "\n" | |
869 << "flags: `" << elt->flags << "'\n" | |
870 << "width: " << elt->fw << "\n" | |
871 << "prec: " << elt->prec << "\n" | |
872 << "type: `" << elt->type << "'\n" | |
873 << "modifier: `" << elt->modifier << "'\n" | |
874 << "text: `" << undo_string_escapes (elt->text) << "'\n\n"; | |
2117 | 875 } |
876 } | |
877 | |
3145 | 878 int |
3148 | 879 octave_base_stream::file_number (void) |
3145 | 880 { |
881 // Kluge alert! | |
882 | |
883 if (name () == "stdin") | |
884 return 0; | |
885 | |
886 if (name () == "stdout") | |
887 return 1; | |
888 | |
889 if (name () == "stderr") | |
890 return 2; | |
891 | |
892 int retval = -1; | |
893 | |
3523 | 894 std::istream *is = input_stream (); |
895 std::ostream *os = output_stream (); | |
3145 | 896 |
3775 | 897 // There is no standard way to get the underlying file descriptor from |
898 // std::filebuf (nor in the GNU libstdc++-v3 implementation). We cache | |
899 // the descriptor in c_file_ptr_buf, and then extract it here. | |
900 | |
6757 | 901 c_file_ptr_buf *ibuf |
902 = is ? dynamic_cast<c_file_ptr_buf *> (is->rdbuf ()) : 0; | |
903 | |
904 c_file_ptr_buf *obuf | |
905 = os ? dynamic_cast<c_file_ptr_buf *> (os->rdbuf ()) : 0; | |
3775 | 906 |
907 int i_fid = ibuf ? ibuf->file_number () : -1; | |
908 int o_fid = obuf ? obuf->file_number () : -1; | |
3145 | 909 |
910 if (i_fid >= 0) | |
911 { | |
912 if (o_fid >= 0) | |
913 retval = (i_fid == o_fid) ? i_fid : -1; | |
914 else | |
915 retval = i_fid; | |
916 } | |
917 else if (o_fid >= 0) | |
918 retval = o_fid; | |
919 | |
920 return retval; | |
921 } | |
922 | |
2117 | 923 void |
3523 | 924 octave_base_stream::error (const std::string& msg) |
2117 | 925 { |
926 fail = true; | |
927 errmsg = msg; | |
928 } | |
929 | |
930 void | |
4468 | 931 octave_base_stream::error (const std::string& who, const std::string& msg) |
932 { | |
933 fail = true; | |
6296 | 934 errmsg = who + ": " + msg; |
4468 | 935 } |
936 | |
937 void | |
2117 | 938 octave_base_stream::clear (void) |
939 { | |
4889 | 940 fail = false; |
941 errmsg = ""; | |
942 } | |
943 | |
944 void | |
945 octave_base_stream::clearerr (void) | |
946 { | |
4888 | 947 std::istream *is = input_stream (); |
948 std::ostream *os = output_stream (); | |
949 | |
950 if (is) | |
951 is->clear (); | |
952 | |
953 if (os) | |
954 os->clear (); | |
2117 | 955 } |
956 | |
957 // Functions that are defined for all input streams (input streams | |
958 // are those that define is). | |
959 | |
3536 | 960 std::string |
5275 | 961 octave_base_stream::do_gets (octave_idx_type max_len, bool& err, |
4468 | 962 bool strip_newline, const std::string& who) |
2117 | 963 { |
3523 | 964 std::string retval; |
2117 | 965 |
966 err = false; | |
967 | |
3523 | 968 std::istream *isp = input_stream (); |
2117 | 969 |
970 if (isp) | |
971 { | |
3523 | 972 std::istream& is = *isp; |
2117 | 973 |
5765 | 974 std::ostringstream buf; |
2117 | 975 |
976 int c = 0; | |
3553 | 977 int char_count = 0; |
6345 | 978 |
979 if (max_len != 0) | |
2117 | 980 { |
6345 | 981 while (is && (c = is.get ()) != EOF) |
2117 | 982 { |
6345 | 983 char_count++; |
984 | |
985 if (c == '\n') | |
986 { | |
987 if (! strip_newline) | |
988 buf << static_cast<char> (c); | |
989 | |
990 break; | |
991 } | |
992 else | |
5760 | 993 buf << static_cast<char> (c); |
6345 | 994 |
995 if (max_len > 0 && char_count == max_len) | |
996 break; | |
2117 | 997 } |
6345 | 998 } |
999 | |
1000 if (! is.eof () && char_count > 0) | |
1001 { | |
1002 // GAGME. Matlab seems to check for EOF even if the last | |
1003 // character in a file is a newline character. This is NOT | |
1004 // what the corresponding C-library functions do. | |
1005 int disgusting_compatibility_hack = is.get (); | |
1006 if (! is.eof ()) | |
1007 is.putback (disgusting_compatibility_hack); | |
2117 | 1008 } |
1009 | |
4224 | 1010 if (is.good () || (is.eof () && char_count > 0)) |
5765 | 1011 retval = buf.str (); |
4224 | 1012 else |
1013 { | |
1014 err = true; | |
4468 | 1015 |
4224 | 1016 if (is.eof () && char_count == 0) |
4468 | 1017 error (who, "at end of file"); |
4224 | 1018 else |
4468 | 1019 error (who, "read error"); |
4224 | 1020 } |
2117 | 1021 } |
1022 else | |
1023 { | |
1024 err = true; | |
4468 | 1025 invalid_operation (who, "reading"); |
2117 | 1026 } |
1027 | |
1028 return retval; | |
1029 } | |
1030 | |
3536 | 1031 std::string |
5275 | 1032 octave_base_stream::getl (octave_idx_type max_len, bool& err, const std::string& who) |
2117 | 1033 { |
4468 | 1034 return do_gets (max_len, err, true, who); |
2117 | 1035 } |
1036 | |
3536 | 1037 std::string |
5275 | 1038 octave_base_stream::gets (octave_idx_type max_len, bool& err, const std::string& who) |
2117 | 1039 { |
4468 | 1040 return do_gets (max_len, err, false, who); |
2117 | 1041 } |
1042 | |
3640 | 1043 #define OCTAVE_SCAN(is, fmt, arg) octave_scan (is, fmt, arg) |
3636 | 1044 |
1045 template <class T> | |
1046 std::istream& | |
6767 | 1047 octave_scan_1 (std::istream& is, const scanf_format_elt& fmt, T* valptr) |
3636 | 1048 { |
3779 | 1049 T& ref = *valptr; |
1050 | |
1051 switch (fmt.type) | |
1052 { | |
1053 case 'o': | |
4926 | 1054 is >> std::oct >> ref >> std::dec; |
3779 | 1055 break; |
1056 | |
1057 case 'x': | |
4926 | 1058 is >> std::hex >> ref >> std::dec; |
1059 break; | |
1060 | |
1061 case 'i': | |
1062 { | |
1063 int c1 = is.get (); | |
1064 | |
1065 if (! is.eof ()) | |
1066 { | |
1067 if (c1 == '0') | |
1068 { | |
4927 | 1069 int c2 = is.get (); |
4926 | 1070 |
1071 if (c2 == 'x' || c2 == 'X') | |
1072 is >> std::hex >> ref >> std::dec; | |
1073 else | |
4927 | 1074 { |
1075 is.putback (c2); | |
1076 | |
1077 if (c2 == '0' || c2 == '1' || c2 == '2' | |
1078 || c2 == '3' || c2 == '4' || c2 == '5' | |
1079 || c2 == '6' || c2 == '7') | |
1080 is >> std::oct >> ref >> std::dec; | |
1081 else | |
1082 ref = 0; | |
1083 } | |
4926 | 1084 } |
1085 else | |
1086 { | |
1087 is.putback (c1); | |
1088 | |
1089 is >> ref; | |
1090 } | |
1091 } | |
1092 } | |
3779 | 1093 break; |
1094 | |
1095 default: | |
1096 is >> ref; | |
1097 break; | |
1098 } | |
3639 | 1099 |
3638 | 1100 return is; |
3636 | 1101 } |
1102 | |
6767 | 1103 template <class T> |
1104 std::istream& | |
1105 octave_scan (std::istream& is, const scanf_format_elt& fmt, T* valptr) | |
1106 { | |
1107 if (fmt.width) | |
1108 { | |
1109 // Limit input to fmt.width characters by reading into a | |
1110 // temporary stringstream buffer. | |
1111 | |
1112 std::string tmp; | |
1113 | |
1114 is.width (fmt.width); | |
1115 is >> tmp; | |
1116 | |
1117 std::istringstream ss (tmp); | |
1118 | |
1119 octave_scan_1 (ss, fmt, valptr); | |
1120 } | |
1121 else | |
1122 octave_scan_1 (is, fmt, valptr); | |
1123 | |
1124 return is; | |
1125 } | |
1126 | |
3779 | 1127 // Note that this specialization is only used for reading characters, not |
1128 // character strings. See BEGIN_S_CONVERSION for details. | |
1129 | |
1130 template<> | |
1131 std::istream& | |
4661 | 1132 octave_scan<> (std::istream& is, const scanf_format_elt& /* fmt */, |
1133 char* valptr) | |
3779 | 1134 { |
1135 return is >> valptr; | |
1136 } | |
3636 | 1137 |
4595 | 1138 template std::istream& |
1139 octave_scan (std::istream&, const scanf_format_elt&, int*); | |
1140 | |
1141 template std::istream& | |
1142 octave_scan (std::istream&, const scanf_format_elt&, long int*); | |
1143 | |
1144 template std::istream& | |
1145 octave_scan (std::istream&, const scanf_format_elt&, short int*); | |
1146 | |
1147 template std::istream& | |
1148 octave_scan (std::istream&, const scanf_format_elt&, unsigned int*); | |
1149 | |
1150 template std::istream& | |
1151 octave_scan (std::istream&, const scanf_format_elt&, unsigned long int*); | |
1152 | |
1153 template std::istream& | |
1154 octave_scan (std::istream&, const scanf_format_elt&, unsigned short int*); | |
1155 | |
1156 #if 0 | |
1157 template std::istream& | |
1158 octave_scan (std::istream&, const scanf_format_elt&, float*); | |
1159 #endif | |
1160 | |
5403 | 1161 template<> |
5176 | 1162 std::istream& |
5403 | 1163 octave_scan<> (std::istream& is, const scanf_format_elt& fmt, double* valptr) |
5176 | 1164 { |
1165 double& ref = *valptr; | |
1166 | |
1167 switch (fmt.type) | |
1168 { | |
1169 case 'e': | |
1170 case 'f': | |
1171 case 'g': | |
1172 { | |
5259 | 1173 int c1 = EOF; |
5176 | 1174 |
1175 while (is && (c1 = is.get ()) != EOF && isspace (c1)) | |
1176 /* skip whitespace */; | |
1177 | |
1178 if (c1 != EOF) | |
1179 { | |
1180 if (c1 == 'N') | |
1181 { | |
1182 int c2 = is.get (); | |
1183 | |
1184 if (c2 != EOF) | |
1185 { | |
1186 if (c2 == 'A') | |
1187 { | |
1188 int c3 = is.get (); | |
1189 | |
1190 if (c3 != EOF) | |
1191 { | |
1192 is.putback (c3); | |
1193 | |
1194 if (isspace (c3) || ispunct (c3)) | |
1195 ref = octave_NA; | |
1196 else | |
1197 { | |
1198 is.putback (c2); | |
1199 is.putback (c1); | |
1200 | |
1201 is >> ref; | |
1202 } | |
1203 } | |
1204 else | |
1205 { | |
1206 is.clear (); | |
1207 | |
1208 ref = octave_NA; | |
1209 } | |
1210 } | |
1211 else if (c2 == 'a') | |
1212 { | |
1213 int c3 = is.get (); | |
1214 | |
1215 if (c3 != EOF) | |
1216 { | |
1217 if (c3 == 'N') | |
1218 { | |
1219 int c4 = is.get (); | |
1220 | |
1221 if (c4 != EOF) | |
1222 { | |
1223 is.putback (c4); | |
1224 | |
1225 if (isspace (c4) || ispunct (c4)) | |
1226 ref = octave_NaN; | |
1227 else | |
1228 { | |
1229 is.putback (c3); | |
1230 is.putback (c2); | |
1231 is.putback (c1); | |
1232 | |
1233 is >> ref; | |
1234 } | |
1235 } | |
1236 else | |
1237 { | |
1238 is.clear (); | |
1239 | |
1240 ref = octave_NaN; | |
1241 } | |
1242 } | |
1243 else | |
1244 { | |
1245 is.putback (c3); | |
1246 is.putback (c2); | |
1247 is.putback (c1); | |
1248 | |
1249 is >> ref; | |
1250 } | |
1251 } | |
1252 } | |
1253 else | |
1254 { | |
1255 is.putback (c2); | |
1256 is.putback (c1); | |
1257 | |
1258 is >> ref; | |
1259 } | |
1260 } | |
1261 } | |
1262 else if (c1 == 'I') | |
1263 { | |
1264 int c2 = is.get (); | |
1265 | |
1266 if (c2 != EOF) | |
1267 { | |
1268 if (c2 == 'n') | |
1269 { | |
1270 int c3 = is.get (); | |
1271 | |
1272 if (c3 != EOF) | |
6483 | 1273 { |
1274 if (c3 == 'f') | |
1275 { | |
1276 int c4 = is.get (); | |
1277 | |
1278 if (c4 != EOF) | |
1279 { | |
1280 is.putback (c4); | |
1281 | |
1282 if (isspace (c4) || ispunct (c4)) | |
1283 ref = octave_Inf; | |
1284 else | |
1285 { | |
1286 is.putback (c3); | |
1287 is.putback (c2); | |
1288 is.putback (c1); | |
1289 | |
1290 is >> ref; | |
1291 } | |
1292 } | |
1293 else | |
1294 { | |
1295 is.clear (); | |
1296 | |
5176 | 1297 ref = octave_Inf; |
6483 | 1298 } |
1299 } | |
1300 else | |
1301 { | |
1302 is.putback (c3); | |
1303 is.putback (c2); | |
1304 is.putback (c1); | |
1305 | |
1306 is >> ref; | |
1307 } | |
1308 } | |
1309 else | |
1310 { | |
1311 is.putback (c2); | |
1312 is.putback (c1); | |
1313 | |
1314 is >> ref; | |
1315 } | |
5176 | 1316 } |
1317 } | |
1318 } | |
1319 else | |
1320 { | |
1321 is.putback (c1); | |
1322 | |
1323 is >> ref; | |
1324 } | |
1325 } | |
1326 } | |
1327 break; | |
1328 | |
1329 default: | |
1330 panic_impossible (); | |
1331 break; | |
1332 } | |
1333 | |
1334 return is; | |
1335 } | |
1336 | |
2572 | 1337 template <class T> |
1338 void | |
3636 | 1339 do_scanf_conv (std::istream& is, const scanf_format_elt& fmt, |
5275 | 1340 T valptr, Matrix& mval, double *data, octave_idx_type& idx, |
1341 octave_idx_type& conversion_count, octave_idx_type nr, octave_idx_type max_size, | |
3636 | 1342 bool discard) |
2572 | 1343 { |
3640 | 1344 OCTAVE_SCAN (is, fmt, valptr); |
2572 | 1345 |
1346 if (is) | |
1347 { | |
1348 if (idx == max_size && ! discard) | |
1349 { | |
1350 max_size *= 2; | |
1351 | |
1352 if (nr > 0) | |
1353 mval.resize (nr, max_size / nr, 0.0); | |
1354 else | |
1355 mval.resize (max_size, 1, 0.0); | |
1356 | |
1357 data = mval.fortran_vec (); | |
1358 } | |
1359 | |
1360 if (! discard) | |
3268 | 1361 { |
3559 | 1362 conversion_count++; |
3268 | 1363 data[idx++] = *(valptr); |
1364 } | |
2572 | 1365 } |
1366 } | |
1367 | |
1368 template void | |
3878 | 1369 do_scanf_conv (std::istream&, const scanf_format_elt&, int*, |
5275 | 1370 Matrix&, double*, octave_idx_type&, octave_idx_type&, octave_idx_type, octave_idx_type, bool); |
2572 | 1371 |
3233 | 1372 template void |
3636 | 1373 do_scanf_conv (std::istream&, const scanf_format_elt&, long int*, |
5275 | 1374 Matrix&, double*, octave_idx_type&, octave_idx_type&, octave_idx_type, octave_idx_type, bool); |
3233 | 1375 |
1376 template void | |
3636 | 1377 do_scanf_conv (std::istream&, const scanf_format_elt&, short int*, |
5275 | 1378 Matrix&, double*, octave_idx_type&, octave_idx_type&, octave_idx_type, octave_idx_type, bool); |
3233 | 1379 |
3878 | 1380 template void |
1381 do_scanf_conv (std::istream&, const scanf_format_elt&, unsigned int*, | |
5275 | 1382 Matrix&, double*, octave_idx_type&, octave_idx_type&, octave_idx_type, octave_idx_type, bool); |
3878 | 1383 |
1384 template void | |
1385 do_scanf_conv (std::istream&, const scanf_format_elt&, unsigned long int*, | |
5275 | 1386 Matrix&, double*, octave_idx_type&, octave_idx_type&, octave_idx_type, octave_idx_type, bool); |
3878 | 1387 |
1388 template void | |
1389 do_scanf_conv (std::istream&, const scanf_format_elt&, unsigned short int*, | |
5275 | 1390 Matrix&, double*, octave_idx_type&, octave_idx_type&, octave_idx_type, octave_idx_type, bool); |
3878 | 1391 |
2600 | 1392 #if 0 |
2572 | 1393 template void |
3636 | 1394 do_scanf_conv (std::istream&, const scanf_format_elt&, float*, |
5275 | 1395 Matrix&, double*, octave_idx_type&, octave_idx_type&, octave_idx_type, octave_idx_type, bool); |
2600 | 1396 #endif |
2572 | 1397 |
1398 template void | |
3636 | 1399 do_scanf_conv (std::istream&, const scanf_format_elt&, double*, |
5275 | 1400 Matrix&, double*, octave_idx_type&, octave_idx_type&, octave_idx_type, octave_idx_type, bool); |
2572 | 1401 |
3483 | 1402 #define DO_WHITESPACE_CONVERSION() \ |
1403 do \ | |
1404 { \ | |
1405 int c = EOF; \ | |
1406 \ | |
1407 while (is && (c = is.get ()) != EOF && isspace (c)) \ | |
1408 /* skip whitespace */; \ | |
1409 \ | |
1410 if (c != EOF) \ | |
1411 is.putback (c); \ | |
1412 } \ | |
1413 while (0) | |
1414 | |
1415 #define DO_LITERAL_CONVERSION() \ | |
1416 do \ | |
1417 { \ | |
1418 int c = EOF; \ | |
1419 \ | |
1420 int n = strlen (fmt); \ | |
1421 int i = 0; \ | |
1422 \ | |
1423 while (i < n && is && (c = is.get ()) != EOF) \ | |
1424 { \ | |
5326 | 1425 if (c == static_cast<unsigned char> (fmt[i])) \ |
3483 | 1426 { \ |
1427 i++; \ | |
1428 continue; \ | |
1429 } \ | |
1430 else \ | |
1431 { \ | |
1432 is.putback (c); \ | |
1433 break; \ | |
1434 } \ | |
1435 } \ | |
1436 \ | |
1437 if (i != n) \ | |
3538 | 1438 is.setstate (std::ios::failbit); \ |
3483 | 1439 } \ |
1440 while (0) | |
1441 | |
3640 | 1442 #define DO_PCT_CONVERSION() \ |
1443 do \ | |
1444 { \ | |
1445 int c = is.get (); \ | |
1446 \ | |
1447 if (c != EOF) \ | |
1448 { \ | |
1449 if (c != '%') \ | |
1450 { \ | |
1451 is.putback (c); \ | |
1452 is.setstate (std::ios::failbit); \ | |
1453 } \ | |
1454 } \ | |
1455 else \ | |
1456 is.setstate (std::ios::failbit); \ | |
1457 } \ | |
1458 while (0) | |
1459 | |
3483 | 1460 #define BEGIN_C_CONVERSION() \ |
3538 | 1461 is.unsetf (std::ios::skipws); \ |
3483 | 1462 \ |
1463 int width = elt->width ? elt->width : 1; \ | |
1464 \ | |
4051 | 1465 char *tbuf = new char[width + 1]; \ |
3483 | 1466 \ |
1467 int c = EOF; \ | |
1468 int n = 0; \ | |
1469 \ | |
1470 while (is && n < width && (c = is.get ()) != EOF) \ | |
5760 | 1471 tbuf[n++] = static_cast<char> (c); \ |
4051 | 1472 \ |
1473 tbuf[n] = '\0'; \ | |
3483 | 1474 \ |
5266 | 1475 if (n > 0 && c == EOF) \ |
1476 is.clear (); \ | |
1477 \ | |
4051 | 1478 std::string tmp = tbuf; \ |
1479 \ | |
1480 delete [] tbuf | |
3483 | 1481 |
1482 // For a `%s' format, skip initial whitespace and then read until the | |
5338 | 1483 // next whitespace character or until WIDTH characters have been read. |
3483 | 1484 #define BEGIN_S_CONVERSION() \ |
1485 int width = elt->width; \ | |
1486 \ | |
4051 | 1487 std::string tmp; \ |
3483 | 1488 \ |
1489 do \ | |
1490 { \ | |
1491 if (width) \ | |
5338 | 1492 { \ |
1493 char *tbuf = new char [width+1]; \ | |
1494 \ | |
1495 int c = EOF; \ | |
1496 \ | |
1497 int n = 0; \ | |
1498 \ | |
1499 while (is && (c = is.get ()) != EOF) \ | |
1500 { \ | |
1501 if (! isspace (c)) \ | |
1502 { \ | |
1503 tbuf[n++] = static_cast<char> (c); \ | |
1504 break; \ | |
1505 } \ | |
1506 } \ | |
4051 | 1507 \ |
5338 | 1508 while (is && n < width && (c = is.get ()) != EOF) \ |
1509 { \ | |
1510 if (isspace (c)) \ | |
1511 { \ | |
1512 is.putback (c); \ | |
1513 break; \ | |
1514 } \ | |
1515 else \ | |
1516 tbuf[n++] = static_cast<char> (c); \ | |
1517 } \ | |
3483 | 1518 \ |
5338 | 1519 tbuf[n] = '\0'; \ |
1520 \ | |
1521 if (n > 0 && c == EOF) \ | |
1522 is.clear (); \ | |
1523 \ | |
4051 | 1524 tmp = tbuf; \ |
5338 | 1525 \ |
4051 | 1526 delete [] tbuf; \ |
5338 | 1527 } \ |
3483 | 1528 else \ |
5338 | 1529 { \ |
1530 is >> std::ws >> tmp; \ | |
1531 } \ | |
3483 | 1532 } \ |
1533 while (0) | |
1534 | |
1535 // This format must match a nonempty sequence of characters. | |
1536 #define BEGIN_CHAR_CLASS_CONVERSION() \ | |
1537 int width = elt->width; \ | |
1538 \ | |
4051 | 1539 std::string tmp; \ |
3483 | 1540 \ |
1541 do \ | |
1542 { \ | |
7426 | 1543 if (! width) \ |
7427 | 1544 width = INT_MAX; \ |
1545 \ | |
7426 | 1546 std::ostringstream buf; \ |
1547 \ | |
1548 std::string char_class = elt->char_class; \ | |
4051 | 1549 \ |
7426 | 1550 int c = EOF; \ |
3483 | 1551 \ |
7426 | 1552 if (elt->type == '[') \ |
1553 { \ | |
1554 int chars_read = 0; \ | |
1555 while (is && chars_read++ < width && (c = is.get ()) != EOF \ | |
1556 && char_class.find (c) != NPOS) \ | |
1557 buf << static_cast<char> (c); \ | |
3483 | 1558 } \ |
1559 else \ | |
1560 { \ | |
7426 | 1561 int chars_read = 0; \ |
1562 while (is && chars_read++ < width && (c = is.get ()) != EOF \ | |
1563 && char_class.find (c) == NPOS) \ | |
1564 buf << static_cast<char> (c); \ | |
1565 } \ | |
3483 | 1566 \ |
7426 | 1567 if (width == INT_MAX && c != EOF) \ |
1568 is.putback (c); \ | |
3483 | 1569 \ |
7426 | 1570 tmp = buf.str (); \ |
3483 | 1571 \ |
7426 | 1572 if (tmp.empty ()) \ |
1573 is.setstate (std::ios::failbit); \ | |
3483 | 1574 } \ |
1575 while (0) | |
1576 | |
3410 | 1577 #define FINISH_CHARACTER_CONVERSION() \ |
1578 do \ | |
1579 { \ | |
4051 | 1580 width = tmp.length (); \ |
3410 | 1581 \ |
1582 if (is) \ | |
1583 { \ | |
1584 int i = 0; \ | |
1585 \ | |
1586 if (! discard) \ | |
1587 { \ | |
1588 conversion_count++; \ | |
1589 \ | |
1590 while (i < width && tmp[i] != '\0') \ | |
1591 { \ | |
1592 if (data_index == max_size) \ | |
1593 { \ | |
1594 max_size *= 2; \ | |
1595 \ | |
4420 | 1596 if (all_char_conv) \ |
3410 | 1597 { \ |
4420 | 1598 if (one_elt_size_spec) \ |
3410 | 1599 mval.resize (1, max_size, 0.0); \ |
4420 | 1600 else if (nr > 0) \ |
1601 mval.resize (nr, max_size / nr, 0.0); \ | |
3410 | 1602 else \ |
4420 | 1603 panic_impossible (); \ |
3410 | 1604 } \ |
4420 | 1605 else if (nr > 0) \ |
6970 | 1606 mval.resize (nr, max_size / nr, 0.0); \ |
4420 | 1607 else \ |
1608 mval.resize (max_size, 1, 0.0); \ | |
3410 | 1609 \ |
1610 data = mval.fortran_vec (); \ | |
1611 } \ | |
1612 \ | |
1613 data[data_index++] = tmp[i++]; \ | |
1614 } \ | |
1615 } \ | |
1616 } \ | |
1617 } \ | |
1618 while (0) | |
2117 | 1619 |
1620 octave_value | |
1621 octave_base_stream::do_scanf (scanf_format_list& fmt_list, | |
5275 | 1622 octave_idx_type nr, octave_idx_type nc, bool one_elt_size_spec, |
1623 octave_idx_type& conversion_count, const std::string& who) | |
2117 | 1624 { |
3268 | 1625 conversion_count = 0; |
1626 | |
3640 | 1627 int nconv = fmt_list.num_conversions (); |
1628 | |
5275 | 1629 octave_idx_type data_index = 0; |
2121 | 1630 |
2117 | 1631 octave_value retval = Matrix (); |
1632 | |
3268 | 1633 if (nr == 0 || nc == 0) |
1634 { | |
1635 if (one_elt_size_spec) | |
1636 nc = 0; | |
1637 | |
1638 return Matrix (nr, nc, 0.0); | |
1639 } | |
1640 | |
3523 | 1641 std::istream *isp = input_stream (); |
2117 | 1642 |
1643 bool all_char_conv = fmt_list.all_character_conversions (); | |
1644 | |
1645 Matrix mval; | |
1646 double *data = 0; | |
5275 | 1647 octave_idx_type max_size = 0; |
1648 octave_idx_type max_conv = 0; | |
1649 | |
1650 octave_idx_type final_nr = 0; | |
1651 octave_idx_type final_nc = 0; | |
2117 | 1652 |
3268 | 1653 if (all_char_conv) |
1654 { | |
4420 | 1655 // Any of these could be resized later (if we have %s |
1656 // conversions, we may read more than one element for each | |
1657 // conversion). | |
1658 | |
3268 | 1659 if (one_elt_size_spec) |
1660 { | |
3410 | 1661 max_size = 512; |
1662 mval.resize (1, max_size, 0.0); | |
1663 | |
3268 | 1664 if (nr > 0) |
1665 max_conv = nr; | |
1666 } | |
4420 | 1667 else if (nr > 0) |
3268 | 1668 { |
4420 | 1669 if (nc > 0) |
1670 { | |
1671 mval.resize (nr, nc, 0.0); | |
1672 max_size = max_conv = nr * nc; | |
1673 } | |
1674 else | |
1675 { | |
1676 mval.resize (nr, 32, 0.0); | |
1677 max_size = nr * 32; | |
1678 } | |
3268 | 1679 } |
4420 | 1680 else |
1681 panic_impossible (); | |
3268 | 1682 } |
1683 else if (nr > 0) | |
2117 | 1684 { |
1685 if (nc > 0) | |
1686 { | |
4420 | 1687 // Will not resize later. |
2117 | 1688 mval.resize (nr, nc, 0.0); |
1689 max_size = nr * nc; | |
3268 | 1690 max_conv = max_size; |
2117 | 1691 } |
1692 else | |
1693 { | |
4420 | 1694 // Maybe resize later. |
2117 | 1695 mval.resize (nr, 32, 0.0); |
2121 | 1696 max_size = nr * 32; |
2117 | 1697 } |
1698 } | |
1699 else | |
1700 { | |
4420 | 1701 // Maybe resize later. |
2117 | 1702 mval.resize (32, 1, 0.0); |
1703 max_size = 32; | |
1704 } | |
1705 | |
4420 | 1706 data = mval.fortran_vec (); |
1707 | |
2117 | 1708 if (isp) |
1709 { | |
3523 | 1710 std::istream& is = *isp; |
2117 | 1711 |
1712 const scanf_format_elt *elt = fmt_list.first (); | |
1713 | |
3538 | 1714 std::ios::fmtflags flags = is.flags (); |
2213 | 1715 |
2117 | 1716 for (;;) |
1717 { | |
4153 | 1718 OCTAVE_QUIT; |
1719 | |
2117 | 1720 if (elt) |
1721 { | |
3268 | 1722 if (max_conv > 0 && conversion_count == max_conv) |
1723 { | |
1724 if (all_char_conv && one_elt_size_spec) | |
1725 { | |
1726 final_nr = 1; | |
1727 final_nc = data_index; | |
1728 } | |
1729 else | |
1730 { | |
1731 final_nr = nr; | |
1732 final_nc = (data_index - 1) / nr + 1; | |
1733 } | |
1734 | |
1735 break; | |
1736 } | |
1737 else if (data_index == max_size) | |
2117 | 1738 { |
3410 | 1739 max_size *= 2; |
1740 | |
4420 | 1741 if (all_char_conv) |
2687 | 1742 { |
4420 | 1743 if (one_elt_size_spec) |
3410 | 1744 mval.resize (1, max_size, 0.0); |
4420 | 1745 else if (nr > 0) |
1746 mval.resize (nr, max_size / nr, 0.0); | |
3410 | 1747 else |
4420 | 1748 panic_impossible (); |
2687 | 1749 } |
4420 | 1750 else if (nr > 0) |
6970 | 1751 mval.resize (nr, max_size / nr, 0.0); |
4420 | 1752 else |
1753 mval.resize (max_size, 1, 0.0); | |
3410 | 1754 |
1755 data = mval.fortran_vec (); | |
2117 | 1756 } |
1757 | |
1758 const char *fmt = elt->text; | |
1759 | |
1760 bool discard = elt->discard; | |
1761 | |
1762 switch (elt->type) | |
1763 { | |
3483 | 1764 case scanf_format_elt::whitespace_conversion: |
1765 DO_WHITESPACE_CONVERSION (); | |
1766 break; | |
1767 | |
1768 case scanf_format_elt::literal_conversion: | |
1769 DO_LITERAL_CONVERSION (); | |
1770 break; | |
1771 | |
2117 | 1772 case '%': |
3640 | 1773 DO_PCT_CONVERSION (); |
3483 | 1774 break; |
2117 | 1775 |
3878 | 1776 case 'd': case 'i': |
2117 | 1777 { |
3233 | 1778 switch (elt->modifier) |
1779 { | |
1780 case 'h': | |
1781 { | |
1782 short int tmp; | |
3779 | 1783 do_scanf_conv (is, *elt, &tmp, mval, data, |
3268 | 1784 data_index, conversion_count, |
3233 | 1785 nr, max_size, discard); |
1786 } | |
3483 | 1787 break; |
3233 | 1788 |
1789 case 'l': | |
1790 { | |
1791 long int tmp; | |
3779 | 1792 do_scanf_conv (is, *elt, &tmp, mval, data, |
3268 | 1793 data_index, conversion_count, |
3233 | 1794 nr, max_size, discard); |
1795 } | |
3483 | 1796 break; |
3233 | 1797 |
1798 default: | |
1799 { | |
1800 int tmp; | |
3779 | 1801 do_scanf_conv (is, *elt, &tmp, mval, data, |
3268 | 1802 data_index, conversion_count, |
3233 | 1803 nr, max_size, discard); |
1804 } | |
3483 | 1805 break; |
3233 | 1806 } |
2117 | 1807 } |
3483 | 1808 break; |
2117 | 1809 |
3878 | 1810 case 'o': case 'u': case 'x': |
1811 { | |
1812 switch (elt->modifier) | |
1813 { | |
1814 case 'h': | |
1815 { | |
1816 unsigned short int tmp; | |
1817 do_scanf_conv (is, *elt, &tmp, mval, data, | |
1818 data_index, conversion_count, | |
1819 nr, max_size, discard); | |
1820 } | |
1821 break; | |
1822 | |
1823 case 'l': | |
1824 { | |
1825 unsigned long int tmp; | |
1826 do_scanf_conv (is, *elt, &tmp, mval, data, | |
1827 data_index, conversion_count, | |
1828 nr, max_size, discard); | |
1829 } | |
1830 break; | |
1831 | |
1832 default: | |
1833 { | |
1834 unsigned int tmp; | |
1835 do_scanf_conv (is, *elt, &tmp, mval, data, | |
1836 data_index, conversion_count, | |
1837 nr, max_size, discard); | |
1838 } | |
1839 break; | |
1840 } | |
1841 } | |
1842 break; | |
1843 | |
2117 | 1844 case 'e': case 'f': case 'g': |
1845 { | |
2600 | 1846 double tmp; |
1847 | |
3779 | 1848 do_scanf_conv (is, *elt, &tmp, mval, data, |
3268 | 1849 data_index, conversion_count, |
2600 | 1850 nr, max_size, discard); |
2117 | 1851 } |
3483 | 1852 break; |
2117 | 1853 |
2213 | 1854 case 'c': |
3410 | 1855 { |
3483 | 1856 BEGIN_C_CONVERSION (); |
3410 | 1857 |
1858 FINISH_CHARACTER_CONVERSION (); | |
3483 | 1859 |
1860 is.setf (flags); | |
3410 | 1861 } |
1862 break; | |
2213 | 1863 |
2117 | 1864 case 's': |
1865 { | |
3483 | 1866 BEGIN_S_CONVERSION (); |
3268 | 1867 |
3410 | 1868 FINISH_CHARACTER_CONVERSION (); |
2117 | 1869 } |
3483 | 1870 break; |
1871 | |
1872 case '[': case '^': | |
1873 { | |
1874 BEGIN_CHAR_CLASS_CONVERSION (); | |
1875 | |
1876 FINISH_CHARACTER_CONVERSION (); | |
1877 } | |
1878 break; | |
1879 | |
1880 case 'p': | |
4468 | 1881 error ("%s: unsupported format specifier", who.c_str ()); |
2117 | 1882 break; |
1883 | |
1884 default: | |
4468 | 1885 error ("%s: internal format error", who.c_str ()); |
2117 | 1886 break; |
1887 } | |
1888 | |
1889 if (! ok ()) | |
1890 { | |
1891 break; | |
1892 } | |
1893 else if (! is) | |
1894 { | |
3268 | 1895 if (all_char_conv) |
2117 | 1896 { |
3268 | 1897 if (one_elt_size_spec) |
1898 { | |
1899 final_nr = 1; | |
1900 final_nc = data_index; | |
1901 } | |
1902 else if (data_index > nr) | |
2117 | 1903 { |
2759 | 1904 final_nr = nr; |
3268 | 1905 final_nc = (data_index - 1) / nr + 1; |
2117 | 1906 } |
1907 else | |
1908 { | |
3268 | 1909 final_nr = data_index; |
1910 final_nc = 1; | |
1911 } | |
1912 } | |
1913 else if (nr > 0) | |
1914 { | |
1915 if (data_index > nr) | |
1916 { | |
1917 final_nr = nr; | |
1918 final_nc = (data_index - 1) / nr + 1; | |
1919 } | |
1920 else | |
1921 { | |
1922 final_nr = data_index; | |
2117 | 1923 final_nc = 1; |
1924 } | |
1925 } | |
1926 else | |
1927 { | |
3268 | 1928 final_nr = data_index; |
2759 | 1929 final_nc = 1; |
1930 } | |
1931 | |
3337 | 1932 // If it looks like we have a matching failure, then |
1933 // reset the failbit in the stream state. | |
1934 | |
3538 | 1935 if (is.rdstate () & std::ios::failbit) |
1936 is.clear (is.rdstate () & (~std::ios::failbit)); | |
3337 | 1937 |
5775 | 1938 // FIXME -- is this the right thing to do? |
3342 | 1939 |
1940 if (interactive && name () == "stdin") | |
2759 | 1941 { |
1942 is.clear (); | |
1943 | |
1944 // Skip to end of line. | |
1945 | |
1946 bool err; | |
4468 | 1947 do_gets (-1, err, false, who); |
2117 | 1948 } |
1949 | |
1950 break; | |
1951 } | |
1952 } | |
1953 else | |
1954 { | |
4468 | 1955 error ("%s: internal format error", who.c_str ()); |
2117 | 1956 break; |
1957 } | |
1958 | |
3640 | 1959 elt = fmt_list.next (nconv > 0); |
2117 | 1960 } |
1961 } | |
1962 | |
1963 if (ok ()) | |
1964 { | |
2121 | 1965 mval.resize (final_nr, final_nc, 0.0); |
2117 | 1966 |
3268 | 1967 retval = mval; |
1968 | |
2117 | 1969 if (all_char_conv) |
5279 | 1970 retval = retval.convert_to_str (false, true); |
2117 | 1971 } |
1972 | |
1973 return retval; | |
1974 } | |
1975 | |
1976 octave_value | |
3810 | 1977 octave_base_stream::scanf (const std::string& fmt, const Array<double>& size, |
5275 | 1978 octave_idx_type& conversion_count, const std::string& who) |
2117 | 1979 { |
1980 octave_value retval = Matrix (); | |
1981 | |
3559 | 1982 conversion_count = 0; |
2117 | 1983 |
3523 | 1984 std::istream *isp = input_stream (); |
2117 | 1985 |
1986 if (isp) | |
1987 { | |
1988 scanf_format_list fmt_list (fmt); | |
1989 | |
3640 | 1990 if (fmt_list.num_conversions () == -1) |
4468 | 1991 ::error ("%s: invalid format specified", who.c_str ()); |
3640 | 1992 else |
2117 | 1993 { |
5275 | 1994 octave_idx_type nr = -1; |
1995 octave_idx_type nc = -1; | |
3640 | 1996 |
1997 bool one_elt_size_spec; | |
1998 | |
4468 | 1999 get_size (size, nr, nc, one_elt_size_spec, who); |
3640 | 2000 |
2001 if (! error_state) | |
2002 retval = do_scanf (fmt_list, nr, nc, one_elt_size_spec, | |
4468 | 2003 conversion_count, who); |
2215 | 2004 } |
2005 } | |
2006 else | |
4468 | 2007 invalid_operation (who, "reading"); |
2572 | 2008 |
2009 return retval; | |
2010 } | |
2011 | |
2712 | 2012 bool |
2013 octave_base_stream::do_oscanf (const scanf_format_elt *elt, | |
4468 | 2014 octave_value& retval, const std::string& who) |
2572 | 2015 { |
2712 | 2016 bool quit = false; |
2215 | 2017 |
3523 | 2018 std::istream *isp = input_stream (); |
2215 | 2019 |
2020 if (isp) | |
2021 { | |
3523 | 2022 std::istream& is = *isp; |
2215 | 2023 |
3538 | 2024 std::ios::fmtflags flags = is.flags (); |
2215 | 2025 |
2026 if (elt) | |
2027 { | |
2028 const char *fmt = elt->text; | |
2029 | |
2030 bool discard = elt->discard; | |
2031 | |
2032 switch (elt->type) | |
2033 { | |
3483 | 2034 case scanf_format_elt::whitespace_conversion: |
2035 DO_WHITESPACE_CONVERSION (); | |
2036 break; | |
2037 | |
2038 case scanf_format_elt::literal_conversion: | |
2039 DO_LITERAL_CONVERSION (); | |
2040 break; | |
2041 | |
2215 | 2042 case '%': |
2043 { | |
3640 | 2044 DO_PCT_CONVERSION (); |
2045 | |
2046 if (! is) | |
2712 | 2047 quit = true; |
3640 | 2048 |
2215 | 2049 } |
2050 break; | |
2051 | |
3878 | 2052 case 'd': case 'i': |
2215 | 2053 { |
2054 int tmp; | |
2055 | |
3640 | 2056 if (OCTAVE_SCAN (is, *elt, &tmp)) |
2712 | 2057 { |
2058 if (! discard) | |
4233 | 2059 retval = tmp; |
2712 | 2060 } |
2061 else | |
2062 quit = true; | |
2215 | 2063 } |
2064 break; | |
2065 | |
3878 | 2066 case 'o': case 'u': case 'x': |
2067 { | |
2068 long int tmp; | |
2069 | |
2070 if (OCTAVE_SCAN (is, *elt, &tmp)) | |
2071 { | |
2072 if (! discard) | |
4254 | 2073 retval = tmp; |
3878 | 2074 } |
2075 else | |
2076 quit = true; | |
2077 } | |
2078 break; | |
2079 | |
2215 | 2080 case 'e': case 'f': case 'g': |
2081 { | |
2600 | 2082 double tmp; |
2083 | |
3640 | 2084 if (OCTAVE_SCAN (is, *elt, &tmp)) |
2712 | 2085 { |
2086 if (! discard) | |
2087 retval = tmp; | |
2088 } | |
2089 else | |
2090 quit = true; | |
2215 | 2091 } |
2092 break; | |
2093 | |
2094 case 'c': | |
2095 { | |
3483 | 2096 BEGIN_C_CONVERSION (); |
2097 | |
2098 if (! discard) | |
2099 retval = tmp; | |
2100 | |
2101 if (! is) | |
2712 | 2102 quit = true; |
2215 | 2103 |
2104 is.setf (flags); | |
2105 } | |
2106 break; | |
2107 | |
2108 case 's': | |
2109 { | |
3483 | 2110 BEGIN_S_CONVERSION (); |
2111 | |
2112 if (! discard) | |
2113 retval = tmp; | |
2572 | 2114 |
3268 | 2115 if (! is) |
2116 quit = true; | |
2215 | 2117 } |
2118 break; | |
2119 | |
3483 | 2120 case '[': case '^': |
2121 { | |
2122 BEGIN_CHAR_CLASS_CONVERSION (); | |
2123 | |
2124 if (! discard) | |
2125 retval = tmp; | |
2126 | |
2127 if (! is) | |
2128 quit = true; | |
2129 } | |
2130 break; | |
2131 | |
2132 case 'p': | |
4468 | 2133 error ("%s: unsupported format specifier", who.c_str ()); |
2215 | 2134 break; |
2135 | |
2136 default: | |
4468 | 2137 error ("%s: internal format error", who.c_str ()); |
2215 | 2138 break; |
2139 } | |
2140 } | |
2141 | |
2142 if (ok () && is.fail ()) | |
2143 { | |
4468 | 2144 error ("%s: read error", who.c_str ()); |
3483 | 2145 |
5775 | 2146 // FIXME -- is this the right thing to do? |
3342 | 2147 |
2148 if (interactive && name () == "stdin") | |
2215 | 2149 { |
2150 // Skip to end of line. | |
2151 | |
2152 bool err; | |
4468 | 2153 do_gets (-1, err, false, who); |
2215 | 2154 } |
2155 } | |
2156 } | |
2157 | |
2712 | 2158 return quit; |
2215 | 2159 } |
2160 | |
2161 octave_value_list | |
4468 | 2162 octave_base_stream::oscanf (const std::string& fmt, const std::string& who) |
2215 | 2163 { |
2164 octave_value_list retval; | |
2165 | |
3523 | 2166 std::istream *isp = input_stream (); |
2215 | 2167 |
2168 if (isp) | |
2169 { | |
3523 | 2170 std::istream& is = *isp; |
2215 | 2171 |
2172 scanf_format_list fmt_list (fmt); | |
2173 | |
2174 int nconv = fmt_list.num_conversions (); | |
2175 | |
3640 | 2176 if (nconv == -1) |
4468 | 2177 ::error ("%s: invalid format specified", who.c_str ()); |
3640 | 2178 else |
2215 | 2179 { |
3640 | 2180 is.clear (); |
2181 | |
2182 int len = fmt_list.length (); | |
2183 | |
2184 retval.resize (nconv+1, Matrix ()); | |
2185 | |
2186 const scanf_format_elt *elt = fmt_list.first (); | |
2187 | |
2188 int num_values = 0; | |
2189 | |
2190 bool quit = false; | |
2191 | |
5275 | 2192 for (octave_idx_type i = 0; i < len; i++) |
3640 | 2193 { |
2194 octave_value tmp; | |
2195 | |
4468 | 2196 quit = do_oscanf (elt, tmp, who); |
3640 | 2197 |
2198 if (quit) | |
2199 break; | |
2200 else | |
2201 { | |
2202 if (tmp.is_defined ()) | |
2203 retval (num_values++) = tmp; | |
2204 | |
2205 if (! ok ()) | |
2206 break; | |
2207 | |
2208 elt = fmt_list.next (nconv > 0); | |
2209 } | |
2210 } | |
2211 | |
4233 | 2212 retval(nconv) = num_values; |
3640 | 2213 |
2214 if (! quit) | |
2215 { | |
2216 // Pick up any trailing stuff. | |
2217 if (ok () && len > nconv) | |
2218 { | |
2219 octave_value tmp; | |
3704 | 2220 |
2221 elt = fmt_list.next (); | |
2222 | |
4468 | 2223 do_oscanf (elt, tmp, who); |
3640 | 2224 } |
2225 } | |
2117 | 2226 } |
2227 } | |
2228 else | |
4468 | 2229 invalid_operation (who, "reading"); |
2117 | 2230 |
2231 return retval; | |
2232 } | |
2233 | |
2234 // Functions that are defined for all output streams (output streams | |
2235 // are those that define os). | |
2236 | |
2237 int | |
2238 octave_base_stream::flush (void) | |
2239 { | |
2240 int retval = -1; | |
2241 | |
3523 | 2242 std::ostream *os = output_stream (); |
2117 | 2243 |
2244 if (os) | |
2245 { | |
2246 os->flush (); | |
2247 | |
2248 if (os->good ()) | |
2249 retval = 0; | |
2250 } | |
2251 else | |
2252 invalid_operation ("fflush", "writing"); | |
2253 | |
2254 return retval; | |
2255 } | |
2256 | |
2257 class | |
2258 printf_value_cache | |
2259 { | |
2260 public: | |
2261 | |
3653 | 2262 enum state { ok, conversion_error }; |
2117 | 2263 |
7352 | 2264 printf_value_cache (const octave_value_list& args, const std::string& who) |
2117 | 2265 : values (args), val_idx (0), elt_idx (0), |
2266 n_vals (values.length ()), n_elts (0), data (0), | |
7352 | 2267 curr_state (ok) |
2268 { | |
2269 for (octave_idx_type i = 0; i < values.length (); i++) | |
2270 { | |
2271 octave_value val = values(i); | |
2272 | |
2273 if (val.is_map () || val.is_cell () || val.is_object () | |
2274 || val.is_list ()) | |
2275 { | |
2276 gripe_wrong_type_arg (who, val); | |
2277 break; | |
2278 } | |
2279 } | |
2280 } | |
2117 | 2281 |
2282 ~printf_value_cache (void) { } | |
2283 | |
2284 // Get the current value as a double and advance the internal pointer. | |
2285 double double_value (void); | |
2286 | |
2287 // Get the current value as an int and advance the internal pointer. | |
2288 int int_value (void); | |
2289 | |
2290 // Get the current value as a string and advance the internal pointer. | |
3523 | 2291 std::string string_value (void); |
2117 | 2292 |
3145 | 2293 operator bool () const { return (curr_state == ok); } |
2117 | 2294 |
3653 | 2295 bool exhausted (void) { return (val_idx >= n_vals); } |
2117 | 2296 |
2297 private: | |
2298 | |
2299 const octave_value_list values; | |
2300 int val_idx; | |
2301 int elt_idx; | |
2302 int n_vals; | |
2303 int n_elts; | |
2304 const double *data; | |
4874 | 2305 NDArray curr_val; |
2117 | 2306 state curr_state; |
2307 | |
2308 // Must create value cache with values! | |
2309 | |
2310 printf_value_cache (void); | |
2311 | |
2312 // No copying! | |
2313 | |
2314 printf_value_cache (const printf_value_cache&); | |
2315 | |
2316 printf_value_cache& operator = (const printf_value_cache&); | |
2317 }; | |
2318 | |
2319 double | |
2320 printf_value_cache::double_value (void) | |
2321 { | |
2322 double retval = 0.0; | |
2323 | |
3711 | 2324 if (exhausted ()) |
2325 curr_state = conversion_error; | |
2326 | |
2327 while (! exhausted ()) | |
2117 | 2328 { |
2329 if (! data) | |
2330 { | |
2331 octave_value tmp_val = values (val_idx); | |
2332 | |
5476 | 2333 // Force string conversion here for compatibility. |
2334 | |
2335 curr_val = tmp_val.array_value (true); | |
2117 | 2336 |
2337 if (! error_state) | |
2338 { | |
2339 elt_idx = 0; | |
2340 n_elts = curr_val.length (); | |
2341 data = curr_val.data (); | |
2342 } | |
2343 else | |
2344 { | |
2345 curr_state = conversion_error; | |
2346 break; | |
2347 } | |
2348 } | |
2349 | |
2350 if (elt_idx < n_elts) | |
2351 { | |
3653 | 2352 retval = data[elt_idx++]; |
2353 | |
2354 if (elt_idx >= n_elts) | |
2355 { | |
2356 elt_idx = 0; | |
2357 val_idx++; | |
2358 data = 0; | |
2359 } | |
2360 | |
2117 | 2361 break; |
2362 } | |
2363 else | |
2364 { | |
2365 val_idx++; | |
2366 data = 0; | |
3969 | 2367 |
2368 if (n_elts == 0 && exhausted ()) | |
2369 curr_state = conversion_error; | |
2370 | |
2117 | 2371 continue; |
2372 } | |
2373 } | |
2374 | |
2375 return retval; | |
2376 } | |
2377 | |
2378 int | |
2379 printf_value_cache::int_value (void) | |
2380 { | |
2381 int retval = 0; | |
2382 | |
2383 double dval = double_value (); | |
2384 | |
2385 if (! error_state) | |
2386 { | |
2387 if (D_NINT (dval) == dval) | |
2388 retval = NINT (dval); | |
2389 else | |
2390 curr_state = conversion_error; | |
2391 } | |
2392 | |
2393 return retval; | |
2394 } | |
2395 | |
3536 | 2396 std::string |
2117 | 2397 printf_value_cache::string_value (void) |
2398 { | |
3523 | 2399 std::string retval; |
2117 | 2400 |
4425 | 2401 if (exhausted ()) |
2402 curr_state = conversion_error; | |
4257 | 2403 else |
2117 | 2404 { |
4425 | 2405 octave_value tval = values (val_idx++); |
2406 | |
2407 if (tval.rows () == 1) | |
2408 retval = tval.string_value (); | |
2409 else | |
2410 { | |
2411 // In the name of Matlab compatibility. | |
2412 | |
2413 charMatrix chm = tval.char_matrix_value (); | |
2414 | |
5275 | 2415 octave_idx_type nr = chm.rows (); |
2416 octave_idx_type nc = chm.columns (); | |
4425 | 2417 |
2418 int k = 0; | |
2419 | |
2420 retval.resize (nr * nc, '\0'); | |
2421 | |
5275 | 2422 for (octave_idx_type j = 0; j < nc; j++) |
2423 for (octave_idx_type i = 0; i < nr; i++) | |
4425 | 2424 retval[k++] = chm(i,j); |
2425 } | |
2426 | |
2427 if (error_state) | |
2428 curr_state = conversion_error; | |
2117 | 2429 } |
4257 | 2430 |
2117 | 2431 return retval; |
2432 } | |
2433 | |
2434 // Ugh again and again. | |
2435 | |
2572 | 2436 template <class T> |
3620 | 2437 int |
3523 | 2438 do_printf_conv (std::ostream& os, const char *fmt, int nsa, int sa_1, |
4468 | 2439 int sa_2, T arg, const std::string& who) |
2572 | 2440 { |
3620 | 2441 int retval = 0; |
2442 | |
2572 | 2443 switch (nsa) |
2444 { | |
2445 case 2: | |
3640 | 2446 retval = octave_format (os, fmt, sa_1, sa_2, arg); |
2572 | 2447 break; |
2448 | |
2449 case 1: | |
3640 | 2450 retval = octave_format (os, fmt, sa_1, arg); |
2572 | 2451 break; |
2452 | |
2453 case 0: | |
3640 | 2454 retval = octave_format (os, fmt, arg); |
2572 | 2455 break; |
2456 | |
2457 default: | |
4468 | 2458 ::error ("%s: internal error handling format", who.c_str ()); |
2572 | 2459 break; |
2460 } | |
3620 | 2461 |
2462 return retval; | |
2572 | 2463 } |
2464 | |
3620 | 2465 template int |
4468 | 2466 do_printf_conv (std::ostream&, const char*, int, int, int, int, |
2467 const std::string&); | |
2468 | |
2469 template int | |
2470 do_printf_conv (std::ostream&, const char*, int, int, int, long, | |
2471 const std::string&); | |
2472 | |
3878 | 2473 template int |
4468 | 2474 do_printf_conv (std::ostream&, const char*, int, int, int, unsigned int, |
2475 const std::string&); | |
2476 | |
2477 template int | |
2478 do_printf_conv (std::ostream&, const char*, int, int, int, unsigned long, | |
2479 const std::string&); | |
2480 | |
2481 template int | |
2482 do_printf_conv (std::ostream&, const char*, int, int, int, double, | |
2483 const std::string&); | |
2484 | |
2485 template int | |
2486 do_printf_conv (std::ostream&, const char*, int, int, int, const char*, | |
2487 const std::string&); | |
2117 | 2488 |
6492 | 2489 #define DO_DOUBLE_CONV(TQUAL) \ |
2490 do \ | |
2491 { \ | |
7199 | 2492 if (val > std::numeric_limits<TQUAL long>::max () \ |
2493 || val < std::numeric_limits<TQUAL long>::min ()) \ | |
6492 | 2494 { \ |
7199 | 2495 std::string tfmt = fmt; \ |
6492 | 2496 \ |
7199 | 2497 tfmt.replace (tfmt.rfind (elt->type), 1, ".f"); \ |
6492 | 2498 \ |
7199 | 2499 if (elt->modifier == 'l') \ |
2500 tfmt.replace (tfmt.rfind (elt->modifier), 1, ""); \ | |
2501 \ | |
2502 retval += do_printf_conv (os, tfmt.c_str (), nsa, sa_1, sa_2, \ | |
2503 val, who); \ | |
6492 | 2504 } \ |
2505 else \ | |
7199 | 2506 retval += do_printf_conv (os, fmt, nsa, sa_1, sa_2, \ |
2507 static_cast<TQUAL long> (val), who); \ | |
6492 | 2508 } \ |
2509 while (0) | |
2510 | |
2117 | 2511 int |
2512 octave_base_stream::do_printf (printf_format_list& fmt_list, | |
4468 | 2513 const octave_value_list& args, |
2514 const std::string& who) | |
2117 | 2515 { |
3620 | 2516 int retval = 0; |
2117 | 2517 |
3640 | 2518 int nconv = fmt_list.num_conversions (); |
2519 | |
3523 | 2520 std::ostream *osp = output_stream (); |
2117 | 2521 |
2522 if (osp) | |
2523 { | |
3523 | 2524 std::ostream& os = *osp; |
2117 | 2525 |
2526 const printf_format_elt *elt = fmt_list.first (); | |
2527 | |
7352 | 2528 printf_value_cache val_cache (args, who); |
2529 | |
2530 if (error_state) | |
2531 return retval; | |
2117 | 2532 |
2533 for (;;) | |
2534 { | |
4153 | 2535 OCTAVE_QUIT; |
2536 | |
2117 | 2537 if (elt) |
2538 { | |
3640 | 2539 // NSA is the number of `star' args to convert. |
2540 | |
2541 int nsa = (elt->fw < 0) + (elt->prec < 0); | |
2117 | 2542 |
2543 int sa_1 = 0; | |
2544 int sa_2 = 0; | |
2545 | |
2546 if (nsa > 0) | |
2547 { | |
2548 sa_1 = val_cache.int_value (); | |
2549 | |
2550 if (! val_cache) | |
2551 break; | |
2552 else | |
2553 { | |
2554 if (nsa > 1) | |
2555 { | |
2556 sa_2 = val_cache.int_value (); | |
2557 | |
2558 if (! val_cache) | |
2559 break; | |
2560 } | |
2561 } | |
2562 } | |
2563 | |
2564 const char *fmt = elt->text; | |
2565 | |
3640 | 2566 if (elt->type == '%') |
2567 { | |
2568 os << "%"; | |
2569 retval++; | |
2570 } | |
2571 else if (elt->args == 0 && elt->text) | |
2572 { | |
2573 os << elt->text; | |
2574 retval += strlen (elt->text); | |
2575 } | |
4257 | 2576 else if (elt->type == 's') |
3640 | 2577 { |
2578 std::string val = val_cache.string_value (); | |
2579 | |
2580 if (val_cache) | |
2581 retval += do_printf_conv (os, fmt, nsa, sa_1, | |
4468 | 2582 sa_2, val.c_str (), who); |
3640 | 2583 else |
2584 break; | |
2585 } | |
2117 | 2586 else |
2587 { | |
3640 | 2588 double val = val_cache.double_value (); |
2589 | |
2590 if (val_cache) | |
2117 | 2591 { |
6492 | 2592 if (lo_ieee_isnan (val) || xisinf (val)) |
4303 | 2593 { |
2594 std::string tfmt = fmt; | |
6865 | 2595 std::string::size_type i1, i2; |
2596 | |
2597 tfmt.replace ((i1 = tfmt.rfind (elt->type)), | |
2598 1, 1, 's'); | |
2599 | |
2600 if ((i2 = tfmt.rfind ('.')) != NPOS && i2 < i1) | |
2601 { | |
2602 tfmt.erase (i2, i1-i2); | |
2603 if (elt->prec < 0) | |
2604 nsa--; | |
2605 } | |
6492 | 2606 |
2607 const char *tval = xisinf (val) | |
2608 ? (val < 0 ? "-Inf" : "Inf") | |
2609 : (lo_ieee_is_NA (val) ? "NA" : "NaN"); | |
2610 | |
2611 retval += do_printf_conv (os, tfmt.c_str (), | |
2612 nsa, sa_1, sa_2, | |
2613 tval, who); | |
4303 | 2614 } |
2615 else | |
3640 | 2616 { |
6492 | 2617 char type = elt->type; |
2618 | |
2619 switch (type) | |
4303 | 2620 { |
2621 case 'd': case 'i': case 'c': | |
7227 | 2622 DO_DOUBLE_CONV (OCTAVE_EMPTY_CPP_ARG); |
4303 | 2623 break; |
2624 | |
2625 case 'o': case 'x': case 'X': case 'u': | |
6492 | 2626 DO_DOUBLE_CONV (unsigned); |
4303 | 2627 break; |
2628 | |
2629 case 'f': case 'e': case 'E': | |
2630 case 'g': case 'G': | |
2631 retval | |
2632 += do_printf_conv (os, fmt, nsa, sa_1, sa_2, | |
4468 | 2633 val, who); |
4303 | 2634 break; |
2635 | |
2636 default: | |
4468 | 2637 error ("%s: invalid format specifier", |
2638 who.c_str ()); | |
4303 | 2639 return -1; |
2640 break; | |
2641 } | |
3640 | 2642 } |
2117 | 2643 } |
2644 else | |
3620 | 2645 break; |
2117 | 2646 } |
2647 | |
3620 | 2648 if (! os) |
2117 | 2649 { |
4468 | 2650 error ("%s: write error", who.c_str ()); |
2117 | 2651 break; |
2652 } | |
2653 } | |
2654 else | |
2655 { | |
4468 | 2656 ::error ("%s: internal error handling format", who.c_str ()); |
2117 | 2657 retval = -1; |
2658 break; | |
2659 } | |
2660 | |
3640 | 2661 elt = fmt_list.next (nconv > 0 && ! val_cache.exhausted ()); |
2662 | |
2663 if (! elt || (val_cache.exhausted () && elt->args > 0)) | |
2664 break; | |
2665 } | |
2117 | 2666 } |
3640 | 2667 else |
4468 | 2668 invalid_operation (who, "writing"); |
2117 | 2669 |
2670 return retval; | |
2671 } | |
2672 | |
2673 int | |
3640 | 2674 octave_base_stream::printf (const std::string& fmt, |
4468 | 2675 const octave_value_list& args, |
2676 const std::string& who) | |
2117 | 2677 { |
3640 | 2678 int retval = 0; |
2679 | |
2680 printf_format_list fmt_list (fmt); | |
2681 | |
2682 if (fmt_list.num_conversions () == -1) | |
4468 | 2683 ::error ("%s: invalid format specified", who.c_str ()); |
2117 | 2684 else |
4468 | 2685 retval = do_printf (fmt_list, args, who); |
2117 | 2686 |
2687 return retval; | |
2688 } | |
2689 | |
2690 int | |
4468 | 2691 octave_base_stream::puts (const std::string& s, const std::string& who) |
2117 | 2692 { |
2693 int retval = -1; | |
2694 | |
3523 | 2695 std::ostream *osp = output_stream (); |
2117 | 2696 |
2697 if (osp) | |
2698 { | |
3523 | 2699 std::ostream& os = *osp; |
2117 | 2700 |
2701 os << s; | |
2702 | |
2703 if (os) | |
2704 { | |
5775 | 2705 // FIXME -- why does this seem to be necessary? |
2117 | 2706 // Without it, output from a loop like |
2707 // | |
2708 // for i = 1:100, fputs (stdout, "foo\n"); endfor | |
2709 // | |
2710 // doesn't seem to go to the pager immediately. | |
2711 | |
2712 os.flush (); | |
2713 | |
2714 if (os) | |
2715 retval = 0; | |
2716 else | |
4468 | 2717 error ("%s: write error", who.c_str ()); |
2117 | 2718 } |
2719 else | |
4468 | 2720 error ("%s: write error", who.c_str ()); |
2117 | 2721 } |
2722 else | |
4468 | 2723 invalid_operation (who, "writing"); |
2117 | 2724 |
2725 return retval; | |
2726 } | |
2727 | |
2728 // Return current error message for this stream. | |
2729 | |
3536 | 2730 std::string |
2435 | 2731 octave_base_stream::error (bool clear_err, int& err_num) |
2117 | 2732 { |
2435 | 2733 err_num = fail ? -1 : 0; |
2117 | 2734 |
3523 | 2735 std::string tmp = errmsg; |
2117 | 2736 |
2737 if (clear_err) | |
2738 clear (); | |
2739 | |
2740 return tmp; | |
2741 } | |
2742 | |
2743 void | |
4468 | 2744 octave_base_stream::invalid_operation (const std::string& who, const char *rw) |
2117 | 2745 { |
4468 | 2746 // Note that this is not ::error () ! |
2747 | |
6297 | 2748 error (who, std::string ("stream not open for ") + rw); |
2117 | 2749 } |
2750 | |
3552 | 2751 octave_stream::octave_stream (octave_base_stream *bs) |
3340 | 2752 : rep (bs) |
2753 { | |
2754 if (rep) | |
2755 rep->count = 1; | |
2756 } | |
2757 | |
2758 octave_stream::~octave_stream (void) | |
2759 { | |
2760 if (rep && --rep->count == 0) | |
2761 delete rep; | |
2762 } | |
2763 | |
2764 octave_stream::octave_stream (const octave_stream& s) | |
2765 : rep (s.rep) | |
2766 { | |
2767 if (rep) | |
2768 rep->count++; | |
2769 } | |
2770 | |
2771 octave_stream& | |
2772 octave_stream::operator = (const octave_stream& s) | |
2773 { | |
2774 if (rep != s.rep) | |
2775 { | |
2776 if (rep && --rep->count == 0) | |
2777 delete rep; | |
2778 | |
2779 rep = s.rep; | |
2780 | |
2781 if (rep) | |
2782 rep->count++; | |
2783 } | |
2784 | |
2785 return *this; | |
2786 } | |
2787 | |
2117 | 2788 int |
2789 octave_stream::flush (void) | |
2790 { | |
2791 int retval = -1; | |
2792 | |
5659 | 2793 if (stream_ok ()) |
2117 | 2794 retval = rep->flush (); |
2795 | |
2796 return retval; | |
2797 } | |
2798 | |
3536 | 2799 std::string |
5275 | 2800 octave_stream::getl (octave_idx_type max_len, bool& err, const std::string& who) |
2117 | 2801 { |
3523 | 2802 std::string retval; |
2117 | 2803 |
5659 | 2804 if (stream_ok ()) |
4468 | 2805 retval = rep->getl (max_len, err, who); |
2117 | 2806 |
2807 return retval; | |
2808 } | |
2809 | |
3536 | 2810 std::string |
4468 | 2811 octave_stream::getl (const octave_value& tc_max_len, bool& err, |
2812 const std::string& who) | |
2117 | 2813 { |
3523 | 2814 std::string retval; |
2117 | 2815 |
2816 err = false; | |
2817 | |
2818 int conv_err = 0; | |
2819 | |
6345 | 2820 int max_len = -1; |
2821 | |
2822 if (tc_max_len.is_defined ()) | |
2117 | 2823 { |
6345 | 2824 max_len = convert_to_valid_int (tc_max_len, conv_err); |
2825 | |
2826 if (conv_err || max_len < 0) | |
2827 { | |
2828 err = true; | |
2829 ::error ("%s: invalid maximum length specified", who.c_str ()); | |
2830 } | |
2117 | 2831 } |
6345 | 2832 |
2833 if (! error_state) | |
4468 | 2834 retval = getl (max_len, err, who); |
2117 | 2835 |
2836 return retval; | |
2837 } | |
2838 | |
3536 | 2839 std::string |
5275 | 2840 octave_stream::gets (octave_idx_type max_len, bool& err, const std::string& who) |
2117 | 2841 { |
3523 | 2842 std::string retval; |
2117 | 2843 |
5659 | 2844 if (stream_ok ()) |
4468 | 2845 retval = rep->gets (max_len, err, who); |
2117 | 2846 |
2847 return retval; | |
2848 } | |
2849 | |
3536 | 2850 std::string |
4468 | 2851 octave_stream::gets (const octave_value& tc_max_len, bool& err, |
2852 const std::string& who) | |
2117 | 2853 { |
3523 | 2854 std::string retval; |
2117 | 2855 |
2856 err = false; | |
2857 | |
2858 int conv_err = 0; | |
2859 | |
6345 | 2860 int max_len = -1; |
2861 | |
2862 if (tc_max_len.is_defined ()) | |
2117 | 2863 { |
6345 | 2864 max_len = convert_to_valid_int (tc_max_len, conv_err); |
2865 | |
2866 if (conv_err || max_len < 0) | |
2867 { | |
2868 err = true; | |
2869 ::error ("%s: invalid maximum length specified", who.c_str ()); | |
2870 } | |
2117 | 2871 } |
6345 | 2872 |
2873 if (! error_state) | |
4468 | 2874 retval = gets (max_len, err, who); |
2117 | 2875 |
2876 return retval; | |
2877 } | |
2878 | |
2879 int | |
4797 | 2880 octave_stream::seek (long offset, int origin) |
2117 | 2881 { |
5065 | 2882 int status = -1; |
2117 | 2883 |
5659 | 2884 if (stream_ok ()) |
4889 | 2885 { |
2886 clearerr (); | |
2887 | |
5065 | 2888 long orig_pos = rep->tell (); |
2889 | |
2890 status = rep->seek (offset, origin); | |
2891 | |
2892 if (status == 0) | |
2893 { | |
2894 long save_pos = rep->tell (); | |
2895 | |
2896 rep->seek (0, SEEK_END); | |
2897 | |
2898 long pos_eof = rep->tell (); | |
2899 | |
2900 // I don't think save_pos can be less than zero, but we'll | |
2901 // check anyway... | |
2902 | |
2903 if (save_pos > pos_eof || save_pos < 0) | |
2904 { | |
2905 // Seek outside bounds of file. Failure should leave | |
2906 // position unchanged. | |
2907 | |
2908 rep->seek (orig_pos, SEEK_SET); | |
2909 | |
2910 status = -1; | |
2911 } | |
2912 else | |
2913 { | |
2914 // Is it possible for this to fail? We are just | |
2915 // returning to a position after the first successful | |
2916 // seek. | |
2917 | |
2918 rep->seek (save_pos, SEEK_SET); | |
2919 } | |
2920 } | |
4889 | 2921 } |
2117 | 2922 |
5065 | 2923 return status; |
2117 | 2924 } |
2925 | |
2926 int | |
2927 octave_stream::seek (const octave_value& tc_offset, | |
2928 const octave_value& tc_origin) | |
2929 { | |
2930 int retval = -1; | |
2931 | |
4797 | 2932 long xoffset = tc_offset.long_value (true); |
4645 | 2933 |
2934 if (! error_state) | |
2117 | 2935 { |
4645 | 2936 int conv_err = 0; |
2937 | |
4797 | 2938 int origin = SEEK_SET; |
2117 | 2939 |
2341 | 2940 if (tc_origin.is_string ()) |
2117 | 2941 { |
3523 | 2942 std::string xorigin = tc_origin.string_value (); |
2341 | 2943 |
2944 if (xorigin == "bof") | |
4797 | 2945 origin = SEEK_SET; |
2341 | 2946 else if (xorigin == "cof") |
4797 | 2947 origin = SEEK_CUR; |
2341 | 2948 else if (xorigin == "eof") |
4797 | 2949 origin = SEEK_END; |
2117 | 2950 else |
2951 conv_err = -1; | |
2952 } | |
2341 | 2953 else |
2954 { | |
2955 int xorigin = convert_to_valid_int (tc_origin, conv_err); | |
2956 | |
2957 if (! conv_err) | |
2958 { | |
2959 if (xorigin == -1) | |
4797 | 2960 origin = SEEK_SET; |
2341 | 2961 else if (xorigin == 0) |
4797 | 2962 origin = SEEK_CUR; |
2341 | 2963 else if (xorigin == 1) |
4797 | 2964 origin = SEEK_END; |
2341 | 2965 else |
2966 conv_err = -1; | |
2967 } | |
2968 } | |
2117 | 2969 |
2970 if (! conv_err) | |
5065 | 2971 { |
2972 retval = seek (xoffset, origin); | |
2973 | |
2974 if (retval != 0) | |
2975 error ("fseek: failed to seek to requested position"); | |
2976 } | |
2117 | 2977 else |
2978 error ("fseek: invalid value for origin"); | |
2979 } | |
2980 else | |
2981 error ("fseek: invalid value for offset"); | |
2982 | |
2983 return retval; | |
2984 } | |
2985 | |
4797 | 2986 long |
2987 octave_stream::tell (void) | |
2117 | 2988 { |
4797 | 2989 long retval = -1; |
2117 | 2990 |
5659 | 2991 if (stream_ok ()) |
2117 | 2992 retval = rep->tell (); |
2993 | |
2994 return retval; | |
2995 } | |
2996 | |
2997 int | |
2998 octave_stream::rewind (void) | |
2999 { | |
6296 | 3000 return seek (0, SEEK_SET); |
2117 | 3001 } |
3002 | |
3340 | 3003 bool |
3004 octave_stream::is_open (void) const | |
3005 { | |
3006 bool retval = false; | |
3007 | |
5659 | 3008 if (stream_ok ()) |
3340 | 3009 retval = rep->is_open (); |
3010 | |
3011 return retval; | |
3012 } | |
3013 | |
3014 void | |
3015 octave_stream::close (void) | |
3016 { | |
5659 | 3017 if (stream_ok ()) |
3340 | 3018 rep->close (); |
3019 } | |
3020 | |
4944 | 3021 template <class RET_T, class READ_T> |
2117 | 3022 octave_value |
5275 | 3023 do_read (octave_stream& strm, octave_idx_type nr, octave_idx_type nc, octave_idx_type block_size, |
3024 octave_idx_type skip, bool do_float_fmt_conv, | |
3025 oct_mach_info::float_format from_flt_fmt, octave_idx_type& count) | |
2117 | 3026 { |
3027 octave_value retval; | |
3028 | |
4944 | 3029 RET_T nda; |
3030 | |
3031 count = 0; | |
3032 | |
3033 typename octave_array_type_traits<RET_T>::element_type elt_zero | |
3034 = typename octave_array_type_traits<RET_T>::element_type (); | |
3035 | |
3036 typename octave_array_type_traits<RET_T>::element_type *dat = 0; | |
3037 | |
5275 | 3038 octave_idx_type max_size = 0; |
3039 | |
3040 octave_idx_type final_nr = 0; | |
3041 octave_idx_type final_nc = 1; | |
4944 | 3042 |
3043 if (nr > 0) | |
3044 { | |
3045 if (nc > 0) | |
3046 { | |
3047 nda.resize (dim_vector (nr, nc), elt_zero); | |
3048 dat = nda.fortran_vec (); | |
3049 max_size = nr * nc; | |
3050 } | |
3051 else | |
3052 { | |
3053 nda.resize (dim_vector (nr, 32), elt_zero); | |
3054 dat = nda.fortran_vec (); | |
3055 max_size = nr * 32; | |
3056 } | |
3057 } | |
3058 else | |
3059 { | |
3060 nda.resize (dim_vector (32, 1), elt_zero); | |
3061 dat = nda.fortran_vec (); | |
3062 max_size = 32; | |
3063 } | |
3064 | |
5775 | 3065 // FIXME -- byte order for Cray? |
4944 | 3066 |
3067 bool swap = false; | |
3068 | |
3069 if (oct_mach_info::words_big_endian ()) | |
3070 swap = (from_flt_fmt == oct_mach_info::flt_fmt_ieee_little_endian | |
3071 || from_flt_fmt == oct_mach_info::flt_fmt_vax_g | |
3072 || from_flt_fmt == oct_mach_info::flt_fmt_vax_g); | |
3073 else | |
3074 swap = (from_flt_fmt == oct_mach_info::flt_fmt_ieee_big_endian); | |
3075 | |
3076 union | |
3077 { | |
3078 char buf[sizeof (typename octave_type_traits<READ_T>::val_type)]; | |
3079 typename octave_type_traits<READ_T>::val_type val; | |
3080 } u; | |
3081 | |
3082 std::istream *isp = strm.input_stream (); | |
3083 | |
3084 if (isp) | |
3085 { | |
3086 std::istream& is = *isp; | |
3087 | |
5275 | 3088 octave_idx_type elts_read = 0; |
4944 | 3089 |
3090 for (;;) | |
3091 { | |
5775 | 3092 // FIXME -- maybe there should be a special case for |
4944 | 3093 // skip == 0. |
3094 | |
3095 if (is) | |
3096 { | |
3097 if (nr > 0 && nc > 0 && count == max_size) | |
3098 { | |
3099 final_nr = nr; | |
3100 final_nc = nc; | |
3101 | |
3102 break; | |
3103 } | |
3104 | |
3105 is.read (u.buf, sizeof (typename octave_type_traits<READ_T>::val_type)); | |
3106 | |
3107 // We only swap bytes for integer types. For float | |
3108 // types, the format conversion will also handle byte | |
3109 // swapping. | |
3110 | |
3111 if (swap) | |
3112 swap_bytes<sizeof (typename octave_type_traits<READ_T>::val_type)> (u.buf); | |
3113 else if (do_float_fmt_conv) | |
3114 do_float_format_conversion | |
3115 (u.buf, | |
3116 sizeof (typename octave_type_traits<READ_T>::val_type), | |
3117 1, from_flt_fmt, oct_mach_info::float_format ()); | |
3118 | |
3119 typename octave_array_type_traits<RET_T>::element_type tmp | |
3120 = static_cast <typename octave_array_type_traits<RET_T>::element_type> (u.val); | |
3121 | |
5030 | 3122 if (is) |
4944 | 3123 { |
5030 | 3124 if (count == max_size) |
4944 | 3125 { |
5030 | 3126 max_size *= 2; |
3127 | |
3128 if (nr > 0) | |
3129 nda.resize (dim_vector (nr, max_size / nr), | |
3130 elt_zero); | |
3131 else | |
3132 nda.resize (dim_vector (max_size, 1), elt_zero); | |
3133 | |
3134 dat = nda.fortran_vec (); | |
4944 | 3135 } |
3136 | |
5030 | 3137 dat[count++] = tmp; |
3138 | |
3139 elts_read++; | |
3140 } | |
3141 | |
7538
2c4b0cbda85a
oct-stream.cc (do_read): stop reading if seek fails
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
3142 int seek_status = 0; |
2c4b0cbda85a
oct-stream.cc (do_read): stop reading if seek fails
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
3143 |
5030 | 3144 if (skip != 0 && elts_read == block_size) |
3145 { | |
7538
2c4b0cbda85a
oct-stream.cc (do_read): stop reading if seek fails
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
3146 seek_status = strm.seek (skip, SEEK_CUR); |
5030 | 3147 elts_read = 0; |
3148 } | |
3149 | |
7538
2c4b0cbda85a
oct-stream.cc (do_read): stop reading if seek fails
John W. Eaton <jwe@octave.org>
parents:
7433
diff
changeset
|
3150 if (is.eof () || seek_status < 0) |
5030 | 3151 { |
3152 if (nr > 0) | |
4944 | 3153 { |
5030 | 3154 if (count > nr) |
4944 | 3155 { |
5030 | 3156 final_nr = nr; |
3157 final_nc = (count - 1) / nr + 1; | |
4944 | 3158 } |
3159 else | |
3160 { | |
3161 final_nr = count; | |
3162 final_nc = 1; | |
3163 } | |
3164 } | |
5030 | 3165 else |
3166 { | |
3167 final_nr = count; | |
3168 final_nc = 1; | |
3169 } | |
3170 | |
4944 | 3171 break; |
3172 } | |
3173 } | |
5030 | 3174 else if (is.eof ()) |
3175 break; | |
4944 | 3176 } |
3177 } | |
3178 | |
5030 | 3179 nda.resize (dim_vector (final_nr, final_nc), elt_zero); |
3180 | |
3181 retval = nda; | |
4944 | 3182 |
3183 return retval; | |
3184 } | |
3185 | |
3186 #define DO_READ_VAL_TEMPLATE(RET_T, READ_T) \ | |
3187 template octave_value \ | |
5275 | 3188 do_read<RET_T, READ_T> (octave_stream&, octave_idx_type, octave_idx_type, octave_idx_type, octave_idx_type, bool, \ |
3189 oct_mach_info::float_format, octave_idx_type&) | |
4944 | 3190 |
5775 | 3191 // FIXME -- should we only have float if it is a different |
4944 | 3192 // size from double? |
3193 | |
3194 #define INSTANTIATE_DO_READ(VAL_T) \ | |
3195 DO_READ_VAL_TEMPLATE (VAL_T, octave_int8); \ | |
3196 DO_READ_VAL_TEMPLATE (VAL_T, octave_uint8); \ | |
3197 DO_READ_VAL_TEMPLATE (VAL_T, octave_int16); \ | |
3198 DO_READ_VAL_TEMPLATE (VAL_T, octave_uint16); \ | |
3199 DO_READ_VAL_TEMPLATE (VAL_T, octave_int32); \ | |
3200 DO_READ_VAL_TEMPLATE (VAL_T, octave_uint32); \ | |
3201 DO_READ_VAL_TEMPLATE (VAL_T, octave_int64); \ | |
3202 DO_READ_VAL_TEMPLATE (VAL_T, octave_uint64); \ | |
3203 DO_READ_VAL_TEMPLATE (VAL_T, float); \ | |
3204 DO_READ_VAL_TEMPLATE (VAL_T, double); \ | |
3205 DO_READ_VAL_TEMPLATE (VAL_T, char); \ | |
3206 DO_READ_VAL_TEMPLATE (VAL_T, signed char); \ | |
3207 DO_READ_VAL_TEMPLATE (VAL_T, unsigned char) | |
3208 | |
4970 | 3209 INSTANTIATE_DO_READ (int8NDArray); |
3210 INSTANTIATE_DO_READ (uint8NDArray); | |
3211 INSTANTIATE_DO_READ (int16NDArray); | |
3212 INSTANTIATE_DO_READ (uint16NDArray); | |
3213 INSTANTIATE_DO_READ (int32NDArray); | |
3214 INSTANTIATE_DO_READ (uint32NDArray); | |
3215 INSTANTIATE_DO_READ (int64NDArray); | |
3216 INSTANTIATE_DO_READ (uint64NDArray); | |
3217 // INSTANTIATE_DO_READ (floatNDArray); | |
3218 INSTANTIATE_DO_READ (NDArray); | |
3219 INSTANTIATE_DO_READ (charNDArray); | |
5780 | 3220 INSTANTIATE_DO_READ (boolNDArray); |
4944 | 3221 |
5275 | 3222 typedef octave_value (*read_fptr) (octave_stream&, octave_idx_type, octave_idx_type, octave_idx_type, octave_idx_type, bool, |
3223 oct_mach_info::float_format ffmt, octave_idx_type&); | |
4944 | 3224 |
7433 | 3225 NO_INSTANTIATE_ARRAY_SORT (read_fptr); |
6708 | 3226 INSTANTIATE_ARRAY (read_fptr,); |
4944 | 3227 template class Array2<read_fptr>; |
3228 | |
3229 #define FILL_TABLE_ROW(R, VAL_T) \ | |
3230 read_fptr_table(R,oct_data_conv::dt_int8) = do_read<VAL_T, octave_int8>; \ | |
3231 read_fptr_table(R,oct_data_conv::dt_uint8) = do_read<VAL_T, octave_uint8>; \ | |
3232 read_fptr_table(R,oct_data_conv::dt_int16) = do_read<VAL_T, octave_int16>; \ | |
3233 read_fptr_table(R,oct_data_conv::dt_uint16) = do_read<VAL_T, octave_uint16>; \ | |
3234 read_fptr_table(R,oct_data_conv::dt_int32) = do_read<VAL_T, octave_int32>; \ | |
3235 read_fptr_table(R,oct_data_conv::dt_uint32) = do_read<VAL_T, octave_uint32>; \ | |
3236 read_fptr_table(R,oct_data_conv::dt_int64) = do_read<VAL_T, octave_int64>; \ | |
3237 read_fptr_table(R,oct_data_conv::dt_uint64) = do_read<VAL_T, octave_uint64>; \ | |
3238 read_fptr_table(R,oct_data_conv::dt_single) = do_read<VAL_T, float>; \ | |
3239 read_fptr_table(R,oct_data_conv::dt_double) = do_read<VAL_T, double>; \ | |
3240 read_fptr_table(R,oct_data_conv::dt_char) = do_read<VAL_T, char>; \ | |
3241 read_fptr_table(R,oct_data_conv::dt_schar) = do_read<VAL_T, signed char>; \ | |
4970 | 3242 read_fptr_table(R,oct_data_conv::dt_uchar) = do_read<VAL_T, unsigned char>; \ |
3243 read_fptr_table(R,oct_data_conv::dt_logical) = do_read<VAL_T, unsigned char> | |
4944 | 3244 |
3245 octave_value | |
5275 | 3246 octave_stream::read (const Array<double>& size, octave_idx_type block_size, |
4944 | 3247 oct_data_conv::data_type input_type, |
3248 oct_data_conv::data_type output_type, | |
5275 | 3249 octave_idx_type skip, oct_mach_info::float_format ffmt, |
3250 octave_idx_type& char_count) | |
4944 | 3251 { |
3252 static bool initialized = false; | |
3253 | |
3254 // Table function pointers for return types x read types. | |
3255 | |
4970 | 3256 static Array2<read_fptr> read_fptr_table (oct_data_conv::dt_unknown, 14, 0); |
4944 | 3257 |
3258 if (! initialized) | |
3259 { | |
3260 FILL_TABLE_ROW (oct_data_conv::dt_int8, int8NDArray); | |
3261 FILL_TABLE_ROW (oct_data_conv::dt_uint8, uint8NDArray); | |
3262 FILL_TABLE_ROW (oct_data_conv::dt_int16, int16NDArray); | |
3263 FILL_TABLE_ROW (oct_data_conv::dt_uint16, uint16NDArray); | |
3264 FILL_TABLE_ROW (oct_data_conv::dt_int32, int32NDArray); | |
3265 FILL_TABLE_ROW (oct_data_conv::dt_uint32, uint32NDArray); | |
3266 FILL_TABLE_ROW (oct_data_conv::dt_int64, int64NDArray); | |
3267 FILL_TABLE_ROW (oct_data_conv::dt_uint64, uint64NDArray); | |
3268 FILL_TABLE_ROW (oct_data_conv::dt_double, NDArray); | |
3269 FILL_TABLE_ROW (oct_data_conv::dt_char, charNDArray); | |
3270 FILL_TABLE_ROW (oct_data_conv::dt_schar, charNDArray); | |
3271 FILL_TABLE_ROW (oct_data_conv::dt_uchar, charNDArray); | |
4970 | 3272 FILL_TABLE_ROW (oct_data_conv::dt_logical, boolNDArray); |
4944 | 3273 |
3274 initialized = true; | |
3275 } | |
3276 | |
3277 octave_value retval; | |
3278 | |
5659 | 3279 if (stream_ok ()) |
4944 | 3280 { |
5775 | 3281 // FIXME -- we may eventually want to make this extensible. |
3282 | |
3283 // FIXME -- we need a better way to ensure that this | |
4944 | 3284 // numbering stays consistent with the order of the elements in the |
3285 // data_type enum in the oct_data_conv class. | |
3286 | |
3287 char_count = 0; | |
3288 | |
5275 | 3289 octave_idx_type nr = -1; |
3290 octave_idx_type nc = -1; | |
4944 | 3291 |
3292 bool ignore; | |
3293 | |
3294 get_size (size, nr, nc, ignore, "fread"); | |
3295 | |
3296 if (! error_state) | |
3297 { | |
3298 if (nr == 0 || nc == 0) | |
3299 retval = Matrix (nr, nc); | |
3300 else | |
3301 { | |
3302 if (ffmt == oct_mach_info::flt_fmt_unknown) | |
3303 ffmt = float_format (); | |
3304 | |
3305 read_fptr fcn = read_fptr_table (output_type, input_type); | |
3306 | |
3307 bool do_float_fmt_conv = ((input_type == oct_data_conv::dt_double | |
3308 || input_type == oct_data_conv::dt_single) | |
3309 && ffmt != float_format ()); | |
3310 | |
3311 if (fcn) | |
3312 { | |
3313 retval = (*fcn) (*this, nr, nc, block_size, skip, | |
3314 do_float_fmt_conv, ffmt, char_count); | |
3315 | |
5775 | 3316 // FIXME -- kluge! |
4944 | 3317 |
3318 if (! error_state | |
3319 && (output_type == oct_data_conv::dt_char | |
3320 || output_type == oct_data_conv::dt_schar | |
3321 || output_type == oct_data_conv::dt_uchar)) | |
3322 retval = octave_value (retval.char_matrix_value (), true); | |
3323 } | |
3324 else | |
3325 error ("fread: unable to read and convert requested types"); | |
3326 } | |
3327 } | |
3328 else | |
3329 invalid_operation ("fread", "reading"); | |
3330 } | |
2117 | 3331 |
3332 return retval; | |
3333 } | |
3334 | |
5275 | 3335 octave_idx_type |
3336 octave_stream::write (const octave_value& data, octave_idx_type block_size, | |
3337 oct_data_conv::data_type output_type, octave_idx_type skip, | |
2317 | 3338 oct_mach_info::float_format flt_fmt) |
2117 | 3339 { |
5275 | 3340 octave_idx_type retval = -1; |
2117 | 3341 |
5659 | 3342 if (stream_ok ()) |
4944 | 3343 { |
3344 if (! error_state) | |
3345 { | |
3346 if (flt_fmt == oct_mach_info::flt_fmt_unknown) | |
3347 flt_fmt = float_format (); | |
3348 | |
5275 | 3349 octave_idx_type status = data.write (*this, block_size, output_type, |
4944 | 3350 skip, flt_fmt); |
3351 | |
3352 if (status < 0) | |
3353 error ("fwrite: write error"); | |
3354 else | |
3355 retval = status; | |
3356 } | |
3357 else | |
3358 invalid_operation ("fwrite", "writing"); | |
3359 } | |
2117 | 3360 |
3361 return retval; | |
3362 } | |
3363 | |
4944 | 3364 template <class T> |
3365 void | |
3366 write_int (std::ostream& os, bool swap, const T& val) | |
3367 { | |
3368 typename octave_type_traits<T>::val_type tmp = val.value (); | |
3369 | |
3370 if (swap) | |
3371 swap_bytes<sizeof (typename octave_type_traits<T>::val_type)> (&tmp); | |
3372 | |
3373 os.write (reinterpret_cast<const char *> (&tmp), | |
3374 sizeof (typename octave_type_traits<T>::val_type)); | |
3375 } | |
3376 | |
3377 template void write_int (std::ostream&, bool, const octave_int8&); | |
3378 template void write_int (std::ostream&, bool, const octave_uint8&); | |
3379 template void write_int (std::ostream&, bool, const octave_int16&); | |
3380 template void write_int (std::ostream&, bool, const octave_uint16&); | |
3381 template void write_int (std::ostream&, bool, const octave_int32&); | |
3382 template void write_int (std::ostream&, bool, const octave_uint32&); | |
3383 template void write_int (std::ostream&, bool, const octave_int64&); | |
3384 template void write_int (std::ostream&, bool, const octave_uint64&); | |
3385 | |
3386 template <class T> | |
3387 static inline bool | |
3388 do_write (std::ostream& os, const T& val, oct_data_conv::data_type output_type, | |
3389 oct_mach_info::float_format flt_fmt, bool swap, | |
3390 bool do_float_conversion) | |
3391 { | |
3392 bool retval = true; | |
3393 | |
3394 // For compatibility, Octave converts to the output type, then | |
3395 // writes. This means that truncation happens on the conversion. | |
3396 // For example, the following program prints 0: | |
3397 // | |
3398 // x = int8 (-1) | |
3399 // f = fopen ("foo.dat", "w"); | |
3400 // fwrite (f, x, "unsigned char"); | |
3401 // fclose (f); | |
3402 // f = fopen ("foo.dat", "r"); | |
3403 // y = fread (f, 1, "unsigned char"); | |
3404 // printf ("%d\n", y); | |
3405 | |
3406 switch (output_type) | |
3407 { | |
3408 case oct_data_conv::dt_char: | |
3409 case oct_data_conv::dt_schar: | |
3410 case oct_data_conv::dt_int8: | |
3411 write_int (os, swap, octave_int8 (val)); | |
3412 break; | |
3413 | |
3414 case oct_data_conv::dt_uchar: | |
3415 case oct_data_conv::dt_uint8: | |
3416 write_int (os, swap, octave_uint8 (val)); | |
3417 break; | |
3418 | |
3419 case oct_data_conv::dt_int16: | |
3420 write_int (os, swap, octave_int16 (val)); | |
3421 break; | |
3422 | |
3423 case oct_data_conv::dt_uint16: | |
3424 write_int (os, swap, octave_uint16 (val)); | |
3425 break; | |
3426 | |
3427 case oct_data_conv::dt_int32: | |
3428 write_int (os, swap, octave_int32 (val)); | |
3429 break; | |
3430 | |
3431 case oct_data_conv::dt_uint32: | |
3432 write_int (os, swap, octave_uint32 (val)); | |
3433 break; | |
3434 | |
3435 case oct_data_conv::dt_int64: | |
3436 write_int (os, swap, octave_int64 (val)); | |
3437 break; | |
3438 | |
3439 case oct_data_conv::dt_uint64: | |
3440 write_int (os, swap, octave_uint64 (val)); | |
3441 break; | |
3442 | |
3443 case oct_data_conv::dt_single: | |
3444 { | |
3445 float f = static_cast<float> (val); | |
3446 | |
3447 if (do_float_conversion) | |
3448 do_float_format_conversion (&f, 1, flt_fmt); | |
3449 | |
3450 os.write (reinterpret_cast<const char *> (&f), sizeof (float)); | |
3451 } | |
3452 break; | |
3453 | |
3454 case oct_data_conv::dt_double: | |
3455 { | |
3456 double d = static_cast<double> (val); | |
3457 if (do_float_conversion) | |
3458 do_double_format_conversion (&d, 1, flt_fmt); | |
3459 | |
3460 os.write (reinterpret_cast<const char *> (&d), sizeof (double)); | |
3461 } | |
3462 break; | |
3463 | |
3464 default: | |
3465 retval = false; | |
3466 (*current_liboctave_error_handler) | |
3467 ("write: invalid type specification"); | |
3468 break; | |
3469 } | |
3470 | |
3471 return retval; | |
3472 } | |
3473 | |
5887 | 3474 template bool |
3475 do_write (std::ostream&, const octave_int8&, oct_data_conv::data_type, | |
3476 oct_mach_info::float_format, bool, bool); | |
3477 | |
3478 template bool | |
3479 do_write (std::ostream&, const octave_uint8&, oct_data_conv::data_type, | |
3480 oct_mach_info::float_format, bool, bool); | |
3481 | |
3482 template bool | |
3483 do_write (std::ostream&, const octave_int16&, oct_data_conv::data_type, | |
3484 oct_mach_info::float_format, bool, bool); | |
3485 | |
3486 template bool | |
3487 do_write (std::ostream&, const octave_uint16&, oct_data_conv::data_type, | |
3488 oct_mach_info::float_format, bool, bool); | |
3489 | |
3490 template bool | |
3491 do_write (std::ostream&, const octave_int32&, oct_data_conv::data_type, | |
3492 oct_mach_info::float_format, bool, bool); | |
3493 | |
3494 template bool | |
3495 do_write (std::ostream&, const octave_uint32&, oct_data_conv::data_type, | |
3496 oct_mach_info::float_format, bool, bool); | |
3497 | |
3498 template bool | |
3499 do_write (std::ostream&, const octave_int64&, oct_data_conv::data_type, | |
3500 oct_mach_info::float_format, bool, bool); | |
3501 | |
3502 template bool | |
3503 do_write (std::ostream&, const octave_uint64&, oct_data_conv::data_type, | |
3504 oct_mach_info::float_format, bool, bool); | |
3505 | |
4944 | 3506 template <class T> |
5275 | 3507 octave_idx_type |
3508 octave_stream::write (const Array<T>& data, octave_idx_type block_size, | |
4944 | 3509 oct_data_conv::data_type output_type, |
5275 | 3510 octave_idx_type skip, oct_mach_info::float_format flt_fmt) |
4944 | 3511 { |
5275 | 3512 octave_idx_type retval = -1; |
4944 | 3513 |
3514 bool status = true; | |
3515 | |
5275 | 3516 octave_idx_type count = 0; |
4944 | 3517 |
3518 const T *d = data.data (); | |
3519 | |
5275 | 3520 octave_idx_type n = data.length (); |
4944 | 3521 |
3522 oct_mach_info::float_format native_flt_fmt | |
3523 = oct_mach_info::float_format (); | |
3524 | |
3525 bool do_float_conversion = (flt_fmt != native_flt_fmt); | |
3526 | |
5775 | 3527 // FIXME -- byte order for Cray? |
4944 | 3528 |
3529 bool swap = false; | |
3530 | |
3531 if (oct_mach_info::words_big_endian ()) | |
3532 swap = (flt_fmt == oct_mach_info::flt_fmt_ieee_little_endian | |
3533 || flt_fmt == oct_mach_info::flt_fmt_vax_g | |
3534 || flt_fmt == oct_mach_info::flt_fmt_vax_g); | |
3535 else | |
3536 swap = (flt_fmt == oct_mach_info::flt_fmt_ieee_big_endian); | |
3537 | |
5275 | 3538 for (octave_idx_type i = 0; i < n; i++) |
4944 | 3539 { |
3540 std::ostream *osp = output_stream (); | |
3541 | |
3542 if (osp) | |
3543 { | |
3544 std::ostream& os = *osp; | |
3545 | |
5254 | 3546 // It seems that Matlab writes zeros instead of actually |
3547 // seeking. Hmm... | |
3548 | |
4944 | 3549 if (skip != 0 && (i % block_size) == 0) |
5254 | 3550 { |
5775 | 3551 // FIXME -- probably should try to write larger |
5254 | 3552 // blocks... |
3553 | |
3554 unsigned char zero = 0; | |
3555 for (int j = 0; j < skip; j++) | |
3556 os.write (reinterpret_cast<const char *> (&zero), 1); | |
3557 } | |
4944 | 3558 |
3559 if (os) | |
3560 { | |
3561 status = do_write (os, d[i], output_type, flt_fmt, swap, | |
3562 do_float_conversion); | |
3563 | |
3564 if (os && status) | |
3565 count++; | |
3566 else | |
3567 break; | |
3568 } | |
3569 else | |
3570 { | |
3571 status = false; | |
3572 break; | |
3573 } | |
3574 } | |
3575 else | |
3576 { | |
3577 status = false; | |
3578 break; | |
3579 } | |
3580 } | |
3581 | |
3582 if (status) | |
3583 retval = count; | |
3584 | |
3585 return retval; | |
3586 } | |
3587 | |
5275 | 3588 template octave_idx_type |
3589 octave_stream::write (const Array<char>&, octave_idx_type, | |
4944 | 3590 oct_data_conv::data_type, |
5275 | 3591 octave_idx_type, oct_mach_info::float_format); |
3592 | |
3593 template octave_idx_type | |
3594 octave_stream::write (const Array<bool>&, octave_idx_type, | |
4970 | 3595 oct_data_conv::data_type, |
5275 | 3596 octave_idx_type, oct_mach_info::float_format); |
3597 | |
3598 template octave_idx_type | |
3599 octave_stream::write (const Array<double>&, octave_idx_type, | |
4944 | 3600 oct_data_conv::data_type, |
5275 | 3601 octave_idx_type, oct_mach_info::float_format); |
3602 | |
3603 template octave_idx_type | |
3604 octave_stream::write (const Array<octave_int8>&, octave_idx_type, | |
4944 | 3605 oct_data_conv::data_type, |
5275 | 3606 octave_idx_type, oct_mach_info::float_format); |
3607 | |
3608 template octave_idx_type | |
3609 octave_stream::write (const Array<octave_uint8>&, octave_idx_type, | |
4944 | 3610 oct_data_conv::data_type, |
5275 | 3611 octave_idx_type, oct_mach_info::float_format); |
3612 | |
3613 template octave_idx_type | |
3614 octave_stream::write (const Array<octave_int16>&, octave_idx_type, | |
4944 | 3615 oct_data_conv::data_type, |
5275 | 3616 octave_idx_type, oct_mach_info::float_format); |
3617 | |
3618 template octave_idx_type | |
3619 octave_stream::write (const Array<octave_uint16>&, octave_idx_type, | |
4944 | 3620 oct_data_conv::data_type, |
5275 | 3621 octave_idx_type, oct_mach_info::float_format); |
3622 | |
3623 template octave_idx_type | |
3624 octave_stream::write (const Array<octave_int32>&, octave_idx_type, | |
4944 | 3625 oct_data_conv::data_type, |
5275 | 3626 octave_idx_type, oct_mach_info::float_format); |
3627 | |
3628 template octave_idx_type | |
3629 octave_stream::write (const Array<octave_uint32>&, octave_idx_type, | |
4944 | 3630 oct_data_conv::data_type, |
5275 | 3631 octave_idx_type, oct_mach_info::float_format); |
3632 | |
3633 template octave_idx_type | |
3634 octave_stream::write (const Array<octave_int64>&, octave_idx_type, | |
4944 | 3635 oct_data_conv::data_type, |
5275 | 3636 octave_idx_type, oct_mach_info::float_format); |
3637 | |
3638 template octave_idx_type | |
3639 octave_stream::write (const Array<octave_uint64>&, octave_idx_type, | |
4944 | 3640 oct_data_conv::data_type, |
5275 | 3641 octave_idx_type, oct_mach_info::float_format); |
4944 | 3642 |
2117 | 3643 octave_value |
3810 | 3644 octave_stream::scanf (const std::string& fmt, const Array<double>& size, |
5275 | 3645 octave_idx_type& count, const std::string& who) |
2117 | 3646 { |
3647 octave_value retval; | |
3648 | |
5659 | 3649 if (stream_ok ()) |
4468 | 3650 retval = rep->scanf (fmt, size, count, who); |
2117 | 3651 |
3652 return retval; | |
3653 } | |
3654 | |
5279 | 3655 octave_value |
3656 octave_stream::scanf (const octave_value& fmt, const Array<double>& size, | |
5299 | 3657 octave_idx_type& count, const std::string& who) |
5279 | 3658 { |
3659 octave_value retval = Matrix (); | |
3660 | |
3661 if (fmt.is_string ()) | |
3662 { | |
3663 std::string sfmt = fmt.string_value (); | |
3664 | |
3665 if (fmt.is_sq_string ()) | |
3666 sfmt = do_string_escapes (sfmt); | |
3667 | |
3668 retval = scanf (sfmt, size, count, who); | |
3669 } | |
3670 else | |
3671 { | |
3672 // Note that this is not ::error () ! | |
3673 | |
3674 error (who + ": format must be a string"); | |
3675 } | |
3676 | |
3677 return retval; | |
3678 } | |
3679 | |
2215 | 3680 octave_value_list |
4468 | 3681 octave_stream::oscanf (const std::string& fmt, const std::string& who) |
2215 | 3682 { |
3683 octave_value_list retval; | |
3684 | |
5659 | 3685 if (stream_ok ()) |
4468 | 3686 retval = rep->oscanf (fmt, who); |
2215 | 3687 |
3688 return retval; | |
3689 } | |
3690 | |
5279 | 3691 octave_value_list |
3692 octave_stream::oscanf (const octave_value& fmt, const std::string& who) | |
3693 { | |
3694 octave_value_list retval; | |
3695 | |
3696 if (fmt.is_string ()) | |
3697 { | |
3698 std::string sfmt = fmt.string_value (); | |
3699 | |
3700 if (fmt.is_sq_string ()) | |
3701 sfmt = do_string_escapes (sfmt); | |
3702 | |
3703 retval = oscanf (sfmt, who); | |
3704 } | |
3705 else | |
3706 { | |
3707 // Note that this is not ::error () ! | |
3708 | |
3709 error (who + ": format must be a string"); | |
3710 } | |
3711 | |
3712 return retval; | |
3713 } | |
3714 | |
2117 | 3715 int |
4468 | 3716 octave_stream::printf (const std::string& fmt, const octave_value_list& args, |
3717 const std::string& who) | |
2117 | 3718 { |
3719 int retval = -1; | |
3720 | |
5659 | 3721 if (stream_ok ()) |
4468 | 3722 retval = rep->printf (fmt, args, who); |
2117 | 3723 |
3724 return retval; | |
3725 } | |
3726 | |
3727 int | |
5279 | 3728 octave_stream::printf (const octave_value& fmt, const octave_value_list& args, |
3729 const std::string& who) | |
3730 { | |
3731 int retval = 0; | |
3732 | |
3733 if (fmt.is_string ()) | |
3734 { | |
3735 std::string sfmt = fmt.string_value (); | |
3736 | |
3737 if (fmt.is_sq_string ()) | |
3738 sfmt = do_string_escapes (sfmt); | |
3739 | |
3740 retval = printf (sfmt, args, who); | |
3741 } | |
3742 else | |
3743 { | |
3744 // Note that this is not ::error () ! | |
3745 | |
3746 error (who + ": format must be a string"); | |
3747 } | |
3748 | |
3749 return retval; | |
3750 } | |
3751 | |
3752 int | |
4468 | 3753 octave_stream::puts (const std::string& s, const std::string& who) |
2117 | 3754 { |
3755 int retval = -1; | |
3756 | |
5659 | 3757 if (stream_ok ()) |
4468 | 3758 retval = rep->puts (s, who); |
2117 | 3759 |
3760 return retval; | |
3761 } | |
3762 | |
5775 | 3763 // FIXME -- maybe this should work for string arrays too. |
2117 | 3764 |
3765 int | |
4468 | 3766 octave_stream::puts (const octave_value& tc_s, const std::string& who) |
2117 | 3767 { |
3768 int retval = -1; | |
3769 | |
3770 if (tc_s.is_string ()) | |
3771 { | |
3523 | 3772 std::string s = tc_s.string_value (); |
5279 | 3773 retval = puts (s, who); |
2117 | 3774 } |
3775 else | |
4468 | 3776 { |
3777 // Note that this is not ::error () ! | |
3778 | |
3779 error (who + ": argument must be a string"); | |
3780 } | |
2117 | 3781 |
3782 return retval; | |
3783 } | |
3784 | |
3785 bool | |
3786 octave_stream::eof (void) const | |
3787 { | |
3788 int retval = -1; | |
3789 | |
5659 | 3790 if (stream_ok ()) |
2117 | 3791 retval = rep->eof (); |
3792 | |
3793 return retval; | |
3794 } | |
3795 | |
3536 | 3796 std::string |
2435 | 3797 octave_stream::error (bool clear, int& err_num) |
2117 | 3798 { |
5649 | 3799 std::string retval = "invalid stream object"; |
3800 | |
5659 | 3801 if (stream_ok (false)) |
2435 | 3802 retval = rep->error (clear, err_num); |
2117 | 3803 |
3804 return retval; | |
3805 } | |
3806 | |
3536 | 3807 std::string |
3340 | 3808 octave_stream::name (void) const |
2117 | 3809 { |
3523 | 3810 std::string retval; |
2117 | 3811 |
5659 | 3812 if (stream_ok ()) |
2117 | 3813 retval = rep->name (); |
3814 | |
3815 return retval; | |
3816 } | |
3817 | |
3818 int | |
3340 | 3819 octave_stream::mode (void) const |
2117 | 3820 { |
3821 int retval = 0; | |
3822 | |
5659 | 3823 if (stream_ok ()) |
2117 | 3824 retval = rep->mode (); |
3825 | |
3826 return retval; | |
3827 } | |
3828 | |
2317 | 3829 oct_mach_info::float_format |
3340 | 3830 octave_stream::float_format (void) const |
2117 | 3831 { |
4574 | 3832 oct_mach_info::float_format retval = oct_mach_info::flt_fmt_unknown; |
2317 | 3833 |
5659 | 3834 if (stream_ok ()) |
2317 | 3835 retval = rep->float_format (); |
2117 | 3836 |
3837 return retval; | |
3838 } | |
3839 | |
3536 | 3840 std::string |
2117 | 3841 octave_stream::mode_as_string (int mode) |
3842 { | |
3523 | 3843 std::string retval = "???"; |
3775 | 3844 std::ios::openmode in_mode = static_cast<std::ios::openmode> (mode); |
3845 | |
3846 if (in_mode == std::ios::in) | |
3847 retval = "r"; | |
3848 else if (in_mode == std::ios::out | |
4078 | 3849 || in_mode == (std::ios::out | std::ios::trunc)) |
3775 | 3850 retval = "w"; |
4078 | 3851 else if (in_mode == (std::ios::out | std::ios::app)) |
3775 | 3852 retval = "a"; |
4078 | 3853 else if (in_mode == (std::ios::in | std::ios::out)) |
3775 | 3854 retval = "r+"; |
4078 | 3855 else if (in_mode == (std::ios::in | std::ios::out | std::ios::trunc)) |
3775 | 3856 retval = "w+"; |
4078 | 3857 else if (in_mode == (std::ios::in | std::ios::out | std::ios::ate)) |
3775 | 3858 retval = "a+"; |
4078 | 3859 else if (in_mode == (std::ios::in | std::ios::binary)) |
3775 | 3860 retval = "rb"; |
4078 | 3861 else if (in_mode == (std::ios::out | std::ios::binary) |
3862 || in_mode == (std::ios::out | std::ios::trunc | std::ios::binary)) | |
3775 | 3863 retval = "wb"; |
4078 | 3864 else if (in_mode == (std::ios::out | std::ios::app | std::ios::binary)) |
3775 | 3865 retval = "ab"; |
4078 | 3866 else if (in_mode == (std::ios::in | std::ios::out | std::ios::binary)) |
3775 | 3867 retval = "r+b"; |
4078 | 3868 else if (in_mode == (std::ios::in | std::ios::out | std::ios::trunc |
3869 | std::ios::binary)) | |
3775 | 3870 retval = "w+b"; |
4078 | 3871 else if (in_mode == (std::ios::in | std::ios::out | std::ios::ate |
3872 | std::ios::binary)) | |
3775 | 3873 retval = "a+b"; |
2117 | 3874 |
3875 return retval; | |
3876 } | |
3877 | |
3878 octave_stream_list *octave_stream_list::instance = 0; | |
3879 | |
2926 | 3880 bool |
3881 octave_stream_list::instance_ok (void) | |
3882 { | |
3883 bool retval = true; | |
3884 | |
3885 if (! instance) | |
3886 instance = new octave_stream_list (); | |
3887 | |
3888 if (! instance) | |
3889 { | |
3890 ::error ("unable to create stream list object!"); | |
3891 | |
3892 retval = false; | |
3893 } | |
3894 | |
3895 return retval; | |
3896 } | |
3897 | |
5353 | 3898 int |
6757 | 3899 octave_stream_list::insert (octave_stream& os) |
2926 | 3900 { |
5353 | 3901 return (instance_ok ()) ? instance->do_insert (os) : -1; |
2926 | 3902 } |
3903 | |
3340 | 3904 octave_stream |
3523 | 3905 octave_stream_list::lookup (int fid, const std::string& who) |
2926 | 3906 { |
3341 | 3907 return (instance_ok ()) ? instance->do_lookup (fid, who) : octave_stream (); |
2926 | 3908 } |
3909 | |
3340 | 3910 octave_stream |
3523 | 3911 octave_stream_list::lookup (const octave_value& fid, const std::string& who) |
2926 | 3912 { |
3341 | 3913 return (instance_ok ()) ? instance->do_lookup (fid, who) : octave_stream (); |
2926 | 3914 } |
3915 | |
3916 int | |
3523 | 3917 octave_stream_list::remove (int fid, const std::string& who) |
2926 | 3918 { |
3341 | 3919 return (instance_ok ()) ? instance->do_remove (fid, who) : -1; |
2926 | 3920 } |
3921 | |
3922 int | |
3523 | 3923 octave_stream_list::remove (const octave_value& fid, const std::string& who) |
2926 | 3924 { |
3341 | 3925 return (instance_ok ()) ? instance->do_remove (fid, who) : -1; |
2926 | 3926 } |
3927 | |
3928 void | |
3929 octave_stream_list::clear (void) | |
3930 { | |
3931 if (instance) | |
3932 instance->do_clear (); | |
3933 } | |
3934 | |
3935 string_vector | |
3936 octave_stream_list::get_info (int fid) | |
3937 { | |
3938 return (instance_ok ()) ? instance->do_get_info (fid) : string_vector (); | |
3939 } | |
3940 | |
3941 string_vector | |
3942 octave_stream_list::get_info (const octave_value& fid) | |
3943 { | |
3944 return (instance_ok ()) ? instance->do_get_info (fid) : string_vector (); | |
3945 } | |
3946 | |
3536 | 3947 std::string |
2926 | 3948 octave_stream_list::list_open_files (void) |
3949 { | |
3523 | 3950 return (instance_ok ()) ? instance->do_list_open_files () : std::string (); |
2926 | 3951 } |
3952 | |
3953 octave_value | |
3954 octave_stream_list::open_file_numbers (void) | |
3955 { | |
3956 return (instance_ok ()) | |
3957 ? instance->do_open_file_numbers () : octave_value (); | |
3958 } | |
3959 | |
3960 int | |
3961 octave_stream_list::get_file_number (const octave_value& fid) | |
3962 { | |
3963 return (instance_ok ()) ? instance->do_get_file_number (fid) : -1; | |
3964 } | |
3965 | |
5353 | 3966 int |
6757 | 3967 octave_stream_list::do_insert (octave_stream& os) |
2117 | 3968 { |
6757 | 3969 // Insert item with key corresponding to file-descriptor. |
3970 | |
3971 int stream_number; | |
3972 | |
3973 if ((stream_number = os.file_number ()) == -1) | |
3974 return stream_number; | |
3975 | |
3976 // Should we test for "(list.find (stream_number) != list.end ()) && | |
3977 // list[stream_number].is_open ()" and respond with "error | |
3978 // ("internal error: ...")"? It should not happen except for some | |
3979 // bug or if the user has opened a stream with an interpreted | |
3980 // command, but closed it directly with a system call in an | |
3981 // oct-file; then the kernel knows the fd is free, but Octave does | |
3982 // not know. If it happens, it should not do harm here to simply | |
3983 // overwrite this entry, although the wrong entry might have done | |
3984 // harm before. | |
3985 | |
3986 if (list.size () < list.max_size ()) | |
3987 list[stream_number] = os; | |
3988 else | |
2117 | 3989 { |
6757 | 3990 stream_number = -1; |
3991 error ("could not create file id"); | |
3340 | 3992 } |
2117 | 3993 |
5353 | 3994 return stream_number; |
6757 | 3995 |
2117 | 3996 } |
3997 | |
3341 | 3998 static void |
3523 | 3999 gripe_invalid_file_id (int fid, const std::string& who) |
3341 | 4000 { |
4001 if (who.empty ()) | |
4002 ::error ("invalid stream number = %d", fid); | |
4003 else | |
4004 ::error ("%s: invalid stream number = %d", who.c_str (), fid); | |
4005 } | |
4006 | |
3340 | 4007 octave_stream |
3523 | 4008 octave_stream_list::do_lookup (int fid, const std::string& who) const |
2117 | 4009 { |
3340 | 4010 octave_stream retval; |
2117 | 4011 |
6757 | 4012 if (fid >= 0) |
4013 { | |
4014 ostrl_map::const_iterator iter = list.find (fid); | |
4015 | |
4016 if (iter != list.end ()) | |
4017 retval = iter->second; | |
4018 else | |
4019 gripe_invalid_file_id (fid, who); | |
4020 } | |
3341 | 4021 else |
4022 gripe_invalid_file_id (fid, who); | |
2117 | 4023 |
4024 return retval; | |
4025 } | |
4026 | |
3340 | 4027 octave_stream |
3341 | 4028 octave_stream_list::do_lookup (const octave_value& fid, |
3523 | 4029 const std::string& who) const |
2117 | 4030 { |
3340 | 4031 octave_stream retval; |
2117 | 4032 |
4033 int i = get_file_number (fid); | |
4034 | |
4035 if (! error_state) | |
3341 | 4036 retval = do_lookup (i, who); |
2117 | 4037 |
4038 return retval; | |
4039 } | |
4040 | |
4041 int | |
3523 | 4042 octave_stream_list::do_remove (int fid, const std::string& who) |
2117 | 4043 { |
4044 int retval = -1; | |
4045 | |
3531 | 4046 // Can't remove stdin (std::cin), stdout (std::cout), or stderr |
4047 // (std::cerr). | |
2117 | 4048 |
6757 | 4049 if (fid > 2) |
2117 | 4050 { |
6757 | 4051 ostrl_map::iterator iter = list.find (fid); |
4052 | |
4053 if (iter != list.end ()) | |
2117 | 4054 { |
6757 | 4055 octave_stream os = iter->second; |
4056 | |
4057 if (os.is_valid ()) | |
4058 { | |
4059 os.close (); | |
4060 iter->second = octave_stream (); | |
4061 retval = 0; | |
4062 } | |
4063 else | |
4064 gripe_invalid_file_id (fid, who); | |
2117 | 4065 } |
3341 | 4066 else |
4067 gripe_invalid_file_id (fid, who); | |
2117 | 4068 } |
3341 | 4069 else |
4070 gripe_invalid_file_id (fid, who); | |
2117 | 4071 |
4072 return retval; | |
4073 } | |
4074 | |
4075 int | |
3523 | 4076 octave_stream_list::do_remove (const octave_value& fid, const std::string& who) |
2117 | 4077 { |
4078 int retval = -1; | |
4079 | |
6054 | 4080 if (fid.is_string () && fid.string_value () == "all") |
4081 { | |
6757 | 4082 for (ostrl_map::iterator p = list.begin (); p != list.end (); p++) |
6054 | 4083 { |
6757 | 4084 // Skip stdin, stdout, and stderr. |
4085 | |
4086 if (p->first > 2) | |
4087 { | |
4088 octave_stream os = p->second; | |
4089 | |
4090 if (os.is_valid ()) | |
4091 do_remove (p->first, who); | |
4092 } | |
6054 | 4093 } |
4094 | |
4095 retval = 0; | |
4096 } | |
4097 else | |
4098 { | |
4099 int i = get_file_number (fid); | |
4100 | |
4101 if (! error_state) | |
4102 retval = do_remove (i, who); | |
4103 } | |
2117 | 4104 |
4105 return retval; | |
4106 } | |
4107 | |
4108 void | |
4109 octave_stream_list::do_clear (void) | |
4110 { | |
4111 // Do flush stdout and stderr. | |
4112 | |
6757 | 4113 list[0].flush (); |
4114 list[1].flush (); | |
2117 | 4115 |
4116 // But don't delete them or stdin. | |
4117 | |
6757 | 4118 for (ostrl_map::iterator p = list.begin (); p != list.end (); p++) |
4119 { | |
4120 // Skip stdin, stdout, and stderr. | |
4121 | |
4122 if (p->first > 2) | |
4123 p->second = octave_stream (); | |
4124 } | |
2117 | 4125 } |
4126 | |
4127 string_vector | |
4128 octave_stream_list::do_get_info (int fid) const | |
4129 { | |
4130 string_vector retval; | |
4131 | |
3340 | 4132 octave_stream os = do_lookup (fid); |
2117 | 4133 |
3341 | 4134 if (os.is_valid ()) |
2117 | 4135 { |
4136 retval.resize (3); | |
4137 | |
3340 | 4138 retval(0) = os.name (); |
4139 retval(1) = octave_stream::mode_as_string (os.mode ()); | |
4140 retval(2) = oct_mach_info::float_format_as_string (os.float_format ()); | |
2117 | 4141 } |
4142 else | |
3341 | 4143 ::error ("invalid file id = %d", fid); |
2117 | 4144 |
4145 return retval; | |
4146 } | |
4147 | |
4148 string_vector | |
4149 octave_stream_list::do_get_info (const octave_value& fid) const | |
4150 { | |
4151 string_vector retval; | |
4152 | |
4153 int conv_err = 0; | |
4154 | |
4155 int int_fid = convert_to_valid_int (fid, conv_err); | |
4156 | |
4157 if (! conv_err) | |
4158 retval = do_get_info (int_fid); | |
4159 else | |
2915 | 4160 ::error ("file id must be a file object or integer value"); |
2117 | 4161 |
4162 return retval; | |
4163 } | |
4164 | |
3536 | 4165 std::string |
2117 | 4166 octave_stream_list::do_list_open_files (void) const |
4167 { | |
3523 | 4168 std::string retval; |
2117 | 4169 |
5765 | 4170 std::ostringstream buf; |
2117 | 4171 |
4172 buf << "\n" | |
4173 << " number mode arch name\n" | |
4174 << " ------ ---- ---- ----\n"; | |
4175 | |
6757 | 4176 for (ostrl_map::const_iterator p = list.begin (); p != list.end (); p++) |
2117 | 4177 { |
6757 | 4178 octave_stream os = p->second; |
2117 | 4179 |
4326 | 4180 buf << " " |
4181 << std::setiosflags (std::ios::right) | |
6757 | 4182 << std::setw (4) << p->first << " " |
4326 | 4183 << std::setiosflags (std::ios::left) |
4184 << std::setw (3) | |
4185 << octave_stream::mode_as_string (os.mode ()) | |
4186 << " " | |
4187 << std::setw (9) | |
4188 << oct_mach_info::float_format_as_string (os.float_format ()) | |
4189 << " " | |
4190 << os.name () << "\n"; | |
2117 | 4191 } |
4192 | |
5765 | 4193 buf << "\n"; |
4194 | |
4195 retval = buf.str (); | |
2117 | 4196 |
4197 return retval; | |
4198 } | |
4199 | |
4200 octave_value | |
4201 octave_stream_list::do_open_file_numbers (void) const | |
4202 { | |
6757 | 4203 Matrix retval (1, list.size (), 0.0); |
2117 | 4204 |
4205 int num_open = 0; | |
4206 | |
6757 | 4207 for (ostrl_map::const_iterator p = list.begin (); p != list.end (); p++) |
2117 | 4208 { |
6757 | 4209 // Skip stdin, stdout, and stderr. |
4210 | |
4211 if (p->first > 2 && p->second) | |
4212 retval(0,num_open++) = p->first; | |
2117 | 4213 } |
4214 | |
4215 retval.resize ((num_open > 0), num_open); | |
4216 | |
4217 return retval; | |
4218 } | |
4219 | |
4220 int | |
2609 | 4221 octave_stream_list::do_get_file_number (const octave_value& fid) const |
2117 | 4222 { |
4223 int retval = -1; | |
4224 | |
4225 if (fid.is_string ()) | |
4226 { | |
3523 | 4227 std::string nm = fid.string_value (); |
2117 | 4228 |
6757 | 4229 for (ostrl_map::const_iterator p = list.begin (); p != list.end (); p++) |
2117 | 4230 { |
6757 | 4231 // stdin (std::cin), stdout (std::cout), and stderr (std::cerr) |
4232 // are unnamed. | |
4233 | |
4234 if (p->first > 2) | |
2117 | 4235 { |
6757 | 4236 octave_stream os = p->second; |
4237 | |
4238 if (os && os.name () == nm) | |
4239 { | |
4240 retval = p->first; | |
4241 break; | |
4242 } | |
2117 | 4243 } |
4244 } | |
4245 } | |
4246 else | |
4247 { | |
4248 int conv_err = 0; | |
4249 | |
4250 int int_fid = convert_to_valid_int (fid, conv_err); | |
4251 | |
4252 if (conv_err) | |
3523 | 4253 ::error ("file id must be a file object, std::string, or integer value"); |
2117 | 4254 else |
4255 retval = int_fid; | |
4256 } | |
4257 | |
4258 return retval; | |
4259 } | |
4260 | |
4261 /* | |
4262 ;;; Local Variables: *** | |
4263 ;;; mode: C++ *** | |
4264 ;;; End: *** | |
4265 */ |