packages feed

strings (empty) → 1.0.0

raw patch · 4 files changed

+673/−0 lines, 4 filesdep +basedep +bytestringdep +textsetup-changed

Dependencies added: base, bytestring, text

Files

+ LICENSE view
@@ -0,0 +1,18 @@+Permission is hereby granted, free of charge, to any person obtaining+a copy of this software and associated documentation files (the "Software"),+to deal in the Software without restriction, including without limitation+the rights to use, copy, modify, merge, publish, distribute, sublicense,+and/or sell copies of the Software, and to permit persons to whom the+Software is furnished to do so, subject to the following conditions:++The above copyright notice and this permission notice shall be included+in all copies or substantial portions of the Software.++THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL+THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER+DEALINGS IN THE SOFTWARE.+
+ Setup.lhs view
@@ -0,0 +1,4 @@+import Distribution.Simple++main = defaultMain+
+ src/Data/Strings.hs view
@@ -0,0 +1,633 @@+{-# LANGUAGE TypeSynonymInstances,+             FlexibleInstances,+             Trustworthy #-}++-- | Functions for working with strings, including 'Text', 'ByteString', etc.+--+-- This module aims at offering a consistent interface across all the available+-- string types. It currently offers instances for the ordinary Haskell 'String'+-- type, 'Text', lazy 'LazyT.Text', 'ByteString', and lazy 'LazyB.ByteString'.+--+-- If especially provides functions for some types, which are otherwise not+-- available nativly (such as 'breakOnSubstring' is not available for the lazy+-- 'LazyT.Text' type, is offered by 'sBreak' and 'strBreak').+module Data.Strings (++    text,+    lazyText,+    bytes,+    lazyBytes,++    Str (..),+    Strings (..)++) where+++import Data.Int+import Data.Word+import Data.String hiding (fromString)+import qualified Data.String as S+import qualified Data.Char as C++import qualified Data.ByteString.Char8 as B8+import qualified Data.ByteString as B+import Data.ByteString (ByteString)+import qualified Data.ByteString.Lazy.Char8 as LazyB8+import qualified Data.ByteString.Lazy as LazyB+import qualified Data.Text as T+import Data.Text (Text)+import qualified Data.Text.Lazy as LazyT+import qualified Data.List as L+import qualified Data.Text.Encoding as Enc+import qualified Data.Text.Lazy.Encoding as LazyEnc++-- | Returns @True@ exactly for space (0x20), and horizontal tab (0x09).+isSpace x+    | x == ' '  = True+    | x == '\t' = True+    | otherwise = False++-- | Returns @True@ exactly for space (0x20), horizontal tab (0x09), carriage return (0x0D), and line feed (0x0A).+isWhiteSpace x+    | x == ' '  = True+    | x == '\t' = True+    | x == '\r' = True+    | x == '\n' = True+    | otherwise = False+++-- | Create a 'Text' object form an ordinary Haskell 'String'.+text :: String -> Text+text = S.fromString++-- | Create a lazy 'LazyT.Text' object from an ordinary Haskell 'String'.+lazyText :: String -> LazyT.Text+lazyText = S.fromString++-- | Create a 'ByteString' object form an ordinary Haskell 'String'.+-- This function will encode a String using the UTF-8 character encoding.+bytes :: String -> ByteString+bytes = sFromUnicodeString++-- | Create a lazy 'LazyB.ByteString' object from an ordinary Haskell 'String'.+-- This function will encode a String using the UTF-8 character encoding.+lazyBytes :: String -> LazyB.ByteString+lazyBytes = sFromUnicodeString++-- | The 'Str' class provides functions for working with arbitrary Strings.+-- It is basically the same interface as provided by the 'Strings' class.+-- However, every input string is a Haskell String here, thus easing the+-- usage of different string types with native Haskell String literals.+--+-- For example @strAppend "suffix"@ works with any string type for which+-- an instance of @Str@ is defined. In order to maximize the ease of use+-- of this library, the functions are prefixed with @str@.+--+-- The complexity and efficiency of these functions depends on the underlying+-- string type being used.+class (Eq a, Strings a) => Str a where++    -- | Check whether the given string is empty or not. 'null' generalised.+    strNull :: a -> Bool++    -- | 'length' generalised.+    strLen :: a -> Int++    -- | 'head' generalised. This function is undefined if 'strNull' would return @True@.+    strHead :: a -> Char++    -- | 'last' generalised. This function is undefined if 'strNull' would return @True@.+    strLast :: a -> Char++    -- | 'init' generalised. This function is undefined if 'strNull' would return @True@.+    strInit :: a -> a++    -- | 'tail' generalised. This function is undefined if 'strNull' would return @True@.+    strTail :: a -> a++    -- | 'take' generalised.+    strTake :: Int -> a -> a++    -- | 'drop' generalised.+    strDrop :: Int -> a -> a+    +    -- | Replace a substring with another string.+    strReplace :: String -- ^ Needle.+               -> String -- ^ Replacement.+               -> a      -- ^ Haystack.+               -> a      -- ^ Result: @Haystack@ with @Needle@ replaced by @Replacement@.++    -- | Breaks the string on the first occurence of the given substring.+    --+    -- > strBreak "xx" "1x2xx3xx4" = ("1x2", "xx3xx4")+    strBreak :: String -> a -> (a, a)++    -- | Like 'strBreak', but the string to break on is excluded from the result.+    --+    -- > strSplit "xx" "1x2xx3xx4" = ("1x2", "3xx4")+    strSplit :: String -> a -> (a, a)++    -- | Split a string into multiple fragments, separated by the given substring.+    --+    -- > strSplitAll "xx" "1x2xx3xx4" = ["1x2", "3", "4"]+    strSplitAll :: String -> a -> [a]++    -- | @concat@ generalised.+    strConcat :: [a] -> a++    -- | Glue together multiple strings by a given Haskell 'String'.+    --+    -- > strJoin x = concat . intersperse x+    strJoin :: String -> [a] -> a++    -- | Appends the given Haskell 'String' to the string. @++@ generalised.+    --+    -- > strAppend " world" "hello" = "hello world"+    strAppend :: String -- The String to append.+              -> a      -- The string to append to.+              -> a      -- The concatenation of the two strings.++    -- | Strips white space characters off both ends of the string.+    strTrim :: a -> a++    -- | Appends the given character n times to the left, such that+    -- the resulting string has the given length.+    --+    -- > strPadLeft '0' 8 "4711" == "00004711"+    strPadLeft  :: Char -> Int -> a -> a++    -- | Appends the given character n times to the right, such that+    -- the resulting string has the given length.+    --+    -- > strPadRight '0' 8 "4711" == "47110000"+    strPadRight :: Char -> Int -> a -> a++    -- | Appends the given character n times to both sides, such that+    -- the resulting string has the given length.+    --+    -- > strPadBoth '0' 8 "4711" == "00471100"+    strPadBoth  :: Char -> Int -> a -> a++    -- | Reverse the string.+    strReverse :: a -> a++    -- | Check if the given Haskell String equals the string.+    strEq :: String -- ^ The Haskell String.+          -> a      -- ^ The string.+          -> Bool   -- @True@ iff @fromString haskellString == string@++    -- | Check if the string starts with the given Haskell String.+    strStartsWith :: a -> String -> Bool++    -- | Check if the string ends with the given Haskell String.+    strEndsWith :: a -> String -> Bool++    -- | Create a string from a Haskell String.+    fromString :: String -> a++    -- | Create a string from a Haskell String. If the string does not support unicode,+    -- the Haskell String is encoded using UTF-8.+    fromUnicodeString :: String -> a++    -- | Convert the string into a Haskell String.+    toString :: a -> String++    -- | Convert the string into a list of bytes.+    toWord8 :: a -> [Word8]++    strNull = sNull+    strLen = sLen++    strHead = sHead+    strLast = sLast++    strInit = sInit+    strTail = sTail+    strTake = sTake+    strDrop = sDrop++    strReplace n r = sReplace (fromString n) (fromString r)++    strBreak n = sBreak (fromString n)+    strSplit d s = (a, b)+      where (a, b, _) = sSplit (fromString d) s+    strSplitAll n = sSplitAll (fromString n)++    strConcat = sConcat+    strJoin d = let d' = fromUnicodeString d in strConcat . L.intersperse d'+    strAppend x xs = sConcat [xs, fromString x]+    strTrim = sTrim++    strPadLeft  = sPadLeft+    strPadRight = sPadRight+    strPadBoth  = sPadBoth++    strReverse = sReverse++    strStartsWith s pref = sStartsWith s (fromString pref)+    strEndsWith   s suff = sEndsWith   s (fromString suff)++    strEq s1 s2 = fromUnicodeString s1 == s2++    fromString = sFromString+    fromUnicodeString = sFromUnicodeString++    toString = sToString+    toWord8 = sToWord8++{-+instance IsString Data.ByteString.ByteString where+    fromString = Enc.encodeUtf8 . Data.Text.pack++instance IsString Data.ByteString.Lazy.ByteString where+    fromString = LazyEnc.encodeUtf8 . Data.Text.Lazy.pack+-}++instance Str Text where+instance Str LazyT.Text where+instance Str ByteString where+instance Str LazyB.ByteString where+instance Str String where++-- | The goal of this class is to offer the same interface for various+-- types of strings ('ByteString', 'Text', Haskell 'String', etc.).+-- If a certain type offers a native implementation for a given function,+-- 'Strings' uses it. If not, a default implementation is given.+--+-- All of these functions are prefixed with @s@ to avoid nameclashes+-- with existing functions from the prelude.+--+-- The complexity and efficiency of these functions depends on the underlying+-- string type being used.+class Strings a where++    -- | Check whether the given string is empty or not. @null@ generalised.+    sNull :: a -> Bool++    -- | The empty string.+    sEmpty :: a++    -- | 'length' generalised.+    sLen :: a -> Int++    -- | 'head' generalised. This function is undefined if 'strNull' would return @True@.+    sHead :: a -> Char++    -- | 'last' generalised. This function is undefined if 'strNull' would return @True@.+    sLast :: a -> Char++    -- | 'init' generalised. This function is undefined if 'strNull' would return @True@.+    sInit :: a -> a++    -- | 'tail' generalised. This function is undefined if 'strNull' would return @True@.+    sTail :: a -> a++    -- | 'take' generalised.+    sTake :: Int -> a -> a++    -- | 'drop' generalised.+    sDrop :: Int -> a -> a++    -- | 'takeWhile' generalised.+    sTakeWhile :: (Char -> Bool) -> a -> a++    -- | 'dropWhile' generalised.+    sDropWhile :: (Char -> Bool) -> a -> a++    -- | Replace a substring with another string.+    sReplace :: a -> a -> a -> a++    -- | Breaks the string on the first occurence of the given substring.+    --+    -- > strBreak "xx" "1x2xx3xx4" = ("1x2", "xx3xx4")+    sBreak :: a -> a -> (a, a)++    -- | Like 'sBreak', but the string to break on is excluded from the result.+    --+    -- > strSplit "xx" "1x2xx3xx4" = ("1x2", "3xx4")+    sSplit :: a -> a -> (a, a, Bool)++    -- | Split a string into multiple fragments, separated by the given substring.+    --+    -- > strSplitAll "xx" "1x2xx3xx4" = ["1x2", "3", "4"]+    sSplitAll :: a -> a -> [a]++    -- | Check if the string starts with the given string.+    sStartsWith :: a -> a -> Bool++    -- | Check if the string ends with the given string.+    sEndsWith   :: a -> a -> Bool++    -- | Concatenate all the strings in the list to a single string.+    sConcat :: [a] -> a++    -- | Strips white space characters off both ends of the string.+    sTrim :: a -> a++    -- | Appends the given character n times to the left, such that+    -- the resulting string has the given length.+    --+    -- > strPadLeft '0' 8 "4711" == "00004711"+    sPadLeft  :: Char -> Int -> a -> a++    -- | Appends the given character n times to the right, such that+    -- the resulting string has the given length.+    --+    -- > strPadRight '0' 8 "4711" == "47110000"+    sPadRight :: Char -> Int -> a -> a++    -- | Appends the given character n times to both sides, such that+    -- the resulting string has the given length.+    --+    -- > strPadBoth '0' 8 "4711" == "00471100"+    sPadBoth  :: Char -> Int -> a -> a++    -- 'reverse' the string.+    sReverse :: a -> a++    -- | Create a string from a Haskell String.+    sFromString :: String -> a++    -- | Create a string from a Haskell String. If the string does not support unicode,+    -- the Haskell String is encoded using UTF-8.+    sFromUnicodeString :: String -> a++    -- | Convert the string into a Haskell String.+    sToString :: a -> String++    -- | Convert the string into a list of bytes.+    sToWord8 :: a -> [Word8]++    sBreak d src = search 0 src+      where+        search a b | a `seq` b `seq` False = undefined+        search n s+            | sNull s         = (src, sEmpty)+            | sStartsWith s d = (sTake n src, s)+            | otherwise       = search (n+1) (sTail s)++    sReplace n r = sConcat . replace n r+      where+        replace n r h = if sNull b+                        then (if c then [a, r] else [a])+                        else a : r : replace n r b+          where (a, b, c) = sSplit n h++    sSplit d s = (a, sDrop (sLen d) b, not $ sNull b)+      where (a, b) = sBreak d s++    sSplitAll d s = if sNull b+                      then (if c then [a, b] else [a])+                      else a : sSplitAll d b+      where (a, b, c) = sSplit d s++    sPadLeft  c n s = let len    = sLen s+                          padLen = max 0 (n - len)+                          padStr = sFromString $ replicate padLen c+                      in  sConcat [padStr, s]+                      +    sPadRight c n s = let len    = sLen s+                          padLen = max 0 (n - len)+                          padStr = sFromString $ replicate padLen c+                      in  sConcat [s, padStr]      ++    sPadBoth  c n s = let len     = sLen s+                          padLen  = (max 0 (n - len))+                          padLenR = padLen `quot` 2+                          padLenL = padLen - padLenR+                          padStrL = sFromString $ replicate padLenL c+                          padStrR = sFromString $ replicate padLenR c+                      in  sConcat [padStrL, s, padStrR]+++instance Strings ByteString where++    sNull  = B.null+    sEmpty = B.empty++    sHead = toEnum . fromIntegral . B.head+    sLast = toEnum . fromIntegral . B.last++    sInit = B.init+    sTail = B.tail++    sTake = B.take+    sTakeWhile f = B.takeWhile (f . chr)+    sDrop = B.drop+    sDropWhile f = B.dropWhile (f . chr)++    sBreak = B.breakSubstring++    sStartsWith = flip B.isPrefixOf+    sEndsWith = flip B.isSuffixOf++    sConcat = B.concat+    sLen = B.length++    sTrim s = let (a, b) = B.span    (isWhiteSpace . chr) s+                  (c, d) = B.spanEnd (isWhiteSpace . chr) b+              in c++    sReverse = B.reverse++    sFromString = B8.pack+    sFromUnicodeString = Enc.encodeUtf8 . T.pack++    sToString = B8.unpack+    sToWord8 = B.unpack+++instance Strings LazyB.ByteString where++    sNull  = LazyB.null+    sEmpty = LazyB.empty++    sHead = toEnum . fromIntegral . LazyB.head+    sLast = toEnum . fromIntegral . LazyB.last++    sInit = LazyB.init+    sTail = LazyB.tail++    sTake = LazyB.take . fromIntegral+    sTakeWhile f = LazyB.takeWhile (f . chr)+    sDrop = LazyB.drop . fromIntegral+    sDropWhile f = LazyB.dropWhile (f . chr)++    sStartsWith = flip LazyB.isPrefixOf+    sEndsWith = flip LazyB.isSuffixOf++    sConcat = LazyB.concat+    sLen = fromIntegral . LazyB.length++    sTrim = LazyB.fromChunks . (:[]) . sTrim . B.concat . LazyB.toChunks++    sReverse = LazyB.reverse++    sFromString = LazyB8.pack+    sFromUnicodeString = LazyEnc.encodeUtf8 . LazyT.pack++    sToString = LazyB8.unpack+    sToWord8 = LazyB.unpack+++instance Strings Text where++    sNull  = T.null+    sEmpty = T.empty++    sHead = T.head+    sLast = T.last++    sInit = T.init+    sTail = T.tail++    sTake = T.take+    sTakeWhile = T.takeWhile+    sDrop = T.drop+    sDropWhile = T.dropWhile++    sReplace = T.replace+    sBreak = T.breakOn++    sStartsWith = flip T.isPrefixOf+    sEndsWith = flip T.isSuffixOf++    sConcat = T.concat+    sLen = T.length++    sTrim = T.strip++    sPadLeft  = flip T.justifyLeft+    sPadRight = flip T.justifyRight+    sPadBoth  = flip T.center++    sReverse = T.reverse++    sFromUnicodeString = S.fromString+    sFromString = S.fromString++    sToString = T.unpack+    sToWord8 = B.unpack . Enc.encodeUtf8+++instance Strings LazyT.Text where++    sNull  = LazyT.null+    sEmpty = LazyT.empty++    sHead = LazyT.head+    sLast = LazyT.last++    sInit = LazyT.init+    sTail = LazyT.tail++    sTake = LazyT.take . fromIntegral+    sTakeWhile = LazyT.takeWhile+    sDrop = LazyT.drop . fromIntegral+    sDropWhile = LazyT.dropWhile++    sBreak = LazyT.breakOn++    sStartsWith = flip LazyT.isPrefixOf+    sEndsWith = flip LazyT.isSuffixOf++    sConcat = LazyT.concat+    sLen = fromIntegral . LazyT.length++    sTrim = LazyT.strip++    sPadLeft  = flip (LazyT.justifyLeft . fromIntegral)+    sPadRight = flip (LazyT.justifyRight . fromIntegral)+    sPadBoth  = flip (LazyT.center . fromIntegral)++    sReverse = LazyT.reverse++    sFromUnicodeString = S.fromString+    sFromString = S.fromString++    sToString = LazyT.unpack+    sToWord8 = LazyB.unpack . LazyEnc.encodeUtf8+++instance Strings String where++    sNull = null+    sEmpty = []++    sHead = head+    sLast = last++    sInit = init+    sTail = tail++    sTake = take+    sTakeWhile = takeWhile+    sDrop = drop+    sDropWhile = dropWhile++    sStartsWith = flip L.isPrefixOf+    sEndsWith = flip L.isSuffixOf++    sConcat = concat+    sLen = length++    sTrim = T.unpack . T.strip . T.pack++    sReverse = reverse++    sFromString = id+    sFromUnicodeString = id++    sToString = id+    sToWord8 = B.unpack . Enc.encodeUtf8 . T.pack++-- | Utility class for working with characters.+class Chars a where+    -- | Retrieve the value of the given character.+    ord :: Char -> a++    -- | Construct a character form the given value.+    chr :: a -> Char++instance Chars Int where+    ord = fromIntegral . fromEnum+    chr = toEnum . fromIntegral++instance Chars Word8 where+    ord = fromIntegral . fromEnum+    chr = toEnum . fromIntegral++instance Chars Word16 where+    ord = fromIntegral . fromEnum+    chr = toEnum . fromIntegral++instance Chars Word32 where+    ord = fromIntegral . fromEnum+    chr = toEnum . fromIntegral++instance Chars Word64 where+    ord = fromIntegral . fromEnum+    chr = toEnum . fromIntegral++instance Chars Int8 where+    ord = fromIntegral . fromEnum+    chr = toEnum . fromIntegral++instance Chars Int16 where+    ord = fromIntegral . fromEnum+    chr = toEnum . fromIntegral++instance Chars Int32 where+    ord = fromIntegral . fromEnum+    chr = toEnum . fromIntegral++instance Chars Int64 where+    ord = fromIntegral . fromEnum+    chr = toEnum . fromIntegral++instance Chars Integer where+    ord = fromIntegral . fromEnum+    chr = toEnum . fromIntegral++
+ strings.cabal view
@@ -0,0 +1,18 @@+Name:               strings+Version:            1.0.0+Synopsis:           Functions for working with strings, including Text, ByteString, etc.+Description:        Functions for working with strings, including Text, ByteString, etc.+License:            MIT+License-File:       LICENSE+Author:             Julian Fleischer+Maintainer:         julian.fleischer@fu-berlin.de+Build-Type:         Simple+Cabal-Version:      >= 1.4+Category:           Text, String, Utility+Stability:          provisional++Library+    Exposed-Modules:    Data.Strings+    Build-Depends:      base >= 4 && < 5, bytestring >= 0.9 && < 0.10, text >= 0.10+    Hs-Source-Dirs:     src+