module System.IO.UTF8 where

import Prelude

import qualified Data.ByteString as BS
import qualified Data.ByteString.Lazy as BSL
import qualified Data.ByteString.Search as BSS
import qualified Data.ByteString.UTF8 as UTF8
import           Data.Text (Text)
import qualified Data.Text.Encoding as TE
import           Protolude (ordNub)

-- | Unfortunately ByteString's readFile does not convert line endings on
-- Windows, so we have to do it ourselves
fixCRLF :: BS.ByteString -> BS.ByteString
fixCRLF :: ByteString -> ByteString
fixCRLF = ByteString -> ByteString
BSL.toStrict forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall rep.
Substitution rep =>
ByteString -> rep -> ByteString -> ByteString
BSS.replace ByteString
"\r\n" (ByteString
"\n" :: BS.ByteString)

readUTF8FilesT :: [FilePath] -> IO [(FilePath, Text)]
readUTF8FilesT :: [FilePath] -> IO [(FilePath, Text)]
readUTF8FilesT =
  forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
traverse (\FilePath
inFile -> (FilePath
inFile, ) forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> FilePath -> IO Text
readUTF8FileT FilePath
inFile) forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Ord a => [a] -> [a]
ordNub

readUTF8FileT :: FilePath -> IO Text
readUTF8FileT :: FilePath -> IO Text
readUTF8FileT FilePath
inFile =
  forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (ByteString -> Text
TE.decodeUtf8 forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> ByteString
fixCRLF) (FilePath -> IO ByteString
BS.readFile FilePath
inFile)

writeUTF8FileT :: FilePath -> Text -> IO ()
writeUTF8FileT :: FilePath -> Text -> IO ()
writeUTF8FileT FilePath
inFile Text
text =
  FilePath -> ByteString -> IO ()
BS.writeFile FilePath
inFile (Text -> ByteString
TE.encodeUtf8 Text
text)

readUTF8File :: FilePath -> IO String
readUTF8File :: FilePath -> IO FilePath
readUTF8File FilePath
inFile =
  forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (ByteString -> FilePath
UTF8.toString forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> ByteString
fixCRLF) (FilePath -> IO ByteString
BS.readFile FilePath
inFile)