primitive-addr (empty) → 0.1.0.0
raw patch · 5 files changed
+193/−0 lines, 5 filesdep +basedep +primitivesetup-changed
Dependencies added: base, primitive
Files
- CHANGELOG.md +5/−0
- LICENSE +30/−0
- Setup.hs +2/−0
- primitive-addr.cabal +21/−0
- src/Data/Primitive/Addr.hs +135/−0
+ CHANGELOG.md view
@@ -0,0 +1,5 @@+# Revision history for primitive-addr++## 0.1.0.0 -- YYYY-mm-dd++* First version. Released on an unsuspecting world.
+ LICENSE view
@@ -0,0 +1,30 @@+Copyright (c) 2019, Andrew Martin++All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are met:++ * Redistributions of source code must retain the above copyright+ notice, this list of conditions and the following disclaimer.++ * Redistributions in binary form must reproduce the above+ copyright notice, this list of conditions and the following+ disclaimer in the documentation and/or other materials provided+ with the distribution.++ * Neither the name of Andrew Martin nor the names of other+ contributors may be used to endorse or promote products derived+ from this software without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ primitive-addr.cabal view
@@ -0,0 +1,21 @@+cabal-version: 2.2+name: primitive-addr+version: 0.1.0.0+synopsis: Addresses to unmanaged memory+homepage: https://github.com/andrewthad/primitive-addr+bug-reports: https://github.com/andrewthad/primitive-addr/issues+license: BSD-3-Clause+license-file: LICENSE+author: Andrew Martin+maintainer: andrew.thaddeus@gmail.com+copyright: 2019 Andrew Martin+category: Data+extra-source-files: CHANGELOG.md++library+ exposed-modules: Data.Primitive.Addr+ build-depends:+ base >=4.11.1.0 && <5+ , primitive >=0.7 && <0.8+ hs-source-dirs: src+ default-language: Haskell2010
+ src/Data/Primitive/Addr.hs view
@@ -0,0 +1,135 @@+{-# language MagicHash #-}+{-# language UnboxedTuples #-}++-- | Primitive operations on machine addresses.+module Data.Primitive.Addr+ ( -- * Types+ Addr(..)+ -- * Address arithmetic+ , nullAddr+ , plusAddr+ , minusAddr+ , remAddr+ -- * Element access+ , indexOffAddr+ , readOffAddr+ , writeOffAddr+ -- * Block operations+ , copyAddr+ , copyAddrToByteArray+ , moveAddr+ , setAddr+ -- * Conversion+ , addrToInt+) where++import Numeric (showHex)+import Control.Monad.Primitive+import Data.Primitive.Types+import Data.Primitive.ByteArray++import GHC.Exts+import GHC.Ptr+import Foreign.Marshal.Utils++-- | A machine address+data Addr = Addr Addr#++instance Show Addr where+ showsPrec _ (Addr a) =+ showString "0x" . showHex (fromIntegral (I# (addr2Int# a)) :: Word)++instance Eq Addr where+ Addr a# == Addr b# = isTrue# (eqAddr# a# b#)+ Addr a# /= Addr b# = isTrue# (neAddr# a# b#)++instance Ord Addr where+ Addr a# > Addr b# = isTrue# (gtAddr# a# b#)+ Addr a# >= Addr b# = isTrue# (geAddr# a# b#)+ Addr a# < Addr b# = isTrue# (ltAddr# a# b#)+ Addr a# <= Addr b# = isTrue# (leAddr# a# b#)++-- | The null address+nullAddr :: Addr+nullAddr = Addr nullAddr#++infixl 6 `plusAddr`, `minusAddr`+infixl 7 `remAddr`++-- | Offset an address by the given number of bytes+plusAddr :: Addr -> Int -> Addr+plusAddr (Addr a#) (I# i#) = Addr (plusAddr# a# i#)++-- | Distance in bytes between two addresses. The result is only valid if the+-- difference fits in an 'Int'.+minusAddr :: Addr -> Addr -> Int+minusAddr (Addr a#) (Addr b#) = I# (minusAddr# a# b#)++-- | The remainder of the address and the integer.+remAddr :: Addr -> Int -> Int+remAddr (Addr a#) (I# i#) = I# (remAddr# a# i#)++-- | Read a value from a memory position given by an address and an offset.+-- The memory block the address refers to must be immutable. The offset is in+-- elements of type @a@ rather than in bytes.+indexOffAddr :: Prim a => Addr -> Int -> a+{-# INLINE indexOffAddr #-}+indexOffAddr (Addr addr#) (I# i#) = indexOffAddr# addr# i#++-- | Read a value from a memory position given by an address and an offset.+-- The offset is in elements of type @a@ rather than in bytes.+readOffAddr :: (Prim a, PrimMonad m) => Addr -> Int -> m a+{-# INLINE readOffAddr #-}+readOffAddr (Addr addr#) (I# i#) = primitive (readOffAddr# addr# i#)++-- | Write a value to a memory position given by an address and an offset.+-- The offset is in elements of type @a@ rather than in bytes.+writeOffAddr :: (Prim a, PrimMonad m) => Addr -> Int -> a -> m ()+{-# INLINE writeOffAddr #-}+writeOffAddr (Addr addr#) (I# i#) x = primitive_ (writeOffAddr# addr# i# x)++-- | Copy the given number of bytes from the second 'Addr' to the first. The+-- areas may not overlap.+copyAddr :: PrimMonad m+ => Addr -- ^ destination address+ -> Addr -- ^ source address+ -> Int -- ^ number of bytes+ -> m ()+{-# INLINE copyAddr #-}+copyAddr (Addr dst#) (Addr src#) n+ = unsafePrimToPrim $ copyBytes (Ptr dst#) (Ptr src#) n++-- | Copy the given number of bytes from the 'Addr' to the 'MutableByteArray'.+-- The areas may not overlap. This function is only available when compiling+-- with GHC 7.8 or newer.+copyAddrToByteArray :: PrimMonad m+ => MutableByteArray (PrimState m) -- ^ destination+ -> Int -- ^ offset into the destination array+ -> Addr -- ^ source+ -> Int -- ^ number of bytes to copy+ -> m ()+{-# INLINE copyAddrToByteArray #-}+copyAddrToByteArray (MutableByteArray marr) (I# off) (Addr addr) (I# len) =+ primitive_ $ copyAddrToByteArray# addr marr off len++-- | Copy the given number of bytes from the second 'Addr' to the first. The+-- areas may overlap.+moveAddr :: PrimMonad m => Addr -- ^ destination address+ -> Addr -- ^ source address+ -> Int -- ^ number of bytes+ -> m ()+{-# INLINE moveAddr #-}+moveAddr (Addr dst#) (Addr src#) n+ = unsafePrimToPrim $ moveBytes (Ptr dst#) (Ptr src#) n++-- | Fill a memory block of with the given value. The length is in+-- elements of type @a@ rather than in bytes.+setAddr :: (Prim a, PrimMonad m) => Addr -> Int -> a -> m ()+{-# INLINE setAddr #-}+setAddr (Addr addr#) (I# n#) x = primitive_ (setOffAddr# addr# 0# n# x)++-- | Convert an 'Addr' to an 'Int'.+addrToInt :: Addr -> Int+{-# INLINE addrToInt #-}+addrToInt (Addr addr#) = I# (addr2Int# addr#)+