on master help sign in
Write nodeChildreBy and nodeAttributeBy
6da2eceNeil Mitchell
cbits/hexml.c+15−13
@@ -190,31 +190,33 @@ attr* node_attributes(document* d, node* n, int* res)
190
190
191attr* node_attributeBy(document* d, node* n, char* s, int slen)
191attr* node_attributeBy(document* d, node* n, char* s, int slen)
192{
192{
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+ }
194 return NULL;
202 return NULL;
195}
203}
196
204
197// Search for given strings within a node
205// 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)
199{
207{
200 if (slen == -1) slen = strlen(s);
208 if (slen == -1) slen = strlen(s);
201− int i = n->nodes.start;
209+ int i = prev == NULL ? parent->nodes.start : prev + 1 - d->nodes.nodes;
202− int limit = i + n->nodes.length;
210+ int limit = end(parent->nodes);
203 for (; i < limit; i++)
211 for (; i < limit; i++)
204 {
212 {
205− if (d->nodes.nodes[i].name.length == slen &&
213+ node* r = &d->nodes.nodes[i];
206− memcmp(s, &d->body[d->nodes.nodes[i].name.start], slen) == 0)
214+ if (r->name.length == slen && memcmp(s, &d->body[r->name.start], slen) == 0)
207− return &d->nodes.nodes[i];
215+ return r;
208 }
216 }
209 return NULL;
217 return NULL;
210}
218}
211
219
212−node* node_nextChildBy(document* d, node* parent, node* prev, char* s, int slen)
213−{
214− assert(0);
215− return NULL;
216−}
217−
218
220
219/////////////////////////////////////////////////////////////////////
221/////////////////////////////////////////////////////////////////////
220// PARSE TABLE
222// PARSE TABLE
cbits/hexml.h+2−3
@@ -48,7 +48,6 @@ node* document_node(document* d);
48node* node_children(document* d, node* n, int* res);
48node* node_children(document* d, node* n, int* res);
49attr* node_attributes(document* d, node* n, int* res);
49attr* node_attributes(document* d, node* n, int* res);
50
50
51−// Search for given strings within a node
51+// Search for given strings within a node, note that prev may be NULL
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);
52+node* node_childBy(document* d, node* parent, node* prev, char* s, int slen);
54attr* node_attributeBy(document* d, node* n, char* s, int slen);
53attr* 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)
51foreign import ccall node_children :: Ptr CDocument -> Ptr CNode -> Ptr CInt -> IO (Ptr CNode)
51foreign import ccall node_children :: Ptr CDocument -> Ptr CNode -> Ptr CInt -> IO (Ptr CNode)
52foreign import ccall node_attributes :: Ptr CDocument -> Ptr CNode -> Ptr CInt -> IO (Ptr CAttr)
52foreign import ccall node_attributes :: Ptr CDocument -> Ptr CNode -> Ptr CInt -> IO (Ptr CAttr)
53
53
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)
56foreign import ccall node_attributeBy :: Ptr CDocument -> Ptr CNode -> CString -> CInt -> IO (Ptr CAttr)
55foreign import ccall node_attributeBy :: Ptr CDocument -> Ptr CNode -> CString -> CInt -> IO (Ptr CAttr)
57
56
58data Document = Document BS.ByteString (ForeignPtr CDocument)
57data Document = Document BS.ByteString (ForeignPtr CDocument)
@@ -140,7 +139,15 @@ nodeAttributes (Node src doc n) = unsafePerformIO $ withForeignPtr doc $ \d -> d
140 return [attrPeek src doc $ plusPtr res $ i*szAttr | i <- [0..count-1]]
139 return [attrPeek src doc $ plusPtr res $ i*szAttr | i <- [0..count-1]]
141
140
142nodeChildrenBy :: Node -> BS.ByteString -> [Node]
141nodeChildrenBy :: 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
144
148
145nodeAttributeBy :: Node -> BS.ByteString -> Maybe Attribute
149nodeAttributeBy :: Node -> BS.ByteString -> Maybe Attribute
150+nodeAttributeBy (Node src doc n) str = unsafePerformIO $ withForeignPtr doc $ \d ->
151+ BS.unsafeUseAsCStringLen str $ \(bs, len) -> do
146−nodeAttributeBy = node_attributeBy `seq` undefined
152+ r <- node_attributeBy d n bs $ fromIntegral len
153+ return $ if r == nullPtr then Nothing else Just $ attrPeek src doc r