{- |
 
  Module      :  Codec.Percent
  Copyright   :  (c) 2008

  Maintainer  : sof@forkIO.com

  License     : See the file LICENSE

  Status      : Coded

  Codec for de/encoding URI strings via percent encodings
 (cf. RFC 3986.)
-}
module Codec.Percent where

import Data.Char ( chr, isAlphaNum )
import Numeric   ( readHex, showHex )

getEncodedString :: String -> String
getEncodedString "" = ""
getEncodedString (x:xs) = 
  case getEncodedChar x of
    Nothing -> x : getEncodedString xs
    Just ss -> ss ++ getEncodedString xs

getDecodedString :: String -> String
getDecodedString "" = ""
getDecodedString ls@(x:xs) = 
  case getDecodedChar ls of
    Nothing -> x : getDecodedString xs
    Just (ch,xs1) -> ch : getDecodedString xs1

getEncodedChar :: Char -> Maybe String
getEncodedChar x
 | isAlphaNum x || 
   x `elem` "-_.~" = Nothing
 | xi < 0xff       = Just ('%':showHex (xi `div` 16) (showHex (xi `mod` 16) ""))
 | otherwise       = -- ToDo: import utf8 lib
   error "getEncodedChar: can only handle 8-bit chars right now."
 where
  xi :: Int
  xi = fromEnum x

getDecodedChar :: String -> Maybe (Char, String)
getDecodedChar str =
 case str of
   ""          -> Nothing
   (x:xs) 
    | x /= '%'  -> Nothing
    | otherwise -> do
       case xs of
         (b1:b2:bs) -> 
	    case readHex [b1,b2] of
	      ((v,_):_) -> Just (Data.Char.chr v, bs)
	      _ -> Nothing
	 _ -> Nothing