{-# LANGUAGE MagicHash #-}

module HsForeign.CppStd
  ( -- * StdString
    StdString
  , newStdString
  , newStdStringFromShort
  , maybeNewStdString
  , hs_new_std_string
  , hs_new_std_string_def
  , hs_std_string_size
  , hs_std_string_cstr
  , hs_delete_std_string
  , unsafePeekStdString
  , peekStdStringShort
    -- * StdVector
  , StdVector

  ) where

import           Data.ByteString        (ByteString)
import           Data.ByteString.Short  (ShortByteString)
import qualified Data.ByteString.Short  as BSS
import qualified Data.ByteString.Unsafe as BS
import           Data.Word
import           Foreign.Ptr

import           HsForeign.Primitive
import           HsForeign.String

-------------------------------------------------------------------------------
-- StdString

data StdString

-- | New a c++ std::string from proviced bytestring.
--
-- The memory should be deallocated using delete when no longer required.
newStdString :: ByteString -> IO (Ptr StdString)
newStdString :: ByteString -> IO (Ptr StdString)
newStdString ByteString
bs = ByteString
-> (Ptr Word8 -> Int -> IO (Ptr StdString)) -> IO (Ptr StdString)
forall a. ByteString -> (Ptr Word8 -> Int -> IO a) -> IO a
withByteString ByteString
bs ((Ptr Word8 -> Int -> IO (Ptr StdString)) -> IO (Ptr StdString))
-> (Ptr Word8 -> Int -> IO (Ptr StdString)) -> IO (Ptr StdString)
forall a b. (a -> b) -> a -> b
$ Ptr Word8 -> Int -> IO (Ptr StdString)
hs_new_std_string

newStdStringFromShort :: ShortByteString -> IO (Ptr StdString)
newStdStringFromShort :: ShortByteString -> IO (Ptr StdString)
newStdStringFromShort ShortByteString
sbs = ShortByteString
-> (ByteArray# -> Int -> IO (Ptr StdString)) -> IO (Ptr StdString)
forall a. ShortByteString -> (ByteArray# -> Int -> IO a) -> IO a
withShortByteString ShortByteString
sbs ((ByteArray# -> Int -> IO (Ptr StdString)) -> IO (Ptr StdString))
-> (ByteArray# -> Int -> IO (Ptr StdString)) -> IO (Ptr StdString)
forall a b. (a -> b) -> a -> b
$ ByteArray# -> Int -> IO (Ptr StdString)
hs_new_std_string'

maybeNewStdString :: Maybe ByteString -> IO (Ptr StdString)
maybeNewStdString :: Maybe ByteString -> IO (Ptr StdString)
maybeNewStdString Maybe ByteString
Nothing   = Ptr StdString -> IO (Ptr StdString)
forall (f :: * -> *) a. Applicative f => a -> f a
pure Ptr StdString
forall a. Ptr a
nullPtr
maybeNewStdString (Just ByteString
bs) = ByteString -> IO (Ptr StdString)
newStdString ByteString
bs

unsafePeekStdString :: Ptr StdString -> IO ByteString
unsafePeekStdString :: Ptr StdString -> IO ByteString
unsafePeekStdString Ptr StdString
stdstring = do
  Int
siz <- Ptr StdString -> IO Int
hs_std_string_size Ptr StdString
stdstring
  Ptr Word8
ptr <- Ptr StdString -> IO (Ptr Word8)
hs_std_string_cstr Ptr StdString
stdstring
  Ptr Word8 -> Int -> IO () -> IO ByteString
BS.unsafePackCStringFinalizer Ptr Word8
ptr Int
siz (Ptr StdString -> IO ()
hs_delete_std_string Ptr StdString
stdstring)
{-# INLINE unsafePeekStdString #-}

peekStdStringShort :: Ptr StdString -> IO ShortByteString
peekStdStringShort :: Ptr StdString -> IO ShortByteString
peekStdStringShort Ptr StdString
stdstring = do
  Int
siz <- Ptr StdString -> IO Int
hs_std_string_size Ptr StdString
stdstring
  Ptr Word8
ptr <- Ptr StdString -> IO (Ptr Word8)
hs_std_string_cstr Ptr StdString
stdstring
  CStringLen -> IO ShortByteString
BSS.packCStringLen (Ptr Word8 -> Ptr CChar
forall a b. Ptr a -> Ptr b
castPtr Ptr Word8
ptr, Int
siz)

-- TODO
--withStdString :: (Ptr StdString -> IO a) -> IO (ByteString, a)
--withStdString = undefined

foreign import ccall unsafe hs_new_std_string :: Ptr Word8 -> Int -> IO (Ptr StdString)
foreign import ccall unsafe "hs_new_std_string"
  hs_new_std_string' :: ByteArray# -> Int -> IO (Ptr StdString)
foreign import ccall unsafe hs_new_std_string_def :: IO (Ptr StdString)
foreign import ccall unsafe hs_std_string_size :: Ptr StdString -> IO Int
foreign import ccall unsafe hs_std_string_cstr :: Ptr StdString -> IO (Ptr Word8)
foreign import ccall unsafe hs_delete_std_string :: Ptr StdString -> IO ()

-------------------------------------------------------------------------------
-- StdVector

data StdVector a

-- TODO

--peekStdVectorOfString :: Ptr (StdVector StdString) -> [ByteString]
--peekStdVectorOfString = undefined

-------------------------------------------------------------------------------
-- StdMap

-- TODO

-------------------------------------------------------------------------------
-- StdMultiMap

-- TODO

--data CStdMultiMap k v
--newtype StdMultiMap k v = StdMultiMap (CStdMultiMap k v)