on 01bcbbe help sign in
7 files changed+58−20
since splitsnapshots
unifiedsplit
Data/Text.hs+1−1 Data/Text/Internal/Fusion/Common.hs+10−9 Data/Text/Lazy/Read.hs+3−3 Data/Text/Read.hs+3−3 changelog.md+11 tests/Tests/Properties.hs+13−2 tests/text-tests.cabal+17−2
Data/Text.hs+1−1
@@ -1099,8 +1099,8 @@ takeEnd n t@(Text arr off len)
10991099iterNEnd :: Int -> Text -> Int
11001100iterNEnd n t@(Text _arr _off len) = loop (len-1) n
11011101 where loop i !m
1102+ | m <= 0 = i+1
11021103 | i <= 0 = 0
1103− | m <= 1 = i
11041104 | otherwise = loop (i+d) (m-1)
11051105 where d = reverseIter_ t i
11061106
Data/Text/Internal/Fusion/Common.hs+10−9
@@ -107,7 +107,7 @@ import Prelude (Bool(..), Char, Eq(..), Int, Integral, Maybe(..),
107107import qualified Data.List as L
108108import qualified Prelude as P
109109import Data.Bits (shiftL)
110−import Data.Char (isLetter)
110+import Data.Char (isLetter, isSpace)
111111import Data.Int (Int64)
112112import Data.Text.Internal.Fusion.Types
113113import Data.Text.Internal.Fusion.CaseMapping (foldMapping, lowerMapping, titleMapping,
@@ -462,15 +462,16 @@ toTitle (Stream next0 s0 len) = Stream next (CC (False :*: s0) '\0' '\0') len
462462 where
463463 next (CC (letter :*: s) '\0' _) =
464464 case next0 s of
465− Done -> Done
466− Skip s' -> Skip (CC (letter :*: s') '\0' '\0')
465+ Done -> Done
466+ Skip s' -> Skip (CC (letter :*: s') '\0' '\0')
467467 Yield c s'
468− | letter' -> if letter
469− then lowerMapping c (letter' :*: s')
470− else titleMapping c (letter' :*: s')
471− | otherwise -> Yield c (CC (letter' :*: s') '\0' '\0')
472− where letter' = isLetter c
473− next (CC s a b) = Yield a (CC s b '\0')
468+ | nonSpace -> if letter
469+ then lowerMapping c (nonSpace :*: s')
470+ else titleMapping c (letter' :*: s')
471+ | otherwise -> Yield c (CC (letter' :*: s') '\0' '\0')
472+ where nonSpace = P.not (isSpace c)
473+ letter' = isLetter c
474+ next (CC s a b) = Yield a (CC s b '\0')
474475{-# INLINE [0] toTitle #-}
475476
476477data Justify i s = Just1 !i !s
Data/Text/Lazy/Read.hs+3−3
@@ -68,9 +68,9 @@ decimal txt
6868 go n d = (n * 10 + fromIntegral (digitToInt d))
6969
7070-- | Read a hexadecimal integer, consisting of an optional leading
71−-- @\"0x\"@ followed by at least one decimal digit. Input is consumed
72−-- until a non-hex-digit or end of string is reached. This function
73−-- is case insensitive.
71+-- @\"0x\"@ followed by at least one hexadecimal digit. Input is
72+-- consumed until a non-hex-digit or end of string is reached.
73+-- This function is case insensitive.
7474--
7575-- This function does not handle leading sign characters. If you need
7676-- to handle signed input, use @'signed' 'hexadecimal'@.
Data/Text/Read.hs+3−3
@@ -67,9 +67,9 @@ decimal txt
6767 go n d = (n * 10 + fromIntegral (digitToInt d))
6868
6969-- | Read a hexadecimal integer, consisting of an optional leading
70−-- @\"0x\"@ followed by at least one decimal digit. Input is consumed
71−-- until a non-hex-digit or end of string is reached. This function
72−-- is case insensitive.
70+-- @\"0x\"@ followed by at least one hexadecimal digit. Input is
71+-- consumed until a non-hex-digit or end of string is reached.
72+-- This function is case insensitive.
7373--
7474-- This function does not handle leading sign characters. If you need
7575-- to handle signed input, use @'signed' 'hexadecimal'@.
changelog.md+11
@@ -1,3 +1,14 @@
1+* The `toTitle` function now correctly handles letters that
2+ immediately follow puncutation. Before, `"there's"` would turn into
3+ `"There'S"`. Now, it becomes `"There's"`.
4+
5+* The implementation of unstreaming is faster, resulting in operations
6+ such as `map` and `intersperse` speeding up by up to 30%, with
7+ smaller code generated.
8+
9+* The optimised length comparison function is now more likely to be
10+ used after some rewrite rule tweaking.
11+
1121.2.2.1
213
314* The switch to `integer-pure` in 1.2.2.0 was apparently mistaken.
tests/Tests/Properties.hs+13−2
@@ -11,7 +11,7 @@ module Tests.Properties
1111import Control.Applicative ((<$>), (<*>))
1212import Control.Arrow ((***), second)
1313import Data.Bits ((.&.))
14−import Data.Char (chr, isDigit, isHexDigit, isLower, isSpace, isUpper, ord)
14+import Data.Char (chr, isDigit, isHexDigit, isLower, isSpace, isLetter, isUpper, ord)
1515import Data.Int (Int8, Int16, Int32, Int64)
1616import Data.Monoid (Monoid(..))
1717import Data.String (IsString(fromString))
@@ -23,6 +23,7 @@ import Data.Text.Internal.Search (indices)
2323import Data.Text.Lazy.Read as TL
2424import Data.Text.Read as T
2525import Data.Word (Word, Word8, Word16, Word32, Word64)
26+import Data.Maybe (mapMaybe)
2627import Numeric (showEFloat, showFFloat, showGFloat, showHex)
2728import Prelude hiding (replicate)
2829import Test.Framework (Test, testGroup)
@@ -326,6 +327,14 @@ t_toUpper_upper t = p (T.toUpper t) >= p t
326327 where p = T.length . T.filter isUpper
327328tl_toUpper_upper t = p (TL.toUpper t) >= p t
328329 where p = TL.length . TL.filter isUpper
330+t_toTitle_title t = all (<= 1) (caps t)
331+ where caps = fmap (T.length . T.filter isUpper) . T.words . T.toTitle
332+t_toTitle_1stNotLower = and . notLow . T.toTitle . T.filter stable
333+ where notLow = mapMaybe (fmap (not . isLower) . (T.find isLetter)) . T.words
334+ -- Surprise! The Spanish/Portuguese ordinal indicators changed
335+ -- from category Ll (letter, lowercase) to Lo (letter, other)
336+ -- in Unicode 7.0
337+ stable c = c /= '\170' && c /= '\186'
329338
330339justifyLeft k c xs = xs ++ L.replicate (k - length xs) c
331340justifyRight m n xs = L.replicate (m - length xs) n ++ xs
@@ -1030,7 +1039,9 @@ tests =
10301039 testProperty "tl_toLower_lower" tl_toLower_lower,
10311040 testProperty "t_toUpper_length" t_toUpper_length,
10321041 testProperty "t_toUpper_upper" t_toUpper_upper,
1033− testProperty "tl_toUpper_upper" tl_toUpper_upper
1042+ testProperty "tl_toUpper_upper" tl_toUpper_upper,
1043+ testProperty "t_toTitle_title" t_toTitle_title,
1044+ testProperty "t_toTitle_1stNotLower" t_toTitle_1stNotLower
10341045 ],
10351046
10361047 testGroup "justification" [
tests/text-tests.cabal+17−2
@@ -20,6 +20,11 @@ flag hpc
2020 default: False
2121 manual: True
2222
23+flag bytestring-builder
24+ description: Depend on the bytestring-builder package for backwards compatibility.
25+ default: False
26+ manual: False
27+
2328executable text-tests
2429 main-is: Tests.hs
2530
@@ -48,7 +53,6 @@ executable text-tests
4853 HUnit >= 1.2,
4954 QuickCheck >= 2.7,
5055 base == 4.*,
51− bytestring,
5256 deepseq,
5357 directory,
5458 quickcheck-unicode,
@@ -58,6 +62,12 @@ executable text-tests
5862 test-framework-quickcheck2 >= 0.2,
5963 text-tests
6064
65+ if flag(bytestring-builder)
66+ build-depends: bytestring >= 0.9 && < 0.10.4,
67+ bytestring-builder >= 0.10.4
68+ else
69+ build-depends: bytestring >= 0.10.4
70+
6171executable text-tests-stdio
6272 main-is: Tests/IO.hs
6373
@@ -137,7 +147,12 @@ library
137147 array,
138148 base == 4.*,
139149 binary,
140− bytestring,
141150 deepseq,
142151 ghc-prim,
143152 integer-gmp
153+
154+ if flag(bytestring-builder)
155+ build-depends: bytestring >= 0.9 && < 0.10.4,
156+ bytestring-builder >= 0.10.4
157+ else
158+ build-depends: bytestring >= 0.10.4