on master help sign in
Write nodeChildreBy and nodeAttributeBy
commit6da2ecee566d91dbbc1f4aa1cc2f351351ae6a1d authorNeil Mitchell <ndmitchell@gmail.com> dateWed 30 Nov 2016, 19:08 (10 years ago) parentb17e7eb
3 files changed+28−20
cbits/hexml.c+15−13 cbits/hexml.h+2−3 src/Text/XML/Hexml.hs+11−4
cbits/hexml.c+15−13
@@ -190,31 +190,33 @@ attr* node_attributes(document* d, node* n, int* res)
190190
191191attr* node_attributeBy(document* d, node* n, char* s, int slen)
192192{
193− assert(0);
193+ if (slen == -1) slen = strlen(s);
194+ int i = n->attrs.start;
195+ int limit = end(n->attrs);
196+ for (i = n->attrs.start; i < limit; i++)
197+ {
198+ attr* r = &d->attrs.attrs[i];
199+ if (r->name.length == slen && memcmp(s, &d->body[r->name.start], slen) == 0)
200+ return r;
201+ }
194202 return NULL;
195203}
196204
197205// Search for given strings within a node
198−node* node_firstChildBy(document* d, node* n, char* s, int slen)
206+node* node_childBy(document* d, node* parent, node* prev, char* s, int slen)
199207{
200208 if (slen == -1) slen = strlen(s);
201− int i = n->nodes.start;
202− int limit = i + n->nodes.length;
209+ int i = prev == NULL ? parent->nodes.start : prev + 1 - d->nodes.nodes;
210+ int limit = end(parent->nodes);
203211 for (; i < limit; i++)
204212 {
205− if (d->nodes.nodes[i].name.length == slen &&
206− memcmp(s, &d->body[d->nodes.nodes[i].name.start], slen) == 0)
207− return &d->nodes.nodes[i];
213+ node* r = &d->nodes.nodes[i];
214+ if (r->name.length == slen && memcmp(s, &d->body[r->name.start], slen) == 0)
215+ return r;
208216 }
209217 return NULL;
210218}
211219
212−node* node_nextChildBy(document* d, node* parent, node* prev, char* s, int slen)
213−{
214− assert(0);
215− return NULL;
216−}
217−
218220
219221/////////////////////////////////////////////////////////////////////
220222// PARSE TABLE
cbits/hexml.h+2−3
@@ -48,7 +48,6 @@ node* document_node(document* d);
4848node* node_children(document* d, node* n, int* res);
4949attr* node_attributes(document* d, node* n, int* res);
5050
51−// Search for given strings within a node
52−node* node_firstChildBy(document* d, node* n, char* s, int slen);
53−node* node_nextChildBy(document* d, node* parent, node* prev, char* s, int slen);
51+// Search for given strings within a node, note that prev may be NULL
52+node* node_childBy(document* d, node* parent, node* prev, char* s, int slen);
5453attr* node_attributeBy(document* d, node* n, char* s, int slen);
src/Text/XML/Hexml.hs+11−4
@@ -51,8 +51,7 @@ foreign import ccall document_node :: Ptr CDocument -> IO (Ptr CNode)
5151foreign import ccall node_children :: Ptr CDocument -> Ptr CNode -> Ptr CInt -> IO (Ptr CNode)
5252foreign import ccall node_attributes :: Ptr CDocument -> Ptr CNode -> Ptr CInt -> IO (Ptr CAttr)
5353
54−foreign import ccall node_firstChildBy :: Ptr CDocument -> Ptr CNode -> CString -> CInt -> IO (Ptr CNode)
55−foreign import ccall node_nextChildBy :: Ptr CDocument -> Ptr CNode -> Ptr CNode -> CString -> CInt -> IO (Ptr CNode)
54+foreign import ccall node_childBy :: Ptr CDocument -> Ptr CNode -> Ptr CNode -> CString -> CInt -> IO (Ptr CNode)
5655foreign import ccall node_attributeBy :: Ptr CDocument -> Ptr CNode -> CString -> CInt -> IO (Ptr CAttr)
5756
5857data Document = Document BS.ByteString (ForeignPtr CDocument)
@@ -140,7 +139,15 @@ nodeAttributes (Node src doc n) = unsafePerformIO $ withForeignPtr doc $ \d -> d
140139 return [attrPeek src doc $ plusPtr res $ i*szAttr | i <- [0..count-1]]
141140
142141nodeChildrenBy :: Node -> BS.ByteString -> [Node]
143−nodeChildrenBy = node_firstChildBy `seq` node_nextChildBy `seq` undefined
142+nodeChildrenBy (Node src doc n) str = go nullPtr
143+ where
144+ go old = unsafePerformIO $ withForeignPtr doc $ \d ->
145+ BS.unsafeUseAsCStringLen str $ \(bs, len) -> do
146+ r <- node_childBy d n old bs $ fromIntegral len
147+ return $ if r == nullPtr then [] else Node src doc r : go r
144148
145149nodeAttributeBy :: Node -> BS.ByteString -> Maybe Attribute
146−nodeAttributeBy = node_attributeBy `seq` undefined
150+nodeAttributeBy (Node src doc n) str = unsafePerformIO $ withForeignPtr doc $ \d ->
151+ BS.unsafeUseAsCStringLen str $ \(bs, len) -> do
152+ r <- node_attributeBy d n bs $ fromIntegral len
153+ return $ if r == nullPtr then Nothing else Just $ attrPeek src doc r