module Foundation.Primitive.Types.OffsetSize
( FileSize(..)
, Offset(..)
, Offset8
, offsetOfE
, offsetPlusE
, offsetMinusE
, offsetRecast
, offsetCast
, sizeCast
, sizeLastOffset
, sizeAsOffset
, sizeSub
, offsetAsSize
, (+.)
, (.==#)
, CountOf(..)
, Size8
, sizeOfE
, csizeOfOffset
, csizeOfSize
, sizeOfCSSize
, sizeOfCSize
) where
#include "MachDeps.h"
import GHC.Types
import GHC.Word
import GHC.Int
import GHC.Prim
import Foreign.C.Types
import System.Posix.Types (CSsize (..))
import Foundation.Internal.Base
import Foundation.Internal.Proxy
import Foundation.Numerical.Primitives
import Foundation.Numerical.Number
import Foundation.Numerical.Additive
import Foundation.Numerical.Subtractive
import Foundation.Numerical.Multiplicative
import Foundation.Primitive.IntegralConv
import Data.List (foldl')
#if WORD_SIZE_IN_BITS < 64
import GHC.IntWord64
#endif
newtype FileSize = FileSize Word64
deriving (Show,Eq,Ord)
type Offset8 = Offset Word8
newtype Offset ty = Offset Int
deriving (Show,Eq,Ord,Enum,Additive,Typeable)
instance Integral (Offset ty) where
fromInteger n
| n < 0 = error "CountOf: fromInteger: negative"
| otherwise = Offset . fromInteger $ n
instance IsIntegral (Offset ty) where
toInteger (Offset i) = toInteger i
instance IsNatural (Offset ty) where
toNatural (Offset i) = toNatural (intToWord i)
instance Subtractive (Offset ty) where
type Difference (Offset ty) = CountOf ty
(Offset a) (Offset b) = CountOf (ab)
instance IntegralCast Int (Offset ty) where
integralCast i = Offset i
instance IntegralCast Word (Offset ty) where
integralCast (W# w) = Offset (I# (word2Int# w))
(+.) :: Offset ty -> Int -> Offset ty
(+.) (Offset a) b = Offset (a + b)
(.==#) :: Offset ty -> CountOf ty -> Bool
(.==#) (Offset ofs) (CountOf sz) = ofs == sz
offsetOfE :: Size8 -> Offset ty -> Offset8
offsetOfE (CountOf sz) (Offset ty) = Offset (ty * sz)
offsetPlusE :: Offset ty -> CountOf ty -> Offset ty
offsetPlusE (Offset ofs) (CountOf sz) = Offset (ofs + sz)
offsetMinusE :: Offset ty -> CountOf ty -> Offset ty
offsetMinusE (Offset ofs) (CountOf sz) = Offset (ofs sz)
offsetRecast :: Size8 -> Size8 -> Offset ty -> Offset ty2
offsetRecast szTy (CountOf szTy2) ofs =
let (Offset bytes) = offsetOfE szTy ofs
in Offset (bytes `div` szTy2)
offsetCast :: Proxy (a -> b) -> Offset a -> Offset b
offsetCast _ (Offset o) = Offset o
sizeCast :: Proxy (a -> b) -> CountOf a -> CountOf b
sizeCast _ (CountOf sz) = CountOf sz
sizeSub :: CountOf a -> CountOf a -> CountOf a
sizeSub (CountOf m) (CountOf n)
| m > n = CountOf diff
| otherwise = error "sizeSub negative size"
where
diff = m n
sizeLastOffset :: CountOf a -> Offset a
sizeLastOffset (CountOf s)
| s > 0 = Offset (pred s)
| otherwise = error "last offset on size 0"
sizeAsOffset :: CountOf a -> Offset a
sizeAsOffset (CountOf a) = Offset a
offsetAsSize :: Offset a -> CountOf a
offsetAsSize (Offset a) = CountOf a
type Size8 = CountOf Word8
newtype CountOf ty = CountOf Int
deriving (Show,Eq,Ord,Enum,Typeable)
instance Integral (CountOf ty) where
fromInteger n
| n < 0 = error "CountOf: fromInteger: negative"
| otherwise = CountOf . fromInteger $ n
instance IsIntegral (CountOf ty) where
toInteger (CountOf i) = toInteger i
instance IsNatural (CountOf ty) where
toNatural (CountOf i) = toNatural (intToWord i)
instance Additive (CountOf ty) where
azero = CountOf 0
(+) (CountOf a) (CountOf b) = CountOf (a+b)
instance Subtractive (CountOf ty) where
type Difference (CountOf ty) = CountOf ty
(CountOf a) (CountOf b) = CountOf (ab)
instance Monoid (CountOf ty) where
mempty = azero
mappend = (+)
mconcat = foldl' (+) 0
instance IntegralCast Int (CountOf ty) where
integralCast i = CountOf i
instance IntegralCast Word (CountOf ty) where
integralCast (W# w) = CountOf (I# (word2Int# w))
sizeOfE :: Size8 -> CountOf ty -> Size8
sizeOfE (CountOf sz) (CountOf ty) = CountOf (ty * sz)
csizeOfSize :: Size8 -> CSize
#if WORD_SIZE_IN_BITS < 64
csizeOfSize (CountOf (I# sz)) = CSize (W32# (int2Word# sz))
#else
csizeOfSize (CountOf (I# sz)) = CSize (W64# (int2Word# sz))
#endif
csizeOfOffset :: Offset8 -> CSize
#if WORD_SIZE_IN_BITS < 64
csizeOfOffset (Offset (I# sz)) = CSize (W32# (int2Word# sz))
#else
csizeOfOffset (Offset (I# sz)) = CSize (W64# (int2Word# sz))
#endif
sizeOfCSSize :: CSsize -> Size8
sizeOfCSSize (CSsize (1)) = error "invalid size: CSSize is -1"
#if WORD_SIZE_IN_BITS < 64
sizeOfCSSize (CSsize (I32# sz)) = CountOf (I# sz)
#else
sizeOfCSSize (CSsize (I64# sz)) = CountOf (I# sz)
#endif
sizeOfCSize :: CSize -> Size8
#if WORD_SIZE_IN_BITS < 64
sizeOfCSize (CSize (W32# sz)) = CountOf (I# (word2Int# sz))
#else
sizeOfCSize (CSize (W64# sz)) = CountOf (I# (word2Int# sz))
#endif