summaryrefslogtreecommitdiff
path: root/src/Data/ByteString/Base32/Internal.hs
diff options
context:
space:
mode:
Diffstat (limited to 'src/Data/ByteString/Base32/Internal.hs')
-rw-r--r--src/Data/ByteString/Base32/Internal.hs46
1 files changed, 46 insertions, 0 deletions
diff --git a/src/Data/ByteString/Base32/Internal.hs b/src/Data/ByteString/Base32/Internal.hs
index c34e80c..725be37 100644
--- a/src/Data/ByteString/Base32/Internal.hs
+++ b/src/Data/ByteString/Base32/Internal.hs
@@ -18,6 +18,7 @@ module Data.ByteString.Base32.Internal
18 18
19 , DecTable 19 , DecTable
20 , pack5 20 , pack5
21 , pack5Lenient
21 , invIx 22 , invIx
22 ) where 23 ) where
23 24
@@ -228,3 +229,48 @@ pack5 (PS fptr off len) bs
228 unsafePerformIO $ do 229 unsafePerformIO $ do
229 withForeignPtr fptr $ \ptr -> 230 withForeignPtr fptr $ \ptr ->
230 return $ pack5Ptr (ptr `advancePtr` off) bs 231 return $ pack5Ptr (ptr `advancePtr` off) bs
232
233{-----------------------------------------------------------------------
234-- Lenient Decoding
235-----------------------------------------------------------------------}
236
237pack5PtrLenient :: Ptr Word5 -> ByteString -> ByteString
238pack5PtrLenient !tbl bs @ (PS fptr off sz) =
239 unsafePerformIO $ do
240 BS.createAndTrim (sz * 2) $ \ dst -> do
241 withForeignPtr fptr $ \ ptr -> do
242 dst_end <- smallStep dst (advancePtr ptr off) sz 0 0
243 return (dst_end `minusPtr` dst)
244 where
245 lookupTable :: Word8 -> Word5
246 lookupTable ix = inlinePerformIO (peekByteOff tbl (fromIntegral ix))
247 {-# INLINE lookupTable #-}
248
249 smallStep :: Ptr Word8 -> Ptr Word5 -> Int -> Word -> Int
250 -> IO (Ptr Word5)
251 smallStep !dst !src !s !unused !un_cnt
252 | un_cnt >= 8 = do
253 poke dst $ fromIntegral (unused `unsafeShiftR` (un_cnt - 8))
254 smallStep (dst `advancePtr` 1) src s unused (un_cnt - 8)
255
256 | s == 0 = return dst
257 | otherwise = do
258 w8 <- peek src
259 if w2c w8 == '='
260 then if (bit un_cnt - 1) .&. unused == 0
261 then smallStep dst src 0 0 0
262 else smallStep dst src 0 (unused `shiftL` (8 - un_cnt)) 8
263 else smallStep dst
264 (src `advancePtr` 1) (pred s)
265 ((unused `unsafeShiftL` 5)
266 .|. fromIntegral (lookupTable (fromIntegral w8)))
267 (un_cnt + 5)
268
269pack5Lenient :: DecTable -> ByteString -> ByteString
270pack5Lenient (PS fptr off len) bs
271 | len /= 256
272 = error $ "base32: pack5: invalid lookup table size " ++ show len
273 | otherwise =
274 unsafePerformIO $ do
275 withForeignPtr fptr $ \ptr ->
276 return $ pack5Ptr (ptr `advancePtr` off) bs