packages feed

text-icu 0.6.0.1 → 0.6.2.1

raw patch · 13 files changed

+1062/−159 lines, 13 filesdep ~text

Dependency ranges changed: text

Files

Data/Text/ICU.hs view
@@ -62,6 +62,28 @@     , collateIter     , sortKey     , uca+    -- * Regular expressions+    , MatchOption(..)+    , ParseError(errError, errLine, errOffset)+    , Match+    , Regex+    , Regular+    -- ** Construction+    , regex+    , regex'+    -- ** Inspection+    , pattern+    -- ** Searching+    , find+    , findAll+    -- ** Match groups+    -- $group+    , groupCount+    , unfold+    , span+    , group+    , prefix+    , suffix     ) where  import Data.Text.ICU.Break.Pure@@ -69,6 +91,7 @@ import Data.Text.ICU.Internal import Data.Text.ICU.Iterator import Data.Text.ICU.Normalize+import Data.Text.ICU.Regex.Pure import Data.Text.ICU.Text #if defined(__HADDOCK__) import Data.Text.Foreign@@ -129,3 +152,9 @@ -- For the impure collation API (which is richer, but less easy to -- use than the pure API), see the 'Data.Text.ICU.Collate' -- module.++-- $group+--+-- Capturing groups are numbered starting from zero.  Group zero is+-- always the entire matching text.  Groups greater than zero contain+-- the text matching each capturing group in a regular expression.
Data/Text/ICU/Error.hsc view
@@ -11,15 +11,19 @@ -- Unicode (ICU) libraries. -- -- Most ICU functions can throw an 'ICUError' value as an exception.+-- Some can additionally throw a 'ParseError', if more detailed error+-- information is necessary. module Data.Text.ICU.Error     (      -- * Types      ICUError,+     ParseError(errError, errLine, errOffset),       -- * Functions      isSuccess,      isFailure,      errorName,+     isRegexError,       -- * Warnings      u_USING_FALLBACK_WARNING,@@ -168,43 +172,43 @@  #{enum ICUError, ICUError,   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_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_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,@@ -234,7 +238,7 @@   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_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,@@ -248,7 +252,7 @@   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_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,@@ -262,7 +266,7 @@   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_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,@@ -290,3 +294,7 @@   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 }++isRegexError :: ICUError -> Bool+isRegexError (ICUError err) =+    err >= #{const U_REGEX_ERROR_START} && err < #{const U_REGEX_ERROR_LIMIT}
− Data/Text/ICU/Error/Internal.hs
@@ -1,80 +0,0 @@-{-# LANGUAGE DeriveDataTypeable, ForeignFunctionInterface #-}--module Data.Text.ICU.Error.Internal-    (-    -- * Types-      ICUError(..)-    -- ** Low-level types-    , UErrorCode-    -- * Functions-    , isFailure-    , isSuccess-    , errorName-    , handleError-    , throwOnError-    , withError-    ) where--import Control.Exception (Exception, throw)-import Foreign.Ptr (Ptr)-import Foreign.Marshal.Utils (with)-import Data.Typeable (Typeable)-import Foreign.C.String (CString, peekCString)-import Foreign.C.Types (CInt)-import Foreign.Storable (peek)-import System.IO.Unsafe (unsafePerformIO)--type UErrorCode = CInt---- | ICU error type.  This is an instance of the 'Exception' type--- class.  A value of this type may be thrown as an exception by most--- ICU functions.-newtype ICUError = ICUError {-      fromErrorCode :: UErrorCode-    } deriving (Eq, Typeable)--instance Show ICUError where-    show code = "ICUError " ++ errorName code--instance Exception ICUError---- | Indicate whether the given error code is a success.-isSuccess :: ICUError -> Bool-{-# INLINE isSuccess #-}-isSuccess = (<= 0) . fromErrorCode---- | Indicate whether the given error code is a failure.-isFailure :: ICUError -> 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 = (ICUError code)-  if isFailure err-    then throw err-    else return ()--withError :: (Ptr UErrorCode -> IO a) -> IO (ICUError, a)-{-# INLINE withError #-}-withError action = with 0 $ \errPtr -> do-                     ret <- action errPtr-                     err <- peek errPtr-                     return (ICUError err, ret)--handleError :: (Ptr UErrorCode -> IO a) -> IO a-{-# INLINE handleError #-}-handleError action = with 0 $ \errPtr -> do-                       ret <- action errPtr-                       throwOnError =<< peek errPtr-                       return ret---- | Return a string representing the name of the given error code.-errorName :: ICUError -> String-errorName code = unsafePerformIO $-                 peekCString (u_errorName (fromErrorCode code))--foreign import ccall unsafe "hs_text_icu.h __hs_u_errorName" u_errorName-    :: UErrorCode -> CString
+ Data/Text/ICU/Error/Internal.hsc view
@@ -0,0 +1,138 @@+{-# LANGUAGE DeriveDataTypeable, ForeignFunctionInterface,+    ScopedTypeVariables #-}++module Data.Text.ICU.Error.Internal+    (+    -- * Types+      ICUError(..)+    -- ** Low-level types+    , UErrorCode+    , ParseError(errError, errLine, errOffset)+    , UParseError+    -- * Functions+    , isFailure+    , isSuccess+    , errorName+    , handleError+    , handleParseError+    , throwOnError+    , withError+    ) where++import Control.Exception (Exception, throw)+import Foreign.Ptr (Ptr)+import Foreign.Marshal.Alloc (alloca)+import Foreign.Marshal.Utils (with)+import Data.Int (Int32)+import Data.Typeable (Typeable)+import Foreign.C.String (CString, peekCString)+import Foreign.C.Types (CInt)+import Foreign.Storable (Storable(..))+import System.IO.Unsafe (unsafePerformIO)++#include <unicode/parseerr.h>+#include <unicode/utypes.h>++type UErrorCode = CInt+    +-- | ICU error type.  This is an instance of the 'Exception' type+-- class.  A value of this type may be thrown as an exception by most+-- ICU functions.+newtype ICUError = ICUError {+      fromErrorCode :: UErrorCode+    } deriving (Eq, Typeable)++instance Show ICUError where+    show code = "ICUError " ++ errorName code++instance Exception ICUError++-- | Detailed information about parsing errors.  Used by ICU parsing+-- engines that parse long rules, patterns, or programs, where the+-- text being parsed is long enough that more information than an+-- 'ICUError' is needed to localize the error.+data ParseError = ParseError {+      errError :: ICUError+    , errLine :: !(Maybe Int)+    -- ^ The line on which the error occured.  If the parser uses this+    -- field, it sets it to the line number of the source text line on+    -- which the error appears, which will be be a positive value.  If+    -- the parser does not support line numbers, the value will be+    -- 'Nothing'.+    , errOffset :: !(Maybe Int)+    -- ^ The character offset to the error.  If the 'errLine' field is+    -- 'Just' some value, then this field contains the offset from the+    -- beginning of the line that contains the error.  Otherwise, it+    -- represents the offset from the start of the text.  If the+    -- parser does not support this field, it will have a value of+    -- 'Nothing'.+    } deriving (Show, Typeable)++type UParseError = ParseError++instance Exception ParseError++instance Storable ParseError where+    sizeOf _    = #{size UParseError}+    alignment _ = alignment (undefined :: CString)+    peek ptr = do+      (line::Int32) <- #{peek UParseError, line} ptr+      (offset::Int32) <- #{peek UParseError, offset} ptr+      let wrap k = if k == -1 then Nothing else Just $! fromIntegral k+      return $! ParseError undefined (wrap line) (wrap offset)++-- | Indicate whether the given error code is a success.+isSuccess :: ICUError -> Bool+{-# INLINE isSuccess #-}+isSuccess = (<= 0) . fromErrorCode++-- | Indicate whether the given error code is a failure.+isFailure :: ICUError -> 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 = (ICUError code)+  if isFailure err+    then throw err+    else return ()++withError :: (Ptr UErrorCode -> IO a) -> IO (ICUError, a)+{-# INLINE withError #-}+withError action = with 0 $ \errPtr -> do+                     ret <- action errPtr+                     err <- peek errPtr+                     return (ICUError err, ret)++handleError :: (Ptr UErrorCode -> IO a) -> IO a+{-# INLINE handleError #-}+handleError action = with 0 $ \errPtr -> do+                       ret <- action errPtr+                       throwOnError =<< peek errPtr+                       return ret++handleParseError :: (ICUError -> Bool)+                 -> (Ptr UParseError -> Ptr UErrorCode -> IO a) -> IO a+handleParseError isParseError action =+    with 0 $ \uerrPtr ->+      alloca $ \perrPtr -> do+        ret <- action perrPtr uerrPtr+        err <- ICUError `fmap` peek uerrPtr+        if isParseError err+          then do+            perr <- peek perrPtr+            throw perr { errError = err }+          else if isFailure err+               then throw err+               else return ret++-- | Return a string representing the name of the given error code.+errorName :: ICUError -> String+errorName code = unsafePerformIO $+                 peekCString (u_errorName (fromErrorCode code))++foreign import ccall unsafe "hs_text_icu.h __hs_u_errorName" u_errorName+    :: UErrorCode -> CString
+ Data/Text/ICU/Regex.hs view
@@ -0,0 +1,198 @@+{-# LANGUAGE BangPatterns, EmptyDataDecls, MagicHash, RecordWildCards,+    ScopedTypeVariables #-}+{-# OPTIONS_GHC -fno-warn-orphans #-}++-- |+-- Module      : Data.Text.ICU.Regex+-- Copyright   : (c) 2010 Bryan O'Sullivan+--+-- License     : BSD-style+-- Maintainer  : bos@serpentine.com+-- Stability   : experimental+-- Portability : GHC+--+-- Regular expression support for Unicode, implemented as bindings to+-- the International Components for Unicode (ICU) libraries.+--+-- The syntax and behaviour of ICU regular expressions are Perl-like.+-- For complete details, see the ICU User Guide entry at+-- <http://userguide.icu-project.org/strings/regexp>.+--+-- /Note/: The functions in this module are not thread safe.  For+-- thread safe use, see 'clone' below, or use the pure functions in+-- 'Data.Text.ICU'.++module Data.Text.ICU.Regex+    (+    -- * Types+      MatchOption(..)+    , ParseError(errError, errLine, errOffset)+    , Regex+    -- * Functions+    -- ** Construction+    , regex+    , regex'+    , clone+    -- ** Managing text to search+    , setText+    , getText+    -- ** Inspection+    , pattern+    -- ** Searching+    , find+    , findNext+    -- ** Match groups+    -- $groups+    , groupCount+    , start+    , end+    , start_+    , end_+    ) where++import Data.Text.ICU.Regex.Internal+import Control.Exception (catch)+import Data.IORef (newIORef, readIORef, writeIORef)+import Data.Text (Text)+import qualified Data.Text.Foreign as T+import Data.Text.Foreign (I16)+import Data.Text.ICU.Internal (asBool)+import Data.Text.ICU.Error.Internal (ParseError(..), handleError)+import Data.Word (Word16)+import Foreign.ForeignPtr (ForeignPtr, newForeignPtr, withForeignPtr)+import Foreign.Marshal.Alloc (alloca)+import Foreign.Storable (peek)+import Prelude hiding (catch)+import System.IO.Unsafe (unsafePerformIO)+                   +instance Show Regex where+    show re = "Regex " ++ show (pattern re)++-- $groups+--+-- Capturing groups are numbered starting from zero.  Group zero is+-- always the entire matching text.  Groups greater than zero contain+-- the text matching each capturing group in a regular expression.++-- | Compile a regular expression with the given options.  This is+-- safest to use when the pattern is constructed at run time.+regex' :: [MatchOption] -> Text -> IO (Either ParseError Regex)+regex' opts pat = (Right `fmap` regex opts pat) `catch` \(err::ParseError) ->+                  return (Left err)++-- | Set the subject text string upon which the regular expression+-- will look for matches.  This function may be called any number of+-- times, allowing the regular expression pattern to be applied to+-- different strings.+setText :: Regex -> Text -> IO ()+setText Regex{..} t = do+  (hayfp, hayLen) <- T.asForeignPtr t+  withForeignPtr reRe $ \rePtr ->+    withForeignPtr hayfp $ \hayPtr -> handleError $+      uregex_setText rePtr hayPtr (fromIntegral hayLen)+  writeIORef reText hayfp++-- | Get the subject text that is currently associated with this+-- regular expression object.+getText :: Regex -> IO (ForeignPtr Word16, I16)+getText Regex{..} =+  alloca $ \lenPtr -> do+    _ <- withForeignPtr reRe $ \rePtr -> handleError $+         uregex_getText rePtr lenPtr+    len <- peek lenPtr+    fp <- readIORef reText+    return (fp, fromIntegral len)++-- | Return the source form of the pattern used to construct this+-- regular expression or match.+pattern :: Regex -> Text+pattern Regex{..} = unsafePerformIO . withForeignPtr reRe $ \rePtr ->+  alloca $ \lenPtr -> do+    textPtr <- handleError $ uregex_pattern rePtr lenPtr+    (T.fromPtr textPtr . fromIntegral) =<< peek lenPtr++-- | Find the first matching substring of the input string that+-- matches the pattern.+--+-- If /n/ is non-negative, the search for a match begins at the+-- specified index, and any match region is reset.+--+-- If /n/ is -1, the search begins at the start of the input region,+-- or at the start of the full string if no region has been specified.+--+-- If a match is found, 'start', 'end', and 'group' will provide more+-- information regarding the match.+find :: Regex -> I16 -> IO Bool+find Regex{..} n =+    fmap asBool . withForeignPtr reRe $ \rePtr -> handleError $+    uregex_find rePtr (fromIntegral n)++-- | Find the next pattern match in the input string.  Begin searching+-- the input at the location following the end of he previous match,+-- or at the start of the string (or region) if there is no previous+-- match.+--+-- If a match is found, 'start', 'end', and 'group' will provide more+-- information regarding the match.+findNext :: Regex -> IO Bool+findNext Regex{..} =+    fmap asBool . withForeignPtr reRe $ handleError . uregex_findNext++-- | Make a copy of a compiled regular expression.  Cloning a regular+-- expression is faster than opening a second instance from the source+-- form of the expression, and requires less memory.+--+-- Note that the current input string and the position of any matched+-- text within it are not cloned; only the pattern itself and and the+-- match mode flags are copied.+--+-- Cloning can be particularly useful to threaded applications that+-- perform multiple match operations in parallel.  Each concurrent RE+-- operation requires its own instance of a 'Regex'.+clone :: Regex -> IO Regex+{-# INLINE clone #-}+clone Regex{..} = do+  fp <- newForeignPtr uregex_close =<< withForeignPtr reRe (handleError . uregex_clone)+  Regex fp `fmap` newIORef emptyForeignPtr++-- | Return the number of capturing groups in this regular+-- expression's pattern.+groupCount :: Regex -> IO Int+groupCount Regex{..} =+    fmap fromIntegral . withForeignPtr reRe $ handleError . uregex_groupCount++-- | Returns the index in the input string of the start of the text+-- matched by the specified capture group during the previous match+-- operation.  Returns @-1@ if the capture group was not part of the+-- last match.+start_ :: Regex -> Int -> IO I16+start_ Regex{..} n =+    fmap fromIntegral . withForeignPtr reRe $ \rePtr -> handleError $+    uregex_start rePtr (fromIntegral n)++-- | Returns the index in the input string of the end of the text+-- matched by the specified capture group during the previous match+-- operation.  Returns @-1@ if the capture group was not part of+-- the last match.+end_ :: Regex -> Int -> IO I16+end_ Regex{..} n =+  fmap fromIntegral . withForeignPtr reRe $ \rePtr -> handleError $+  uregex_end rePtr (fromIntegral n)++-- | Returns the index in the input string of the start of the text+-- matched by the specified capture group during the previous match+-- operation.  Returns 'Nothing' if the capture group was not part of+-- the last match.+start :: Regex -> Int -> IO (Maybe I16)+start r n = check `fmap` start_ r n++-- | Returns the index in the input string of the end of the text+-- matched by the specified capture group during the previous match+-- operation.  Returns 'Nothing' if the capture group was not part of+-- the last match.+end :: Regex -> Int -> IO (Maybe I16)+end r n = check `fmap` end_ r n++check :: I16 -> Maybe I16+check (-1) = Nothing+check k    = Just $! fromIntegral k
+ Data/Text/ICU/Regex/Internal.hsc view
@@ -0,0 +1,230 @@+{-# LANGUAGE BangPatterns, DeriveDataTypeable, EmptyDataDecls,+    ForeignFunctionInterface, MagicHash, RecordWildCards,+    ScopedTypeVariables #-}++-- |+-- Module      : Data.Text.ICU.Regex.Internal+-- Copyright   : (c) 2010 Bryan O'Sullivan+--+-- License     : BSD-style+-- Maintainer  : bos@serpentine.com+-- Stability   : experimental+-- Portability : GHC+--+-- Regular expression support for Unicode, implemented as bindings to+-- the International Components for Unicode (ICU) libraries.+--+-- The syntax and behaviour of ICU regular expressions are Perl-like.+-- For complete details, see the ICU User Guide entry at+-- <http://userguide.icu-project.org/strings/regexp>.++module Data.Text.ICU.Regex.Internal+    (+    -- * Types+      MatchOption(..)+    , Regex(..)+    , URegularExpression+    -- * Functions+    , emptyForeignPtr+    , regex+    , uregex_clone+    , uregex_close+    , uregex_end+    , uregex_find+    , uregex_findNext+    , uregex_getText+    , uregex_group+    , uregex_groupCount+    , uregex_pattern+    , uregex_setText+    , uregex_start+    ) where++import Control.Monad (when)+import Data.IORef (IORef, newIORef)+import Data.Int (Int32)+import Data.Text (Text)+import qualified Data.Text as T+import qualified Data.Text.Foreign as T+import Data.Text.ICU.Internal (UBool, UChar)+import Data.Text.ICU.Error (isRegexError)+import Data.Text.ICU.Error.Internal (UParseError, UErrorCode,+                                     handleError, handleParseError)+import Data.Typeable (Typeable)+import Data.Word (Word16, Word32)+import Foreign.ForeignPtr (ForeignPtr, newForeignPtr, touchForeignPtr)+import Foreign.Ptr (FunPtr, Ptr)+import Prelude hiding (catch)+import System.IO.Unsafe (unsafePerformIO)++#include <unicode/uregex.h>++-- | Options for controlling matching behaviour.+data MatchOption+    = CaseInsensitive+    -- ^ Enable case insensitive matching.+    | Comments+    -- ^ Allow comments and white space within patterns.+    | DotAll+    -- ^ If set, @\'.\'@ matches line terminators. Otherwise @\'.\'@+    -- matching stops at line end.+    | Literal+    -- ^ If set, treat the entire pattern as a literal string.+    --  Metacharacters or escape sequences in the input sequence will+    --  be given no special meaning.+    --+    --  The option 'CaseInsensitive' retains its meanings on matching+    --  when used in conjunction with this option.  Other options+    --  become superfluous.+    | Multiline+    -- ^ Control behaviour of @\'$\'@ and @\'^\'@. If set, recognize+    -- line terminators within string, Otherwise, match only at start+    -- and end of input string.+    | HaskellLines+    -- ^ Haskell-only line endings.  When this mode is enabled, only+    -- @\'\\n\'@ is recognized as a line ending in the behavior of+    -- @\'.\'@, @\'^\'@, and @\'$\'@.+    | UnicodeWord+    -- ^ Unicode word boundaries.  If set, @\'\\\\b\'@ uses the+    -- Unicode TR 29 definition of word boundaries.+    --+    -- /Warning/: Unicode word boundaries are quite different from+    -- traditional regular expression word boundaries.  See+    -- <http://unicode.org/reports/tr29/#Word_Boundaries>.+    | ErrorOnUnknownEscapes+    -- ^ Throw an error on unrecognized backslash escapes.  If set,+    -- fail with an error on patterns that contain backslash-escaped+    -- ASCII letters without a known special meaning.  If this flag is+    -- not set, these escaped letters represent themselves.+    | WorkLimit Int+    -- ^ Set a processing limit for match operations.+    --+    -- Some patterns, when matching certain strings, can run in+    -- exponential time.  For practical purposes, the match operation+    -- may appear to be in an infinite loop.  When a limit is set a+    -- match operation will fail with an error if the limit is+    -- exceeded.+    --+    -- The units of the limit are steps of the match engine.+    -- Correspondence with actual processor time will depend on the+    -- speed of the processor and the details of the specific pattern,+    -- but will typically be on the order of milliseconds.+    --+    -- By default, the matching time is not limited.+    | StackLimit Int+    -- ^ Set the amount of heap storage avaliable for use by the match+    -- backtracking stack.+    --+    -- ICU uses a backtracking regular expression engine, with the+    -- backtrack stack maintained on the heap.  This function sets the+    -- limit to the amount of memory that can be used for this+    -- purpose.  A backtracking stack overflow will result in an error+    -- from the match operation that caused it.+    --+    -- A limit is desirable because a malicious or poorly designed+    -- pattern can use excessive memory, potentially crashing the+    -- process.  A limit is enabled by default.+      deriving (Eq, Show, Typeable)++-- | A compiled regular expression.+--+-- 'Regex' values are usually constructed using the 'regex' or+-- 'regex'' functions.  This type is also an instance of 'IsString',+-- so if you have the @OverloadedStrings@ language extension enabled,+-- you can construct a 'Regex' by simply writing the pattern in+-- quotes (though this does not allow you to specify any 'Option's).+data Regex = Regex {+      reRe :: ForeignPtr URegularExpression+    , reText :: IORef (ForeignPtr Word16)+    }++emptyForeignPtr :: ForeignPtr Word16+emptyForeignPtr = unsafePerformIO $ fst `fmap` T.asForeignPtr T.empty+{-# NOINLINE emptyForeignPtr #-}++-- | Compile a regular expression with the given options.  This+-- function throws a 'ParseError' if the pattern is invalid.+regex :: [MatchOption] -> Text -> IO Regex+regex opts pat = T.useAsPtr pat $ \pptr plen -> do+  let (flags,workLimit,stackLimit) = toURegexpOpts opts+  ptr <- handleParseError isRegexError $+         uregex_open pptr (fromIntegral plen) flags+  fp <- newForeignPtr uregex_close ptr+  when (workLimit /= -1) .+    handleError $ uregex_setTimeLimit ptr (fromIntegral workLimit)+  when (stackLimit /= -1) .+    handleError $ uregex_setStackLimit ptr (fromIntegral stackLimit)+  touchForeignPtr fp+  Regex fp `fmap` newIORef emptyForeignPtr++data URegularExpression++type URegexpFlag = Word32++toURegexpOpts :: [MatchOption] -> (URegexpFlag,Int,Int)+toURegexpOpts = foldl go (0,-1,-1)+  where+    go (!flag,work,stack) opt = (flag+flag',work',stack')+     where+      flag' = case opt of+                CaseInsensitive       -> #const UREGEX_CASE_INSENSITIVE+                Comments              -> #const UREGEX_COMMENTS+                DotAll                -> #const UREGEX_DOTALL+                Literal               -> #const UREGEX_LITERAL+                Multiline             -> #const UREGEX_MULTILINE+                HaskellLines          -> #const UREGEX_UNIX_LINES+                UnicodeWord           -> #const UREGEX_UWORD+                ErrorOnUnknownEscapes -> #const UREGEX_ERROR_ON_UNKNOWN_ESCAPES+                _                     -> 0+      work' = case opt of+                WorkLimit limit       -> limit+                _                     -> work+      stack' = case opt of+                 StackLimit limit     -> limit+                 _                    -> stack++foreign import ccall unsafe "hs_text_icu.h __hs_uregex_open" uregex_open+    :: Ptr UChar -> Int32 -> Word32 -> Ptr UParseError -> Ptr UErrorCode+    -> IO (Ptr URegularExpression)++foreign import ccall unsafe "hs_text_icu.h &__hs_uregex_close" uregex_close+    :: FunPtr (Ptr URegularExpression -> IO ())++foreign import ccall unsafe "hs_text_icu.h __hs_uregex_clone" uregex_clone+    :: Ptr URegularExpression -> Ptr UErrorCode+    -> IO (Ptr URegularExpression)++foreign import ccall unsafe "hs_text_icu.h __hs_uregex_pattern" uregex_pattern+    :: Ptr URegularExpression -> Ptr Int32 -> Ptr UErrorCode+    -> IO (Ptr UChar)++foreign import ccall unsafe "hs_text_icu.h __hs_uregex_setText" uregex_setText+    :: Ptr URegularExpression -> Ptr UChar -> Int32 -> Ptr UErrorCode -> IO ()++foreign import ccall unsafe "hs_text_icu.h __hs_uregex_getText" uregex_getText+    :: Ptr URegularExpression -> Ptr Int32 -> Ptr UErrorCode -> IO (Ptr UChar)++foreign import ccall unsafe "hs_text_icu.h __hs_uregex_find" uregex_find+    :: Ptr URegularExpression -> Int32 -> Ptr UErrorCode -> IO UBool++foreign import ccall unsafe "hs_text_icu.h __hs_uregex_findNext" uregex_findNext+    :: Ptr URegularExpression -> Ptr UErrorCode -> IO UBool++foreign import ccall unsafe "hs_text_icu.h __hs_uregex_start" uregex_start+    :: Ptr URegularExpression -> Int32 -> Ptr UErrorCode -> IO Int32++foreign import ccall unsafe "hs_text_icu.h __hs_uregex_end" uregex_end+    :: Ptr URegularExpression -> Int32 -> Ptr UErrorCode -> IO Int32++foreign import ccall unsafe "hs_text_icu.h __hs_uregex_groupCount" uregex_groupCount+    :: Ptr URegularExpression -> Ptr UErrorCode -> IO Int32++foreign import ccall unsafe "hs_text_icu.h __hs_uregex_group" uregex_group+    :: Ptr URegularExpression -> Int32 -> Ptr UChar -> Int32 -> Ptr UErrorCode+    -> IO Int32++foreign import ccall unsafe "hs_text_icu.h __hs_uregex_setTimeLimit" uregex_setTimeLimit+    :: Ptr URegularExpression -> Int32 -> Ptr UErrorCode -> IO ()++foreign import ccall unsafe "hs_text_icu.h __hs_uregex_setStackLimit" uregex_setStackLimit+    :: Ptr URegularExpression -> Int32 -> Ptr UErrorCode -> IO ()
+ Data/Text/ICU/Regex/Pure.hs view
@@ -0,0 +1,218 @@+{-# LANGUAGE BangPatterns, EmptyDataDecls, ScopedTypeVariables #-}++-- |+-- Module      : Data.Text.ICU.Regex.Pure+-- Copyright   : (c) 2010 Bryan O'Sullivan+--+-- License     : BSD-style+-- Maintainer  : bos@serpentine.com+-- Stability   : experimental+-- Portability : GHC+--+-- Regular expression support for Unicode, implemented as bindings to+-- the International Components for Unicode (ICU) libraries.+--+-- The functions in this module are pure and hence thread safe, but+-- may not be as fast or as flexible as those in the+-- 'Data.Text.ICU.Regex.IO' module.+--+-- The syntax and behaviour of ICU regular expressions are Perl-like.+-- For complete details, see the ICU User Guide entry at+-- <http://userguide.icu-project.org/strings/regexp>.++module Data.Text.ICU.Regex.Pure+    (+    -- * Types+      MatchOption(..)+    , ParseError(errError, errLine, errOffset)+    , Match+    , Regex+    , Regular+    -- * Functions+    -- ** Construction+    , regex+    , regex'+    -- ** Inspection+    , pattern+    -- ** Searching+    , find+    , findAll+    -- ** Match groups+    -- $group+    , groupCount+    , unfold+    , span+    , group+    , prefix+    , suffix+    ) where++import Control.Exception (catch)+import Data.String (IsString(..))+import Data.Text (Text)+import qualified Data.Text as T+import qualified Data.Text.Foreign as T+import Data.Text.ICU.Error.Internal (ParseError(..), handleError)+import qualified Data.Text.ICU.Regex as IO+import Data.Text.ICU.Regex.Internal hiding (Regex(..), regex)+import qualified Data.Text.ICU.Regex.Internal as Internal+import Foreign.ForeignPtr (ForeignPtr, withForeignPtr)+import Foreign.Marshal.Alloc (alloca)+import Foreign.Marshal.Array (advancePtr)+import Foreign.Storable (peek)+import Prelude hiding (catch, span)+import System.IO.Unsafe (unsafeInterleaveIO, unsafePerformIO)++-- | A compiled regular expression.+--+-- 'Regex' values are usually constructed using the 'regex' or+-- 'regex'' functions.  This type is also an instance of 'IsString',+-- so if you have the @OverloadedStrings@ language extension enabled,+-- you can construct a 'Regex' by simply writing the pattern in+-- quotes (though this does not allow you to specify any 'Option's).+newtype Regex = Regex {+      reRe :: Internal.Regex+    }++instance Show Regex where+    show re = "Regex " ++ show (pattern re)++instance IsString Regex where+    fromString = regex [] . T.pack++-- | A match for a regular expression.+data Match = Match {+      matchRe :: Internal.Regex+    , _matchPrev :: T.I16+    }++instance Show Match where+    show m = "Match " ++ show (unfold group m)++-- | A typeclass for functions common to both 'Match' and 'Regex'+-- types.+class Regular r where+    regRe :: r -> Internal.Regex++    regFp :: r -> ForeignPtr URegularExpression+    regFp = Internal.reRe . regRe+    {-# INLINE regFp #-}++instance Regular Match where+    regRe = matchRe++instance Regular Regex where+    regRe = reRe++-- | Compile a regular expression with the given options.  This+-- function throws a 'ParseError' if the pattern is invalid, so it is+-- best for use when the pattern is statically known.+regex :: [MatchOption] -> Text -> Regex+regex opts pat = Regex . unsafePerformIO $ IO.regex opts pat++-- | Compile a regular expression with the given options.  This is+-- safest to use when the pattern is constructed at run time.+regex' :: [MatchOption] -> Text -> Either ParseError Regex+regex' opts pat = unsafePerformIO $+  ((Right . Regex) `fmap` Internal.regex opts pat) `catch`+  \(err::ParseError) -> return (Left err)++-- | Return the source form of the pattern used to construct this+-- regular expression or match.+pattern :: Regular r => r -> Text+pattern r = unsafePerformIO . withForeignPtr (regFp r) $ \rePtr ->+  alloca $ \lenPtr -> do+    textPtr <- handleError $ uregex_pattern rePtr lenPtr+    (T.fromPtr textPtr . fromIntegral) =<< peek lenPtr++-- | Find the first match for the regular expression in the given text.+find :: Regex -> Text -> Maybe Match+find re0 haystack = unsafePerformIO .+  matching re0 haystack $ \re -> do+    m <- IO.findNext re+    return $! if m then Nothing else Just (Match re 0)++-- | Lazily find all matches for the regular expression in the given+-- text.+findAll :: Regex -> Text -> [Match]+findAll re0 haystack = unsafePerformIO . unsafeInterleaveIO $ go 0+  where+    go !n = matching re0 haystack $ \re -> do+      f <- IO.find re n+      if f+        then do+          n' <- IO.end_ re 0+          (Match re n:) `fmap` go n'+        else return []++matching :: Regex -> Text -> (IO.Regex -> IO a) -> IO a+matching (Regex re0) haystack act = do+  re <- IO.clone re0+  IO.setText re haystack+  act re++-- $group+--+-- Capturing groups are numbered starting from zero.  Group zero is+-- always the entire matching text.  Groups greater than zero contain+-- the text matching each capturing group in a regular expression.++-- | Return the number of capturing groups in this regular+-- expression or match's pattern.+groupCount :: Regular r => r -> Int+groupCount = unsafePerformIO . IO.groupCount . regRe++-- | A combinator for returning a list of all capturing groups on a+-- 'Match'.+unfold :: (Int -> Match -> Maybe Text) -> Match -> [Text]+unfold f m = go 0+  where go !n = case f n m of+                  Nothing -> []+                  Just z  -> z : go (n+1)++-- | Return the /n/th capturing group in a match, or 'Nothing' if /n/+-- is out of bounds.+group :: Int -> Match -> Maybe Text+group n m = grouping n m $ \re -> do+  let n' = fromIntegral n+  start <- fromIntegral `fmap` IO.start_ re n'+  end <- fromIntegral `fmap` IO.end_ re n'+  (fp,_) <- IO.getText re+  withForeignPtr fp $ \ptr ->+    T.fromPtr (ptr `advancePtr` fromIntegral start) (end - start)++-- | Return the prefix of the /n/th capturing group in a match (the+-- text from the start of the string to the start of the match), or+-- 'Nothing' if /n/ is out of bounds.+prefix :: Int -> Match -> Maybe Text+prefix n m = grouping n m $ \re -> do+  start <- fromIntegral `fmap` IO.start_ re n+  (fp,_) <- IO.getText re+  withForeignPtr fp (`T.fromPtr` start)++-- | Return the span of text between the end of the previous match and+-- the beginning of the current match.+span :: Match -> Text+span (Match re p) = unsafePerformIO $ do+  start <- IO.start_ re 0+  (fp,_) <- IO.getText re+  withForeignPtr fp $ \ptr ->+    T.fromPtr (ptr `advancePtr` fromIntegral p) (start - p)++-- | Return the suffix of the /n/th capturing group in a match (the+-- text from the end of the match to the end of the string), or+-- 'Nothing' if /n/ is out of bounds.+suffix :: Int -> Match -> Maybe Text+suffix n m = grouping n m $ \re -> do+  end <- fromIntegral `fmap` IO.end_ re n+  (fp,len) <- IO.getText re+  withForeignPtr fp $ \ptr -> do+    T.fromPtr (ptr `advancePtr` fromIntegral end) (len - end)++grouping :: Int -> Match -> (Internal.Regex -> IO a) -> Maybe a+grouping n (Match m _) act = unsafePerformIO $ do+  count <- IO.groupCount m+  let n' = fromIntegral n+  if n < 0 || (n' >= count && count > 0)+    then return Nothing+    else Just `fmap` act m
Data/Text/ICU/Types.hs view
@@ -13,6 +13,8 @@     (     -- * Widely used types       LocaleName(..)+    , ParseError(errError, errLine, errOffset)     ) where +import Data.Text.ICU.Error.Internal (ParseError(..)) import Data.Text.ICU.Internal (LocaleName(..))
− README
@@ -1,31 +0,0 @@-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.
+ README.markdown view
@@ -0,0 +1,37 @@+# 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](http://www.icu-project.org/), which is not included.  The versions+of ICU currently supported are 4.0 and newer.+++# Get involved!++Please report bugs via the+[bitbucket issue tracker](http://bitbucket.org/bos/text-icu/issues).++Master [Mercurial repository](http://bitbucket.org/bos/text-icu):++* `hg clone http://bitbucket.org/bos/text-icu`++There's also a [git mirror](http://github.com/bos/text-icu):++* `git clone git://github.com/bos/text-icu.git`++(You can create and contribute changes using either Mercurial or git.)+++# Authors++This library was written by Bryan O'Sullivan.
cbits/text_icu.c view
@@ -365,3 +365,93 @@ {     return u_getNumericValue(c); }++URegularExpression * __hs_uregex_open(const UChar *pattern,+				      int32_t patternLength, uint32_t flags,+				      UParseError *pe, UErrorCode *status)+{+    return uregex_open(pattern, patternLength, flags, pe, status);+}++void __hs_uregex_setTimeLimit(URegularExpression *regexp,+			      int32_t limit, UErrorCode *status)+{+    return uregex_setTimeLimit(regexp, limit, status);+}++void __hs_uregex_setStackLimit(URegularExpression *regexp,+			       int32_t limit, UErrorCode *status)+{+    return uregex_setStackLimit(regexp, limit, status);+}++void __hs_uregex_close(URegularExpression *regexp)+{+    return uregex_close(regexp);+}++URegularExpression *__hs_uregex_clone(URegularExpression *regexp,+				      UErrorCode *pErrorCode)+{+    return uregex_clone(regexp, pErrorCode);+}++const UChar *__hs_uregex_pattern(const URegularExpression *regexp,+				 int32_t *patLength, UErrorCode *status)+{+    return uregex_pattern(regexp, patLength, status);+}++int32_t __hs_uregex_flags(const URegularExpression *regexp,+			  UErrorCode *status)+{+    return uregex_flags(regexp, status);+}++void __hs_uregex_setText(URegularExpression *regexp, const UChar *text,+			 int32_t textLength, UErrorCode *status)+{+    return uregex_setText(regexp, text, textLength, status);+}++const UChar *__hs_uregex_getText(URegularExpression *regexp,+				 int32_t *textLength, UErrorCode *status)+{+    return uregex_getText(regexp, textLength, status);+}++UBool __hs_uregex_find(URegularExpression *regexp, int32_t startIndex, +		       UErrorCode *status)+{+    return uregex_find(regexp, startIndex, status);+}++UBool __hs_uregex_findNext(URegularExpression *regexp, UErrorCode *status)+{+    return uregex_findNext(regexp, status);+}++int32_t __hs_uregex_start(URegularExpression *regexp, int32_t groupNum,+			  UErrorCode *status)+{+    return uregex_start(regexp, groupNum, status);+}++int32_t __hs_uregex_end(URegularExpression *regexp, int32_t groupNum,+			  UErrorCode *status)+{+    return uregex_end(regexp, groupNum, status);+}++int32_t __hs_uregex_groupCount(URegularExpression *regexp, UErrorCode *status)+{+    return uregex_groupCount(regexp, status);+}++int32_t __hs_uregex_group(URegularExpression *regexp, int32_t groupNum,+			  UChar *dest, int32_t destCapacity,+			  UErrorCode *status)+{+    return uregex_group(regexp, groupNum, dest, destCapacity, status);+}+
include/hs_text_icu.h view
@@ -10,6 +10,7 @@ #include "unicode/ucnv.h" #include "unicode/uiter.h" #include "unicode/unorm.h"+#include "unicode/uregex.h" #include "unicode/ustring.h"  #include <stdint.h>@@ -129,6 +130,38 @@ 			     UNormalizationMode mode, int32_t options, 			     UChar *result, int32_t resultLength, 			     UErrorCode *status);++/* uregex.h */++URegularExpression * __hs_uregex_open(const UChar *pattern,+				      int32_t patternLength, uint32_t flags,+				      UParseError *pe, UErrorCode *status);+void __hs_uregex_setTimeLimit(URegularExpression *regexp,+			      int32_t limit, UErrorCode *status);+void __hs_uregex_setStackLimit(URegularExpression *regexp,+			       int32_t limit, UErrorCode *status);+void __hs_uregex_close(URegularExpression *regexp);+URegularExpression *__hs_uregex_clone(URegularExpression *regexp,+				      UErrorCode *pErrorCode);+const UChar *__hs_uregex_pattern(const URegularExpression *regexp,+				 int32_t *patLength, UErrorCode *status);+int32_t __hs_uregex_flags(const URegularExpression *regexp,+			  UErrorCode *status);+void __hs_uregex_setText(URegularExpression *regexp, const UChar *text,+			 int32_t textLength, UErrorCode *status);+const UChar *__hs_uregex_getText(URegularExpression *regexp,+				 int32_t *textLength, UErrorCode *status);+UBool __hs_uregex_find(URegularExpression *regexp, int32_t startIndex, +		       UErrorCode *status);+UBool __hs_uregex_findNext(URegularExpression *regexp, UErrorCode *status);+int32_t __hs_uregex_start(URegularExpression *regexp, int32_t groupNum,+			  UErrorCode *status);+int32_t __hs_uregex_end(URegularExpression *regexp, int32_t groupNum,+			UErrorCode *status);+int32_t __hs_uregex_groupCount(URegularExpression *regexp, UErrorCode *status);+int32_t __hs_uregex_group(URegularExpression *regexp, int32_t groupNum,+			  UChar *dest, int32_t destCapacity,+			  UErrorCode *status);  /* ustring.h */ 
text-icu.cabal view
@@ -1,10 +1,34 @@ name:           text-icu-version:        0.6.0.1+version:        0.6.2.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.+homepage:       http://bitbucket.org/bos/text-icu+bug-reports:    http://bitbucket.org/bos/text-icu/issues+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.+  .+  Features include:+  .+  * Both pure and impure bindings, to allow for fine control over efficiency+    and ease of use.+  .+  * Breaking of strings on character, word, sentence, and line boundaries.+  .+  * Access to the Unicode Character Database (UCD) of character metadata.+  .+  * String collation functions, for locales where the conventions for+    lexicographic ordering differ from the simple numeric ordering of+    character codes.+  .+  * Character set conversion functions, allowing conversion between+    Unicode and over 220 character encodings.+  .+  * Unicode normalization.  (When implementations keep strings in a+    normalized form, they can be assured that equivalent strings have a+    unique binary representation.)+  .+  * Regular expression search and replace. maintainer:     Bryan O'Sullivan <bos@serpentine.com> copyright:      2009, 2010 Bryan O'Sullivan category:       Data, Text@@ -13,10 +37,10 @@ build-type:     Simple cabal-version:  >= 1.6 extra-source-files:-  README include/hs_text_icu.h tests/benchmarks/Breaker.hs+  README.markdown include/hs_text_icu.h tests/benchmarks/Breaker.hs  library-  build-depends:     base < 5, bytestring, text == 0.9.*+  build-depends:     base < 5, bytestring, text >= 0.9.1.0 && <= 0.11.0.0   if impl(ghc >= 6.10)     build-depends:   base >= 4 @@ -28,6 +52,7 @@       Data.Text.ICU.Convert       Data.Text.ICU.Error       Data.Text.ICU.Normalize+      Data.Text.ICU.Regex       Data.Text.ICU.Types   other-modules:       Data.Text.ICU.Break.Pure@@ -39,6 +64,8 @@       Data.Text.ICU.Internal       Data.Text.ICU.Iterator       Data.Text.ICU.Normalize.Internal+      Data.Text.ICU.Regex.Internal+      Data.Text.ICU.Regex.Pure       Data.Text.ICU.Text   c-sources: cbits/text_icu.c   include-dirs: include@@ -53,5 +80,9 @@     ghc-options: -fwarn-tabs  source-repository head-  type:     darcs-  location: http://code.haskell.org/text-icu/+  type:     mercurial+  location: http://bitbucket.org/bos/text-icu++source-repository head+  type:     git+  location: http://github.com/bos/text-icu