Blame Network/HTTP/Utils.hs

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)