about summary refs log tree commit diff
path: root/src/libcore
diff options
context:
space:
mode:
authorBrian Anderson <banderson@mozilla.com>2012-09-11 19:37:29 -0700
committerBrian Anderson <banderson@mozilla.com>2012-09-11 19:41:07 -0700
commit2c6c963f61d84d2a959df0d5c82f519c157ef552 (patch)
tree39e1e9cd24b8db28302db9a0018192b097b77b75 /src/libcore
parentec225166cd73398052dcf4a2135cd1110856f4d1 (diff)
Convert core::extfmt to camel case
Diffstat (limited to 'src/libcore')
-rw-r--r--src/libcore/extfmt.rs339
1 files changed, 266 insertions, 73 deletions
diff --git a/src/libcore/extfmt.rs b/src/libcore/extfmt.rs
index cd22b2c5c04..e7b1ec517ec 100644
--- a/src/libcore/extfmt.rs
+++ b/src/libcore/extfmt.rs
@@ -1,5 +1,4 @@
 #[doc(hidden)];
-#[allow(non_camel_case_types)];
 
 /*
 Syntax Extension: fmt
@@ -43,53 +42,53 @@ use option::{Some, None};
 
 // Functions used by the fmt extension at compile time
 mod ct {
-    enum signedness { signed, unsigned, }
-    enum caseness { case_upper, case_lower, }
-    enum ty {
-        ty_bool,
-        ty_str,
-        ty_char,
-        ty_int(signedness),
-        ty_bits,
-        ty_hex(caseness),
-        ty_octal,
-        ty_float,
-        ty_poly,
-    }
-    enum flag {
-        flag_left_justify,
-        flag_left_zero_pad,
-        flag_space_for_sign,
-        flag_sign_always,
-        flag_alternate,
-    }
-    enum count {
-        count_is(int),
-        count_is_param(int),
-        count_is_next_param,
-        count_implied,
+    enum Signedness { Signed, Unsigned, }
+    enum Caseness { CaseUpper, CaseLower, }
+    enum Ty {
+        TyBool,
+        TyStr,
+        TyChar,
+        TyInt(Signedness),
+        TyBits,
+        TyHex(Caseness),
+        TyOctal,
+        TyFloat,
+        TyPoly,
+    }
+    enum Flag {
+        FlagLeftJustify,
+        FlagLeftZeroPad,
+        FlagSpaceForSign,
+        FlagSignAlways,
+        FlagAlternate,
+    }
+    enum Count {
+        CountIs(int),
+        CountIsParam(int),
+        CountIsNextParam,
+        CountImplied,
     }
 
     // A formatted conversion from an expression to a string
-    type conv =
+    type Conv =
         {param: Option<int>,
-         flags: ~[flag],
-         width: count,
-         precision: count,
-         ty: ty};
+         flags: ~[Flag],
+         width: Count,
+         precision: Count,
+         ty: Ty};
 
 
     // A fragment of the output sequence
-    enum piece { piece_string(~str), piece_conv(conv), }
-    type error_fn = fn@(~str) -> ! ;
+    enum Piece { PieceString(~str), PieceConv(Conv), }
+    type ErrorFn = fn@(~str) -> ! ;
 
-    fn parse_fmt_string(s: ~str, error: error_fn) -> ~[piece] {
-        let mut pieces: ~[piece] = ~[];
+    fn parse_fmt_string(s: ~str, error: ErrorFn) -> ~[Piece] {
+        let mut pieces: ~[Piece] = ~[];
         let lim = str::len(s);
         let mut buf = ~"";
-        fn flush_buf(+buf: ~str, &pieces: ~[piece]) -> ~str {
+        fn flush_buf(+buf: ~str, &pieces: ~[Piece]) -> ~str {
             if str::len(buf) > 0 {
-                let piece = piece_string(move buf);
+                let piece = PieceString(move buf);
                 vec::push(pieces, move piece);
             }
             return ~"";
@@ -140,15 +139,15 @@ mod ct {
             None
         }
     }
-    fn parse_conversion(s: ~str, i: uint, lim: uint, error: error_fn) ->
-       {piece: piece, next: uint} {
+    fn parse_conversion(s: ~str, i: uint, lim: uint, error: ErrorFn) ->
+       {piece: Piece, next: uint} {
         let parm = parse_parameter(s, i, lim);
         let flags = parse_flags(s, parm.next, lim);
         let width = parse_count(s, flags.next, lim);
         let prec = parse_precision(s, width.next, lim);
         let ty = parse_type(s, prec.next, lim, error);
         return {piece:
-                 piece_conv({param: parm.param,
+                 PieceConv({param: parm.param,
                              flags: copy flags.flags,
                              width: width.count,
                              precision: prec.count,
@@ -171,58 +170,58 @@ mod ct {
             };
     }
     fn parse_flags(s: ~str, i: uint, lim: uint) ->
-       {flags: ~[flag], next: uint} {
-        let noflags: ~[flag] = ~[];
+       {flags: ~[Flag], next: uint} {
+        let noflags: ~[Flag] = ~[];
         if i >= lim { return {flags: move noflags, next: i}; }
 
-        fn more_(f: flag, s: ~str, i: uint, lim: uint) ->
-           {flags: ~[flag], next: uint} {
+        fn more_(f: Flag, s: ~str, i: uint, lim: uint) ->
+           {flags: ~[Flag], next: uint} {
             let next = parse_flags(s, i + 1u, lim);
             let rest = copy next.flags;
             let j = next.next;
-            let curr: ~[flag] = ~[f];
+            let curr: ~[Flag] = ~[f];
             return {flags: vec::append(move curr, rest), next: j};
         }
         let more = |x, copy s| more_(x, copy s, i, lim);
         let f = s[i];
         return if f == '-' as u8 {
-                more(flag_left_justify)
+                more(FlagLeftJustify)
             } else if f == '0' as u8 {
-                more(flag_left_zero_pad)
+                more(FlagLeftZeroPad)
             } else if f == ' ' as u8 {
-                more(flag_space_for_sign)
+                more(FlagSpaceForSign)
             } else if f == '+' as u8 {
-                more(flag_sign_always)
+                more(FlagSignAlways)
             } else if f == '#' as u8 {
-                more(flag_alternate)
+                more(FlagAlternate)
             } else { {flags: move noflags, next: i} };
     }
     fn parse_count(s: ~str, i: uint, lim: uint)
-        -> {count: count, next: uint} {
+        -> {count: Count, next: uint} {
         return if i >= lim {
-                {count: count_implied, next: i}
+                {count: CountImplied, next: i}
             } else if s[i] == '*' as u8 {
                 let param = parse_parameter(s, i + 1u, lim);
                 let j = param.next;
                 match param.param {
-                  None => {count: count_is_next_param, next: j},
-                  Some(n) => {count: count_is_param(n), next: j}
+                  None => {count: CountIsNextParam, next: j},
+                  Some(n) => {count: CountIsParam(n), next: j}
                 }
             } else {
                 let num = peek_num(s, i, lim);
                 match num {
-                  None => {count: count_implied, next: i},
+                  None => {count: CountImplied, next: i},
                   Some(num) => {
-                    count: count_is(num.num as int),
+                    count: CountIs(num.num as int),
                     next: num.next
                   }
                 }
             };
     }
     fn parse_precision(s: ~str, i: uint, lim: uint) ->
-       {count: count, next: uint} {
+       {count: Count, next: uint} {
         return if i >= lim {
-                {count: count_implied, next: i}
+                {count: CountImplied, next: i}
             } else if s[i] == '.' as u8 {
                 let count = parse_count(s, i + 1u, lim);
 
@@ -230,40 +229,40 @@ mod ct {
                 // If there were no digits specified, i.e. the precision
                 // was ".", then the precision is 0
                 match count.count {
-                  count_implied => {count: count_is(0), next: count.next},
+                  CountImplied => {count: CountIs(0), next: count.next},
                   _ => count
                 }
-            } else { {count: count_implied, next: i} };
+            } else { {count: CountImplied, next: i} };
     }
-    fn parse_type(s: ~str, i: uint, lim: uint, error: error_fn) ->
-       {ty: ty, next: uint} {
+    fn parse_type(s: ~str, i: uint, lim: uint, error: ErrorFn) ->
+       {ty: Ty, next: uint} {
         if i >= lim { error(~"missing type in conversion"); }
         let tstr = str::slice(s, i, i+1u);
         // FIXME (#2249): Do we really want two signed types here?
         // How important is it to be printf compatible?
         let t =
             if tstr == ~"b" {
-                ty_bool
+                TyBool
             } else if tstr == ~"s" {
-                ty_str
+                TyStr
             } else if tstr == ~"c" {
-                ty_char
+                TyChar
             } else if tstr == ~"d" || tstr == ~"i" {
-                ty_int(signed)
+                TyInt(Signed)
             } else if tstr == ~"u" {
-                ty_int(unsigned)
+                TyInt(Unsigned)
             } else if tstr == ~"x" {
-                ty_hex(case_lower)
+                TyHex(CaseLower)
             } else if tstr == ~"X" {
-                ty_hex(case_upper)
+                TyHex(CaseUpper)
             } else if tstr == ~"t" {
-                ty_bits
+                TyBits
             } else if tstr == ~"o" {
-                ty_octal
+                TyOctal
             } else if tstr == ~"f" {
-                ty_float
+                TyFloat
             } else if tstr == ~"?" {
-                ty_poly
+                TyPoly
             } else { error(~"unknown type in conversion: " + tstr) };
         return {ty: t, next: i + 1u};
     }
@@ -274,6 +273,199 @@ mod ct {
 // decisions made a runtime. If it proves worthwhile then some of these
 // conditions can be evaluated at compile-time. For now though it's cleaner to
 // implement it 0this way, I think.
+#[cfg(stage1)]
+#[cfg(stage2)]
+#[cfg(stage3)]
+mod rt {
+    const flag_none : u32 = 0u32;
+    const flag_left_justify   : u32 = 0b00000000000000000000000000000001u32;
+    const flag_left_zero_pad  : u32 = 0b00000000000000000000000000000010u32;
+    const flag_space_for_sign : u32 = 0b00000000000000000000000000000100u32;
+    const flag_sign_always    : u32 = 0b00000000000000000000000000001000u32;
+    const flag_alternate      : u32 = 0b00000000000000000000000000010000u32;
+
+    enum Count { CountIs(int), CountImplied, }
+    enum Ty { TyDefault, TyBits, TyHexUpper, TyHexLower, TyOctal, }
+
+    type Conv = {flags: u32, width: Count, precision: Count, ty: Ty};
+
+    pure fn conv_int(cv: Conv, i: int) -> ~str {
+        let radix = 10u;
+        let prec = get_int_precision(cv);
+        let mut s : ~str = int_to_str_prec(i, radix, prec);
+        if 0 <= i {
+            if have_flag(cv.flags, flag_sign_always) {
+                unchecked { str::unshift_char(s, '+') };
+            } else if have_flag(cv.flags, flag_space_for_sign) {
+                unchecked { str::unshift_char(s, ' ') };
+            }
+        }
+        return unchecked { pad(cv, s, PadSigned) };
+    }
+    pure fn conv_uint(cv: Conv, u: uint) -> ~str {
+        let prec = get_int_precision(cv);
+        let mut rs =
+            match cv.ty {
+              TyDefault => uint_to_str_prec(u, 10u, prec),
+              TyHexLower => uint_to_str_prec(u, 16u, prec),
+              TyHexUpper => str::to_upper(uint_to_str_prec(u, 16u, prec)),
+              TyBits => uint_to_str_prec(u, 2u, prec),
+              TyOctal => uint_to_str_prec(u, 8u, prec)
+            };
+        return unchecked { pad(cv, rs, PadUnsigned) };
+    }
+    pure fn conv_bool(cv: Conv, b: bool) -> ~str {
+        let s = if b { ~"true" } else { ~"false" };
+        // run the boolean conversion through the string conversion logic,
+        // giving it the same rules for precision, etc.
+        return conv_str(cv, s);
+    }
+    pure fn conv_char(cv: Conv, c: char) -> ~str {
+        let mut s = str::from_char(c);
+        return unchecked { pad(cv, s, PadNozero) };
+    }
+    pure fn conv_str(cv: Conv, s: &str) -> ~str {
+        // For strings, precision is the maximum characters
+        // displayed
+        let mut unpadded = match cv.precision {
+          CountImplied => s.to_unique(),
+          CountIs(max) => if max as uint < str::char_len(s) {
+            str::substr(s, 0u, max as uint)
+          } else {
+            s.to_unique()
+          }
+        };
+        return unchecked { pad(cv, unpadded, PadNozero) };
+    }
+    pure fn conv_float(cv: Conv, f: float) -> ~str {
+        let (to_str, digits) = match cv.precision {
+              CountIs(c) => (float::to_str_exact, c as uint),
+              CountImplied => (float::to_str, 6u)
+        };
+        let mut s = unchecked { to_str(f, digits) };
+        if 0.0 <= f {
+            if have_flag(cv.flags, flag_sign_always) {
+                s = ~"+" + s;
+            } else if have_flag(cv.flags, flag_space_for_sign) {
+                s = ~" " + s;
+            }
+        }
+        return unchecked { pad(cv, s, PadFloat) };
+    }
+    pure fn conv_poly<T>(cv: Conv, v: T) -> ~str {
+        let s = sys::log_str(v);
+        return conv_str(cv, s);
+    }
+
+    // Convert an int to string with minimum number of digits. If precision is
+    // 0 and num is 0 then the result is the empty string.
+    pure fn int_to_str_prec(num: int, radix: uint, prec: uint) -> ~str {
+        return if num < 0 {
+                ~"-" + uint_to_str_prec(-num as uint, radix, prec)
+            } else { uint_to_str_prec(num as uint, radix, prec) };
+    }
+
+    // Convert a uint to string with a minimum number of digits.  If precision
+    // is 0 and num is 0 then the result is the empty string. Could move this
+    // to uint: but it doesn't seem all that useful.
+    pure fn uint_to_str_prec(num: uint, radix: uint, prec: uint) -> ~str {
+        return if prec == 0u && num == 0u {
+                ~""
+            } else {
+                let s = uint::to_str(num, radix);
+                let len = str::char_len(s);
+                if len < prec {
+                    let diff = prec - len;
+                    let pad = str::from_chars(vec::from_elem(diff, '0'));
+                    pad + s
+                } else { move s }
+            };
+    }
+    pure fn get_int_precision(cv: Conv) -> uint {
+        return match cv.precision {
+              CountIs(c) => c as uint,
+              CountImplied => 1u
+            };
+    }
+
+    enum PadMode { PadSigned, PadUnsigned, PadNozero, PadFloat }
+
+    impl PadMode: Eq {
+        pure fn eq(&&other: PadMode) -> bool {
+            match (self, other) {
+                (PadSigned, PadSigned) => true,
+                (PadUnsigned, PadUnsigned) => true,
+                (PadNozero, PadNozero) => true,
+                (PadFloat, PadFloat) => true,
+                (PadSigned, _) => false,
+                (PadUnsigned, _) => false,
+                (PadNozero, _) => false,
+                (PadFloat, _) => false
+            }
+        }
+        pure fn ne(&&other: PadMode) -> bool { !self.eq(other) }
+    }
+
+    fn pad(cv: Conv, &s: ~str, mode: PadMode) -> ~str {
+        let uwidth : uint = match cv.width {
+          CountImplied => return copy s,
+          CountIs(width) => {
+              // FIXME: width should probably be uint (see Issue #1996)
+              width as uint
+          }
+        };
+        let strlen = str::char_len(s);
+        if uwidth <= strlen { return copy s; }
+        let mut padchar = ' ';
+        let diff = uwidth - strlen;
+        if have_flag(cv.flags, flag_left_justify) {
+            let padstr = str::from_chars(vec::from_elem(diff, padchar));
+            return s + padstr;
+        }
+        let {might_zero_pad, signed} = match mode {
+          PadNozero => {might_zero_pad:false, signed:false},
+          PadSigned => {might_zero_pad:true,  signed:true },
+          PadFloat => {might_zero_pad:true,  signed:true},
+          PadUnsigned => {might_zero_pad:true,  signed:false}
+        };
+        pure fn have_precision(cv: Conv) -> bool {
+            return match cv.precision { CountImplied => false, _ => true };
+        }
+        let zero_padding = {
+            if might_zero_pad && have_flag(cv.flags, flag_left_zero_pad) &&
+                (!have_precision(cv) || mode == PadFloat) {
+                padchar = '0';
+                true
+            } else {
+                false
+            }
+        };
+        let padstr = str::from_chars(vec::from_elem(diff, padchar));
+        // This is completely heinous. If we have a signed value then
+        // potentially rip apart the intermediate result and insert some
+        // zeros. It may make sense to convert zero padding to a precision
+        // instead.
+
+        if signed && zero_padding && str::len(s) > 0u {
+            let head = str::shift_char(s);
+            if head == '+' || head == '-' || head == ' ' {
+                let headstr = str::from_chars(vec::from_elem(1u, head));
+                return headstr + padstr + s;
+            }
+            else {
+                str::unshift_char(s, head);
+            }
+        }
+        return padstr + s;
+    }
+    pure fn have_flag(flags: u32, f: u32) -> bool {
+        flags & f != 0
+    }
+}
+
+// XXX remove after snappies
+#[cfg(stage0)]
+#[allow(non_camel_case_types)]
 mod rt {
     const flag_none : u32 = 0u32;
     const flag_left_justify   : u32 = 0b00000000000000000000000000000001u32;
@@ -461,6 +653,7 @@ mod rt {
     }
 }
 
+
 #[cfg(test)]
 mod test {
     #[test]