packages feed

byteslice 0.2.13.2 → 0.2.14.0

raw patch · 5 files changed

+219/−103 lines, 5 filesdep ~primitive-unliftednew-uploaderPVP ok

version bump matches the API change (PVP)

Dependency ranges changed: primitive-unlifted

API changes (from Hackage documentation)

+ Data.Bytes.Text.AsciiExt: anyEq :: Char -> Bytes -> Bool
+ Data.Bytes.Text.AsciiExt: dropWhileEndEq :: Char -> Bytes -> Bytes
+ Data.Bytes.Text.AsciiExt: dropWhileNotEq :: Char -> Bytes -> Bytes
+ Data.Bytes.Text.AsciiExt: split1 :: Char -> Bytes -> Maybe (Bytes, Bytes)
+ Data.Bytes.Text.AsciiExt: split2 :: Char -> Bytes -> Maybe (Bytes, Bytes, Bytes)
+ Data.Bytes.Text.AsciiExt: split3 :: Char -> Bytes -> Maybe (Bytes, Bytes, Bytes, Bytes)
+ Data.Bytes.Text.AsciiExt: split4 :: Char -> Bytes -> Maybe (Bytes, Bytes, Bytes, Bytes, Bytes)
+ Data.Bytes.Text.AsciiExt: splitTetragram1 :: Char -> Char -> Char -> Char -> Bytes -> Maybe (Bytes, Bytes)
+ Data.Bytes.Text.AsciiExt: takeWhileEndNotEq :: Char -> Bytes -> Bytes
+ Data.Bytes.Text.AsciiExt: takeWhileNotEq :: Char -> Bytes -> Bytes
+ Data.Bytes.Text.Utf8: toText :: Bytes -> Maybe Text

Files

CHANGELOG.md view
@@ -1,5 +1,12 @@ # Revision history for byteslice +## 0.2.14.0 -- 2024-02-26++* Add functions to `Data.Bytes.Text.AsciiExt`: `split(1|2|3|4)`,+  `splitTetragram1`, `anyEq`, `takeWhileNotEq`, `dropWhileNotEq`,+  `takeWhileEndNotEq`, dropWhileEndEq`.+* Increment upper bound on `primitive-unlifted`+ ## 0.2.13.2 -- 2024-02-06  * Restore `Data.Bytes.Text.Utf8.toText`.
byteslice.cabal view
@@ -1,6 +1,6 @@ cabal-version:   2.4 name:            byteslice-version:         0.2.13.2+version:         0.2.14.0 synopsis:        Slicing managed and unmanaged memory description:   This library provides types that allow the user to talk about a slice of@@ -61,7 +61,7 @@     , natural-arithmetic  >=0.1.4     , primitive           >=0.7.4  && <0.10     , primitive-addr      >=0.1    && <0.2-    , primitive-unlifted  >=0.1.2  && <2.2+    , primitive-unlifted  >=0.1.2  && <2.3     , run-st              >=0.1.1  && <0.2     , text                >=1.2.5     , text-short          >=0.1.3  && <0.2
src/Data/Bytes.hs view
@@ -34,8 +34,8 @@   , unsnoc      -- * Predicates-  , any-  , all+  , Pure.any+  , Pure.all      -- * Create @@ -89,7 +89,7 @@      -- ** Fixed from Beginning   , Byte.split1-  , splitTetragram1+  , Pure.splitTetragram1   , Byte.split2   , Byte.split3   , Byte.split4@@ -106,7 +106,7 @@     -- * Searching   , replace   , findIndices-  , findTetragramIndex+  , Pure.findTetragramIndex      -- * Counting   , Byte.count@@ -207,9 +207,8 @@ import Control.Monad.Primitive (PrimMonad, primitive_, unsafeIOToPrim) import Control.Monad.ST.Run (runByteArrayST) import Cstrlen (cstringLength#)-import Data.Bits (unsafeShiftL, (.|.)) import Data.ByteString.Short.Internal (ShortByteString (SBS))-import Data.Bytes.Pure (foldr, fromByteArray, length, toShortByteString, unsafeDrop, unsafeIndex)+import Data.Bytes.Pure (fromByteArray, length, toShortByteString, unsafeDrop, unsafeIndex) import Data.Bytes.Search (findIndices, isInfixOf, replace) import Data.Bytes.Types (ByteArrayN (ByteArrayN), Bytes (Bytes, array, offset), BytesN (BytesN)) import Data.Primitive (Array, ByteArray (ByteArray))@@ -217,7 +216,7 @@ import Foreign.C.String (CString) import Foreign.Ptr (Ptr, castPtr, plusPtr) import GHC.Exts (Addr#, Int (I#), Int#, Ptr (Ptr), Word#)-import GHC.Word (Word32, Word8 (W8#))+import GHC.Word (Word8 (W8#)) import Reps (Bytes# (..), word8ToWord#)  import qualified Arithmetic.Nat as Nat@@ -402,12 +401,12 @@ -- | Take bytes while the predicate is true. takeWhile :: (Word8 -> Bool) -> Bytes -> Bytes {-# INLINE takeWhile #-}-takeWhile k b = Pure.unsafeTake (countWhile k b) b+takeWhile k b = Pure.unsafeTake (Pure.countWhile k b) b  -- | Drop bytes while the predicate is true. dropWhile :: (Word8 -> Bool) -> Bytes -> Bytes {-# INLINE dropWhile #-}-dropWhile k b = Pure.unsafeDrop (countWhile k b) b+dropWhile k b = Pure.unsafeDrop (Pure.countWhile k b) b  {- | /O(n)/ 'dropWhileEnd' @p@ @b@ returns the prefix remaining after dropping characters that satisfy the predicate @p@ from the end of@@ -415,7 +414,7 @@ -} dropWhileEnd :: (Word8 -> Bool) -> Bytes -> Bytes {-# INLINE dropWhileEnd #-}-dropWhileEnd k !b = Pure.unsafeTake (length b - countWhileEnd k b) b+dropWhileEnd k !b = Pure.unsafeTake (length b - Pure.countWhileEnd k b) b  {- | /O(n)/ 'takeWhileEnd' @p@ @b@ returns the longest suffix of elements that satisfy predicate @p@.@@ -423,39 +422,9 @@ takeWhileEnd :: (Word8 -> Bool) -> Bytes -> Bytes {-# INLINE takeWhileEnd #-} takeWhileEnd k !b =-  let n = countWhileEnd k b+  let n = Pure.countWhileEnd k b    in Bytes (array b) (offset b + length b - n) n --- Internal. The returns the number of bytes that match the--- predicate until the first non-match occurs. If all bytes--- match the predicate, this will return the length originally--- provided.-countWhile :: (Word8 -> Bool) -> Bytes -> Int-{-# INLINE countWhile #-}-countWhile k (Bytes arr off0 len0) = go off0 len0 0- where-  go !off !len !n =-    if len > 0-      then-        if k (PM.indexByteArray arr off)-          then go (off + 1) (len - 1) (n + 1)-          else n-      else n---- Internal. Variant of countWhile that starts from the end--- of the string instead of the beginning.-countWhileEnd :: (Word8 -> Bool) -> Bytes -> Int-{-# INLINE countWhileEnd #-}-countWhileEnd k (Bytes arr off0 len0) = go (off0 + len0 - 1) (len0 - 1) 0- where-  go !off !len !n =-    if len >= 0-      then-        if k (PM.indexByteArray arr off)-          then go (off - 1) (len - 1) (n + 1)-          else n-      else n- {- | Convert a 'String' consisting of only characters in the ASCII block to a byte sequence. Any character with a codepoint above @U+007F@ is replaced by @U+0000@.@@ -694,16 +663,6 @@  where   len = length a + length b + 1 --- | /O(n)/ Returns true if any byte in the sequence satisfies the predicate.-any :: (Word8 -> Bool) -> Bytes -> Bool-{-# INLINE any #-}-any f = foldr (\b r -> f b || r) False---- | /O(n)/ Returns true if all bytes in the sequence satisfy the predicate.-all :: (Word8 -> Bool) -> Bytes -> Bool-{-# INLINE all #-}-all f = foldr (\b r -> f b && r) True- {- | Variant of 'toShortByteString' that unconditionally makes a copy of the array backing the sliced 'Bytes' even if the original array could be reused. Prefer 'toShortByteString'.@@ -786,52 +745,3 @@   Nat.with     (PM.sizeofByteArray arr)     (\n -> f n (ByteArrayN arr))--findTetragramIndex ::-  Word8 ->-  Word8 ->-  Word8 ->-  Word8 ->-  Bytes ->-  Maybe Int-findTetragramIndex !w0 !w1 !w2 !w3 (Bytes arr off len) =-  if len < 4-    then Nothing-    else-      let !target =-            unsafeShiftL (fromIntegral w0 :: Word32) 24-              .|. unsafeShiftL (fromIntegral w1 :: Word32) 16-              .|. unsafeShiftL (fromIntegral w2 :: Word32) 8-              .|. unsafeShiftL (fromIntegral w3 :: Word32) 0-          !end = off + len-          go !ix !acc =-            if acc == target-              then-                let n = ix - off-                 in Just (n - 4)-              else-                if ix < end-                  then-                    let !w = PM.indexByteArray arr ix :: Word8-                        acc' =-                          (fromIntegral w :: Word32)-                            .|. unsafeShiftL acc 8-                     in go (ix + 1) acc'-                  else Nothing-          !acc0 =-            unsafeShiftL (fromIntegral (PM.indexByteArray arr 0 :: Word8) :: Word32) 24-              .|. unsafeShiftL (fromIntegral (PM.indexByteArray arr 1 :: Word8) :: Word32) 16-              .|. unsafeShiftL (fromIntegral (PM.indexByteArray arr 2 :: Word8) :: Word32) 8-              .|. unsafeShiftL (fromIntegral (PM.indexByteArray arr 3 :: Word8) :: Word32) 0-       in go 4 acc0--splitTetragram1 ::-  Word8 ->-  Word8 ->-  Word8 ->-  Word8 ->-  Bytes ->-  Maybe (Bytes, Bytes)-splitTetragram1 !w0 !w1 !w2 !w3 !b = case findTetragramIndex w0 w1 w2 w3 b of-  Nothing -> Nothing-  Just n -> Just (Pure.unsafeTake n b, Pure.unsafeDrop (n + 4) b)
src/Data/Bytes/Pure.hs view
@@ -40,12 +40,19 @@   , toShortByteString   , replicate   , replicateU+  , splitTetragram1+  , findTetragramIndex+  , countWhile+  , countWhileEnd+  , any+  , all   ) where -import Prelude hiding (Foldable (..), map, replicate)+import Prelude hiding (Foldable (..), map, replicate, any, all)  import Control.Monad.Primitive (PrimMonad, PrimState) import Control.Monad.ST.Run (runByteArrayST)+import Data.Bits (unsafeShiftL, (.|.)) import Data.Bits (xor) import Data.ByteString (ByteString) import Data.ByteString.Short.Internal (ShortByteString (SBS))@@ -402,3 +409,93 @@   arr <- PM.newByteArray n   PM.setByteArray arr 0 n w   PM.unsafeFreezeByteArray arr++splitTetragram1 ::+  Word8 ->+  Word8 ->+  Word8 ->+  Word8 ->+  Bytes ->+  Maybe (Bytes, Bytes)+splitTetragram1 !w0 !w1 !w2 !w3 !b = case findTetragramIndex w0 w1 w2 w3 b of+  Nothing -> Nothing+  Just n -> Just (unsafeTake n b, unsafeDrop (n + 4) b)++findTetragramIndex ::+  Word8 ->+  Word8 ->+  Word8 ->+  Word8 ->+  Bytes ->+  Maybe Int+findTetragramIndex !w0 !w1 !w2 !w3 (Bytes arr off len) =+  if len < 4+    then Nothing+    else+      let !target =+            unsafeShiftL (fromIntegral w0 :: Word32) 24+              .|. unsafeShiftL (fromIntegral w1 :: Word32) 16+              .|. unsafeShiftL (fromIntegral w2 :: Word32) 8+              .|. unsafeShiftL (fromIntegral w3 :: Word32) 0+          !end = off + len+          go !ix !acc =+            if acc == target+              then+                let n = ix - off+                 in Just (n - 4)+              else+                if ix < end+                  then+                    let !w = PM.indexByteArray arr ix :: Word8+                        acc' =+                          (fromIntegral w :: Word32)+                            .|. unsafeShiftL acc 8+                     in go (ix + 1) acc'+                  else Nothing+          !acc0 =+            unsafeShiftL (fromIntegral (PM.indexByteArray arr 0 :: Word8) :: Word32) 24+              .|. unsafeShiftL (fromIntegral (PM.indexByteArray arr 1 :: Word8) :: Word32) 16+              .|. unsafeShiftL (fromIntegral (PM.indexByteArray arr 2 :: Word8) :: Word32) 8+              .|. unsafeShiftL (fromIntegral (PM.indexByteArray arr 3 :: Word8) :: Word32) 0+       in go 4 acc0++-- Internal. The returns the number of bytes that match the+-- predicate until the first non-match occurs. If all bytes+-- match the predicate, this will return the length originally+-- provided.+countWhile :: (Word8 -> Bool) -> Bytes -> Int+{-# INLINE countWhile #-}+countWhile k (Bytes arr off0 len0) = go off0 len0 0+ where+  go !off !len !n =+    if len > 0+      then+        if k (PM.indexByteArray arr off)+          then go (off + 1) (len - 1) (n + 1)+          else n+      else n++-- Internal. Variant of countWhile that starts from the end+-- of the string instead of the beginning.+countWhileEnd :: (Word8 -> Bool) -> Bytes -> Int+{-# INLINE countWhileEnd #-}+countWhileEnd k (Bytes arr off0 len0) = go (off0 + len0 - 1) (len0 - 1) 0+ where+  go !off !len !n =+    if len >= 0+      then+        if k (PM.indexByteArray arr off)+          then go (off - 1) (len - 1) (n + 1)+          else n+      else n++-- | /O(n)/ Returns true if any byte in the sequence satisfies the predicate.+any :: (Word8 -> Bool) -> Bytes -> Bool+{-# INLINE any #-}+any f = foldr (\b r -> f b || r) False++-- | /O(n)/ Returns true if all bytes in the sequence satisfy the predicate.+all :: (Word8 -> Bool) -> Bytes -> Bool+{-# INLINE all #-}+all f = foldr (\b r -> f b && r) True+
src/Data/Bytes/Text/AsciiExt.hs view
@@ -1,6 +1,7 @@ {-# LANGUAGE BangPatterns #-} {-# LANGUAGE LambdaCase #-} {-# LANGUAGE RankNTypes #-}+{-# LANGUAGE TypeApplications #-}  -- For functions that can fail for bytes outside the ASCII range, see -- 'Data.Bytes.Ascii'. For functions that can inspect bytes outside ASCII, see@@ -19,6 +20,23 @@   , forLines_   , foldLines +    -- * Predicates+  , anyEq++    -- * Filtering+  , takeWhileNotEq+  , dropWhileNotEq+  , takeWhileEndNotEq+  , dropWhileEndEq++    -- * Splitting+    -- ** Fixed from Beginning+  , split1+  , splitTetragram1+  , split2+  , split3+  , split4+     -- * Text Manipulation   , toLowerU   ) where@@ -26,12 +44,14 @@ import Control.Monad.ST (ST) import Control.Monad.ST.Run (runByteArrayST) import Data.Bytes.Types (Bytes (..))+import Data.Char (ord) import Data.Primitive (ByteArray) import Data.Word (Word8) import System.IO (Handle, hIsEOF, stdin)  import qualified Data.ByteString.Char8 as BC8 import qualified Data.Bytes.Pure as Bytes+import qualified Data.Bytes.Byte as Byte import qualified Data.Primitive as PM  -- | `hForLines_` over `stdin`@@ -104,3 +124,85 @@               go (off + 1) (ix + 1) (len - 1)     go off0 0 len0     PM.unsafeFreezeByteArray dst++-- | Throws an exception the 'Char' argument is non-ascii.+split1 :: Char -> Bytes -> Maybe (Bytes, Bytes)+{-# INLINE split1 #-}+split1 !c !b+  | c > '\DEL' = errorWithoutStackTrace "Data.Bytes.Text.AsciiExt.split1: argument not in ASCII range"+  | otherwise = Byte.split1 (c2w c) b++-- | Throws an exception the 'Char' argument is non-ascii.+split2 :: Char -> Bytes -> Maybe (Bytes, Bytes, Bytes)+{-# INLINE split2 #-}+split2 !c !b+  | c > '\DEL' = errorWithoutStackTrace "Data.Bytes.Text.AsciiExt.split2: argument not in ASCII range"+  | otherwise = Byte.split2 (c2w c) b++-- | Throws an exception the 'Char' argument is non-ascii.+split3 :: Char -> Bytes -> Maybe (Bytes, Bytes, Bytes, Bytes)+{-# INLINE split3 #-}+split3 !c !b+  | c > '\DEL' = errorWithoutStackTrace "Data.Bytes.Text.AsciiExt.split3: argument not in ASCII range"+  | otherwise = Byte.split3 (c2w c) b++-- | Throws an exception the 'Char' argument is non-ascii.+split4 :: Char -> Bytes -> Maybe (Bytes, Bytes, Bytes, Bytes, Bytes)+{-# INLINE split4 #-}+split4 !c !b+  | c > '\DEL' = errorWithoutStackTrace "Data.Bytes.Text.AsciiExt.split4: argument not in ASCII range"+  | otherwise = Byte.split4 (c2w c) b++-- | Throws an exception if any of the 'Char' arguments are non-ascii.+splitTetragram1 :: Char -> Char -> Char -> Char -> Bytes -> Maybe (Bytes, Bytes)+{-# inline splitTetragram1 #-}+splitTetragram1 !c0 !c1 !c2 !c3 !b+  | c0 > '\DEL' || c1 > '\DEL' || c2 > '\DEL' || c3 > '\DEL' =+      errorWithoutStackTrace "Data.Bytes.Text.AsciiExt.splitTetragram1: one of the characters is not in ASCII range"+  | otherwise = Bytes.splitTetragram1 (c2w c0) (c2w c1) (c2w c2) (c2w c3) b++c2w :: Char -> Word8+{-# inline c2w #-}+c2w !c = fromIntegral @Int @Word8 (ord c)++-- | Throws an exception the 'Char' argument is non-ascii.+dropWhileNotEq :: Char -> Bytes -> Bytes+dropWhileNotEq !c !b+  | c > '\DEL' = errorWithoutStackTrace "Data.Bytes.Text.AsciiExt.dropWhileNotEq: argument not in ASCII range"+  | otherwise =+      let !w = c2w c+       in Bytes.unsafeDrop (Bytes.countWhile (/= w) b) b++-- | Throws an exception the 'Char' argument is non-ascii.+takeWhileNotEq :: Char -> Bytes -> Bytes+takeWhileNotEq !c !b+  | c > '\DEL' = errorWithoutStackTrace "Data.Bytes.Text.AsciiExt.takeWhileNotEq: argument not in ASCII range"+  | otherwise =+      let !w = c2w c+       in Bytes.unsafeTake (Bytes.countWhile (/= w) b) b+  +-- | Throws an exception the 'Char' argument is non-ascii.+takeWhileEndNotEq :: Char -> Bytes -> Bytes+takeWhileEndNotEq !c !b+  | c > '\DEL' = errorWithoutStackTrace "Data.Bytes.Text.AsciiExt.takeWhileEndNotEq: argument not in ASCII range"+  | otherwise =+      let !w = c2w c+          !n = Bytes.countWhileEnd (/=w) b+       in Bytes (array b) (offset b + Bytes.length b - n) n++-- | Throws an exception the 'Char' argument is non-ascii.+dropWhileEndEq :: Char -> Bytes -> Bytes+dropWhileEndEq !c !b+  | c > '\DEL' = errorWithoutStackTrace "Data.Bytes.Text.AsciiExt.dropWhileEndEq: argument not in ASCII range"+  | otherwise =+      let !w = c2w c+          !n = Bytes.countWhileEnd (==w) b+       in Bytes.unsafeTake (Bytes.length b - n) b++-- | Throws an exception the 'Char' argument is non-ascii.+anyEq :: Char -> Bytes -> Bool+anyEq !c !b+  | c > '\DEL' = errorWithoutStackTrace "Data.Bytes.Text.AsciiExt.takeWhileNotEq: argument not in ASCII range"+  | otherwise =+      let !w = c2w c+       in Bytes.any (==w) b