Skip to content

Commit 95d44ba

Browse files
committed
---
yaml --- r: 80703 b: refs/heads/try c: 4825db4 h: refs/heads/master i: 80701: ff006a5 80699: ffc5e5b 80695: f3548d0 80687: 4df5489 80671: 8a2bc4e 80639: 23f00f9 v: v3
1 parent 33dc5fe commit 95d44ba

File tree

7 files changed

+235
-83
lines changed

7 files changed

+235
-83
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
refs/heads/master: 4c6bf4872012c010f84dc7fa2cdfe87522533f89
33
refs/heads/snap-stage1: e33de59e47c5076a89eadeb38f4934f58a3618a6
44
refs/heads/snap-stage3: cbd1eefbd350797b783df119fed7956d7e1c74ad
5-
refs/heads/try: 68125359cdd053628b437c2b963bd82e1ff03523
5+
refs/heads/try: 4825db44c81ca2b122282dfb59aa705ad2475e5d
66
refs/tags/release-0.1: 1f5c5126e96c79d22cb7862f75304136e204f105
77
refs/heads/ndm: f3868061cd7988080c30d6d5bf352a5a5fe2460b
88
refs/heads/try2: 147ecfdd8221e4a4d4e090486829a06da1e0ca3c

branches/try/src/libstd/fmt/mod.rs

Lines changed: 75 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ Some examples of the `format!` extension are:
3636
format!("Hello") // => ~"Hello"
3737
format!("Hello, {:s}!", "world") // => ~"Hello, world!"
3838
format!("The number is {:d}", 1) // => ~"The number is 1"
39-
format!("{}", ~[3, 4]) // => ~"~[3, 4]"
39+
format!("{:?}", ~[3, 4]) // => ~"~[3, 4]"
4040
format!("{value}", value=4) // => ~"4"
4141
format!("{} {}", 1, 2) // => ~"1 2"
4242
~~~
@@ -363,6 +363,32 @@ pub struct Argument<'self> {
363363
priv value: &'self util::Void,
364364
}
365365

366+
impl<'self> Arguments<'self> {
367+
/// When using the format_args!() macro, this function is used to generate the
368+
/// Arguments structure. The compiler inserts an `unsafe` block to call this,
369+
/// which is valid because the compiler performs all necessary validation to
370+
/// ensure that the resulting call to format/write would be safe.
371+
#[doc(hidden)] #[inline]
372+
pub unsafe fn new<'a>(fmt: &'static [rt::Piece<'static>],
373+
args: &'a [Argument<'a>]) -> Arguments<'a> {
374+
Arguments{ fmt: cast::transmute(fmt), args: args }
375+
}
376+
}
377+
378+
/// This structure represents a safely precompiled version of a format string
379+
/// and its arguments. This cannot be generated at runtime because it cannot
380+
/// safely be done so, so no constructors are given and the fields are private
381+
/// to prevent modification.
382+
///
383+
/// The `format_args!` macro will safely create an instance of this structure
384+
/// and pass it to a user-supplied function. The macro validates the format
385+
/// string at compile-time so usage of the `write` and `format` functions can
386+
/// be safely performed.
387+
pub struct Arguments<'self> {
388+
priv fmt: &'self [rt::Piece<'self>],
389+
priv args: &'self [Argument<'self>],
390+
}
391+
366392
/// When a format is not otherwise specified, types are formatted by ascribing
367393
/// to this trait. There is not an explicit way of selecting this trait to be
368394
/// used for formatting, it is only if no other format is specified.
@@ -410,6 +436,26 @@ pub trait Float { fn fmt(&Self, &mut Formatter); }
410436
/// and a list of arguments. The arguments will be formatted according to the
411437
/// specified format string into the output stream provided.
412438
///
439+
/// # Arguments
440+
///
441+
/// * output - the buffer to write output to
442+
/// * args - the precompiled arguments generated by `format_args!`
443+
///
444+
/// # Example
445+
///
446+
/// ~~~{.rust}
447+
/// use std::fmt;
448+
/// let w: &mut io::Writer = ...;
449+
/// format_args!(|args| { fmt::write(w, args) }, "Hello, {}!", "world");
450+
/// ~~~
451+
pub fn write(output: &mut io::Writer, args: &Arguments) {
452+
unsafe { write_unsafe(output, args.fmt, args.args) }
453+
}
454+
455+
/// The `write_unsafe` function takes an output stream, a precompiled format
456+
/// string, and a list of arguments. The arguments will be formatted according
457+
/// to the specified format string into the output stream provided.
458+
///
413459
/// See the documentation for `format` for why this function is unsafe and care
414460
/// should be taken if calling it manually.
415461
///
@@ -426,8 +472,9 @@ pub trait Float { fn fmt(&Self, &mut Formatter); }
426472
///
427473
/// Note that this function assumes that there are enough arguments for the
428474
/// format string.
429-
pub unsafe fn write(output: &mut io::Writer,
430-
fmt: &[rt::Piece], args: &[Argument]) {
475+
pub unsafe fn write_unsafe(output: &mut io::Writer,
476+
fmt: &[rt::Piece],
477+
args: &[Argument]) {
431478
let mut formatter = Formatter {
432479
flags: 0,
433480
width: None,
@@ -446,6 +493,25 @@ pub unsafe fn write(output: &mut io::Writer,
446493
/// The format function takes a precompiled format string and a list of
447494
/// arguments, to return the resulting formatted string.
448495
///
496+
/// # Arguments
497+
///
498+
/// * args - a structure of arguments generated via the `format_args!` macro.
499+
/// Because this structure can only be safely generated at
500+
/// compile-time, this function is safe.
501+
///
502+
/// # Example
503+
///
504+
/// ~~~{.rust}
505+
/// use std::fmt;
506+
/// let s = format_args!(fmt::format, "Hello, {}!", "world");
507+
/// assert_eq!(s, "Hello, world!");
508+
/// ~~~
509+
pub fn format(args: &Arguments) -> ~str {
510+
unsafe { format_unsafe(args.fmt, args.args) }
511+
}
512+
513+
/// The unsafe version of the formatting function.
514+
///
449515
/// This is currently an unsafe function because the types of all arguments
450516
/// aren't verified by immediate callers of this function. This currently does
451517
/// not validate that the correct types of arguments are specified for each
@@ -465,9 +531,9 @@ pub unsafe fn write(output: &mut io::Writer,
465531
///
466532
/// Note that this function assumes that there are enough arguments for the
467533
/// format string.
468-
pub unsafe fn format(fmt: &[rt::Piece], args: &[Argument]) -> ~str {
534+
pub unsafe fn format_unsafe(fmt: &[rt::Piece], args: &[Argument]) -> ~str {
469535
let mut output = MemWriter::new();
470-
write(&mut output as &mut io::Writer, fmt, args);
536+
write_unsafe(&mut output as &mut io::Writer, fmt, args);
471537
return str::from_utf8_owned(output.inner());
472538
}
473539

@@ -740,7 +806,7 @@ impl<'self> Formatter<'self> {
740806

741807
/// This is a function which calls are emitted to by the compiler itself to
742808
/// create the Argument structures that are passed into the `format` function.
743-
#[doc(hidden)]
809+
#[doc(hidden)] #[inline]
744810
pub fn argument<'a, T>(f: extern "Rust" fn(&T, &mut Formatter),
745811
t: &'a T) -> Argument<'a> {
746812
unsafe {
@@ -753,14 +819,14 @@ pub fn argument<'a, T>(f: extern "Rust" fn(&T, &mut Formatter),
753819

754820
/// When the compiler determines that the type of an argument *must* be a string
755821
/// (such as for select), then it invokes this method.
756-
#[doc(hidden)]
822+
#[doc(hidden)] #[inline]
757823
pub fn argumentstr<'a>(s: &'a &str) -> Argument<'a> {
758824
argument(String::fmt, s)
759825
}
760826

761827
/// When the compiler determines that the type of an argument *must* be a uint
762828
/// (such as for plural), then it invokes this method.
763-
#[doc(hidden)]
829+
#[doc(hidden)] #[inline]
764830
pub fn argumentuint<'a>(s: &'a uint) -> Argument<'a> {
765831
argument(Unsigned::fmt, s)
766832
}
@@ -899,14 +965,8 @@ impl<T> Pointer for *T {
899965
}
900966
}
901967
}
902-
903968
impl<T> Pointer for *mut T {
904-
fn fmt(t: &*mut T, f: &mut Formatter) {
905-
f.flags |= 1 << (parse::FlagAlternate as uint);
906-
do ::uint::to_str_bytes(*t as uint, 16) |buf| {
907-
f.pad_integral(buf, "0x", true);
908-
}
909-
}
969+
fn fmt(t: &*mut T, f: &mut Formatter) { Pointer::fmt(&(*t as *T), f) }
910970
}
911971

912972
// Implementation of Default for various core types
@@ -940,7 +1000,6 @@ delegate!(f64 to Float)
9401000
impl<T> Default for *T {
9411001
fn fmt(me: &*T, f: &mut Formatter) { Pointer::fmt(me, f) }
9421002
}
943-
9441003
impl<T> Default for *mut T {
9451004
fn fmt(me: &*mut T, f: &mut Formatter) { Pointer::fmt(me, f) }
9461005
}

branches/try/src/libsyntax/ext/base.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,8 @@ pub fn syntax_expander_table() -> SyntaxEnv {
161161
builtin_normal_tt_no_ctxt(ext::ifmt::expand_write));
162162
syntax_expanders.insert(intern(&"writeln"),
163163
builtin_normal_tt_no_ctxt(ext::ifmt::expand_writeln));
164+
syntax_expanders.insert(intern(&"format_args"),
165+
builtin_normal_tt_no_ctxt(ext::ifmt::expand_format_args));
164166
syntax_expanders.insert(
165167
intern(&"auto_encode"),
166168
@SE(ItemDecorator(ext::auto_encode::expand_auto_encode)));

0 commit comments

Comments
 (0)