git.iko.soy/typeable/attoparsec
on 0.12.1.6 help sign in
123 lines 4.6 kB history raw
1{-# OPTIONS_GHC -Wall -fwarn-tabs #-}
2{-# LANGUAGE ForeignFunctionInterface #-}
3----------------------------------------------------------------
4-- 2010.10.09
5-- |
6-- Module : IsSpace
7-- Copyright : Copyright (c) 2010 wren ng thornton
8-- License : BSD
9-- Maintainer : wren@community.haskell.org
10-- Stability : experimental
11-- Portability : portable (FFI)
12--
13-- A benchmark for comparing different definitions of predicates
14-- for detecting whitespace. As of the last run the results are:
15--
16-- * Data.Char.isSpace : 14.44786 us +/- 258.0377 ns
17-- * isSpace_DataChar : 43.25154 us +/- 655.7037 ns
18-- * isSpace_Char : 29.26598 us +/- 454.1445 ns
19-- * isPerlSpace :
20-- * Data.Attoparsec.Char8.isSpace : 81.87335 us +/- 1.195903 us
21-- * isSpace_Char8 : 11.84677 us +/- 178.9795 ns
22-- * isSpace_w8 : 11.55470 us +/- 133.7644 ns
23----------------------------------------------------------------
24module IsSpace (main) where
26import qualified Data.Char as C
27import Data.Word (Word8)
28import qualified Data.ByteString as B
29import qualified Data.ByteString.Char8 as B8
30import Foreign.C.Types (CInt)
32import Criterion (bench, nf)
33import Criterion.Main (defaultMain)
35----------------------------------------------------------------
36----- Character predicates
37-- N.B. \x9..\xD == "\t\n\v\f\r"
39-- | Recognize the same characters as Perl's @/\s/@ in Unicode mode.
40-- In particular, we recognize POSIX 1003.2 @[[:space:]]@ except
41-- @\'\v\'@, and recognize the Unicode @\'\x85\'@, @\'\x2028\'@,
42-- @\'\x2029\'@. Notably, @\'\x85\'@ belongs to Latin-1 (but not
43-- ASCII) and therefore does not belong to POSIX 1003.2 @[[:space:]]@
44-- (nor non-Unicode @/\s/@).
45isPerlSpace :: Char -> Bool
46isPerlSpace c
47 = (' ' == c)
48 || ('\t' <= c && c <= '\r' && c /= '\v')
49 || ('\x85' == c)
50 || ('\x2028' == c)
51 || ('\x2029' == c)
52{-# INLINE isPerlSpace #-}
55-- | 'Data.Attoparsec.Char8.isSpace', duplicated here because it's
56-- not exported. This is the definition as of attoparsec-0.8.1.0.
57isSpace :: Char -> Bool
58isSpace c = c `B8.elem` spaces
59 where
60 spaces = B8.pack " \n\r\t\v\f"
61 {-# NOINLINE spaces #-}
62{-# INLINE isSpace #-}
65-- | An alternate version of 'Data.Attoparsec.Char8.isSpace'.
66isSpace_Char8 :: Char -> Bool
67isSpace_Char8 c = (' ' == c) || ('\t' <= c && c <= '\r')
68{-# INLINE isSpace_Char8 #-}
71-- | An alternate version of 'Data.Char.isSpace'. This uses the
72-- same trick as 'isSpace_Char8' but we include Unicode whitespaces
73-- too, in order to have the same results as 'Data.Char.isSpace'
74-- (whereas 'isSpace_Char8' doesn't recognize Unicode whitespace).
75isSpace_Char :: Char -> Bool
76isSpace_Char c
77 = (' ' == c)
78 || ('\t' <= c && c <= '\r')
79 || ('\xA0' == c)
80 || (iswspace (fromIntegral (C.ord c)) /= 0)
81{-# INLINE isSpace_Char #-}
83foreign import ccall unsafe "u_iswspace"
84 iswspace :: CInt -> CInt
86-- | Verbatim version of 'Data.Char.isSpace' (i.e., 'GHC.Unicode.isSpace'
87-- as of base-4.2.0.2) in order to try to figure out why 'isSpace_Char'
88-- is slower than 'Data.Char.isSpace'. It appears to be something
89-- special in how the base library was compiled.
90isSpace_DataChar :: Char -> Bool
91isSpace_DataChar c =
92 c == ' ' ||
93 c == '\t' ||
94 c == '\n' ||
95 c == '\r' ||
96 c == '\f' ||
97 c == '\v' ||
98 c == '\xa0' ||
99 iswspace (fromIntegral (C.ord c)) /= 0
100{-# INLINE isSpace_DataChar #-}
103-- | A 'Word8' version of 'Data.Attoparsec.Char8.isSpace'.
104isSpace_w8 :: Word8 -> Bool
105isSpace_w8 w = (w == 32) || (9 <= w && w <= 13)
106{-# INLINE isSpace_w8 #-}
108----------------------------------------------------------------
110main :: IO ()
111main = defaultMain
112 [ bench "Data.Char.isSpace" $ nf (map C.isSpace) ['\x0'..'\255']
113 , bench "isSpace_DataChar" $ nf (map isSpace_DataChar) ['\x0'..'\255']
114 , bench "isSpace_Char" $ nf (map isSpace_Char) ['\x0'..'\255']
115 , bench "isPerlSpace" $ nf (map isPerlSpace) ['\x0'..'\255']
116 , bench "Data.Attoparsec.Char8.isSpace"
117 $ nf (map isSpace) ['\x0'..'\255']
118 , bench "isSpace_Char8" $ nf (map isSpace_Char8) ['\x0'..'\255']
119 , bench "isSpace_w8" $ nf (map isSpace_w8) [0..255]
120 ]
122----------------------------------------------------------------
123----------------------------------------------------------- fin.