module LLVM.Internal.String where
import LLVM.Prelude
import Control.Arrow
import Control.Monad.AnyCont
import Control.Monad.IO.Class
import Control.Exception (finally)
import Foreign.C (CString, CChar)
import Foreign.Ptr
import Foreign.Storable (Storable)
import Foreign.Marshal.Alloc as F.M (alloca, free)
import LLVM.Internal.FFI.LLVMCTypes
import LLVM.Internal.Coding
import qualified Data.ByteString as BS
import qualified LLVM.Internal.FFI.ShortByteString as SBS
import qualified Data.ByteString.Unsafe as BS
import qualified Data.ByteString.UTF8 as BSUTF8
newtype UTF8ByteString = UTF8ByteString { utf8Bytes :: BS.ByteString }
instance (Monad e) => EncodeM e String UTF8ByteString where
encodeM = return . UTF8ByteString . BSUTF8.fromString
instance (Monad d) => DecodeM d String UTF8ByteString where
decodeM = return . BSUTF8.toString . utf8Bytes
instance (MonadAnyCont IO e) => EncodeM e String CString where
encodeM s = anyContToM (BS.unsafeUseAsCString . utf8Bytes =<< encodeM (s ++ "\0"))
instance (MonadAnyCont IO e) => EncodeM e ByteString CString where
encodeM s = anyContToM (BS.useAsCString s)
instance (MonadAnyCont IO e) => EncodeM e ShortByteString CString where
encodeM s = anyContToM (SBS.useAsCString s)
instance (Integral i, MonadAnyCont IO e) => EncodeM e String (Ptr CChar, i) where
encodeM s = anyContToM ((. (. second fromIntegral)) $ BS.useAsCStringLen . utf8Bytes =<< encodeM s)
instance (Integral i, MonadAnyCont IO e) => EncodeM e ByteString (Ptr CChar, i) where
encodeM s =
anyContToM (\cont -> BS.useAsCStringLen s (\(ptr, len) -> cont (ptr, fromIntegral len)))
instance (Integral i, MonadAnyCont IO e) => EncodeM e ShortByteString (Ptr CChar, i) where
encodeM s =
anyContToM (\cont -> SBS.useAsCStringLen s (\(ptr, len) -> cont (ptr, fromIntegral len)))
instance (MonadIO d) => DecodeM d String CString where
decodeM = decodeM . UTF8ByteString <=< liftIO . BS.packCString
instance (MonadIO d) => DecodeM d ByteString CString where
decodeM = liftIO . BS.packCString
instance (MonadIO d) => DecodeM d ShortByteString CString where
decodeM = liftIO . SBS.packCString
instance (MonadIO d) => DecodeM d String (OwnerTransfered CString) where
decodeM (OwnerTransfered s) = liftIO $ finally (decodeM s) (free s)
instance (MonadIO d) => DecodeM d ByteString (OwnerTransfered CString) where
decodeM (OwnerTransfered s) = liftIO $ finally (decodeM s) (free s)
instance (MonadIO d) => DecodeM d ShortByteString (OwnerTransfered CString) where
decodeM (OwnerTransfered s) = liftIO $ finally (decodeM s) (free s)
instance (MonadIO d, DecodeM IO s (OwnerTransfered CString)) =>DecodeM d s (Ptr (OwnerTransfered CString)) where
decodeM = liftIO . decodeM <=< peek
instance (Integral i, MonadIO d) => DecodeM d String (Ptr CChar, i) where
decodeM = decodeM . UTF8ByteString <=< liftIO . BS.packCStringLen . second fromIntegral
instance (Integral i, MonadIO d) => DecodeM d BS.ByteString (Ptr CChar, i) where
decodeM = liftIO . BS.packCStringLen . second fromIntegral
instance (Integral i, MonadIO d) => DecodeM d ShortByteString (Ptr CChar, i) where
decodeM = liftIO . SBS.packCStringLen . second fromIntegral
instance (Integral i, Storable i, MonadIO d, DecodeM d s (CString, i)) => DecodeM d s (Ptr i -> IO CString) where
decodeM f = decodeM =<< (liftIO $ F.M.alloca $ \p -> (,) `liftM` f p `ap` peek p)
instance (Monad e, EncodeM e String c) => EncodeM e (Maybe String) (NothingAsEmptyString c) where
encodeM = liftM NothingAsEmptyString . encodeM . fromMaybe ""