Add function for zero-padded decimal encoding of two digit numers
This commit is contained in:
parent
10ed08c77d
commit
2b85e2cb84
3 changed files with 35 additions and 3 deletions
|
@ -8,6 +8,7 @@
|
||||||
* Add `putManyConsLength`, useful for chunked HTTP encoding.
|
* Add `putManyConsLength`, useful for chunked HTTP encoding.
|
||||||
* Add `runOnto`
|
* Add `runOnto`
|
||||||
* Add `Data.Bytes.Chunks.length`
|
* Add `Data.Bytes.Chunks.length`
|
||||||
|
* Add `wordPaddedTwoDigitDec`
|
||||||
|
|
||||||
## 0.3.1.0 -- 2019-11-20
|
## 0.3.1.0 -- 2019-11-20
|
||||||
|
|
||||||
|
|
|
@ -51,6 +51,8 @@ module Data.ByteArray.Builder.Bounded
|
||||||
, word8LowerHex
|
, word8LowerHex
|
||||||
, ascii
|
, ascii
|
||||||
, char
|
, char
|
||||||
|
-- ** Native
|
||||||
|
, wordPaddedTwoDigitDec
|
||||||
-- ** Machine-Readable
|
-- ** Machine-Readable
|
||||||
-- *** One
|
-- *** One
|
||||||
, word8
|
, word8
|
||||||
|
@ -522,6 +524,22 @@ word8LowerHex# w#
|
||||||
where
|
where
|
||||||
w = W# w#
|
w = W# w#
|
||||||
|
|
||||||
|
-- | Encode a number less than 100 as a decimal number, zero-padding it to
|
||||||
|
-- two digits. For example: 0 is encoded as @00@, 5 is encoded as @05@, and
|
||||||
|
-- 73 is encoded as @73@.
|
||||||
|
--
|
||||||
|
-- Precondition: Argument less than 100. Failure to satisfy this precondition
|
||||||
|
-- will not result in a segfault, but the resulting bytes are undefined. The
|
||||||
|
-- implement uses a heuristic for division that is inaccurate for large
|
||||||
|
-- numbers.
|
||||||
|
wordPaddedTwoDigitDec :: Word -> Builder 2
|
||||||
|
wordPaddedTwoDigitDec !w = Unsafe.construct $ \arr off -> do
|
||||||
|
let d1 = approxDiv10 w
|
||||||
|
d2 = w - (10 * d1)
|
||||||
|
writeByteArray arr off (unsafeWordToWord8 (d1 + 48))
|
||||||
|
writeByteArray arr (off + 1) (unsafeWordToWord8 (d2 + 48))
|
||||||
|
pure (off + 2)
|
||||||
|
|
||||||
-- | Encode an ASCII character.
|
-- | Encode an ASCII character.
|
||||||
-- Precondition: Input must be an ASCII character. This is not checked.
|
-- Precondition: Input must be an ASCII character. This is not checked.
|
||||||
ascii :: Char -> Builder 1
|
ascii :: Char -> Builder 1
|
||||||
|
@ -561,9 +579,6 @@ char c
|
||||||
codepoint :: Word
|
codepoint :: Word
|
||||||
codepoint = fromIntegral (ord c)
|
codepoint = fromIntegral (ord c)
|
||||||
|
|
||||||
unsafeWordToWord8 :: Word -> Word8
|
|
||||||
unsafeWordToWord8 (W# w) = W8# w
|
|
||||||
|
|
||||||
-- precondition: codepoint is less than 0x800
|
-- precondition: codepoint is less than 0x800
|
||||||
byteTwoOne :: Word -> Word
|
byteTwoOne :: Word -> Word
|
||||||
byteTwoOne w = unsafeShiftR w 6 .|. 0b11000000
|
byteTwoOne w = unsafeShiftR w 6 .|. 0b11000000
|
||||||
|
@ -807,3 +822,10 @@ unIntST s0 (ST f) = case f s0 of
|
||||||
-- result anyway. Hmm...
|
-- result anyway. Hmm...
|
||||||
logBase10 :: Double -> Double
|
logBase10 :: Double -> Double
|
||||||
logBase10 d = log d / 2.30258509299
|
logBase10 d = log d / 2.30258509299
|
||||||
|
|
||||||
|
-- Based on C code from https://stackoverflow.com/a/5558614
|
||||||
|
approxDiv10 :: Word -> Word
|
||||||
|
approxDiv10 !n = unsafeShiftR (0x1999999A * n) 32
|
||||||
|
|
||||||
|
unsafeWordToWord8 :: Word -> Word8
|
||||||
|
unsafeWordToWord8 (W# w) = W8# w
|
||||||
|
|
|
@ -64,6 +64,10 @@ tests = testGroup "Tests"
|
||||||
runConcat 1 (word64PaddedUpperHex w)
|
runConcat 1 (word64PaddedUpperHex w)
|
||||||
===
|
===
|
||||||
pack (showWord64PaddedUpperHex w)
|
pack (showWord64PaddedUpperHex w)
|
||||||
|
, TQC.testProperty "wordPaddedTwoDigitDec" $ TQC.forAll (TQC.choose (0,99)) $ \w ->
|
||||||
|
Bounded.run Nat.two (Bounded.wordPaddedTwoDigitDec w)
|
||||||
|
===
|
||||||
|
pack (zeroPadL 2 (show w))
|
||||||
, TQC.testProperty "word8Dec" $ \w ->
|
, TQC.testProperty "word8Dec" $ \w ->
|
||||||
runConcat 1 (word8Dec w)
|
runConcat 1 (word8Dec w)
|
||||||
===
|
===
|
||||||
|
@ -278,3 +282,8 @@ c2w = fromIntegral . ord
|
||||||
|
|
||||||
instance Arbitrary Word128 where
|
instance Arbitrary Word128 where
|
||||||
arbitrary = liftA2 Word128 TQC.arbitrary TQC.arbitrary
|
arbitrary = liftA2 Word128 TQC.arbitrary TQC.arbitrary
|
||||||
|
|
||||||
|
zeroPadL :: Int -> String -> String
|
||||||
|
zeroPadL n s
|
||||||
|
| length s < n = replicate (n - length s) '0' ++ s
|
||||||
|
| otherwise = s
|
||||||
|
|
Loading…
Reference in a new issue