diff options
author | Sam Truzjan <pxqr.sta@gmail.com> | 2013-10-04 13:58:00 +0400 |
---|---|---|
committer | Sam Truzjan <pxqr.sta@gmail.com> | 2013-10-04 13:58:00 +0400 |
commit | 1c2440559d09a75789d36ebbf5030729354aea42 (patch) | |
tree | 64b7195d15cfd48038607293582b8f2b07a37ee9 | |
parent | 2534b8aff490a9e38e927ffc77d0a2e37c17db77 (diff) |
Add stubs for lenient decoding
-rw-r--r-- | src/Data/ByteString/Base32.hs | 20 | ||||
-rw-r--r-- | src/Data/ByteString/Base32/Hex.hs | 2 | ||||
-rw-r--r-- | src/Data/ByteString/Base32/Internal.hs | 46 |
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 | ||
23 | import Data.ByteString as BS | 23 | import Data.ByteString as BS |
24 | import Data.ByteString.Internal as BS | ||
25 | import Data.ByteString.Base32.Internal | 24 | import Data.ByteString.Base32.Internal |
26 | import Data.List as L | 25 | import Data.List as L |
27 | 26 | ||
@@ -60,23 +59,6 @@ decTable = BS.pack $ L.map decW5 [minBound .. maxBound] | |||
60 | decode :: Base32 -> ByteString | 59 | decode :: Base32 -> ByteString |
61 | decode = pack5 decTable | 60 | decode = pack5 decTable |
62 | 61 | ||
63 | decCharLenient :: Char -> Word5 | ||
64 | decCharLenient 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 | |||
75 | decW5Lenient :: Word8 -> Word5 | ||
76 | decW5Lenient = decCharLenient . w2c | ||
77 | {-# INLINE decW5Lenient #-} | ||
78 | |||
79 | -- TODO padding leniency | ||
80 | -- | Case-insensitive counterpart of the 'decode'. | 62 | -- | Case-insensitive counterpart of the 'decode'. |
81 | decodeLenient :: Base32 -> ByteString | 63 | decodeLenient :: Base32 -> ByteString |
82 | decodeLenient = id -- pack5 nullPtr decW5Lenient \ No newline at end of file | 64 | decodeLenient = 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 | |||
58 | decode = pack5 decTable | 58 | decode = pack5 decTable |
59 | 59 | ||
60 | decodeLenient :: Base32Hex -> ByteString | 60 | decodeLenient :: Base32Hex -> ByteString |
61 | decodeLenient = id \ No newline at end of file | 61 | decodeLenient = 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 | |||
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 | ||