on master help sign in
Get rendering of numbers working in all cases
commit0d6703c3df9b2449206eb82422515261f7faf710 authorBryan O'Sullivan <bos@serpentine.com> dateThu 28 Jun 2012, 23:20 (14 years ago) parentfa37514
1 file changed+46−16
Data/Text/Lazy/Builder/Int.hs+46−16
Data/Text/Lazy/Builder/Int.hs+46−16
@@ -1,6 +1,6 @@
11{-# LANGUAGE BangPatterns, CPP, MagicHash, UnboxedTuples #-}
22
3−-- Module: Data.Text.Lazy.Builder.Int
3+-- Module: Data.Text.Lazy.Builder.Intxo
44-- Copyright: (c) 2011 MailRank, Inc.
55-- License: BSD3
66-- Maintainer: Bryan O'Sullivan <bos@serpentine.com>
@@ -19,6 +19,7 @@ import Data.Int (Int8, Int16, Int32, Int64)
1919import Data.Monoid (mempty)
2020import Data.Text.Lazy.Builder.Functions ((<>), i2d)
2121import Data.Text.Lazy.Builder
22+import Data.Text.Lazy (pack)
2223import Data.Word (Word, Word8, Word16, Word32, Word64)
2324import GHC.Base (quotInt, remInt)
2425import GHC.Num (quotRemInteger)
@@ -43,23 +44,51 @@ import GHC.Integer
4344#endif
4445
4546decimal :: Integral a => a -> Builder
46−{-# SPECIALIZE decimal :: Int -> Builder #-}
4747{-# SPECIALIZE decimal :: Int8 -> Builder #-}
48−{-# SPECIALIZE decimal :: Int16 -> Builder #-}
49−{-# SPECIALIZE decimal :: Int32 -> Builder #-}
50−{-# SPECIALIZE decimal :: Int64 -> Builder #-}
51−{-# SPECIALIZE decimal :: Word -> Builder #-}
52−{-# SPECIALIZE decimal :: Word8 -> Builder #-}
53−{-# SPECIALIZE decimal :: Word16 -> Builder #-}
54−{-# SPECIALIZE decimal :: Word32 -> Builder #-}
55−{-# SPECIALIZE decimal :: Word64 -> Builder #-}
48+{-# RULES "decimal/Int" decimal = boundedDecimal :: Int -> Builder #-}
49+{-# RULES "decimal/Int16" decimal = boundedDecimal :: Int16 -> Builder #-}
50+{-# RULES "decimal/Int32" decimal = boundedDecimal :: Int32 -> Builder #-}
51+{-# RULES "decimal/Int64" decimal = boundedDecimal :: Int64 -> Builder #-}
52+{-# RULES "decimal/Word" decimal = positive :: Word -> Builder #-}
53+{-# RULES "decimal/Word8" decimal = positive :: Word8 -> Builder #-}
54+{-# RULES "decimal/Word16" decimal = positive :: Word16 -> Builder #-}
55+{-# RULES "decimal/Word32" decimal = positive :: Word32 -> Builder #-}
56+{-# RULES "decimal/Word64" decimal = positive :: Word64 -> Builder #-}
5657{-# RULES "decimal/Integer" decimal = integer 10 :: Integer -> Builder #-}
5758decimal i
58− | i < 0 = singleton '-' <> go (-i)
59− | otherwise = go i
60− where
61− go n | n < 10 = digit n
62− | otherwise = go (n `quot` 10) <> digit (n `rem` 10)
59+ | i < 0 = singleton '-' <>
60+ if i <= -128
61+ then positive (-(i `quot` 10)) <> digit (-(i `rem` 10))
62+ else positive (-i)
63+ | otherwise = positive i
64+
65+boundedDecimal :: (Integral a, Bounded a) => a -> Builder
66+{-# SPECIALIZE boundedDecimal :: Int -> Builder #-}
67+{-# SPECIALIZE boundedDecimal :: Int8 -> Builder #-}
68+{-# SPECIALIZE boundedDecimal :: Int16 -> Builder #-}
69+{-# SPECIALIZE boundedDecimal :: Int32 -> Builder #-}
70+{-# SPECIALIZE boundedDecimal :: Int64 -> Builder #-}
71+boundedDecimal i
72+ | i < 0 = singleton '-' <>
73+ if i == minBound
74+ then positive (-(i `quot` 10)) <> digit (-(i `rem` 10))
75+ else positive (-i)
76+ | otherwise = positive i
77+
78+positive :: (Integral a) => a -> Builder
79+{-# SPECIALIZE positive :: Int -> Builder #-}
80+{-# SPECIALIZE positive :: Int8 -> Builder #-}
81+{-# SPECIALIZE positive :: Int16 -> Builder #-}
82+{-# SPECIALIZE positive :: Int32 -> Builder #-}
83+{-# SPECIALIZE positive :: Int64 -> Builder #-}
84+{-# SPECIALIZE positive :: Word -> Builder #-}
85+{-# SPECIALIZE positive :: Word8 -> Builder #-}
86+{-# SPECIALIZE positive :: Word16 -> Builder #-}
87+{-# SPECIALIZE positive :: Word32 -> Builder #-}
88+{-# SPECIALIZE positive :: Word64 -> Builder #-}
89+positive = go
90+ where go n | n < 10 = digit n
91+ | otherwise = go (n `quot` 10) <> digit (n `rem` 10)
6392
6493hexadecimal :: Integral a => a -> Builder
6594{-# SPECIALIZE hexadecimal :: Int -> Builder #-}
@@ -74,11 +103,12 @@ hexadecimal :: Integral a => a -> Builder
74103{-# SPECIALIZE hexadecimal :: Word64 -> Builder #-}
75104{-# RULES "hexadecimal/Integer" hexadecimal = integer 16 :: Integer -> Builder #-}
76105hexadecimal i
77− | i < 0 = singleton '-' <> go (-i)
106+ | i < 0 = error msg
78107 | otherwise = go i
79108 where
80109 go n | n < 16 = hexDigit n
81110 | otherwise = go (n `quot` 16) <> hexDigit (n `rem` 16)
111+ msg = "Data.Text.Lazy.Builder.Int.hexadecimal: applied to negative number"
82112
83113digit :: Integral a => a -> Builder
84114digit n = singleton $! i2d (fromIntegral n)