@@ -0,0 +1,84 @@
1+
2+module Text.XML.Hexml(
3+ Document, Node, Attribute(..),
4+ parse, render, rootNode,
5+ nodeInner, nodeOuter, nodeContents, nodeChildren, nodeAttributes,
6+ nodeChildrenBy, nodeAttributeBy
7+ ) where
8+
9+import Control.Monad
10+import Data.Int
11+import Foreign.C
12+import Foreign.Ptr
13+import Foreign.ForeignPtr
14+import System.IO.Unsafe
15+import Data.Monoid
16+import qualified Data.ByteString as BS
17+import qualified Data.ByteString.Unsafe as BS
18+import qualified Data.ByteString.Internal as BS
19+
20+data CDocument
21+data CNode
22+data CAttr
23+
24+data Str = Str {start :: {-# UNPACK #-} !Int32, length :: {-# UNPACK #-} !Int32}
25+
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)
32+
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)
36+
37+data Document = Document BS.ByteString (ForeignPtr CDocument)
38+
39+data Node = Node BS.ByteString (ForeignPtr CDocument) (Ptr CNode)
40+
41+data Attribute = Attribute BS.ByteString BS.ByteString
42+
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
49+ document_free doc
50+ return $ Left bs
51+ else do
52+ doc <- newForeignPtr document_free_funptr doc
53+ return $ Right $ Document src doc
54+
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
59+
60+
61+rootNode :: Document -> Node
62+rootNode d@(Document src doc) = unsafePerformIO $ withForeignPtr doc $ \d -> do
63+ Node src doc <$> document_node d
64+
65+nodeInner :: Node -> BS.ByteString
66+nodeInner (Node src doc i) = undefined
67+
68+nodeOuter :: Node -> BS.ByteString
69+nodeOuter = undefined
70+
71+nodeContents :: Node -> [Either Node BS.ByteString]
72+nodeContents = undefined
73+
74+nodeChildren :: Node -> [Node]
75+nodeChildren = undefined
76+
77+nodeAttributes :: Node -> [Attribute]
78+nodeAttributes = undefined
79+
80+nodeChildrenBy :: Node -> BS.ByteString -> [Node]
81+nodeChildrenBy = undefined
82+
83+nodeAttributeBy :: Node -> BS.ByteString -> Maybe Attribute
84+nodeAttributeBy = undefined