{- |
Taken from Haskore.
-}
module Sound.MIDI.IO
          (openBinaryFile, readBinaryFile, writeBinaryFile,
           ByteList, listCharFromByte, listByteFromChar)
   where

import System.IO
import Control.Exception(bracket)
import Control.Monad(liftM)
import Data.Char (ord, chr)
import Data.Word (Word8)

type ByteList = [Word8]

{- |
Hugs makes trouble here because it performs UTF-8 conversions.
E.g. @[255]@ is output as @[195,191]@
It would be easy to replace these routines by FastPackedString(fps).ByteList.Lazy,
however this introduces a new package dependency.
-}
writeBinaryFile :: FilePath -> ByteList -> IO ()
writeBinaryFile :: FilePath -> ByteList -> IO ()
writeBinaryFile FilePath
path ByteList
str =
   IO Handle -> (Handle -> IO ()) -> (Handle -> IO ()) -> IO ()
forall a b c. IO a -> (a -> IO b) -> (a -> IO c) -> IO c
bracket (FilePath -> IOMode -> IO Handle
openBinaryFile FilePath
path IOMode
WriteMode) Handle -> IO ()
hClose
           ((Handle -> FilePath -> IO ()) -> FilePath -> Handle -> IO ()
forall a b c. (a -> b -> c) -> b -> a -> c
flip Handle -> FilePath -> IO ()
hPutStr (ByteList -> FilePath
listCharFromByte ByteList
str))

listCharFromByte :: ByteList -> String
listCharFromByte :: ByteList -> FilePath
listCharFromByte = (Word8 -> Char) -> ByteList -> FilePath
forall a b. (a -> b) -> [a] -> [b]
map (Int -> Char
chr (Int -> Char) -> (Word8 -> Int) -> Word8 -> Char
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Word8 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral)

readBinaryFile :: FilePath -> IO ByteList
readBinaryFile :: FilePath -> IO ByteList
readBinaryFile FilePath
path =
   (FilePath -> ByteList) -> IO FilePath -> IO ByteList
forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
liftM FilePath -> ByteList
listByteFromChar (IO FilePath -> IO ByteList)
-> (Handle -> IO FilePath) -> Handle -> IO ByteList
forall b c a. (b -> c) -> (a -> b) -> a -> c
.
      Handle -> IO FilePath
hGetContents (Handle -> IO ByteList) -> IO Handle -> IO ByteList
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< FilePath -> IOMode -> IO Handle
openBinaryFile FilePath
path IOMode
ReadMode

listByteFromChar :: String -> ByteList
listByteFromChar :: FilePath -> ByteList
listByteFromChar = (Char -> Word8) -> FilePath -> ByteList
forall a b. (a -> b) -> [a] -> [b]
map (Int -> Word8
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int -> Word8) -> (Char -> Int) -> Char -> Word8
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Char -> Int
ord)