diff --git a/src/Data/ByteArray/Builder/Bounded.hs b/src/Data/ByteArray/Builder/Bounded.hs index 622aecd..764a36f 100644 --- a/src/Data/ByteArray/Builder/Bounded.hs +++ b/src/Data/ByteArray/Builder/Bounded.hs @@ -172,7 +172,7 @@ word16Dec (W16# w) = wordCommonDec# w -- | Requires up to 3 bytes. Encodes an unsigned 8-bit integer as decimal. -- This encoding never starts with a zero unless the argument was zero. word8Dec :: Word8 -> Builder 3 -word8Dec (W8# w) = wordCommonDec# w +word8Dec (W8# w) = word8Dec# w -- | Requires up to 19 bytes. Encodes an unsigned machine-sized integer -- as decimal. This encoding never starts with a zero unless the argument @@ -215,6 +215,22 @@ int8Dec (I8# w) = intCommonDec# w intDec :: Int -> Builder 20 intDec (I# w) = intCommonDec# w +word8Dec# :: Word# -> Builder 3 +{-# noinline word8Dec# #-} +word8Dec# w# = Unsafe.construct $ \arr off0 -> do + let !(I# off0# ) = off0 + !(!x,!ones) = quotRem w 10 + !(hundreds@(W# hundreds# ),tens@(W# tens# )) = quotRem x 10 + writeByteArray arr off0 (fromIntegral (hundreds + 0x30) :: Word8) + let !hasHundreds = gtWord# hundreds# 0## + !off1@(I# off1# ) = I# (off0# +# hasHundreds) + writeByteArray arr off1 (fromIntegral (tens + 0x30) :: Word8) + let !off2 = I# (off1# +# (orI# hasHundreds (gtWord# tens# 0## ))) + writeByteArray arr off2 (fromIntegral (ones + 0x30) :: Word8) + pure (off2 + 1) + where + w = W# w# + -- Requires a number of bytes that is bounded by the size of -- the word. This is only used internally. wordCommonDec# :: Word# -> Builder n diff --git a/test/Main.hs b/test/Main.hs index 6a2e6f8..19ef7b7 100644 --- a/test/Main.hs +++ b/test/Main.hs @@ -53,6 +53,10 @@ tests = testGroup "Tests" run 1 (word64PaddedUpperHex w) === pack (showWord64PaddedUpperHex w) + , TQC.testProperty "word8Dec" $ \w -> + run 1 (word8Dec w) + === + pack (show w) , TQC.testProperty "pasteArrayST" $ \(xs :: [Word64]) -> (runArray word64Dec (V.fromList xs)) ===