diff --git a/Data/Encoding/ISO2022.hs b/Data/Encoding/ISO2022.hs new file mode 100644 index 0000000..49da7c1 --- /dev/null +++ b/Data/Encoding/ISO2022.hs @@ -0,0 +1,60 @@ +module Data.Encoding.ISO2022 where + +import Data.Encoding.Base +import Data.Encoding.ByteSource +import Data.Encoding.ByteSink +import Data.Encoding.Exception +import Data.Encoding.ASCII + +import Data.Word +import Control.Throws + +class ISO2022 e where + readEscape :: ByteSource m => e -> m (Maybe DynEncoding) + encodingForChar :: e -> Char -> Maybe (DynEncoding,[Word8]) + +encodeCharISO2022 :: (ISO2022 e,ByteSink m) => e -> Char -> m () +encodeCharISO2022 e c = case encodingForChar e c of + Nothing -> throwException (HasNoRepresentation c) + Just (enc,esc) -> do + mapM_ pushWord8 esc + encodeChar enc c + +decodeCharISO2022 :: (ISO2022 e,ByteSource m) => e -> m Char +decodeCharISO2022 e = do + enc <- readEscape e + case enc of + Nothing -> decodeChar ASCII + Just renc -> decodeChar renc + +encodeISO2022 :: (ISO2022 e,ByteSink m) => e -> String -> m () +encodeISO2022 e = encode' (DynEncoding ASCII) + where + encode' _ [] = return () + encode' enc (c:cs) = case encodingForChar e c of + Nothing -> throwException (HasNoRepresentation c) + Just (nenc,esc) + | enc==nenc -> do + encodeChar enc c + encode' enc cs + | otherwise -> do + mapM_ pushWord8 esc + encodeChar nenc c + encode' nenc cs + +decodeISO2022 :: (ISO2022 e,ByteSource m) => e -> m String +decodeISO2022 e = decode' (DynEncoding ASCII) + where + decode' enc = do + empty <- sourceEmpty + if empty + then return [] + else (do + nenc <- readEscape e + case nenc of + Just renc -> decode' renc + Nothing -> do + c <- decodeChar enc + cs <- decode' enc + return (c:cs) + )