]> git.lizzy.rs Git - rust.git/blobdiff - src/libstd/io/stdio.rs
Fix spelling errors in comments.
[rust.git] / src / libstd / io / stdio.rs
index 61ad9905771a406b328d8de4161f2157a038b4b4..f55a825a1370a09431d979b861ac44a3f7dce3f3 100644 (file)
@@ -11,6 +11,7 @@
 use prelude::v1::*;
 use io::prelude::*;
 
+use cell::RefCell;
 use cmp;
 use fmt;
 use io::lazy::Lazy;
 use sync::{Arc, Mutex, MutexGuard};
 use sys::stdio;
 
+/// Stdout used by print! and println! macros
+thread_local! {
+    static LOCAL_STDOUT: RefCell<Option<Box<Write + Send>>> = {
+        RefCell::new(None)
+    }
+}
+
 /// A handle to a raw instance of the standard input stream of this process.
 ///
 /// This handle is not synchronized or buffered in any fashion. Constructed via
-/// the `std::io::stdin_raw` function.
-pub struct StdinRaw(stdio::Stdin);
+/// the `std::io::stdio::stdin_raw` function.
+struct StdinRaw(stdio::Stdin);
 
 /// A handle to a raw instance of the standard output stream of this process.
 ///
 /// This handle is not synchronized or buffered in any fashion. Constructed via
-/// the `std::io::stdout_raw` function.
-pub struct StdoutRaw(stdio::Stdout);
+/// the `std::io::stdio::stdout_raw` function.
+struct StdoutRaw(stdio::Stdout);
 
 /// A handle to a raw instance of the standard output stream of this process.
 ///
 /// This handle is not synchronized or buffered in any fashion. Constructed via
-/// the `std::io::stderr_raw` function.
-pub struct StderrRaw(stdio::Stderr);
+/// the `std::io::stdio::stderr_raw` function.
+struct StderrRaw(stdio::Stderr);
 
 /// Construct a new raw handle to the standard input of this process.
 ///
@@ -43,7 +51,7 @@
 /// handles is **not** available to raw handles returned from this function.
 ///
 /// The returned handle has no external synchronization or buffering.
-pub fn stdin_raw() -> StdinRaw { StdinRaw(stdio::Stdin::new()) }
+fn stdin_raw() -> StdinRaw { StdinRaw(stdio::Stdin::new()) }
 
 /// Construct a new raw handle to the standard input stream of this process.
 ///
@@ -54,7 +62,7 @@ pub fn stdin_raw() -> StdinRaw { StdinRaw(stdio::Stdin::new()) }
 ///
 /// The returned handle has no external synchronization or buffering layered on
 /// top.
-pub fn stdout_raw() -> StdoutRaw { StdoutRaw(stdio::Stdout::new()) }
+fn stdout_raw() -> StdoutRaw { StdoutRaw(stdio::Stdout::new()) }
 
 /// Construct a new raw handle to the standard input stream of this process.
 ///
@@ -63,7 +71,7 @@ pub fn stdout_raw() -> StdoutRaw { StdoutRaw(stdio::Stdout::new()) }
 ///
 /// The returned handle has no external synchronization or buffering layered on
 /// top.
-pub fn stderr_raw() -> StderrRaw { StderrRaw(stdio::Stderr::new()) }
+fn stderr_raw() -> StderrRaw { StderrRaw(stdio::Stderr::new()) }
 
 impl Read for StdinRaw {
     fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { self.0.read(buf) }
@@ -86,6 +94,7 @@ fn flush(&mut self) -> io::Result<()> { Ok(()) }
 ///
 /// This handle implements the `Read` trait, but beware that concurrent reads
 /// of `Stdin` must be executed with care.
+#[stable(feature = "rust1", since = "1.0.0")]
 pub struct Stdin {
     inner: Arc<Mutex<BufReader<StdinRaw>>>,
 }
@@ -94,6 +103,7 @@ pub struct Stdin {
 ///
 /// This handle implements both the `Read` and `BufRead` traits and is
 /// constructed via the `lock` method on `Stdin`.
+#[stable(feature = "rust1", since = "1.0.0")]
 pub struct StdinLock<'a> {
     inner: MutexGuard<'a, BufReader<StdinRaw>>,
 }
@@ -107,9 +117,7 @@ pub struct StdinLock<'a> {
 /// The `Read` trait is implemented for the returned value but the `BufRead`
 /// trait is not due to the global nature of the standard input stream. The
 /// locked version, `StdinLock`, implements both `Read` and `BufRead`, however.
-///
-/// To avoid locking and buffering altogether, it is recommended to use the
-/// `stdin_raw` constructor.
+#[stable(feature = "rust1", since = "1.0.0")]
 pub fn stdin() -> Stdin {
     static INSTANCE: Lazy<Mutex<BufReader<StdinRaw>>> = lazy_init!(stdin_init);
     return Stdin {
@@ -136,33 +144,41 @@ impl Stdin {
     /// The lock is released when the returned lock goes out of scope. The
     /// returned guard also implements the `Read` and `BufRead` traits for
     /// accessing the underlying data.
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn lock(&self) -> StdinLock {
         StdinLock { inner: self.inner.lock().unwrap() }
     }
+
+    /// Locks this handle and reads a line of input into the specified buffer.
+    ///
+    /// For detailed semantics of this method, see the documentation on
+    /// `BufRead::read_line`.
+    #[stable(feature = "rust1", since = "1.0.0")]
+    pub fn read_line(&mut self, buf: &mut String) -> io::Result<usize> {
+        self.lock().read_line(buf)
+    }
 }
 
+#[stable(feature = "rust1", since = "1.0.0")]
 impl Read for Stdin {
     fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
         self.lock().read(buf)
     }
-
-    fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<()> {
+    fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
         self.lock().read_to_end(buf)
     }
-
-    fn read_to_string(&mut self, buf: &mut String) -> io::Result<()> {
+    fn read_to_string(&mut self, buf: &mut String) -> io::Result<usize> {
         self.lock().read_to_string(buf)
     }
 }
 
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'a> Read for StdinLock<'a> {
     fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
-        // Flush stdout so that weird issues like a print!'d prompt not being
-        // shown until after the user hits enter.
-        drop(stdout().flush());
         self.inner.read(buf)
     }
 }
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'a> BufRead for StdinLock<'a> {
     fn fill_buf(&mut self) -> io::Result<&[u8]> { self.inner.fill_buf() }
     fn consume(&mut self, n: usize) { self.inner.consume(n) }
@@ -189,6 +205,7 @@ fn consume(&mut self, n: usize) { self.inner.consume(n) }
 /// Each handle shares a global buffer of data to be written to the standard
 /// output stream. Access is also synchronized via a lock and explicit control
 /// over locking is available via the `lock` method.
+#[stable(feature = "rust1", since = "1.0.0")]
 pub struct Stdout {
     // FIXME: this should be LineWriter or BufWriter depending on the state of
     //        stdout (tty or not). Note that if this is not line buffered it
@@ -200,6 +217,7 @@ pub struct Stdout {
 ///
 /// This handle implements the `Write` trait and is constructed via the `lock`
 /// method on `Stdout`.
+#[stable(feature = "rust1", since = "1.0.0")]
 pub struct StdoutLock<'a> {
     inner: MutexGuard<'a, LineWriter<StdoutRaw>>,
 }
@@ -211,9 +229,7 @@ pub struct StdoutLock<'a> {
 /// provided via the `lock` method.
 ///
 /// The returned handle implements the `Write` trait.
-///
-/// To avoid locking and buffering altogether, it is recommended to use the
-/// `stdout_raw` constructor.
+#[stable(feature = "rust1", since = "1.0.0")]
 pub fn stdout() -> Stdout {
     static INSTANCE: Lazy<Mutex<LineWriter<StdoutRaw>>> = lazy_init!(stdout_init);
     return Stdout {
@@ -231,11 +247,13 @@ impl Stdout {
     ///
     /// The lock is released when the returned lock goes out of scope. The
     /// returned guard also implements the `Write` trait for writing data.
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn lock(&self) -> StdoutLock {
         StdoutLock { inner: self.inner.lock().unwrap() }
     }
 }
 
+#[stable(feature = "rust1", since = "1.0.0")]
 impl Write for Stdout {
     fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
         self.lock().write(buf)
@@ -250,6 +268,7 @@ fn write_fmt(&mut self, fmt: fmt::Arguments) -> io::Result<()> {
         self.lock().write_fmt(fmt)
     }
 }
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'a> Write for StdoutLock<'a> {
     fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
         self.inner.write(&buf[..cmp::min(buf.len(), OUT_MAX)])
@@ -260,6 +279,7 @@ fn flush(&mut self) -> io::Result<()> { self.inner.flush() }
 /// A handle to the standard error stream of a process.
 ///
 /// For more information, see `stderr`
+#[stable(feature = "rust1", since = "1.0.0")]
 pub struct Stderr {
     inner: Arc<Mutex<StderrRaw>>,
 }
@@ -268,6 +288,7 @@ pub struct Stderr {
 ///
 /// This handle implements the `Write` trait and is constructed via the `lock`
 /// method on `Stderr`.
+#[stable(feature = "rust1", since = "1.0.0")]
 pub struct StderrLock<'a> {
     inner: MutexGuard<'a, StderrRaw>,
 }
@@ -278,9 +299,7 @@ pub struct StderrLock<'a> {
 /// this function. No handles are buffered, however.
 ///
 /// The returned handle implements the `Write` trait.
-///
-/// To avoid locking altogether, it is recommended to use the `stderr_raw`
-/// constructor.
+#[stable(feature = "rust1", since = "1.0.0")]
 pub fn stderr() -> Stderr {
     static INSTANCE: Lazy<Mutex<StderrRaw>> = lazy_init!(stderr_init);
     return Stderr {
@@ -298,11 +317,13 @@ impl Stderr {
     ///
     /// The lock is released when the returned lock goes out of scope. The
     /// returned guard also implements the `Write` trait for writing data.
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn lock(&self) -> StderrLock {
         StderrLock { inner: self.inner.lock().unwrap() }
     }
 }
 
+#[stable(feature = "rust1", since = "1.0.0")]
 impl Write for Stderr {
     fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
         self.lock().write(buf)
@@ -317,9 +338,67 @@ fn write_fmt(&mut self, fmt: fmt::Arguments) -> io::Result<()> {
         self.lock().write_fmt(fmt)
     }
 }
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<'a> Write for StderrLock<'a> {
     fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
         self.inner.write(&buf[..cmp::min(buf.len(), OUT_MAX)])
     }
     fn flush(&mut self) -> io::Result<()> { self.inner.flush() }
 }
+
+/// Resets the task-local stderr handle to the specified writer
+///
+/// This will replace the current task's stderr handle, returning the old
+/// handle. All future calls to `panic!` and friends will emit their output to
+/// this specified handle.
+///
+/// Note that this does not need to be called for all new tasks; the default
+/// output handle is to the process's stderr stream.
+#[unstable(feature = "set_stdio",
+           reason = "this function may disappear completely or be replaced \
+                     with a more general mechanism")]
+#[doc(hidden)]
+pub fn set_panic(sink: Box<Write + Send>) -> Option<Box<Write + Send>> {
+    use panicking::LOCAL_STDERR;
+    use mem;
+    LOCAL_STDERR.with(move |slot| {
+        mem::replace(&mut *slot.borrow_mut(), Some(sink))
+    }).and_then(|mut s| {
+        let _ = s.flush();
+        Some(s)
+    })
+}
+
+/// Resets the task-local stdout handle to the specified writer
+///
+/// This will replace the current task's stdout handle, returning the old
+/// handle. All future calls to `print!` and friends will emit their output to
+/// this specified handle.
+///
+/// Note that this does not need to be called for all new tasks; the default
+/// output handle is to the process's stdout stream.
+#[unstable(feature = "set_stdio",
+           reason = "this function may disappear completely or be replaced \
+                     with a more general mechanism")]
+#[doc(hidden)]
+pub fn set_print(sink: Box<Write + Send>) -> Option<Box<Write + Send>> {
+    use mem;
+    LOCAL_STDOUT.with(move |slot| {
+        mem::replace(&mut *slot.borrow_mut(), Some(sink))
+    }).and_then(|mut s| {
+        let _ = s.flush();
+        Some(s)
+    })
+}
+
+#[unstable(feature = "print",
+           reason = "implementation detail which may disappear or be replaced at any time")]
+#[doc(hidden)]
+pub fn _print(args: fmt::Arguments) {
+    if let Err(e) = LOCAL_STDOUT.with(|s| match s.borrow_mut().as_mut() {
+        Some(w) => w.write_fmt(args),
+        None => stdout().write_fmt(args)
+    }) {
+        panic!("failed printing to stdout: {}", e);
+    }
+}