summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSam Truzjan <pxqr.sta@gmail.com>2013-10-04 13:58:00 +0400
committerSam Truzjan <pxqr.sta@gmail.com>2013-10-04 13:58:00 +0400
commit1c2440559d09a75789d36ebbf5030729354aea42 (patch)
tree64b7195d15cfd48038607293582b8f2b07a37ee9
parent2534b8aff490a9e38e927ffc77d0a2e37c17db77 (diff)
Add stubs for lenient decoding
-rw-r--r--src/Data/ByteString/Base32.hs20
-rw-r--r--src/Data/ByteString/Base32/Hex.hs2
-rw-r--r--src/Data/ByteString/Base32/Internal.hs46
3 files changed, 48 insertions, 20 deletions
diff --git a/src/Data/ByteString/Base32.hs b/src/Data/ByteString/Base32.hs
index e9ac3ee..0568c54 100644
--- a/src/Data/ByteString/Base32.hs
+++ b/src/Data/ByteString/Base32.hs
@@ -21,7 +21,6 @@ module Data.ByteString.Base32
21 ) where 21 ) where
22 22
23import Data.ByteString as BS 23import Data.ByteString as BS
24import Data.ByteString.Internal as BS
25import Data.ByteString.Base32.Internal 24import Data.ByteString.Base32.Internal
26import Data.List as L 25import Data.List as L
27 26
@@ -60,23 +59,6 @@ decTable = BS.pack $ L.map decW5 [minBound .. maxBound]
60decode :: Base32 -> ByteString 59decode :: Base32 -> ByteString
61decode = pack5 decTable 60decode = pack5 decTable
62 61
63decCharLenient :: Char -> Word5
64decCharLenient x
65 | x < '2' = err
66 | x <= '7' = 26 + fromIntegral (fromEnum x) - fromIntegral (fromEnum '2')
67 | x < 'A' = err
68 | x <= 'Z' = fromIntegral (fromEnum x) - fromIntegral (fromEnum 'A')
69 | x < 'a' = err
70 | x <= 'z' = fromIntegral (fromEnum x) - fromIntegral (fromEnum 'a')
71 | otherwise = err
72 where
73 err = error "base32: decodeChar: out of range"
74
75decW5Lenient :: Word8 -> Word5
76decW5Lenient = decCharLenient . w2c
77{-# INLINE decW5Lenient #-}
78
79-- TODO padding leniency
80-- | Case-insensitive counterpart of the 'decode'. 62-- | Case-insensitive counterpart of the 'decode'.
81decodeLenient :: Base32 -> ByteString 63decodeLenient :: Base32 -> ByteString
82decodeLenient = id -- pack5 nullPtr decW5Lenient \ No newline at end of file 64decodeLenient = pack5Lenient decTable \ No newline at end of file
diff --git a/src/Data/ByteString/Base32/Hex.hs b/src/Data/ByteString/Base32/Hex.hs
index ce7682b..db5fe1b 100644
--- a/src/Data/ByteString/Base32/Hex.hs
+++ b/src/Data/ByteString/Base32/Hex.hs
@@ -58,4 +58,4 @@ decode :: Base32Hex -> ByteString
58decode = pack5 decTable 58decode = pack5 decTable
59 59
60decodeLenient :: Base32Hex -> ByteString 60decodeLenient :: Base32Hex -> ByteString
61decodeLenient = id \ No newline at end of file 61decodeLenient = pack5Lenient decTable \ No newline at end of file
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