diff options
Diffstat (limited to 'src/Data/ByteString/Base32/Internal.hs')
-rw-r--r-- | src/Data/ByteString/Base32/Internal.hs | 46 |
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 | |||
237 | pack5PtrLenient :: Ptr Word5 -> ByteString -> ByteString | ||
238 | pack5PtrLenient !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 | |||
269 | pack5Lenient :: DecTable -> ByteString -> ByteString | ||
270 | pack5Lenient (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 | ||