packages feed

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 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