{-# LANGUAGE DeriveFunctor #-}
{-# LANGUAGE MagicHash #-}
module Foreign.JNI.String
( String
, toChars
, fromChars
, fromByteString
, unsafeFromByteString
, toByteString
, withString
) where
import qualified Data.ByteString as BS
import qualified Data.ByteString.Internal as BS
import qualified Data.ByteString.Unsafe as BS
import Data.ByteString (ByteString)
import Data.String (IsString(..))
import Foreign.C.String (CString)
import qualified GHC.Foreign as GHC
import qualified GHC.IO.Encoding as GHC
import System.IO.Unsafe (unsafeDupablePerformIO)
import qualified Prelude
import Prelude hiding (String)
newtype String = String ByteString
deriving (String -> String -> Bool
(String -> String -> Bool)
-> (String -> String -> Bool) -> Eq String
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: String -> String -> Bool
$c/= :: String -> String -> Bool
== :: String -> String -> Bool
$c== :: String -> String -> Bool
Eq, Eq String
Eq String
-> (String -> String -> Ordering)
-> (String -> String -> Bool)
-> (String -> String -> Bool)
-> (String -> String -> Bool)
-> (String -> String -> Bool)
-> (String -> String -> String)
-> (String -> String -> String)
-> Ord String
String -> String -> Bool
String -> String -> Ordering
String -> String -> String
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: String -> String -> String
$cmin :: String -> String -> String
max :: String -> String -> String
$cmax :: String -> String -> String
>= :: String -> String -> Bool
$c>= :: String -> String -> Bool
> :: String -> String -> Bool
$c> :: String -> String -> Bool
<= :: String -> String -> Bool
$c<= :: String -> String -> Bool
< :: String -> String -> Bool
$c< :: String -> String -> Bool
compare :: String -> String -> Ordering
$ccompare :: String -> String -> Ordering
$cp1Ord :: Eq String
Ord)
instance Show String where
show :: String -> String
show String
str = ShowS
forall a. Show a => a -> String
show (String -> String
toChars String
str)
instance IsString String where
fromString :: String -> String
fromString String
str = String -> String
fromChars String
str
fromChars :: Prelude.String -> String
{-# INLINE [0] fromChars #-}
fromChars :: String -> String
fromChars String
str = IO String -> String
forall a. IO a -> a
unsafeDupablePerformIO (IO String -> String) -> IO String -> String
forall a b. (a -> b) -> a -> b
$
TextEncoding -> String -> (CString -> IO String) -> IO String
forall a. TextEncoding -> String -> (CString -> IO a) -> IO a
GHC.withCString TextEncoding
GHC.utf8 String
str ((CString -> IO String) -> IO String)
-> (CString -> IO String) -> IO String
forall a b. (a -> b) -> a -> b
$ \CString
cstr -> do
CSize
len <- CString -> IO CSize
BS.c_strlen CString
cstr
ByteString -> String
String (ByteString -> String) -> IO ByteString -> IO String
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> CStringLen -> IO ByteString
BS.packCStringLen (CString
cstr, CSize -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral CSize
len Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1)
toChars :: String -> Prelude.String
toChars :: String -> String
toChars (String ByteString
bs) = IO String -> String
forall a. IO a -> a
unsafeDupablePerformIO (IO String -> String) -> IO String -> String
forall a b. (a -> b) -> a -> b
$ ByteString -> (CString -> IO String) -> IO String
forall a. ByteString -> (CString -> IO a) -> IO a
BS.unsafeUseAsCString ByteString
bs ((CString -> IO String) -> IO String)
-> (CString -> IO String) -> IO String
forall a b. (a -> b) -> a -> b
$ TextEncoding -> CString -> IO String
GHC.peekCString TextEncoding
GHC.utf8
withString :: String -> (CString -> IO a) -> IO a
withString :: String -> (CString -> IO a) -> IO a
withString (String ByteString
bs) CString -> IO a
f = ByteString -> (CString -> IO a) -> IO a
forall a. ByteString -> (CString -> IO a) -> IO a
BS.unsafeUseAsCString ByteString
bs CString -> IO a
f
toByteString :: String -> ByteString
toByteString :: String -> ByteString
toByteString (String ByteString
bs) = ByteString -> ByteString
BS.init ByteString
bs
fromByteString :: ByteString -> String
fromByteString :: ByteString -> String
fromByteString ByteString
bs
| ByteString -> Word8
BS.last ByteString
bs Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
0 = ByteString -> String
String ByteString
bs
| Bool
otherwise = ByteString -> String
String (ByteString
bs ByteString -> Word8 -> ByteString
`BS.snoc` Word8
0)
unsafeFromByteString :: ByteString -> String
unsafeFromByteString :: ByteString -> String
unsafeFromByteString = ByteString -> String
String