packages feed

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 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 #-}