xeno 0.4.2 → 0.4.3
raw patch · 4 files changed
+95/−80 lines, 4 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
Files
- CHANGELOG.markdown +6/−0
- src/Xeno/DOM.hs +3/−1
- src/Xeno/SAX.hs +85/−78
- xeno.cabal +1/−1
CHANGELOG.markdown view
@@ -1,3 +1,9 @@+ 0.4.3+ * Ensure we don't grow with a negative size in DOM parser (#48)+ * Flatten code nesting in process function (#45)+ * Introduce a whitespace-around-equals CPP flag (#44)+ * Use modify' instead of modify in fold (#42)+ 0.4.2 * all benchmarks marked as such in the Cabal file
src/Xeno/DOM.hs view
@@ -138,7 +138,9 @@ -- -- predictGrowSize _bsStart _bsLen _index vecLen = round $ fromIntegral vecLen * (1.25 :: Double) predictGrowSize bsStart bsLen index vecLen =- let processedLen = bsStart + bsLen - offset0+ let -- at least 1 so we don't divide by zero below and end up with + -- a negative grow size if (bsStart + bsLen - offset0) == 0+ processedLen = max 1 (bsStart + bsLen - offset0) -- 1. Using integral operations, such as -- "predictedTotalSize = (index * S.length str) `div` processedLen" -- cause overflow, so we use float.
src/Xeno/SAX.hs view
@@ -1,7 +1,6 @@ {-# LANGUAGE BangPatterns #-} {-# LANGUAGE BinaryLiterals #-} {-# LANGUAGE LambdaCase #-}-{-# LANGUAGE MultiWayIf #-} {-# LANGUAGE NamedFieldPuns #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE ScopedTypeVariables #-}@@ -192,12 +191,12 @@ spork (execState (process Process {- openF = \name -> modify (\s' -> openF s' name)- , attrF = \key value -> modify (\s' -> attrF s' key value)- , endOpenF = \name -> modify (\s' -> endOpenF s' name)- , textF = \text -> modify (\s' -> textF s' text)- , closeF = \name -> modify (\s' -> closeF s' name)- , cdataF = \cdata -> modify (\s' -> cdataF s' cdata)+ openF = \name -> modify' (\s' -> openF s' name)+ , attrF = \key value -> modify' (\s' -> attrF s' key value)+ , endOpenF = \name -> modify' (\s' -> endOpenF s' name)+ , textF = \text -> modify' (\s' -> textF s' text)+ , closeF = \name -> modify' (\s' -> closeF s' name)+ , cdataF = \cdata -> modify' (\s' -> cdataF s' cdata) } str) s) @@ -221,22 +220,24 @@ checkOpenComment (fromLt + 1) where text = substring' str index fromLt -- Find open comment, CDATA or tag name.- checkOpenComment index =- if | s_index' this 0 == bangChar -- !- && s_index' this 1 == commentChar -- -- && s_index' this 2 == commentChar -> -- -- findCommentEnd (index + 3)- | s_index' this 0 == bangChar -- !- && s_index' this 1 == openAngleBracketChar -- [- && s_index' this 2 == 67 -- C- && s_index' this 3 == 68 -- D- && s_index' this 4 == 65 -- A- && s_index' this 5 == 84 -- T- && s_index' this 6 == 65 -- A- && s_index' this 7 == openAngleBracketChar -> -- [- findCDataEnd (index + 8) (index + 8)- | otherwise ->- findTagName index+ checkOpenComment index+ | s_index' this 0 == bangChar -- !+ , s_index' this 1 == commentChar -- -+ , s_index' this 2 == commentChar -- -+ = findCommentEnd (index + 3)++ | s_index' this 0 == bangChar -- !+ , s_index' this 1 == openAngleBracketChar -- [+ , s_index' this 2 == 67 -- C+ , s_index' this 3 == 68 -- D+ , s_index' this 4 == 65 -- A+ , s_index' this 5 == 84 -- T+ , s_index' this 6 == 65 -- A+ , s_index' this 7 == openAngleBracketChar -- [+ = findCDataEnd (index + 8) (index + 8)++ | otherwise+ = findTagName index where this = drop' index str findCommentEnd index =@@ -258,68 +259,74 @@ else -- We only found one ], that means that we need to keep searching. findCDataEnd cdata_start (fromCloseAngleBracket + 1)- findTagName index0 =- let spaceOrCloseTag = parseName str index- in if | s_index' str index0 == questionChar ->- case elemIndexFrom' closeTagChar str spaceOrCloseTag of- Nothing -> throw $ XenoParseError index "Couldn't find the end of the tag."- Just fromGt -> do- findLT (fromGt + 1)- | s_index' str spaceOrCloseTag == closeTagChar ->- do let tagname = substring' str index spaceOrCloseTag- if s_index' str index0 == slashChar- then closeF tagname- else do- openF tagname- endOpenF tagname- findLT (spaceOrCloseTag + 1)- | otherwise ->- do let tagname = substring' str index spaceOrCloseTag- openF tagname- result <- findAttributes spaceOrCloseTag- endOpenF tagname- case result of- Right closingTag -> findLT (closingTag + 1)- Left closingPair -> do- closeF tagname- findLT (closingPair + 2)+ findTagName index0+ | s_index' str index0 == questionChar =+ case elemIndexFrom' closeTagChar str spaceOrCloseTag of+ Nothing -> throw $ XenoParseError index "Couldn't find the end of the tag."+ Just fromGt -> do+ findLT (fromGt + 1)+ | s_index' str spaceOrCloseTag == closeTagChar = do+ let tagname = substring' str index spaceOrCloseTag+ if s_index' str index0 == slashChar+ then closeF tagname+ else do+ openF tagname+ endOpenF tagname+ findLT (spaceOrCloseTag + 1)+ | otherwise = do+ let tagname = substring' str index spaceOrCloseTag+ openF tagname+ result <- findAttributes spaceOrCloseTag+ endOpenF tagname+ case result of+ Right closingTag -> findLT (closingTag + 1)+ Left closingPair -> do+ closeF tagname+ findLT (closingPair + 2) where index = if s_index' str index0 == slashChar then index0 + 1 else index0- findAttributes index0 =- if s_index' str index == slashChar &&- s_index' str (index + 1) == closeTagChar- then pure (Left index)- else if s_index' str index == closeTagChar- then pure (Right index)- else let afterAttrName = parseName str index- in if s_index' str afterAttrName == equalChar- then let quoteIndex = afterAttrName + 1- usedChar = s_index' str quoteIndex- in if usedChar == quoteChar ||- usedChar == doubleQuoteChar- then case elemIndexFrom'- usedChar- str- (quoteIndex + 1) of- Nothing ->- throw- (XenoParseError index "Couldn't find the matching quote character.")- Just endQuoteIndex -> do- attrF- (substring' str index afterAttrName)- (substring'- str- (quoteIndex + 1)- (endQuoteIndex))- findAttributes (endQuoteIndex + 1)- else throw- (XenoParseError index("Expected ' or \", got: " <> S.singleton usedChar))- else throw (XenoParseError index ("Expected =, got: " <> S.singleton (s_index' str afterAttrName) <> " at character index: " <> (S8.pack . show) afterAttrName))+ spaceOrCloseTag = parseName str index+ findAttributes index0+ -- case: />+ | s_index' str index == slashChar+ , s_index' str (index + 1) == closeTagChar+ = pure (Left index)++ -- case: >+ | s_index' str index == closeTagChar+ = pure (Right index)++ -- case: attr=' or attr="+ | s_index' str afterAttrName == equalChar+ , usedChar == quoteChar || usedChar == doubleQuoteChar+ = case elemIndexFrom' usedChar str (quoteIndex + 1) of+ Nothing ->+ throw+ (XenoParseError index "Couldn't find the matching quote character.")+ Just endQuoteIndex -> do+ attrF+ (substring' str index afterAttrName)+ (substring'+ str+ (quoteIndex + 1)+ (endQuoteIndex))+ findAttributes (endQuoteIndex + 1)++ -- case: attr= without following quote+ | s_index' str afterAttrName == equalChar+ = throw (XenoParseError index("Expected ' or \", got: " <> S.singleton usedChar))++ | otherwise+ = throw (XenoParseError index ("Expected =, got: " <> S.singleton (s_index' str afterAttrName) <> " at character index: " <> (S8.pack . show) afterAttrName)) where index = skipSpaces str index0+ afterAttrName = parseName str index+ quoteIndex = afterAttrName + 1+ usedChar = s_index' str quoteIndex+ {-# INLINE process #-} {-# SPECIALISE process :: Process (Identity ()) -> ByteString -> Identity () #-}
xeno.cabal view
@@ -1,5 +1,5 @@ name: xeno-version: 0.4.2+version: 0.4.3 synopsis: A fast event-based XML parser in pure Haskell description: A fast, low-memory use, event-based XML parser in pure Haskell. build-type: Simple