{-# LANGUAGE DeriveFunctor #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE OverloadedRecordDot #-}
{-# LANGUAGE PatternSynonyms #-}
module Text.Newline.LineMap
( Line(..)
, display
, breakLines_unixUtf8
, breakLine_unixUtf8
) where
import Prelude hiding (length)
import Text.Newline (Newline,pattern Unix)
import qualified Data.ByteString.Lazy as LBS
data Line a = Line
{ forall a. Line a -> Int
startOffset :: {-# UNPACK #-} !Int
, forall a. Line a -> a
content :: a
, forall a. Line a -> Maybe Newline
nlType :: Maybe Newline
, forall a. Line a -> Int
length :: {-# UNPACK #-} !Int
}
deriving ((forall a b. (a -> b) -> Line a -> Line b)
-> (forall a b. a -> Line b -> Line a) -> Functor Line
forall a b. a -> Line b -> Line a
forall a b. (a -> b) -> Line a -> Line b
forall (f :: * -> *).
(forall a b. (a -> b) -> f a -> f b)
-> (forall a b. a -> f b -> f a) -> Functor f
<$ :: forall a b. a -> Line b -> Line a
$c<$ :: forall a b. a -> Line b -> Line a
fmap :: forall a b. (a -> b) -> Line a -> Line b
$cfmap :: forall a b. (a -> b) -> Line a -> Line b
Functor)
display :: [Line a] -> String
display :: forall a. [Line a] -> [Char]
display [Line a]
ls0 = [Char]
"offset,length,terminator\n" [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Line a] -> [Char]
forall {a} {a} {r}.
(Show a, Show a, HasField "length" r a, HasField "startOffset" r a,
HasField "nlType" r (Maybe Newline)) =>
[r] -> [Char]
go [Line a]
ls0
where
go :: [r] -> [Char]
go [] = [Char]
""
go (r
l:[r]
ls) = r -> [Char]
forall {a} {a} {r}.
(Show a, Show a, HasField "length" r a, HasField "startOffset" r a,
HasField "nlType" r (Maybe Newline)) =>
r -> [Char]
go1 r
l [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [r] -> [Char]
go [r]
ls
go1 :: r -> [Char]
go1 r
l = [[Char]] -> [Char]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat
[ a -> [Char]
forall a. Show a => a -> [Char]
show r
l.startOffset
, [Char]
","
, a -> [Char]
forall a. Show a => a -> [Char]
show r
l.length
, [Char]
","
, case r
l.nlType of
Maybe Newline
Nothing -> [Char]
"eof"
Just Newline
Unix -> [Char]
"unix"
Maybe Newline
_ -> [Char]
"<UNKNOWN>"
, [Char]
"\n"
]
breakLines_unixUtf8 ::
LBS.ByteString
-> [Line LBS.ByteString]
breakLines_unixUtf8 :: ByteString -> [Line ByteString]
breakLines_unixUtf8 = Int -> ByteString -> [Line ByteString]
go Int
0
where
go :: Int -> ByteString -> [Line ByteString]
go Int
_ ByteString
bs | ByteString -> Bool
LBS.null ByteString
bs = []
go Int
off ByteString
bs =
let (Line ByteString
l, ByteString
bs') = Int -> ByteString -> (Line ByteString, ByteString)
breakLine_unixUtf8 Int
off ByteString
bs
off' :: Int
off' = Int
off Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Line ByteString
l.length
in Line ByteString
l Line ByteString -> [Line ByteString] -> [Line ByteString]
forall a. a -> [a] -> [a]
: Int -> ByteString -> [Line ByteString]
go Int
off' ByteString
bs'
breakLine_unixUtf8 ::
Int
-> LBS.ByteString
-> (Line LBS.ByteString, LBS.ByteString)
breakLine_unixUtf8 :: Int -> ByteString -> (Line ByteString, ByteString)
breakLine_unixUtf8 Int
off ByteString
bs =
let (ByteString
pre, ByteString
atpost) = (Word8 -> Bool) -> ByteString -> (ByteString, ByteString)
LBS.break (Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
==Word8
0x0A) ByteString
bs
in case ByteString -> Maybe (Word8, ByteString)
LBS.uncons ByteString
atpost of
Maybe (Word8, ByteString)
Nothing -> (Line ByteString
l, ByteString
atpost)
where
l :: Line ByteString
l = Line
{ startOffset :: Int
startOffset = Int
off
, content :: ByteString
content = ByteString
pre
, nlType :: Maybe Newline
nlType = Maybe Newline
forall a. Maybe a
Nothing
, length :: Int
length = Int64 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int64 -> Int) -> Int64 -> Int
forall a b. (a -> b) -> a -> b
$ ByteString -> Int64
LBS.length ByteString
pre
}
Just (Word8
0x0A, ByteString
post) -> (Line ByteString
l, ByteString
post)
where
l :: Line ByteString
l = Line
{ startOffset :: Int
startOffset = Int
off
, content :: ByteString
content = ByteString
pre
, nlType :: Maybe Newline
nlType = Newline -> Maybe Newline
forall a. a -> Maybe a
Just Newline
Unix
, length :: Int
length = Int64 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int64 -> Int) -> Int64 -> Int
forall a b. (a -> b) -> a -> b
$ ByteString -> Int64
LBS.length ByteString
pre Int64 -> Int64 -> Int64
forall a. Num a => a -> a -> a
+ Int64
1
}
Just (Word8
c, ByteString
_) -> [Char] -> (Line ByteString, ByteString)
forall a. [Char] -> a
errorWithoutStackTrace ([Char] -> (Line ByteString, ByteString))
-> [Char] -> (Line ByteString, ByteString)
forall a b. (a -> b) -> a -> b
$
[Char]
"internal error: newline delimited by byte " [Char] -> [Char] -> [Char]
forall a. Semigroup a => a -> a -> a
<> Word8 -> [Char]
forall a. Show a => a -> [Char]
show Word8
c