git.iko.soy/typeable/attoparsec
on master help sign in
.travis.yml+149−79
since splitsnapshots
unifiedsplit
@@ -1,91 +1,161 @@
1−# This file has been generated -- see https://github.com/hvr/multi-ghc-travis
1+# This Travis job script has been generated by a script via
2+#
3+# haskell-ci '--tests-jobs=>=7.4' '--no-benchmarks' 'attoparsec.cabal'
4+#
5+# For more information, see https://github.com/haskell-CI/haskell-ci
6+#
7+# version: 0.3.20190815
8+#
2language: c
9language: c
3−sudo: false
10+dist: xenial
4−
11+git:
5−# Bryan threatens to turn off Travis-CI if he gets any email :-)
12+ # whether to recursively clone submodules
6−notifications:
7− email: false
13+ submodules: false
8−
9cache:
14cache:
10 directories:
15 directories:
11− - $HOME/.cabsnap
12 - $HOME/.cabal/packages
16 - $HOME/.cabal/packages
13−
17+ - $HOME/.cabal/store
14before_cache:
18before_cache:
15− - rm -fv $HOME/.cabal/packages/hackage.haskell.org/build-reports.log
19+ - rm -fv $CABALHOME/packages/hackage.haskell.org/build-reports.log
20+ # remove files that are regenerated by 'cabal update'
16− - rm -fv $HOME/.cabal/packages/hackage.haskell.org/00-index.tar
21+ - rm -fv $CABALHOME/packages/hackage.haskell.org/00-index.*
17−
22+ - rm -fv $CABALHOME/packages/hackage.haskell.org/*.json
23+ - rm -fv $CABALHOME/packages/hackage.haskell.org/01-index.cache
24+ - rm -fv $CABALHOME/packages/hackage.haskell.org/01-index.tar
25+ - rm -fv $CABALHOME/packages/hackage.haskell.org/01-index.tar.idx
26+ - rm -rfv $CABALHOME/packages/head.hackage
18matrix:
27matrix:
19 include:
28 include:
20− - env: CABALVER=1.16 GHCVER=7.4.2
29+ - compiler: ghc-8.8.1
21− compiler: ": #GHC 7.4.2"
30+ addons: {"apt":{"sources":["hvr-ghc"],"packages":["ghc-8.8.1","cabal-install-3.0"]}}
31+ - compiler: ghc-8.6.5
32+ addons: {"apt":{"sources":["hvr-ghc"],"packages":["ghc-8.6.5","cabal-install-2.4"]}}
33+ - compiler: ghc-8.4.4
34+ addons: {"apt":{"sources":["hvr-ghc"],"packages":["ghc-8.4.4","cabal-install-2.4"]}}
35+ - compiler: ghc-8.2.2
22− addons: {apt: {packages: [cabal-install-1.16,ghc-7.4.2], sources: [hvr-ghc]}}
36+ addons: {"apt":{"sources":["hvr-ghc"],"packages":["ghc-8.2.2","cabal-install-2.4"]}}
23− - env: CABALVER=1.16 GHCVER=7.6.3
37+ - compiler: ghc-8.0.2
24− compiler: ": #GHC 7.6.3"
38+ addons: {"apt":{"sources":["hvr-ghc"],"packages":["ghc-8.0.2","cabal-install-2.4"]}}
39+ - compiler: ghc-7.10.3
40+ addons: {"apt":{"sources":["hvr-ghc"],"packages":["ghc-7.10.3","cabal-install-2.4"]}}
41+ - compiler: ghc-7.8.4
25− addons: {apt: {packages: [cabal-install-1.16,ghc-7.6.3], sources: [hvr-ghc]}}
42+ addons: {"apt":{"sources":["hvr-ghc"],"packages":["ghc-7.8.4","cabal-install-2.4"]}}
26− - env: CABALVER=1.18 GHCVER=7.8.4
43+ - compiler: ghc-7.6.3
27− compiler: ": #GHC 7.8.4"
44+ addons: {"apt":{"sources":["hvr-ghc"],"packages":["ghc-7.6.3","cabal-install-2.4"]}}
28− addons: {apt: {packages: [cabal-install-1.18,ghc-7.8.4], sources: [hvr-ghc]}}
45+ - compiler: ghc-7.4.2
29− - env: CABALVER=1.22 GHCVER=7.10.3
46+ addons: {"apt":{"sources":["hvr-ghc"],"packages":["ghc-7.4.2","cabal-install-2.4"]}}
30− compiler: ": #GHC 7.10.3"
47+ - compiler: ghc-7.2.2
31− addons: {apt: {packages: [cabal-install-1.22,ghc-7.10.3], sources: [hvr-ghc]}}
48+ addons: {"apt":{"sources":["hvr-ghc"],"packages":["ghc-7.2.2","cabal-install-2.4"]}}
32− - env: CABALVER=1.24 GHCVER=8.0.1
33− compiler: ": #GHC 8.0.1"
49+ - compiler: ghc-7.0.4
34− addons: {apt: {packages: [cabal-install-1.24,ghc-8.0.1], sources: [hvr-ghc]}}
50+ addons: {"apt":{"sources":["hvr-ghc"],"packages":["ghc-7.0.4","cabal-install-2.4"]}}
35−
36before_install:
51before_install:
52+ - HC=$(echo "/opt/$CC/bin/ghc" | sed 's/-/\//')
53+ - WITHCOMPILER="-w $HC"
54+ - HCPKG="$HC-pkg"
37− - unset CC
55+ - unset CC
38− - export PATH=/opt/ghc/$GHCVER/bin:/opt/cabal/$CABALVER/bin:$PATH
56+ - CABAL=/opt/ghc/bin/cabal
39−
57+ - CABALHOME=$HOME/.cabal
58+ - export PATH="$CABALHOME/bin:$PATH"
59+ - TOP=$(pwd)
60+ - "HCNUMVER=$(${HC} --numeric-version|perl -ne '/^(\\d+)\\.(\\d+)\\.(\\d+)(\\.(\\d+))?$/; print(10000 * $1 + 100 * $2 + ($3 == 0 ? $5 != 1 : $3))')"
61+ - echo $HCNUMVER
62+ - CABAL="$CABAL -vnormal+nowrap+markoutput"
63+ - set -o pipefail
64+ - |
65+ echo 'function blue(s) { printf "\033[0;34m" s "\033[0m " }' >> .colorful.awk
66+ echo 'BEGIN { state = "output"; }' >> .colorful.awk
67+ echo '/^-----BEGIN CABAL OUTPUT-----$/ { state = "cabal" }' >> .colorful.awk
68+ echo '/^-----END CABAL OUTPUT-----$/ { state = "output" }' >> .colorful.awk
69+ echo '!/^(-----BEGIN CABAL OUTPUT-----|-----END CABAL OUTPUT-----)/ {' >> .colorful.awk
70+ echo ' if (state == "cabal") {' >> .colorful.awk
71+ echo ' print blue($0)' >> .colorful.awk
72+ echo ' } else {' >> .colorful.awk
73+ echo ' print $0' >> .colorful.awk
74+ echo ' }' >> .colorful.awk
75+ echo '}' >> .colorful.awk
76+ - cat .colorful.awk
77+ - |
78+ color_cabal_output () {
79+ awk -f $TOP/.colorful.awk
80+ }
81+ - echo text | color_cabal_output
40install:
82install:
41− - cabal --version
83+ - ${CABAL} --version
42− - echo "$(ghc --version) [$(ghc --print-project-git-commit-id 2> /dev/null || echo '?')]"
84+ - echo "$(${HC} --version) [$(${HC} --print-project-git-commit-id 2> /dev/null || echo '?')]"
43− - if [ -f $HOME/.cabal/packages/hackage.haskell.org/00-index.tar.gz ];
85+ - TEST=--enable-tests
44− then
86+ - if [ $HCNUMVER -lt 70400 ] ; then TEST=--disable-tests ; fi
45− zcat $HOME/.cabal/packages/hackage.haskell.org/00-index.tar.gz >
87+ - BENCH=--enable-benchmarks
46− $HOME/.cabal/packages/hackage.haskell.org/00-index.tar;
88+ - BENCH=--disable-benchmarks
47− fi
89+ - HEADHACKAGE=false
90+ - rm -f $CABALHOME/config
91+ - |
92+ echo "verbose: normal +nowrap +markoutput" >> $CABALHOME/config
93+ echo "remote-build-reporting: anonymous" >> $CABALHOME/config
94+ echo "write-ghc-environment-files: always" >> $CABALHOME/config
95+ echo "remote-repo-cache: $CABALHOME/packages" >> $CABALHOME/config
96+ echo "logs-dir: $CABALHOME/logs" >> $CABALHOME/config
97+ echo "world-file: $CABALHOME/world" >> $CABALHOME/config
98+ echo "extra-prog-path: $CABALHOME/bin" >> $CABALHOME/config
99+ echo "symlink-bindir: $CABALHOME/bin" >> $CABALHOME/config
100+ echo "installdir: $CABALHOME/bin" >> $CABALHOME/config
101+ echo "build-summary: $CABALHOME/logs/build.log" >> $CABALHOME/config
102+ echo "store-dir: $CABALHOME/store" >> $CABALHOME/config
103+ echo "install-dirs user" >> $CABALHOME/config
104+ echo " prefix: $CABALHOME" >> $CABALHOME/config
105+ echo "repository hackage.haskell.org" >> $CABALHOME/config
106+ echo " url: http://hackage.haskell.org/" >> $CABALHOME/config
107+ - cat $CABALHOME/config
108+ - rm -fv cabal.project cabal.project.local cabal.project.freeze
48− - travis_retry cabal update -v
109+ - travis_retry ${CABAL} v2-update -v
49− - sed -i 's/^jobs:/-- jobs:/' ${HOME}/.cabal/config
110+ # Generate cabal.project
50− - cabal install --only-dependencies --enable-tests --dry -v > installplan.txt
111+ - rm -rf cabal.project cabal.project.local cabal.project.freeze
51− - sed -i -e '1,/^Resolving /d' installplan.txt; cat installplan.txt
112+ - touch cabal.project
52−
113+ - |
53−# check whether current requested install-plan matches cached package-db snapshot
114+ echo "packages: ." >> cabal.project
54− - if diff -u installplan.txt $HOME/.cabsnap/installplan.txt;
115+ - |
55− then
116+ - "for pkg in $($HCPKG list --simple-output); do echo $pkg | sed 's/-[^-]*$//' | (grep -vE -- '^(attoparsec)$' || true) | sed 's/^/constraints: /' | sed 's/$/ installed/' >> cabal.project.local; done"
56− echo "cabal build-cache HIT";
117+ - cat cabal.project || true
57− rm -rfv .ghc;
118+ - cat cabal.project.local || true
58− cp -a $HOME/.cabsnap/ghc $HOME/.ghc;
119+ - if [ -f "./configure.ac" ]; then (cd "." && autoreconf -i); fi
59− cp -a $HOME/.cabsnap/lib $HOME/.cabsnap/share $HOME/.cabsnap/bin $HOME/.cabal/;
120+ - ${CABAL} v2-freeze $WITHCOMPILER ${TEST} ${BENCH} | color_cabal_output
60− else
121+ - "cat cabal.project.freeze | sed -E 's/^(constraints: *| *)//' | sed 's/any.//'"
61− echo "cabal build-cache MISS";
122+ - rm cabal.project.freeze
62− rm -rf $HOME/.cabsnap;
123+ - ${CABAL} v2-build $WITHCOMPILER ${TEST} ${BENCH} --dep -j2 all | color_cabal_output
63− mkdir -p $HOME/.ghc $HOME/.cabal/lib $HOME/.cabal/share $HOME/.cabal/bin;
124+ - ${CABAL} v2-build $WITHCOMPILER --disable-tests --disable-benchmarks --dep -j2 all | color_cabal_output
64− cabal install --only-dependencies --enable-tests;
65− fi
66−
67−# snapshot package-db on cache miss
68− - if [ ! -d $HOME/.cabsnap ];
69− then
70− echo "snapshotting package-db to build-cache";
71− mkdir $HOME/.cabsnap;
72− cp -a $HOME/.ghc $HOME/.cabsnap/ghc;
73− cp -a $HOME/.cabal/lib $HOME/.cabal/share $HOME/.cabal/bin installplan.txt $HOME/.cabsnap/;
74− fi
75−
76−# Here starts the actual work to be performed for the package under test;
77−# any command which exits with a non-zero exit code causes the build to fail.
78script:
125script:
79− - if [ -f configure.ac ]; then autoreconf -i; fi
126+ - DISTDIR=$(mktemp -d /tmp/dist-test.XXXX)
80− - cabal configure --enable-tests -v2 # -v2 provides useful information for debugging
127+ # Packaging...
128+ - ${CABAL} v2-sdist all | color_cabal_output
129+ # Unpacking...
130+ - mv dist-newstyle/sdist/*.tar.gz ${DISTDIR}/
131+ - cd ${DISTDIR} || false
132+ - find . -maxdepth 1 -type f -name '*.tar.gz' -exec tar -xvf '{}' \;
133+ - find . -maxdepth 1 -type f -name '*.tar.gz' -exec rm '{}' \;
134+ - PKGDIR_attoparsec="$(find . -maxdepth 1 -type d -regex '.*/attoparsec-[0-9.]*')"
135+ # Generate cabal.project
136+ - rm -rf cabal.project cabal.project.local cabal.project.freeze
137+ - touch cabal.project
138+ - |
139+ echo "packages: ${PKGDIR_attoparsec}" >> cabal.project
140+ - |
141+ - "for pkg in $($HCPKG list --simple-output); do echo $pkg | sed 's/-[^-]*$//' | (grep -vE -- '^(attoparsec)$' || true) | sed 's/^/constraints: /' | sed 's/$/ installed/' >> cabal.project.local; done"
142+ - cat cabal.project || true
143+ - cat cabal.project.local || true
144+ # Building...
81− - cabal build # this builds all libraries and executables (including tests)
145+ # this builds all libraries and executables (without tests/benchmarks)
82− - cabal test
146+ - ${CABAL} v2-build $WITHCOMPILER --disable-tests --disable-benchmarks all | color_cabal_output
83− - cabal sdist # tests that a source-distribution can be generated
147+ # Building with tests and benchmarks...
84−
148+ # build & run tests, build benchmarks
85−# Check that the resulting source distribution can be built & installed.
149+ - ${CABAL} v2-build $WITHCOMPILER ${TEST} ${BENCH} all | color_cabal_output
86−# If there are no other `.tar.gz` files in `dist`, this can be even simpler:
150+ # Testing...
87−# `cabal install --force-reinstalls dist/*-*.tar.gz`
151+ - if [ $HCNUMVER -ge 70400 ] ; then ${CABAL} v2-test $WITHCOMPILER ${TEST} ${BENCH} all | color_cabal_output ; fi
88− - SRC_TGZ=$(cabal info . | awk '{print $2;exit}').tar.gz &&
152+ # cabal check...
89− (cd dist && cabal install --force-reinstalls "$SRC_TGZ")
153+ - (cd ${PKGDIR_attoparsec} && ${CABAL} -vnormal check)
154+ # haddock...
155+ - ${CABAL} v2-haddock $WITHCOMPILER ${TEST} ${BENCH} all | color_cabal_output
156+ # Building without installed constraints for packages in global-db...
157+ - rm -f cabal.project.local
158+ - ${CABAL} v2-build $WITHCOMPILER --disable-tests --disable-benchmarks all | color_cabal_output
90
159
160+# REGENDATA ["--tests-jobs=>=7.4","--no-benchmarks","attoparsec.cabal"]
91# EOF
161# EOF
Data/Attoparsec/Internal/Types.hs+8−5
@@ -1,4 +1,4 @@
1−{-# LANGUAGE BangPatterns, GeneralizedNewtypeDeriving, OverloadedStrings,
1+{-# LANGUAGE CPP, BangPatterns, GeneralizedNewtypeDeriving, OverloadedStrings,
2 Rank2Types, RecordWildCards, TypeFamilies #-}
2 Rank2Types, RecordWildCards, TypeFamilies #-}
3-- |
3-- |
4-- Module : Data.Attoparsec.Internal.Types
4-- Module : Data.Attoparsec.Internal.Types
@@ -39,7 +39,7 @@ import Data.ByteString.Internal (w2c)
39import Data.Text (Text)
39import Data.Text (Text)
40import qualified Data.Text as Text
40import qualified Data.Text as Text
41import Data.Text.Unsafe (Iter(..))
41import Data.Text.Unsafe (Iter(..))
42−import Prelude hiding (getChar, succ)
42+import Prelude hiding (succ)
43import qualified Data.Attoparsec.ByteString.Buffer as B
43import qualified Data.Attoparsec.ByteString.Buffer as B
44import qualified Data.Attoparsec.Text.Buffer as T
44import qualified Data.Attoparsec.Text.Buffer as T
45
45
@@ -136,8 +136,10 @@ instance Mon.Monoid More where
136 mempty = Incomplete
136 mempty = Incomplete
137
137
138instance Monad (Parser i) where
138instance Monad (Parser i) where
139+#if !(MIN_VERSION_base(4,13,0))
139 fail = Fail.fail
140 fail = Fail.fail
140 {-# INLINE fail #-}
141 {-# INLINE fail #-}
142+#endif
141
143
142 return = App.pure
144 return = App.pure
143 {-# INLINE return #-}
145 {-# INLINE return #-}
@@ -180,7 +182,7 @@ apP d e = do
180{-# INLINE apP #-}
182{-# INLINE apP #-}
181
183
182instance Applicative (Parser i) where
184instance Applicative (Parser i) where
183− pure v = Parser $ \t pos more _lose succ -> succ t pos more v
185+ pure v = Parser $ \t !pos more _lose succ -> succ t pos more v
184 {-# INLINE pure #-}
186 {-# INLINE pure #-}
185 (<*>) = apP
187 (<*>) = apP
186 {-# INLINE (<*>) #-}
188 {-# INLINE (<*>) #-}
@@ -207,8 +209,9 @@ instance Alternative (Parser i) where
207 {-# INLINE (<|>) #-}
209 {-# INLINE (<|>) #-}
208
210
209 many v = many_v
211 many v = many_v
212+ where
210− where many_v = some_v <|> pure []
213+ many_v = some_v <|> pure []
211− some_v = (:) App.<$> v <*> many_v
214+ some_v = (:) <$> v <*> many_v
212 {-# INLINE many #-}
215 {-# INLINE many #-}
213
216
214 some v = some_v
217 some v = some_v
Data/Attoparsec/Text/Internal.hs+11−13
@@ -1,4 +1,4 @@
1−{-# LANGUAGE BangPatterns, CPP, FlexibleInstances, GADTs, OverloadedStrings,
1+{-# LANGUAGE BangPatterns, FlexibleInstances, GADTs, OverloadedStrings,
2 Rank2Types, RecordWildCards, TypeFamilies, TypeSynonymInstances #-}
2 Rank2Types, RecordWildCards, TypeFamilies, TypeSynonymInstances #-}
3{-# OPTIONS_GHC -fno-warn-orphans #-}
3{-# OPTIONS_GHC -fno-warn-orphans #-}
4-- |
4-- |
@@ -65,17 +65,14 @@ module Data.Attoparsec.Text.Internal
65 , atEnd
65 , atEnd
66 ) where
66 ) where
67
67
68−#if !MIN_VERSION_base(4,8,0)
69−import Control.Applicative ((<$>))
68+import Control.Applicative ((<|>), (<$>), pure, (*>))
70−#endif
71−import Control.Applicative ((<|>))
72import Control.Monad (when)
69import Control.Monad (when)
73import Data.Attoparsec.Combinator ((<?>))
70import Data.Attoparsec.Combinator ((<?>))
74import Data.Attoparsec.Internal
71import Data.Attoparsec.Internal
75import Data.Attoparsec.Internal.Types hiding (Parser, Failure, Success)
72import Data.Attoparsec.Internal.Types hiding (Parser, Failure, Success)
76import qualified Data.Attoparsec.Text.Buffer as Buf
73import qualified Data.Attoparsec.Text.Buffer as Buf
77import Data.Attoparsec.Text.Buffer (Buffer, buffer)
74import Data.Attoparsec.Text.Buffer (Buffer, buffer)
78−import Data.Char (chr, ord)
75+import Data.Char (isAsciiUpper, isAsciiLower, toUpper, toLower)
79import Data.List (intercalate)
76import Data.List (intercalate)
80import Data.String (IsString(..))
77import Data.String (IsString(..))
81import Data.Text.Internal (Text(..))
78import Data.Text.Internal (Text(..))
@@ -225,15 +222,16 @@ stringCI s = go 0
225
222
226-- | Satisfy a literal string, ignoring case for characters in the ASCII range.
223-- | Satisfy a literal string, ignoring case for characters in the ASCII range.
227asciiCI :: Text -> Parser Text
224asciiCI :: Text -> Parser Text
228−asciiCI s = string_ (stringSuspended asciiToLower) asciiToLower s
225+asciiCI s = fmap fst $ match $ T.foldr ((*>) . asciiCharCI) (pure ()) s
229− where
230− asciiToLower = T.map f
231− where
232− offset = ord 'a' - ord 'A'
233− f c | 'A' <= c && c <= 'Z' = chr (ord c + offset)
234− | otherwise = c
235{-# INLINE asciiCI #-}
226{-# INLINE asciiCI #-}
236
227
228+asciiCharCI :: Char -> Parser Char
229+asciiCharCI c
230+ | isAsciiUpper c = char c <|> char (toLower c)
231+ | isAsciiLower c = char c <|> char (toUpper c)
232+ | otherwise = char c
233+{-# INLINE asciiCharCI #-}
234+
237-- | Skip past input for as long as the predicate returns 'True'.
235-- | Skip past input for as long as the predicate returns 'True'.
238skipWhile :: (Char -> Bool) -> Parser ()
236skipWhile :: (Char -> Bool) -> Parser ()
239skipWhile p = go
237skipWhile p = go
Data/Attoparsec/Zepto.hs+2
@@ -92,8 +92,10 @@ instance Monad m => Monad (ZeptoT m) where
92 Fail err -> return (Fail err)
92 Fail err -> return (Fail err)
93 {-# INLINE (>>=) #-}
93 {-# INLINE (>>=) #-}
94
94
95+#if !(MIN_VERSION_base(4,13,0))
95 fail = Fail.fail
96 fail = Fail.fail
96 {-# INLINE fail #-}
97 {-# INLINE fail #-}
98+#endif
97
99
98instance Monad m => Fail.MonadFail (ZeptoT m) where
100instance Monad m => Fail.MonadFail (ZeptoT m) where
99 fail msg = Parser $ \_ -> return (Fail msg)
101 fail msg = Parser $ \_ -> return (Fail msg)
attoparsec.cabal+30−11
@@ -1,12 +1,13 @@
1name: attoparsec
1name: attoparsec
2−version: 0.13.1.0
2+version: 0.13.2.2
3+x-revision: 3
3license: BSD3
4license: BSD3
4license-file: LICENSE
5license-file: LICENSE
5category: Text, Parsing
6category: Text, Parsing
6author: Bryan O'Sullivan <bos@serpentine.com>
7author: Bryan O'Sullivan <bos@serpentine.com>
7−maintainer: Bryan O'Sullivan <bos@serpentine.com>
8+maintainer: Bryan O'Sullivan <bos@serpentine.com>, Ben Gamari <ben@smart-cactus.org>
8stability: experimental
9stability: experimental
9−tested-with: GHC == 7.0.1, GHC == 7.2.1, GHC == 7.4.2, GHC ==7.6.3, GHC ==7.8.4, GHC ==7.10.3
10+tested-with: GHC == 7.0.4, GHC == 7.2.2, GHC == 7.4.2, GHC ==7.6.3, GHC ==7.8.4, GHC ==7.10.3, GHC ==8.0.2, GHC ==8.2.2, GHC==8.4.4, GHC==8.6.5, GHC==8.8.1
10synopsis: Fast combinator parsing for bytestrings and text
11synopsis: Fast combinator parsing for bytestrings and text
11cabal-version: >= 1.8
12cabal-version: >= 1.8
12homepage: https://github.com/bos/attoparsec
13homepage: https://github.com/bos/attoparsec
@@ -39,12 +40,12 @@ Flag developer
39
40
40library
41library
41 build-depends: array,
42 build-depends: array,
42− base >= 4.2 && < 5,
43+ base >= 4.3 && < 5,
43 bytestring,
44 bytestring,
44 containers,
45 containers,
45 deepseq,
46 deepseq,
46 scientific >= 0.3.1 && < 0.4,
47 scientific >= 0.3.1 && < 0.4,
47− transformers,
48+ transformers >= 0.2 && (< 0.4 || >= 0.4.1.0) && < 0.6,
48 text >= 1.1.1.3
49 text >= 1.1.1.3
49 if impl(ghc < 7.4)
50 if impl(ghc < 7.4)
50 build-depends:
51 build-depends:
@@ -53,7 +54,7 @@ library
53 if !impl(ghc >= 8.0)
54 if !impl(ghc >= 8.0)
54 -- Data.Semigroup && Control.Monad.Fail are available in base-4.9+
55 -- Data.Semigroup && Control.Monad.Fail are available in base-4.9+
55 build-depends: fail == 4.9.*,
56 build-depends: fail == 4.9.*,
56− semigroups >=0.16.1 && <0.19
57+ semigroups >=0.16.1 && <0.20
57
58
58 exposed-modules: Data.Attoparsec
59 exposed-modules: Data.Attoparsec
59 Data.Attoparsec.ByteString
60 Data.Attoparsec.ByteString
@@ -98,6 +99,24 @@ test-suite tests
98 QC.Text.FastSet
99 QC.Text.FastSet
99 QC.Text.Regressions
100 QC.Text.Regressions
100
101
102+ other-modules: Data.Attoparsec.ByteString
103+ Data.Attoparsec.ByteString.Buffer
104+ Data.Attoparsec.ByteString.Char8
105+ Data.Attoparsec.ByteString.FastSet
106+ Data.Attoparsec.ByteString.Internal
107+ Data.Attoparsec.ByteString.Lazy
108+ Data.Attoparsec.Combinator
109+ Data.Attoparsec.Internal
110+ Data.Attoparsec.Internal.Fhthagn
111+ Data.Attoparsec.Internal.Types
112+ Data.Attoparsec.Number
113+ Data.Attoparsec.Text
114+ Data.Attoparsec.Text.Buffer
115+ Data.Attoparsec.Text.FastSet
116+ Data.Attoparsec.Text.Internal
117+ Data.Attoparsec.Text.Lazy
118+ Data.Attoparsec.Zepto
119+
101 ghc-options:
120 ghc-options:
102 -Wall -threaded -rtsopts
121 -Wall -threaded -rtsopts
103
122
@@ -106,22 +125,22 @@ test-suite tests
106
125
107 build-depends:
126 build-depends:
108 array,
127 array,
109− base >= 4 && < 5,
128+ base,
110 bytestring,
129 bytestring,
111 deepseq >= 1.1,
130 deepseq >= 1.1,
112− QuickCheck >= 2.7,
131+ QuickCheck >= 2.13.2 && < 2.14,
113 quickcheck-unicode,
132 quickcheck-unicode,
114 scientific,
133 scientific,
115 tasty >= 0.11,
134 tasty >= 0.11,
116 tasty-quickcheck >= 0.8,
135 tasty-quickcheck >= 0.8,
117 text,
136 text,
118− transformers,
137+ transformers >= 0.2 && (< 0.4 || >= 0.4.1.0) && < 0.6,
119 vector
138 vector
120
139
121 if !impl(ghc >= 8.0)
140 if !impl(ghc >= 8.0)
122 -- Data.Semigroup && Control.Monad.Fail are available in base-4.9+
141 -- Data.Semigroup && Control.Monad.Fail are available in base-4.9+
123 build-depends: fail == 4.9.*,
142 build-depends: fail == 4.9.*,
124− semigroups >=0.16.1 && <0.19
143+ semigroups >=0.16.1 && <0.20
125
144
126benchmark benchmarks
145benchmark benchmarks
127 type: exitcode-stdio-1.0
146 type: exitcode-stdio-1.0
@@ -160,7 +179,7 @@ benchmark benchmarks
160 parsec >= 3.1.2,
179 parsec >= 3.1.2,
161 scientific,
180 scientific,
162 text >= 1.1.1.0,
181 text >= 1.1.1.0,
163− transformers,
182+ transformers >= 0.2 && (< 0.4 || >= 0.4.1.0) && < 0.6,
164 unordered-containers,
183 unordered-containers,
165 vector
184 vector
166
185
benchmarks/HeadersByteString.hs+10−1
@@ -9,6 +9,15 @@ import qualified Data.Attoparsec.ByteString.Char8 as B
9import qualified Data.Attoparsec.ByteString.Lazy as BL
9import qualified Data.Attoparsec.ByteString.Lazy as BL
10import qualified Data.ByteString.Char8 as B
10import qualified Data.ByteString.Char8 as B
11
11
12+-- Note: In the benchmarks for parsing an http request
13+-- from a strict bytestring, we consider warp's implementation,
14+-- which has highly optimized code for handling the first
15+-- line in particular. It's treatment of the headers
16+-- is more relaxed from the treatment they are given by the
17+-- attoparsec parser benchmarked here. Consequently, it
18+-- is should not be possible to match its performance since
19+-- it accepts header names with disallowed characters.
20+
12headers :: IO Benchmark
21headers :: IO Benchmark
13headers = do
22headers = do
14 req <- B.readFile =<< pathTo "http-request.txt"
23 req <- B.readFile =<< pathTo "http-request.txt"
@@ -18,7 +27,7 @@ headers = do
18 return $ bgroup "headers" [
27 return $ bgroup "headers" [
19 bgroup "B" [
28 bgroup "B" [
20 bench "request" $ nf (B.parseOnly request) req
29 bench "request" $ nf (B.parseOnly request) req
21− , bench "warp" $ nfIO (parseHeaderLines [req])
30+ , bench "warp" $ nfIO (parseHeaderLines (B.split '\n' req))
22 , bench "response" $ nf (B.parseOnly response) resp
31 , bench "response" $ nf (B.parseOnly response) resp
23 ]
32 ]
24 , bgroup "BL" [
33 , bgroup "BL" [
benchmarks/HeadersByteString/Atto.hs+9−1
@@ -15,8 +15,16 @@ import qualified Data.ByteString.Char8 as B
15instance NFData HttpVersion where
15instance NFData HttpVersion where
16 rnf !_ = ()
16 rnf !_ = ()
17
17
18+isHeaderChar :: Char -> Bool
19+isHeaderChar c =
20+ (c >= 'a' && c <= 'z') ||
21+ (c >= 'A' && c <= 'Z') ||
22+ (c >= '0' && c <= '9') ||
23+ (c == '_') ||
24+ (c == '-')
25+
18header = do
26header = do
19− name <- B.takeWhile1 (B.inClass "a-zA-Z0-9_-") <* B.char ':' <* B.skipSpace
27+ name <- B.takeWhile1 isHeaderChar <* B.char ':' <* B.skipSpace
20 body <- bodyLine
28 body <- bodyLine
21 return (name, body)
29 return (name, body)
22
30
benchmarks/http-request.txt+3−8
@@ -1,14 +1,9 @@
1GET / HTTP/1.1
1GET / HTTP/1.1
2Host: twitter.com
2Host: twitter.com
3−Accept: text/html, application/xhtml+xml, application/xml; q=0.9,
3+Accept: text/html, application/xhtml+xml, application/xml; q=0.9, image/webp, */*; q=0.8
4− image/webp, */*; q=0.8
5Accept-Encoding: gzip,deflate,sdch
4Accept-Encoding: gzip,deflate,sdch
6Accept-Language: en-GB,en-US;q=0.8,en;q=0.6
5Accept-Language: en-GB,en-US;q=0.8,en;q=0.6
7Cache-Control: max-age=0
6Cache-Control: max-age=0
8−Cookie: guest_id=v1%3A139; _twitter_sess=BAh7CSIKZmxhc2hJQz-e1e1;
7+Cookie: guest_id=v1%3A139; _twitter_sess=BAh7CSIKZmxhc2hJQz-e1e1; __utma=43838368.452555194.1399611824.1; __utmb=43838368; __utmc=43838368; __utmz=1399611824.1.1.utmcsr=(direct)|utmcmd=(none)
9− __utma=43838368.452555194.1399611824.1; __utmb=43838368;
10− __utmc=43838368; __utmz=1399611824.1.1.utmcsr=(direct)|utmcmd=(none)
11−User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_5)
12− AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.86
8+User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.86 Safari/537.36
13− Safari/537.36
14
9
benchmarks/http-response.txt+2−4
@@ -3,10 +3,8 @@ Date: Fri, 09 May 2014 04:24:57 GMT
3Expires: -1
3Expires: -1
4Cache-Control: private, max-age=0
4Cache-Control: private, max-age=0
5Content-Type: text/html; charset=ISO-8859-1
5Content-Type: text/html; charset=ISO-8859-1
6−Set-Cookie: PREF=ID=1a871afc4240db5e:FF:LM=1399609497:S=e5MZ0itEekjVwNcU;
6+Set-Cookie: PREF=ID=1a871afc4240db5e:FF:LM=1399609497:S=e5MZ0itEekjVwNcU; expires=Sun, 08-May-2016 04:24:57 GMT; path=/; domain=.google.com
7− expires=Sun, 08-May-2016 04:24:57 GMT; path=/; domain=.google.com
8−Set-Cookie: NID=67=-WlfaDG6VSEPk7abAjrK98HBSoCD2ID6JKkUR95tEumzDmg7Fc8pSQ8;
7+Set-Cookie: NID=67=-WlfaDG6VSEPk7abAjrK98HBSoCD2ID6JKkUR95tEumzDmg7Fc8pSQ8; expires=Sat, 08-Nov-2014 04:24:57 GMT; path=/; domain=.google.com; HttpOnly
9− expires=Sat, 08-Nov-2014 04:24:57 GMT; path=/; domain=.google.com; HttpOnly
10P3P: CP="This is not a P3P policy! See http://www.google.com/support/accounts/bin/answer.py?hl=en&answer=151657 for more info."
8P3P: CP="This is not a P3P policy! See http://www.google.com/support/accounts/bin/answer.py?hl=en&answer=151657 for more info."
11Server: gws
9Server: gws
12X-XSS-Protection: 1; mode=block
10X-XSS-Protection: 1; mode=block
changelog.md+8
@@ -1,3 +1,11 @@
1+0.13.2.1
2+
3+* Improved performance of `Data.Attoparsec.Text.asciiCI`
4+
5+0.13.2.0
6+
7+* `pure` is now strict in `Position`
8+
10.13.1.0
90.13.1.0
2
10
3* `runScanner` now correctly returns the final state
11* `runScanner` now correctly returns the final state
tests/QC/ByteString.hs+4−2
@@ -26,9 +26,11 @@ import qualified Data.ByteString.Lazy.Char8 as L8
26satisfy :: Word8 -> L.ByteString -> Property
26satisfy :: Word8 -> L.ByteString -> Property
27satisfy w s = parseBS (P.satisfy (<=w)) (L.cons w s) === Just w
27satisfy w s = parseBS (P.satisfy (<=w)) (L.cons w s) === Just w
28
28
29−satisfyWith :: Char -> L.ByteString -> Property
29+satisfyWith :: Word8 -> L.ByteString -> Property
30−satisfyWith c s = parseBS (P.satisfyWith (chr . fromIntegral) (<=c))
30+satisfyWith w s = parseBS (P.satisfyWith (chr . fromIntegral) (<=c))
31 (L.cons (fromIntegral (ord c)) s) === Just c
31 (L.cons (fromIntegral (ord c)) s) === Just c
32+ where
33+ c = chr (fromIntegral w)
32
34
33word8 :: Word8 -> L.ByteString -> Property
35word8 :: Word8 -> L.ByteString -> Property
34word8 w s = parseBS (P.word8 w) (L.cons w s) === Just w
36word8 w s = parseBS (P.word8 w) (L.cons w s) === Just w
tests/QC/Text.hs+11−3
@@ -6,6 +6,7 @@ module QC.Text (tests) where
6import Control.Applicative ((<*>), (<$>))
6import Control.Applicative ((<*>), (<$>))
7#endif
7#endif
8import Data.Int (Int64)
8import Data.Int (Int64)
9+import Data.Word (Word8)
9import Prelude hiding (take, takeWhile)
10import Prelude hiding (take, takeWhile)
10import QC.Common (liftOp, parseT)
11import QC.Common (liftOp, parseT)
11import qualified QC.Text.FastSet as FastSet
12import qualified QC.Text.FastSet as FastSet
@@ -16,8 +17,10 @@ import Test.QuickCheck
16import qualified Data.Attoparsec.Text as P
17import qualified Data.Attoparsec.Text as P
17import qualified Data.Attoparsec.Text.Lazy as PL
18import qualified Data.Attoparsec.Text.Lazy as PL
18import qualified Data.Attoparsec.Text.FastSet as S
19import qualified Data.Attoparsec.Text.FastSet as S
20+import qualified Data.ByteString as BS
19import qualified Data.Char as Char
21import qualified Data.Char as Char
20import qualified Data.Text as T
22import qualified Data.Text as T
23+import qualified Data.Text.Encoding as TE
21import qualified Data.Text.Lazy as L
24import qualified Data.Text.Lazy as L
22
25
23-- Basic byte-level combinators.
26-- Basic byte-level combinators.
@@ -70,9 +73,12 @@ strings s t u =
70 === Just t'
73 === Just t'
71 where t' = toStrict t
74 where t' = toStrict t
72
75
76+-- | Note: "simple, and efficient" works for well formed input...
77+-- i.e. e.g. Latin1 texts
73−stringCI :: T.Text -> Property
78+stringCI :: [Word8] -> Property
74−stringCI s = P.parseOnly (P.stringCI fs) s === Right s
79+stringCI ws = P.parseOnly (P.stringCI fs) s === Right s
75 where fs = T.toCaseFold s
80 where fs = T.toCaseFold s
81+ s = TE.decodeLatin1 (BS.pack ws)
76
82
77asciiCI :: T.Text -> Gen Bool
83asciiCI :: T.Text -> Gen Bool
78asciiCI x =
84asciiCI x =
@@ -150,7 +156,9 @@ endOfLine s =
150 (c, fst <$> L.uncons s') === ('\r', Just '\n')
156 (c, fst <$> L.uncons s') === ('\r', Just '\n')
151
157
152scan :: L.Text -> Positive Int64 -> Property
158scan :: L.Text -> Positive Int64 -> Property
159+-- for some reason, if counterexample is removed, this test fails?
160+scan s (Positive k) = counterexample (show s)
153−scan s (Positive k) = parseT p s === Just (toStrict $ L.take k s)
161+ $ parseT p s === Just (toStrict $ L.take k s)
154 where p = P.scan k $ \ n _ ->
162 where p = P.scan k $ \ n _ ->
155 if n > 0 then let !n' = n - 1 in Just n' else Nothing
163 if n > 0 then let !n' = n - 1 in Just n' else Nothing
156
164