foreign 0.1.1.0 → 0.1.2.0
raw patch · 6 files changed
+106/−15 lines, 6 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
+ HsForeign.String: maybeNewStdString :: Maybe ByteString -> IO (Ptr StdString)
+ HsForeign.String: newStablePtrByteString :: ByteString -> IO (CString, Int, StablePtr ByteString)
+ HsForeign.String: newStdString :: ByteString -> IO (Ptr StdString)
+ HsForeign.String: withByteStringList :: [ByteString] -> (Ptr (Ptr Word8) -> Ptr Int -> Int -> IO a) -> IO a
+ HsForeign.String: withMaybeByteString :: Maybe ByteString -> (Ptr Word8 -> Int -> IO a) -> IO a
+ HsForeign.String: withShortByteString :: ShortByteString -> (ByteArray# -> Int -> IO a) -> IO a
+ HsForeign.Utils: withMaybePtr :: Maybe a -> (a -> (Ptr a -> IO b) -> IO b) -> (Ptr a -> IO b) -> IO b
Files
- README.md +2/−2
- foreign.cabal +2/−1
- src/HsForeign.hs +2/−0
- src/HsForeign/Primitive.hs +1/−1
- src/HsForeign/String.hs +85/−11
- src/HsForeign/Utils.hs +14/−0
README.md view
@@ -1,4 +1,4 @@ # foreign -A collection of data types, classes, and functions for easing your ffi-experience.+Extra collection of data types, classes, and functions for interfacing with c+and c++.
foreign.cabal view
@@ -1,6 +1,6 @@ cabal-version: 2.4 name: foreign-version: 0.1.1.0+version: 0.1.2.0 synopsis: A collection of helpers for ffi. description: Please see the README on Github at <https://github.com/4eUeP/foreign#readme>@@ -52,6 +52,7 @@ HsForeign.AsyncFFI HsForeign.Primitive HsForeign.String+ HsForeign.Utils build-depends: , base >=4.14 && <5
src/HsForeign.hs view
@@ -2,8 +2,10 @@ ( module HsForeign.Primitive , module HsForeign.AsyncFFI , module HsForeign.String+ , module HsForeign.Utils ) where import HsForeign.AsyncFFI import HsForeign.Primitive import HsForeign.String+import HsForeign.Utils
src/HsForeign/Primitive.hs view
@@ -24,7 +24,7 @@ , byteArrayContents# , mutableByteArrayContents# - -- * Re-export+ -- * Re-exports , module Data.Primitive , module Control.Monad.Primitive ) where
src/HsForeign/String.hs view
@@ -1,12 +1,24 @@+{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE CPP #-}+{-# LANGUAGE MagicHash #-}+{-# LANGUAGE PatternSynonyms #-}+{-# LANGUAGE TupleSections #-}+ module HsForeign.String ( -- * CString mallocFromByteString , mallocFromMaybeByteString+ , newStablePtrByteString , withByteString+ , withMaybeByteString+ , withByteStringList , withByteStrings+ , withShortByteString -- * CXX: std::string , StdString+ , newStdString+ , maybeNewStdString , hs_new_std_string , hs_new_std_string_def , hs_std_string_size@@ -15,16 +27,21 @@ , unsafePeekStdString ) where -import Control.Exception (AssertionFailed (..), throw)-import Control.Monad (unless)-import Data.ByteString (ByteString)-import qualified Data.ByteString.Internal as BS-import qualified Data.ByteString.Unsafe as BS+import Control.Exception (AssertionFailed (..), throw)+import Control.Monad (unless)+import Data.ByteString (ByteString)+import qualified Data.ByteString.Internal as BS+import Data.ByteString.Short (ShortByteString)+import qualified Data.ByteString.Short.Internal as BSS+import qualified Data.ByteString.Unsafe as BS import Data.Word import Foreign.C.String import Foreign.ForeignPtr+import Foreign.ForeignPtr.Unsafe import Foreign.Marshal import Foreign.Ptr+import Foreign.StablePtr+import GHC.Exts (touch#) import HsForeign.Primitive @@ -48,15 +65,42 @@ mallocFromMaybeByteString Nothing = return (nullPtr, 0) {-# INLINE mallocFromMaybeByteString #-} +newStablePtrByteString :: ByteString -> IO (CString, Int, StablePtr ByteString)+newStablePtrByteString bs = do+ !sp <- newStablePtr bs+ let (fp, len) = toForeignPtr0 bs+ !p = unsafeForeignPtrToPtr fp+ pure (castPtr p, len, sp)+ withByteString :: ByteString -> (Ptr Word8 -> Int -> IO a) -> IO a-withByteString (BS.PS fp off len) f =- -- TODO: since bytestring 0.11.0.0, it exports the 'BS' constructor.- -- we can change to benefit from the simplified BS constructor if we only- -- support bytestring >= 0.11- let fp' = fp `plusForeignPtr` off- in withForeignPtr fp' $ \p -> f p len+withByteString bs f =+ let (fp, len) = toForeignPtr0 bs+ in withForeignPtr fp $ \p -> f p len+{-# INLINABLE withByteString #-} +withMaybeByteString :: Maybe ByteString -> (Ptr Word8 -> Int -> IO a) -> IO a+withMaybeByteString Nothing f = f nullPtr 0+withMaybeByteString (Just bs) f =+ let (fp, len) = toForeignPtr0 bs+ in withForeignPtr fp $ \p -> f p len+{-# INLINABLE withMaybeByteString #-}+ -- | Pass list of ByteStrings to FFI.+withByteStringList+ :: [ByteString]+ -> (Ptr (Ptr Word8) -> Ptr Int -> Int -> IO a)+ -- ^ cstring*, len*, list_len+ -> IO a+withByteStringList bss f = do+ let (ps, lens) = unzip (map toForeignPtr0 bss)+ withPrimArray (primArrayFromList lens) $ \lens' num ->+ withForeignPtrList ps $ \ps' num_ps -> do+ unless (num == num_ps) $ throw $+ AssertionFailed "This should never happen..."+ f ps' lens' num++{-# DEPRECATED withByteStrings "use withByteStringList instead" #-}+-- | Pass list of ByteStrings to FFI. withByteStrings :: [ByteString] -> (Ptr (Ptr Word8) -> Ptr Int -> Ptr Int -> Int -> IO a)@@ -72,6 +116,12 @@ AssertionFailed "This should never happen..." f ps' offs' lens' num +withShortByteString :: ShortByteString -> (ByteArray# -> Int -> IO a) -> IO a+withShortByteString sbs@(BSS.SBS ba#) f = do+ !r <- f ba# (BSS.length sbs)+ primitive_ $ touch# ba#+ pure r+ ------------------------------------------------------------------------------- -- std::string @@ -83,9 +133,33 @@ foreign import ccall unsafe hs_std_string_cstr :: Ptr StdString -> IO (Ptr Word8) foreign import ccall unsafe hs_delete_std_string :: Ptr StdString -> IO () +-- | New a c++ std::string from proviced bytestring.+--+-- The memory should be deallocated using delete when no longer required.+newStdString :: ByteString -> IO (Ptr StdString)+newStdString bs = withByteString bs $ hs_new_std_string++maybeNewStdString :: Maybe ByteString -> IO (Ptr StdString)+maybeNewStdString Nothing = pure nullPtr+maybeNewStdString (Just bs) = newStdString bs+ unsafePeekStdString :: Ptr StdString -> IO ByteString unsafePeekStdString stdstring = do siz <- hs_std_string_size stdstring ptr <- hs_std_string_cstr stdstring BS.unsafePackCStringFinalizer ptr siz (hs_delete_std_string stdstring) {-# INLINE unsafePeekStdString #-}++-------------------------------------------------------------------------------++-- TODO: since bytestring 0.11.0.0, it exports the 'BS' constructor and+-- 'toForeignPtr0'.+--+-- we can change to benefit from the simplified BS constructor if we only+-- support bytestring >= 0.11+toForeignPtr0 :: ByteString -> (ForeignPtr Word8, Int)+#if !MIN_VERSION_bytestring(0, 11, 0)+toForeignPtr0 (BS.PS fp off len) = (fp `plusForeignPtr` off, len)+#else+toForeignPtr0 = BS.toForeignPtr0+#endif
+ src/HsForeign/Utils.hs view
@@ -0,0 +1,14 @@+module HsForeign.Utils+ ( withMaybePtr+ ) where++import Foreign.Ptr++withMaybePtr+ :: Maybe a+ -> (a -> (Ptr a -> IO b) -> IO b)+ -> (Ptr a -> IO b)+ -> IO b+withMaybePtr Nothing _withx f = f nullPtr+withMaybePtr (Just x) withx f = withx x f+{-# INLINABLE withMaybePtr #-}