{-# LANGUAGE ForeignFunctionInterface,FlexibleInstances #-} {-# LANGUAGE EmptyDataDecls #-} {- DC++ protocl utls for GHC Copyright (C) 2009 Nikolay Orlyuk (virkony _at_ gmail _dot_ com) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -} module Data.Digest.TigerHash.Internal ( TigerHash(..), TigerContext(..), TigerState, TigerTreeState, newTigerContext, newTigerTreeContext, withTigerContext, withTigerTreeContext, ) where import Foreign import Foreign.Ptr import Foreign.ForeignPtr import Foreign.Marshal.Alloc import Foreign.Marshal.Array import Foreign.C.Types data TigerHash = TigerHash {-# UNPACK #-} !Word64 {-# UNPACK #-} !Word64 {-# UNPACK #-} !Word64 -- Level 1 class TigerContext c where initContext :: c -> IO () updateContext :: c -> Ptr a -> Int -> IO () resetContext :: c -> IO () finalizeContext :: c -> IO TigerHash newTigerContext :: IO (ForeignPtr TigerState) newTigerContext = do ctx <- mallocBytes sizeofTigerContext >>= newForeignPtr finalizerFree initContext ctx return ctx newTigerTreeContext :: IO (ForeignPtr TigerTreeState) newTigerTreeContext = do ctx <- mallocBytes sizeofTigerTreeContext >>= newForeignPtr finalizerFree initContext ctx return ctx withTigerContext :: (Ptr TigerState -> IO a) -> IO a withTigerContext actions = allocaBytes sizeofTigerContext (\ctx_ -> initContext ctx_ >> actions ctx_) withTigerTreeContext :: (Ptr TigerTreeState -> IO a) -> IO a withTigerTreeContext actions = allocaBytes sizeofTigerTreeContext (\ctx_ -> initContext ctx_ >> actions ctx_) instance TigerContext (Ptr TigerState) where initContext ctx_ = initTigerContext_ ctx_ updateContext ctx_ p_ s = updateTigerContext_ ctx_ p_ (fromIntegral s) resetContext ctx_ = resetTigerContext_ ctx_ finalizeContext ctx_ = allocaArray 3 internal where internal p_ = do finalizeTigerContext_ ctx_ p_ a <- peekElemOff p_ 0 b <- peekElemOff p_ 1 c <- peekElemOff p_ 2 return (TigerHash a b c) instance TigerContext (Ptr TigerTreeState) where initContext ctx_ = initTigerTreeContext_ ctx_ updateContext ctx_ p_ s = updateTigerTreeContext_ ctx_ p_ (fromIntegral s) resetContext ctx_ = resetTigerTreeContext_ ctx_ finalizeContext ctx_ = allocaArray 3 internal where internal p_ = do finalizeTigerTreeContext_ ctx_ p_ a <- peekElemOff p_ 0 b <- peekElemOff p_ 1 c <- peekElemOff p_ 2 return (TigerHash a b c) instance (TigerContext (Ptr a)) => TigerContext (ForeignPtr a) where initContext ctx = withForeignPtr ctx initContext updateContext ctx p_ s = withForeignPtr ctx (\ctx_ -> updateContext ctx_ p_ s) resetContext ctx = withForeignPtr ctx resetContext finalizeContext ctx = withForeignPtr ctx finalizeContext -- Level 0 data TigerState data TigerTreeState {-# CFILES c_lib/tiger.c #-} foreign import ccall unsafe "tiger.h tiger_context_size" sizeofTigerContext :: Int foreign import ccall unsafe "tiger.h tiger_init" initTigerContext_ :: Ptr TigerState -> IO () -- foreign import ccall unsafe "tiger.h tiger_new" newTigerContext_ :: IO (Ptr TigerState) -- foreign import ccall unsafe "tiger.h &tiger_free" freeTigerContext_ :: FinalizerPtr TigerState foreign import ccall unsafe "tiger.h tiger_feed" updateTigerContext_ :: Ptr TigerState -> Ptr a -> CSize -> IO () foreign import ccall unsafe "tiger.h tiger_finalize" finalizeTigerContext_ :: Ptr TigerState -> Ptr Word64 -> IO () foreign import ccall unsafe "tiger.h tiger_reset" resetTigerContext_ :: Ptr TigerState -> IO () {-# CFILES c_lib/tigertree.c #-} foreign import ccall unsafe "tigertree.h tigertree_context_size" sizeofTigerTreeContext :: Int foreign import ccall unsafe "tigertree.h tigertree_init" initTigerTreeContext_ :: Ptr TigerTreeState -> IO () -- foreign import ccall unsafe "tigertree.h tigertree_new" newTigerTreeContext_ :: IO (Ptr TigerTreeState) -- foreign import ccall unsafe "tigertree.h &tigertree_free" freeTigerTreeContext_ :: FinalizerPtr TigerTreeState foreign import ccall unsafe "tigertree.h tigertree_feed" updateTigerTreeContext_ :: Ptr TigerTreeState -> Ptr a -> CSize -> IO () foreign import ccall unsafe "tigertree.h tigertree_finalize" finalizeTigerTreeContext_ :: Ptr TigerTreeState -> Ptr Word64 -> IO () foreign import ccall unsafe "tigertree.h tigertree_reset" resetTigerTreeContext_ :: Ptr TigerTreeState -> IO () -- ex:syntax=haskell