diff --git a/ArcvProcessExtract.hs b/ArcvProcessExtract.hs index cd3825c..c0f7bd8 100644 --- a/ArcvProcessExtract.hs +++ b/ArcvProcessExtract.hs @@ -174,6 +174,12 @@ de_compress_PROCESS1 de_compress reader times command comprMethod num pipe = do -- Прочие (неподдерживаемые) callbacks callback _ _ _ = return aFREEARC_ERRCODE_NOT_IMPLEMENTED + -- Поскольку Haskell'овский код, вызываемый из Си, не может получать исключений, добавим к процедурам чтения/записи явные проверки + let checked_callback what buf size = do + operationTerminated' <- val operationTerminated + if operationTerminated' + then return CompressionLib.aFREEARC_ERRCODE_OPERATION_TERMINATED -- foreverM doNothing0 + else callback what buf size {- -- Debugging wrapper debug f what buf size = inside (print (comprMethod,what,size)) @@ -184,8 +190,10 @@ de_compress_PROCESS1 de_compress reader times command comprMethod num pipe = do debug f what buf size = f what buf size -- СОБСТВЕННО УПАКОВКА ИЛИ РАСПАКОВКА - result <- de_compress num comprMethod (debug callback) - debug callback "finished" nullPtr result + res <- debug checked_callback "read" nullPtr 0 -- этот вызов позволяет отложить запуск следующего в цепочке алгоритма упаковки/распаковки до момента, когда предыдущий возвратит хоть какие-нибудь данные (а если это поблочный алгоритм - до момента, когда он обработает весь блок) + result <- if res<0 then return res + else de_compress num comprMethod (debug checked_callback) + debug checked_callback "finished" nullPtr result -- Статистика total <- val total' time <- val time' diff --git a/Compression.hs b/Compression.hs index b5ac5f6..61ca603 100644 --- a/Compression.hs +++ b/Compression.hs @@ -257,25 +257,12 @@ decompress method callback - -- |Процедуры упаковки для различных алгоритмов сжатия. freearcCompress num method | aSTORING == method = copy_data freearcCompress num method | isFakeMethod method = eat_data -freearcCompress num method = checkingCtrlBreak num (CompressionLib.compress method) +freearcCompress num method = CompressionLib.compress method -- |Процедуры распаковки для различных алгоритмов сжатия. freearcDecompress num method | aSTORING == method = copy_data freearcDecompress num method | isFakeMethod method = impossible_to_decompress -- эти типы сжатых данных не подлежат распаковке -freearcDecompress num method = checkingCtrlBreak num (CompressionLib.decompress method) - --- |Поскольку Haskell'овский код, вызываемый из Си, не может получать --- исключений, добавим к процедурам чтения/записи явные проверки -checkingCtrlBreak num action callback = do - let checked_callback what buf size auxdata = do - operationTerminated' <- val operationTerminated - if operationTerminated' - then return CompressionLib.aFREEARC_ERRCODE_OPERATION_TERMINATED -- foreverM doNothing0 - else callback what buf size - -- - res <- checked_callback "read" nullPtr 0 undefined -- этот вызов позволяет отложить запуск следующего в цепочке алгоритма упаковки/распаковки до момента, когда предыдущий возвратит хоть какие-нибудь данные (а если это поблочный алгоритм - до момента, когда он обработает весь блок) - if res<0 then return res - else action (checked_callback) +freearcDecompress num method = CompressionLib.decompress method -- |Копирование данных без сжатия (-m0) copy_data callback = do @@ -309,7 +296,6 @@ eat_data callback = do impossible_to_decompress callback = do return CompressionLib.aFREEARC_ERRCODE_GENERAL -- сразу возвратить ошибку, поскольку этот алгоритм (FAKE/CRC_ONLY) не подлежит распаковке -{-# NOINLINE checkingCtrlBreak #-} {-# NOINLINE copy_data #-} {-# NOINLINE eat_data #-} diff --git a/Compression/CompressionLib.hs b/Compression/CompressionLib.hs index 172dba9..5939d57 100644 --- a/Compression/CompressionLib.hs +++ b/Compression/CompressionLib.hs @@ -124,10 +124,11 @@ runWithMethod action method callback = do -- |Execute C (de)compression routine `action` using read/write callbacks `read_f` & `write_f` run action callback = do + -- Ignore auxdata since we can do better with closures let callback2 cwhat buf size auxdata = do what <- peekCString cwhat - callback what buf (ii size) auxdata >>=return.ii + callback what buf (ii size) >>=return.ii bracket (mkCALL_BACK callback2) (freeHaskellFunPtr)$ \c_callback -> do -- convert Haskell routine to C-callable routine - action c_callback c_callback + action c_callback nullPtr withMethod action method inp insize outp outsize = do withCString method $ \c_method -> do @@ -189,19 +190,19 @@ compressionErrorMessage x -- |Compress using callbacks foreign import ccall threadsafe "Compression.h Compress" - c_compress :: CMethod -> FunPtr CALLBACK_FUNC -> FunPtr CALLBACK_FUNC -> IO Int + c_compress :: CMethod -> FunPtr CALLBACK_FUNC -> VoidPtr -> IO Int -- |Decompress using callbacks foreign import ccall threadsafe "Compression.h Decompress" - c_decompress :: CMethod -> FunPtr CALLBACK_FUNC -> FunPtr CALLBACK_FUNC -> IO Int + c_decompress :: CMethod -> FunPtr CALLBACK_FUNC -> VoidPtr -> IO Int -- |Compress using callbacks and save method name in compressed output foreign import ccall threadsafe "Compression.h CompressWithHeader" - c_CompressWithHeader :: CMethod -> FunPtr CALLBACK_FUNC -> FunPtr CALLBACK_FUNC -> IO Int + c_CompressWithHeader :: CMethod -> FunPtr CALLBACK_FUNC -> VoidPtr -> IO Int -- |Decompress data compressed with c_CompressWithHeader (method name is read from compressed stream) foreign import ccall threadsafe "Compression.h DecompressWithHeader" - c_DecompressWithHeader :: FunPtr CALLBACK_FUNC -> FunPtr CALLBACK_FUNC -> IO Int + c_DecompressWithHeader :: FunPtr CALLBACK_FUNC -> VoidPtr -> IO Int ----------------------------------------------------------------------------------------------------