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