{- |
Parse primitive types contained in MIDI files.
-}
module Sound.MIDI.Parser.Primitive
   (getByte,
    getN, getString, getBigN, getNByteInt,
    get1, get2, get3, get4,
    getNByteCardinal,
    getVar, getVarBytes,
    getEnum, makeEnum, ) where

import qualified Sound.MIDI.Parser.Class as Parser
import Control.Monad (replicateM, liftM, )

import Sound.MIDI.IO (ByteList, listCharFromByte, )
import qualified Sound.MIDI.Bit as Bit
import Data.Bits (testBit, clearBit)
import Data.Word (Word8)
import qualified Numeric.NonNegative.Wrapper as NonNeg



{- |
'getByte' gets a single byte from the input.
-}
getByte :: Parser.C parser => Parser.Fragile parser Word8
getByte :: forall (parser :: * -> *). C parser => Fragile parser Word8
getByte = forall (parser :: * -> *). C parser => Fragile parser Word8
Parser.getByte


{- |
@getN n@ returns n characters (bytes) from the input.
-}
getN :: Parser.C parser => NonNeg.Int -> Parser.Fragile parser ByteList
getN :: forall (parser :: * -> *).
C parser =>
Int -> Fragile parser ByteList
getN Int
n = forall (m :: * -> *) a. Applicative m => Int -> m a -> m [a]
replicateM (forall a. T a -> a
NonNeg.toNumber Int
n) forall (parser :: * -> *). C parser => Fragile parser Word8
getByte

getString :: Parser.C parser => NonNeg.Integer -> Parser.Fragile parser String
getString :: forall (parser :: * -> *).
C parser =>
Integer -> Fragile parser UserMessage
getString Integer
n = forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
liftM ByteList -> UserMessage
listCharFromByte (forall (parser :: * -> *).
C parser =>
Integer -> Fragile parser ByteList
getBigN Integer
n)

getBigN :: Parser.C parser => NonNeg.Integer -> Parser.Fragile parser ByteList
getBigN :: forall (parser :: * -> *).
C parser =>
Integer -> Fragile parser ByteList
getBigN Integer
n =
   forall (t :: * -> *) (m :: * -> *) a.
(Traversable t, Monad m) =>
t (m a) -> m (t a)
sequence forall a b. (a -> b) -> a -> b
$
   forall a. Integer -> Integer -> a -> [a]
Bit.replicateBig
      (Integer
1 forall a. Num a => a -> a -> a
+ forall a b. (Integral a, Num b) => a -> b
fromIntegral (forall a. Bounded a => a
maxBound :: NonNeg.Int))
      (forall a. T a -> a
NonNeg.toNumber Integer
n)
      forall (parser :: * -> *). C parser => Fragile parser Word8
getByte


{- |
'get1', 'get2', 'get3', and 'get4' take 1-, 2-, 3-, or
4-byte numbers from the input (respectively), convert the base-256 data
into a single number, and return.
-}
get1 :: Parser.C parser => Parser.Fragile parser Int
get1 :: forall (parser :: * -> *). C parser => Fragile parser Int
get1 = forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
liftM forall a b. (Integral a, Num b) => a -> b
fromIntegral forall (parser :: * -> *). C parser => Fragile parser Word8
getByte

getNByteInt :: Parser.C parser => NonNeg.Int -> Parser.Fragile parser Int
getNByteInt :: forall (parser :: * -> *). C parser => Int -> Fragile parser Int
getNByteInt Int
n =
   forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
liftM forall a. Integral a => [a] -> a
Bit.fromBytes (forall (m :: * -> *) a. Applicative m => Int -> m a -> m [a]
replicateM (forall a. T a -> a
NonNeg.toNumber Int
n) forall (parser :: * -> *). C parser => Fragile parser Int
get1)

get2, get3, get4 :: Parser.C parser => Parser.Fragile parser Int
get2 :: forall (parser :: * -> *). C parser => Fragile parser Int
get2 = forall (parser :: * -> *). C parser => Int -> Fragile parser Int
getNByteInt Int
2
get3 :: forall (parser :: * -> *). C parser => Fragile parser Int
get3 = forall (parser :: * -> *). C parser => Int -> Fragile parser Int
getNByteInt Int
3
get4 :: forall (parser :: * -> *). C parser => Fragile parser Int
get4 = forall (parser :: * -> *). C parser => Int -> Fragile parser Int
getNByteInt Int
4

getByteAsCardinal :: Parser.C parser => Parser.Fragile parser NonNeg.Integer
getByteAsCardinal :: forall (parser :: * -> *). C parser => Fragile parser Integer
getByteAsCardinal = forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
liftM forall a b. (Integral a, Num b) => a -> b
fromIntegral forall (parser :: * -> *). C parser => Fragile parser Word8
getByte

getNByteCardinal :: Parser.C parser => NonNeg.Int -> Parser.Fragile parser NonNeg.Integer
getNByteCardinal :: forall (parser :: * -> *).
C parser =>
Int -> Fragile parser Integer
getNByteCardinal Int
n =
   forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
liftM forall a. Integral a => [a] -> a
Bit.fromBytes (forall (m :: * -> *) a. Applicative m => Int -> m a -> m [a]
replicateM (forall a. T a -> a
NonNeg.toNumber Int
n) forall (parser :: * -> *). C parser => Fragile parser Integer
getByteAsCardinal)

{- |
/Variable-length quantities/ are used often in MIDI notation.
They are represented in the following way:
Each byte (containing 8 bits) uses the 7 least significant bits to store information.
The most significant bit is used to signal whether or not more information is coming.
If it's @1@, another byte is coming.
If it's @0@, that byte is the last one.
'getVar' gets a variable-length quantity from the input.
-}
getVar :: Parser.C parser => Parser.Fragile parser NonNeg.Integer
getVar :: forall (parser :: * -> *). C parser => Fragile parser Integer
getVar =
   forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
liftM (forall a. Integral a => a -> [a] -> a
Bit.fromBase (Integer
2forall a b. (Num a, Integral b) => a -> b -> a
^(Int
7::Int)) forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (a -> b) -> [a] -> [b]
map forall a b. (Integral a, Num b) => a -> b
fromIntegral) forall (parser :: * -> *). C parser => Fragile parser ByteList
getVarBytes

{- |
The returned list contains only bytes with the most significant bit cleared.
These are digits of a 128-ary number.
-}
getVarBytes :: Parser.C parser => Parser.Fragile parser [Word8]
getVarBytes :: forall (parser :: * -> *). C parser => Fragile parser ByteList
getVarBytes =
   do
      Word8
digit <- forall (parser :: * -> *). C parser => Fragile parser Word8
getByte
      if forall a b c. (a -> b -> c) -> b -> a -> c
flip forall a. Bits a => a -> Int -> Bool
testBit Int
7 Word8
digit            -- if it's the last byte
        then forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
liftM (forall a b c. (a -> b -> c) -> b -> a -> c
flip forall a. Bits a => a -> Int -> a
clearBit Int
7 Word8
digit forall a. a -> [a] -> [a]
:) forall (parser :: * -> *). C parser => Fragile parser ByteList
getVarBytes
        else forall (m :: * -> *) a. Monad m => a -> m a
return [Word8
digit]


getEnum :: (Parser.C parser, Enum enum, Bounded enum) => Parser.Fragile parser enum
getEnum :: forall (parser :: * -> *) enum.
(C parser, Enum enum, Bounded enum) =>
Fragile parser enum
getEnum = forall (parser :: * -> *) enum.
(C parser, Enum enum, Bounded enum) =>
Int -> Fragile parser enum
makeEnum forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< forall (parser :: * -> *). C parser => Fragile parser Int
get1

makeEnum :: (Parser.C parser, Enum enum, Bounded enum) => Int -> Parser.Fragile parser enum
makeEnum :: forall (parser :: * -> *) enum.
(C parser, Enum enum, Bounded enum) =>
Int -> Fragile parser enum
makeEnum Int
n =
   let go :: (Parser.C parser, Enum a) => a -> a -> Parser.Fragile parser a
       go :: forall (parser :: * -> *) a.
(C parser, Enum a) =>
a -> a -> Fragile parser a
go a
lower a
upper =
          if forall a. Enum a => a -> Int
fromEnum a
lower forall a. Ord a => a -> a -> Bool
<= Int
n Bool -> Bool -> Bool
&& Int
n forall a. Ord a => a -> a -> Bool
<= forall a. Enum a => a -> Int
fromEnum a
upper
            then forall (m :: * -> *) a. Monad m => a -> m a
return (forall a. Enum a => Int -> a
toEnum Int
n)
            else forall (m :: * -> *) a. Monad m => UserMessage -> T m a
Parser.giveUp (UserMessage
"value " forall a. [a] -> [a] -> [a]
++ forall a. Show a => a -> UserMessage
show Int
n forall a. [a] -> [a] -> [a]
++ UserMessage
" is out of range for enumeration")
   in  forall (parser :: * -> *) a.
(C parser, Enum a) =>
a -> a -> Fragile parser a
go forall a. Bounded a => a
minBound forall a. Bounded a => a
maxBound