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