diff options
author | Joe Crayne <joe@jerkface.net> | 2018-10-23 22:23:56 -0400 |
---|---|---|
committer | Joe Crayne <joe@jerkface.net> | 2018-10-23 22:23:56 -0400 |
commit | 94ab26f229bc59e8e917e0e67484b0b833fb0fa8 (patch) | |
tree | 6b108785d0112c8ce5b91da46efb5537ef117966 | |
parent | d62577cf423148a2a07eac33377003802e7e70d6 (diff) |
withByteString (wrapper on withForeignPtr)
-rw-r--r-- | haskell/Data/XDelta.hsc | 49 |
1 files changed, 32 insertions, 17 deletions
diff --git a/haskell/Data/XDelta.hsc b/haskell/Data/XDelta.hsc index 113959b..d276a8d 100644 --- a/haskell/Data/XDelta.hsc +++ b/haskell/Data/XDelta.hsc | |||
@@ -59,11 +59,15 @@ foreign import ccall "xdelta3.h xd3_abort_stream" xd3_abort_stream :: Ptr Xd3Str | |||
59 | foreign import ccall "xdelta3.h xd3_close_stream" xd3_close_stream :: Ptr Xd3Stream -> IO ErrorCode | 59 | foreign import ccall "xdelta3.h xd3_close_stream" xd3_close_stream :: Ptr Xd3Stream -> IO ErrorCode |
60 | 60 | ||
61 | 61 | ||
62 | writeCompressorConfig :: PrimMonad m => | ||
63 | MutableByteArray (PrimState m) -> Int -> CompressorConfig -> m () | ||
62 | writeCompressorConfig c o sec = do | 64 | writeCompressorConfig c o sec = do |
63 | writeAtByte c (o + #{offset xd3_sec_cfg,ngroups}) (ngroups sec) | 65 | writeAtByte c (o + #{offset xd3_sec_cfg,ngroups}) (ngroups sec) |
64 | writeAtByte c (o + #{offset xd3_sec_cfg,sector_size}) (sector_size sec) | 66 | writeAtByte c (o + #{offset xd3_sec_cfg,sector_size}) (sector_size sec) |
65 | writeAtByte c (o + #{offset xd3_sec_cfg,inefficient}) (inefficient sec) | 67 | writeAtByte c (o + #{offset xd3_sec_cfg,inefficient}) (inefficient sec) |
66 | 68 | ||
69 | writeMatcher :: PrimMonad m => | ||
70 | MutableByteArray (PrimState m) -> Int -> StringMatcher -> m () | ||
67 | writeMatcher c o sm = do | 71 | writeMatcher c o sm = do |
68 | -- handled elsewhere: const char *name; <- smName :: String | 72 | -- handled elsewhere: const char *name; <- smName :: String |
69 | writeAtByte c (o + #{offset xd3_smatcher, string_match }) (smStringMatch sm) | 73 | writeAtByte c (o + #{offset xd3_smatcher, string_match }) (smStringMatch sm) |
@@ -75,7 +79,10 @@ writeMatcher c o sm = do | |||
75 | writeAtByte c (o + #{offset xd3_smatcher, max_lazy }) (smMaxLazy sm) | 79 | writeAtByte c (o + #{offset xd3_smatcher, max_lazy }) (smMaxLazy sm) |
76 | writeAtByte c (o + #{offset xd3_smatcher, long_enough }) (smLongEnough sm) | 80 | writeAtByte c (o + #{offset xd3_smatcher, long_enough }) (smLongEnough sm) |
77 | 81 | ||
82 | ptr :: Addr -> Ptr a | ||
78 | ptr (Addr a) = Ptr a | 83 | ptr (Addr a) = Ptr a |
84 | |||
85 | adr :: Ptr a -> Addr | ||
79 | adr (Ptr a) = Addr a | 86 | adr (Ptr a) = Addr a |
80 | 87 | ||
81 | -- The xd3_config structure is used to initialize a stream - all data | 88 | -- The xd3_config structure is used to initialize a stream - all data |
@@ -134,12 +141,13 @@ config_stream cfg = do | |||
134 | XD3_SUCCESS -> return $ c `seq` Right stream | 141 | XD3_SUCCESS -> return $ c `seq` Right stream |
135 | ecode -> return $ Left ecode | 142 | ecode -> return $ Left ecode |
136 | 143 | ||
144 | writeStringAt :: PrimMonad m => MutableByteArray s -> Int -> B.ByteString -> m (Ptr a) | ||
137 | writeStringAt src o bsname = do | 145 | writeStringAt src o bsname = do |
138 | (p,cnt) <- unsafeIOToPrim $ B.unsafeUseAsCStringLen bsname return | 146 | (p,cnt) <- unsafeIOToPrim $ B.unsafeUseAsCStringLen bsname return |
139 | let nptr = ptr (mutableByteArrayContents src) `plusPtr` o | 147 | let nptr = ptr (mutableByteArrayContents src) `plusPtr` o |
140 | copyAddr (adr nptr) (adr p) cnt | 148 | copyAddr (adr nptr) (adr p) cnt |
141 | writeOffAddr (adr nptr) cnt (0 :: Word8) | 149 | writeOffAddr (adr nptr) cnt (0 :: Word8) |
142 | return nptr | 150 | return nptr |
143 | 151 | ||
144 | data Xd3Source | 152 | data Xd3Source |
145 | 153 | ||
@@ -222,8 +230,9 @@ foreign import ccall "xdelta3.h xd3_errstring" xd3_errstring :: Ptr Xd3Stream -> | |||
222 | 230 | ||
223 | -- | Gives some extra information about the latest library error, if any | 231 | -- | Gives some extra information about the latest library error, if any |
224 | -- is known. | 232 | -- is known. |
225 | errorString stream = unsafeIOToPrim $ withForeignPtr (streamPtr stream) $ \stream -> do | 233 | errorString :: PrimMonad m => Stream m -> m String |
226 | cstring <- xd3_errstring stream | 234 | errorString stream = unsafeIOToPrim $ do |
235 | cstring <- xd3_errstring (ptr $ mutableByteArrayContents $ streamArray stream) | ||
227 | peekCString cstring | 236 | peekCString cstring |
228 | 237 | ||
229 | pokeCurrentBlock :: PrimMonad m => Stream m -> CurrentBlock -> m () | 238 | pokeCurrentBlock :: PrimMonad m => Stream m -> CurrentBlock -> m () |
@@ -235,20 +244,27 @@ pokeCurrentBlock stream (CurrentBlock no sz ptr) = do | |||
235 | writeAtByte src #{offset xd3_source, curblk} ptr | 244 | writeAtByte src #{offset xd3_source, curblk} ptr |
236 | 245 | ||
237 | 246 | ||
247 | withByteString :: PrimBase m => B.ByteString -> (Ptr b -> Usize_t -> m a) -> m a | ||
248 | withByteString d act = | ||
249 | let (fp,off,len) = B.toForeignPtr d | ||
250 | in unsafeIOToPrim $ withForeignPtr fp $ \ptr -> unsafePrimToIO $ do | ||
251 | act (ptr `plusPtr` off) (fromIntegral len) | ||
252 | |||
238 | xdelta :: (PrimBase m, Monoid u) => XDeltaMethods m u -> (Stream m -> IO ErrorCode) -> [B.ByteString] | 253 | xdelta :: (PrimBase m, Monoid u) => XDeltaMethods m u -> (Stream m -> IO ErrorCode) -> [B.ByteString] |
239 | -> m (Either ErrorCode u) | 254 | -> m u |
240 | xdelta x xxcode_input ds = do | 255 | xdelta x xxcode_input ds = do |
241 | mstream <- config_stream (xConfig x) | 256 | mstream <- config_stream (xConfig x) |
242 | forM mstream $ \stream -> do | 257 | either (\e _ -> xOnError x e "config_stream failed") |
258 | (flip ($)) | ||
259 | mstream $ \stream -> do | ||
243 | set_source stream "xdelta" (xBlockSize x) (xBlockSize x) | 260 | set_source stream "xdelta" (xBlockSize x) (xBlockSize x) |
244 | let go withBlk (d:ds) = do | 261 | let go withBlk (d:ds) = do |
245 | let (fp,off,len) = B.toForeignPtr d | 262 | let (fp,off,len) = B.toForeignPtr d |
246 | eof = null ds | 263 | eof = null ds |
247 | when eof $ setFlush stream True | 264 | when eof $ setFlush stream True |
248 | unsafeIOToPrim $ withForeignPtr fp $ \indata0 -> do | 265 | withByteString d $ \indata len -> do |
249 | let indata = indata0 `plusPtr` off | 266 | avail_input stream indata len |
250 | avail_input stream indata (fromIntegral len) | 267 | go2 withBlk eof ds |
251 | unsafePrimToIO $ go2 withBlk eof ds | ||
252 | go2 withBlk eof ds = do | 268 | go2 withBlk eof ds = do |
253 | ret <- withBlk $ unsafeIOToPrim $ xxcode_input stream | 269 | ret <- withBlk $ unsafeIOToPrim $ xxcode_input stream |
254 | case ret of | 270 | case ret of |
@@ -260,10 +276,9 @@ xdelta x xxcode_input ds = do | |||
260 | XD3_GETSRCBLK -> do | 276 | XD3_GETSRCBLK -> do |
261 | Just n <- requestedBlockNumber stream | 277 | Just n <- requestedBlockNumber stream |
262 | let blk = xGetSource x n | 278 | let blk = xGetSource x n |
263 | withBlk' act = let (fp,off,len) = B.toForeignPtr blk | 279 | withBlk' act = withByteString blk $ \p len -> do |
264 | in unsafeIOToPrim $ withForeignPtr fp $ \p -> unsafePrimToIO $ do | 280 | pokeCurrentBlock stream $ CurrentBlock n len p |
265 | pokeCurrentBlock stream $ CurrentBlock n (fromIntegral len) (plusPtr p off) | 281 | act |
266 | act | ||
267 | go2 withBlk' eof ds | 282 | go2 withBlk' eof ds |
268 | XD3_GOTHEADER -> go2 withBlk eof ds -- No | 283 | XD3_GOTHEADER -> go2 withBlk eof ds -- No |
269 | XD3_WINSTART -> go2 withBlk eof ds -- action | 284 | XD3_WINSTART -> go2 withBlk eof ds -- action |