@@ -43,7 +43,7 @@ module Data.Attoparsec.Text.Internal
4343 -- * Efficient string handling
4444 , skipWhile
4545 , string
46− , stringTransform
46+ , stringCI
4747 , take
4848 , scan
4949 , takeWhile
@@ -224,10 +224,25 @@ string :: Text -> Parser Text
224224string s = takeWith (T.length s) (==s)
225225{-# INLINE string #-}
226226
227−stringTransform :: (Text -> Text) -> Text
228− -> Parser Text
229−stringTransform f s = takeWith (T.length s) ((==f s) . f)
230−{-# INLINE stringTransform #-}
227+-- | Satisfy a literal string, ignoring case.
228+--
229+-- Note: this function is currently quite inefficient. Unicode case
230+-- folding can change the length of a string (\"ß\" becomes
231+-- "ss"), which makes a simple, efficient implementation tricky. We
232+-- have (for now) chosen simplicity over efficiency.
233+stringCI :: Text -> Parser Text
234+stringCI s = go (T.length s)
235+ where
236+ go !n
237+ | n > T.length fs = fail "stringCI"
238+ | otherwise = do
239+ t <- ensure n
240+ let h = unsafeTake n t
241+ if T.toCaseFold h == fs
242+ then put (unsafeDrop n t) >> return h
243+ else go (n+1)
244+ fs = T.toCaseFold s
245+{-# INLINE stringCI #-}
231246
232247-- | Skip past input for as long as the predicate returns 'True'.
233248skipWhile :: (Char -> Bool) -> Parser ()