on master help sign in
Add location, implemented entirely on the Haskell side
commit7df2ee9ee3bb276cf928d1556c73302a3e6da7fd authorNeil Mitchell <ndmitchell@gmail.com> dateWed 30 Nov 2016, 19:08 (10 years ago) parent75e35de
1 file changed+16−2
src/Text/XML/Hexml.hs+16−2
src/Text/XML/Hexml.hs+16−2
@@ -1,11 +1,11 @@
1−{-# LANGUAGE RecordWildCards #-}
1+{-# LANGUAGE RecordWildCards, BangPatterns #-}
22
33-- | A module for fast first-approximation parsing of XML.
44-- Note that entities, e.g. @&amp;@, are not expanded.
55module Text.XML.Hexml(
66 Node, Attribute(..),
77 parse, render,
8− name, inner, outer,
8+ location, name, inner, outer,
99 attributes, children, contents,
1010 attributeBy, childrenBy
1111 ) where
@@ -179,3 +179,17 @@ attributeBy (Node src doc n) str = unsafePerformIO $ withForeignPtr doc $ \d ->
179179 BS.unsafeUseAsCStringLen str $ \(bs, len) -> do
180180 r <- node_attributeBy d n bs $ fromIntegral len
181181 return $ if r == nullPtr then Nothing else Just $ attrPeek src doc r
182+
183+-- | Find the starting location of a node, the '<' character.
184+-- The first character will be reported as @(line 1,column 1)@, because thats
185+-- how error messages typically do it.
186+location :: Node -> (Int, Int)
187+location n@(Node src _ _) = BS.foldl' f (pair 1 1) $ BS.take (fromIntegral i) src
188+ where
189+ pair !a !b = (a,b)
190+
191+ i = strStart $ nodeStr 2 n
192+ f (!line, !col) c
193+ | c == '\n' = pair (line+1) 1
194+ | c == '\t' = pair line (col+8)
195+ | otherwise = pair line (col+1)