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 +29/−0
- Data/Text/ICU/Error.hsc +47/−39
- Data/Text/ICU/Error/Internal.hs +0/−80
- Data/Text/ICU/Error/Internal.hsc +138/−0
- Data/Text/ICU/Regex.hs +198/−0
- Data/Text/ICU/Regex/Internal.hsc +230/−0
- Data/Text/ICU/Regex/Pure.hs +218/−0
- Data/Text/ICU/Types.hs +2/−0
- README +0/−31
- README.markdown +37/−0
- cbits/text_icu.c +90/−0
- include/hs_text_icu.h +33/−0
- text-icu.cabal +40/−9
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