@@ -77,91 +77,11 @@ import Data.Word ( Word8 )
7777import qualified GHC.Exts as Exts
7878import GHC.Exts hiding (setByteArray #)
7979
80- #if MIN_VERSION_base(4,17,0)
81-
82- import Data.Array.Byte (ByteArray (.. ), MutableByteArray (.. ))
83-
84- #else
85-
86- import Control.DeepSeq
87- import Data.Bits ( (.&.) , unsafeShiftR )
88- import GHC.Show ( intToDigit )
89- import Data.Typeable ( Typeable )
90- import Data.Data ( Data (.. ), mkNoRepType )
91- import qualified Language.Haskell.TH.Syntax as TH
92- import qualified Language.Haskell.TH.Lib as TH
93- import qualified Data.Semigroup as SG
94- import qualified Data.Foldable as F
95- import System.IO.Unsafe (unsafePerformIO , unsafeDupablePerformIO )
96-
97- -- | Byte arrays.
98- data ByteArray = ByteArray ByteArray # deriving ( Typeable )
99-
100- -- | Mutable byte arrays associated with a primitive state token.
101- data MutableByteArray s = MutableByteArray (MutableByteArray # s )
102- deriving ( Typeable )
103-
104- -- | Respects array pinnedness for GHC >= 8.2
105- instance TH. Lift ByteArray where
106- #if MIN_VERSION_template_haskell(2,17,0)
107- liftTyped ba = TH. unsafeCodeCoerce (TH. lift ba)
108- #elif MIN_VERSION_template_haskell(2,16,0)
109- liftTyped ba = TH. unsafeTExpCoerce (TH. lift ba)
80+ #if __GLASGOW_HASKELL__ < 804
81+ import System.IO.Unsafe (unsafeDupablePerformIO )
11082#endif
11183
112- lift ba =
113- TH. appE
114- (if small
115- then [| fromLitAddrSmall# pinned len | ]
116- else [| fromLitAddrLarge# pinned len | ])
117- (TH. litE (TH. stringPrimL (toList ba)))
118- where
119- -- Pin it if the original was pinned; otherwise don't. This seems more
120- -- logical to me than the alternatives. Anyone who wants a different
121- -- pinnedness can just copy the compile-time byte array to one that
122- -- matches what they want at run-time.
123- #if __GLASGOW_HASKELL__ >= 802
124- pinned = isByteArrayPinned ba
125- #else
126- pinned = True
127- #endif
128- len = sizeofByteArray ba
129- small = len <= 2048
130-
131- -- I don't think inlining these can be very helpful, so let's not
132- -- do it.
133- {-# NOINLINE fromLitAddrSmall# #-}
134- fromLitAddrSmall# :: Bool -> Int -> Addr # -> ByteArray
135- fromLitAddrSmall# pinned len ptr = inline (fromLitAddr# True pinned len ptr)
136-
137- {-# NOINLINE fromLitAddrLarge# #-}
138- fromLitAddrLarge# :: Bool -> Int -> Addr # -> ByteArray
139- fromLitAddrLarge# pinned len ptr = inline (fromLitAddr# False pinned len ptr)
140-
141- fromLitAddr# :: Bool -> Bool -> Int -> Addr # -> ByteArray
142- fromLitAddr# small pinned ! len ! ptr = upIO $ do
143- mba <- if pinned
144- then newPinnedByteArray len
145- else newByteArray len
146- copyPtrToMutableByteArray mba 0 (Ptr ptr :: Ptr Word8 ) len
147- unsafeFreezeByteArray mba
148- where
149- -- We don't care too much about duplication if the byte arrays are
150- -- small. If they're large, we do. Since we don't allocate while
151- -- we copy (we do it with a primop!), I don't believe the thunk
152- -- deduplication mechanism can help us if two threads just happen
153- -- to try to build the ByteArray at the same time.
154- upIO
155- | small = unsafeDupablePerformIO
156- | otherwise = unsafePerformIO
157-
158- instance NFData ByteArray where
159- rnf (ByteArray _) = ()
160-
161- instance NFData (MutableByteArray s ) where
162- rnf (MutableByteArray _) = ()
163-
164- #endif
84+ import Data.Array.Byte (ByteArray (.. ), MutableByteArray (.. ))
16585
16686-- | Create a new mutable byte array of the specified size in bytes.
16787--
@@ -599,65 +519,6 @@ foreign import ccall unsafe "primitive-memops.h hsprimitive_memmove"
599519 -> MutableByteArray # s -> CPtrdiff
600520 -> CSize -> IO ()
601521
602- #if !MIN_VERSION_base(4,17,0)
603-
604- instance Eq (MutableByteArray s ) where
605- (==) = sameMutableByteArray
606-
607- instance Data ByteArray where
608- toConstr _ = error " toConstr"
609- gunfold _ _ = error " gunfold"
610- dataTypeOf _ = mkNoRepType " Data.Primitive.ByteArray.ByteArray"
611-
612- instance Typeable s => Data (MutableByteArray s ) where
613- toConstr _ = error " toConstr"
614- gunfold _ _ = error " gunfold"
615- dataTypeOf _ = mkNoRepType " Data.Primitive.ByteArray.MutableByteArray"
616-
617- -- | @since 0.6.3.0
618- --
619- -- Behavior changed in 0.7.2.0. Before 0.7.2.0, this instance rendered
620- -- 8-bit words less than 16 as a single hexadecimal digit (e.g. 13 was @0xD@).
621- -- Starting with 0.7.2.0, all 8-bit words are represented as two digits
622- -- (e.g. 13 is @0x0D@).
623- instance Show ByteArray where
624- showsPrec _ ba =
625- showString " [" . go 0
626- where
627- showW8 :: Word8 -> String -> String
628- showW8 ! w s =
629- ' 0'
630- : ' x'
631- : intToDigit (fromIntegral (unsafeShiftR w 4 ))
632- : intToDigit (fromIntegral (w .&. 0x0F ))
633- : s
634- go i
635- | i < sizeofByteArray ba = comma . showW8 (indexByteArray ba i :: Word8 ) . go (i+ 1 )
636- | otherwise = showChar ' ]'
637- where
638- comma | i == 0 = id
639- | otherwise = showString " , "
640-
641- -- Only used internally
642- compareByteArraysFromBeginning :: ByteArray -> ByteArray -> Int -> Ordering
643- {-# INLINE compareByteArraysFromBeginning #-}
644- #if __GLASGOW_HASKELL__ >= 804
645- compareByteArraysFromBeginning (ByteArray ba1# ) (ByteArray ba2# ) (I # n# )
646- = compare (I # (compareByteArrays# ba1# 0 # ba2# 0 # n# )) 0
647- #else
648- -- Emulate GHC 8.4's 'GHC.Prim.compareByteArrays#'
649- compareByteArraysFromBeginning (ByteArray ba1# ) (ByteArray ba2# ) (I # n# )
650- = compare (fromCInt (unsafeDupablePerformIO (memcmp_ba ba1# ba2# n))) 0
651- where
652- n = fromIntegral (I # n# ) :: CSize
653- fromCInt = fromIntegral :: CInt -> Int
654-
655- foreign import ccall unsafe " primitive-memops.h hsprimitive_memcmp"
656- memcmp_ba :: ByteArray # -> ByteArray # -> CSize -> IO CInt
657- #endif
658-
659- #endif
660-
661522-- | Lexicographic comparison of equal-length slices into two byte arrays.
662523-- This wraps the @compareByteArrays#@ primop, which wraps @memcmp@.
663524compareByteArrays
@@ -683,112 +544,11 @@ foreign import ccall unsafe "primitive-memops.h hsprimitive_memcmp_offset"
683544 memcmp_ba_offs :: ByteArray # -> Int # -> ByteArray # -> Int # -> CSize -> IO CInt
684545#endif
685546
686- #if !MIN_VERSION_base(4,17,0)
687-
688- sameByteArray :: ByteArray # -> ByteArray # -> Bool
689- sameByteArray ba1 ba2 =
690- case reallyUnsafePtrEquality# (unsafeCoerce# ba1 :: () ) (unsafeCoerce# ba2 :: () ) of
691- r -> isTrue# r
692-
693- -- | @since 0.6.3.0
694- instance Eq ByteArray where
695- ba1@ (ByteArray ba1# ) == ba2@ (ByteArray ba2# )
696- | sameByteArray ba1# ba2# = True
697- | n1 /= n2 = False
698- | otherwise = compareByteArraysFromBeginning ba1 ba2 n1 == EQ
699- where
700- n1 = sizeofByteArray ba1
701- n2 = sizeofByteArray ba2
702-
703- -- | Non-lexicographic ordering. This compares the lengths of
704- -- the byte arrays first and uses a lexicographic ordering if
705- -- the lengths are equal. Subject to change between major versions.
706- --
707- -- @since 0.6.3.0
708- instance Ord ByteArray where
709- ba1@ (ByteArray ba1# ) `compare` ba2@ (ByteArray ba2# )
710- | sameByteArray ba1# ba2# = EQ
711- | n1 /= n2 = n1 `compare` n2
712- | otherwise = compareByteArraysFromBeginning ba1 ba2 n1
713- where
714- n1 = sizeofByteArray ba1
715- n2 = sizeofByteArray ba2
716- -- Note: On GHC 8.4, the primop compareByteArrays# performs a check for pointer
717- -- equality as a shortcut, so the check here is actually redundant. However, it
718- -- is included here because it is likely better to check for pointer equality
719- -- before checking for length equality. Getting the length requires deferencing
720- -- the pointers, which could cause accesses to memory that is not in the cache.
721- -- By contrast, a pointer equality check is always extremely cheap.
722-
723- appendByteArray :: ByteArray -> ByteArray -> ByteArray
724- appendByteArray a b = runST $ do
725- marr <- newByteArray (sizeofByteArray a + sizeofByteArray b)
726- copyByteArray marr 0 a 0 (sizeofByteArray a)
727- copyByteArray marr (sizeofByteArray a) b 0 (sizeofByteArray b)
728- unsafeFreezeByteArray marr
729-
730- concatByteArray :: [ByteArray ] -> ByteArray
731- concatByteArray arrs = runST $ do
732- let len = calcLength arrs 0
733- marr <- newByteArray len
734- pasteByteArrays marr 0 arrs
735- unsafeFreezeByteArray marr
736-
737- pasteByteArrays :: MutableByteArray s -> Int -> [ByteArray ] -> ST s ()
738- pasteByteArrays ! _ ! _ [] = return ()
739- pasteByteArrays ! marr ! ix (x : xs) = do
740- copyByteArray marr ix x 0 (sizeofByteArray x)
741- pasteByteArrays marr (ix + sizeofByteArray x) xs
742-
743- calcLength :: [ByteArray ] -> Int -> Int
744- calcLength [] ! n = n
745- calcLength (x : xs) ! n = calcLength xs (sizeofByteArray x + n)
746-
747- #endif
748-
749547-- | The empty 'ByteArray'.
750548emptyByteArray :: ByteArray
751549{-# NOINLINE emptyByteArray #-}
752550emptyByteArray = runST (newByteArray 0 >>= unsafeFreezeByteArray)
753551
754- #if !MIN_VERSION_base(4,17,0)
755-
756- replicateByteArray :: Int -> ByteArray -> ByteArray
757- replicateByteArray n arr = runST $ do
758- marr <- newByteArray (n * sizeofByteArray arr)
759- let go i = if i < n
760- then do
761- copyByteArray marr (i * sizeofByteArray arr) arr 0 (sizeofByteArray arr)
762- go (i + 1 )
763- else return ()
764- go 0
765- unsafeFreezeByteArray marr
766-
767- instance SG. Semigroup ByteArray where
768- (<>) = appendByteArray
769- sconcat = mconcat . F. toList
770- stimes n arr = case compare n 0 of
771- LT -> die " stimes" " negative multiplier"
772- EQ -> emptyByteArray
773- GT -> replicateByteArray (fromIntegral n) arr
774-
775- instance Monoid ByteArray where
776- mempty = emptyByteArray
777- #if !(MIN_VERSION_base(4,11,0))
778- mappend = appendByteArray
779- #endif
780- mconcat = concatByteArray
781-
782- -- | @since 0.6.3.0
783- instance Exts. IsList ByteArray where
784- type Item ByteArray = Word8
785-
786- toList = foldrByteArray (:) []
787- fromList xs = byteArrayFromListN (length xs) xs
788- fromListN = byteArrayFromListN
789-
790- #endif
791-
792552die :: String -> String -> a
793553die fun problem = error $ " Data.Primitive.ByteArray." ++ fun ++ " : " ++ problem
794554
0 commit comments