Skip to content

Commit d7a2ce2

Browse files
authored
Use FFI for unaligned reads (#235)
1 parent f762304 commit d7a2ce2

3 files changed

Lines changed: 47 additions & 20 deletions

File tree

binary.cabal

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ library
5353
Data.Binary.Internal,
5454
Data.Binary.Generic,
5555
Data.Binary.FloatCast
56-
56+
c-sources: cbits/unaligned_read.c
5757
ghc-options: -O2 -Wall -fliberate-case-threshold=1000
5858

5959
if impl(ghc >= 8.0)

cbits/unaligned_read.c

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
#include <string.h>
2+
3+
#include "HsFFI.h"
4+
5+
#define UNALIGNED_READ(TYPE) Hs##TYPE _hs_binary_unaligned_read_##TYPE(HsWord8 *ptr) { Hs##TYPE result; memcpy(&result, ptr, sizeof(Hs##TYPE)); return result; }
6+
7+
UNALIGNED_READ(Word)
8+
UNALIGNED_READ(Word16)
9+
UNALIGNED_READ(Word32)
10+
UNALIGNED_READ(Word64)
11+
UNALIGNED_READ(Int)
12+
UNALIGNED_READ(Int16)
13+
UNALIGNED_READ(Int32)
14+
UNALIGNED_READ(Int64)
15+
UNALIGNED_READ(Float)
16+
UNALIGNED_READ(Double)

src/Data/Binary/Get.hs

Lines changed: 30 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -446,15 +446,6 @@ getShortByteString = fmap toShort . getByteString
446446
------------------------------------------------------------------------
447447
-- Primitives
448448

449-
-- helper, get a raw Ptr onto a strict ByteString copied out of the
450-
-- underlying lazy byteString.
451-
452-
#if !defined(HS_UNALIGNED_ADDR_PRIMOPS_AVAILABLE)
453-
getPtr :: Storable a => Int -> Get a
454-
getPtr n = readNWith n peek
455-
{-# INLINE getPtr #-}
456-
#endif
457-
458449
-- | Read a Word8 from the monad state
459450
getWord8 :: Get Word8
460451
getWord8 = readN 1 B.unsafeHead
@@ -594,7 +585,9 @@ getWordhost = readNWith SIZEOF_HSWORD $ \(Ptr p#) ->
594585
IO $ \s -> case readWord8OffAddrAsWord# p# 0# s of
595586
(# s', w# #) -> (# s', W# w# #)
596587
#else
597-
getWordhost = getPtr (sizeOf (undefined :: Word))
588+
getWordhost = readNWith (sizeOf (0 :: Word)) unalignedReadWord
589+
590+
foreign import ccall unsafe "_hs_binary_unaligned_read_Word" unalignedReadWord :: Ptr Word -> IO Word
598591
#endif
599592
{-# INLINE getWordhost #-}
600593

@@ -605,7 +598,9 @@ getWord16host = readNWith 2 $ \(Ptr p#) ->
605598
IO $ \s -> case readWord8OffAddrAsWord16# p# 0# s of
606599
(# s', w16# #) -> (# s', W16# w16# #)
607600
#else
608-
getWord16host = getPtr (sizeOf (undefined :: Word16))
601+
getWord16host = readNWith (sizeOf (0 :: Word16)) unalignedReadWord16
602+
603+
foreign import ccall unsafe "_hs_binary_unaligned_read_Word16" unalignedReadWord16 :: Ptr Word16 -> IO Word16
609604
#endif
610605
{-# INLINE getWord16host #-}
611606

@@ -616,7 +611,9 @@ getWord32host = readNWith 4 $ \(Ptr p#) ->
616611
IO $ \s -> case readWord8OffAddrAsWord32# p# 0# s of
617612
(# s', w32# #) -> (# s', W32# w32# #)
618613
#else
619-
getWord32host = getPtr (sizeOf (undefined :: Word32))
614+
getWord32host = readNWith (sizeOf (0 :: Word32)) unalignedReadWord32
615+
616+
foreign import ccall unsafe "_hs_binary_unaligned_read_Word32" unalignedReadWord32 :: Ptr Word32 -> IO Word32
620617
#endif
621618
{-# INLINE getWord32host #-}
622619

@@ -627,7 +624,9 @@ getWord64host = readNWith 8 $ \(Ptr p#) ->
627624
IO $ \s -> case readWord8OffAddrAsWord64# p# 0# s of
628625
(# s', w64# #) -> (# s', W64# w64# #)
629626
#else
630-
getWord64host = getPtr (sizeOf (undefined :: Word64))
627+
getWord64host = readNWith (sizeOf (0 :: Word64)) unalignedReadWord64
628+
629+
foreign import ccall unsafe "_hs_binary_unaligned_read_Word64" unalignedReadWord64 :: Ptr Word64 -> IO Word64
631630
#endif
632631
{-# INLINE getWord64host #-}
633632

@@ -639,7 +638,9 @@ getInthost = readNWith SIZEOF_HSINT $ \(Ptr p#) ->
639638
IO $ \s -> case readWord8OffAddrAsInt# p# 0# s of
640639
(# s', i# #) -> (# s', I# i# #)
641640
#else
642-
getInthost = getPtr (sizeOf (undefined :: Int))
641+
getInthost = readNWith (sizeOf (0 :: Int)) unalignedReadInt
642+
643+
foreign import ccall unsafe "_hs_binary_unaligned_read_Int" unalignedReadInt :: Ptr Int -> IO Int
643644
#endif
644645
{-# INLINE getInthost #-}
645646

@@ -650,7 +651,9 @@ getInt16host = readNWith 2 $ \(Ptr p#) ->
650651
IO $ \s -> case readWord8OffAddrAsInt16# p# 0# s of
651652
(# s', i16# #) -> (# s', I16# i16# #)
652653
#else
653-
getInt16host = getPtr (sizeOf (undefined :: Int16))
654+
getInt16host = readNWith (sizeOf (0 :: Int16)) unalignedReadInt16
655+
656+
foreign import ccall unsafe "_hs_binary_unaligned_read_Int16" unalignedReadInt16 :: Ptr Int16 -> IO Int16
654657
#endif
655658
{-# INLINE getInt16host #-}
656659

@@ -661,7 +664,9 @@ getInt32host = readNWith 4 $ \(Ptr p#) ->
661664
IO $ \s -> case readWord8OffAddrAsInt32# p# 0# s of
662665
(# s', i32# #) -> (# s', I32# i32# #)
663666
#else
664-
getInt32host = getPtr (sizeOf (undefined :: Int32))
667+
getInt32host = readNWith (sizeOf (0 :: Int32)) unalignedReadInt32
668+
669+
foreign import ccall unsafe "_hs_binary_unaligned_read_Int32" unalignedReadInt32 :: Ptr Int32 -> IO Int32
665670
#endif
666671
{-# INLINE getInt32host #-}
667672

@@ -672,7 +677,9 @@ getInt64host = readNWith 8 $ \(Ptr p#) ->
672677
IO $ \s -> case readWord8OffAddrAsInt64# p# 0# s of
673678
(# s', i64# #) -> (# s', I64# i64# #)
674679
#else
675-
getInt64host = getPtr (sizeOf (undefined :: Int64))
680+
getInt64host = readNWith (sizeOf (0 :: Int64)) unalignedReadInt64
681+
682+
foreign import ccall unsafe "_hs_binary_unaligned_read_Int64" unalignedReadInt64 :: Ptr Int64 -> IO Int64
676683
#endif
677684
{-# INLINE getInt64host #-}
678685

@@ -705,7 +712,9 @@ getFloathost = readNWith 4 $ \(Ptr p#) ->
705712
IO $ \s -> case readWord8OffAddrAsFloat# p# 0# s of
706713
(# s', f# #) -> (# s', F# f# #)
707714
#else
708-
getFloathost = wordToFloat <$> getWord32host
715+
getFloathost = readNWith (sizeOf (0 :: Float)) unalignedReadFloat
716+
717+
foreign import ccall unsafe "_hs_binary_unaligned_read_Float" unalignedReadFloat :: Ptr Float -> IO Float
709718
#endif
710719
{-# INLINE getFloathost #-}
711720

@@ -734,6 +743,8 @@ getDoublehost = readNWith 8 $ \(Ptr p#) ->
734743
IO $ \s -> case readWord8OffAddrAsDouble# p# 0# s of
735744
(# s', d# #) -> (# s', D# d# #)
736745
#else
737-
getDoublehost = wordToDouble <$> getWord64host
746+
getDoublehost = readNWith (sizeOf (0 :: Double)) unalignedReadDouble
747+
748+
foreign import ccall unsafe "_hs_binary_unaligned_read_Double" unalignedReadDouble :: Ptr Double -> IO Double
738749
#endif
739750
{-# INLINE getDoublehost #-}

0 commit comments

Comments
 (0)