@@ -0,0 +1,84 @@
3+ Document, Node, Attribute(..),
4+ parse, render, rootNode,
5+ nodeInner, nodeOuter, nodeContents, nodeChildren, nodeAttributes,
6+ nodeChildrenBy, nodeAttributeBy
13+import Foreign.ForeignPtr
14+import System.IO.Unsafe
16+import qualified Data.ByteString as BS
17+import qualified Data.ByteString.Unsafe as BS
18+import qualified Data.ByteString.Internal as BS
24+data Str = Str {start :: {-# UNPACK #-} !Int32, length :: {-# UNPACK #-} !Int32}
26+foreign import ccall document_parse :: CString -> CInt -> IO (Ptr CDocument)
27+foreign import ccall document_free :: Ptr CDocument -> IO ()
28+foreign import ccall "&document_free" document_free_funptr :: FunPtr (Ptr CDocument -> IO ())
29+foreign import ccall document_render :: Ptr CDocument -> CString -> CInt -> IO CInt
30+foreign import ccall document_error :: Ptr CDocument -> IO CString
31+foreign import ccall document_node :: Ptr CDocument -> IO (Ptr CNode)
33+foreign import ccall node_firstChildBy :: Ptr CDocument -> Ptr CNode -> CString -> CInt -> IO (Ptr CNode)
34+foreign import ccall node_nextChildBy :: Ptr CDocument -> Ptr CNode -> Ptr CNode -> CString -> CInt -> IO (Ptr CNode)
35+foreign import ccall node_attributeBy :: Ptr CDocument -> Ptr CNode -> CString -> CInt -> IO (Ptr CAttr)
37+data Document = Document BS.ByteString (ForeignPtr CDocument)
39+data Node = Node BS.ByteString (ForeignPtr CDocument) (Ptr CNode)
41+data Attribute = Attribute BS.ByteString BS.ByteString
43+parse :: BS.ByteString -> Either BS.ByteString Document
44+parse src = unsafePerformIO $ BS.unsafeUseAsCStringLen (src <> BS.singleton 0) $ \(str, len) -> do
45+ doc <- document_parse str (fromIntegral len - 1)
46+ err <- document_error doc
47+ if err /= nullPtr then do
48+ bs <- BS.packCString =<< document_error doc
52+ doc <- newForeignPtr document_free_funptr doc
53+ return $ Right $ Document src doc
55+render :: Document -> BS.ByteString
56+render (Document _ doc) = unsafePerformIO $ withForeignPtr doc $ \d -> do
57+ i <- document_render d nullPtr 0
58+ BS.create (fromIntegral i) $ \ptr -> void $ document_render d (castPtr ptr) i
61+rootNode :: Document -> Node
62+rootNode d@(Document src doc) = unsafePerformIO $ withForeignPtr doc $ \d -> do
63+ Node src doc <$> document_node d
65+nodeInner :: Node -> BS.ByteString
66+nodeInner (Node src doc i) = undefined
68+nodeOuter :: Node -> BS.ByteString
71+nodeContents :: Node -> [Either Node BS.ByteString]
72+nodeContents = undefined
74+nodeChildren :: Node -> [Node]
75+nodeChildren = undefined
77+nodeAttributes :: Node -> [Attribute]
78+nodeAttributes = undefined
80+nodeChildrenBy :: Node -> BS.ByteString -> [Node]
81+nodeChildrenBy = undefined
83+nodeAttributeBy :: Node -> BS.ByteString -> Maybe Attribute
84+nodeAttributeBy = undefined