diff options
Diffstat (limited to 'src/libstd')
| -rw-r--r-- | src/libstd/fmt/mod.rs | 91 |
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) } } |
