packages feed

text-icu (empty) → 0.1

raw patch · 11 files changed

+1065/−0 lines, 11 filesdep +basedep +bytestringdep +textsetup-changed

Dependencies added: base, bytestring, text

Files

+ Data/Text/ICU/Converter.hs view
@@ -0,0 +1,235 @@+{-# 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 "unicode/ucnv.h ucnv_open_4_0" ucnv_open+    :: CString -> Ptr UErrorCode -> IO (Ptr UConverter)++foreign import ccall unsafe "unicode/ucnv.h &ucnv_close_4_0" 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 "unicode/ucnv.h ucnv_toUChars_4_0" ucnv_toUChars+    :: Ptr UConverter -> Ptr UChar -> Int32 -> CString -> Int32+    -> Ptr UErrorCode -> IO Int32++foreign import ccall unsafe "unicode/ucnv.h ucnv_fromUChars_4_0" ucnv_fromUChars+    :: Ptr UConverter -> CString -> Int32 -> Ptr UChar -> Int32+    -> Ptr UErrorCode -> IO Int32++foreign import ccall unsafe "unicode/ucnv.h ucnv_compareNames_4_0" ucnv_compareNames+    :: CString -> CString -> IO CInt++foreign import ccall unsafe "unicode/ucnv.h ucnv_getDefaultName_4_0" ucnv_getDefaultName+    :: IO CString++foreign import ccall unsafe "unicode/ucnv.h ucnv_setDefaultName_4_0" ucnv_setDefaultName+    :: CString -> IO ()++foreign import ccall unsafe "unicode/ucnv.h ucnv_countAvailable_4_0" ucnv_countAvailable+    :: Int32++foreign import ccall unsafe "unicode/ucnv.h ucnv_getAvailableName_4_0" ucnv_getAvailableName+    :: Int32 -> IO CString++foreign import ccall unsafe "unicode/ucnv.h ucnv_countAliases_4_0" ucnv_countAliases+    :: CString -> IO Word16++foreign import ccall unsafe "unicode/ucnv.h ucnv_getAlias_4_0" ucnv_getAlias+    :: CString -> Word16 -> Ptr UErrorCode -> IO CString++foreign import ccall unsafe "unicode/ucnv.h ucnv_countStandards_4_0" ucnv_countStandards+    :: Word16++foreign import ccall unsafe "unicode/ucnv.h ucnv_getStandard_4_0" ucnv_getStandard+    :: Word16 -> Ptr UErrorCode -> IO CString++foreign import ccall unsafe "unicode/ucnv.h ucnv_usesFallback_4_0" ucnv_usesFallback+    :: Ptr UConverter -> IO UBool++foreign import ccall unsafe "unicode/ucnv.h ucnv_setFallback_4_0" ucnv_setFallback+    :: Ptr UConverter -> UBool -> IO ()++foreign import ccall unsafe "unicode/ucnv.h ucnv_isAmbiguous_4_0" ucnv_isAmbiguous+    :: Ptr UConverter -> IO UBool
+ Data/Text/ICU/Converter/Internal.hs view
@@ -0,0 +1,50 @@+{-# 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 "unicode/ucnv.h ucnv_getName_4_0" ucnv_getName+    :: Ptr UConverter -> Ptr UErrorCode -> IO CString
+ Data/Text/ICU/Error.hsc view
@@ -0,0 +1,275 @@+module Data.Text.ICU.Error+    (+     -- * Types+     ErrorCode,++     -- * Functions+     isSuccess,+     isFailure,+     errorName,++     -- * Warnings+     u_USING_FALLBACK_WARNING,+     u_USING_DEFAULT_WARNING,+     u_SAFECLONE_ALLOCATED_WARNING,+     u_STATE_OLD_WARNING,+     u_STRING_NOT_TERMINATED_WARNING,+     u_SORT_KEY_TOO_SHORT_WARNING,+     u_AMBIGUOUS_ALIAS_WARNING,+     u_DIFFERENT_UCA_VERSION,++     -- * Errors+     u_ILLEGAL_ARGUMENT_ERROR,+     u_MISSING_RESOURCE_ERROR,+     u_INVALID_FORMAT_ERROR,+     u_FILE_ACCESS_ERROR,+     u_INTERNAL_PROGRAM_ERROR,+     u_MESSAGE_PARSE_ERROR,+     u_MEMORY_ALLOCATION_ERROR,+     u_INDEX_OUTOFBOUNDS_ERROR,+     u_PARSE_ERROR,+     u_INVALID_CHAR_FOUND,+     u_TRUNCATED_CHAR_FOUND,+     u_ILLEGAL_CHAR_FOUND,+     u_INVALID_TABLE_FORMAT,+     u_INVALID_TABLE_FILE,+     u_BUFFER_OVERFLOW_ERROR,+     u_UNSUPPORTED_ERROR,+     u_RESOURCE_TYPE_MISMATCH,+     u_ILLEGAL_ESCAPE_SEQUENCE,+     u_UNSUPPORTED_ESCAPE_SEQUENCE,+     u_NO_SPACE_AVAILABLE,+     u_CE_NOT_FOUND_ERROR,+     u_PRIMARY_TOO_LONG_ERROR,+     u_STATE_TOO_OLD_ERROR,+     u_TOO_MANY_ALIASES_ERROR,+     u_ENUM_OUT_OF_SYNC_ERROR,+     u_INVARIANT_CONVERSION_ERROR,+     u_INVALID_STATE_ERROR,+     u_COLLATOR_VERSION_MISMATCH,+     u_USELESS_COLLATOR_ERROR,+     u_NO_WRITE_PERMISSION,++     -- ** Transliterator errors+     u_BAD_VARIABLE_DEFINITION,+     u_MALFORMED_RULE,+     u_MALFORMED_SET,+     u_MALFORMED_UNICODE_ESCAPE,+     u_MALFORMED_VARIABLE_DEFINITION,+     u_MALFORMED_VARIABLE_REFERENCE,+     u_MISPLACED_CURSOR_OFFSET,+     u_MISPLACED_QUANTIFIER,+     u_MISSING_OPERATOR,+     u_MULTIPLE_ANTE_CONTEXTS,+     u_MULTIPLE_CURSORS,+     u_MULTIPLE_POST_CONTEXTS,+     u_TRAILING_BACKSLASH,+     u_UNDEFINED_SEGMENT_REFERENCE,+     u_UNDEFINED_VARIABLE,+     u_UNQUOTED_SPECIAL,+     u_UNTERMINATED_QUOTE,+     u_RULE_MASK_ERROR,+     u_MISPLACED_COMPOUND_FILTER,+     u_MULTIPLE_COMPOUND_FILTERS,+     u_INVALID_RBT_SYNTAX,+     u_MALFORMED_PRAGMA,+     u_UNCLOSED_SEGMENT,+     u_VARIABLE_RANGE_EXHAUSTED,+     u_VARIABLE_RANGE_OVERLAP,+     u_ILLEGAL_CHARACTER,+     u_INTERNAL_TRANSLITERATOR_ERROR,+     u_INVALID_ID,+     u_INVALID_FUNCTION,++     -- ** Formatting API parsing errors+     u_UNEXPECTED_TOKEN,+     u_MULTIPLE_DECIMAL_SEPARATORS,+     u_MULTIPLE_EXPONENTIAL_SYMBOLS,+     u_MALFORMED_EXPONENTIAL_PATTERN,+     u_MULTIPLE_PERCENT_SYMBOLS,+     u_MULTIPLE_PERMILL_SYMBOLS,+     u_MULTIPLE_PAD_SPECIFIERS,+     u_PATTERN_SYNTAX_ERROR,+     u_ILLEGAL_PAD_POSITION,+     u_UNMATCHED_BRACES,+     u_ARGUMENT_TYPE_MISMATCH,+     u_DUPLICATE_KEYWORD,+     u_UNDEFINED_KEYWORD,+     u_DEFAULT_KEYWORD_MISSING,++     -- ** Break iterator errors+     u_BRK_INTERNAL_ERROR,+     u_BRK_HEX_DIGITS_EXPECTED,+     u_BRK_SEMICOLON_EXPECTED,+     u_BRK_RULE_SYNTAX,+     u_BRK_UNCLOSED_SET,+     u_BRK_ASSIGN_ERROR,+     u_BRK_VARIABLE_REDFINITION,+     u_BRK_MISMATCHED_PAREN,+     u_BRK_NEW_LINE_IN_QUOTED_STRING,+     u_BRK_UNDEFINED_VARIABLE,+     u_BRK_INIT_ERROR,+     u_BRK_RULE_EMPTY_SET,+     u_BRK_UNRECOGNIZED_OPTION,+     u_BRK_MALFORMED_RULE_TAG,++     -- ** Regular expression errors+     u_REGEX_INTERNAL_ERROR,+     u_REGEX_RULE_SYNTAX,+     u_REGEX_INVALID_STATE,+     u_REGEX_BAD_ESCAPE_SEQUENCE,+     u_REGEX_PROPERTY_SYNTAX,+     u_REGEX_UNIMPLEMENTED,+     u_REGEX_MISMATCHED_PAREN,+     u_REGEX_NUMBER_TOO_BIG,+     u_REGEX_BAD_INTERVAL,+     u_REGEX_MAX_LT_MIN,+     u_REGEX_INVALID_BACK_REF,+     u_REGEX_INVALID_FLAG,+     u_REGEX_SET_CONTAINS_STRING,+     u_REGEX_OCTAL_TOO_BIG,+     u_REGEX_INVALID_RANGE,+     u_REGEX_STACK_OVERFLOW,+     u_REGEX_TIME_OUT,+     u_REGEX_STOPPED_BY_CALLER,++     -- ** IDNA errors+     u_IDNA_PROHIBITED_ERROR,+     u_IDNA_UNASSIGNED_ERROR,+     u_IDNA_CHECK_BIDI_ERROR,+     u_IDNA_STD3_ASCII_RULES_ERROR,+     u_IDNA_ACE_PREFIX_ERROR,+     u_IDNA_VERIFICATION_ERROR,+     u_IDNA_LABEL_TOO_LONG_ERROR,+     u_IDNA_ZERO_LENGTH_LABEL_ERROR,+     u_IDNA_DOMAIN_NAME_TOO_LONG_ERROR+    ) where++#include <unicode/utypes.h>++import Data.Text.ICU.Error.Internal++#{enum ErrorCode, ErrorCode,+  u_USING_FALLBACK_WARNING = U_USING_FALLBACK_WARNING,+  u_USING_DEFAULT_WARNING = U_USING_DEFAULT_WARNING,   +  u_SAFECLONE_ALLOCATED_WARNING = U_SAFECLONE_ALLOCATED_WARNING, +  u_STATE_OLD_WARNING = U_STATE_OLD_WARNING,   +  u_STRING_NOT_TERMINATED_WARNING = U_STRING_NOT_TERMINATED_WARNING,+  u_SORT_KEY_TOO_SHORT_WARNING = U_SORT_KEY_TOO_SHORT_WARNING, +  u_AMBIGUOUS_ALIAS_WARNING = U_AMBIGUOUS_ALIAS_WARNING,   +  u_DIFFERENT_UCA_VERSION = U_DIFFERENT_UCA_VERSION,     +  u_ILLEGAL_ARGUMENT_ERROR = U_ILLEGAL_ARGUMENT_ERROR,     +  u_MISSING_RESOURCE_ERROR = U_MISSING_RESOURCE_ERROR,     +  u_INVALID_FORMAT_ERROR = U_INVALID_FORMAT_ERROR,     +  u_FILE_ACCESS_ERROR = U_FILE_ACCESS_ERROR,     +  u_INTERNAL_PROGRAM_ERROR = U_INTERNAL_PROGRAM_ERROR,     +  u_MESSAGE_PARSE_ERROR = U_MESSAGE_PARSE_ERROR,     +  u_MEMORY_ALLOCATION_ERROR = U_MEMORY_ALLOCATION_ERROR,     +  u_INDEX_OUTOFBOUNDS_ERROR = U_INDEX_OUTOFBOUNDS_ERROR,     +  u_PARSE_ERROR = U_PARSE_ERROR,     +  u_INVALID_CHAR_FOUND = U_INVALID_CHAR_FOUND,     +  u_TRUNCATED_CHAR_FOUND = U_TRUNCATED_CHAR_FOUND,     +  u_ILLEGAL_CHAR_FOUND = U_ILLEGAL_CHAR_FOUND,     +  u_INVALID_TABLE_FORMAT = U_INVALID_TABLE_FORMAT,     +  u_INVALID_TABLE_FILE = U_INVALID_TABLE_FILE,     +  u_BUFFER_OVERFLOW_ERROR = U_BUFFER_OVERFLOW_ERROR,     +  u_UNSUPPORTED_ERROR = U_UNSUPPORTED_ERROR,     +  u_RESOURCE_TYPE_MISMATCH = U_RESOURCE_TYPE_MISMATCH,     +  u_ILLEGAL_ESCAPE_SEQUENCE = U_ILLEGAL_ESCAPE_SEQUENCE,     +  u_UNSUPPORTED_ESCAPE_SEQUENCE = U_UNSUPPORTED_ESCAPE_SEQUENCE, +  u_NO_SPACE_AVAILABLE = U_NO_SPACE_AVAILABLE,     +  u_CE_NOT_FOUND_ERROR = U_CE_NOT_FOUND_ERROR,     +  u_PRIMARY_TOO_LONG_ERROR = U_PRIMARY_TOO_LONG_ERROR,     +  u_STATE_TOO_OLD_ERROR = U_STATE_TOO_OLD_ERROR,     +  u_TOO_MANY_ALIASES_ERROR = U_TOO_MANY_ALIASES_ERROR,     +  u_ENUM_OUT_OF_SYNC_ERROR = U_ENUM_OUT_OF_SYNC_ERROR,     +  u_INVARIANT_CONVERSION_ERROR = U_INVARIANT_CONVERSION_ERROR,  +  u_INVALID_STATE_ERROR = U_INVALID_STATE_ERROR,     +  u_COLLATOR_VERSION_MISMATCH = U_COLLATOR_VERSION_MISMATCH,   +  u_USELESS_COLLATOR_ERROR = U_USELESS_COLLATOR_ERROR,     +  u_NO_WRITE_PERMISSION = U_NO_WRITE_PERMISSION,     +  u_BAD_VARIABLE_DEFINITION = U_BAD_VARIABLE_DEFINITION,+  u_MALFORMED_RULE = U_MALFORMED_RULE,+  u_MALFORMED_SET = U_MALFORMED_SET,+  u_MALFORMED_UNICODE_ESCAPE = U_MALFORMED_UNICODE_ESCAPE,+  u_MALFORMED_VARIABLE_DEFINITION = U_MALFORMED_VARIABLE_DEFINITION,+  u_MALFORMED_VARIABLE_REFERENCE = U_MALFORMED_VARIABLE_REFERENCE,+  u_MISPLACED_CURSOR_OFFSET = U_MISPLACED_CURSOR_OFFSET,+  u_MISPLACED_QUANTIFIER = U_MISPLACED_QUANTIFIER,+  u_MISSING_OPERATOR = U_MISSING_OPERATOR,+  u_MULTIPLE_ANTE_CONTEXTS = U_MULTIPLE_ANTE_CONTEXTS,+  u_MULTIPLE_CURSORS = U_MULTIPLE_CURSORS,+  u_MULTIPLE_POST_CONTEXTS = U_MULTIPLE_POST_CONTEXTS,+  u_TRAILING_BACKSLASH = U_TRAILING_BACKSLASH,+  u_UNDEFINED_SEGMENT_REFERENCE = U_UNDEFINED_SEGMENT_REFERENCE,+  u_UNDEFINED_VARIABLE = U_UNDEFINED_VARIABLE,+  u_UNQUOTED_SPECIAL = U_UNQUOTED_SPECIAL,+  u_UNTERMINATED_QUOTE = U_UNTERMINATED_QUOTE,+  u_RULE_MASK_ERROR = U_RULE_MASK_ERROR,+  u_MISPLACED_COMPOUND_FILTER = U_MISPLACED_COMPOUND_FILTER,+  u_MULTIPLE_COMPOUND_FILTERS = U_MULTIPLE_COMPOUND_FILTERS,+  u_INVALID_RBT_SYNTAX = U_INVALID_RBT_SYNTAX,+  u_MALFORMED_PRAGMA = U_MALFORMED_PRAGMA,+  u_UNCLOSED_SEGMENT = U_UNCLOSED_SEGMENT,+  u_VARIABLE_RANGE_EXHAUSTED = U_VARIABLE_RANGE_EXHAUSTED,+  u_VARIABLE_RANGE_OVERLAP = U_VARIABLE_RANGE_OVERLAP,+  u_ILLEGAL_CHARACTER = U_ILLEGAL_CHARACTER,+  u_INTERNAL_TRANSLITERATOR_ERROR = U_INTERNAL_TRANSLITERATOR_ERROR,+  u_INVALID_ID = U_INVALID_ID,+  u_INVALID_FUNCTION = U_INVALID_FUNCTION,+  u_UNEXPECTED_TOKEN = U_UNEXPECTED_TOKEN,       +  u_MULTIPLE_DECIMAL_SEPARATORS = U_MULTIPLE_DECIMAL_SEPARATORS,+  u_MULTIPLE_EXPONENTIAL_SYMBOLS = U_MULTIPLE_EXPONENTIAL_SYMBOLS,+  u_MALFORMED_EXPONENTIAL_PATTERN = U_MALFORMED_EXPONENTIAL_PATTERN,+  u_MULTIPLE_PERCENT_SYMBOLS = U_MULTIPLE_PERCENT_SYMBOLS,+  u_MULTIPLE_PERMILL_SYMBOLS = U_MULTIPLE_PERMILL_SYMBOLS,+  u_MULTIPLE_PAD_SPECIFIERS = U_MULTIPLE_PAD_SPECIFIERS,+  u_PATTERN_SYNTAX_ERROR = U_PATTERN_SYNTAX_ERROR,+  u_ILLEGAL_PAD_POSITION = U_ILLEGAL_PAD_POSITION,+  u_UNMATCHED_BRACES = U_UNMATCHED_BRACES,+  u_ARGUMENT_TYPE_MISMATCH = U_ARGUMENT_TYPE_MISMATCH,+  u_DUPLICATE_KEYWORD = U_DUPLICATE_KEYWORD,+  u_UNDEFINED_KEYWORD = U_UNDEFINED_KEYWORD,+  u_DEFAULT_KEYWORD_MISSING = U_DEFAULT_KEYWORD_MISSING,+  u_BRK_INTERNAL_ERROR = U_BRK_INTERNAL_ERROR,          +  u_BRK_HEX_DIGITS_EXPECTED = U_BRK_HEX_DIGITS_EXPECTED,+  u_BRK_SEMICOLON_EXPECTED = U_BRK_SEMICOLON_EXPECTED,+  u_BRK_RULE_SYNTAX = U_BRK_RULE_SYNTAX,+  u_BRK_UNCLOSED_SET = U_BRK_UNCLOSED_SET,+  u_BRK_ASSIGN_ERROR = U_BRK_ASSIGN_ERROR,+  u_BRK_VARIABLE_REDFINITION = U_BRK_VARIABLE_REDFINITION,+  u_BRK_MISMATCHED_PAREN = U_BRK_MISMATCHED_PAREN,+  u_BRK_NEW_LINE_IN_QUOTED_STRING = U_BRK_NEW_LINE_IN_QUOTED_STRING,+  u_BRK_UNDEFINED_VARIABLE = U_BRK_UNDEFINED_VARIABLE,+  u_BRK_INIT_ERROR = U_BRK_INIT_ERROR,+  u_BRK_RULE_EMPTY_SET = U_BRK_RULE_EMPTY_SET,+  u_BRK_UNRECOGNIZED_OPTION = U_BRK_UNRECOGNIZED_OPTION,+  u_BRK_MALFORMED_RULE_TAG = U_BRK_MALFORMED_RULE_TAG,+  u_REGEX_INTERNAL_ERROR = U_REGEX_INTERNAL_ERROR,       +  u_REGEX_RULE_SYNTAX = U_REGEX_RULE_SYNTAX,+  u_REGEX_INVALID_STATE = U_REGEX_INVALID_STATE,+  u_REGEX_BAD_ESCAPE_SEQUENCE = U_REGEX_BAD_ESCAPE_SEQUENCE,+  u_REGEX_PROPERTY_SYNTAX = U_REGEX_PROPERTY_SYNTAX,+  u_REGEX_UNIMPLEMENTED = U_REGEX_UNIMPLEMENTED,+  u_REGEX_MISMATCHED_PAREN = U_REGEX_MISMATCHED_PAREN,+  u_REGEX_NUMBER_TOO_BIG = U_REGEX_NUMBER_TOO_BIG,+  u_REGEX_BAD_INTERVAL = U_REGEX_BAD_INTERVAL,+  u_REGEX_MAX_LT_MIN = U_REGEX_MAX_LT_MIN,+  u_REGEX_INVALID_BACK_REF = U_REGEX_INVALID_BACK_REF,+  u_REGEX_INVALID_FLAG = U_REGEX_INVALID_FLAG,+  u_REGEX_SET_CONTAINS_STRING = U_REGEX_SET_CONTAINS_STRING,+  u_REGEX_OCTAL_TOO_BIG = U_REGEX_OCTAL_TOO_BIG,+  u_REGEX_INVALID_RANGE = U_REGEX_INVALID_RANGE,+  u_REGEX_STACK_OVERFLOW = U_REGEX_STACK_OVERFLOW,+  u_REGEX_TIME_OUT = U_REGEX_TIME_OUT,+  u_REGEX_STOPPED_BY_CALLER = U_REGEX_STOPPED_BY_CALLER,+  u_IDNA_PROHIBITED_ERROR = U_IDNA_PROHIBITED_ERROR,+  u_IDNA_UNASSIGNED_ERROR = U_IDNA_UNASSIGNED_ERROR,+  u_IDNA_CHECK_BIDI_ERROR = U_IDNA_CHECK_BIDI_ERROR,+  u_IDNA_STD3_ASCII_RULES_ERROR = U_IDNA_STD3_ASCII_RULES_ERROR,+  u_IDNA_ACE_PREFIX_ERROR = U_IDNA_ACE_PREFIX_ERROR,+  u_IDNA_VERIFICATION_ERROR = U_IDNA_VERIFICATION_ERROR,+  u_IDNA_LABEL_TOO_LONG_ERROR = U_IDNA_LABEL_TOO_LONG_ERROR,+  u_IDNA_ZERO_LENGTH_LABEL_ERROR = U_IDNA_ZERO_LENGTH_LABEL_ERROR,+  u_IDNA_DOMAIN_NAME_TOO_LONG_ERROR = U_IDNA_DOMAIN_NAME_TOO_LONG_ERROR+}
+ Data/Text/ICU/Error/Internal.hs view
@@ -0,0 +1,80 @@+{-# LANGUAGE DeriveDataTypeable, ForeignFunctionInterface #-}++module Data.Text.ICU.Error.Internal+    (+    -- * Types+      ErrorCode(..)+    -- ** Low-level types+    , UErrorCode+    -- * Functions+    , isFailure+    , isSuccess+    , errorName+    , handleError+    , throwOnError+    , withError+    ) where++import Control.Exception+import Foreign.Ptr+import Foreign.Marshal.Alloc+import Data.Typeable (Typeable)+import Foreign.C.String (CString, peekCString)+import Foreign.C.Types (CInt)+import Foreign.Storable+import System.IO.Unsafe (unsafePerformIO)++type UErrorCode = CInt++-- | ICU error code.+newtype ErrorCode = ErrorCode {+      fromErrorCode :: UErrorCode+    } deriving (Eq, Typeable)++instance Show ErrorCode where+    show code = "ErrorCode " ++ errorName code++instance Exception ErrorCode++-- | Indicate whether the given error code is a success.+isSuccess :: ErrorCode -> Bool+{-# INLINE isSuccess #-}+isSuccess = (<= 0) . fromErrorCode++-- | Indicate whether the given error code is a failure.+isFailure :: ErrorCode -> Bool+{-# INLINE isFailure #-}+isFailure = (> 0) . fromErrorCode++-- | Throw an exception if the given code is actually an error.+throwOnError :: UErrorCode -> IO ()+{-# INLINE throwOnError #-}+throwOnError code = do+  let err = (ErrorCode code)+  if isFailure err+    then throw err+    else return ()++withError :: (Ptr UErrorCode -> IO a) -> IO (ErrorCode, a)+{-# INLINE withError #-}+withError action = alloca $ \errPtr -> do+                     poke errPtr 0+                     ret <- action errPtr+                     err <- peek errPtr+                     return (ErrorCode err, ret)++handleError :: (Ptr UErrorCode -> IO a) -> IO a+{-# INLINE handleError #-}+handleError action = alloca $ \errPtr -> do+                       poke errPtr 0+                       ret <- action errPtr+                       throwOnError =<< peek errPtr+                       return ret++-- | Return a string representing the name of the given error code.+errorName :: ErrorCode -> String+errorName code = unsafePerformIO $+                 peekCString (u_errorName (fromErrorCode code))++foreign import ccall unsafe "unicode/utypes.h u_errorName_4_0" u_errorName+    :: UErrorCode -> CString
+ Data/Text/ICU/Internal.hs view
@@ -0,0 +1,24 @@+module Data.Text.ICU.Internal+    (+      UBool+    , UChar+    , asBool+    , asOrdering+    ) where++import Data.Int (Int8)+import Data.Word (Word16)++type UBool = Int8+type UChar = Word16++asBool :: Integral a => a -> Bool+{-# INLINE asBool #-}+asBool = (/=0)++asOrdering :: Integral a => a -> Ordering+{-# INLINE asOrdering #-}+asOrdering i+    | i < 0     = LT+    | i == 0    = EQ+    | otherwise = GT
+ Data/Text/ICU/Normalizer.hsc view
@@ -0,0 +1,298 @@+{-# 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++#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++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 "unicode/unorm.h unorm_compare_4_0" unorm_compare+    :: Ptr UChar -> Int32 -> Ptr UChar -> Int32 -> Word32+    -> Ptr UErrorCode -> IO Int32++foreign import ccall unsafe "unicode/unorm.h unorm_quickCheck_4_0" unorm_quickCheck+    :: Ptr UChar -> Int32 -> UNormalizationMode -> Ptr UErrorCode+    -> IO UNormalizationCheckResult++foreign import ccall unsafe "unicode/unorm.h unorm_isNormalized_4_0" unorm_isNormalized+    :: Ptr UChar -> Int32 -> UNormalizationMode -> Ptr UErrorCode -> IO UBool++foreign import ccall unsafe "unicode/unorm.h unorm_normalize_4_0" unorm_normalize+    :: Ptr UChar -> Int32 -> UNormalizationMode -> Int32+    -> Ptr UChar -> Int32 -> Ptr UErrorCode -> IO Int32
+ LICENSE view
@@ -0,0 +1,26 @@+Copyright (c) 2009, Bryan O'Sullivan+All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions+are met:++    * Redistributions of source code must retain the above copyright+      notice, this list of conditions and the following disclaimer.++    * Redistributions in binary form must reproduce the above+      copyright notice, this list of conditions and the following+      disclaimer in the documentation and/or other materials provided+      with the distribution.++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ README view
@@ -0,0 +1,31 @@+Text-ICU: Comprehensive support for string manipulation+-------------------------------------------------------++This package provides the Data.Text.ICU library, for performing+complex manipulation of Unicode text.  It provides features such as+the following:++- Unicode normalization+- Conversion to and from many common and obscure encodings+++Prerequisites+-------------++This library is implemented as bindings to the well-respected ICU+library, which is not included.  The version of ICU currently+supported is 4.0.++http://www.icu-project.org/+++Source code+-----------++darcs get http://darcs.serpentine.com/text-icu+++Authors+-------++This library was written by Bryan O'Sullivan.
+ Setup.lhs view
@@ -0,0 +1,3 @@+#!/usr/bin/env runhaskell+> import Distribution.Simple+> main = defaultMain
+ cbits/text_icu.c view
@@ -0,0 +1,8 @@+#include "unicode/ucnv.h"++#include <stdint.h>++int __get_max_bytes_for_string(UConverter *cnv, int src_length)+{+    return UCNV_GET_MAX_BYTES_FOR_STRING(src_length, ucnv_getMaxCharSize(cnv));+}
+ text-icu.cabal view
@@ -0,0 +1,35 @@+name:           text-icu+version:        0.1+synopsis:       Bindings to the ICU library+description:    Haskell bindings to the International Components for+                Unicode (ICU) libraries.  These libraries provide+                robust and full-featured Unicode services on a wide+                variety of platforms.+maintainer:     Bryan O'Sullivan <bos@serpentine.com>+copyright:      2009 Bryan O'Sullivan+category:       Data, Text+license:        BSD3+license-file:   LICENSE+build-type:     Simple+cabal-version:  >= 1.2+extra-source-files: README++library+  build-depends:     base < 5, bytestring, text+  if impl(ghc >= 6.10)+    build-depends:   base >= 4++  exposed-modules:+      Data.Text.ICU.Converter+      Data.Text.ICU.Error+      Data.Text.ICU.Normalizer+  other-modules:+      Data.Text.ICU.Converter.Internal+      Data.Text.ICU.Error.Internal+      Data.Text.ICU.Internal+  c-sources: cbits/text_icu.c+  extra-libraries: icui18n icuuc icudata++  ghc-options: -Wall+  if impl(ghc >= 6.8)+    ghc-options: -fwarn-tabs