bytesmith 0.3.2.0 → 0.3.3.0
raw patch · 3 files changed
+95/−4 lines, 3 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
+ Data.Bytes.Parser.Latin: hexFixedWord8 :: e -> Parser e s Word8
+ Data.Bytes.Parser.Latin: hexWord16 :: e -> Parser e s Word16
+ Data.Bytes.Parser.Latin: hexWord8 :: e -> Parser e s Word8
Files
- CHANGELOG.md +4/−1
- bytesmith.cabal +2/−2
- src/Data/Bytes/Parser/Latin.hs +89/−1
CHANGELOG.md view
@@ -1,6 +1,9 @@ # Revision history for bytesmith -## 0.3.2.0 -- 2019-??-??+## 0.3.3.0 -- 2020-01-22+* Add `hexWord8`, `hexWord16`, and `hexFixedWord8`.++## 0.3.2.0 -- 2019-12-27 * Add `parseBytesEither` and `parseBytesMaybe`. * Add common idioms from other parser libaries. This includes: `satisfy`,
bytesmith.cabal view
@@ -1,6 +1,6 @@ cabal-version: 2.2 name: bytesmith-version: 0.3.2.0+version: 0.3.3.0 synopsis: Nonresumable byte parser description: Parse bytes as fast as possible. This is a nonresumable parser@@ -31,7 +31,7 @@ build-depends: , base >=4.12 && <5 , bytestring >=0.10.8 && <0.11- , byteslice >=0.1.3 && <0.3+ , byteslice >=0.1.4 && <0.3 , contiguous >= 0.4 && < 0.6 , primitive >=0.7 && <0.8 , text-short >=0.1.3 && <0.2
src/Data/Bytes/Parser/Latin.hs view
@@ -66,7 +66,13 @@ , decUnsignedInteger , decTrailingInteger -- ** Hexadecimal+ -- *** Variable Length+ , hexWord8+ , hexWord16+ -- *** Fixed Length+ , hexFixedWord8 , hexFixedWord16+ -- *** Digit , hexNibbleLower , tryHexNibbleLower , hexNibble@@ -398,6 +404,26 @@ (# s1, r #) -> (# s1, upcastWord8Result r #) ) +-- | Parse a hexadecimal-encoded 8-bit word. If the number is larger+-- than 255, this parser fails. This allows leading zeroes and is+-- insensitive to case. For example, @00A@, @0a@ and @A@ would all+-- be accepted as the same number.+hexWord8 :: e -> Parser e s Word8+hexWord8 e = Parser+ (\chunk0 s0 -> case hexSmallWordStart e 256 (boxBytes chunk0) s0 of+ (# s1, r #) -> (# s1, upcastWord8Result r #)+ )++-- | Parse a hexadecimal-encoded 16-bit word. If the number is larger+-- than 65535, this parser fails. This allows leading zeroes and is+-- insensitive to case. For example, @0100a@ and @100A@ would both+-- be accepted as the same number.+hexWord16 :: e -> Parser e s Word16+hexWord16 e = Parser+ (\chunk0 s0 -> case hexSmallWordStart e 65536 (boxBytes chunk0) s0 of+ (# s1, r #) -> (# s1, upcastWord16Result r #)+ )+ -- | Parse a decimal-encoded 16-bit word. If the number is larger -- than 65535, this parser fails. decWord16 :: e -> Parser e s Word16@@ -434,6 +460,17 @@ (# s1, r #) -> (# s1, upcastWord64Result r #) ) +hexSmallWordStart ::+ e -- Error message+ -> Word -- Upper Bound+ -> Bytes -- Chunk+ -> ST# s (Result# e Word# )+hexSmallWordStart e !limit !chunk0 s0 = if length chunk0 > 0+ then case oneHexMaybe (PM.indexByteArray (array chunk0) (offset chunk0)) of+ Nothing -> (# s0, (# e | #) #)+ Just w -> (# s0, hexSmallWordMore e w limit (Bytes.unsafeDrop 1 chunk0) #)+ else (# s0, (# e | #) #)+ decSmallWordStart :: e -- Error message -> Word -- Upper Bound@@ -479,6 +516,21 @@ upcastWord64Result (# e | #) = (# e | #) upcastWord64Result (# | (# a, b, c #) #) = (# | (# W64# a, b, c #) #) +hexSmallWordMore ::+ e -- Error message+ -> Word -- Accumulator+ -> Word -- Upper Bound+ -> Bytes -- Chunk+ -> Result# e Word#+hexSmallWordMore e !acc !limit !chunk0 = if length chunk0 > 0+ then case oneHexMaybe (PM.indexByteArray (array chunk0) (offset chunk0)) of+ Nothing -> (# | (# unW acc, unI (offset chunk0), unI (length chunk0) #) #)+ Just w -> let w' = acc * 16 + w in+ if w' < limit+ then hexSmallWordMore e w' limit (Bytes.unsafeDrop 1 chunk0)+ else (# e | #)+ else (# | (# unW acc, unI (offset chunk0), 0# #) #)+ decSmallWordMore :: e -- Error message -> Word -- Accumulator@@ -842,7 +894,7 @@ else (# | (# (), unI (offset c + 1), unI (length c - 1) #) #) -- | Parse exactly four ASCII-encoded characters, interpretting--- them as the hexadecimal encoding of a 32-bit number. Note that+-- them as the hexadecimal encoding of a 16-bit number. Note that -- this rejects a sequence such as @5A9@, requiring @05A9@ instead. -- This is insensitive to case. This is particularly useful when -- parsing escape sequences in C or JSON, which allow encoding@@ -875,6 +927,34 @@ | otherwise -> (# e | #) else (# e | #) +-- | Parse exactly two ASCII-encoded characters, interpretting+-- them as the hexadecimal encoding of a 8-bit number. Note that+-- this rejects a sequence such as @A@, requiring @0A@ instead.+-- This is insensitive to case.+hexFixedWord8 :: e -> Parser e s Word8+{-# inline hexFixedWord8 #-}+hexFixedWord8 e = Parser+ (\x s0 -> case runParser (hexFixedWord8# e) x s0 of+ (# s1, r #) -> case r of+ (# err | #) -> (# s1, (# err | #) #)+ (# | (# a, b, c #) #) -> (# s1, (# | (# W8# a, b, c #) #) #)+ )++hexFixedWord8# :: e -> Parser e s Word#+{-# noinline hexFixedWord8# #-}+hexFixedWord8# e = uneffectfulWord# $ \chunk -> if length chunk >= 2+ then+ let !w0@(W# n0) = oneHex $ PM.indexByteArray (array chunk) (offset chunk)+ !w1@(W# n1) = oneHex $ PM.indexByteArray (array chunk) (offset chunk + 1)+ in if | w0 .|. w1 /= maxBound ->+ (# |+ (# (n0 `Exts.timesWord#` 16##) `Exts.plusWord#`+ n1+ , unI (offset chunk) +# 2#+ , unI (length chunk) -# 2# #) #)+ | otherwise -> (# e | #)+ else (# e | #)+ -- | Consume a single character that is the lowercase hexadecimal -- encoding of a 4-bit word. Fails if the character is not in the class -- @[a-f0-9]@.@@ -935,6 +1015,14 @@ | w >= 65 && w < 71 = (fromIntegral w - 55) | w >= 97 && w < 103 = (fromIntegral w - 87) | otherwise = maxBound++oneHexMaybe :: Word8 -> Maybe Word+{-# inline oneHexMaybe #-}+oneHexMaybe w+ | w >= 48 && w < 58 = Just (fromIntegral w - 48)+ | w >= 65 && w < 71 = Just (fromIntegral w - 55)+ | w >= 97 && w < 103 = Just (fromIntegral w - 87)+ | otherwise = Nothing uneffectfulWord# :: (Bytes -> Result# e Word#) -> Parser e s Word# uneffectfulWord# f = Parser