diff options
Diffstat (limited to 'haskell/Data')
-rw-r--r-- | haskell/Data/BA.hs | 17 | ||||
-rw-r--r-- | haskell/Data/Primitive/ByteArray/Util.hs | 45 | ||||
-rw-r--r-- | haskell/Data/VCDIFF.hsc (renamed from haskell/Data/XDelta.hsc) | 108 | ||||
-rw-r--r-- | haskell/Data/VCDIFF/Types.hsc | 208 |
4 files changed, 314 insertions, 64 deletions
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 #-} | ||
3 | module Data.BA where | ||
4 | |||
5 | import GHC.Exts | ||
6 | import Control.Monad.Primitive | ||
7 | import Data.Primitive.Types | ||
8 | import Data.Primitive.ByteArray | ||
9 | |||
10 | -- | WARNING: Unsafe to use this on packed C structs. | ||
11 | writeAtByte :: (Prim a, PrimMonad m) => MutableByteArray (PrimState m) -> Int -> a -> m () | ||
12 | writeAtByte buf offset a = writeByteArray buf (div offset $ I# (sizeOf# a)) a | ||
13 | {-# INLINE writeAtByte #-} | ||
14 | |||
15 | readAtByte :: forall a m. (Prim a, PrimMonad m) => MutableByteArray (PrimState m) -> Int -> m a | ||
16 | readAtByte 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 #-} | ||
10 | module Data.Primitive.ByteArray.Util where | ||
11 | |||
12 | import GHC.TypeLits | ||
13 | import Control.Monad.Primitive | ||
14 | import Data.Primitive.Types | ||
15 | import Data.Primitive.ByteArray | ||
16 | |||
17 | newtype Offset (n :: Nat) = Offset Int | ||
18 | |||
19 | offset :: KnownNat n => Offset n | ||
20 | offset = let k = Offset $ fromIntegral $ natVal k in k | ||
21 | |||
22 | (+.) :: Offset j -> Offset k -> Offset (j + k) | ||
23 | Offset j +. Offset k = Offset (j + k) | ||
24 | |||
25 | |||
26 | type family SizeOf a :: Nat | ||
27 | |||
28 | class IsMultipleOf (n::Nat) (k::Nat) | ||
29 | |||
30 | instance n ~ (q * k) => IsMultipleOf n k | ||
31 | |||
32 | writeAtByte :: ( Prim a | ||
33 | , PrimMonad m | ||
34 | , IsMultipleOf n (SizeOf a) | ||
35 | ) => MutableByteArray (PrimState m) -> Offset n -> a -> m () | ||
36 | writeAtByte buf (Offset offset) a = writeByteArray buf (div offset $ (sizeOf a)) a | ||
37 | {-# INLINE writeAtByte #-} | ||
38 | |||
39 | readAtByte :: forall a m n. | ||
40 | ( Prim a | ||
41 | , PrimMonad m | ||
42 | , IsMultipleOf n (SizeOf a) | ||
43 | ) => MutableByteArray (PrimState m) -> Offset n -> m a | ||
44 | readAtByte 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 #-} |
10 | module Data.XDelta where | 16 | module Data.VCDIFF where |
11 | 17 | ||
12 | import Control.Monad | 18 | import Control.Monad |
13 | import Control.Monad.Primitive | 19 | import Control.Monad.Primitive |
14 | import Control.Monad.ST | 20 | import Control.Monad.ST |
15 | import Control.Monad.ST.Unsafe | 21 | import Control.Monad.ST.Unsafe |
16 | import Data.BA | ||
17 | import Data.Bits | 22 | import Data.Bits |
18 | import qualified Data.ByteString as B | 23 | import qualified Data.ByteString as B |
19 | import qualified Data.ByteString.Unsafe as B | 24 | import qualified Data.ByteString.Unsafe as B |
@@ -25,6 +30,7 @@ import qualified Data.IntMap as IntMap | |||
25 | import Data.Monoid | 30 | import Data.Monoid |
26 | import Data.Primitive.Addr | 31 | import Data.Primitive.Addr |
27 | import Data.Primitive.ByteArray | 32 | import Data.Primitive.ByteArray |
33 | import Data.Primitive.ByteArray.Util | ||
28 | import Data.Primitive.MutVar | 34 | import Data.Primitive.MutVar |
29 | import Data.STRef | 35 | import Data.STRef |
30 | import qualified Data.Text as T | 36 | import qualified Data.Text as T |
@@ -38,8 +44,9 @@ import Foreign.Concurrent | |||
38 | import Foreign.Storable | 44 | import Foreign.Storable |
39 | import Foreign.ForeignPtr (ForeignPtr) | 45 | import Foreign.ForeignPtr (ForeignPtr) |
40 | import GHC.Exts | 46 | import GHC.Exts |
47 | import GHC.TypeLits | ||
41 | 48 | ||
42 | import XDelta.Types | 49 | import 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 | |||
53 | data Stream m = Stream | 62 | data 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 | ||
68 | foreign import ccall "xdelta3.h xd3_close_stream" xd3_close_stream :: Ptr Xd3Stream -> IO ErrorCode | 77 | foreign import ccall "xdelta3.h xd3_close_stream" xd3_close_stream :: Ptr Xd3Stream -> IO ErrorCode |
69 | 78 | ||
79 | type instance SizeOf Usize_t = #const sizeof(usize_t) | ||
80 | type instance SizeOf (FunPtr a) = #const sizeof(void(*)()) | ||
81 | type instance SizeOf (Ptr a) = #const sizeof(void*) | ||
82 | type instance SizeOf #{type int} = #const sizeof(int) | ||
83 | type instance SizeOf #{type unsigned int} = #const sizeof(unsigned int) | ||
84 | |||
85 | |||
70 | 86 | ||
71 | writeCompressorConfig :: PrimMonad m => | 87 | writeCompressorConfig :: (PrimMonad m, _) => MutableByteArray (PrimState m) -> Offset j -> CompressorConfig -> m () |
72 | MutableByteArray (PrimState m) -> Int -> CompressorConfig -> m () | ||
73 | writeCompressorConfig c o sec = do | 88 | writeCompressorConfig 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 | ||
78 | writeMatcher :: PrimMonad m => | 93 | writeMatcher :: (PrimMonad m, _) => MutableByteArray (PrimState m) -> Offset j -> StringMatcher -> m () |
79 | MutableByteArray (PrimState m) -> Int -> StringMatcher -> m () | ||
80 | writeMatcher c o sm = do | 94 | writeMatcher 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 | ||
91 | ptr :: Addr -> Ptr a | 105 | ptr :: Addr -> Ptr a |
92 | ptr (Addr a) = Ptr a | 106 | ptr (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 | ||
202 | setFlag :: PrimMonad m => Flags -> Stream m -> Bool -> m () | 216 | setFlag :: PrimMonad m => Flags -> Stream m -> Bool -> m () |
203 | setFlag b stream wantFlush = do | 217 | setFlag 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 | ||
219 | avail_input :: PrimMonad m => Stream m -> Ptr a -> Usize_t -> m () | 233 | avail_input :: PrimMonad m => Stream m -> Ptr a -> Usize_t -> m () |
220 | avail_input stream p sz = do | 234 | avail_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 | |||
229 | nextOut :: PrimMonad m => Stream m -> ((Ptr Word8, Usize_t) -> m a) -> m a | 243 | nextOut :: PrimMonad m => Stream m -> ((Ptr Word8, Usize_t) -> m a) -> m a |
230 | nextOut stream action = do | 244 | nextOut 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 | ||
240 | requestedBlockNumber :: PrimMonad m => Stream m -> m (Maybe Xoff_t) | 254 | requestedBlockNumber :: PrimMonad m => Stream m -> m (Maybe Xoff_t) |
241 | requestedBlockNumber stream = do | 255 | requestedBlockNumber 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 | ||
245 | data CurrentBlock = CurrentBlock | 259 | data 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. |
256 | errorString :: PrimMonad m => Stream m -> m String | 270 | errorString :: PrimMonad m => Stream m -> m String |
257 | errorString stream = do | 271 | errorString 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 () | |||
264 | pokeCurrentBlock stream (CurrentBlock no sz ptr) = do | 278 | pokeCurrentBlock 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 | ||
272 | withByteString :: PrimBase m => B.ByteString -> (Ptr b -> Usize_t -> m a) -> m a | 286 | withByteString :: 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/Data/VCDIFF/Types.hsc b/haskell/Data/VCDIFF/Types.hsc new file mode 100644 index 0000000..015f406 --- /dev/null +++ b/haskell/Data/VCDIFF/Types.hsc | |||
@@ -0,0 +1,208 @@ | |||
1 | {-# LANGUAGE BangPatterns #-} | ||
2 | {-# LANGUAGE GADTs #-} | ||
3 | {-# LANGUAGE GeneralizedNewtypeDeriving #-} | ||
4 | {-# LANGUAGE LambdaCase #-} | ||
5 | {-# LANGUAGE PatternSynonyms #-} | ||
6 | module Data.VCDIFF.Types where | ||
7 | |||
8 | import Control.Exception | ||
9 | import Control.Monad | ||
10 | import Data.Bits | ||
11 | import qualified Data.ByteString as B | ||
12 | import qualified Data.ByteString.Internal as B | ||
13 | import Data.Function | ||
14 | import Data.Int | ||
15 | import Data.Monoid | ||
16 | import Data.Primitive.ByteArray | ||
17 | import qualified Data.Text as T | ||
18 | import Data.Text.Encoding | ||
19 | import Data.Word | ||
20 | import Foreign.C.String | ||
21 | import Foreign.C.Types | ||
22 | import Foreign.ForeignPtr | ||
23 | import Foreign.Marshal.Alloc | ||
24 | import Foreign.Marshal.Utils | ||
25 | import Foreign.Ptr | ||
26 | import Foreign.Storable | ||
27 | import System.IO | ||
28 | import System.IO.Error | ||
29 | import System.IO.Unsafe | ||
30 | |||
31 | |||
32 | |||
33 | #ifndef SIZEOF_SIZE_T | ||
34 | #define SIZEOF_SIZE_T __SIZEOF_SIZE_T__ | ||
35 | #define SIZEOF_UNSIGNED_INT __SIZEOF_INT__ | ||
36 | #define SIZEOF_UNSIGNED_LONG __SIZEOF_LONG__ | ||
37 | #define SIZEOF_UNSIGNED_LONG_LONG __SIZEOF_LONG_LONG__ | ||
38 | #define static_assert(...) | ||
39 | #endif | ||
40 | #include <xdelta3.h> | ||
41 | |||
42 | type Usize_t = #type usize_t | ||
43 | -- | Printf code for type Usize_t | ||
44 | pattern W :: String | ||
45 | pattern W = #const_str W "" | ||
46 | |||
47 | type Xoff_t = #type xoff_t | ||
48 | -- | Printf code for type Xoff_t | ||
49 | pattern Q :: String | ||
50 | pattern Q = #const_str Q "" | ||
51 | |||
52 | |||
53 | -- | These are the five ordinary status codes returned by the | ||
54 | -- xd3_encode_input() and xd3_decode_input() state machines. | ||
55 | -- | ||
56 | -- An application must be prepared to handle these five return | ||
57 | -- values from either xd3_encode_input or xd3_decode_input except | ||
58 | -- in the case of no-source compression in which case XD3_GETSRCBLK | ||
59 | -- is never returned. More detailed comments for these are given in | ||
60 | -- xd3_encode_input and xd3_decode_input comments below. | ||
61 | newtype ErrorCode = ErrorCode CInt | ||
62 | deriving Show | ||
63 | |||
64 | pattern XD3_SUCCESS = ErrorCode 0 | ||
65 | |||
66 | -- | need input | ||
67 | pattern XD3_INPUT = ErrorCode (#const XD3_INPUT) | ||
68 | |||
69 | -- | have output | ||
70 | pattern XD3_OUTPUT = ErrorCode (#const XD3_OUTPUT) | ||
71 | |||
72 | -- | need a block of source input (with no xd3_getblk function) a chance to do non-blocking read. | ||
73 | pattern XD3_GETSRCBLK = ErrorCode (#const XD3_GETSRCBLK) | ||
74 | |||
75 | -- | (decode-only) after the initial VCDIFF & first window header | ||
76 | pattern XD3_GOTHEADER = ErrorCode (#const XD3_GOTHEADER) | ||
77 | |||
78 | -- | notification: returned before a window is processed giving a chance to XD3_SKIP_WINDOW or not XD3_SKIP_EMIT that window. | ||
79 | pattern XD3_WINSTART = ErrorCode (#const XD3_WINSTART) | ||
80 | |||
81 | -- | notification: returned after encode/decode & output for a window | ||
82 | pattern XD3_WINFINISH = ErrorCode (#const XD3_WINFINISH) | ||
83 | |||
84 | -- | (encoder only) may be returned by getblk() if the block is too old | ||
85 | pattern XD3_TOOFARBACK = ErrorCode (#const XD3_TOOFARBACK) | ||
86 | |||
87 | -- | internal error | ||
88 | pattern XD3_INTERNAL = ErrorCode (#const XD3_INTERNAL) | ||
89 | |||
90 | -- | invalid config | ||
91 | pattern XD3_INVALID = ErrorCode (#const XD3_INVALID) | ||
92 | |||
93 | -- | invalid input/decoder error | ||
94 | pattern XD3_INVALID_INPUT = ErrorCode (#const XD3_INVALID_INPUT) | ||
95 | |||
96 | -- | when secondary compression finds no improvement. | ||
97 | pattern XD3_NOSECOND = ErrorCode (#const XD3_NOSECOND) | ||
98 | |||
99 | -- | currently VCD_TARGET VCD_CODETABLE | ||
100 | pattern XD3_UNIMPLEMENTED = ErrorCode (#const XD3_UNIMPLEMENTED) | ||
101 | |||
102 | instance Exception ErrorCode | ||
103 | |||
104 | data Config = Config | ||
105 | { winsize :: Usize_t -- ^ The encoder window size. | ||
106 | -- The encoder allocates a buffer of this size if the | ||
107 | -- program supplies input in smaller units (unless the | ||
108 | -- XD3_FLUSH flag is set). | ||
109 | , sprevsz :: Usize_t -- ^ How far back small string matching goes | ||
110 | , iopt_size :: Usize_t -- ^ entries in the instruction-optimizing buffer | ||
111 | , flags :: Flags -- ^ stream->flags are initialized from xd3_config & never modified by the library. Use xd3_set_flags to modify flags settings mid-stream. | ||
112 | , sec_data :: CompressorConfig -- ^ Secondary compressor config: data | ||
113 | , sec_inst :: CompressorConfig -- ^ Secondary compressor config: inst | ||
114 | , sec_addr :: CompressorConfig -- ^ Secondary compressor config: addr | ||
115 | , smatch_cfg :: Either StringMatcher SMatchSelect -- ^ See enum: use fields below for soft config | ||
116 | , chunk_size :: Usize_t -- ^ Suggested chunking size for streaming. | ||
117 | } | ||
118 | |||
119 | pattern XD3_DEFAULT_WINSIZE = #const XD3_DEFAULT_WINSIZE | ||
120 | pattern XD3_DEFAULT_SPREVSZ = #const XD3_DEFAULT_SPREVSZ | ||
121 | pattern XD3_DEFAULT_IOPT_SIZE = #const XD3_DEFAULT_IOPT_SIZE | ||
122 | |||
123 | newtype Flags = Flags Word32 | ||
124 | deriving (Storable,Eq,Bits,FiniteBits) | ||
125 | |||
126 | -- used by VCDIFF tools, see xdelta3-main.h.--/ | ||
127 | pattern XD3_JUST_HDR = Flags (#const XD3_JUST_HDR) | ||
128 | -- used by VCDIFF tools see xdelta3-main.h.--/ | ||
129 | pattern XD3_SKIP_WINDOW = Flags (#const XD3_SKIP_WINDOW) | ||
130 | -- | used by VCDIFF tools, see xdelta3-main.h. */ | ||
131 | pattern XD3_SKIP_EMIT = Flags (#const XD3_SKIP_EMIT) | ||
132 | -- | flush the stream buffer to prepare for xd3_stream_close(). */ | ||
133 | pattern XD3_FLUSH = Flags (#const XD3_FLUSH) | ||
134 | -- | use DJW static huffman */ | ||
135 | pattern XD3_SEC_DJW = Flags (#const XD3_SEC_DJW) | ||
136 | -- | use FGK adaptive huffman */ | ||
137 | pattern XD3_SEC_FGK = Flags (#const XD3_SEC_FGK) | ||
138 | -- | use LZMA secondary */ | ||
139 | pattern XD3_SEC_LZMA = Flags (#const XD3_SEC_LZMA) | ||
140 | pattern XD3_SEC_TYPE = Flags (#const XD3_SEC_TYPE) | ||
141 | -- | disable secondary compression of the data section. */ | ||
142 | pattern XD3_SEC_NODATA = Flags (#const XD3_SEC_NODATA) | ||
143 | -- | disable secondary compression of the inst section. */ | ||
144 | pattern XD3_SEC_NOINST = Flags (#const XD3_SEC_NOINST) | ||
145 | -- | disable secondary compression of the addr section. */ | ||
146 | pattern XD3_SEC_NOADDR = Flags (#const XD3_SEC_NOADDR) | ||
147 | pattern XD3_SEC_NOALL = Flags (#const XD3_SEC_NOALL) | ||
148 | -- | enable checksum computation in the encoder. */ | ||
149 | pattern XD3_ADLER32 = Flags (#const XD3_ADLER32) | ||
150 | -- | disable checksum verification in the decoder. */ | ||
151 | pattern XD3_ADLER32_NOVER = Flags (#const XD3_ADLER32_NOVER) | ||
152 | -- | disable ordinary data * compression feature, only search * the source, not the target. */ | ||
153 | pattern XD3_NOCOMPRESS = Flags (#const XD3_NOCOMPRESS) | ||
154 | -- | disable the "1.5-pass * algorithm", instead use greedy * matching. Greedy is off by * default. */ | ||
155 | pattern XD3_BEGREEDY = Flags (#const XD3_BEGREEDY) | ||
156 | -- | used by "recode". */ | ||
157 | pattern XD3_ADLER32_RECODE = Flags (#const XD3_ADLER32_RECODE) | ||
158 | -- 4 bits to set the compression level the same as the command-line | ||
159 | -- setting -1 through -9 Flags (-0 corresponds to the XD3_NOCOMPRESS flag | ||
160 | -- and is independent of compression level). This is for | ||
161 | -- convenience especially with xd3_encode_memoryFlags (). */ | ||
162 | pattern XD3_COMPLEVEL_SHIFT = #const XD3_COMPLEVEL_SHIFT | ||
163 | pattern XD3_COMPLEVEL_MASK = Flags (#const XD3_COMPLEVEL_MASK) | ||
164 | pattern XD3_COMPLEVEL_1 = Flags (#const XD3_COMPLEVEL_1) | ||
165 | pattern XD3_COMPLEVEL_2 = Flags (#const XD3_COMPLEVEL_2) | ||
166 | pattern XD3_COMPLEVEL_3 = Flags (#const XD3_COMPLEVEL_3) | ||
167 | pattern XD3_COMPLEVEL_6 = Flags (#const XD3_COMPLEVEL_6) | ||
168 | pattern XD3_COMPLEVEL_9 = Flags (#const XD3_COMPLEVEL_9) | ||
169 | |||
170 | instance Monoid Flags where | ||
171 | mempty = Flags 0 | ||
172 | Flags a `mappend` Flags b = Flags (a .|. b) | ||
173 | |||
174 | -- | Settings for the secondary compressor. | ||
175 | data CompressorConfig = CompressorConfig | ||
176 | { ngroups :: Usize_t -- ^ Number of DJW Huffman groups. | ||
177 | , sector_size :: Usize_t -- ^ Sector size. | ||
178 | , inefficient :: #{type int} -- ^ If true, ignore efficiency check [avoid XD3_NOSECOND]. | ||
179 | } | ||
180 | |||
181 | -- | The values of this enumeration are set in xd3_config using the | ||
182 | -- 'smatch_cfg' variable. It can be set to default, slow, fast, etc., | ||
183 | -- and soft. | ||
184 | data SMatchSelect | ||
185 | = SMATCH_DEFAULT -- ^ Flags may contain XD3_COMPLEVEL bits, else default. | ||
186 | | SMATCH_SLOW | ||
187 | | SMATCH_FAST | ||
188 | | SMATCH_FASTER | ||
189 | | SMATCH_FASTEST | ||
190 | deriving Enum | ||
191 | |||
192 | -- | This type exists only to be a tag for Ptr to an underlying C-struct called | ||
193 | -- xd3_stream. | ||
194 | data Xd3Stream | ||
195 | |||
196 | -- | This is the record of a pre-compiled configuration, a subset of | ||
197 | -- xd3_config. (struct _xd3_smatcher) | ||
198 | data StringMatcher = StringMatcher | ||
199 | { smName :: String | ||
200 | , smStringMatch :: FunPtr (Ptr Xd3Stream -> ErrorCode) | ||
201 | , smLargeLook :: Usize_t | ||
202 | , smLargeStep :: Usize_t | ||
203 | , smSmallLook :: Usize_t | ||
204 | , smSmallChain :: Usize_t | ||
205 | , smSmallLchain :: Usize_t | ||
206 | , smMaxLazy :: Usize_t | ||
207 | , smLongEnough :: Usize_t | ||
208 | } | ||