|
Packit |
acf257 |
-----------------------------------------------------------------------------
|
|
Packit |
acf257 |
-- |
|
|
Packit |
acf257 |
-- Module : Network.HTTP.Utils
|
|
Packit |
acf257 |
-- Copyright : See LICENSE file
|
|
Packit |
acf257 |
-- License : BSD
|
|
Packit |
acf257 |
--
|
|
Packit |
acf257 |
-- Maintainer : Ganesh Sittampalam <ganesh@earth.li>
|
|
Packit |
acf257 |
-- Stability : experimental
|
|
Packit |
acf257 |
-- Portability : non-portable (not tested)
|
|
Packit |
acf257 |
--
|
|
Packit |
acf257 |
-- Set of utility functions and definitions used by package modules.
|
|
Packit |
acf257 |
--
|
|
Packit |
acf257 |
module Network.HTTP.Utils
|
|
Packit |
acf257 |
( trim -- :: String -> String
|
|
Packit |
acf257 |
, trimL -- :: String -> String
|
|
Packit |
acf257 |
, trimR -- :: String -> String
|
|
Packit |
acf257 |
|
|
Packit |
acf257 |
, crlf -- :: String
|
|
Packit |
acf257 |
, lf -- :: String
|
|
Packit |
acf257 |
, sp -- :: String
|
|
Packit |
acf257 |
|
|
Packit |
acf257 |
, split -- :: Eq a => a -> [a] -> Maybe ([a],[a])
|
|
Packit |
acf257 |
, splitBy -- :: Eq a => a -> [a] -> [[a]]
|
|
Packit |
acf257 |
|
|
Packit |
acf257 |
, readsOne -- :: Read a => (a -> b) -> b -> String -> b
|
|
Packit |
acf257 |
|
|
Packit |
acf257 |
, dropWhileTail -- :: (a -> Bool) -> [a] -> [a]
|
|
Packit |
acf257 |
, chopAtDelim -- :: Eq a => a -> [a] -> ([a],[a])
|
|
Packit |
acf257 |
|
|
Packit |
acf257 |
) where
|
|
Packit |
acf257 |
|
|
Packit |
acf257 |
import Data.Char
|
|
Packit |
acf257 |
import Data.List ( elemIndex )
|
|
Packit |
acf257 |
import Data.Maybe ( fromMaybe )
|
|
Packit |
acf257 |
|
|
Packit |
acf257 |
-- | @crlf@ is our beloved two-char line terminator.
|
|
Packit |
acf257 |
crlf :: String
|
|
Packit |
acf257 |
crlf = "\r\n"
|
|
Packit |
acf257 |
|
|
Packit |
acf257 |
-- | @lf@ is a tolerated line terminator, per RFC 2616 section 19.3.
|
|
Packit |
acf257 |
lf :: String
|
|
Packit |
acf257 |
lf = "\n"
|
|
Packit |
acf257 |
|
|
Packit |
acf257 |
-- | @sp@ lets you save typing one character.
|
|
Packit |
acf257 |
sp :: String
|
|
Packit |
acf257 |
sp = " "
|
|
Packit |
acf257 |
|
|
Packit |
acf257 |
-- | @split delim ls@ splits a list into two parts, the @delim@ occurring
|
|
Packit |
acf257 |
-- at the head of the second list. If @delim@ isn't in @ls@, @Nothing@ is
|
|
Packit |
acf257 |
-- returned.
|
|
Packit |
acf257 |
split :: Eq a => a -> [a] -> Maybe ([a],[a])
|
|
Packit |
acf257 |
split delim list = case delim `elemIndex` list of
|
|
Packit |
acf257 |
Nothing -> Nothing
|
|
Packit |
acf257 |
Just x -> Just $ splitAt x list
|
|
Packit |
acf257 |
|
|
Packit |
acf257 |
-- | @trim str@ removes leading and trailing whitespace from @str@.
|
|
Packit |
acf257 |
trim :: String -> String
|
|
Packit |
acf257 |
trim xs = trimR (trimL xs)
|
|
Packit |
acf257 |
|
|
Packit |
acf257 |
-- | @trimL str@ removes leading whitespace (as defined by 'Data.Char.isSpace')
|
|
Packit |
acf257 |
-- from @str@.
|
|
Packit |
acf257 |
trimL :: String -> String
|
|
Packit |
acf257 |
trimL xs = dropWhile isSpace xs
|
|
Packit |
acf257 |
|
|
Packit |
acf257 |
-- | @trimL str@ removes trailing whitespace (as defined by 'Data.Char.isSpace')
|
|
Packit |
acf257 |
-- from @str@.
|
|
Packit |
acf257 |
trimR :: String -> String
|
|
Packit |
acf257 |
trimR str = fromMaybe "" $ foldr trimIt Nothing str
|
|
Packit |
acf257 |
where
|
|
Packit |
acf257 |
trimIt x (Just xs) = Just (x:xs)
|
|
Packit |
acf257 |
trimIt x Nothing
|
|
Packit |
acf257 |
| isSpace x = Nothing
|
|
Packit |
acf257 |
| otherwise = Just [x]
|
|
Packit |
acf257 |
|
|
Packit |
acf257 |
-- | @splitMany delim ls@ removes the delimiter @delim@ from @ls@.
|
|
Packit |
acf257 |
splitBy :: Eq a => a -> [a] -> [[a]]
|
|
Packit |
acf257 |
splitBy _ [] = []
|
|
Packit |
acf257 |
splitBy c xs =
|
|
Packit |
acf257 |
case break (==c) xs of
|
|
Packit |
acf257 |
(_,[]) -> [xs]
|
|
Packit |
acf257 |
(as,_:bs) -> as : splitBy c bs
|
|
Packit |
acf257 |
|
|
Packit |
acf257 |
-- | @readsOne f def str@ tries to 'read' @str@, taking
|
|
Packit |
acf257 |
-- the first result and passing it to @f@. If the 'read'
|
|
Packit |
acf257 |
-- doesn't succeed, return @def@.
|
|
Packit |
acf257 |
readsOne :: Read a => (a -> b) -> b -> String -> b
|
|
Packit |
acf257 |
readsOne f n str =
|
|
Packit |
acf257 |
case reads str of
|
|
Packit |
acf257 |
((v,_):_) -> f v
|
|
Packit |
acf257 |
_ -> n
|
|
Packit |
acf257 |
|
|
Packit |
acf257 |
|
|
Packit |
acf257 |
-- | @dropWhileTail p ls@ chops off trailing elements from @ls@
|
|
Packit |
acf257 |
-- until @p@ returns @False@.
|
|
Packit |
acf257 |
dropWhileTail :: (a -> Bool) -> [a] -> [a]
|
|
Packit |
acf257 |
dropWhileTail f ls =
|
|
Packit |
acf257 |
case foldr chop Nothing ls of { Just xs -> xs; Nothing -> [] }
|
|
Packit |
acf257 |
where
|
|
Packit |
acf257 |
chop x (Just xs) = Just (x:xs)
|
|
Packit |
acf257 |
chop x _
|
|
Packit |
acf257 |
| f x = Nothing
|
|
Packit |
acf257 |
| otherwise = Just [x]
|
|
Packit |
acf257 |
|
|
Packit |
acf257 |
-- | @chopAtDelim elt ls@ breaks up @ls@ into two at first occurrence
|
|
Packit |
acf257 |
-- of @elt@; @elt@ is elided too. If @elt@ does not occur, the second
|
|
Packit |
acf257 |
-- list is empty and the first is equal to @ls@.
|
|
Packit |
acf257 |
chopAtDelim :: Eq a => a -> [a] -> ([a],[a])
|
|
Packit |
acf257 |
chopAtDelim elt xs =
|
|
Packit |
acf257 |
case break (==elt) xs of
|
|
Packit |
acf257 |
(_,[]) -> (xs,[])
|
|
Packit |
acf257 |
(as,_:bs) -> (as,bs)
|