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