packages feed

http-date (empty) → 0.0.0

raw patch · 8 files changed

+383/−0 lines, 8 filesdep +arraydep +attoparsecdep +basesetup-changed

Dependencies added: array, attoparsec, base, bytestring

Files

+ LICENSE view
@@ -0,0 +1,29 @@+Copyright (c) 2009, IIJ Innovation Institute Inc.+All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions+are met:++  * Redistributions of source code must retain the above copyright+    notice, this list of conditions and the following disclaimer.+  * Redistributions in binary form must reproduce the above copyright+    notice, this list of conditions and the following disclaimer in+    the documentation and/or other materials provided with the+    distribution.+  * Neither the name of the copyright holders nor the names of its+    contributors may be used to endorse or promote products derived+    from this software without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS+FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE+COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,+BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT+LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN+ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE+POSSIBILITY OF SUCH DAMAGE.
+ Network/HTTP/Date.hs view
@@ -0,0 +1,15 @@+{-|+  Fast parser and formatter for HTTP Date.+-}+module Network.HTTP.Date (+    module Network.HTTP.Date.Types+  -- * Utility functions+  , parseHTTPDate+  , formatHTTPDate+  , epochTimeToHTTPDate+  ) where++import Network.HTTP.Date.Converter+import Network.HTTP.Date.Formatter+import Network.HTTP.Date.Parser+import Network.HTTP.Date.Types
+ Network/HTTP/Date/Converter.hs view
@@ -0,0 +1,70 @@+module Network.HTTP.Date.Converter (epochTimeToHTTPDate) where++import Data.Word+import Network.HTTP.Date.Types+import System.Posix.Types++{-|+  Translating 'EpochTime' to 'HTTPDate'.+-}+epochTimeToHTTPDate :: EpochTime -> HTTPDate+epochTimeToHTTPDate x = defaultHTTPDate {+    hdYear   = y+  , hdMonth  = m+  , hdDay    = d+  , hdHour   = h+  , hdMinute = n+  , hdSecond = s+  , hdWkday  = w+  }+  where+    w64 :: Word64+    w64 = truncate . toRational $ x+    (days',secs') = w64 `divMod` 86400+    days = fromIntegral days'+    secs = fromIntegral secs'+    -- 1970/1/1 is Thu (4)+    w = (days + 3) `mod` 7 + 1+    (y,m,d) = toYYMMDD days+    (h,n,s) = toHHMMSS secs++toYYMMDD :: Int -> (Int,Int,Int)+toYYMMDD x = (yy, mm, dd)+  where+    (y,d) = x `divMod` 365+    cy = 1970 + y+    cy' = cy - 1+    leap = cy' `div` 4 - cy' `div` 100 + cy' `div` 400 - 477+    (yy,days) = adjust cy d leap+    (mm,dd) = findMonth 1 monthDays (days + 1)+    adjust ty td aj+      | td >= aj        = (ty, td - aj)+      | isLeap (ty - 1) = if td + 366 >= aj+                          then (ty - 1, td + 366 - aj)+                          else adjust (ty - 1) (td + 366) aj+      | otherwise       = if td + 365 >= aj+                          then (ty - 1, td + 365 - aj)+                          else adjust (ty - 1) (td + 365) aj+    isLeap year = year `mod` 4 == 0+              && (year `mod` 400 == 0 ||+                  year `mod` 100 /= 0)+    monthDays+      | isLeap yy = leapMonthDays+      | otherwise = normalMonthDays+    findMonth _ [] _ = error "findMonth"+    findMonth m (n:ns) z+      | z <= n    = (m,z)+      | otherwise = findMonth (m+1) ns (z-n)+++normalMonthDays :: [Int]+normalMonthDays = [31,28,31,30,31,30,31,31,30,31,30,31]++leapMonthDays :: [Int]+leapMonthDays   = [31,29,31,30,31,30,31,31,30,31,30,31]++toHHMMSS :: Int -> (Int,Int,Int)+toHHMMSS x = (hh,mm,ss)+  where+    (hhmm,ss) = x `divMod` 60+    (hh,mm) = hhmm `divMod` 60
+ Network/HTTP/Date/Formatter.hs view
@@ -0,0 +1,106 @@+{-# LANGUAGE OverloadedStrings #-}++module Network.HTTP.Date.Formatter (formatHTTPDate) where++import Data.Array+import Data.ByteString.Internal+import Data.ByteString.Char8 ()+import Data.Word+import Foreign.ForeignPtr+import Foreign.Ptr+import Foreign.Storable+import Network.HTTP.Date.Types++----------------------------------------------------------------++{-|+  Generating HTTP Date in RFC1123 style.+-}+formatHTTPDate :: HTTPDate -> ByteString+formatHTTPDate hd =+    unsafeCreate 29 $ \ptr -> do+        cpy3 ptr week+        poke (ptr `plusPtr`  3) comma+        poke (ptr `plusPtr`  4) spc+        int2 (ptr `plusPtr`  5) d+        poke (ptr `plusPtr`  7) spc+        cpy3 (ptr `plusPtr`  8) month+        poke (ptr `plusPtr` 11) spc+        int4 (ptr `plusPtr` 12) y+        poke (ptr `plusPtr` 16) spc+        int2 (ptr `plusPtr` 17) h+        poke (ptr `plusPtr` 19) colon+        int2 (ptr `plusPtr` 20) n+        poke (ptr `plusPtr` 22) colon+        int2 (ptr `plusPtr` 23) s+        poke (ptr `plusPtr` 25) spc+        poke (ptr `plusPtr` 26) (71 :: Word8)+        poke (ptr `plusPtr` 27) (77 :: Word8)+        poke (ptr `plusPtr` 28) (84 :: Word8)+  where+    y = hdYear hd+    m = hdMonth hd+    d = hdDay hd+    h = hdHour hd+    n = hdMinute hd+    s = hdSecond hd+    w = hdWkday hd+    week = weekDays ! w+    month = months ! m++----------------------------------------------------------------++cpy3 :: Ptr Word8 -> ByteString -> IO ()+cpy3 ptr (PS p s l) = withForeignPtr p $ \fp ->+    memcpy ptr (fp `plusPtr` s) (fromIntegral l)++int2 :: Ptr Word8 -> Int -> IO ()+int2 ptr n+  | n < 10 = do+      poke ptr zero+      poke (ptr `plusPtr` 1) (i2w8 n)+  | otherwise = do+      poke ptr               (i2w8 (n `div` 10))+      poke (ptr `plusPtr` 1) (i2w8 (n `mod` 10))++int4 :: Ptr Word8 -> Int -> IO ()+int4 ptr n0 = do+    let (n1,x1) = n0 `divMod` 10+        (n2,x2) = n1 `divMod` 10+        (x4,x3) = n2 `divMod` 10+    poke ptr               (i2w8 x4)+    poke (ptr `plusPtr` 1) (i2w8 x3)+    poke (ptr `plusPtr` 2) (i2w8 x2)+    poke (ptr `plusPtr` 3) (i2w8 x1)++i2w8 :: Int -> Word8+i2w8 n = fromIntegral n + zero++----------------------------------------------------------------++months :: Array Int ByteString+months = listArray (1,12) [+      "Jan", "Feb", "Mar"+    , "Apr", "May", "Jun"+    , "Jul", "Aug", "Sep"+    , "Oct", "Nov", "Dec"+    ]++weekDays :: Array Int ByteString+weekDays = listArray (1,7) [+      "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"+    ]++----------------------------------------------------------------++spc :: Word8+spc = 32++comma :: Word8+comma = 44++colon :: Word8+colon = 58++zero :: Word8+zero = 48
+ Network/HTTP/Date/Parser.hs view
@@ -0,0 +1,103 @@+{-# LANGUAGE OverloadedStrings #-}++module Network.HTTP.Date.Parser (parseHTTPDate) where++import Data.ByteString+import Network.HTTP.Date.Types+import Data.Attoparsec+import Data.Attoparsec.Char8+import Control.Applicative+import Data.Char++----------------------------------------------------------------++{-|+  Parsing HTTP Date. Currently only RFC1123 style is supported.+-}+parseHTTPDate :: ByteString -> Maybe HTTPDate+parseHTTPDate bs = case feed (parse rfc1123Date bs) "" of+    Done _ ut -> Just ut+    _         -> Nothing++rfc1123Date :: Parser HTTPDate+rfc1123Date = do+    w <- wkday+    string ", "+    (y,m,d) <- date1+    sp+    (h,n,s) <- time+    sp+    string "GMT"+    return $ defaultHTTPDate {+        hdYear   = y+      , hdMonth  = m+      , hdDay    = d+      , hdHour   = h+      , hdMinute = n+      , hdSecond = s+      , hdWkday  = w+      }++wkday :: Parser Int+wkday = 1 <$ string "Mon"+    <|> 2 <$ string "Tue"+    <|> 3 <$ string "Wed"+    <|> 4 <$ string "Thu"+    <|> 5 <$ string "Fri"+    <|> 6 <$ string "Sat"+    <|> 7 <$ string "Sun"++date1 :: Parser (Int,Int,Int)+date1 = do+    d <- day+    sp+    m <- month+    sp+    y <- year+    return (y,m,d)+ where    +   day = digit2+   year = digit4++sp :: Parser ()+sp = () <$ char ' '++time :: Parser (Int,Int,Int)+time = do+    h <- digit2+    char ':'+    m <- digit2+    char ':'+    s <- digit2+    return (h,m,s)++month :: Parser Int+month =  1 <$ string "Jan"+    <|>  2 <$ string "Feb"+    <|>  3 <$ string "Mar"+    <|>  4 <$ string "Apr"+    <|>  5 <$ string "May"+    <|>  6 <$ string "Jun"+    <|>  7 <$ string "Jul"+    <|>  8 <$ string "Aug"+    <|>  9 <$ string "Sep"+    <|> 10 <$ string "Oct"+    <|> 11 <$ string "Nov"+    <|> 12 <$ string "Dec"++digit2 :: Parser Int+digit2 = do+    x1 <- toInt <$> digit+    x2 <- toInt <$> digit+    return $ x1 * 10 + x2++digit4 :: Parser Int+digit4 = do+    x1 <- toInt <$> digit+    x2 <- toInt <$> digit+    x3 <- toInt <$> digit+    x4 <- toInt <$> digit+    return $ x1 * 1000 + x2 * 100 + x3 * 10 + x4++toInt :: Char -> Int+toInt c = ord c - ord '0'
+ Network/HTTP/Date/Types.hs view
@@ -0,0 +1,32 @@+module Network.HTTP.Date.Types (+    HTTPDate+  , hdYear+  , hdMonth+  , hdDay+  , hdHour+  , hdMinute+  , hdSecond+  , hdWkday+  , defaultHTTPDate+  ) where++{-|+  Data structure for HTTP Date. This value should be specified+  with 'defaultHTTPDate' and its field labels.+-}+data HTTPDate = HTTPDate {+    hdYear   :: !Int+  , hdMonth  :: !Int+  , hdDay    :: !Int+  , hdHour   :: !Int+  , hdMinute :: !Int+  , hdSecond :: !Int+  , hdWkday  :: !Int+  } deriving (Eq,Show)++{-|+  A default value for 'HTTPDate'.+-}+-- 1970/1/1 is Thu (4)+defaultHTTPDate :: HTTPDate+defaultHTTPDate = HTTPDate 1970 1 1 0 0 0 4
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ http-date.cabal view
@@ -0,0 +1,26 @@+Name:                   http-date+Version:                0.0.0+Author:                 Kazu Yamamoto <kazu@iij.ad.jp>+Maintainer:             Kazu Yamamoto <kazu@iij.ad.jp>+License:                BSD3+License-File:           LICENSE+Synopsis:               HTTP Date parser/formatter+Description:            Fast parser and formatter for HTTP Date+Category:               Network, Web+Cabal-Version:          >= 1.6+Build-Type:             Simple+library+  if impl(ghc >= 6.12)+    GHC-Options:        -Wall -fno-warn-unused-do-bind+  else+    GHC-Options:        -Wall+  Exposed-Modules:      Network.HTTP.Date+  Other-Modules:        Network.HTTP.Date.Converter+                        Network.HTTP.Date.Formatter+                        Network.HTTP.Date.Types+                        Network.HTTP.Date.Parser+  Build-Depends:        base >= 4 && < 5,+                        bytestring, array, attoparsec+Source-Repository head+  Type:                 git+  Location:             git://github.com/kazu-yamamoto/http-date