import Control.Monad import System.IO import GHC.IO.Encoding import GHC.IO.Handle import Data.Bits import Data.Word import Data.Char import System.FilePath import System.Exit file = "encoding001" encodings = [(utf8, "utf8"), (utf8_bom, "utf8_bom"), (utf16, "utf16"), (utf16le, "utf16le"), (utf16be, "utf16be"), (utf32, "utf32"), (utf32le, "utf32le"), (utf32be, "utf32be")] main = do -- make a UTF-32BE file h <- openBinaryFile (file <.> "utf32be") WriteMode let expand32 :: Word32 -> [Char] expand32 x = [ chr (fromIntegral (x `shiftR` 24) .&. 0xff), chr (fromIntegral (x `shiftR` 16) .&. 0xff), chr (fromIntegral (x `shiftR` 8) .&. 0xff), chr (fromIntegral x .&. 0xff) ] hPutStr h (concatMap expand32 [ 0, 32 .. 0xD7ff ]) hPutStr h (concatMap expand32 [ 0xE000, 0xE000+32 .. 0x10FFFF ]) hClose h -- convert the UTF-32BE file into each other encoding forM_ encodings $ \(enc,name) -> when (name /= "utf32be") $ do hin <- openFile (file <.> "utf32be") ReadMode hSetEncoding hin utf32be hout <- openFile (file <.> name) WriteMode hSetEncoding hout enc hGetContents hin >>= hPutStr hout hClose hin hClose hout forM_ [ (from,to) | from <- encodings, to <- encodings, snd from /= snd to ] $ \((fromenc,fromname),(toenc,toname)) -> do hin <- openFile (file <.> fromname) ReadMode hSetEncoding hin fromenc hout <- openFile (file <.> toname <.> fromname) WriteMode hSetEncoding hout toenc hGetContents hin >>= hPutStr hout hClose hin hClose hout h1 <- openBinaryFile (file <.> toname) ReadMode h2 <- openBinaryFile (file <.> toname <.> fromname) ReadMode str1 <- hGetContents h1 str2 <- hGetContents h2 when (str1 /= str2) $ do putStrLn (file <.> toname ++ " and " ++ file <.> toname <.> fromname ++ " differ") exitWith (ExitFailure 1) hClose h1 hClose h2