{-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE RankNTypes #-} module HaskellWorks.Data.Json.Internal.Backend.Standard.MakeIndex ( blankedJsonToInterestBits , byteStringToBits , blankedJsonToBalancedParens , compressWordAsBit , interestingWord8s ) where import Control.Monad import Data.Array.Unboxed ((!)) import Data.ByteString (ByteString) import Data.Int import Data.Word import Data.Word8 import HaskellWorks.Data.Bits.BitWise import Prelude as P import qualified Data.Array.Unboxed as A import qualified Data.Bits as BITS import qualified Data.ByteString as BS interestingWord8s :: A.UArray Word8 Word8 interestingWord8s = A.array (0, 255) [ (w, if w == _bracketleft || w == _braceleft || w == _parenleft || w == _t || w == _f || w == _n || w == _1 then 1 else 0) | w <- [0 .. 255]] blankedJsonToInterestBits :: [BS.ByteString] -> [BS.ByteString] blankedJsonToInterestBits = blankedJsonToInterestBits' "" padRight :: Word8 -> Int -> BS.ByteString -> BS.ByteString padRight w n bs = if BS.length bs >= n then bs else fst (BS.unfoldrN n gen bs) where gen :: ByteString -> Maybe (Word8, ByteString) gen cs = case BS.uncons cs of Just (c, ds) -> Just (c, ds) Nothing -> Just (w, BS.empty) blankedJsonToInterestBits' :: BS.ByteString -> [BS.ByteString] -> [BS.ByteString] blankedJsonToInterestBits' rs as = case as of (bs:bss) -> let cs = if BS.length rs /= 0 then BS.concat [rs, bs] else bs in let lencs = BS.length cs in let q = lencs + 7 `quot` 8 in let (ds, es) = BS.splitAt (q * 8) cs in let (fs, _) = BS.unfoldrN q gen ds in fs:blankedJsonToInterestBits' es bss [] -> [] where gen :: ByteString -> Maybe (Word8, ByteString) gen ds = if BS.length ds == 0 then Nothing else Just ( BS.foldr (\b m -> (interestingWord8s ! b) .|. (m .<. 1)) 0 (padRight 0 8 (BS.take 8 ds)) , BS.drop 8 ds ) repartitionMod8 :: BS.ByteString -> BS.ByteString -> (BS.ByteString, BS.ByteString) repartitionMod8 aBS bBS = (BS.take cLen abBS, BS.drop cLen abBS) where abBS = BS.concat [aBS, bBS] abLen = BS.length abBS cLen = (abLen `div` 8) * 8 compressWordAsBit :: [BS.ByteString] -> [BS.ByteString] compressWordAsBit = compressWordAsBit' BS.empty compressWordAsBit' :: BS.ByteString -> [BS.ByteString] -> [BS.ByteString] compressWordAsBit' aBS as = case as of (bBS:bBSs) -> let (cBS, dBS) = repartitionMod8 aBS bBS in let (cs, _) = BS.unfoldrN (BS.length cBS + 7 `div` 8) gen cBS in cs:compressWordAsBit' dBS bBSs [] -> do let (cs, _) = BS.unfoldrN (BS.length aBS + 7 `div` 8) gen aBS [cs] where gen :: ByteString -> Maybe (Word8, ByteString) gen xs = if BS.length xs == 0 then Nothing else Just ( BS.foldr (\b m -> ((b .&. 1) .|. (m .<. 1))) 0 (padRight 0 8 (BS.take 8 xs)) , BS.drop 8 xs ) blankedJsonToBalancedParens :: [BS.ByteString] -> [BS.ByteString] blankedJsonToBalancedParens as = case as of (bs:bss) -> let (cs, _) = BS.unfoldrN (BS.length bs * 2) gen (Nothing, bs) in cs:blankedJsonToBalancedParens bss [] -> [] where gen :: (Maybe Bool, ByteString) -> Maybe (Word8, (Maybe Bool, ByteString)) gen (Just True , bs) = Just (0xFF, (Nothing, bs)) gen (Just False , bs) = Just (0x00, (Nothing, bs)) gen (Nothing , bs) = case BS.uncons bs of Just (c, cs) -> case balancedParensOf c of MiniN -> gen (Nothing , cs) MiniT -> Just (0xFF, (Nothing , cs)) MiniF -> Just (0x00, (Nothing , cs)) MiniTF -> Just (0xFF, (Just False , cs)) Nothing -> Nothing data MiniBP = MiniN | MiniT | MiniF | MiniTF balancedParensOf :: Word8 -> MiniBP balancedParensOf c = case c of d | d == _braceleft -> MiniT d | d == _braceright -> MiniF d | d == _bracketleft -> MiniT d | d == _bracketright -> MiniF d | d == _parenleft -> MiniT d | d == _parenright -> MiniF d | d == _t -> MiniTF d | d == _f -> MiniTF d | d == _1 -> MiniTF d | d == _n -> MiniTF _ -> MiniN yieldBitsOfWord8 :: Word8 -> [Bool] -> [Bool] yieldBitsOfWord8 w = (((w .&. BITS.bit 0) /= 0):) . (((w .&. BITS.bit 1) /= 0):) . (((w .&. BITS.bit 2) /= 0):) . (((w .&. BITS.bit 3) /= 0):) . (((w .&. BITS.bit 4) /= 0):) . (((w .&. BITS.bit 5) /= 0):) . (((w .&. BITS.bit 6) /= 0):) . (((w .&. BITS.bit 7) /= 0):) yieldBitsofWord8s :: [Word8] -> [Bool] -> [Bool] yieldBitsofWord8s = P.foldr ((>>) . yieldBitsOfWord8) id byteStringToBits :: [BS.ByteString] -> [Bool] -> [Bool] byteStringToBits as = case as of (bs:bss) -> yieldBitsofWord8s (BS.unpack bs) . byteStringToBits bss [] -> id