module LLVM.General.Internal.String where
import Control.Arrow
import Control.Monad
import Control.Monad.AnyCont
import Control.Monad.IO.Class
import Control.Exception (finally)
import Data.Maybe (fromMaybe)
import Foreign.C (CString, CChar)
import Foreign.Ptr
import Foreign.Storable (Storable)
import Foreign.Marshal.Alloc as F.M (alloca, free)
import LLVM.General.Internal.FFI.LLVMCTypes
import LLVM.General.Internal.Coding
import qualified Data.ByteString as BS
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 (Integral i, MonadAnyCont IO e) => EncodeM e String (Ptr CChar, i) where
encodeM s = anyContToM ((. (. second fromIntegral)) $ BS.useAsCStringLen . utf8Bytes =<< encodeM s)
instance (MonadIO d) => DecodeM d String CString where
decodeM = decodeM . UTF8ByteString <=< liftIO . BS.packCString
instance (MonadIO d) => DecodeM d String (OwnerTransfered CString) where
decodeM (OwnerTransfered s) = liftIO $ finally (decodeM s) (free s)
instance (MonadIO d) => DecodeM d String (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, Storable i, MonadIO d) => DecodeM d String (Ptr i -> IO (Ptr CChar)) 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 ""