module Data.Text.ICU.Error.Internal
(
ErrorCode(..)
, UErrorCode
, isFailure
, isSuccess
, errorName
, handleError
, throwOnError
, withError
) where
import Control.Exception
import Foreign.Ptr
import Foreign.Marshal.Alloc
import Data.Typeable (Typeable)
import Foreign.C.String (CString, peekCString)
import Foreign.C.Types (CInt)
import Foreign.Storable
import System.IO.Unsafe (unsafePerformIO)
type UErrorCode = CInt
newtype ErrorCode = ErrorCode {
fromErrorCode :: UErrorCode
} deriving (Eq, Typeable)
instance Show ErrorCode where
show code = "ErrorCode " ++ errorName code
instance Exception ErrorCode
isSuccess :: ErrorCode -> Bool
isSuccess = (<= 0) . fromErrorCode
isFailure :: ErrorCode -> Bool
isFailure = (> 0) . fromErrorCode
throwOnError :: UErrorCode -> IO ()
throwOnError code = do
let err = (ErrorCode code)
if isFailure err
then throw err
else return ()
withError :: (Ptr UErrorCode -> IO a) -> IO (ErrorCode, a)
withError action = alloca $ \errPtr -> do
poke errPtr 0
ret <- action errPtr
err <- peek errPtr
return (ErrorCode err, ret)
handleError :: (Ptr UErrorCode -> IO a) -> IO a
handleError action = alloca $ \errPtr -> do
poke errPtr 0
ret <- action errPtr
throwOnError =<< peek errPtr
return ret
errorName :: ErrorCode -> String
errorName code = unsafePerformIO $
peekCString (u_errorName (fromErrorCode code))
foreign import ccall unsafe "unicode/utypes.h u_errorName_4_0" u_errorName
:: UErrorCode -> CString