Skip to content

Commit d1d4b41

Browse files
committed
add the attoparsec version
1 parent 2e183ed commit d1d4b41

File tree

4 files changed

+138
-0
lines changed

4 files changed

+138
-0
lines changed

http/attoparsec/LICENSE

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
Copyright (c) 2015 Geoffroy Couprie
2+
3+
Permission is hereby granted, free of charge, to any person obtaining
4+
a copy of this software and associated documentation files (the
5+
"Software"), to deal in the Software without restriction, including
6+
without limitation the rights to use, copy, modify, merge, publish,
7+
distribute, sublicense, and/or sell copies of the Software, and to
8+
permit persons to whom the Software is furnished to do so, subject to
9+
the following conditions:
10+
11+
The above copyright notice and this permission notice shall be included
12+
in all copies or substantial portions of the Software.
13+
14+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
17+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
18+
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
19+
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
20+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

http/attoparsec/Setup.hs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
import Distribution.Simple
2+
main = defaultMain

http/attoparsec/http.cabal

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
-- Initial mp4.cabal generated by cabal init. For further documentation,
2+
-- see http://haskell.org/cabal/users-guide/
3+
4+
name: http
5+
version: 0.1.0.0
6+
-- synopsis:
7+
-- description:
8+
license: MIT
9+
license-file: LICENSE
10+
author: Geoffroy Couprie
11+
maintainer: [email protected]
12+
-- copyright:
13+
category: Testing
14+
build-type: Simple
15+
-- extra-source-files:
16+
cabal-version: >=1.10
17+
18+
19+
executable http
20+
main-is: Main.hs
21+
-- other-modules:
22+
-- other-extensions:
23+
build-depends: criterion, attoparsec-binary, bytestring, attoparsec, base
24+
hs-source-dirs: src
25+
default-language: Haskell2010
26+
--ghc-options: -O2 -fllvm -pgmlo opt-3.4 -pgmlc llc-3.4

http/attoparsec/src/Main.hs

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
{-# LANGUAGE OverloadedStrings #-}
2+
3+
import Criterion.Main (bench, bgroup, defaultMain,
4+
env, nfIO, whnf, whnfIO)
5+
import qualified Data.Attoparsec.Binary as Bin
6+
import qualified Data.ByteString as B
7+
import qualified Data.ByteString.Char8 as C8
8+
9+
import Control.Applicative
10+
import Data.Attoparsec.ByteString as P
11+
import Data.Attoparsec.ByteString.Char8 (char8, endOfLine, isDigit_w8)
12+
import Data.Attoparsec.ByteString.Char8 (isEndOfLine,
13+
isHorizontalSpace)
14+
import Data.ByteString (ByteString)
15+
import Data.Word (Word8)
16+
17+
isToken :: Word8 -> Bool
18+
isToken w = w <= 127 && notInClass "\0-\31()<>@,;:\\\"/[]?={} \t" w
19+
20+
skipSpaces :: Parser ()
21+
skipSpaces = satisfy isHorizontalSpace *> skipWhile isHorizontalSpace
22+
23+
data Request = Request {
24+
requestMethod :: ByteString
25+
, requestUri :: ByteString
26+
, requestVersion :: ByteString
27+
} deriving (Eq, Ord, Show)
28+
29+
httpVersion :: Parser ByteString
30+
httpVersion = "HTTP/" *> P.takeWhile (\c -> isDigit_w8 c || c == 46)
31+
32+
requestLine :: Parser Request
33+
requestLine = Request <$> (takeWhile1 isToken <* char8 ' ')
34+
<*> (takeWhile1 (/=32) <* char8 ' ')
35+
<*> (httpVersion <* endOfLine)
36+
37+
data Header = Header {
38+
headerName :: ByteString
39+
, headerValue :: [ByteString]
40+
} deriving (Eq, Ord, Show)
41+
42+
messageHeader :: Parser Header
43+
messageHeader = Header
44+
<$> (P.takeWhile isToken <* char8 ':' <* skipWhile isHorizontalSpace)
45+
<*> ((:) <$> (takeTill isEndOfLine <* endOfLine)
46+
<*> (many $ skipSpaces *> takeTill isEndOfLine <* endOfLine))
47+
48+
request :: Parser (Request, [Header])
49+
request = (,) <$> requestLine <*> many messageHeader <* endOfLine
50+
51+
allRequests = many1 request
52+
53+
data Response = Response {
54+
responseVersion :: ByteString
55+
, responseCode :: ByteString
56+
, responseMsg :: ByteString
57+
} deriving (Eq, Ord, Show)
58+
59+
responseLine :: Parser Response
60+
responseLine = Response <$> (httpVersion <* char8 ' ')
61+
<*> (P.takeWhile isDigit_w8 <* char8 ' ')
62+
<*> (takeTill isEndOfLine <* endOfLine)
63+
64+
response :: Parser (Response, [Header])
65+
response = (,) <$> responseLine <*> many messageHeader <* endOfLine
66+
67+
smallFile :: FilePath
68+
smallFile = "../http-requests.txt"
69+
biggerFile :: FilePath
70+
biggerFile = "../bigger.txt"
71+
72+
setupEnv = do
73+
small <- B.readFile smallFile
74+
bigger <- B.readFile biggerFile
75+
return (small, bigger)
76+
77+
criterion :: IO ()
78+
criterion = defaultMain
79+
[
80+
env setupEnv $ \ ~(small, bigger) ->
81+
bgroup "IO"
82+
[
83+
bench "small" $ whnf (P.parseOnly allRequests) small
84+
, bench "bigger" $ whnf (P.parseOnly allRequests) bigger
85+
]
86+
]
87+
88+
main :: IO ()
89+
main = criterion
90+
--main = B.readFile biggerFile >>= print . P.parseOnly allRequests

0 commit comments

Comments
 (0)