summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoe Crayne <joe@jerkface.net>2018-10-26 02:17:42 -0400
committerJoe Crayne <joe@jerkface.net>2018-10-26 02:17:42 -0400
commit9eb3ca619568b8c4b3c3d0ed2da0319f1bd9a4bd (patch)
treef0dfb22ec331608d60379b72370549b350f2cea5
parent05ae232e966eccae46d535126a579740b6cf780d (diff)
Reorganizing.
-rw-r--r--examples/testdiff.hs2
-rw-r--r--haskell/Data/BA.hs17
-rw-r--r--haskell/Data/Primitive/ByteArray/Util.hs45
-rw-r--r--haskell/Data/VCDIFF.hsc (renamed from haskell/Data/XDelta.hsc)108
-rw-r--r--haskell/Data/VCDIFF/Types.hsc (renamed from haskell/XDelta/Types.hsc)2
-rw-r--r--haskell/offset.h2
-rw-r--r--lazy.hs30
-rw-r--r--xdelta3.cabal23
8 files changed, 147 insertions, 82 deletions
diff --git a/examples/testdiff.hs b/examples/testdiff.hs
index 2847fc3..7e20dc5 100644
--- a/examples/testdiff.hs
+++ b/examples/testdiff.hs
@@ -1,7 +1,7 @@
1{-# LANGUAGE OverloadedStrings #-} 1{-# LANGUAGE OverloadedStrings #-}
2 2
3import qualified Data.ByteString.Lazy as L 3import qualified Data.ByteString.Lazy as L
4import Data.XDelta 4import Data.VCDIFF
5import Text.XXD 5import Text.XXD
6 6
7source :: L.ByteString 7source :: L.ByteString
diff --git a/haskell/Data/BA.hs b/haskell/Data/BA.hs
deleted file mode 100644
index 60b1136..0000000
--- a/haskell/Data/BA.hs
+++ /dev/null
@@ -1,17 +0,0 @@
1{-# LANGUAGE MagicHash #-}
2{-# LANGUAGE ScopedTypeVariables #-}
3module Data.BA where
4
5import GHC.Exts
6import Control.Monad.Primitive
7import Data.Primitive.Types
8import Data.Primitive.ByteArray
9
10-- | WARNING: Unsafe to use this on packed C structs.
11writeAtByte :: (Prim a, PrimMonad m) => MutableByteArray (PrimState m) -> Int -> a -> m ()
12writeAtByte buf offset a = writeByteArray buf (div offset $ I# (sizeOf# a)) a
13{-# INLINE writeAtByte #-}
14
15readAtByte :: forall a m. (Prim a, PrimMonad m) => MutableByteArray (PrimState m) -> Int -> m a
16readAtByte buf offset = readByteArray buf (div offset $ I# (sizeOf# (undefined :: a)))
17{-# INLINE readAtByte #-}
diff --git a/haskell/Data/Primitive/ByteArray/Util.hs b/haskell/Data/Primitive/ByteArray/Util.hs
new file mode 100644
index 0000000..1776286
--- /dev/null
+++ b/haskell/Data/Primitive/ByteArray/Util.hs
@@ -0,0 +1,45 @@
1{-# LANGUAGE DataKinds #-}
2{-# LANGUAGE FlexibleContexts #-}
3{-# LANGUAGE FlexibleInstances #-}
4{-# LANGUAGE KindSignatures #-}
5{-# LANGUAGE MagicHash #-}
6{-# LANGUAGE MultiParamTypeClasses #-}
7{-# LANGUAGE ScopedTypeVariables #-}
8{-# LANGUAGE TypeFamilies #-}
9{-# LANGUAGE TypeOperators #-}
10module Data.Primitive.ByteArray.Util where
11
12import GHC.TypeLits
13import Control.Monad.Primitive
14import Data.Primitive.Types
15import Data.Primitive.ByteArray
16
17newtype Offset (n :: Nat) = Offset Int
18
19offset :: KnownNat n => Offset n
20offset = let k = Offset $ fromIntegral $ natVal k in k
21
22(+.) :: Offset j -> Offset k -> Offset (j + k)
23Offset j +. Offset k = Offset (j + k)
24
25
26type family SizeOf a :: Nat
27
28class IsMultipleOf (n::Nat) (k::Nat)
29
30instance n ~ (q * k) => IsMultipleOf n k
31
32writeAtByte :: ( Prim a
33 , PrimMonad m
34 , IsMultipleOf n (SizeOf a)
35 ) => MutableByteArray (PrimState m) -> Offset n -> a -> m ()
36writeAtByte buf (Offset offset) a = writeByteArray buf (div offset $ (sizeOf a)) a
37{-# INLINE writeAtByte #-}
38
39readAtByte :: forall a m n.
40 ( Prim a
41 , PrimMonad m
42 , IsMultipleOf n (SizeOf a)
43 ) => MutableByteArray (PrimState m) -> Offset n -> m a
44readAtByte buf (Offset offset) = readByteArray buf (div offset $ (sizeOf (undefined :: a)))
45{-# INLINE readAtByte #-}
diff --git a/haskell/Data/XDelta.hsc b/haskell/Data/VCDIFF.hsc
index 8128a61..5e484e1 100644
--- a/haskell/Data/XDelta.hsc
+++ b/haskell/Data/VCDIFF.hsc
@@ -1,19 +1,24 @@
1{-# OPTIONS_GHC -Wno-partial-type-signatures #-}
1{-# LANGUAGE BangPatterns #-} 2{-# LANGUAGE BangPatterns #-}
3{-# LANGUAGE DataKinds #-}
4{-# LANGUAGE DeriveFunctor #-}
5{-# LANGUAGE FlexibleContexts #-}
6{-# LANGUAGE FlexibleInstances #-}
2{-# LANGUAGE GADTs #-} 7{-# LANGUAGE GADTs #-}
3{-# LANGUAGE GeneralizedNewtypeDeriving #-} 8{-# LANGUAGE GeneralizedNewtypeDeriving #-}
4{-# LANGUAGE LambdaCase #-} 9{-# LANGUAGE LambdaCase #-}
5{-# LANGUAGE NondecreasingIndentation #-} 10{-# LANGUAGE NondecreasingIndentation #-}
11{-# LANGUAGE PartialTypeSignatures #-}
6{-# LANGUAGE PatternSynonyms #-} 12{-# LANGUAGE PatternSynonyms #-}
7{-# LANGUAGE RankNTypes #-} 13{-# LANGUAGE RankNTypes #-}
8{-# LANGUAGE FlexibleInstances #-} 14{-# LANGUAGE TypeFamilies #-}
9{-# LANGUAGE DeriveFunctor #-} 15{-# LANGUAGE TypeOperators #-}
10module Data.XDelta where 16module Data.VCDIFF where
11 17
12import Control.Monad 18import Control.Monad
13import Control.Monad.Primitive 19import Control.Monad.Primitive
14import Control.Monad.ST 20import Control.Monad.ST
15import Control.Monad.ST.Unsafe 21import Control.Monad.ST.Unsafe
16import Data.BA
17import Data.Bits 22import Data.Bits
18import qualified Data.ByteString as B 23import qualified Data.ByteString as B
19import qualified Data.ByteString.Unsafe as B 24import qualified Data.ByteString.Unsafe as B
@@ -25,6 +30,7 @@ import qualified Data.IntMap as IntMap
25import Data.Monoid 30import Data.Monoid
26import Data.Primitive.Addr 31import Data.Primitive.Addr
27import Data.Primitive.ByteArray 32import Data.Primitive.ByteArray
33import Data.Primitive.ByteArray.Util
28import Data.Primitive.MutVar 34import Data.Primitive.MutVar
29import Data.STRef 35import Data.STRef
30import qualified Data.Text as T 36import qualified Data.Text as T
@@ -38,8 +44,9 @@ import Foreign.Concurrent
38import Foreign.Storable 44import Foreign.Storable
39import Foreign.ForeignPtr (ForeignPtr) 45import Foreign.ForeignPtr (ForeignPtr)
40import GHC.Exts 46import GHC.Exts
47import GHC.TypeLits
41 48
42import XDelta.Types 49import Data.VCDIFF.Types
43 50
44#ifndef SIZEOF_SIZE_T 51#ifndef SIZEOF_SIZE_T
45#define SIZEOF_SIZE_T __SIZEOF_SIZE_T__ 52#define SIZEOF_SIZE_T __SIZEOF_SIZE_T__
@@ -50,6 +57,8 @@ import XDelta.Types
50#endif 57#endif
51#include <xdelta3.h> 58#include <xdelta3.h>
52 59
60#include "offset.h"
61
53data Stream m = Stream 62data Stream m = Stream
54 { streamArray :: MutableByteArray (PrimState m) 63 { streamArray :: MutableByteArray (PrimState m)
55 , streamPtr :: ForeignPtr Xd3Stream -- ^ HACK: this is only used to attach a finalizer 64 , streamPtr :: ForeignPtr Xd3Stream -- ^ HACK: this is only used to attach a finalizer
@@ -67,26 +76,31 @@ foreign import ccall "xdelta3.h xd3_abort_stream" xd3_abort_stream :: Ptr Xd3Str
67 76
68foreign import ccall "xdelta3.h xd3_close_stream" xd3_close_stream :: Ptr Xd3Stream -> IO ErrorCode 77foreign import ccall "xdelta3.h xd3_close_stream" xd3_close_stream :: Ptr Xd3Stream -> IO ErrorCode
69 78
79type instance SizeOf Usize_t = #const sizeof(usize_t)
80type instance SizeOf (FunPtr a) = #const sizeof(void(*)())
81type instance SizeOf (Ptr a) = #const sizeof(void*)
82type instance SizeOf #{type int} = #const sizeof(int)
83type instance SizeOf #{type unsigned int} = #const sizeof(unsigned int)
84
85
70 86
71writeCompressorConfig :: PrimMonad m => 87writeCompressorConfig :: (PrimMonad m, _) => MutableByteArray (PrimState m) -> Offset j -> CompressorConfig -> m ()
72 MutableByteArray (PrimState m) -> Int -> CompressorConfig -> m ()
73writeCompressorConfig c o sec = do 88writeCompressorConfig c o sec = do
74 writeAtByte c (o + #{offset xd3_sec_cfg,ngroups}) (ngroups sec) 89 writeAtByte c (o +. #{off xd3_sec_cfg,ngroups}) (ngroups sec)
75 writeAtByte c (o + #{offset xd3_sec_cfg,sector_size}) (sector_size sec) 90 writeAtByte c (o +. #{off xd3_sec_cfg,sector_size}) (sector_size sec)
76 writeAtByte c (o + #{offset xd3_sec_cfg,inefficient}) (inefficient sec) 91 writeAtByte c (o +. #{off xd3_sec_cfg,inefficient}) (inefficient sec)
77 92
78writeMatcher :: PrimMonad m => 93writeMatcher :: (PrimMonad m, _) => MutableByteArray (PrimState m) -> Offset j -> StringMatcher -> m ()
79 MutableByteArray (PrimState m) -> Int -> StringMatcher -> m ()
80writeMatcher c o sm = do 94writeMatcher c o sm = do
81 -- handled elsewhere: const char *name; <- smName :: String 95 -- handled elsewhere: const char *name; <- smName :: String
82 writeAtByte c (o + #{offset xd3_smatcher, string_match }) (smStringMatch sm) 96 writeAtByte c (o +. #{off xd3_smatcher, string_match }) (smStringMatch sm)
83 writeAtByte c (o + #{offset xd3_smatcher, large_look }) (smLargeLook sm) 97 writeAtByte c (o +. #{off xd3_smatcher, large_look }) (smLargeLook sm)
84 writeAtByte c (o + #{offset xd3_smatcher, large_step }) (smLargeStep sm) 98 writeAtByte c (o +. #{off xd3_smatcher, large_step }) (smLargeStep sm)
85 writeAtByte c (o + #{offset xd3_smatcher, small_look }) (smSmallLook sm) 99 writeAtByte c (o +. #{off xd3_smatcher, small_look }) (smSmallLook sm)
86 writeAtByte c (o + #{offset xd3_smatcher, small_chain }) (smSmallChain sm) 100 writeAtByte c (o +. #{off xd3_smatcher, small_chain }) (smSmallChain sm)
87 writeAtByte c (o + #{offset xd3_smatcher, small_lchain }) (smSmallLchain sm) 101 writeAtByte c (o +. #{off xd3_smatcher, small_lchain }) (smSmallLchain sm)
88 writeAtByte c (o + #{offset xd3_smatcher, max_lazy }) (smMaxLazy sm) 102 writeAtByte c (o +. #{off xd3_smatcher, max_lazy }) (smMaxLazy sm)
89 writeAtByte c (o + #{offset xd3_smatcher, long_enough }) (smLongEnough sm) 103 writeAtByte c (o +. #{off xd3_smatcher, long_enough }) (smLongEnough sm)
90 104
91ptr :: Addr -> Ptr a 105ptr :: Addr -> Ptr a
92ptr (Addr a) = Ptr a 106ptr (Addr a) = Ptr a
@@ -113,23 +127,23 @@ config_stream cfg = do
113 c <- do 127 c <- do
114 c <- newPinnedByteArray #const sizeof(xd3_config) 128 c <- newPinnedByteArray #const sizeof(xd3_config)
115 fillByteArray c 0 #{const sizeof(xd3_config)} 0 129 fillByteArray c 0 #{const sizeof(xd3_config)} 0
116 writeAtByte c #{offset xd3_config, winsize} (winsize cfg) 130 writeAtByte c #{off xd3_config, winsize} (winsize cfg)
117 writeAtByte c #{offset xd3_config, sprevsz} (sprevsz cfg) 131 writeAtByte c #{off xd3_config, sprevsz} (sprevsz cfg)
118 writeAtByte c #{offset xd3_config, iopt_size} (iopt_size cfg) 132 writeAtByte c #{off xd3_config, iopt_size} (iopt_size cfg)
119 writeAtByte c #{offset xd3_config, flags} (coerce (flags cfg) :: Word32) 133 writeAtByte c #{off xd3_config, flags} (coerce (flags cfg) :: Word32)
120 writeCompressorConfig c #{offset xd3_config, sec_data} (sec_data cfg) 134 writeCompressorConfig c #{off xd3_config, sec_data} (sec_data cfg)
121 writeCompressorConfig c #{offset xd3_config, sec_inst} (sec_inst cfg) 135 writeCompressorConfig c #{off xd3_config, sec_inst} (sec_inst cfg)
122 writeCompressorConfig c #{offset xd3_config, sec_addr} (sec_addr cfg) 136 writeCompressorConfig c #{off xd3_config, sec_addr} (sec_addr cfg)
123 let msel :: #type xd3_smatch_cfg 137 let msel :: #type xd3_smatch_cfg
124 msel = either (const #{const XD3_SMATCH_SOFT}) 138 msel = either (const #{const XD3_SMATCH_SOFT})
125 (fromIntegral . fromEnum) 139 (fromIntegral . fromEnum)
126 (smatch_cfg cfg) 140 (smatch_cfg cfg)
127 writeAtByte c #{offset xd3_config, smatch_cfg} msel 141 writeAtByte c (#{off xd3_config, smatch_cfg}) msel
128 case smatch_cfg cfg of 142 case smatch_cfg cfg of
129 Right _ -> return () 143 Right _ -> return ()
130 Left matcher -> do 144 Left matcher -> do
131 let o = #offset xd3_config,smatcher_soft 145 let o = offset :: Offset #offset xd3_config,smatcher_soft
132 writeAtByte c (o + #{offset xd3_smatcher, name}) nptr 146 writeAtByte c (o +. (#{off xd3_smatcher, name})) nptr
133 writeMatcher c o matcher 147 writeMatcher c o matcher
134 unsafeFreezeByteArray c 148 unsafeFreezeByteArray c
135 let cptr = ptr (byteArrayContents c) :: Ptr Config 149 let cptr = ptr (byteArrayContents c) :: Ptr Config
@@ -173,10 +187,10 @@ set_source stream nm blksz maxwinsz = do
173 let bsname = encodeUtf8 $ T.pack nm 187 let bsname = encodeUtf8 $ T.pack nm
174 src <- newPinnedByteArray $ 1 + B.length bsname + #{const sizeof(xd3_source)} 188 src <- newPinnedByteArray $ 1 + B.length bsname + #{const sizeof(xd3_source)}
175 nptr <- writeStringAt src #{const sizeof(xd3_source)} bsname 189 nptr <- writeStringAt src #{const sizeof(xd3_source)} bsname
176 writeAtByte src #{offset xd3_source, blksize } blksz 190 writeAtByte src (#{off xd3_source, blksize }) blksz
177 writeAtByte src #{offset xd3_source, name } nptr 191 writeAtByte src (#{off xd3_source, name }) nptr
178 writeAtByte src #{offset xd3_source, max_winsize} maxwinsz 192 writeAtByte src (#{off xd3_source, max_winsize}) maxwinsz
179 writeAtByte src #{offset xd3_source, curblkno } (maxBound :: Xoff_t) 193 writeAtByte src (#{off xd3_source, curblkno }) (maxBound :: Xoff_t)
180 {- 194 {-
181 writeAtByte (streamArray stream) 195 writeAtByte (streamArray stream)
182 #{offset xd3_stream, getblk} 196 #{offset xd3_stream, getblk}
@@ -201,8 +215,8 @@ data XDeltaMethods m u = XDeltaMethods
201 215
202setFlag :: PrimMonad m => Flags -> Stream m -> Bool -> m () 216setFlag :: PrimMonad m => Flags -> Stream m -> Bool -> m ()
203setFlag b stream wantFlush = do 217setFlag b stream wantFlush = do
204 f <- readAtByte (streamArray stream) #{offset xd3_stream, flags} 218 f <- readAtByte (streamArray stream) (#{off xd3_stream, flags})
205 writeAtByte (streamArray stream) #{offset xd3_stream, flags} 219 writeAtByte (streamArray stream) (#{off xd3_stream, flags})
206 . (coerce :: Flags -> Word32) 220 . (coerce :: Flags -> Word32)
207 $ if wantFlush then Flags f .|. b 221 $ if wantFlush then Flags f .|. b
208 else Flags f .&. complement b 222 else Flags f .&. complement b
@@ -218,8 +232,8 @@ setSkipWindow = setFlag XD3_SKIP_WINDOW
218 232
219avail_input :: PrimMonad m => Stream m -> Ptr a -> Usize_t -> m () 233avail_input :: PrimMonad m => Stream m -> Ptr a -> Usize_t -> m ()
220avail_input stream p sz = do 234avail_input stream p sz = do
221 writeAtByte (streamArray stream) #{offset xd3_stream, next_in} p 235 writeAtByte (streamArray stream) (#{off xd3_stream, next_in}) p
222 writeAtByte (streamArray stream) #{offset xd3_stream, avail_in} sz 236 writeAtByte (streamArray stream) (#{off xd3_stream, avail_in}) sz
223 237
224-- | This acknowledges receipt of output data, must be called after any 238-- | This acknowledges receipt of output data, must be called after any
225-- XD3_OUTPUT return. 239-- XD3_OUTPUT return.
@@ -229,18 +243,18 @@ avail_input stream p sz = do
229nextOut :: PrimMonad m => Stream m -> ((Ptr Word8, Usize_t) -> m a) -> m a 243nextOut :: PrimMonad m => Stream m -> ((Ptr Word8, Usize_t) -> m a) -> m a
230nextOut stream action = do 244nextOut stream action = do
231 buf <- (,) 245 buf <- (,)
232 <$> readAtByte (streamArray stream) #{offset xd3_stream, next_out} 246 <$> readAtByte (streamArray stream) (#{off xd3_stream, next_out})
233 <*> readAtByte (streamArray stream) #{offset xd3_stream, avail_out} 247 <*> readAtByte (streamArray stream) (#{off xd3_stream, avail_out})
234 a <- action buf 248 a <- action buf
235 -- unsafeIOToPrim $ xd3_consume_output (ptr $ mutableByteArrayContents $ streamArray stream) 249 -- unsafeIOToPrim $ xd3_consume_output (ptr $ mutableByteArrayContents $ streamArray stream)
236 writeAtByte (streamArray stream) #{offset xd3_stream, avail_out} (0 :: Usize_t) 250 writeAtByte (streamArray stream) (#{off xd3_stream, avail_out}) (0 :: Usize_t)
237 return a 251 return a
238 252
239 253
240requestedBlockNumber :: PrimMonad m => Stream m -> m (Maybe Xoff_t) 254requestedBlockNumber :: PrimMonad m => Stream m -> m (Maybe Xoff_t)
241requestedBlockNumber stream = do 255requestedBlockNumber stream = do
242 msrc <- readMutVar $ streamSource stream 256 msrc <- readMutVar $ streamSource stream
243 forM msrc $ \src -> readAtByte src #offset xd3_source, getblkno 257 forM msrc $ \src -> readAtByte src (#{off xd3_source, getblkno})
244 258
245data CurrentBlock = CurrentBlock 259data CurrentBlock = CurrentBlock
246 { blkno :: !Xoff_t -- ^ current block number 260 { blkno :: !Xoff_t -- ^ current block number
@@ -255,7 +269,7 @@ data CurrentBlock = CurrentBlock
255-- is known. 269-- is known.
256errorString :: PrimMonad m => Stream m -> m String 270errorString :: PrimMonad m => Stream m -> m String
257errorString stream = do 271errorString stream = do
258 cstring <- readAtByte (streamArray stream) #offset xd3_stream, msg 272 cstring <- readAtByte (streamArray stream) (#{off xd3_stream, msg})
259 if cstring /= nullPtr 273 if cstring /= nullPtr
260 then unsafeIOToPrim $ peekCString cstring -- TODO: avoid unsafeIOToPrim 274 then unsafeIOToPrim $ peekCString cstring -- TODO: avoid unsafeIOToPrim
261 else return "" 275 else return ""
@@ -264,9 +278,9 @@ pokeCurrentBlock :: PrimMonad m => Stream m -> CurrentBlock -> m ()
264pokeCurrentBlock stream (CurrentBlock no sz ptr) = do 278pokeCurrentBlock stream (CurrentBlock no sz ptr) = do
265 msrc <- readMutVar $ streamSource stream 279 msrc <- readMutVar $ streamSource stream
266 forM_ msrc $ \src -> do 280 forM_ msrc $ \src -> do
267 writeAtByte src #{offset xd3_source, curblkno} no 281 writeAtByte src (#{off xd3_source, curblkno}) no
268 writeAtByte src #{offset xd3_source, onblk} sz 282 writeAtByte src (#{off xd3_source, onblk}) sz
269 writeAtByte src #{offset xd3_source, curblk} ptr 283 writeAtByte src (#{off xd3_source, curblk}) ptr
270 284
271 285
272withByteString :: PrimBase m => B.ByteString -> (Ptr b -> Usize_t -> m a) -> m a 286withByteString :: PrimBase m => B.ByteString -> (Ptr b -> Usize_t -> m a) -> m a
@@ -305,7 +319,7 @@ xdelta x xxcode_input ds = do
305 pokeCurrentBlock stream $ CurrentBlock n len p 319 pokeCurrentBlock stream $ CurrentBlock n len p
306 when (len < xBlockSize x) $ do 320 when (len < xBlockSize x) $ do
307 Just src <- readMutVar $ streamSource stream 321 Just src <- readMutVar $ streamSource stream
308 writeAtByte src #{offset xd3_source, eof_known} (1 :: #{type int}) 322 writeAtByte src (#{off xd3_source, eof_known}) (1 :: #{type int})
309 act 323 act
310 go2 withBlk' eof ds 324 go2 withBlk' eof ds
311 XD3_GOTHEADER -> go2 withBlk eof ds -- No 325 XD3_GOTHEADER -> go2 withBlk eof ds -- No
diff --git a/haskell/XDelta/Types.hsc b/haskell/Data/VCDIFF/Types.hsc
index 8a60805..015f406 100644
--- a/haskell/XDelta/Types.hsc
+++ b/haskell/Data/VCDIFF/Types.hsc
@@ -3,7 +3,7 @@
3{-# LANGUAGE GeneralizedNewtypeDeriving #-} 3{-# LANGUAGE GeneralizedNewtypeDeriving #-}
4{-# LANGUAGE LambdaCase #-} 4{-# LANGUAGE LambdaCase #-}
5{-# LANGUAGE PatternSynonyms #-} 5{-# LANGUAGE PatternSynonyms #-}
6module XDelta.Types where 6module Data.VCDIFF.Types where
7 7
8import Control.Exception 8import Control.Exception
9import Control.Monad 9import Control.Monad
diff --git a/haskell/offset.h b/haskell/offset.h
new file mode 100644
index 0000000..0f344a2
--- /dev/null
+++ b/haskell/offset.h
@@ -0,0 +1,2 @@
1
2#define hsc_off(t, f) hsc_printf("(Offset (%ld) :: Offset (%ld))", (long) offsetof (t, f), (long) offsetof (t, f));
diff --git a/lazy.hs b/lazy.hs
new file mode 100644
index 0000000..5bbfa51
--- /dev/null
+++ b/lazy.hs
@@ -0,0 +1,30 @@
1{-# LANGUAGE NoMonomorphismRestriction #-}
2import Control.Monad.ST
3import Control.Monad.ST.Unsafe
4import Data.VCDIFF
5import qualified Data.ByteString as B
6
7step2 = undefined
8
9step1 = do
10 xs <- unsafeInterleaveST $ step2
11 return $ 3 : xs
12
13test f = do
14 xs <- f $ step2
15 return $ 3 : xs
16
17test2 f = withByteString B.empty $ \_ _ -> do
18 xs <- f $ step2
19 return $ 3 : xs
20
21main = do
22 let xs = runST step1
23 ys = runST (test id)
24 zs = runST (test unsafeInterleaveST)
25 vs = runST (test2 unsafeInterleaveST)
26 print $ take 1 xs
27 -- print $ take 1 ys
28 print $ take 1 zs
29 print $ take 1 vs
30
diff --git a/xdelta3.cabal b/xdelta3.cabal
index bc8a81b..6907ebc 100644
--- a/xdelta3.cabal
+++ b/xdelta3.cabal
@@ -1,36 +1,27 @@
1cabal-version: 2.2 1cabal-version: 2.2
2name: xdelta 2name: xdelta
3version: 3.2.0 3version: 3.1.0
4synopsis: VCDIFF encoder/decoder. 4synopsis: VCDIFF encoder/decoder.
5-- description: 5-- description:
6homepage: xdelta.org 6homepage: xdelta.org
7license: Apache-2.0 7license: Apache-2.0
8license-file: xdelta3/LICENSE 8license-file: xdelta3/LICENSE
9author: Josh MacDonald 9author: Joe Crayne
10maintainer: josh.macdonald@gmail.com 10maintainer: joe@jerkface.net
11-- copyright:
12category: Data 11category: Data
13-- build-type: Custom
14build-type: Simple 12build-type: Simple
15 13
16extra-source-files: xdelta3/*.h xdelta3/*.c 14extra-source-files: xdelta3/*.h xdelta3/*.c
17 15
18library 16library
19 exposed-modules: XDelta.Types 17 exposed-modules: Data.VCDIFF.Types
20 , Data.XDelta 18 , Data.VCDIFF
21 , Data.BA 19 , Data.Primitive.ByteArray.Util
22 20
23 build-tools: hsc2hs 21 build-tools: hsc2hs
24 -- include-dirs: xdelta3 xdelta3_lib
25 -- extra-lib-dirs: xdelta3_lib
26 include-dirs: haskell . 22 include-dirs: haskell .
27 -- cc-options: -std=c++14 -Wno-literal-suffix
28 cxx-options: -Wno-literal-suffix -g
29 cpp-options: -DNOT_MAIN=1 -DREGRESSION_TEST=1 -DSECONDARY_DJW=1 -DSECONDARY_FGK=1 -DXD3_MAIN=1 -DXD3_DEBUG=0 -DHAVE_CONFIG 23 cpp-options: -DNOT_MAIN=1 -DREGRESSION_TEST=1 -DSECONDARY_DJW=1 -DSECONDARY_FGK=1 -DXD3_MAIN=1 -DXD3_DEBUG=0 -DHAVE_CONFIG
30 -- cpp-options: -DHAVE_CONFIG_H -DSIZEOF_SIZE_T=__SIZEOF_SIZE_T__ -DSIZEOF_UNSIGNED_INT=__SIZEOF_INT__ -DSIZEOF_UNSIGNED_LONG=__SIZEOF_LONG__ 24 cxx-options: -Wno-literal-suffix -g
31 -- cpp-options: -DSIZEOF_UNSIGNED_LONG_LONG=__SIZEOF_LONG_LONG__
32 -- -DHAVE_CONFIG_H=1
33 -- -include xdelta3/build2/config.h -Wall -Wshadow -fno-builtin -Wextra -Wsign-compare -Wformat=2 -Wno-format-nonliteral -Wno-unused-parameter -Wno-unused-function extra-libraries: xdelta3, lzma, stdc++, m
34 cxx-sources: haskell/xdelta3.cc 25 cxx-sources: haskell/xdelta3.cc
35 26
36 hs-source-dirs: haskell 27 hs-source-dirs: haskell