on master help sign in
#7, every C function should start hexml_ or be static
b88a0edNeil Mitchell
CHANGES.txt+1
@@ -1,5 +1,6 @@
1Changelog for Hexml
1Changelog for Hexml
2
2
3+ #7, prefix all the C functions with hexml_
30.2
40.2
4 #6, remove buffer overruns
5 #6, remove buffer overruns
5 #5, add lower bounds
6 #5, add lower bounds
cbits/hexml.c+22−22
@@ -97,16 +97,16 @@ static inline void bound_str(str s, int mn, int mx)
97 bound(end(s), mn, mx);
97 bound(end(s), mn, mx);
98}
98}
99
99
100−void render_str(render* r, str s)
100+static void render_str(render* r, str s)
101{
101{
102 bound_str(s, 0, doc_length(r->d));
102 bound_str(s, 0, doc_length(r->d));
103 for (int i = 0; i < s.length; i++)
103 for (int i = 0; i < s.length; i++)
104 render_char(r, r->d->body[s.start + i]);
104 render_char(r, r->d->body[s.start + i]);
105}
105}
106
106
107−void render_tag(render* r, const node* n);
107+static void render_tag(render* r, const node* n);
108
108
109−void render_content(render* r, const node* n)
109+static void render_content(render* r, const node* n)
110{
110{
111 bound_str(n->inner, 0, doc_length(r->d));
111 bound_str(n->inner, 0, doc_length(r->d));
112 bound_str(n->nodes, 0, r->d->nodes.used_front);
112 bound_str(n->nodes, 0, r->d->nodes.used_front);
@@ -123,7 +123,7 @@ void render_content(render* r, const node* n)
123 render_str(r, start_end(done, end(n->inner)));
123 render_str(r, start_end(done, end(n->inner)));
124}
124}
125
125
126−void render_tag(render* r, const node* n)
126+static void render_tag(render* r, const node* n)
127{
127{
128 render_char(r, '<');
128 render_char(r, '<');
129 render_str(r, n->name);
129 render_str(r, n->name);
@@ -145,7 +145,7 @@ void render_tag(render* r, const node* n)
145 render_char(r, '>');
145 render_char(r, '>');
146}
146}
147
147
148−int node_render(const document* d, const node* n, char* buffer, int length)
148+int hexml_node_render(const document* d, const node* n, char* buffer, int length)
149{
149{
150 render r;
150 render r;
151 r.d = d;
151 r.d = d;
@@ -164,10 +164,10 @@ int node_render(const document* d, const node* n, char* buffer, int length)
164/////////////////////////////////////////////////////////////////////
164/////////////////////////////////////////////////////////////////////
165// NOT THE PARSER
165// NOT THE PARSER
166
166
167−char* document_error(const document* d){return d->error_message;}
167+char* hexml_document_error(const document* d){return d->error_message;}
168−node* document_node(const document* d){return &d->nodes.nodes[0];}
168+node* hexml_document_node(const document* d){return &d->nodes.nodes[0];}
169
169
170−void document_free(document* d)
170+void hexml_document_free(document* d)
171{
171{
172 free(d->error_message);
172 free(d->error_message);
173 free(d->nodes.alloc);
173 free(d->nodes.alloc);
@@ -175,20 +175,20 @@ void document_free(document* d)
175 free(d);
175 free(d);
176}
176}
177
177
178−node* node_children(const document* d, const node* n, int* res)
178+node* hexml_node_children(const document* d, const node* n, int* res)
179{
179{
180 *res = n->nodes.length;
180 *res = n->nodes.length;
181 return &d->nodes.nodes[n->nodes.start];
181 return &d->nodes.nodes[n->nodes.start];
182}
182}
183
183
184−attr* node_attributes(const document* d, const node* n, int* res)
184+attr* hexml_node_attributes(const document* d, const node* n, int* res)
185{
185{
186 *res = n->attrs.length;
186 *res = n->attrs.length;
187 return &d->attrs.attrs[n->attrs.start];
187 return &d->attrs.attrs[n->attrs.start];
188}
188}
189
189
190
190
191−attr* node_attributeBy(const document* d, const node* n, const char* s, int slen)
191+attr* hexml_node_attributeBy(const document* d, const node* n, const char* s, int slen)
192{
192{
193 if (slen == -1) slen = (int) strlen(s);
193 if (slen == -1) slen = (int) strlen(s);
194 const int limit = end(n->attrs);
194 const int limit = end(n->attrs);
@@ -202,7 +202,7 @@ attr* node_attributeBy(const document* d, const node* n, const char* s, int slen
202}
202}
203
203
204// Search for given strings within a node
204// Search for given strings within a node
205−node* node_childBy(const document* d, const node* parent, const node* prev, const char* s, int slen)
205+node* hexml_node_childBy(const document* d, const node* parent, const node* prev, const char* s, int slen)
206{
206{
207 if (slen == -1) slen = (int) strlen(s);
207 if (slen == -1) slen = (int) strlen(s);
208 int i = prev == NULL ? parent->nodes.start : (int) (prev + 1 - d->nodes.nodes);
208 int i = prev == NULL ? parent->nodes.start : (int) (prev + 1 - d->nodes.nodes);
@@ -220,13 +220,13 @@ node* node_childBy(const document* d, const node* parent, const node* prev, cons
220/////////////////////////////////////////////////////////////////////
220/////////////////////////////////////////////////////////////////////
221// PARSE TABLE
221// PARSE TABLE
222
222
223−const char tag_name1 = 0x1;
223+static const char tag_name1 = 0x1;
224−const char tag_name = 0x2;
224+static const char tag_name = 0x2;
225−const char tag_space = 0x4;
225+static const char tag_space = 0x4;
226
226
227−char parse_table[256];
227+static char parse_table[256];
228
228
229−void init_parse_table()
229+static void init_parse_table()
230{
230{
231 static bool done = 0;
231 static bool done = 0;
232 if (done) return;
232 if (done) return;
@@ -262,7 +262,7 @@ static inline void trim(document* d)
262}
262}
263
263
264// Find this character form the cursor onwards, if true adjust the cursor to that char, otherwise leave it at the end
264// Find this character form the cursor onwards, if true adjust the cursor to that char, otherwise leave it at the end
265−bool find(document* d, char c)
265+static bool find(document* d, char c)
266{
266{
267 char* x = memchr(d->cursor, c, d->end - d->cursor);
267 char* x = memchr(d->cursor, c, d->end - d->cursor);
268 if (x == NULL)
268 if (x == NULL)
@@ -310,7 +310,7 @@ static inline void attr_alloc(attr_buffer* b, int ask)
310 b->alloc = buf2;
310 b->alloc = buf2;
311}
311}
312
312
313−void set_error(document* d, const char* msg)
313+static void set_error(document* d, const char* msg)
314{
314{
315 if (d->error_message != NULL) return; // keep the first error message
315 if (d->error_message != NULL) return; // keep the first error message
316 d->error_message = malloc(strlen(msg)+1);
316 d->error_message = malloc(strlen(msg)+1);
@@ -381,7 +381,7 @@ static inline str parse_attributes(document* d)
381 return start_end(start, d->attrs.used);
381 return start_end(start, d->attrs.used);
382}
382}
383
383
384−str parse_content(document* d);
384+static str parse_content(document* d);
385
385
386
386
387// Add a new entry into tag, am at a '<'
387// Add a new entry into tag, am at a '<'
@@ -451,7 +451,7 @@ static inline void parse_tag(document* d)
451
451
452// Parser until </, return the index of your node children
452// Parser until </, return the index of your node children
453// Not inline as it is recursive
453// Not inline as it is recursive
454−str parse_content(document* d)
454+static str parse_content(document* d)
455{
455{
456 int before = d->nodes.used_back;
456 int before = d->nodes.used_back;
457 while (d->error_message == NULL)
457 while (d->error_message == NULL)
@@ -512,7 +512,7 @@ typedef struct
512 node nodes[500];
512 node nodes[500];
513} buffer;
513} buffer;
514
514
515−document* document_parse(const char* s, int slen)
515+document* hexml_document_parse(const char* s, int slen)
516{
516{
517 if (slen == -1) slen = (int) strlen(s);
517 if (slen == -1) slen = (int) strlen(s);
518 assert(s[slen] == 0);
518 assert(s[slen] == 0);
cbits/hexml.h+9−9
@@ -30,27 +30,27 @@ typedef struct
30// Parse a document, returns a potentially invalid document - use document_error to check
30// Parse a document, returns a potentially invalid document - use document_error to check
31// Must use document_free to release the memory (even if invalid).
31// Must use document_free to release the memory (even if invalid).
32// The string must be nul terminated, e.g. slen != -1 ==> slen[0]
32// The string must be nul terminated, e.g. slen != -1 ==> slen[0]
33−document* document_parse(const char* s, int slen);
33+document* hexml_document_parse(const char* s, int slen);
34
34
35// Free the memory returned from document_parse.
35// Free the memory returned from document_parse.
36−void document_free(document* d);
36+void hexml_document_free(document* d);
37
37
38// Generate a fresh string with the same semantics as the node.
38// Generate a fresh string with the same semantics as the node.
39// Requires an input buffer, returns the size of the rendered document.
39// Requires an input buffer, returns the size of the rendered document.
40// Requires the string passed to document_parse to be valid.
40// Requires the string passed to document_parse to be valid.
41−int node_render(const document* d, const node* n, char* buffer, int length);
41+int hexml_node_render(const document* d, const node* n, char* buffer, int length);
42
42
43// Return either NULL (successful parse) or the error message.
43// Return either NULL (successful parse) or the error message.
44−char* document_error(const document* d);
44+char* hexml_document_error(const document* d);
45
45
46// Return the root node of the document - imagine the document is wrapped in <>$DOC</> tags.
46// Return the root node of the document - imagine the document is wrapped in <>$DOC</> tags.
47−node* document_node(const document* d);
47+node* hexml_document_node(const document* d);
48
48
49// List all items within a node
49// List all items within a node
50−node* node_children(const document* d, const node* n, int* res);
50+node* hexml_node_children(const document* d, const node* n, int* res);
51−attr* node_attributes(const document* d, const node* n, int* res);
51+attr* hexml_node_attributes(const document* d, const node* n, int* res);
52
52
53// Search for given strings within a node, note that prev may be NULL
53// Search for given strings within a node, note that prev may be NULL
54// Requires the string passed to document_parse to be valid.
54// Requires the string passed to document_parse to be valid.
55−node* node_childBy(const document* d, const node* parent, const node* prev, const char* s, int slen);
55+node* hexml_node_childBy(const document* d, const node* parent, const node* prev, const char* s, int slen);
56−attr* node_attributeBy(const document* d, const node* n, const char* s, int slen);
56+attr* hexml_node_attributeBy(const document* d, const node* n, const char* s, int slen);
src/Text/XML/Hexml.hs+22−22
@@ -45,18 +45,18 @@ instance Storable Str where
45 peek p = Str <$> peekByteOff p 0 <*> peekByteOff p 4
45 peek p = Str <$> peekByteOff p 0 <*> peekByteOff p 4
46 poke p Str{..} = pokeByteOff p 0 strStart >> pokeByteOff p 4 strLength
46 poke p Str{..} = pokeByteOff p 0 strStart >> pokeByteOff p 4 strLength
47
47
48−foreign import ccall document_parse :: CString -> CInt -> IO (Ptr CDocument)
48+foreign import ccall hexml_document_parse :: CString -> CInt -> IO (Ptr CDocument)
49−foreign import ccall document_free :: Ptr CDocument -> IO ()
49+foreign import ccall hexml_document_free :: Ptr CDocument -> IO ()
50−foreign import ccall "&document_free" document_free_funptr :: FunPtr (Ptr CDocument -> IO ())
50+foreign import ccall "&hexml_document_free" hexml_document_free_funptr :: FunPtr (Ptr CDocument -> IO ())
51−foreign import ccall node_render :: Ptr CDocument -> Ptr CNode -> CString -> CInt -> IO CInt
51+foreign import ccall hexml_node_render :: Ptr CDocument -> Ptr CNode -> CString -> CInt -> IO CInt
52−foreign import ccall document_error :: Ptr CDocument -> IO CString
52+foreign import ccall hexml_document_error :: Ptr CDocument -> IO CString
53−foreign import ccall document_node :: Ptr CDocument -> IO (Ptr CNode)
53+foreign import ccall hexml_document_node :: Ptr CDocument -> IO (Ptr CNode)
54
54
55−foreign import ccall node_children :: Ptr CDocument -> Ptr CNode -> Ptr CInt -> IO (Ptr CNode)
55+foreign import ccall hexml_node_children :: Ptr CDocument -> Ptr CNode -> Ptr CInt -> IO (Ptr CNode)
56−foreign import ccall node_attributes :: Ptr CDocument -> Ptr CNode -> Ptr CInt -> IO (Ptr CAttr)
56+foreign import ccall hexml_node_attributes :: Ptr CDocument -> Ptr CNode -> Ptr CInt -> IO (Ptr CAttr)
57
57
58−foreign import ccall node_childBy :: Ptr CDocument -> Ptr CNode -> Ptr CNode -> CString -> CInt -> IO (Ptr CNode)
58+foreign import ccall hexml_node_childBy :: Ptr CDocument -> Ptr CNode -> Ptr CNode -> CString -> CInt -> IO (Ptr CNode)
59−foreign import ccall node_attributeBy :: Ptr CDocument -> Ptr CNode -> CString -> CInt -> IO (Ptr CAttr)
59+foreign import ccall hexml_node_attributeBy :: Ptr CDocument -> Ptr CNode -> CString -> CInt -> IO (Ptr CAttr)
60
60
61-- | A node in an XML document, created by 'parse', then calling functions such
61-- | A node in an XML document, created by 'parse', then calling functions such
62-- as 'children' on that initial 'Node'.
62-- as 'children' on that initial 'Node'.
@@ -85,23 +85,23 @@ parse :: BS.ByteString -> Either BS.ByteString Node
85parse src = do
85parse src = do
86 let src0 = src <> BS.singleton '\0'
86 let src0 = src <> BS.singleton '\0'
87 unsafePerformIO $ BS.unsafeUseAsCStringLen src0 $ \(str, len) -> do
87 unsafePerformIO $ BS.unsafeUseAsCStringLen src0 $ \(str, len) -> do
88− doc <- document_parse str (fromIntegral len - 1)
88+ doc <- hexml_document_parse str (fromIntegral len - 1)
89− err <- document_error doc
89+ err <- hexml_document_error doc
90 if err /= nullPtr then do
90 if err /= nullPtr then do
91− bs <- BS.packCString =<< document_error doc
91+ bs <- BS.packCString =<< hexml_document_error doc
92− document_free doc
92+ hexml_document_free doc
93 return $ Left bs
93 return $ Left bs
94 else do
94 else do
95− node <- document_node doc
95+ node <- hexml_document_node doc
96− doc <- newForeignPtr document_free_funptr doc
96+ doc <- newForeignPtr hexml_document_free_funptr doc
97 return $ Right $ Node src0 doc node
97 return $ Right $ Node src0 doc node
98
98
99-- | Given a node, rerender it to something with an equivalent parse tree.
99-- | Given a node, rerender it to something with an equivalent parse tree.
100-- Mostly useful for debugging - if you want the real source document use 'outer' instead.
100-- Mostly useful for debugging - if you want the real source document use 'outer' instead.
101render :: Node -> BS.ByteString
101render :: Node -> BS.ByteString
102render (Node src doc n) = unsafePerformIO $ withForeignPtr doc $ \d -> do
102render (Node src doc n) = unsafePerformIO $ withForeignPtr doc $ \d -> do
103− i <- node_render d n nullPtr 0
103+ i <- hexml_node_render d n nullPtr 0
104− res <- BS.create (fromIntegral i) $ \ptr -> void $ node_render d n (castPtr ptr) i
104+ res <- BS.create (fromIntegral i) $ \ptr -> void $ hexml_node_render d n (castPtr ptr) i
105 touchBS src
105 touchBS src
106 return res
106 return res
107
107
@@ -154,7 +154,7 @@ contents n@(Node src _ _) = f (strStart inner) outers
154children :: Node -> [Node]
154children :: Node -> [Node]
155children (Node src doc n) = unsafePerformIO $ withForeignPtr doc $ \d -> do
155children (Node src doc n) = unsafePerformIO $ withForeignPtr doc $ \d -> do
156 alloca $ \count -> do
156 alloca $ \count -> do
157− res <- node_children d n count
157+ res <- hexml_node_children d n count
158 count <- fromIntegral <$> peek count
158 count <- fromIntegral <$> peek count
159 return [Node src doc $ plusPtr res $ i*szNode | i <- [0..count-1]]
159 return [Node src doc $ plusPtr res $ i*szNode | i <- [0..count-1]]
160
160
@@ -162,7 +162,7 @@ children (Node src doc n) = unsafePerformIO $ withForeignPtr doc $ \d -> do
162attributes :: Node -> [Attribute]
162attributes :: Node -> [Attribute]
163attributes (Node src doc n) = unsafePerformIO $ withForeignPtr doc $ \d -> do
163attributes (Node src doc n) = unsafePerformIO $ withForeignPtr doc $ \d -> do
164 alloca $ \count -> do
164 alloca $ \count -> do
165− res <- node_attributes d n count
165+ res <- hexml_node_attributes d n count
166 count <- fromIntegral <$> peek count
166 count <- fromIntegral <$> peek count
167 return [attrPeek src doc $ plusPtr res $ i*szAttr | i <- [0..count-1]]
167 return [attrPeek src doc $ plusPtr res $ i*szAttr | i <- [0..count-1]]
168
168
@@ -175,7 +175,7 @@ childrenBy (Node src doc n) str = go nullPtr
175 where
175 where
176 go old = unsafePerformIO $ withForeignPtr doc $ \d ->
176 go old = unsafePerformIO $ withForeignPtr doc $ \d ->
177 BS.unsafeUseAsCStringLen str $ \(bs, len) -> do
177 BS.unsafeUseAsCStringLen str $ \(bs, len) -> do
178− r <- node_childBy d n old bs $ fromIntegral len
178+ r <- hexml_node_childBy d n old bs $ fromIntegral len
179 touchBS src
179 touchBS src
180 return $ if r == nullPtr then [] else Node src doc r : go r
180 return $ if r == nullPtr then [] else Node src doc r : go r
181
181
@@ -186,7 +186,7 @@ childrenBy (Node src doc n) str = go nullPtr
186attributeBy :: Node -> BS.ByteString -> Maybe Attribute
186attributeBy :: Node -> BS.ByteString -> Maybe Attribute
187attributeBy (Node src doc n) str = unsafePerformIO $ withForeignPtr doc $ \d ->
187attributeBy (Node src doc n) str = unsafePerformIO $ withForeignPtr doc $ \d ->
188 BS.unsafeUseAsCStringLen str $ \(bs, len) -> do
188 BS.unsafeUseAsCStringLen str $ \(bs, len) -> do
189− r <- node_attributeBy d n bs $ fromIntegral len
189+ r <- hexml_node_attributeBy d n bs $ fromIntegral len
190 touchBS src
190 touchBS src
191 return $ if r == nullPtr then Nothing else Just $ attrPeek src doc r
191 return $ if r == nullPtr then Nothing else Just $ attrPeek src doc r
192
192
vs/main.c+4−4
@@ -26,14 +26,14 @@ int main(int argc, char **argv)
26{
26{
27 setbuf(stdout, NULL);
27 setbuf(stdout, NULL);
28 char* body = argv[1] == NULL ? example : readFile(argv[1]);
28 char* body = argv[1] == NULL ? example : readFile(argv[1]);
29− document* doc = document_parse(body, -1);
29+ document* doc = hexml_document_parse(body, -1);
30− char* err = document_error(doc);
30+ char* err = hexml_document_error(doc);
31 if (err == NULL)
31 if (err == NULL)
32 {
32 {
33− int len = node_render(doc, document_node(doc), NULL, 0);
33+ int len = hexml_node_render(doc, hexml_document_node(doc), NULL, 0);
34 char* s = malloc(len + 1);
34 char* s = malloc(len + 1);
35 assert(s);
35 assert(s);
36− node_render(doc, document_node(doc), s, len);
36+ hexml_node_render(doc, hexml_document_node(doc), s, len);
37 s[len] = 0;
37 s[len] = 0;
38 printf("Parse successful\n"); // , %s\n", s);
38 printf("Parse successful\n"); // , %s\n", s);
39 return 0;
39 return 0;