Skip to content

Commit 3042d4c

Browse files
committed
Re CLC issue 292 Avoid using partial init and last
1 parent 618b690 commit 3042d4c

File tree

2 files changed

+33
-14
lines changed

2 files changed

+33
-14
lines changed

lib/Data/Format.hs

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
{-# LANGUAGE CPP #-}
12
{-# LANGUAGE Safe #-}
23

34
module Data.Format (
@@ -26,6 +27,7 @@ module Data.Format (
2627

2728
import Control.Monad.Fail
2829
import Data.Char
30+
import qualified Data.List as L
2931
import Data.Void
3032
import Text.ParserCombinators.ReadP
3133
import Prelude hiding (fail)
@@ -227,11 +229,17 @@ zeroPad Nothing s = s
227229
zeroPad (Just i) s = replicate (i - length s) '0' ++ s
228230

229231
trimTrailing :: String -> String
230-
trimTrailing "" = ""
231232
trimTrailing "." = ""
232-
trimTrailing s
233-
| last s == '0' = trimTrailing $ init s
234-
trimTrailing s = s
233+
trimTrailing s = case L.unsnoc s of
234+
Nothing -> ""
235+
Just (initial, '0') -> trimTrailing initial
236+
_ -> s
237+
238+
#if !MIN_VERSION_base(4,19,0)
239+
unsnoc :: [a] -> Maybe ([a], a)
240+
unsnoc = foldr (\x -> Just . maybe ([], x) (\(~(a, b)) -> (x : a, b))) Nothing
241+
{-# INLINABLE unsnoc #-}
242+
#endif
235243

236244
showNumber :: Show t => SignOption -> Maybe Int -> t -> Maybe String
237245
showNumber signOpt mdigitcount t =

test/unix/Test/Format/Format.hs

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
{-# LANGUAGE CPP #-}
12
{-# OPTIONS -fno-warn-orphans #-}
23

34
module Test.Format.Format (
@@ -6,6 +7,7 @@ module Test.Format.Format (
67

78
import Data.Char
89
import Data.Fixed as F
10+
import qualified Data.List as L
911
import Data.Time
1012
import Data.Time.Clock.POSIX
1113
import Foreign
@@ -151,16 +153,25 @@ unixWorkarounds fmt s
151153
unixWorkarounds _ s = s
152154

153155
compareFormat :: (String -> String) -> String -> TimeZone -> UTCTime -> Result
154-
compareFormat _modUnix fmt zone _time
155-
| last fmt == 'Z' && timeZoneName zone == "" = rejected
156-
compareFormat modUnix fmt zone time =
157-
let
158-
ctime = utcToZonedTime zone time
159-
haskellText = formatTime locale fmt ctime
160-
unixText = unixFormatTime fmt zone time
161-
expectedText = unixWorkarounds fmt (modUnix unixText)
162-
in
163-
assertEqualQC (show time ++ " with " ++ show zone) expectedText haskellText
156+
compareFormat modUnix fmt zone time = case L.unsnoc fmt of
157+
Nothing ->
158+
error "compareFormat: The impossible happened! Format string is \"\"."
159+
Just (_, lastChar)
160+
| lastChar == 'Z' && timeZoneName zone == "" -> rejected
161+
| otherwise ->
162+
let
163+
ctime = utcToZonedTime zone time
164+
haskellText = formatTime locale fmt ctime
165+
unixText = unixFormatTime fmt zone time
166+
expectedText = unixWorkarounds fmt (modUnix unixText)
167+
in
168+
assertEqualQC (show time ++ " with " ++ show zone) expectedText haskellText
169+
170+
#if !MIN_VERSION_base(4,19,0)
171+
unsnoc :: [a] -> Maybe ([a], a)
172+
unsnoc = foldr (\x -> Just . maybe ([], x) (\(~(a, b)) -> (x : a, b))) Nothing
173+
{-# INLINABLE unsnoc #-}
174+
#endif
164175

165176
-- as found in http://www.opengroup.org/onlinepubs/007908799/xsh/strftime.html
166177
-- plus FgGklz

0 commit comments

Comments
 (0)