about summary refs log tree commit diff
path: root/src/libstd
diff options
context:
space:
mode:
Diffstat (limited to 'src/libstd')
-rw-r--r--src/libstd/fmt/mod.rs91
1 files changed, 75 insertions, 16 deletions
diff --git a/src/libstd/fmt/mod.rs b/src/libstd/fmt/mod.rs
index 7d5033e3a6a..c7ab508ea6e 100644
--- a/src/libstd/fmt/mod.rs
+++ b/src/libstd/fmt/mod.rs
@@ -36,7 +36,7 @@ Some examples of the `format!` extension are:
 format!("Hello")                  // => ~"Hello"
 format!("Hello, {:s}!", "world")  // => ~"Hello, world!"
 format!("The number is {:d}", 1)  // => ~"The number is 1"
-format!("{}", ~[3, 4])            // => ~"~[3, 4]"
+format!("{:?}", ~[3, 4])          // => ~"~[3, 4]"
 format!("{value}", value=4)       // => ~"4"
 format!("{} {}", 1, 2)            // => ~"1 2"
 ~~~
@@ -363,6 +363,32 @@ pub struct Argument<'self> {
     priv value: &'self util::Void,
 }
 
+impl<'self> Arguments<'self> {
+    /// When using the format_args!() macro, this function is used to generate the
+    /// Arguments structure. The compiler inserts an `unsafe` block to call this,
+    /// which is valid because the compiler performs all necessary validation to
+    /// ensure that the resulting call to format/write would be safe.
+    #[doc(hidden)] #[inline]
+    pub unsafe fn new<'a>(fmt: &'static [rt::Piece<'static>],
+                          args: &'a [Argument<'a>]) -> Arguments<'a> {
+        Arguments{ fmt: cast::transmute(fmt), args: args }
+    }
+}
+
+/// This structure represents a safely precompiled version of a format string
+/// and its arguments. This cannot be generated at runtime because it cannot
+/// safely be done so, so no constructors are given and the fields are private
+/// to prevent modification.
+///
+/// The `format_args!` macro will safely create an instance of this structure
+/// and pass it to a user-supplied function. The macro validates the format
+/// string at compile-time so usage of the `write` and `format` functions can
+/// be safely performed.
+pub struct Arguments<'self> {
+    priv fmt: &'self [rt::Piece<'self>],
+    priv args: &'self [Argument<'self>],
+}
+
 /// When a format is not otherwise specified, types are formatted by ascribing
 /// to this trait. There is not an explicit way of selecting this trait to be
 /// used for formatting, it is only if no other format is specified.
@@ -410,6 +436,26 @@ pub trait Float { fn fmt(&Self, &mut Formatter); }
 /// and a list of arguments. The arguments will be formatted according to the
 /// specified format string into the output stream provided.
 ///
+/// # Arguments
+///
+///   * output - the buffer to write output to
+///   * args - the precompiled arguments generated by `format_args!`
+///
+/// # Example
+///
+/// ~~~{.rust}
+/// use std::fmt;
+/// let w: &mut io::Writer = ...;
+/// format_args!(|args| { fmt::write(w, args) }, "Hello, {}!", "world");
+/// ~~~
+pub fn write(output: &mut io::Writer, args: &Arguments) {
+    unsafe { write_unsafe(output, args.fmt, args.args) }
+}
+
+/// The `write_unsafe` function takes an output stream, a precompiled format
+/// string, and a list of arguments. The arguments will be formatted according
+/// to the specified format string into the output stream provided.
+///
 /// See the documentation for `format` for why this function is unsafe and care
 /// should be taken if calling it manually.
 ///
@@ -426,8 +472,9 @@ pub trait Float { fn fmt(&Self, &mut Formatter); }
 ///
 /// Note that this function assumes that there are enough arguments for the
 /// format string.
-pub unsafe fn write(output: &mut io::Writer,
-                    fmt: &[rt::Piece], args: &[Argument]) {
+pub unsafe fn write_unsafe(output: &mut io::Writer,
+                           fmt: &[rt::Piece],
+                           args: &[Argument]) {
     let mut formatter = Formatter {
         flags: 0,
         width: None,
@@ -446,6 +493,25 @@ pub unsafe fn write(output: &mut io::Writer,
 /// The format function takes a precompiled format string and a list of
 /// arguments, to return the resulting formatted string.
 ///
+/// # Arguments
+///
+///   * args - a structure of arguments generated via the `format_args!` macro.
+///            Because this structure can only be safely generated at
+///            compile-time, this function is safe.
+///
+/// # Example
+///
+/// ~~~{.rust}
+/// use std::fmt;
+/// let s = format_args!(fmt::format, "Hello, {}!", "world");
+/// assert_eq!(s, "Hello, world!");
+/// ~~~
+pub fn format(args: &Arguments) -> ~str {
+    unsafe { format_unsafe(args.fmt, args.args) }
+}
+
+/// The unsafe version of the formatting function.
+///
 /// This is currently an unsafe function because the types of all arguments
 /// aren't verified by immediate callers of this function. This currently does
 /// not validate that the correct types of arguments are specified for each
@@ -465,9 +531,9 @@ pub unsafe fn write(output: &mut io::Writer,
 ///
 /// Note that this function assumes that there are enough arguments for the
 /// format string.
-pub unsafe fn format(fmt: &[rt::Piece], args: &[Argument]) -> ~str {
+pub unsafe fn format_unsafe(fmt: &[rt::Piece], args: &[Argument]) -> ~str {
     let mut output = MemWriter::new();
-    write(&mut output as &mut io::Writer, fmt, args);
+    write_unsafe(&mut output as &mut io::Writer, fmt, args);
     return str::from_utf8_owned(output.inner());
 }
 
@@ -740,7 +806,7 @@ impl<'self> Formatter<'self> {
 
 /// This is a function which calls are emitted to by the compiler itself to
 /// create the Argument structures that are passed into the `format` function.
-#[doc(hidden)]
+#[doc(hidden)] #[inline]
 pub fn argument<'a, T>(f: extern "Rust" fn(&T, &mut Formatter),
                        t: &'a T) -> Argument<'a> {
     unsafe {
@@ -753,14 +819,14 @@ pub fn argument<'a, T>(f: extern "Rust" fn(&T, &mut Formatter),
 
 /// When the compiler determines that the type of an argument *must* be a string
 /// (such as for select), then it invokes this method.
-#[doc(hidden)]
+#[doc(hidden)] #[inline]
 pub fn argumentstr<'a>(s: &'a &str) -> Argument<'a> {
     argument(String::fmt, s)
 }
 
 /// When the compiler determines that the type of an argument *must* be a uint
 /// (such as for plural), then it invokes this method.
-#[doc(hidden)]
+#[doc(hidden)] #[inline]
 pub fn argumentuint<'a>(s: &'a uint) -> Argument<'a> {
     argument(Unsigned::fmt, s)
 }
@@ -899,14 +965,8 @@ impl<T> Pointer for *T {
         }
     }
 }
-
 impl<T> Pointer for *mut T {
-    fn fmt(t: &*mut T, f: &mut Formatter) {
-        f.flags |= 1 << (parse::FlagAlternate as uint);
-        do ::uint::to_str_bytes(*t as uint, 16) |buf| {
-            f.pad_integral(buf, "0x", true);
-        }
-    }
+    fn fmt(t: &*mut T, f: &mut Formatter) { Pointer::fmt(&(*t as *T), f) }
 }
 
 // Implementation of Default for various core types
@@ -940,7 +1000,6 @@ delegate!(f64 to Float)
 impl<T> Default for *T {
     fn fmt(me: &*T, f: &mut Formatter) { Pointer::fmt(me, f) }
 }
-
 impl<T> Default for *mut T {
     fn fmt(me: &*mut T, f: &mut Formatter) { Pointer::fmt(me, f) }
 }