From ce38867d46ee5dccb4916f0da32c9e52c197f26f Mon Sep 17 00:00:00 2001 From: Mike Pilgrem Date: Sat, 9 Nov 2024 22:35:11 +0000 Subject: [PATCH] Re CLC issue 292 Avoid using partial init and last --- lib/Data/Format.hs | 18 ++++++++++++++---- test/unix/Test/Format/Format.hs | 33 +++++++++++++++++++++++---------- 2 files changed, 37 insertions(+), 14 deletions(-) diff --git a/lib/Data/Format.hs b/lib/Data/Format.hs index 8adb892b..cc2ead64 100644 --- a/lib/Data/Format.hs +++ b/lib/Data/Format.hs @@ -1,3 +1,4 @@ +{-# LANGUAGE CPP #-} {-# LANGUAGE Safe #-} module Data.Format ( @@ -26,6 +27,9 @@ module Data.Format ( import Control.Monad.Fail import Data.Char +#if MIN_VERSION_base(4,19,0) +import Data.List (unsnoc) +#endif import Data.Void import Text.ParserCombinators.ReadP import Prelude hiding (fail) @@ -227,11 +231,17 @@ zeroPad Nothing s = s zeroPad (Just i) s = replicate (i - length s) '0' ++ s trimTrailing :: String -> String -trimTrailing "" = "" trimTrailing "." = "" -trimTrailing s - | last s == '0' = trimTrailing $ init s -trimTrailing s = s +trimTrailing s = case unsnoc s of + Nothing -> "" + Just (initial, '0') -> trimTrailing initial + _ -> s + +#if !MIN_VERSION_base(4,19,0) +unsnoc :: [a] -> Maybe ([a], a) +unsnoc = foldr (\x -> Just . maybe ([], x) (\(~(a, b)) -> (x : a, b))) Nothing +{-# INLINABLE unsnoc #-} +#endif showNumber :: Show t => SignOption -> Maybe Int -> t -> Maybe String showNumber signOpt mdigitcount t = diff --git a/test/unix/Test/Format/Format.hs b/test/unix/Test/Format/Format.hs index 9532f648..772d18cb 100644 --- a/test/unix/Test/Format/Format.hs +++ b/test/unix/Test/Format/Format.hs @@ -1,3 +1,4 @@ +{-# LANGUAGE CPP #-} {-# OPTIONS -fno-warn-orphans #-} module Test.Format.Format ( @@ -6,6 +7,9 @@ module Test.Format.Format ( import Data.Char import Data.Fixed as F +#if MIN_VERSION_base(4,19,0) +import Data.List (unsnoc) +#endif import Data.Time import Data.Time.Clock.POSIX import Foreign @@ -151,16 +155,25 @@ unixWorkarounds fmt s unixWorkarounds _ s = s compareFormat :: (String -> String) -> String -> TimeZone -> UTCTime -> Result -compareFormat _modUnix fmt zone _time - | last fmt == 'Z' && timeZoneName zone == "" = rejected -compareFormat modUnix fmt zone time = - let - ctime = utcToZonedTime zone time - haskellText = formatTime locale fmt ctime - unixText = unixFormatTime fmt zone time - expectedText = unixWorkarounds fmt (modUnix unixText) - in - assertEqualQC (show time ++ " with " ++ show zone) expectedText haskellText +compareFormat modUnix fmt zone time = case unsnoc fmt of + Nothing -> + error "compareFormat: The impossible happened! Format string is \"\"." + Just (_, lastChar) + | lastChar == 'Z' && timeZoneName zone == "" -> rejected + | otherwise -> + let + ctime = utcToZonedTime zone time + haskellText = formatTime locale fmt ctime + unixText = unixFormatTime fmt zone time + expectedText = unixWorkarounds fmt (modUnix unixText) + in + assertEqualQC (show time ++ " with " ++ show zone) expectedText haskellText + +#if !MIN_VERSION_base(4,19,0) +unsnoc :: [a] -> Maybe ([a], a) +unsnoc = foldr (\x -> Just . maybe ([], x) (\(~(a, b)) -> (x : a, b))) Nothing +{-# INLINABLE unsnoc #-} +#endif -- as found in http://www.opengroup.org/onlinepubs/007908799/xsh/strftime.html -- plus FgGklz