module Text.Unicode.Base(UChar
,UErrorCode
,UBool
,uBoolToBool
,BitPackable(..)
,withCompactString
,handleError
,cOrderingToOrdering
) where
import Data.CompactString(CompactString)
import Data.CompactString.Encodings(UTF16Native)
import qualified Data.CompactString as CS
import qualified Data.CompactString.Unsafe as CS(unsafeFromByteString)
#if __GLASGOW_HASKELL__ >= 608
import Data.ByteString.Internal(toForeignPtr)
#else
import Data.ByteString.Base(toForeignPtr)
#endif
import Foreign.Ptr
import Foreign.ForeignPtr
import Foreign.C.Types(CInt, CChar)
import Foreign.Storable(peek, poke)
import Foreign.Marshal.Alloc(alloca)
import Data.Int(Int32)
import Data.Word(Word16)
import Data.Bits((.|.))
import Control.Monad(when)
type UChar = Word16
type UErrorCode = CInt
type UBool = CChar
uBoolToBool :: UBool -> Bool
uBoolToBool = (/= 0)
class BitPackable a where
intValue :: a -> Int32
packOptions :: [a] -> Int32
packOptions = foldr (.|.) 0 . map intValue
withPackedOptions :: [a] -> (Int32 -> IO b) -> IO b
withPackedOptions opts f = f $ packOptions opts
withCompactString :: CompactString UTF16Native -> (Ptr UChar -> Int32 -> IO a) -> IO a
withCompactString cs f = withForeignPtr ptr $ \word8Pointer ->
let contentPointer = plusPtr word8Pointer offset :: Ptr UChar
numUChars = fromIntegral (length `div` 2)
in f contentPointer numUChars
where (ptr, offset, length) = toForeignPtr $ CS.toByteString cs
handleError :: (Ptr UErrorCode -> IO a) -> IO a
handleError f = alloca $ \errptr ->
do poke errptr 0
result <- f errptr
errorCode <- peek errptr
when (errorCode > 0) (error (errMsg ++ show errorCode))
return result
where errMsg = "Data.CompactString.ICU.handleError: error returned by ICU4C function: "
cOrderingToOrdering :: (Integral a) => a -> Ordering
cOrderingToOrdering i | i < 0 = LT
| i == 0 = EQ
| i > 0 = GT