packages feed

cgrep-8.0.0: src/Util.hs

--
-- Copyright (c) 2013-2023 Nicola Bonelli <nicola@larthia.com>
--
-- This program is free software; you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation; either version 2 of the License, or
-- (at your option) any later version.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program; if not, write to the Free Software
-- Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
--

module Util where

import Data.Maybe ( listToMaybe )
import Data.Char ( toLower )

import qualified Data.ByteString.Char8 as C
import qualified Data.Sequence as S
import Data.Sequence ((|>), Seq((:<|), (:|>), Empty))
import Text.Read (readMaybe)

partitionM :: Monad m => (a -> m Bool) -> [a] -> m ([a], [a])
partitionM _ [] = return ([], [])
partitionM f (x:xs) = do
    res <- f x
    (as,bs) <- partitionM f xs
    return ([x | res]<>as, [x | not res]<>bs)
{-# INLINE partitionM #-}


xor :: Bool -> Bool -> Bool
a `xor` b = a && not b || not a && b
{-# INLINE xor #-}


prettyRead :: Read a => String -> String -> a
prettyRead xs err =
    case readMaybe xs of
        Just v -> v
        _      -> error $ err <> ": parse error near '" <> take 40 xs <> "'"


spanGroup :: Int -> [a] -> [[a]]
spanGroup _ [] = []
spanGroup 1 xs = map (: []) xs
spanGroup n xs = take n xs : spanGroup n (tail xs)
{-# INLINE spanGroup #-}


spanGroupSeq :: Int -> S.Seq a -> [S.Seq a]
spanGroupSeq _ S.Empty = []
spanGroupSeq 1 xs = [xs]
spanGroupSeq n xs = S.take n xs : spanGroupSeq n (S.drop 1 xs)
{-# INLINE spanGroupSeq #-}


rmQuote :: String -> String
rmQuote []   = []
rmQuote [x]  = [x]
rmQuote y@(x:xs)
    | x == '"' || x == '\'' =  if x == last xs then init xs
                                               else y
    | otherwise = y
{-# INLINE  rmQuote #-}


rmQuote8 :: C.ByteString -> C.ByteString
rmQuote8 b | C.length b < 2 = b
           | otherwise =
    case C.uncons b of
        Just (x,xs) -> if (x == '"' || x == '\'') && (x == C.last b) then C.init xs else b
        _ -> b
{-# INLINE  rmQuote8 #-}


mapMaybe' :: Foldable f => (a -> Maybe b) -> f a -> [b]
mapMaybe' f = foldr g []
  where
    g x rest
      | Just y <- f x = y : rest
      | otherwise     = rest


findWithIndex :: forall a. (a -> Bool) -> [a] -> (# Int, Maybe a #)
findWithIndex predicate = go predicate 0
  where
    go :: forall a. (a -> Bool) -> Int -> [a] -> (# Int, Maybe a #)
    go p _ [] = (# 0, Nothing #)
    go p !index (x:xs)
      | p x = (# index, Just x #)
      | otherwise = go p (index + 1) xs