summaryrefslogtreecommitdiff
path: root/src/ZNC.hs
diff options
context:
space:
mode:
Diffstat (limited to 'src/ZNC.hs')
-rw-r--r--src/ZNC.hs61
1 files changed, 48 insertions, 13 deletions
diff --git a/src/ZNC.hs b/src/ZNC.hs
index 35eafe0..c23ffe2 100644
--- a/src/ZNC.hs
+++ b/src/ZNC.hs
@@ -2,6 +2,7 @@
module ZNC (
-- Log(..),
Nick, Event(..),
+ preparseLog,
parseLog, parseLogRange,
) where
@@ -14,15 +15,13 @@ import Data.Char (ord)
import Data.Either (fromRight)
import Data.Text (Text)
import Data.Text.Encoding qualified as TE
--- import Data.Vector qualified as V
--- import Data.Vector (Vector)
-import Data.Word (Word8)
+import Data.Vector.Storable qualified as VS
+import Data.Word (Word8, Word32)
-import Util
+import Debug.Trace
+import Util
--- newtype Log = Log (Vector (TOD, Event))
--- deriving (Show)
type Nick = Text
@@ -41,20 +40,56 @@ data Event
| ParseError
deriving (Show)
+preparseLog :: ByteString -> VS.Vector Word32
+preparseLog = VS.fromList . findLineStarts 0
+ where
+ findLineStarts :: Int -> ByteString -> [Word32]
+ findLineStarts off bs =
+ case BS.findIndex (== 10) (BS.drop off bs) of
+ Nothing | BS.length bs == off -> []
+ | otherwise -> [fromIntegral off]
+ Just i -> fromIntegral off : findLineStarts (off + i + 1) bs
+
-- these INLINE/NOINLINE pragmas are optimisation without testing or profiling, have fun
{-# INLINE parseLog #-}
parseLog :: ByteString -> [(HMS, Event)]
-parseLog = parseLogRange (0, Nothing)
+parseLog = map parseLogLine . BS8.lines
-- (start line, number of lines (default to rest of file))
{-# INLINE parseLogRange #-}
-parseLogRange :: (Int, Maybe Int) -> ByteString -> [(HMS, Event)]
-parseLogRange (startln, mnumln) =
- -- Log . V.fromList .
- map go . maybe id take mnumln . drop startln . BS8.lines
+parseLogRange :: (Int, Maybe Int) -> VS.Vector Word32 -> ByteString -> [(HMS, Event)]
+parseLogRange (startln, mnumln) linestarts topbs =
+ let numln = maybe (VS.length linestarts - startln) id mnumln
+ splitted = splitWithLineStarts 0 (VS.slice startln numln linestarts) topbs
+ in -- traceShow ("pLR"::String, splitted) $
+ map parseLogLine splitted
where
- {-# NOINLINE go #-}
- go = fromRight (HMS 0 0 0, ParseError) . P.parseOnly parseLine
+ {-# INLINE splitWithLineStarts #-}
+ splitWithLineStarts :: Int -> VS.Vector Word32 -> ByteString -> [ByteString]
+ splitWithLineStarts idx starts bs
+ | idx >= VS.length starts = []
+ | idx == VS.length starts - 1 =
+ [BS.takeWhile (\b -> b /= 13 && b /= 10) (BS.drop (at idx) bs)]
+ | otherwise =
+ trimCR (BS.drop (at idx) (BS.take (at (idx + 1) - 1) bs))
+ : splitWithLineStarts (idx + 1) starts bs
+ where
+ at i = fromIntegral @Word32 @Int (starts VS.! i)
+
+ trimCR :: ByteString -> ByteString
+ trimCR bs = case BS.unsnoc bs of
+ Just (bs', c) | c == 13 -> bs'
+ _ -> bs
+
+parseLogLine :: ByteString -> (HMS, Event)
+parseLogLine bs =
+ case parseLogLine' bs of
+ res@(HMS 0 0 0, ParseError) -> traceShow ("PE" :: String, bs) res
+ res -> res
+
+{-# NOINLINE parseLogLine' #-}
+parseLogLine' :: ByteString -> (HMS, Event)
+parseLogLine' = fromRight (HMS 0 0 0, ParseError) . P.parseOnly parseLine
parseLine :: P.Parser (HMS, Event)
parseLine = (,) <$> parseTOD <*> parseEvent