NGLess-1.4.0: NGLess/Interpretation/Count/RefSeqInfoVector.hs
{-# LANGUAGE TemplateHaskell, QuasiQuotes #-}
{- Copyright 2013-2022 NGLess Authors
- License: MIT
-}
module Interpretation.Count.RefSeqInfoVector
( RefSeqInfo(..)
, RefSeqInfoVectorMutable
, RefSeqInfoVector
, fromList
, newRefSeqInfoVector
, insert
, sort
, unsafeFreeze
, unsafeThaw
, lookup
, retrieveSize
, retrieveSizeIO
, retrieveName
, length
, writeSizeIO
) where
import Prelude hiding (length, lookup)
import Foreign.C.Types
import Control.DeepSeq (NFData(..))
import Control.Monad (forM_)
import qualified Data.ByteString as B
import Foreign.Ptr
import Foreign.ForeignPtr
import System.IO.Unsafe (unsafeDupablePerformIO)
import qualified Language.C.Inline.Context as C
import qualified Language.C.Inline.Unsafe as CU
import qualified Language.C.Inline.Cpp as C
import qualified Language.C.Inline.Cpp.Exception as C
foreign import ccall "&rsiv_free" c_rsiv_free :: FunPtr (Ptr () -> IO ())
C.context (C.baseCtx <> C.bsCtx <> C.fptrCtx <> C.cppCtx)
C.include "RefSeqInfoVector.h"
data RefSeqInfo = RefSeqInfo
{ rsiName :: {-# UNPACK #-} !B.ByteString
, rsiSize :: {-# UNPACK #-} !Double
} deriving (Eq, Show)
instance NFData RefSeqInfo where
rnf !_ = ()
instance Ord RefSeqInfo where
compare RefSeqInfo{ rsiName = n0 } RefSeqInfo{ rsiName = n1 } = compare n0 n1
newtype RefSeqInfoVectorMutable = RefSeqInfoVectorMutable (ForeignPtr ())
newtype RefSeqInfoVector = RefSeqInfoVector (ForeignPtr ())
instance NFData RefSeqInfoVector where
rnf (RefSeqInfoVector !_) = ()
newRefSeqInfoVector :: IO RefSeqInfoVectorMutable
newRefSeqInfoVector = do
p <- C.withPtr_ $ \r ->
[C.catchBlock| { *( $(void** r) ) = new RefSeqInfoVector; }|]
RefSeqInfoVectorMutable <$> newForeignPtr c_rsiv_free (p :: Ptr ())
insert :: RefSeqInfoVectorMutable -> B.ByteString -> Double -> IO ()
insert (RefSeqInfoVectorMutable p) bs val = do
let val' :: CDouble
val' = CDouble val
[C.catchBlock| { static_cast<RefSeqInfoVector*>($fptr-ptr:(void* p))->insert(std::string($bs-ptr:bs, $bs-len:bs), $(double val')); } |]
sort :: RefSeqInfoVectorMutable -> IO ()
sort (RefSeqInfoVectorMutable p) = [CU.block| void {
RefSeqInfoVector* vec = static_cast<RefSeqInfoVector*>($fptr-ptr:(void* p));
vec->sort();
}|]
unsafeFreeze :: RefSeqInfoVectorMutable -> IO RefSeqInfoVector
unsafeFreeze (RefSeqInfoVectorMutable v) = return $ RefSeqInfoVector v
unsafeThaw :: RefSeqInfoVector -> IO RefSeqInfoVectorMutable
unsafeThaw (RefSeqInfoVector v) = return $ RefSeqInfoVectorMutable v
lookup :: RefSeqInfoVector -> B.ByteString -> Maybe Int
lookup (RefSeqInfoVector p) key = let
CInt ix = [CU.pure| int { static_cast<RefSeqInfoVector*>($fptr-ptr:(void* p))->find(std::string($bs-ptr:key, $bs-len:key).c_str()) } |]
in if ix == -1
then Nothing
else Just (fromEnum ix)
retrieveSize :: RefSeqInfoVector -> Int -> Double
retrieveSize (RefSeqInfoVector r) ix = unsafeDupablePerformIO (retrieveSizeIO (RefSeqInfoVectorMutable r) ix)
retrieveSizeIO :: RefSeqInfoVectorMutable -> Int -> IO Double
retrieveSizeIO (RefSeqInfoVectorMutable p) ix = do
let ix' = toEnum ix
CDouble val <- [CU.exp| double { static_cast<RefSeqInfoVector*>($fptr-ptr:(void* p))->at($(int ix')).val } |]
return val
writeSizeIO :: RefSeqInfoVectorMutable -> Int -> Double -> IO ()
writeSizeIO (RefSeqInfoVectorMutable p) ix val = do
let val' = CDouble val
ix' = toEnum ix
[C.catchBlock| { static_cast<RefSeqInfoVector*>($fptr-ptr:(void* p))->at($(int ix')).val = $(double val'); } |]
length :: RefSeqInfoVector -> Int
length (RefSeqInfoVector p) =
fromEnum [CU.pure| unsigned int { static_cast<RefSeqInfoVector*>($fptr-ptr:(void* p))->size() } |]
retrieveName :: RefSeqInfoVector -> Int -> B.ByteString
retrieveName (RefSeqInfoVector p) ix = unsafeDupablePerformIO $ do
let ix' = toEnum ix
[CU.exp| const char* {static_cast<RefSeqInfoVector*>($fptr-ptr:(void* p))->at($(int ix')).str } |] >>= B.packCString
fromList :: [RefSeqInfo] -> RefSeqInfoVector
fromList entries = unsafeDupablePerformIO $ do
r <- newRefSeqInfoVector
forM_ entries $ \(RefSeqInfo n v) -> insert r n v
sort r
unsafeFreeze r