text-icu 0.2.0.0 → 0.3.0.0
raw patch · 8 files changed
+602/−596 lines, 8 files
Files
- Data/Text/ICU/Convert.hs +236/−0
- Data/Text/ICU/Convert/Internal.hs +50/−0
- Data/Text/ICU/Converter.hs +0/−235
- Data/Text/ICU/Converter/Internal.hs +0/−50
- Data/Text/ICU/Error/Internal.hs +4/−4
- Data/Text/ICU/Normalize.hsc +308/−0
- Data/Text/ICU/Normalizer.hsc +0/−303
- text-icu.cabal +4/−4
+ Data/Text/ICU/Convert.hs view
@@ -0,0 +1,236 @@+{-# LANGUAGE CPP, ForeignFunctionInterface #-}+-- |+-- Module : Data.Text.ICU.Convert+-- Copyright : (c) Bryan O'Sullivan 2009+--+-- License : BSD-style+-- Maintainer : bos@serpentine.com+-- Stability : experimental+-- Portability : GHC+--+-- Character set conversion functions for Unicode, implemented as+-- bindings to the International Components for Unicode (ICU)+-- libraries.++module Data.Text.ICU.Convert+ (+ -- * Character set conversion+ Converter+ -- ** Basic functions+ , open+ , fromUnicode+ , toUnicode+ -- ** Converter metadata+ , getName+ , usesFallback+ , isAmbiguous+ -- * Functions for controlling global behavior+ , getDefaultName+ , setDefaultName+ -- * Miscellaneous functions+ , compareNames+ , aliases+ -- * Metadata+ , converterNames+ , standardNames+ ) where++import Data.ByteString.Internal (ByteString, createAndTrim)+import Data.ByteString.Unsafe (unsafeUseAsCStringLen)+import Data.Int (Int32)+import Data.Text (Text)+import Data.Text.Foreign (fromPtr, lengthWord16, useAsPtr)+import Data.Text.ICU.Convert.Internal+import Data.Text.ICU.Error.Internal (UErrorCode, handleError)+import Data.Word (Word16)+import Foreign.C.String (CString, peekCString, withCString)+import Foreign.C.Types (CInt)+import Foreign.ForeignPtr (newForeignPtr)+import Foreign.Marshal.Array (allocaArray)+import Foreign.Ptr (FunPtr, Ptr, castPtr, nullPtr)+import System.IO.Unsafe (unsafePerformIO)+import Data.Text.ICU.Internal (UBool, UChar, asBool, asOrdering)++-- | Do a fuzzy compare of two converter/alias names. The comparison+-- is case-insensitive, ignores leading zeroes if they are not+-- followed by further digits, and ignores all but letters and digits.+-- Thus the strings @\"UTF-8\"@, @\"utf_8\"@, @\"u*T\@f08\"@ and+-- @\"Utf 8\"@ are exactly equivalent. See section 1.4, Charset Alias+-- Matching in Unicode Technical Standard #22 at+-- <http://www.unicode.org/reports/tr22/>+compareNames :: String -> String -> Ordering+compareNames a b =+ unsafePerformIO . withCString a $ \aptr ->+ fmap asOrdering . withCString b $ ucnv_compareNames aptr++-- | Create a 'Converter' with the name of a coded character set+-- specified as a string. The actual name will be resolved with the+-- alias file using a case-insensitive string comparison that ignores+-- leading zeroes and all non-alphanumeric characters. E.g., the+-- names @\"UTF8\"@, @\"utf-8\"@, @\"u*T\@f08\"@ and @\"Utf 8\"@ are+-- all equivalent (see also 'compareNames'). If an empty string is+-- passed for the converter name, it will create one with the+-- 'getDefaultName' return value.+--+-- A converter name may contain options like a locale specification to+-- control the specific behavior of the newly instantiated converter.+-- The meaning of the options depends on the particular converter. If+-- an option is not defined for or recognized by a given converter,+-- then it is ignored.+--+-- Options are appended to the converter name string, with a comma+-- between the name and the first option and also between adjacent+-- options.+--+-- If the alias is ambiguous, then the preferred converter is used.+--+-- The conversion behavior and names can vary between platforms. ICU+-- may convert some characters differently from other+-- platforms. Details on this topic are in the ICU User's Guide at+-- <http://icu-project.org/userguide/conversion.html>. Aliases+-- starting with a @\"cp\"@ prefix have no specific meaning other than+-- its an alias starting with the letters @\"cp\"@. Please do not+-- associate any meaning to these aliases.+open :: String -- ^ Name of the converter to use.+ -> Maybe Bool -- ^ Whether to use fallback mappings+ -- (see 'usesFallback' for details).+ -> IO Converter+open name mf = do+ c <- fmap Converter . newForeignPtr ucnv_close =<< named (handleError . ucnv_open)+ case mf of+ Just f -> withConverter c $ \p -> ucnv_setFallback p . fromIntegral . fromEnum $ f+ _ -> return ()+ return c+ where named act+ | null name = act nullPtr+ | otherwise = withCString name act++-- | Convert the Unicode string into a codepage string using the given+-- converter.+fromUnicode :: Converter -> Text -> ByteString+fromUnicode cnv t =+ unsafePerformIO . useAsPtr t $ \tptr tlen ->+ withConverter cnv $ \cptr -> do+ let capacity = fromIntegral . max_bytes_for_string cptr . fromIntegral $+ lengthWord16 t+ createAndTrim (fromIntegral capacity) $ \sptr ->+ fmap fromIntegral . handleError $+ ucnv_fromUChars cptr (castPtr sptr) capacity tptr (fromIntegral tlen)++-- | Convert the codepage string into a Unicode string using the given+-- converter.+toUnicode :: Converter -> ByteString -> Text+toUnicode cnv bs =+ unsafePerformIO . unsafeUseAsCStringLen bs $ \(sptr, slen) ->+ withConverter cnv $ \cptr -> do+ let capacity = slen * 2+ allocaArray capacity $ \tptr -> + fromPtr tptr =<< (fmap fromIntegral . handleError $+ ucnv_toUChars cptr tptr (fromIntegral capacity) sptr+ (fromIntegral slen))++-- | Determines whether the converter uses fallback mappings or not.+-- This flag has restrictions. Regardless of this flag, the converter+-- will always use fallbacks from Unicode Private Use code points, as+-- well as reverse fallbacks (to Unicode). For details see \".ucm+-- File Format\" in the Conversion Data chapter of the ICU User Guide:+-- <http://www.icu-project.org/userguide/conversion-data.html#ucmformat>+usesFallback :: Converter -> Bool+usesFallback cnv = unsafePerformIO $+ asBool `fmap` withConverter cnv ucnv_usesFallback++-- | Returns the current default converter name. If you want to 'open'+-- a default converter, you do not need to use this function. It is+-- faster to pass the empty string to 'open' the default converter.+getDefaultName :: IO String+getDefaultName = peekCString =<< ucnv_getDefaultName++-- | Indicates whether the converter contains ambiguous mappings of+-- the same character or not.+isAmbiguous :: Converter -> Bool+isAmbiguous cnv = asBool . unsafePerformIO $ withConverter cnv ucnv_isAmbiguous++-- | Sets the current default converter name. If this function needs+-- to be called, it should be called during application+-- initialization. Most of the time, the results from 'getDefaultName'+-- or 'open' with an empty string argument is sufficient for your+-- application.+--+-- /Note/: this function is not thread safe. /Do not/ call this+-- function when /any/ ICU function is being used from more than one+-- thread!+setDefaultName :: String -> IO ()+setDefaultName s = withCString s $ ucnv_setDefaultName++-- | A list of the canonical names of all available converters.+converterNames :: [String]+{-# NOINLINE converterNames #-}+converterNames = unsafePerformIO $+ mapM ((peekCString =<<) . ucnv_getAvailableName) [0..ucnv_countAvailable-1]++-- | The list of supported standard names.+standardNames :: [String]+{-# NOINLINE standardNames #-}+standardNames = filter (not . null) . unsafePerformIO $+ mapM ((peekCString =<<) . handleError . ucnv_getStandard) [0..ucnv_countStandards-1]++-- | Return the aliases for a given converter or alias name.+aliases :: String -> [String]+aliases name = unsafePerformIO . withCString name $ \ptr -> do+ count <- handleError $ ucnv_countAliases ptr+ if count == 0+ then return []+ else mapM ((peekCString =<<) . handleError . ucnv_getAlias ptr) [0..count-1]++foreign import ccall unsafe "hs_text_icu.h __hs_ucnv_open" ucnv_open+ :: CString -> Ptr UErrorCode -> IO (Ptr UConverter)++foreign import ccall unsafe "hs_text_icu.h &__hs_ucnv_close" ucnv_close+ :: FunPtr (Ptr UConverter -> IO ())++foreign import ccall unsafe "__get_max_bytes_for_string" max_bytes_for_string+ :: Ptr UConverter -> CInt -> CInt++foreign import ccall unsafe "hs_text_icu.h __hs_ucnv_toUChars" ucnv_toUChars+ :: Ptr UConverter -> Ptr UChar -> Int32 -> CString -> Int32+ -> Ptr UErrorCode -> IO Int32++foreign import ccall unsafe "hs_text_icu.h __hs_ucnv_fromUChars" ucnv_fromUChars+ :: Ptr UConverter -> CString -> Int32 -> Ptr UChar -> Int32+ -> Ptr UErrorCode -> IO Int32++foreign import ccall unsafe "hs_text_icu.h __hs_ucnv_compareNames" ucnv_compareNames+ :: CString -> CString -> IO CInt++foreign import ccall unsafe "hs_text_icu.h __hs_ucnv_getDefaultName" ucnv_getDefaultName+ :: IO CString++foreign import ccall unsafe "hs_text_icu.h __hs_ucnv_setDefaultName" ucnv_setDefaultName+ :: CString -> IO ()++foreign import ccall unsafe "hs_text_icu.h __hs_ucnv_countAvailable" ucnv_countAvailable+ :: Int32++foreign import ccall unsafe "hs_text_icu.h __hs_ucnv_getAvailableName" ucnv_getAvailableName+ :: Int32 -> IO CString++foreign import ccall unsafe "hs_text_icu.h __hs_ucnv_countAliases" ucnv_countAliases+ :: CString -> Ptr UErrorCode -> IO Word16++foreign import ccall unsafe "hs_text_icu.h __hs_ucnv_getAlias" ucnv_getAlias+ :: CString -> Word16 -> Ptr UErrorCode -> IO CString++foreign import ccall unsafe "hs_text_icu.h __hs_ucnv_countStandards" ucnv_countStandards+ :: Word16++foreign import ccall unsafe "hs_text_icu.h __hs_ucnv_getStandard" ucnv_getStandard+ :: Word16 -> Ptr UErrorCode -> IO CString++foreign import ccall unsafe "hs_text_icu.h __hs_ucnv_usesFallback" ucnv_usesFallback+ :: Ptr UConverter -> IO UBool++foreign import ccall unsafe "hs_text_icu.h __hs_ucnv_setFallback" ucnv_setFallback+ :: Ptr UConverter -> UBool -> IO ()++foreign import ccall unsafe "hs_text_icu.h __hs_ucnv_isAmbiguous" ucnv_isAmbiguous+ :: Ptr UConverter -> IO UBool
+ Data/Text/ICU/Convert/Internal.hs view
@@ -0,0 +1,50 @@+{-# LANGUAGE DeriveDataTypeable, EmptyDataDecls, ForeignFunctionInterface #-}+-- |+-- Module : Data.Text.ICU.Convert.Internal+-- Copyright : (c) Bryan O'Sullivan 2009+--+-- License : BSD-style+-- Maintainer : bos@serpentine.com+-- Stability : experimental+-- Portability : GHC+--+-- Low-level character set types and functions.++module Data.Text.ICU.Convert.Internal+ (+ Converter(..)+ , UConverter+ , getName+ , withConverter+ ) where++import Data.Text.ICU.Error.Internal (UErrorCode, handleError)+import Data.Typeable (Typeable)+import Foreign.C.String (CString, peekCString)+import Foreign.ForeignPtr (ForeignPtr, withForeignPtr)+import Foreign.Ptr (Ptr)+import System.IO.Unsafe (unsafePerformIO)++data UConverter++-- | Character set converter type. /Note/: this structure is not+-- thread safe. It is /not/ safe to use value of this type+-- simultaneously from multiple threads.+data Converter = Converter {-# UNPACK #-} !(ForeignPtr UConverter)+ deriving (Eq, Typeable)++instance Show Converter where+ show c = "Converter " ++ show (getName c)++withConverter :: Converter -> (Ptr UConverter -> IO a) -> IO a+{-# INLINE withConverter #-}+withConverter (Converter cnv) action = withForeignPtr cnv action++-- | Gets the internal, canonical name of the converter.+getName :: Converter -> String+getName cnv = unsafePerformIO .+ withConverter cnv $ \ptr ->+ peekCString =<< handleError (ucnv_getName ptr)++foreign import ccall unsafe "hs_text_icu.h __hs_ucnv_getName" ucnv_getName+ :: Ptr UConverter -> Ptr UErrorCode -> IO CString
− Data/Text/ICU/Converter.hs
@@ -1,235 +0,0 @@-{-# LANGUAGE CPP, ForeignFunctionInterface #-}--- |--- Module : Data.Text.ICU.Converter--- Copyright : (c) Bryan O'Sullivan 2009------ License : BSD-style--- Maintainer : bos@serpentine.com--- Stability : experimental--- Portability : GHC------ Character set conversion functions for Unicode, implemented as--- bindings to the International Components for Unicode (ICU)--- libraries.--module Data.Text.ICU.Converter- (- -- * Character set conversion- Converter- -- ** Basic functions- , open- , fromUnicode- , toUnicode- -- ** Converter metadata- , getName- , usesFallback- , setFallback- , isAmbiguous- -- * Functions for controlling global behavior- , getDefaultName- , setDefaultName- -- * Miscellaneous functions- , compareNames- , aliases- -- * Metadata- , converterNames- , standardNames- ) where--import Data.ByteString.Internal (ByteString, createAndTrim)-import Data.ByteString.Unsafe (unsafeUseAsCStringLen)-import Data.Int (Int32)-import Data.Text (Text)-import Data.Text.Foreign (fromPtr, lengthWord16, useAsPtr)-import Data.Text.ICU.Converter.Internal-import Data.Text.ICU.Error.Internal (UErrorCode, handleError)-import Data.Word (Word16)-import Foreign.C.String (CString, peekCString, withCString)-import Foreign.C.Types (CInt)-import Foreign.ForeignPtr (newForeignPtr)-import Foreign.Marshal.Array (allocaArray)-import Foreign.Ptr (FunPtr, Ptr, castPtr, nullPtr)-import System.IO.Unsafe (unsafePerformIO)-import Data.Text.ICU.Internal (UBool, UChar, asBool, asOrdering)---- | Do a fuzzy compare of two converter/alias names. The comparison--- is case-insensitive, ignores leading zeroes if they are not--- followed by further digits, and ignores all but letters and digits.--- Thus the strings @\"UTF-8\"@, @\"utf_8\"@, @\"u*T\@f08\"@ and--- @\"Utf 8\"@ are exactly equivalent. See section 1.4, Charset Alias--- Matching in Unicode Technical Standard #22 at--- <http://www.unicode.org/reports/tr22/>-compareNames :: String -> String -> Ordering-compareNames a b =- unsafePerformIO . withCString a $ \aptr ->- fmap asOrdering . withCString b $ ucnv_compareNames aptr---- | Create a 'Converter' with the name of a coded character set--- specified as a string. The actual name will be resolved with the--- alias file using a case-insensitive string comparison that ignores--- leading zeroes and all non-alphanumeric characters. E.g., the--- names @\"UTF8\"@, @\"utf-8\"@, @\"u*T\@f08\"@ and @\"Utf 8\"@ are--- all equivalent (see also 'compareNames'). If an empty string is--- passed for the converter name, it will create one with the--- 'getDefaultName' return value.------ A converter name may contain options like a locale specification to--- control the specific behavior of the newly instantiated converter.--- The meaning of the options depends on the particular converter. If--- an option is not defined for or recognized by a given converter,--- then it is ignored.------ Options are appended to the converter name string, with a comma--- between the name and the first option and also between adjacent--- options.------ If the alias is ambiguous, then the preferred converter is used.------ The conversion behavior and names can vary between platforms. ICU--- may convert some characters differently from other--- platforms. Details on this topic are in the ICU User's Guide at--- <http://icu-project.org/userguide/conversion.html>. Aliases--- starting with a @\"cp\"@ prefix have no specific meaning other than--- its an alias starting with the letters @\"cp\"@. Please do not--- associate any meaning to these aliases.-open :: String -> IO Converter-open name =- fmap Converter . newForeignPtr ucnv_close =<< named (handleError . ucnv_open)- where named act- | null name = act nullPtr- | otherwise = withCString name act---- | Convert the Unicode string into a codepage string using the given--- converter.-fromUnicode :: Converter -> Text -> IO ByteString-fromUnicode cnv t =- useAsPtr t $ \tptr tlen ->- withConverter cnv $ \cptr -> do- let capacity = fromIntegral . max_bytes_for_string cptr . fromIntegral $- lengthWord16 t- createAndTrim (fromIntegral capacity) $ \sptr ->- fmap fromIntegral . handleError $- ucnv_fromUChars cptr (castPtr sptr) capacity tptr (fromIntegral tlen)---- | Convert the codepage string into a Unicode string using the given--- converter.-toUnicode :: Converter -> ByteString -> IO Text-toUnicode cnv bs =- unsafeUseAsCStringLen bs $ \(sptr, slen) ->- withConverter cnv $ \cptr -> do- let capacity = slen * 2- allocaArray capacity $ \tptr -> - fromPtr tptr =<< (fmap fromIntegral . handleError $- ucnv_toUChars cptr tptr (fromIntegral capacity) sptr- (fromIntegral slen))---- | Determines whether the converter uses fallback mappings or not.--- This flag has restrictions; see 'setFallback'.-usesFallback :: Converter -> IO Bool-usesFallback cnv = asBool `fmap` withConverter cnv ucnv_usesFallback---- | Sets the converter to use fallback mappings or not. Regardless--- of this flag, the converter will always use fallbacks from Unicode--- Private Use code points, as well as reverse fallbacks (to Unicode).--- For details see \".ucm File Format\" in the Conversion Data chapter--- of the ICU User Guide:--- <http://www.icu-project.org/userguide/conversion-data.html#ucmformat>-setFallback :: Converter -> Bool -> IO ()-setFallback cnv flag =- withConverter cnv $ \p -> (ucnv_setFallback p (fromIntegral (fromEnum flag)))---- | Returns the current default converter name. If you want to 'open'--- a default converter, you do not need to use this function. It is--- faster to pass the empty string to 'open' the default converter.-getDefaultName :: IO String-getDefaultName = peekCString =<< ucnv_getDefaultName---- | Indicates whether the converter contains ambiguous mappings of--- the same character or not.-isAmbiguous :: Converter -> Bool-isAmbiguous cnv = asBool . unsafePerformIO $ withConverter cnv ucnv_isAmbiguous---- | Sets the current default converter name. If this function needs--- to be called, it should be called during application--- initialization. Most of the time, the results from 'getDefaultName'--- or 'open' with an empty string argument is sufficient for your--- application.------ /Note/: this function is not thread safe. /Do not/ call this--- function when /any/ ICU function is being used from more than one--- thread!-setDefaultName :: String -> IO ()-setDefaultName s = withCString s $ ucnv_setDefaultName---- | A list of the canonical names of all available converters.-converterNames :: [String]-{-# NOINLINE converterNames #-}-converterNames = unsafePerformIO $- mapM ((peekCString =<<) . ucnv_getAvailableName) [0..ucnv_countAvailable-1]---- | The list of supported standard names.-standardNames :: [String]-{-# NOINLINE standardNames #-}-standardNames = filter (not . null) . unsafePerformIO $- mapM ((peekCString =<<) . handleError . ucnv_getStandard) [0..ucnv_countStandards-1]---- | Return the aliases for a given converter or alias name.-aliases :: String -> [String]-aliases name = unsafePerformIO . withCString name $ \ptr -> do- count <- ucnv_countAliases ptr- if count == 0- then return []- else mapM ((peekCString =<<) . handleError . ucnv_getAlias ptr) [0..count-1]--foreign import ccall unsafe "hs_text_icu.h __hs_ucnv_open" ucnv_open- :: CString -> Ptr UErrorCode -> IO (Ptr UConverter)--foreign import ccall unsafe "hs_text_icu.h &__hs_ucnv_close" ucnv_close- :: FunPtr (Ptr UConverter -> IO ())--foreign import ccall unsafe "__get_max_bytes_for_string" max_bytes_for_string- :: Ptr UConverter -> CInt -> CInt--foreign import ccall unsafe "hs_text_icu.h __hs_ucnv_toUChars" ucnv_toUChars- :: Ptr UConverter -> Ptr UChar -> Int32 -> CString -> Int32- -> Ptr UErrorCode -> IO Int32--foreign import ccall unsafe "hs_text_icu.h __hs_ucnv_fromUChars" ucnv_fromUChars- :: Ptr UConverter -> CString -> Int32 -> Ptr UChar -> Int32- -> Ptr UErrorCode -> IO Int32--foreign import ccall unsafe "hs_text_icu.h __hs_ucnv_compareNames" ucnv_compareNames- :: CString -> CString -> IO CInt--foreign import ccall unsafe "hs_text_icu.h __hs_ucnv_getDefaultName" ucnv_getDefaultName- :: IO CString--foreign import ccall unsafe "hs_text_icu.h __hs_ucnv_setDefaultName" ucnv_setDefaultName- :: CString -> IO ()--foreign import ccall unsafe "hs_text_icu.h __hs_ucnv_countAvailable" ucnv_countAvailable- :: Int32--foreign import ccall unsafe "hs_text_icu.h __hs_ucnv_getAvailableName" ucnv_getAvailableName- :: Int32 -> IO CString--foreign import ccall unsafe "hs_text_icu.h __hs_ucnv_countAliases" ucnv_countAliases- :: CString -> IO Word16--foreign import ccall unsafe "hs_text_icu.h __hs_ucnv_getAlias" ucnv_getAlias- :: CString -> Word16 -> Ptr UErrorCode -> IO CString--foreign import ccall unsafe "hs_text_icu.h __hs_ucnv_countStandards" ucnv_countStandards- :: Word16--foreign import ccall unsafe "hs_text_icu.h __hs_ucnv_getStandard" ucnv_getStandard- :: Word16 -> Ptr UErrorCode -> IO CString--foreign import ccall unsafe "hs_text_icu.h __hs_ucnv_usesFallback" ucnv_usesFallback- :: Ptr UConverter -> IO UBool--foreign import ccall unsafe "hs_text_icu.h __hs_ucnv_setFallback" ucnv_setFallback- :: Ptr UConverter -> UBool -> IO ()--foreign import ccall unsafe "hs_text_icu.h __hs_ucnv_isAmbiguous" ucnv_isAmbiguous- :: Ptr UConverter -> IO UBool
− Data/Text/ICU/Converter/Internal.hs
@@ -1,50 +0,0 @@-{-# LANGUAGE DeriveDataTypeable, EmptyDataDecls, ForeignFunctionInterface #-}--- |--- Module : Data.Text.ICU.Converter.Internal--- Copyright : (c) Bryan O'Sullivan 2009------ License : BSD-style--- Maintainer : bos@serpentine.com--- Stability : experimental--- Portability : GHC------ Low-level character set types and functions.--module Data.Text.ICU.Converter.Internal- (- Converter(..)- , UConverter- , getName- , withConverter- ) where--import Data.Text.ICU.Error.Internal (UErrorCode, handleError)-import Data.Typeable (Typeable)-import Foreign.C.String (CString, peekCString)-import Foreign.ForeignPtr (ForeignPtr, withForeignPtr)-import Foreign.Ptr (Ptr)-import System.IO.Unsafe (unsafePerformIO)--data UConverter---- | Character set converter type. /Note/: this structure is not--- thread safe. It is /not/ safe to use value of this type--- simultaneously from multiple threads.-data Converter = Converter {-# UNPACK #-} !(ForeignPtr UConverter)- deriving (Eq, Typeable)--instance Show Converter where- show c = "Converter " ++ show (getName c)--withConverter :: Converter -> (Ptr UConverter -> IO a) -> IO a-{-# INLINE withConverter #-}-withConverter (Converter cnv) action = withForeignPtr cnv action---- | Gets the internal, canonical name of the converter.-getName :: Converter -> String-getName cnv = unsafePerformIO .- withConverter cnv $ \ptr ->- peekCString =<< handleError (ucnv_getName ptr)--foreign import ccall unsafe "hs_text_icu.h __hs_ucnv_getName" ucnv_getName- :: Ptr UConverter -> Ptr UErrorCode -> IO CString
Data/Text/ICU/Error/Internal.hs view
@@ -15,13 +15,13 @@ , withError ) where -import Control.Exception-import Foreign.Ptr-import Foreign.Marshal.Alloc+import Control.Exception (Exception, throw)+import Foreign.Ptr (Ptr)+import Foreign.Marshal.Alloc (alloca) import Data.Typeable (Typeable) import Foreign.C.String (CString, peekCString) import Foreign.C.Types (CInt)-import Foreign.Storable+import Foreign.Storable (peek, poke) import System.IO.Unsafe (unsafePerformIO) type UErrorCode = CInt
+ Data/Text/ICU/Normalize.hsc view
@@ -0,0 +1,308 @@+{-# LANGUAGE CPP, DeriveDataTypeable, ForeignFunctionInterface,+ GeneralizedNewtypeDeriving #-}+-- |+-- Module : Data.Text.ICU.Normalize+-- Copyright : (c) Bryan O'Sullivan 2009+--+-- License : BSD-style+-- Maintainer : bos@serpentine.com+-- Stability : experimental+-- Portability : GHC+--+-- Character set normalization functions for Unicode, implemented as+-- bindings to the International Components for Unicode (ICU)+-- libraries.++module Data.Text.ICU.Normalize+ (+ -- * Unicode normalization API+ -- $api+ NormalizationMode(..)+ -- * Normalization functions+ , normalize+ -- * Normalization checks+ , NormalizationCheckResult(..)+ , quickCheck+ , isNormalized+ -- * Normalization-sensitive comparison+ , CompareOption(..)+ , compare+ ) where++#ifdef mingw32_HOST_OS+#define U_HAVE_INTTYPES_H 1+#endif++#include <unicode/uchar.h>+#include <unicode/unorm.h>++import Control.Exception (throw)+import Control.Monad (when)+import Data.Text (Text)+import Data.Text.Foreign (fromPtr, useAsPtr)+import Data.Text.ICU.Error (u_BUFFER_OVERFLOW_ERROR)+import Data.Text.ICU.Error.Internal (UErrorCode, isFailure, handleError, withError)+import Data.Text.ICU.Internal (UBool, UChar, asBool, asOrdering)+import Data.Typeable (Typeable)+import Data.Int (Int32)+import Data.Word (Word32)+import Foreign.C.Types (CInt)+import Foreign.Marshal.Array (allocaArray)+import Foreign.Ptr (Ptr)+import System.IO.Unsafe (unsafePerformIO)+import Prelude hiding (compare)+import Data.List (foldl')+import Data.Bits ((.|.))++-- $api+--+-- 'normalize' transforms Unicode text into an equivalent composed or+-- decomposed form, allowing for easier sorting and searching of text.+-- 'normalize' supports the standard normalization forms described in+-- <http://www.unicode.org/unicode/reports/tr15/>,+-- Unicode Standard Annex #15: Unicode Normalization Forms.+--+-- Characters with accents or other adornments can be encoded in+-- several different ways in Unicode. For example, take the character A-acute.+-- In Unicode, this can be encoded as a single character (the+-- \"composed\" form):+--+-- @+-- 00C1 LATIN CAPITAL LETTER A WITH ACUTE+-- @+--+-- or as two separate characters (the \"decomposed\" form):+--+-- @+-- 0041 LATIN CAPITAL LETTER A+-- 0301 COMBINING ACUTE ACCENT+-- @+--+-- To a user of your program, however, both of these sequences should+-- be treated as the same \"user-level\" character \"A with acute+-- accent\". When you are searching or comparing text, you must+-- ensure that these two sequences are treated equivalently. In+-- addition, you must handle characters with more than one accent.+-- Sometimes the order of a character's combining accents is+-- significant, while in other cases accent sequences in different+-- orders are really equivalent.+--+-- Similarly, the string \"ffi\" can be encoded as three separate letters:+--+-- @+-- 0066 LATIN SMALL LETTER F+-- 0066 LATIN SMALL LETTER F+-- 0069 LATIN SMALL LETTER I+-- @+--+-- or as the single character+--+-- @+-- FB03 LATIN SMALL LIGATURE FFI+-- @+--+-- The \"ffi\" ligature is not a distinct semantic character, and+-- strictly speaking it shouldn't be in Unicode at all, but it was+-- included for compatibility with existing character sets that+-- already provided it. The Unicode standard identifies such+-- characters by giving them \"compatibility\" decompositions into the+-- corresponding semantic characters. When sorting and searching, you+-- will often want to use these mappings.+--+-- 'normalize' helps solve these problems by transforming text into+-- the canonical composed and decomposed forms as shown in the first+-- example above. In addition, you can have it perform compatibility+-- decompositions so that you can treat compatibility characters the+-- same as their equivalents. Finally, 'normalize' rearranges accents+-- into the proper canonical order, so that you do not have to worry+-- about accent rearrangement on your own.+--+-- Form 'FCD', \"Fast C or D\", is also designed for collation. It+-- allows to work on strings that are not necessarily normalized with+-- an algorithm (like in collation) that works under \"canonical+-- closure\", i.e., it treats precomposed characters and their+-- decomposed equivalents the same.+--+-- It is not a normalization form because it does not provide for+-- uniqueness of representation. Multiple strings may be canonically+-- equivalent (their NFDs are identical) and may all conform to 'FCD'+-- without being identical themselves.+--+-- The form is defined such that the \"raw decomposition\", the+-- recursive canonical decomposition of each character, results in a+-- string that is canonically ordered. This means that precomposed+-- characters are allowed for as long as their decompositions do not+-- need canonical reordering.+--+-- Its advantage for a process like collation is that all 'NFD' and+-- most 'NFC' texts - and many unnormalized texts - already conform to+-- 'FCD' and do not need to be normalized ('NFD') for such a+-- process. The 'FCD' 'quickCheck' will return 'Yes' for most strings+-- in practice.+--+-- @'normalize' 'FCD'@ may be implemented with 'NFD'.+--+-- For more details on 'FCD' see the collation design document:+-- <http://source.icu-project.org/repos/icu/icuhtml/trunk/design/collation/ICU_collation_design.htm>+--+-- ICU collation performs either 'NFD' or 'FCD' normalization+-- automatically if normalization is turned on for the collator+-- object. Beyond collation and string search, normalized strings may+-- be useful for string equivalence comparisons,+-- transliteration/transcription, unique representations, etc.+--+-- The W3C generally recommends to exchange texts in 'NFC'. Note also+-- that most legacy character encodings use only precomposed forms and+-- often do not encode any combining marks by themselves. For+-- conversion to such character encodings the Unicode text needs to be+-- normalized to 'NFC'. For more usage examples, see the Unicode+-- Standard Annex.++type UCompareOption = Word32++-- | Options to 'compare'.+data CompareOption = InputIsFCD+ -- ^ The caller knows that both strings fulfill the+ -- 'FCD' conditions. If not set, 'compare' will+ -- 'quickCheck' for 'FCD' and normalize if+ -- necessary.+ | CompareCodePointOrder+ -- ^ Choose code point order instead of code unit+ -- order.+ | CompareIgnoreCase+ -- ^ Compare strings case-insensitively using case+ -- folding, instead of case-sensitively. If set,+ -- then the following case folding options are+ -- used.+ | FoldCaseExcludeSpecialI+ -- ^ When case folding, exclude the special I+ -- character. For use with Turkic+ -- (Turkish/Azerbaijani) text data.+ deriving (Eq, Show, Enum, Typeable)++fromCompareOption :: CompareOption -> UCompareOption+fromCompareOption InputIsFCD = #const UNORM_INPUT_IS_FCD+fromCompareOption CompareCodePointOrder = #const U_COMPARE_CODE_POINT_ORDER+fromCompareOption CompareIgnoreCase = #const U_COMPARE_IGNORE_CASE+fromCompareOption FoldCaseExcludeSpecialI = #const U_FOLD_CASE_EXCLUDE_SPECIAL_I++reduceCompareOptions :: [CompareOption] -> UCompareOption+reduceCompareOptions = foldl' orO (#const U_FOLD_CASE_DEFAULT)+ where a `orO` b = a .|. fromCompareOption b++type UNormalizationMode = CInt++-- | Normalization modes.+data NormalizationMode+ = None -- ^ No decomposition/composition.+ | NFD -- ^ Canonical decomposition.+ | NFKD -- ^ Compatibility decomposition.+ | NFC -- ^ Canonical decomposition followed by canonical composition.+ | NFKC -- ^ Compatibility decomposition followed by canonical composition.+ | FCD -- ^ \"Fast C or D\" form.+ deriving (Eq, Show, Enum, Typeable)+ +toNM :: NormalizationMode -> UNormalizationMode+toNM None = #const UNORM_NONE+toNM NFD = #const UNORM_NFD+toNM NFKD = #const UNORM_NFKD+toNM NFC = #const UNORM_NFC+toNM NFKC = #const UNORM_NFKC+toNM FCD = #const UNORM_FCD++type UNormalizationCheckResult = CInt++-- | Result of a fast normalization check using 'quickCheck'.+data NormalizationCheckResult+ = No -- ^ Text is not normalized.+ | Perhaps -- ^ It cannot be determined whether text is in normalized + -- form without further thorough checks.+ | Yes -- ^ Text is in normalized form.+ deriving (Eq, Show, Enum, Typeable)+ +toNCR :: UNormalizationCheckResult -> NormalizationCheckResult+toNCR (#const UNORM_NO) = No+toNCR (#const UNORM_MAYBE) = Perhaps+toNCR (#const UNORM_YES) = Yes+toNCR _ = error "toNormalizationCheckResult"++-- | Normalize a string according the specified normalization mode.+normalize :: NormalizationMode -> Text -> Text+normalize mode t = unsafePerformIO . useAsPtr t $ \sptr slen ->+ let slen' = fromIntegral slen+ mode' = toNM mode+ loop dlen =+ (either loop return =<<) .+ allocaArray dlen $ \dptr -> do+ (err, newLen) <- withError $+ unorm_normalize sptr slen' mode' 0 dptr (fromIntegral dlen)+ when (isFailure err && err /= u_BUFFER_OVERFLOW_ERROR) $+ throw err+ let newLen' = fromIntegral newLen+ if newLen' > dlen+ then return (Left newLen')+ else Right `fmap` fromPtr dptr newLen'+ in loop slen+ + +-- | Perform an efficient check on a string, to quickly determine if+-- the string is in a particular normalization format.+--+-- A 'Perhaps' result indicates that a more thorough check is+-- required, e.g. with 'isNormalized'. The user may have to put the+-- string in its normalized form and compare the results.+quickCheck :: NormalizationMode -> Text -> NormalizationCheckResult+quickCheck mode t =+ unsafePerformIO . useAsPtr t $ \ptr len ->+ fmap toNCR . handleError $ unorm_quickCheck ptr (fromIntegral len)+ (toNM mode)++-- | Indicate whether a string is in a given normalization form.+--+-- Unlike 'quickCheck', this function returns a definitive result.+-- For 'NFD', 'NFKD', and 'FCD' normalization forms, both functions+-- work in exactly the same ways. For 'NFC' and 'NFKC' forms, where+-- 'quickCheck' may return 'Perhaps', this function will perform+-- further tests to arrive at a definitive result.+isNormalized :: NormalizationMode -> Text -> Bool+isNormalized mode t =+ unsafePerformIO . useAsPtr t $ \ptr len ->+ fmap asBool . handleError $ unorm_isNormalized ptr (fromIntegral len)+ (toNM mode)++-- | Compare two strings for canonical equivalence. Further options+-- include case-insensitive comparison and code point order (as+-- opposed to code unit order).+--+-- Canonical equivalence between two strings is defined as their+-- normalized forms ('NFD' or 'NFC') being identical. This function+-- compares strings incrementally instead of normalizing (and+-- optionally case-folding) both strings entirely, improving+-- performance significantly.+--+-- Bulk normalization is only necessary if the strings do not fulfill+-- the FCD conditions. Only in this case, and only if the strings are+-- relatively long, is memory allocated temporarily. For FCD strings+-- and short non-FCD strings there is no memory allocation.+compare :: [CompareOption] -> Text -> Text -> Ordering+compare opts a b = unsafePerformIO .+ useAsPtr a $ \aptr alen ->+ useAsPtr b $ \bptr blen ->+ fmap asOrdering . handleError $+ unorm_compare aptr (fromIntegral alen) bptr (fromIntegral blen)+ (reduceCompareOptions opts)++foreign import ccall unsafe "hs_text_icu.h __hs_unorm_compare" unorm_compare+ :: Ptr UChar -> Int32 -> Ptr UChar -> Int32 -> Word32+ -> Ptr UErrorCode -> IO Int32++foreign import ccall unsafe "hs_text_icu.h __hs_unorm_quickCheck" unorm_quickCheck+ :: Ptr UChar -> Int32 -> UNormalizationMode -> Ptr UErrorCode+ -> IO UNormalizationCheckResult++foreign import ccall unsafe "hs_text_icu.h __hs_unorm_isNormalized" unorm_isNormalized+ :: Ptr UChar -> Int32 -> UNormalizationMode -> Ptr UErrorCode -> IO UBool++foreign import ccall unsafe "hs_text_icu.h __hs_unorm_normalize" unorm_normalize+ :: Ptr UChar -> Int32 -> UNormalizationMode -> Int32+ -> Ptr UChar -> Int32 -> Ptr UErrorCode -> IO Int32
− Data/Text/ICU/Normalizer.hsc
@@ -1,303 +0,0 @@-{-# LANGUAGE CPP, DeriveDataTypeable, ForeignFunctionInterface,- GeneralizedNewtypeDeriving #-}--- |--- Module : Data.Text.ICU.Normalizer--- Copyright : (c) Bryan O'Sullivan 2009------ License : BSD-style--- Maintainer : bos@serpentine.com--- Stability : experimental--- Portability : GHC------ Character set normalization functions for Unicode, implemented as--- bindings to the International Components for Unicode (ICU)--- libraries.--module Data.Text.ICU.Normalizer- (- -- * Unicode normalization API- -- $api- NormalizationMode(..)- -- * Normalization functions- , normalize- -- * Normalization checks- , NormalizationCheckResult(..)- , quickCheck- , isNormalized- -- * Normalization-sensitive comparison- , CompareOption- , u_INPUT_IS_FCD- , u_COMPARE_CODE_POINT_ORDER- , u_COMPARE_IGNORE_CASE- , compare- ) where--#ifdef mingw32_HOST_OS-#define U_HAVE_INTTYPES_H 1-#endif--#include <unicode/unorm.h>--import Control.Exception (throw)-import Control.Monad (when)-import Data.Text (Text)-import Data.Text.Foreign (fromPtr, useAsPtr)-import Data.Text.ICU.Error (u_BUFFER_OVERFLOW_ERROR)-import Data.Text.ICU.Error.Internal (UErrorCode, isFailure, handleError, withError)-import Data.Text.ICU.Internal (UBool, UChar, asBool, asOrdering)-import Data.Typeable (Typeable)-import Data.Int (Int32)-import Data.Word (Word32)-import Foreign.C.Types (CInt)-import Foreign.Marshal.Array (allocaArray)-import Foreign.Ptr (Ptr)-import System.IO.Unsafe (unsafePerformIO)-import Prelude hiding (compare)-import Data.List (foldl')-import Data.Bits ((.|.))---- $api------ 'normalize' transforms Unicode text into an equivalent composed or--- decomposed form, allowing for easier sorting and searching of text.--- 'normalize' supports the standard normalization forms described in--- <http://www.unicode.org/unicode/reports/tr15/>,--- Unicode Standard Annex #15: Unicode Normalization Forms.------ Characters with accents or other adornments can be encoded in--- several different ways in Unicode. For example, take the character A-acute.--- In Unicode, this can be encoded as a single character (the--- \"composed\" form):------ @--- 00C1 LATIN CAPITAL LETTER A WITH ACUTE--- @------ or as two separate characters (the \"decomposed\" form):------ @--- 0041 LATIN CAPITAL LETTER A--- 0301 COMBINING ACUTE ACCENT--- @------ To a user of your program, however, both of these sequences should--- be treated as the same \"user-level\" character \"A with acute--- accent\". When you are searching or comparing text, you must--- ensure that these two sequences are treated equivalently. In--- addition, you must handle characters with more than one accent.--- Sometimes the order of a character's combining accents is--- significant, while in other cases accent sequences in different--- orders are really equivalent.------ Similarly, the string \"ffi\" can be encoded as three separate letters:------ @--- 0066 LATIN SMALL LETTER F--- 0066 LATIN SMALL LETTER F--- 0069 LATIN SMALL LETTER I--- @------ or as the single character------ @--- FB03 LATIN SMALL LIGATURE FFI--- @------ The \"ffi\" ligature is not a distinct semantic character, and--- strictly speaking it shouldn't be in Unicode at all, but it was--- included for compatibility with existing character sets that--- already provided it. The Unicode standard identifies such--- characters by giving them \"compatibility\" decompositions into the--- corresponding semantic characters. When sorting and searching, you--- will often want to use these mappings.------ 'normalize' helps solve these problems by transforming text into--- the canonical composed and decomposed forms as shown in the first--- example above. In addition, you can have it perform compatibility--- decompositions so that you can treat compatibility characters the--- same as their equivalents. Finally, 'normalize' rearranges accents--- into the proper canonical order, so that you do not have to worry--- about accent rearrangement on your own.------ Form 'FCD', \"Fast C or D\", is also designed for collation. It--- allows to work on strings that are not necessarily normalized with--- an algorithm (like in collation) that works under \"canonical--- closure\", i.e., it treats precomposed characters and their--- decomposed equivalents the same.------ It is not a normalization form because it does not provide for--- uniqueness of representation. Multiple strings may be canonically--- equivalent (their NFDs are identical) and may all conform to 'FCD'--- without being identical themselves.------ The form is defined such that the \"raw decomposition\", the--- recursive canonical decomposition of each character, results in a--- string that is canonically ordered. This means that precomposed--- characters are allowed for as long as their decompositions do not--- need canonical reordering.------ Its advantage for a process like collation is that all 'NFD' and--- most 'NFC' texts - and many unnormalized texts - already conform to--- 'FCD' and do not need to be normalized ('NFD') for such a--- process. The 'FCD' 'quickCheck' will return 'Yes' for most strings--- in practice.------ @'normalize' 'FCD'@ may be implemented with 'NFD'.------ For more details on 'FCD' see the collation design document:--- <http://source.icu-project.org/repos/icu/icuhtml/trunk/design/collation/ICU_collation_design.htm>------ ICU collation performs either 'NFD' or 'FCD' normalization--- automatically if normalization is turned on for the collator--- object. Beyond collation and string search, normalized strings may--- be useful for string equivalence comparisons,--- transliteration/transcription, unique representations, etc.------ The W3C generally recommends to exchange texts in 'NFC'. Note also--- that most legacy character encodings use only precomposed forms and--- often do not encode any combining marks by themselves. For--- conversion to such character encodings the Unicode text needs to be--- normalized to 'NFC'. For more usage examples, see the Unicode--- Standard Annex.--newtype CompareOption = CompareOption {- fromCompareOption :: Word32- } deriving (Eq, Typeable)--foldCompareOptions :: [CompareOption] -> Word32-foldCompareOptions = foldl' orO 0- where a `orO` b = a .|. fromCompareOption b--#{enum CompareOption, CompareOption,- u_INPUT_IS_FCD = UNORM_INPUT_IS_FCD,- u_COMPARE_CODE_POINT_ORDER = U_COMPARE_CODE_POINT_ORDER,- u_COMPARE_IGNORE_CASE = U_COMPARE_IGNORE_CASE- }--type UNormalizationMode = CInt--data NormalizationMode- = None -- ^ No decomposition/composition.- | NFD -- ^ Canonical decomposition.- | NFKD -- ^ Compatibility decomposition.- | NFC -- ^ Canonical decomposition followed by canonical composition.- | NFKC -- ^ Compatibility decomposition followed by canonical composition.- | FCD -- ^ \"Fast C or D\" form.- deriving (Eq, Show, Enum, Typeable)- -toNM :: NormalizationMode -> UNormalizationMode-toNM None = #const UNORM_NONE-toNM NFD = #const UNORM_NFD-toNM NFKD = #const UNORM_NFKD-toNM NFC = #const UNORM_NFC-toNM NFKC = #const UNORM_NFKC-toNM FCD = #const UNORM_FCD--type UNormalizationCheckResult = CInt---- | Result of a fast normalization check using 'quickCheck'.-data NormalizationCheckResult- = No -- ^ Text is not normalized.- | Perhaps -- ^ It cannot be determined whether text is in normalized - -- form without further thorough checks.- | Yes -- ^ Text is in normalized form.- deriving (Eq, Show, Enum, Typeable)- -toNCR :: UNormalizationCheckResult -> NormalizationCheckResult-toNCR (#const UNORM_NO) = No-toNCR (#const UNORM_MAYBE) = Perhaps-toNCR (#const UNORM_YES) = Yes-toNCR _ = error "toNormalizationCheckResult"---- | Normalize a string according the specified normalization mode.-normalize :: NormalizationMode -> Text -> Text-normalize mode t = unsafePerformIO . useAsPtr t $ \sptr slen ->- let slen' = fromIntegral slen- mode' = toNM mode- loop dlen =- (either loop return =<<) .- allocaArray dlen $ \dptr -> do- (err, newLen) <- withError $- unorm_normalize sptr slen' mode' 0 dptr (fromIntegral dlen)- when (isFailure err && err /= u_BUFFER_OVERFLOW_ERROR) $- throw err- let newLen' = fromIntegral newLen- if newLen' > dlen- then return (Left newLen')- else Right `fmap` fromPtr dptr newLen'- in loop slen- - --- | Perform an efficient check on a string, to quickly determine if--- the string is in a particular normalization format.------ A 'Perhaps' result indicates that a more thorough check is--- required, e.g. with 'isNormalized'. The user may have to put the--- string in its normalized form and compare the results.-quickCheck :: NormalizationMode -> Text -> NormalizationCheckResult-quickCheck mode t =- unsafePerformIO . useAsPtr t $ \ptr len ->- fmap toNCR . handleError $ unorm_quickCheck ptr (fromIntegral len)- (toNM mode)---- | Indicate whether a string is in a given normalization form.------ Unlike 'quickCheck', this function returns a definitive result.--- For 'NFD', 'NFKD', and 'FCD' normalization forms, both functions--- work in exactly the same ways. For 'NFC' and 'NFKC' forms, where--- 'quickCheck' may return 'Perhaps', this function will perform--- further tests to arrive at a definitive result.-isNormalized :: NormalizationMode -> Text -> Bool-isNormalized mode t =- unsafePerformIO . useAsPtr t $ \ptr len ->- fmap asBool . handleError $ unorm_isNormalized ptr (fromIntegral len)- (toNM mode)---- | Compare two strings for canonical equivalence.--- Further options include case-insensitive comparison and--- code point order (as opposed to code unit order).------ Canonical equivalence between two strings is defined as their normalized--- forms (NFD or NFC) being identical.--- This function compares strings incrementally instead of normalizing--- (and optionally case-folding) both strings entirely,--- improving performance significantly.------ Bulk normalization is only necessary if the strings do not fulfill the FCD--- conditions. Only in this case, and only if the strings are relatively long,--- is memory allocated temporarily.--- For FCD strings and short non-FCD strings there is no memory allocation.------ Options:------ ['u_INPUT_IS_FCD'] Set if the caller knows that both strings fulfill the FCD conditions.--- If not set, the function will 'quickCheck' for FCD--- and normalize if necessary.------ ['u_COMPARE_CODE_POINT_ORDER'] Set to choose code point order instead of code unit order.------ ['u_COMPARE_IGNORE_CASE'] Set to compare strings case-insensitively using case folding,--- instead of case-sensitively.--- If set, then the following case folding options are used.-compare :: [CompareOption] -> Text -> Text -> Ordering-compare opts a b = unsafePerformIO .- useAsPtr a $ \aptr alen ->- useAsPtr b $ \bptr blen ->- fmap asOrdering . handleError $- unorm_compare aptr (fromIntegral alen) bptr (fromIntegral blen)- (foldCompareOptions opts)--foreign import ccall unsafe "hs_text_icu.h __hs_unorm_compare" unorm_compare- :: Ptr UChar -> Int32 -> Ptr UChar -> Int32 -> Word32- -> Ptr UErrorCode -> IO Int32--foreign import ccall unsafe "hs_text_icu.h __hs_unorm_quickCheck" unorm_quickCheck- :: Ptr UChar -> Int32 -> UNormalizationMode -> Ptr UErrorCode- -> IO UNormalizationCheckResult--foreign import ccall unsafe "hs_text_icu.h __hs_unorm_isNormalized" unorm_isNormalized- :: Ptr UChar -> Int32 -> UNormalizationMode -> Ptr UErrorCode -> IO UBool--foreign import ccall unsafe "hs_text_icu.h __hs_unorm_normalize" unorm_normalize- :: Ptr UChar -> Int32 -> UNormalizationMode -> Int32- -> Ptr UChar -> Int32 -> Ptr UErrorCode -> IO Int32
text-icu.cabal view
@@ -1,5 +1,5 @@ name: text-icu-version: 0.2.0.0+version: 0.3.0.0 synopsis: Bindings to the ICU library description: Haskell bindings to the International Components for Unicode (ICU) libraries. These libraries provide@@ -21,11 +21,11 @@ build-depends: base >= 4 exposed-modules:- Data.Text.ICU.Converter+ Data.Text.ICU.Convert Data.Text.ICU.Error- Data.Text.ICU.Normalizer+ Data.Text.ICU.Normalize other-modules:- Data.Text.ICU.Converter.Internal+ Data.Text.ICU.Convert.Internal Data.Text.ICU.Error.Internal Data.Text.ICU.Internal c-sources: cbits/text_icu.c