{-# LANGUAGE EmptyDataDecls, ForeignFunctionInterface #-} module Data.Text.ICU.Internal ( LocaleName(..) , UBool , UChar , UChar32 , UCharIterator , CharIterator(..) , asBool , asOrdering , withCharIterator , withLocaleName , withName ) where #include import Control.DeepSeq (NFData(..)) import Data.ByteString.Internal (ByteString(..)) import Data.Int (Int8, Int32) import Data.String (IsString(..)) import Data.Text (Text) import Data.Text.Encoding (decodeUtf8) import Data.Text.Foreign (useAsPtr) import Data.Word (Word16, Word32) import Foreign.C.String (CString, withCString) import Foreign.C.Types (CChar) import Foreign.Marshal.Alloc (allocaBytes) import Foreign.ForeignPtr (withForeignPtr) import Foreign.Ptr (Ptr, castPtr, nullPtr) -- | A type that supports efficient iteration over Unicode characters. -- -- As an example of where this may be useful, a function using this -- type may be able to iterate over a UTF-8 'ByteString' directly, -- rather than first copying and converting it to an intermediate -- form. This type also allows e.g. comparison between 'Text' and -- 'ByteString', with minimal overhead. data CharIterator = CIText !Text | CIUTF8 !ByteString instance Show CharIterator where show (CIText t) = show t show (CIUTF8 bs) = show (decodeUtf8 bs) data UCharIterator -- | Temporarily allocate a 'UCharIterator' and use it with the -- contents of the to-be-iterated-over string. withCharIterator :: CharIterator -> (Ptr UCharIterator -> IO a) -> IO a withCharIterator (CIUTF8 (PS fp _ l)) act = allocaBytes (#{size UCharIterator}) $ \i -> withForeignPtr fp $ \p -> uiter_setUTF8 i (castPtr p) (fromIntegral l) >> act i withCharIterator (CIText t) act = allocaBytes (#{size UCharIterator}) $ \i -> useAsPtr t $ \p l -> uiter_setString i p (fromIntegral l) >> act i type UBool = Int8 type UChar = Word16 type UChar32 = Word32 asBool :: Integral a => a -> Bool {-# INLINE asBool #-} asBool = (/=0) asOrdering :: Integral a => a -> Ordering {-# INLINE asOrdering #-} asOrdering i | i < 0 = LT | i == 0 = EQ | otherwise = GT withName :: String -> (CString -> IO a) -> IO a withName name act | null name = act nullPtr | otherwise = withCString name act -- | The name of a locale. data LocaleName = Root -- ^ The root locale. For a description of resource bundles -- and the root resource, see -- . | Locale String -- ^ A specific locale. | Current -- ^ The program's current locale. deriving (Eq, Ord, Read, Show) instance NFData LocaleName where rnf Root = () rnf (Locale l) = rnf l rnf Current = () instance IsString LocaleName where fromString = Locale withLocaleName :: LocaleName -> (CString -> IO a) -> IO a withLocaleName Current act = act nullPtr withLocaleName Root act = withCString "" act withLocaleName (Locale n) act = withCString n act foreign import ccall unsafe "hs_text_icu.h __hs_uiter_setString" uiter_setString :: Ptr UCharIterator -> Ptr UChar -> Int32 -> IO () foreign import ccall unsafe "hs_text_icu.h __hs_uiter_setUTF8" uiter_setUTF8 :: Ptr UCharIterator -> Ptr CChar -> Int32 -> IO ()