(index<- ) ./libstd/io.rs
1 // Copyright 2012 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10
11 /*!
12
13 The `io` module contains basic input and output routines.
14
15 A quick summary:
16
17 ## `Reader` and `Writer` traits
18
19 These traits define the minimal set of methods that anything that can do
20 input and output should implement.
21
22 ## `ReaderUtil` and `WriterUtil` traits
23
24 Richer methods that allow you to do more. `Reader` only lets you read a certain
25 number of bytes into a buffer, while `ReaderUtil` allows you to read a whole
26 line, for example.
27
28 Generally, these richer methods are probably the ones you want to actually
29 use in day-to-day Rust.
30
31 Furthermore, because there is an implementation of `ReaderUtil` for
32 `<T: Reader>`, when your input or output code implements `Reader`, you get
33 all of these methods for free.
34
35 ## `print` and `println`
36
37 These very useful functions are defined here. You generally don't need to
38 import them, though, as the prelude already does.
39
40 ## `stdin`, `stdout`, and `stderr`
41
42 These functions return references to the classic three file descriptors. They
43 implement `Reader` and `Writer`, where appropriate.
44
45 */
46
47 #[allow(missing_doc)];
48
49 use cast;
50 use cast::transmute;
51 use clone::Clone;
52 use c_str::ToCStr;
53 use container::Container;
54 use int;
55 use iter::Iterator;
56 use libc::consts::os::posix88::*;
57 use libc::{c_int, c_void, size_t};
58 use libc;
59 use num;
60 use ops::Drop;
61 use option::{Some, None};
62 use os;
63 use path::{Path,GenericPath};
64 use ptr;
65 use result::{Result, Ok, Err};
66 use str::{StrSlice, OwnedStr};
67 use str;
68 use to_str::ToStr;
69 use uint;
70 use vec::{MutableVector, ImmutableVector, OwnedVector, OwnedCopyableVector, CopyableVector};
71 use vec;
72
73 #[allow(non_camel_case_types)] // not sure what to do about this
74 pub type fd_t = c_int;
75
76 pub mod rustrt {
77 use libc;
78
79 #[link_name = "rustrt"]
80 extern {
81 pub fn rust_get_stdin() -> *libc::FILE;
82 pub fn rust_get_stdout() -> *libc::FILE;
83 pub fn rust_get_stderr() -> *libc::FILE;
84 }
85 }
86
87 // Reading
88
89 // FIXME (#2004): This is all buffered. We might need an unbuffered variant
90 // as well
91 /**
92 * The SeekStyle enum describes the relationship between the position
93 * we'd like to seek to from our current position. It's used as an argument
94 * to the `seek` method defined on the `Reader` trait.
95 *
96 * There are three seek styles:
97 *
98 * 1. `SeekSet` means that the new position should become our position.
99 * 2. `SeekCur` means that we should seek from the current position.
100 * 3. `SeekEnd` means that we should seek from the end.
101 *
102 * # Examples
103 *
104 * None right now.
105 */
106 pub enum SeekStyle { SeekSet, SeekEnd, SeekCur, }
107
108
109 /**
110 * The core Reader trait. All readers must implement this trait.
111 *
112 * # Examples
113 *
114 * None right now.
115 */
116 pub trait Reader {
117 // FIXME (#2004): Seekable really should be orthogonal.
118
119 // FIXME (#2982): This should probably return an error.
120 /**
121 * Reads bytes and puts them into `bytes`, advancing the cursor. Returns the
122 * number of bytes read.
123 *
124 * The number of bytes to be read is `len` or the end of the file,
125 * whichever comes first.
126 *
127 * The buffer must be at least `len` bytes long.
128 *
129 * `read` is conceptually similar to C's `fread` function.
130 *
131 * # Examples
132 *
133 * None right now.
134 */
135 fn read(&self, bytes: &mut [u8], len: uint) -> uint;
136
137 /**
138 * Reads a single byte, advancing the cursor.
139 *
140 * In the case of an EOF or an error, returns a negative value.
141 *
142 * `read_byte` is conceptually similar to C's `getc` function.
143 *
144 * # Examples
145 *
146 * None right now.
147 */
148 fn read_byte(&self) -> int;
149
150 /**
151 * Returns a boolean value: are we currently at EOF?
152 *
153 * Note that stream position may be already at the end-of-file point,
154 * but `eof` returns false until an attempt to read at that position.
155 *
156 * `eof` is conceptually similar to C's `feof` function.
157 *
158 * # Examples
159 *
160 * None right now.
161 */
162 fn eof(&self) -> bool;
163
164 /**
165 * Seek to a given `position` in the stream.
166 *
167 * Takes an optional SeekStyle, which affects how we seek from the
168 * position. See `SeekStyle` docs for more details.
169 *
170 * `seek` is conceptually similar to C's `fseek` function.
171 *
172 * # Examples
173 *
174 * None right now.
175 */
176 fn seek(&self, position: int, style: SeekStyle);
177
178 /**
179 * Returns the current position within the stream.
180 *
181 * `tell` is conceptually similar to C's `ftell` function.
182 *
183 * # Examples
184 *
185 * None right now.
186 */
187 fn tell(&self) -> uint;
188 }
189
190 impl Reader for @Reader {
191 fn read(&self, bytes: &mut [u8], len: uint) -> uint {
192 self.read(bytes, len)
193 }
194 fn read_byte(&self) -> int {
195 self.read_byte()
196 }
197 fn eof(&self) -> bool {
198 self.eof()
199 }
200 fn seek(&self, position: int, style: SeekStyle) {
201 self.seek(position, style)
202 }
203 fn tell(&self) -> uint {
204 self.tell()
205 }
206 }
207
208 /**
209 * The `ReaderUtil` trait is a home for many of the utility functions
210 * a particular Reader should implement.
211 *
212 * The default `Reader` trait is focused entirely on bytes. `ReaderUtil` is based
213 * on higher-level concepts like 'chars' and 'lines.'
214 *
215 * # Examples:
216 *
217 * None right now.
218 */
219 pub trait ReaderUtil {
220
221 /**
222 * Reads `len` number of bytes, and gives you a new vector back.
223 *
224 * # Examples
225 *
226 * None right now.
227 */
228 fn read_bytes(&self, len: uint) -> ~[u8];
229
230 /**
231 * Reads up until a specific byte is seen or EOF.
232 *
233 * The `include` parameter specifies if the character should be included
234 * in the returned string.
235 *
236 * # Examples
237 *
238 * None right now.
239 */
240 fn read_until(&self, c: u8, include: bool) -> ~str;
241
242 /**
243 * Reads up until the first '\n' or EOF.
244 *
245 * The '\n' is not included in the result.
246 *
247 * # Examples
248 *
249 * None right now.
250 */
251 fn read_line(&self) -> ~str;
252
253 /**
254 * Reads `n` chars.
255 *
256 * Assumes that those chars are UTF-8 encoded.
257 *
258 * The '\n' is not included in the result.
259 *
260 * # Examples
261 *
262 * None right now.
263 */
264 fn read_chars(&self, n: uint) -> ~[char];
265
266 /**
267 * Reads a single UTF-8 encoded char.
268 *
269 * # Examples
270 *
271 * None right now.
272 */
273 fn read_char(&self) -> char;
274
275 /**
276 * Reads up until the first null byte or EOF.
277 *
278 * The null byte is not returned.
279 *
280 * # Examples
281 *
282 * None right now.
283 */
284 fn read_c_str(&self) -> ~str;
285
286 /**
287 * Reads all remaining data in the stream.
288 *
289 * # Examples
290 *
291 * None right now.
292 */
293 fn read_whole_stream(&self) -> ~[u8];
294
295 /**
296 * Iterate over every byte until EOF or the iterator breaks.
297 *
298 * # Examples
299 *
300 * None right now.
301 */
302 fn each_byte(&self, it: &fn(int) -> bool) -> bool;
303
304 /**
305 * Iterate over every char until EOF or the iterator breaks.
306 *
307 * # Examples
308 *
309 * None right now.
310 */
311 fn each_char(&self, it: &fn(char) -> bool) -> bool;
312
313 /**
314 * Iterate over every line until EOF or the iterator breaks.
315 *
316 * # Examples
317 *
318 * None right now.
319 */
320 fn each_line(&self, it: &fn(&str) -> bool) -> bool;
321
322 /**
323 * Reads all of the lines in the stream.
324 *
325 * Returns a vector of those lines.
326 *
327 * # Examples
328 *
329 * None right now.
330 */
331 fn read_lines(&self) -> ~[~str];
332
333 /**
334 * Reads `n` little-endian unsigned integer bytes.
335 *
336 * `n` must be between 1 and 8, inclusive.
337 *
338 * # Examples
339 *
340 * None right now.
341 */
342 fn read_le_uint_n(&self, nbytes: uint) -> u64;
343
344 /**
345 * Reads `n` little-endian signed integer bytes.
346 *
347 * `n` must be between 1 and 8, inclusive.
348 *
349 * # Examples
350 *
351 * None right now.
352 */
353 fn read_le_int_n(&self, nbytes: uint) -> i64;
354
355 /**
356 * Reads `n` big-endian unsigned integer bytes.
357 *
358 * `n` must be between 1 and 8, inclusive.
359 *
360 * # Examples
361 *
362 * None right now.
363 */
364 fn read_be_uint_n(&self, nbytes: uint) -> u64;
365
366 /**
367 * Reads `n` big-endian signed integer bytes.
368 *
369 * `n` must be between 1 and 8, inclusive.
370 *
371 * # Examples
372 *
373 * None right now.
374 */
375 fn read_be_int_n(&self, nbytes: uint) -> i64;
376
377 /**
378 * Reads a little-endian unsigned integer.
379 *
380 * The number of bytes returned is system-dependant.
381 *
382 * # Examples
383 *
384 * None right now.
385 */
386 fn read_le_uint(&self) -> uint;
387
388 /**
389 * Reads a little-endian integer.
390 *
391 * The number of bytes returned is system-dependant.
392 *
393 * # Examples
394 *
395 * None right now.
396 */
397 fn read_le_int(&self) -> int;
398
399 /**
400 * Reads a big-endian unsigned integer.
401 *
402 * The number of bytes returned is system-dependant.
403 *
404 * # Examples
405 *
406 * None right now.
407 */
408 fn read_be_uint(&self) -> uint;
409
410 /**
411 * Reads a big-endian integer.
412 *
413 * The number of bytes returned is system-dependant.
414 *
415 * # Examples
416 *
417 * None right now.
418 */
419 fn read_be_int(&self) -> int;
420
421 /**
422 * Reads a big-endian `u64`.
423 *
424 * `u64`s are 8 bytes long.
425 *
426 * # Examples
427 *
428 * None right now.
429 */
430 fn read_be_u64(&self) -> u64;
431
432 /**
433 * Reads a big-endian `u32`.
434 *
435 * `u32`s are 4 bytes long.
436 *
437 * # Examples
438 *
439 * None right now.
440 */
441 fn read_be_u32(&self) -> u32;
442
443 /**
444 * Reads a big-endian `u16`.
445 *
446 * `u16`s are 2 bytes long.
447 *
448 * # Examples
449 *
450 * None right now.
451 */
452 fn read_be_u16(&self) -> u16;
453
454 /**
455 * Reads a big-endian `i64`.
456 *
457 * `i64`s are 8 bytes long.
458 *
459 * # Examples
460 *
461 * None right now.
462 */
463 fn read_be_i64(&self) -> i64;
464
465 /**
466 * Reads a big-endian `i32`.
467 *
468 * `i32`s are 4 bytes long.
469 *
470 * # Examples
471 *
472 * None right now.
473 */
474 fn read_be_i32(&self) -> i32;
475
476 /**
477 * Reads a big-endian `i16`.
478 *
479 * `i16`s are 2 bytes long.
480 *
481 * # Examples
482 *
483 * None right now.
484 */
485 fn read_be_i16(&self) -> i16;
486
487 /**
488 * Reads a big-endian `f64`.
489 *
490 * `f64`s are 8 byte, IEEE754 double-precision floating point numbers.
491 *
492 * # Examples
493 *
494 * None right now.
495 */
496 fn read_be_f64(&self) -> f64;
497
498 /**
499 * Reads a big-endian `f32`.
500 *
501 * `f32`s are 4 byte, IEEE754 single-precision floating point numbers.
502 *
503 * # Examples
504 *
505 * None right now.
506 */
507 fn read_be_f32(&self) -> f32;
508
509 /**
510 * Reads a little-endian `u64`.
511 *
512 * `u64`s are 8 bytes long.
513 *
514 * # Examples
515 *
516 * None right now.
517 */
518 fn read_le_u64(&self) -> u64;
519
520 /**
521 * Reads a little-endian `u32`.
522 *
523 * `u32`s are 4 bytes long.
524 *
525 * # Examples
526 *
527 * None right now.
528 */
529 fn read_le_u32(&self) -> u32;
530
531 /**
532 * Reads a little-endian `u16`.
533 *
534 * `u16`s are 2 bytes long.
535 *
536 * # Examples
537 *
538 * None right now.
539 */
540 fn read_le_u16(&self) -> u16;
541
542 /**
543 * Reads a little-endian `i64`.
544 *
545 * `i64`s are 8 bytes long.
546 *
547 * # Examples
548 *
549 * None right now.
550 */
551 fn read_le_i64(&self) -> i64;
552
553 /**
554 * Reads a little-endian `i32`.
555 *
556 * `i32`s are 4 bytes long.
557 *
558 * # Examples
559 *
560 * None right now.
561 */
562 fn read_le_i32(&self) -> i32;
563
564 /**
565 * Reads a little-endian `i16`.
566 *
567 * `i16`s are 2 bytes long.
568 *
569 * # Examples
570 *
571 * None right now.
572 */
573 fn read_le_i16(&self) -> i16;
574
575 /**
576 * Reads a little-endian `f64`.
577 *
578 * `f64`s are 8 byte, IEEE754 double-precision floating point numbers.
579 *
580 * # Examples
581 *
582 * None right now.
583 */
584 fn read_le_f64(&self) -> f64;
585
586 /**
587 * Reads a little-endian `f32`.
588 *
589 * `f32`s are 4 byte, IEEE754 single-precision floating point numbers.
590 *
591 * # Examples
592 *
593 * None right now.
594 */
595 fn read_le_f32(&self) -> f32;
596
597 /**
598 * Read a u8.
599 *
600 * `u8`s are 1 byte.
601 *
602 * # Examples
603 *
604 * None right now.
605 */
606 fn read_u8(&self) -> u8;
607
608 /**
609 * Read an i8.
610 *
611 * `i8`s are 1 byte.
612 *
613 * # Examples
614 *
615 * None right now.
616 */
617 fn read_i8(&self) -> i8;
618 }
619
620 impl<T:Reader> ReaderUtil for T {
621
622 fn read_bytes(&self, len: uint) -> ~[u8] {
623 let mut bytes = vec::with_capacity(len);
624 unsafe { vec::raw::set_len(&mut bytes, len); }
625
626 let count = self.read(bytes, len);
627
628 unsafe { vec::raw::set_len(&mut bytes, count); }
629 bytes
630 }
631
632 fn read_until(&self, c: u8, include: bool) -> ~str {
633 let mut bytes = ~[];
634 loop {
635 let ch = self.read_byte();
636 if ch == -1 || ch == c as int {
637 if include && ch == c as int {
638 bytes.push(ch as u8);
639 }
640 break;
641 }
642 bytes.push(ch as u8);
643 }
644 str::from_utf8(bytes)
645 }
646
647 fn read_line(&self) -> ~str {
648 self.read_until('\n' as u8, false)
649 }
650
651 fn read_chars(&self, n: uint) -> ~[char] {
652 // returns the (consumed offset, n_req), appends characters to &chars
653 fn chars_from_utf8<T:Reader>(bytes: &~[u8], chars: &mut ~[char])
654 -> (uint, uint) {
655 let mut i = 0;
656 let bytes_len = bytes.len();
657 while i < bytes_len {
658 let b0 = bytes[i];
659 let w = str::utf8_char_width(b0);
660 let end = i + w;
661 i += 1;
662 assert!((w > 0));
663 if w == 1 {
664 unsafe {
665 chars.push(transmute(b0 as u32));
666 }
667 continue;
668 }
669 // can't satisfy this char with the existing data
670 if end > bytes_len {
671 return (i - 1, end - bytes_len);
672 }
673 let mut val = 0;
674 while i < end {
675 let next = bytes[i] as int;
676 i += 1;
677 assert!((next > -1));
678 assert_eq!(next & 192, 128);
679 val <<= 6;
680 val += (next & 63) as uint;
681 }
682 // See str::StrSlice::char_at
683 val += ((b0 << ((w + 1) as u8)) as uint)
684 << (w - 1) * 6 - w - 1u;
685 unsafe {
686 chars.push(transmute(val as u32));
687 }
688 }
689 return (i, 0);
690 }
691 let mut bytes = ~[];
692 let mut chars = ~[];
693 // might need more bytes, but reading n will never over-read
694 let mut nbread = n;
695 while nbread > 0 {
696 let data = self.read_bytes(nbread);
697 if data.is_empty() {
698 // eof - FIXME (#2004): should we do something if
699 // we're split in a unicode char?
700 break;
701 }
702 bytes.push_all(data);
703 let (offset, nbreq) = chars_from_utf8::<T>(&bytes, &mut chars);
704 let ncreq = n - chars.len();
705 // again we either know we need a certain number of bytes
706 // to complete a character, or we make sure we don't
707 // over-read by reading 1-byte per char needed
708 nbread = if ncreq > nbreq { ncreq } else { nbreq };
709 if nbread > 0 {
710 bytes = bytes.slice(offset, bytes.len()).to_owned();
711 }
712 }
713 chars
714 }
715
716 fn read_char(&self) -> char {
717 let c = self.read_chars(1);
718 if c.len() == 0 {
719 return unsafe { transmute(-1u32) }; // FIXME: #8971: unsound
720 }
721 assert_eq!(c.len(), 1);
722 return c[0];
723 }
724
725 fn read_c_str(&self) -> ~str {
726 self.read_until(0u8, false)
727 }
728
729 fn read_whole_stream(&self) -> ~[u8] {
730 let mut bytes: ~[u8] = ~[];
731 while !self.eof() { bytes.push_all(self.read_bytes(2048u)); }
732 bytes
733 }
734
735 fn each_byte(&self, it: &fn(int) -> bool) -> bool {
736 loop {
737 match self.read_byte() {
738 -1 => break,
739 ch => if !it(ch) { return false; }
740 }
741 }
742 return true;
743 }
744
745 fn each_char(&self, it: &fn(char) -> bool) -> bool {
746 // FIXME: #8971: unsound
747 let eof: char = unsafe { transmute(-1u32) };
748 loop {
749 match self.read_char() {
750 c if c == eof => break,
751 ch => if !it(ch) { return false; }
752 }
753 }
754 return true;
755 }
756
757 fn each_line(&self, it: &fn(s: &str) -> bool) -> bool {
758 while !self.eof() {
759 // include the \n, so that we can distinguish an entirely empty
760 // line read after "...\n", and the trailing empty line in
761 // "...\n\n".
762 let mut line = self.read_until('\n' as u8, true);
763
764 // blank line at the end of the reader is ignored
765 if self.eof() && line.is_empty() { break; }
766
767 // trim the \n, so that each_line is consistent with read_line
768 let n = line.len();
769 if line[n-1] == '\n' as u8 {
770 unsafe { str::raw::set_len(&mut line, n-1); }
771 }
772
773 if !it(line) { return false; }
774 }
775 return true;
776 }
777
778 fn read_lines(&self) -> ~[~str] {
779 do vec::build(None) |push| {
780 do self.each_line |line| {
781 push(line.to_owned());
782 true
783 };
784 }
785 }
786
787 // FIXME int reading methods need to deal with eof - issue #2004
788
789 fn read_le_uint_n(&self, nbytes: uint) -> u64 {
790 assert!(nbytes > 0 && nbytes <= 8);
791
792 let mut val = 0u64;
793 let mut pos = 0;
794 let mut i = nbytes;
795 while i > 0 {
796 val += (self.read_u8() as u64) << pos;
797 pos += 8;
798 i -= 1;
799 }
800 val
801 }
802
803 fn read_le_int_n(&self, nbytes: uint) -> i64 {
804 extend_sign(self.read_le_uint_n(nbytes), nbytes)
805 }
806
807 fn read_be_uint_n(&self, nbytes: uint) -> u64 {
808 assert!(nbytes > 0 && nbytes <= 8);
809
810 let mut val = 0u64;
811 let mut i = nbytes;
812 while i > 0 {
813 i -= 1;
814 val += (self.read_u8() as u64) << i * 8;
815 }
816 val
817 }
818
819 fn read_be_int_n(&self, nbytes: uint) -> i64 {
820 extend_sign(self.read_be_uint_n(nbytes), nbytes)
821 }
822
823 fn read_le_uint(&self) -> uint {
824 self.read_le_uint_n(uint::bytes) as uint
825 }
826
827 fn read_le_int(&self) -> int {
828 self.read_le_int_n(int::bytes) as int
829 }
830
831 fn read_be_uint(&self) -> uint {
832 self.read_be_uint_n(uint::bytes) as uint
833 }
834
835 fn read_be_int(&self) -> int {
836 self.read_be_int_n(int::bytes) as int
837 }
838
839 fn read_be_u64(&self) -> u64 {
840 self.read_be_uint_n(8) as u64
841 }
842
843 fn read_be_u32(&self) -> u32 {
844 self.read_be_uint_n(4) as u32
845 }
846
847 fn read_be_u16(&self) -> u16 {
848 self.read_be_uint_n(2) as u16
849 }
850
851 fn read_be_i64(&self) -> i64 {
852 self.read_be_int_n(8) as i64
853 }
854
855 fn read_be_i32(&self) -> i32 {
856 self.read_be_int_n(4) as i32
857 }
858
859 fn read_be_i16(&self) -> i16 {
860 self.read_be_int_n(2) as i16
861 }
862
863 fn read_be_f64(&self) -> f64 {
864 unsafe {
865 cast::transmute::<u64, f64>(self.read_be_u64())
866 }
867 }
868
869 fn read_be_f32(&self) -> f32 {
870 unsafe {
871 cast::transmute::<u32, f32>(self.read_be_u32())
872 }
873 }
874
875 fn read_le_u64(&self) -> u64 {
876 self.read_le_uint_n(8) as u64
877 }
878
879 fn read_le_u32(&self) -> u32 {
880 self.read_le_uint_n(4) as u32
881 }
882
883 fn read_le_u16(&self) -> u16 {
884 self.read_le_uint_n(2) as u16
885 }
886
887 fn read_le_i64(&self) -> i64 {
888 self.read_le_int_n(8) as i64
889 }
890
891 fn read_le_i32(&self) -> i32 {
892 self.read_le_int_n(4) as i32
893 }
894
895 fn read_le_i16(&self) -> i16 {
896 self.read_le_int_n(2) as i16
897 }
898
899 fn read_le_f64(&self) -> f64 {
900 unsafe {
901 cast::transmute::<u64, f64>(self.read_le_u64())
902 }
903 }
904
905 fn read_le_f32(&self) -> f32 {
906 unsafe {
907 cast::transmute::<u32, f32>(self.read_le_u32())
908 }
909 }
910
911 fn read_u8(&self) -> u8 {
912 self.read_byte() as u8
913 }
914
915 fn read_i8(&self) -> i8 {
916 self.read_byte() as i8
917 }
918 }
919
920 fn extend_sign(val: u64, nbytes: uint) -> i64 {
921 let shift = (8 - nbytes) * 8;
922 (val << shift) as i64 >> shift
923 }
924
925 // Reader implementations
926
927 fn convert_whence(whence: SeekStyle) -> i32 {
928 return match whence {
929 SeekSet => 0i32,
930 SeekCur => 1i32,
931 SeekEnd => 2i32
932 };
933 }
934
935 impl Reader for *libc::FILE {
936 fn read(&self, bytes: &mut [u8], len: uint) -> uint {
937 #[fixed_stack_segment]; #[inline(never)];
938
939 unsafe {
940 do bytes.as_mut_buf |buf_p, buf_len| {
941 assert!(buf_len >= len);
942
943 let count = libc::fread(buf_p as *mut c_void, 1u as size_t,
944 len as size_t, *self) as uint;
945 if count < len {
946 match libc::ferror(*self) {
947 0 => (),
948 _ => {
949 error2!("error reading buffer: {}", os::last_os_error());
950 fail2!();
951 }
952 }
953 }
954
955 count
956 }
957 }
958 }
959 fn read_byte(&self) -> int {
960 #[fixed_stack_segment]; #[inline(never)];
961
962 unsafe {
963 libc::fgetc(*self) as int
964 }
965 }
966 fn eof(&self) -> bool {
967 #[fixed_stack_segment]; #[inline(never)];
968
969 unsafe {
970 return libc::feof(*self) != 0 as c_int;
971 }
972 }
973 fn seek(&self, offset: int, whence: SeekStyle) {
974 #[fixed_stack_segment]; #[inline(never)];
975
976 unsafe {
977 assert!(libc::fseek(*self,
978 offset as libc::c_long,
979 convert_whence(whence)) == 0 as c_int);
980 }
981 }
982 fn tell(&self) -> uint {
983 #[fixed_stack_segment]; #[inline(never)];
984
985 unsafe {
986 return libc::ftell(*self) as uint;
987 }
988 }
989 }
990
991 struct Wrapper<T, C> {
992 base: T,
993 cleanup: C,
994 }
995
996 // A forwarding impl of reader that also holds on to a resource for the
997 // duration of its lifetime.
998 // FIXME there really should be a better way to do this // #2004
999 impl<R:Reader,C> Reader for Wrapper<R, C> {
1000 fn read(&self, bytes: &mut [u8], len: uint) -> uint {
1001 self.base.read(bytes, len)
1002 }
1003 fn read_byte(&self) -> int { self.base.read_byte() }
1004 fn eof(&self) -> bool { self.base.eof() }
1005 fn seek(&self, off: int, whence: SeekStyle) {
1006 self.base.seek(off, whence)
1007 }
1008 fn tell(&self) -> uint { self.base.tell() }
1009 }
1010
1011 pub struct FILERes {
1012 f: *libc::FILE,
1013 }
1014
1015 impl FILERes {
1016 pub fn new(f: *libc::FILE) -> FILERes {
1017 FILERes { f: f }
1018 }
1019 }
1020
1021 impl Drop for FILERes {
1022 fn drop(&mut self) {
1023 #[fixed_stack_segment]; #[inline(never)];
1024
1025 unsafe {
1026 libc::fclose(self.f);
1027 }
1028 }
1029 }
1030
1031 pub fn FILE_reader(f: *libc::FILE, cleanup: bool) -> @Reader {
1032 if cleanup {
1033 @Wrapper { base: f, cleanup: FILERes::new(f) } as @Reader
1034 } else {
1035 @f as @Reader
1036 }
1037 }
1038
1039 // FIXME (#2004): this should either be an trait-less impl, a set of
1040 // top-level functions that take a reader, or a set of default methods on
1041 // reader (which can then be called reader)
1042
1043 /**
1044 * Gives a `Reader` that allows you to read values from standard input.
1045 *
1046 * # Example
1047 *
1048 * ```rust
1049 * let stdin = std::io::stdin();
1050 * let line = stdin.read_line();
1051 * std::io::print(line);
1052 * ```
1053 */
1054 pub fn stdin() -> @Reader {
1055 #[fixed_stack_segment]; #[inline(never)];
1056
1057 unsafe {
1058 @rustrt::rust_get_stdin() as @Reader
1059 }
1060 }
1061
1062 pub fn file_reader(path: &Path) -> Result<@Reader, ~str> {
1063 #[fixed_stack_segment]; #[inline(never)];
1064
1065 let f = do path.with_c_str |pathbuf| {
1066 do "rb".with_c_str |modebuf| {
1067 unsafe { libc::fopen(pathbuf, modebuf as *libc::c_char) }
1068 }
1069 };
1070
1071 if f as uint == 0u {
1072 do path.display().with_str |p| {
1073 Err(~"error opening " + p)
1074 }
1075 } else {
1076 Ok(FILE_reader(f, true))
1077 }
1078 }
1079
1080
1081 // Byte readers
1082 pub struct BytesReader {
1083 // FIXME(#5723) see other FIXME below
1084 // FIXME(#7268) this should also be parameterized over <'self>
1085 bytes: &'static [u8],
1086 pos: @mut uint
1087 }
1088
1089 impl Reader for BytesReader {
1090 fn read(&self, bytes: &mut [u8], len: uint) -> uint {
1091 let count = num::min(len, self.bytes.len() - *self.pos);
1092
1093 let view = self.bytes.slice(*self.pos, self.bytes.len());
1094 vec::bytes::copy_memory(bytes, view, count);
1095
1096 *self.pos += count;
1097
1098 count
1099 }
1100
1101 fn read_byte(&self) -> int {
1102 if *self.pos == self.bytes.len() {
1103 return -1;
1104 }
1105
1106 let b = self.bytes[*self.pos];
1107 *self.pos += 1u;
1108 b as int
1109 }
1110
1111 fn eof(&self) -> bool {
1112 *self.pos == self.bytes.len()
1113 }
1114
1115 fn seek(&self, offset: int, whence: SeekStyle) {
1116 let pos = *self.pos;
1117 *self.pos = seek_in_buf(offset, pos, self.bytes.len(), whence);
1118 }
1119
1120 fn tell(&self) -> uint {
1121 *self.pos
1122 }
1123 }
1124
1125 pub fn with_bytes_reader<T>(bytes: &[u8], f: &fn(@Reader) -> T) -> T {
1126 // XXX XXX XXX this is glaringly unsound
1127 // FIXME(#5723) Use a &Reader for the callback's argument. Should be:
1128 // fn with_bytes_reader<'r, T>(bytes: &'r [u8], f: &fn(&'r Reader) -> T) -> T
1129 let bytes: &'static [u8] = unsafe { cast::transmute(bytes) };
1130 f(@BytesReader {
1131 bytes: bytes,
1132 pos: @mut 0
1133 } as @Reader)
1134 }
1135
1136 pub fn with_str_reader<T>(s: &str, f: &fn(@Reader) -> T) -> T {
1137 // FIXME(#5723): As above.
1138 with_bytes_reader(s.as_bytes(), f)
1139 }
1140
1141 // Writing
1142 pub enum FileFlag { Append, Create, Truncate, NoFlag, }
1143
1144 // What type of writer are we?
1145 #[deriving(Eq)]
1146 pub enum WriterType { Screen, File }
1147
1148 // FIXME (#2004): Seekable really should be orthogonal.
1149 // FIXME (#2004): eventually u64
1150 /// The raw underlying writer trait. All writers must implement this.
1151 pub trait Writer {
1152
1153 /// Write all of the given bytes.
1154 fn write(&self, v: &[u8]);
1155
1156 /// Move the current position within the stream. The second parameter
1157 /// determines the position that the first parameter is relative to.
1158 fn seek(&self, int, SeekStyle);
1159
1160 /// Return the current position within the stream.
1161 fn tell(&self) -> uint;
1162
1163 /// Flush the output buffer for this stream (if there is one).
1164 fn flush(&self) -> int;
1165
1166 /// Determine if this Writer is writing to a file or not.
1167 fn get_type(&self) -> WriterType;
1168 }
1169
1170 impl Writer for @Writer {
1171 fn write(&self, v: &[u8]) { self.write(v) }
1172 fn seek(&self, a: int, b: SeekStyle) { self.seek(a, b) }
1173 fn tell(&self) -> uint { self.tell() }
1174 fn flush(&self) -> int { self.flush() }
1175 fn get_type(&self) -> WriterType { self.get_type() }
1176 }
1177
1178 impl<W:Writer,C> Writer for Wrapper<W, C> {
1179 fn write(&self, bs: &[u8]) { self.base.write(bs); }
1180 fn seek(&self, off: int, style: SeekStyle) { self.base.seek(off, style); }
1181 fn tell(&self) -> uint { self.base.tell() }
1182 fn flush(&self) -> int { self.base.flush() }
1183 fn get_type(&self) -> WriterType { File }
1184 }
1185
1186 impl Writer for *libc::FILE {
1187 fn write(&self, v: &[u8]) {
1188 #[fixed_stack_segment]; #[inline(never)];
1189
1190 unsafe {
1191 do v.as_imm_buf |vbuf, len| {
1192 let nout = libc::fwrite(vbuf as *c_void,
1193 1,
1194 len as size_t,
1195 *self);
1196 if nout != len as size_t {
1197 error2!("error writing buffer: {}", os::last_os_error());
1198 fail2!();
1199 }
1200 }
1201 }
1202 }
1203 fn seek(&self, offset: int, whence: SeekStyle) {
1204 #[fixed_stack_segment]; #[inline(never)];
1205
1206 unsafe {
1207 assert!(libc::fseek(*self,
1208 offset as libc::c_long,
1209 convert_whence(whence)) == 0 as c_int);
1210 }
1211 }
1212 fn tell(&self) -> uint {
1213 #[fixed_stack_segment]; #[inline(never)];
1214
1215 unsafe {
1216 libc::ftell(*self) as uint
1217 }
1218 }
1219 fn flush(&self) -> int {
1220 #[fixed_stack_segment]; #[inline(never)];
1221
1222 unsafe {
1223 libc::fflush(*self) as int
1224 }
1225 }
1226 fn get_type(&self) -> WriterType {
1227 #[fixed_stack_segment]; #[inline(never)];
1228
1229 unsafe {
1230 let fd = libc::fileno(*self);
1231 if libc::isatty(fd) == 0 { File }
1232 else { Screen }
1233 }
1234 }
1235 }
1236
1237 impl Writer for fd_t {
1238 fn write(&self, v: &[u8]) {
1239 #[fixed_stack_segment]; #[inline(never)];
1240
1241 #[cfg(windows)]
1242 type IoSize = libc::c_uint;
1243 #[cfg(windows)]
1244 type IoRet = c_int;
1245
1246 #[cfg(unix)]
1247 type IoSize = size_t;
1248 #[cfg(unix)]
1249 type IoRet = libc::ssize_t;
1250
1251 unsafe {
1252 let mut count = 0u;
1253 do v.as_imm_buf |vbuf, len| {
1254 while count < len {
1255 let vb = ptr::offset(vbuf, count as int) as *c_void;
1256 let nout = libc::write(*self, vb, len as IoSize);
1257 if nout < 0 as IoRet {
1258 error2!("error writing buffer: {}", os::last_os_error());
1259 fail2!();
1260 }
1261 count += nout as uint;
1262 }
1263 }
1264 }
1265 }
1266 fn seek(&self, _offset: int, _whence: SeekStyle) {
1267 error2!("need 64-bit foreign calls for seek, sorry");
1268 fail2!();
1269 }
1270 fn tell(&self) -> uint {
1271 error2!("need 64-bit foreign calls for tell, sorry");
1272 fail2!();
1273 }
1274 fn flush(&self) -> int { 0 }
1275 fn get_type(&self) -> WriterType {
1276 #[fixed_stack_segment]; #[inline(never)];
1277
1278 unsafe {
1279 if libc::isatty(*self) == 0 { File } else { Screen }
1280 }
1281 }
1282 }
1283
1284 pub struct FdRes {
1285 fd: fd_t,
1286 }
1287
1288 impl FdRes {
1289 pub fn new(fd: fd_t) -> FdRes {
1290 FdRes { fd: fd }
1291 }
1292 }
1293
1294 impl Drop for FdRes {
1295 fn drop(&mut self) {
1296 #[fixed_stack_segment]; #[inline(never)];
1297
1298 unsafe {
1299 libc::close(self.fd);
1300 }
1301 }
1302 }
1303
1304 pub fn fd_writer(fd: fd_t, cleanup: bool) -> @Writer {
1305 if cleanup {
1306 @Wrapper { base: fd, cleanup: FdRes::new(fd) } as @Writer
1307 } else {
1308 @fd as @Writer
1309 }
1310 }
1311
1312
1313 pub fn mk_file_writer(path: &Path, flags: &[FileFlag])
1314 -> Result<@Writer, ~str> {
1315 #[fixed_stack_segment]; #[inline(never)];
1316
1317 #[cfg(windows)]
1318 fn wb() -> c_int {
1319 (O_WRONLY | libc::consts::os::extra::O_BINARY) as c_int
1320 }
1321
1322 #[cfg(unix)]
1323 fn wb() -> c_int { O_WRONLY as c_int }
1324
1325 let mut fflags: c_int = wb();
1326 for f in flags.iter() {
1327 match *f {
1328 Append => fflags |= O_APPEND as c_int,
1329 Create => fflags |= O_CREAT as c_int,
1330 Truncate => fflags |= O_TRUNC as c_int,
1331 NoFlag => ()
1332 }
1333 }
1334 let fd = unsafe {
1335 do path.with_c_str |pathbuf| {
1336 libc::open(pathbuf, fflags, (S_IRUSR | S_IWUSR) as c_int)
1337 }
1338 };
1339 if fd < (0 as c_int) {
1340 Err(format!("error opening {}: {}", path.display(), os::last_os_error()))
1341 } else {
1342 Ok(fd_writer(fd, true))
1343 }
1344 }
1345
1346 pub fn u64_to_le_bytes<T>(n: u64, size: uint,
1347 f: &fn(v: &[u8]) -> T) -> T {
1348 assert!(size <= 8u);
1349 match size {
1350 1u => f(&[n as u8]),
1351 2u => f(&[n as u8,
1352 (n >> 8) as u8]),
1353 4u => f(&[n as u8,
1354 (n >> 8) as u8,
1355 (n >> 16) as u8,
1356 (n >> 24) as u8]),
1357 8u => f(&[n as u8,
1358 (n >> 8) as u8,
1359 (n >> 16) as u8,
1360 (n >> 24) as u8,
1361 (n >> 32) as u8,
1362 (n >> 40) as u8,
1363 (n >> 48) as u8,
1364 (n >> 56) as u8]),
1365 _ => {
1366
1367 let mut bytes: ~[u8] = ~[];
1368 let mut i = size;
1369 let mut n = n;
1370 while i > 0u {
1371 bytes.push((n & 255_u64) as u8);
1372 n >>= 8_u64;
1373 i -= 1u;
1374 }
1375 f(bytes)
1376 }
1377 }
1378 }
1379
1380 pub fn u64_to_be_bytes<T>(n: u64, size: uint,
1381 f: &fn(v: &[u8]) -> T) -> T {
1382 assert!(size <= 8u);
1383 match size {
1384 1u => f(&[n as u8]),
1385 2u => f(&[(n >> 8) as u8,
1386 n as u8]),
1387 4u => f(&[(n >> 24) as u8,
1388 (n >> 16) as u8,
1389 (n >> 8) as u8,
1390 n as u8]),
1391 8u => f(&[(n >> 56) as u8,
1392 (n >> 48) as u8,
1393 (n >> 40) as u8,
1394 (n >> 32) as u8,
1395 (n >> 24) as u8,
1396 (n >> 16) as u8,
1397 (n >> 8) as u8,
1398 n as u8]),
1399 _ => {
1400 let mut bytes: ~[u8] = ~[];
1401 let mut i = size;
1402 while i > 0u {
1403 let shift = ((i - 1u) * 8u) as u64;
1404 bytes.push((n >> shift) as u8);
1405 i -= 1u;
1406 }
1407 f(bytes)
1408 }
1409 }
1410 }
1411
1412 pub fn u64_from_be_bytes(data: &[u8],
1413 start: uint,
1414 size: uint)
1415 -> u64 {
1416 let mut sz = size;
1417 assert!((sz <= 8u));
1418 let mut val = 0_u64;
1419 let mut pos = start;
1420 while sz > 0u {
1421 sz -= 1u;
1422 val += (data[pos] as u64) << ((sz * 8u) as u64);
1423 pos += 1u;
1424 }
1425 return val;
1426 }
1427
1428 // FIXME: #3048 combine trait+impl (or just move these to
1429 // default methods on writer)
1430 /// Generic utility functions defined on writers.
1431 pub trait WriterUtil {
1432
1433 /// Write a single utf-8 encoded char.
1434 fn write_char(&self, ch: char);
1435
1436 /// Write every char in the given str, encoded as utf-8.
1437 fn write_str(&self, s: &str);
1438
1439 /// Write the given str, as utf-8, followed by '\n'.
1440 fn write_line(&self, s: &str);
1441
1442 /// Write the result of passing n through `int::to_str_bytes`.
1443 fn write_int(&self, n: int);
1444
1445 /// Write the result of passing n through `uint::to_str_bytes`.
1446 fn write_uint(&self, n: uint);
1447
1448 /// Write a little-endian uint (number of bytes depends on system).
1449 fn write_le_uint(&self, n: uint);
1450
1451 /// Write a little-endian int (number of bytes depends on system).
1452 fn write_le_int(&self, n: int);
1453
1454 /// Write a big-endian uint (number of bytes depends on system).
1455 fn write_be_uint(&self, n: uint);
1456
1457 /// Write a big-endian int (number of bytes depends on system).
1458 fn write_be_int(&self, n: int);
1459
1460 /// Write a big-endian u64 (8 bytes).
1461 fn write_be_u64(&self, n: u64);
1462
1463 /// Write a big-endian u32 (4 bytes).
1464 fn write_be_u32(&self, n: u32);
1465
1466 /// Write a big-endian u16 (2 bytes).
1467 fn write_be_u16(&self, n: u16);
1468
1469 /// Write a big-endian i64 (8 bytes).
1470 fn write_be_i64(&self, n: i64);
1471
1472 /// Write a big-endian i32 (4 bytes).
1473 fn write_be_i32(&self, n: i32);
1474
1475 /// Write a big-endian i16 (2 bytes).
1476 fn write_be_i16(&self, n: i16);
1477
1478 /// Write a big-endian IEEE754 double-precision floating-point (8 bytes).
1479 fn write_be_f64(&self, f: f64);
1480
1481 /// Write a big-endian IEEE754 single-precision floating-point (4 bytes).
1482 fn write_be_f32(&self, f: f32);
1483
1484 /// Write a little-endian u64 (8 bytes).
1485 fn write_le_u64(&self, n: u64);
1486
1487 /// Write a little-endian u32 (4 bytes).
1488 fn write_le_u32(&self, n: u32);
1489
1490 /// Write a little-endian u16 (2 bytes).
1491 fn write_le_u16(&self, n: u16);
1492
1493 /// Write a little-endian i64 (8 bytes).
1494 fn write_le_i64(&self, n: i64);
1495
1496 /// Write a little-endian i32 (4 bytes).
1497 fn write_le_i32(&self, n: i32);
1498
1499 /// Write a little-endian i16 (2 bytes).
1500 fn write_le_i16(&self, n: i16);
1501
1502 /// Write a little-endian IEEE754 double-precision floating-point
1503 /// (8 bytes).
1504 fn write_le_f64(&self, f: f64);
1505
1506 /// Write a little-endian IEEE754 single-precision floating-point
1507 /// (4 bytes).
1508 fn write_le_f32(&self, f: f32);
1509
1510 /// Write a u8 (1 byte).
1511 fn write_u8(&self, n: u8);
1512
1513 /// Write a i8 (1 byte).
1514 fn write_i8(&self, n: i8);
1515 }
1516
1517 impl<T:Writer> WriterUtil for T {
1518 fn write_char(&self, ch: char) {
1519 if (ch as uint) < 128u {
1520 self.write(&[ch as u8]);
1521 } else {
1522 self.write_str(str::from_char(ch));
1523 }
1524 }
1525 fn write_str(&self, s: &str) { self.write(s.as_bytes()) }
1526 fn write_line(&self, s: &str) {
1527 self.write_str(s);
1528 self.write_str(&"\n");
1529 }
1530 fn write_int(&self, n: int) {
1531 int::to_str_bytes(n, 10u, |bytes| self.write(bytes))
1532 }
1533 fn write_uint(&self, n: uint) {
1534 uint::to_str_bytes(n, 10u, |bytes| self.write(bytes))
1535 }
1536 fn write_le_uint(&self, n: uint) {
1537 u64_to_le_bytes(n as u64, uint::bytes, |v| self.write(v))
1538 }
1539 fn write_le_int(&self, n: int) {
1540 u64_to_le_bytes(n as u64, int::bytes, |v| self.write(v))
1541 }
1542 fn write_be_uint(&self, n: uint) {
1543 u64_to_be_bytes(n as u64, uint::bytes, |v| self.write(v))
1544 }
1545 fn write_be_int(&self, n: int) {
1546 u64_to_be_bytes(n as u64, int::bytes, |v| self.write(v))
1547 }
1548 fn write_be_u64(&self, n: u64) {
1549 u64_to_be_bytes(n, 8u, |v| self.write(v))
1550 }
1551 fn write_be_u32(&self, n: u32) {
1552 u64_to_be_bytes(n as u64, 4u, |v| self.write(v))
1553 }
1554 fn write_be_u16(&self, n: u16) {
1555 u64_to_be_bytes(n as u64, 2u, |v| self.write(v))
1556 }
1557 fn write_be_i64(&self, n: i64) {
1558 u64_to_be_bytes(n as u64, 8u, |v| self.write(v))
1559 }
1560 fn write_be_i32(&self, n: i32) {
1561 u64_to_be_bytes(n as u64, 4u, |v| self.write(v))
1562 }
1563 fn write_be_i16(&self, n: i16) {
1564 u64_to_be_bytes(n as u64, 2u, |v| self.write(v))
1565 }
1566 fn write_be_f64(&self, f:f64) {
1567 unsafe {
1568 self.write_be_u64(cast::transmute(f))
1569 }
1570 }
1571 fn write_be_f32(&self, f:f32) {
1572 unsafe {
1573 self.write_be_u32(cast::transmute(f))
1574 }
1575 }
1576 fn write_le_u64(&self, n: u64) {
1577 u64_to_le_bytes(n, 8u, |v| self.write(v))
1578 }
1579 fn write_le_u32(&self, n: u32) {
1580 u64_to_le_bytes(n as u64, 4u, |v| self.write(v))
1581 }
1582 fn write_le_u16(&self, n: u16) {
1583 u64_to_le_bytes(n as u64, 2u, |v| self.write(v))
1584 }
1585 fn write_le_i64(&self, n: i64) {
1586 u64_to_le_bytes(n as u64, 8u, |v| self.write(v))
1587 }
1588 fn write_le_i32(&self, n: i32) {
1589 u64_to_le_bytes(n as u64, 4u, |v| self.write(v))
1590 }
1591 fn write_le_i16(&self, n: i16) {
1592 u64_to_le_bytes(n as u64, 2u, |v| self.write(v))
1593 }
1594 fn write_le_f64(&self, f:f64) {
1595 unsafe {
1596 self.write_le_u64(cast::transmute(f))
1597 }
1598 }
1599 fn write_le_f32(&self, f:f32) {
1600 unsafe {
1601 self.write_le_u32(cast::transmute(f))
1602 }
1603 }
1604
1605 fn write_u8(&self, n: u8) { self.write([n]) }
1606 fn write_i8(&self, n: i8) { self.write([n as u8]) }
1607
1608 }
1609
1610 pub fn file_writer(path: &Path, flags: &[FileFlag]) -> Result<@Writer, ~str> {
1611 mk_file_writer(path, flags).and_then(|w| Ok(w))
1612 }
1613
1614 // FIXME (#2004) it would be great if this could be a const
1615 // FIXME (#2004) why are these different from the way stdin() is
1616 // implemented?
1617
1618
1619 /**
1620 * Gives a `Writer` which allows you to write to the standard output.
1621 *
1622 * # Example
1623 *
1624 * ```rust
1625 * let stdout = std::io::stdout();
1626 * stdout.write_str("hello\n");
1627 * ```
1628 */
1629 pub fn stdout() -> @Writer { fd_writer(libc::STDOUT_FILENO as c_int, false) }
1630
1631 /**
1632 * Gives a `Writer` which allows you to write to standard error.
1633 *
1634 * # Example
1635 *
1636 * ```rust
1637 * let stderr = std::io::stderr();
1638 * stderr.write_str("hello\n");
1639 * ```
1640 */
1641 pub fn stderr() -> @Writer { fd_writer(libc::STDERR_FILENO as c_int, false) }
1642
1643 /**
1644 * Prints a string to standard output.
1645 *
1646 * This string will not have an implicit newline at the end. If you want
1647 * an implicit newline, please see `println`.
1648 *
1649 * # Example
1650 *
1651 * ```rust
1652 * // print is imported into the prelude, and so is always available.
1653 * print("hello");
1654 * ```
1655 */
1656 pub fn print(s: &str) {
1657 stdout().write_str(s);
1658 }
1659
1660 /**
1661 * Prints a string to standard output, followed by a newline.
1662 *
1663 * If you do not want an implicit newline, please see `print`.
1664 *
1665 * # Example
1666 *
1667 * ```rust
1668 * // println is imported into the prelude, and so is always available.
1669 * println("hello");
1670 * ```
1671 */
1672 pub fn println(s: &str) {
1673 stdout().write_line(s);
1674 }
1675
1676 pub struct BytesWriter {
1677 bytes: @mut ~[u8],
1678 pos: @mut uint,
1679 }
1680
1681 impl BytesWriter {
1682 pub fn new() -> BytesWriter {
1683 BytesWriter {
1684 bytes: @mut ~[],
1685 pos: @mut 0
1686 }
1687 }
1688 }
1689
1690 impl Writer for BytesWriter {
1691 fn write(&self, v: &[u8]) {
1692 let v_len = v.len();
1693
1694 let bytes = &mut *self.bytes;
1695 let count = num::max(bytes.len(), *self.pos + v_len);
1696 bytes.reserve(count);
1697
1698 unsafe {
1699 vec::raw::set_len(bytes, count);
1700
1701 let view = bytes.mut_slice(*self.pos, count);
1702 vec::bytes::copy_memory(view, v, v_len);
1703 }
1704
1705 *self.pos += v_len;
1706 }
1707
1708 fn seek(&self, offset: int, whence: SeekStyle) {
1709 let pos = *self.pos;
1710 let len = self.bytes.len();
1711 *self.pos = seek_in_buf(offset, pos, len, whence);
1712 }
1713
1714 fn tell(&self) -> uint {
1715 *self.pos
1716 }
1717
1718 fn flush(&self) -> int {
1719 0
1720 }
1721
1722 fn get_type(&self) -> WriterType {
1723 File
1724 }
1725 }
1726
1727 pub fn with_bytes_writer(f: &fn(@Writer)) -> ~[u8] {
1728 let wr = @BytesWriter::new();
1729 f(wr as @Writer);
1730 let @BytesWriter { bytes, _ } = wr;
1731 (*bytes).clone()
1732 }
1733
1734 pub fn with_str_writer(f: &fn(@Writer)) -> ~str {
1735 str::from_utf8(with_bytes_writer(f))
1736 }
1737
1738 // Utility functions
1739 pub fn seek_in_buf(offset: int, pos: uint, len: uint, whence: SeekStyle) ->
1740 uint {
1741 let mut bpos = pos as int;
1742 let blen = len as int;
1743 match whence {
1744 SeekSet => bpos = offset,
1745 SeekCur => bpos += offset,
1746 SeekEnd => bpos = blen + offset
1747 }
1748 if bpos < 0 { bpos = 0; } else if bpos > blen { bpos = blen; }
1749 return bpos as uint;
1750 }
1751
1752 pub fn read_whole_file_str(file: &Path) -> Result<~str, ~str> {
1753 do read_whole_file(file).and_then |bytes| {
1754 if str::is_utf8(bytes) {
1755 Ok(str::from_utf8(bytes))
1756 } else {
1757 Err(file.display().to_str() + " is not UTF-8")
1758 }
1759 }
1760 }
1761
1762 // FIXME (#2004): implement this in a low-level way. Going through the
1763 // abstractions is pointless.
1764 pub fn read_whole_file(file: &Path) -> Result<~[u8], ~str> {
1765 do file_reader(file).and_then |rdr| {
1766 Ok(rdr.read_whole_stream())
1767 }
1768 }
1769
1770 // fsync related
1771
1772 pub mod fsync {
1773 use io::{FILERes, FdRes, fd_t};
1774 use libc;
1775 use ops::Drop;
1776 use option::{None, Option, Some};
1777 use os;
1778
1779 pub enum Level {
1780 // whatever fsync does on that platform
1781 FSync,
1782
1783 // fdatasync on linux, similiar or more on other platforms
1784 FDataSync,
1785
1786 // full fsync
1787 //
1788 // You must additionally sync the parent directory as well!
1789 FullFSync,
1790 }
1791
1792
1793 // Artifacts that need to fsync on destruction
1794 pub struct Res<t> {
1795 arg: Arg<t>,
1796 }
1797
1798 impl <t> Res<t> {
1799 pub fn new(arg: Arg<t>) -> Res<t> {
1800 Res { arg: arg }
1801 }
1802 }
1803
1804 #[unsafe_destructor]
1805 impl<T> Drop for Res<T> {
1806 fn drop(&mut self) {
1807 match self.arg.opt_level {
1808 None => (),
1809 Some(level) => {
1810 // fail hard if not succesful
1811 assert!(((self.arg.fsync_fn)(&self.arg.val, level) != -1));
1812 }
1813 }
1814 }
1815 }
1816
1817 pub struct Arg<t> {
1818 val: t,
1819 opt_level: Option<Level>,
1820 fsync_fn: extern "Rust" fn(f: &t, Level) -> int,
1821 }
1822
1823 // fsync file after executing blk
1824 // FIXME (#2004) find better way to create resources within lifetime of
1825 // outer res
1826 pub fn FILE_res_sync(file: &FILERes,
1827 opt_level: Option<Level>,
1828 blk: &fn(v: Res<*libc::FILE>)) {
1829 blk(Res::new(Arg {
1830 val: file.f,
1831 opt_level: opt_level,
1832 fsync_fn: fsync_FILE,
1833 }));
1834
1835 fn fileno(stream: *libc::FILE) -> libc::c_int {
1836 #[fixed_stack_segment]; #[inline(never)];
1837 unsafe { libc::fileno(stream) }
1838 }
1839
1840 fn fsync_FILE(stream: &*libc::FILE, level: Level) -> int {
1841 fsync_fd(fileno(*stream), level)
1842 }
1843 }
1844
1845 // fsync fd after executing blk
1846 pub fn fd_res_sync(fd: &FdRes, opt_level: Option<Level>,
1847 blk: &fn(v: Res<fd_t>)) {
1848 blk(Res::new(Arg {
1849 val: fd.fd,
1850 opt_level: opt_level,
1851 fsync_fn: fsync_fd_helper,
1852 }));
1853 }
1854
1855 fn fsync_fd(fd: libc::c_int, level: Level) -> int {
1856 #[fixed_stack_segment]; #[inline(never)];
1857
1858 os::fsync_fd(fd, level) as int
1859 }
1860
1861 fn fsync_fd_helper(fd_ptr: &libc::c_int, level: Level) -> int {
1862 fsync_fd(*fd_ptr, level)
1863 }
1864
1865 // Type of objects that may want to fsync
1866 pub trait FSyncable { fn fsync(&self, l: Level) -> int; }
1867
1868 // Call o.fsync after executing blk
1869 pub fn obj_sync(o: @FSyncable, opt_level: Option<Level>,
1870 blk: &fn(v: Res<@FSyncable>)) {
1871 blk(Res::new(Arg {
1872 val: o,
1873 opt_level: opt_level,
1874 fsync_fn: obj_fsync_fn,
1875 }));
1876 }
1877
1878 fn obj_fsync_fn(o: &@FSyncable, level: Level) -> int {
1879 (*o).fsync(level)
1880 }
1881 }
1882
1883 #[cfg(test)]
1884 mod tests {
1885 use prelude::*;
1886 use i32;
1887 use io::{BytesWriter, SeekCur, SeekEnd, SeekSet};
1888 use io;
1889 use path::Path;
1890 use result::{Ok, Err};
1891 use u64;
1892 use vec;
1893 use cast::transmute;
1894
1895 #[test]
1896 fn test_simple() {
1897 let tmpfile = &Path::new("tmp/lib-io-test-simple.tmp");
1898 debug2!("{}", tmpfile.display());
1899 let frood: ~str =
1900 ~"A hoopy frood who really knows where his towel is.";
1901 debug2!("{}", frood.clone());
1902 {
1903 let out = io::file_writer(tmpfile, [io::Create, io::Truncate]).unwrap();
1904 out.write_str(frood);
1905 }
1906 let inp = io::file_reader(tmpfile).unwrap();
1907 let frood2: ~str = inp.read_c_str();
1908 debug2!("{}", frood2.clone());
1909 assert_eq!(frood, frood2);
1910 }
1911
1912 #[test]
1913 fn test_each_byte_each_char_file() {
1914 // Issue #5056 -- shouldn't include trailing EOF.
1915 let path = Path::new("tmp/lib-io-test-each-byte-each-char-file.tmp");
1916
1917 {
1918 // create empty, enough to reproduce a problem
1919 io::file_writer(&path, [io::Create]).unwrap();
1920 }
1921
1922 {
1923 let file = io::file_reader(&path).unwrap();
1924 do file.each_byte() |_| {
1925 fail2!("must be empty")
1926 };
1927 }
1928
1929 {
1930 let file = io::file_reader(&path).unwrap();
1931 do file.each_char() |_| {
1932 fail2!("must be empty")
1933 };
1934 }
1935 }
1936
1937 #[test]
1938 fn test_readchars_empty() {
1939 do io::with_str_reader("") |inp| {
1940 let res : ~[char] = inp.read_chars(128);
1941 assert_eq!(res.len(), 0);
1942 }
1943 }
1944
1945 #[test]
1946 fn test_read_line_utf8() {
1947 do io::with_str_reader("生锈的汤匙切肉汤hello生锈的汤匙切肉汤") |inp| {
1948 let line = inp.read_line();
1949 assert_eq!(line, ~"生锈的汤匙切肉汤hello生锈的汤匙切肉汤");
1950 }
1951 }
1952
1953 #[test]
1954 fn test_read_lines() {
1955 do io::with_str_reader("a\nb\nc\n") |inp| {
1956 assert_eq!(inp.read_lines(), ~[~"a", ~"b", ~"c"]);
1957 }
1958
1959 do io::with_str_reader("a\nb\nc") |inp| {
1960 assert_eq!(inp.read_lines(), ~[~"a", ~"b", ~"c"]);
1961 }
1962
1963 do io::with_str_reader("") |inp| {
1964 assert!(inp.read_lines().is_empty());
1965 }
1966 }
1967
1968 #[test]
1969 fn test_readchars_wide() {
1970 let wide_test = ~"生锈的汤匙切肉汤hello生锈的汤匙切肉汤";
1971 let ivals : ~[int] = ~[
1972 29983, 38152, 30340, 27748,
1973 21273, 20999, 32905, 27748,
1974 104, 101, 108, 108, 111,
1975 29983, 38152, 30340, 27748,
1976 21273, 20999, 32905, 27748];
1977 fn check_read_ln(len : uint, s: &str, ivals: &[int]) {
1978 do io::with_str_reader(s) |inp| {
1979 let res : ~[char] = inp.read_chars(len);
1980 if len <= ivals.len() {
1981 assert_eq!(res.len(), len);
1982 }
1983 for (iv, c) in ivals.iter().zip(res.iter()) {
1984 assert!(*iv == *c as int)
1985 }
1986 }
1987 }
1988 let mut i = 0;
1989 while i < 8 {
1990 check_read_ln(i, wide_test, ivals);
1991 i += 1;
1992 }
1993 // check a long read for good measure
1994 check_read_ln(128, wide_test, ivals);
1995 }
1996
1997 #[test]
1998 fn test_readchar() {
1999 do io::with_str_reader("生") |inp| {
2000 let res = inp.read_char();
2001 assert_eq!(res as int, 29983);
2002 }
2003 }
2004
2005 #[test]
2006 fn test_readchar_empty() {
2007 do io::with_str_reader("") |inp| {
2008 let res = inp.read_char();
2009 assert_eq!(res, unsafe { transmute(-1u32) }); // FIXME: #8971: unsound
2010 }
2011 }
2012
2013 #[test]
2014 fn file_reader_not_exist() {
2015 match io::file_reader(&Path::new("not a file")) {
2016 Err(e) => {
2017 assert_eq!(e, ~"error opening not a file");
2018 }
2019 Ok(_) => fail2!()
2020 }
2021 }
2022
2023 #[test]
2024 #[should_fail]
2025 fn test_read_buffer_too_small() {
2026 let path = &Path::new("tmp/lib-io-test-read-buffer-too-small.tmp");
2027 // ensure the file exists
2028 io::file_writer(path, [io::Create]).unwrap();
2029
2030 let file = io::file_reader(path).unwrap();
2031 let mut buf = vec::from_elem(5, 0u8);
2032 file.read(buf, 6); // this should fail because buf is too small
2033 }
2034
2035 #[test]
2036 fn test_read_buffer_big_enough() {
2037 let path = &Path::new("tmp/lib-io-test-read-buffer-big-enough.tmp");
2038 // ensure the file exists
2039 io::file_writer(path, [io::Create]).unwrap();
2040
2041 let file = io::file_reader(path).unwrap();
2042 let mut buf = vec::from_elem(5, 0u8);
2043 file.read(buf, 4); // this should succeed because buf is big enough
2044 }
2045
2046 #[test]
2047 fn test_write_empty() {
2048 let file = io::file_writer(&Path::new("tmp/lib-io-test-write-empty.tmp"),
2049 [io::Create]).unwrap();
2050 file.write([]);
2051 }
2052
2053 #[test]
2054 fn file_writer_bad_name() {
2055 match io::file_writer(&Path::new("?/?"), []) {
2056 Err(e) => {
2057 assert!(e.starts_with("error opening"));
2058 }
2059 Ok(_) => fail2!()
2060 }
2061 }
2062
2063 #[test]
2064 fn bytes_buffer_overwrite() {
2065 let wr = BytesWriter::new();
2066 wr.write([0u8, 1u8, 2u8, 3u8]);
2067 assert!(*wr.bytes == ~[0u8, 1u8, 2u8, 3u8]);
2068 wr.seek(-2, SeekCur);
2069 wr.write([4u8, 5u8, 6u8, 7u8]);
2070 assert!(*wr.bytes == ~[0u8, 1u8, 4u8, 5u8, 6u8, 7u8]);
2071 wr.seek(-2, SeekEnd);
2072 wr.write([8u8]);
2073 wr.seek(1, SeekSet);
2074 wr.write([9u8]);
2075 assert!(*wr.bytes == ~[0u8, 9u8, 4u8, 5u8, 8u8, 7u8]);
2076 }
2077
2078 #[test]
2079 fn test_read_write_le() {
2080 let path = Path::new("tmp/lib-io-test-read-write-le.tmp");
2081 let uints = [0, 1, 2, 42, 10_123, 100_123_456, u64::max_value];
2082
2083 // write the ints to the file
2084 {
2085 let file = io::file_writer(&path, [io::Create]).unwrap();
2086 for i in uints.iter() {
2087 file.write_le_u64(*i);
2088 }
2089 }
2090
2091 // then read them back and check that they are the same
2092 {
2093 let file = io::file_reader(&path).unwrap();
2094 for i in uints.iter() {
2095 assert_eq!(file.read_le_u64(), *i);
2096 }
2097 }
2098 }
2099
2100 #[test]
2101 fn test_read_write_be() {
2102 let path = Path::new("tmp/lib-io-test-read-write-be.tmp");
2103 let uints = [0, 1, 2, 42, 10_123, 100_123_456, u64::max_value];
2104
2105 // write the ints to the file
2106 {
2107 let file = io::file_writer(&path, [io::Create]).unwrap();
2108 for i in uints.iter() {
2109 file.write_be_u64(*i);
2110 }
2111 }
2112
2113 // then read them back and check that they are the same
2114 {
2115 let file = io::file_reader(&path).unwrap();
2116 for i in uints.iter() {
2117 assert_eq!(file.read_be_u64(), *i);
2118 }
2119 }
2120 }
2121
2122 #[test]
2123 fn test_read_be_int_n() {
2124 let path = Path::new("tmp/lib-io-test-read-be-int-n.tmp");
2125 let ints = [i32::min_value, -123456, -42, -5, 0, 1, i32::max_value];
2126
2127 // write the ints to the file
2128 {
2129 let file = io::file_writer(&path, [io::Create]).unwrap();
2130 for i in ints.iter() {
2131 file.write_be_i32(*i);
2132 }
2133 }
2134
2135 // then read them back and check that they are the same
2136 {
2137 let file = io::file_reader(&path).unwrap();
2138 for i in ints.iter() {
2139 // this tests that the sign extension is working
2140 // (comparing the values as i32 would not test this)
2141 assert_eq!(file.read_be_int_n(4), *i as i64);
2142 }
2143 }
2144 }
2145
2146 #[test]
2147 fn test_read_f32() {
2148 let path = Path::new("tmp/lib-io-test-read-f32.tmp");
2149 //big-endian floating-point 8.1250
2150 let buf = ~[0x41, 0x02, 0x00, 0x00];
2151
2152 {
2153 let file = io::file_writer(&path, [io::Create]).unwrap();
2154 file.write(buf);
2155 }
2156
2157 {
2158 let file = io::file_reader(&path).unwrap();
2159 let f = file.read_be_f32();
2160 assert_eq!(f, 8.1250);
2161 }
2162 }
2163
2164 #[test]
2165 fn test_read_write_f32() {
2166 let path = Path::new("tmp/lib-io-test-read-write-f32.tmp");
2167 let f:f32 = 8.1250;
2168
2169 {
2170 let file = io::file_writer(&path, [io::Create]).unwrap();
2171 file.write_be_f32(f);
2172 file.write_le_f32(f);
2173 }
2174
2175 {
2176 let file = io::file_reader(&path).unwrap();
2177 assert_eq!(file.read_be_f32(), 8.1250);
2178 assert_eq!(file.read_le_f32(), 8.1250);
2179 }
2180 }
2181 }
libstd/io.rs:1345:1-1345:1 -fn- definition:
pub fn u64_to_le_bytes<T>(n: u64, size: uint,
references:-1592: u64_to_le_bytes(n as u64, 2u, |v| self.write(v))
1583: u64_to_le_bytes(n as u64, 2u, |v| self.write(v))
1586: u64_to_le_bytes(n as u64, 8u, |v| self.write(v))
1589: u64_to_le_bytes(n as u64, 4u, |v| self.write(v))
1577: u64_to_le_bytes(n, 8u, |v| self.write(v))
1537: u64_to_le_bytes(n as u64, uint::bytes, |v| self.write(v))
1580: u64_to_le_bytes(n as u64, 4u, |v| self.write(v))
1540: u64_to_le_bytes(n as u64, int::bytes, |v| self.write(v))
libstd/rt/io/extensions.rs:
608: u64_to_le_bytes(n as u64, 2u, |v| self.write(v))
592: u64_to_le_bytes(n as u64, 4u, |v| self.write(v))
536: u64_to_le_bytes(n as u64, uint::bytes, |v| self.write(v))
596: u64_to_le_bytes(n as u64, 2u, |v| self.write(v))
604: u64_to_le_bytes(n as u64, 4u, |v| self.write(v))
600: u64_to_le_bytes(n as u64, 8u, |v| self.write(v))
588: u64_to_le_bytes(n, 8u, |v| self.write(v))
540: u64_to_le_bytes(n as u64, int::bytes, |v| self.write(v))
libstd/io.rs:1145:16-1145:16 -enum- definition:
#[deriving(Eq)]
pub enum WriterType { Screen, File }
references:-1145: #[deriving(Eq)]
1722: fn get_type(&self) -> WriterType {
1145: #[deriving(Eq)]
1167: fn get_type(&self) -> WriterType;
1175: fn get_type(&self) -> WriterType { self.get_type() }
1183: fn get_type(&self) -> WriterType { File }
1226: fn get_type(&self) -> WriterType {
1145: #[deriving(Eq)]
1275: fn get_type(&self) -> WriterType {
libstd/io.rs:1835:8-1835:8 -fn- definition:
fn fileno(stream: *libc::FILE) -> libc::c_int {
#[fixed_stack_segment]; #[inline(never)];
references:-1841: fsync_fd(fileno(*stream), level)
libstd/io.rs:990:1-990:1 -struct- definition:
struct Wrapper<T, C> {
references:-1306: @Wrapper { base: fd, cleanup: FdRes::new(fd) } as @Writer
1178: impl<W:Writer,C> Writer for Wrapper<W, C> {
1033: @Wrapper { base: f, cleanup: FILERes::new(f) } as @Reader
999: impl<R:Reader,C> Reader for Wrapper<R, C> {
libstd/io.rs:926:1-926:1 -fn- definition:
fn convert_whence(whence: SeekStyle) -> i32 {
references:-1209: convert_whence(whence)) == 0 as c_int);
979: convert_whence(whence)) == 0 as c_int);
libstd/io.rs:1249:8-1249:8 -ty- definition:
type IoRet = libc::ssize_t;
references:-1257: if nout < 0 as IoRet {
libstd/io.rs:1430:50-1430:50 -trait- definition:
/// Generic utility functions defined on writers.
pub trait WriterUtil {
references:-1517: impl<T:Writer> WriterUtil for T {
libstd/io.rs:1628:3-1628:3 -fn- definition:
*/
pub fn stdout() -> @Writer { fd_writer(libc::STDOUT_FILENO as c_int, false) }
references:-1673: stdout().write_line(s);
1657: stdout().write_str(s);
libstd/io.rs:1030:1-1030:1 -fn- definition:
pub fn FILE_reader(f: *libc::FILE, cleanup: bool) -> @Reader {
references:-1076: Ok(FILE_reader(f, true))
libstd/io.rs:1010:1-1010:1 -struct- definition:
pub struct FILERes {
references:-1016: pub fn new(f: *libc::FILE) -> FILERes {
1826: pub fn FILE_res_sync(file: &FILERes,
1017: FILERes { f: f }
1021: impl Drop for FILERes {
1015: impl FILERes {
libstd/io.rs:1861:4-1861:4 -fn- definition:
fn fsync_fd_helper(fd_ptr: &libc::c_int, level: Level) -> int {
fsync_fd(*fd_ptr, level)
references:-1851: fsync_fn: fsync_fd_helper,
libstd/io.rs:1738:21-1738:21 -fn- definition:
// Utility functions
pub fn seek_in_buf(offset: int, pos: uint, len: uint, whence: SeekStyle) ->
references:-1117: *self.pos = seek_in_buf(offset, pos, self.bytes.len(), whence);
1711: *self.pos = seek_in_buf(offset, pos, len, whence);
libstd/io.rs:1794:4-1794:4 -struct- definition:
pub struct Res<t> {
arg: Arg<t>,
references:-1805: impl<T> Drop for Res<T> {
1870: blk: &fn(v: Res<@FSyncable>)) {
1799: pub fn new(arg: Arg<t>) -> Res<t> {
1800: Res { arg: arg }
1828: blk: &fn(v: Res<*libc::FILE>)) {
1798: impl <t> Res<t> {
1847: blk: &fn(v: Res<fd_t>)) {
libstd/io.rs:653:8-653:8 -fn- definition:
fn chars_from_utf8<T:Reader>(bytes: &~[u8], chars: &mut ~[char])
-> (uint, uint) {
references:-703: let (offset, nbreq) = chars_from_utf8::<T>(&bytes, &mut chars);
libstd/io.rs:1150:70-1150:70 -trait- definition:
/// The raw underlying writer trait. All writers must implement this.
pub trait Writer {
references:-1517: impl<T:Writer> WriterUtil for T {
1690: impl Writer for BytesWriter {
1629: pub fn stdout() -> @Writer { fd_writer(libc::STDOUT_FILENO as c_int, false) }
1727: pub fn with_bytes_writer(f: &fn(@Writer)) -> ~[u8] {
1610: pub fn file_writer(path: &Path, flags: &[FileFlag]) -> Result<@Writer, ~str> {
1729: f(wr as @Writer);
1170: impl Writer for @Writer {
1308: @fd as @Writer
1306: @Wrapper { base: fd, cleanup: FdRes::new(fd) } as @Writer
1734: pub fn with_str_writer(f: &fn(@Writer)) -> ~str {
1178: impl<W:Writer,C> Writer for Wrapper<W, C> {
1170: impl Writer for @Writer {
1314: -> Result<@Writer, ~str> {
1237: impl Writer for fd_t {
1304: pub fn fd_writer(fd: fd_t, cleanup: bool) -> @Writer {
1178: impl<W:Writer,C> Writer for Wrapper<W, C> {
1186: impl Writer for *libc::FILE {
1641: pub fn stderr() -> @Writer { fd_writer(libc::STDERR_FILENO as c_int, false) }
libstd/io.rs:1283:1-1283:1 -struct- definition:
pub struct FdRes {
references:-1294: impl Drop for FdRes {
1288: impl FdRes {
1289: pub fn new(fd: fd_t) -> FdRes {
1290: FdRes { fd: fd }
1846: pub fn fd_res_sync(fd: &FdRes, opt_level: Option<Level>,
libstd/io.rs:1817:4-1817:4 -struct- definition:
pub struct Arg<t> {
val: t,
references:-1848: blk(Res::new(Arg {
1795: arg: Arg<t>,
1871: blk(Res::new(Arg {
1829: blk(Res::new(Arg {
1799: pub fn new(arg: Arg<t>) -> Res<t> {
libstd/io.rs:1061:1-1061:1 -fn- definition:
pub fn file_reader(path: &Path) -> Result<@Reader, ~str> {
references:-1765: do file_reader(file).and_then |rdr| {
libstd/io.rs:1303:1-1303:1 -fn- definition:
pub fn fd_writer(fd: fd_t, cleanup: bool) -> @Writer {
references:-1641: pub fn stderr() -> @Writer { fd_writer(libc::STDERR_FILENO as c_int, false) }
1342: Ok(fd_writer(fd, true))
1629: pub fn stdout() -> @Writer { fd_writer(libc::STDOUT_FILENO as c_int, false) }
libstd/io.rs:1779:4-1779:4 -enum- definition:
pub enum Level {
// whatever fsync does on that platform
references:-1869: pub fn obj_sync(o: @FSyncable, opt_level: Option<Level>,
1861: fn fsync_fd_helper(fd_ptr: &libc::c_int, level: Level) -> int {
1819: opt_level: Option<Level>,
1840: fn fsync_FILE(stream: &*libc::FILE, level: Level) -> int {
1855: fn fsync_fd(fd: libc::c_int, level: Level) -> int {
1866: pub trait FSyncable { fn fsync(&self, l: Level) -> int; }
1846: pub fn fd_res_sync(fd: &FdRes, opt_level: Option<Level>,
1820: fsync_fn: extern "Rust" fn(f: &t, Level) -> int,
1827: opt_level: Option<Level>,
1878: fn obj_fsync_fn(o: &@FSyncable, level: Level) -> int {
libstd/os.rs:
340: pub fn fsync_fd(fd: c_int, level: io::fsync::Level) -> c_int {
libstd/io.rs:1323:4-1323:4 -fn- definition:
fn wb() -> c_int { O_WRONLY as c_int }
references:-1325: let mut fflags: c_int = wb();
libstd/io.rs:1081:16-1081:16 -struct- definition:
// Byte readers
pub struct BytesReader {
references:-1089: impl Reader for BytesReader {
1130: f(@BytesReader {
libstd/io.rs:218:3-218:3 -trait- definition:
*/
pub trait ReaderUtil {
references:-620: impl<T:Reader> ReaderUtil for T {
libstd/io.rs:1840:8-1840:8 -fn- definition:
fn fsync_FILE(stream: &*libc::FILE, level: Level) -> int {
fsync_fd(fileno(*stream), level)
references:-1832: fsync_fn: fsync_FILE,
libstd/io.rs:1247:8-1247:8 -ty- definition:
type IoSize = size_t;
#[cfg(unix)]
references:-1256: let nout = libc::write(*self, vb, len as IoSize);
libstd/io.rs:1726:1-1726:1 -fn- definition:
pub fn with_bytes_writer(f: &fn(@Writer)) -> ~[u8] {
references:-1735: str::from_utf8(with_bytes_writer(f))
libstd/to_bytes.rs:
363: do io::with_bytes_writer |wr| {
libstd/io.rs:73:65-73:65 -ty- definition:
#[allow(non_camel_case_types)] // not sure what to do about this
pub type fd_t = c_int;
references:-1289: pub fn new(fd: fd_t) -> FdRes {
1304: pub fn fd_writer(fd: fd_t, cleanup: bool) -> @Writer {
1237: impl Writer for fd_t {
1847: blk: &fn(v: Res<fd_t>)) {
1285: fd: fd_t,
libstd/io.rs:115:3-115:3 -trait- definition:
*/
pub trait Reader {
references:-999: impl<R:Reader,C> Reader for Wrapper<R, C> {
1058: @rustrt::rust_get_stdin() as @Reader
1062: pub fn file_reader(path: &Path) -> Result<@Reader, ~str> {
1133: } as @Reader)
1125: pub fn with_bytes_reader<T>(bytes: &[u8], f: &fn(@Reader) -> T) -> T {
1136: pub fn with_str_reader<T>(s: &str, f: &fn(@Reader) -> T) -> T {
999: impl<R:Reader,C> Reader for Wrapper<R, C> {
935: impl Reader for *libc::FILE {
190: impl Reader for @Reader {
190: impl Reader for @Reader {
1033: @Wrapper { base: f, cleanup: FILERes::new(f) } as @Reader
1089: impl Reader for BytesReader {
1035: @f as @Reader
653: fn chars_from_utf8<T:Reader>(bytes: &~[u8], chars: &mut ~[char])
620: impl<T:Reader> ReaderUtil for T {
1031: pub fn FILE_reader(f: *libc::FILE, cleanup: bool) -> @Reader {
1054: pub fn stdin() -> @Reader {
libstd/io.rs:1379:1-1379:1 -fn- definition:
pub fn u64_to_be_bytes<T>(n: u64, size: uint,
references:-1555: u64_to_be_bytes(n as u64, 2u, |v| self.write(v))
1543: u64_to_be_bytes(n as u64, uint::bytes, |v| self.write(v))
1558: u64_to_be_bytes(n as u64, 8u, |v| self.write(v))
1564: u64_to_be_bytes(n as u64, 2u, |v| self.write(v))
1549: u64_to_be_bytes(n, 8u, |v| self.write(v))
1546: u64_to_be_bytes(n as u64, int::bytes, |v| self.write(v))
1561: u64_to_be_bytes(n as u64, 4u, |v| self.write(v))
1552: u64_to_be_bytes(n as u64, 4u, |v| self.write(v))
libstd/rt/io/extensions.rs:
548: u64_to_be_bytes(n as u64, int::bytes, |v| self.write(v))
556: u64_to_be_bytes(n as u64, 4u, |v| self.write(v))
544: u64_to_be_bytes(n as u64, uint::bytes, |v| self.write(v))
564: u64_to_be_bytes(n as u64, 8u, |v| self.write(v))
572: u64_to_be_bytes(n as u64, 2u, |v| self.write(v))
560: u64_to_be_bytes(n as u64, 2u, |v| self.write(v))
568: u64_to_be_bytes(n as u64, 4u, |v| self.write(v))
552: u64_to_be_bytes(n, 8u, |v| self.write(v))
libstd/io.rs:1763:30-1763:30 -fn- definition:
// abstractions is pointless.
pub fn read_whole_file(file: &Path) -> Result<~[u8], ~str> {
references:-1753: do read_whole_file(file).and_then |bytes| {
libstd/io.rs:1312:1-1312:1 -fn- definition:
pub fn mk_file_writer(path: &Path, flags: &[FileFlag])
references:-1611: mk_file_writer(path, flags).and_then(|w| Ok(w))
libstd/io.rs:1866:4-1866:4 -trait- definition:
pub trait FSyncable { fn fsync(&self, l: Level) -> int; }
references:-1870: blk: &fn(v: Res<@FSyncable>)) {
1869: pub fn obj_sync(o: @FSyncable, opt_level: Option<Level>,
1878: fn obj_fsync_fn(o: &@FSyncable, level: Level) -> int {
libstd/io.rs:1855:4-1855:4 -fn- definition:
fn fsync_fd(fd: libc::c_int, level: Level) -> int {
#[fixed_stack_segment]; #[inline(never)];
references:-1841: fsync_fd(fileno(*stream), level)
1862: fsync_fd(*fd_ptr, level)
libstd/io.rs:1878:4-1878:4 -fn- definition:
fn obj_fsync_fn(o: &@FSyncable, level: Level) -> int {
(*o).fsync(level)
references:-1874: fsync_fn: obj_fsync_fn,
libstd/io.rs:1141:11-1141:11 -enum- definition:
// Writing
pub enum FileFlag { Append, Create, Truncate, NoFlag, }
references:-1313: pub fn mk_file_writer(path: &Path, flags: &[FileFlag])
1610: pub fn file_writer(path: &Path, flags: &[FileFlag]) -> Result<@Writer, ~str> {
libstd/io.rs:1675:1-1675:1 -struct- definition:
pub struct BytesWriter {
references:-1730: let @BytesWriter { bytes, _ } = wr;
1682: pub fn new() -> BytesWriter {
1690: impl Writer for BytesWriter {
1681: impl BytesWriter {
1683: BytesWriter {
libstd/io.rs:1124:1-1124:1 -fn- definition:
pub fn with_bytes_reader<T>(bytes: &[u8], f: &fn(@Reader) -> T) -> T {
references:-1138: with_bytes_reader(s.as_bytes(), f)
libstd/io.rs:105:3-105:3 -enum- definition:
*/
pub enum SeekStyle { SeekSet, SeekEnd, SeekCur, }
references:-1115: fn seek(&self, offset: int, whence: SeekStyle) {
1158: fn seek(&self, int, SeekStyle);
973: fn seek(&self, offset: int, whence: SeekStyle) {
1739: pub fn seek_in_buf(offset: int, pos: uint, len: uint, whence: SeekStyle) ->
1172: fn seek(&self, a: int, b: SeekStyle) { self.seek(a, b) }
1180: fn seek(&self, off: int, style: SeekStyle) { self.base.seek(off, style); }
1203: fn seek(&self, offset: int, whence: SeekStyle) {
1266: fn seek(&self, _offset: int, _whence: SeekStyle) {
1005: fn seek(&self, off: int, whence: SeekStyle) {
176: fn seek(&self, position: int, style: SeekStyle);
927: fn convert_whence(whence: SeekStyle) -> i32 {
1708: fn seek(&self, offset: int, whence: SeekStyle) {
200: fn seek(&self, position: int, style: SeekStyle) {
libstd/io.rs:919:1-919:1 -fn- definition:
fn extend_sign(val: u64, nbytes: uint) -> i64 {
references:-820: extend_sign(self.read_be_uint_n(nbytes), nbytes)
804: extend_sign(self.read_le_uint_n(nbytes), nbytes)