From eb6f5e7f1127783c347e31d8de506d583cc69c59 Mon Sep 17 00:00:00 2001 From: defanor Date: Sat, 9 Sep 2023 13:54:01 +0300 Subject: Use rxml for XML parsing when building with Rust --- src/Cargo.toml | 1 + src/Makefile.am | 8 +-- src/rexmpp.c | 2 +- src/rexmpp_console.c | 1 + src/rexmpp_dns.c | 1 + src/rexmpp_http_upload.c | 1 + src/rexmpp_roster.c | 1 + src/rexmpp_rust.rs | 1 + src/rexmpp_sasl.c | 1 + src/rexmpp_tls.c | 1 + src/rexmpp_xml.c | 14 +++-- src/rexmpp_xml.rs | 114 ++++++++++++++++++------------------ src/rexmpp_xml_parser.c | 7 ++- src/rexmpp_xml_parser.h | 5 +- src/rexmpp_xml_parser.rs | 146 +++++++++++++++++++++++++++++++++++++++++++++++ 15 files changed, 232 insertions(+), 72 deletions(-) create mode 100644 src/rexmpp_xml_parser.rs (limited to 'src') diff --git a/src/Cargo.toml b/src/Cargo.toml index 6ce67b4..65a0ff4 100644 --- a/src/Cargo.toml +++ b/src/Cargo.toml @@ -14,3 +14,4 @@ path = "rexmpp_rust.rs" [dependencies] libc = "0.2" errno = "0.3" +rxml = "0.9" diff --git a/src/Makefile.am b/src/Makefile.am index eea4f8f..5bf0f1a 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -15,8 +15,7 @@ librexmpp_la_SOURCES = rexmpp_roster.h rexmpp_roster.c \ rexmpp_base64.h rexmpp_base64.c \ rexmpp_sasl.h rexmpp_sasl.c \ rexmpp_xml.h rexmpp_xml.c \ - rexmpp_utf8.h \ - rexmpp_xml_parser.h rexmpp_xml_parser.c + rexmpp_utf8.h include_HEADERS = config.h rexmpp_roster.h rexmpp_tcp.h rexmpp_socks.h rexmpp.h \ rexmpp_dns.h rexmpp_tls.h rexmpp_jid.h rexmpp_openpgp.h rexmpp_console.h \ @@ -36,7 +35,7 @@ librexmpp_la_LDFLAGS = [] if USE_RUST target_debug_librexmpp_rust_a_SOURCES = \ rexmpp_rust.rs rexmpp.rs rexmpp_jid.rs rexmpp_dns.rs rexmpp_tcp.rs \ - rexmpp_socks.rs rexmpp_xml.rs + rexmpp_socks.rs rexmpp_xml.rs rexmpp_xml_parser.rs noinst_LIBRARIES = target/debug/librexmpp_rust.a librexmpp_la_LIBADD += target/debug/librexmpp_rust.a librexmpp_la_LDFLAGS += -L. -lpthread -ldl @@ -46,5 +45,6 @@ target/debug/librexmpp_rust.a: $(target_debug_librexmpp_rust_a_SOURCES) else librexmpp_la_SOURCES += rexmpp_tcp.h rexmpp_tcp.c \ - rexmpp_socks.h rexmpp_socks.c + rexmpp_socks.h rexmpp_socks.c \ + rexmpp_xml_parser.h rexmpp_xml_parser.c endif diff --git a/src/rexmpp.c b/src/rexmpp.c index 886f091..7194d87 100644 --- a/src/rexmpp.c +++ b/src/rexmpp.c @@ -1225,7 +1225,7 @@ rexmpp_err_t rexmpp_recv (rexmpp_t *s) { chunk = chunk_raw; chunk_len = chunk_raw_len; } - rexmpp_xml_parser_feed(s->xml_parser, chunk, chunk_len); + rexmpp_xml_parser_feed(s->xml_parser, chunk, chunk_len, 0); if (chunk != chunk_raw && chunk != NULL) { free(chunk); } diff --git a/src/rexmpp_console.c b/src/rexmpp_console.c index ce325aa..f1a5ca5 100644 --- a/src/rexmpp_console.c +++ b/src/rexmpp_console.c @@ -11,6 +11,7 @@ */ #include +#include #include "rexmpp.h" #include "rexmpp_xml.h" diff --git a/src/rexmpp_dns.c b/src/rexmpp_dns.c index f793e88..d13472e 100644 --- a/src/rexmpp_dns.c +++ b/src/rexmpp_dns.c @@ -7,6 +7,7 @@ */ #include +#include #include #include "config.h" diff --git a/src/rexmpp_http_upload.c b/src/rexmpp_http_upload.c index 2552771..4d8c631 100644 --- a/src/rexmpp_http_upload.c +++ b/src/rexmpp_http_upload.c @@ -10,6 +10,7 @@ #include #include #include +#include #include "config.h" diff --git a/src/rexmpp_roster.c b/src/rexmpp_roster.c index 0048848..c9d4532 100644 --- a/src/rexmpp_roster.c +++ b/src/rexmpp_roster.c @@ -10,6 +10,7 @@ #include "rexmpp_xml.h" #include #include +#include rexmpp_xml_t * rexmpp_roster_find_item (rexmpp_t *s, diff --git a/src/rexmpp_rust.rs b/src/rexmpp_rust.rs index fd19bd4..04bbcca 100644 --- a/src/rexmpp_rust.rs +++ b/src/rexmpp_rust.rs @@ -1,5 +1,6 @@ mod rexmpp_jid; mod rexmpp_xml; +mod rexmpp_xml_parser; mod rexmpp_dns; mod rexmpp_tcp; mod rexmpp_socks; diff --git a/src/rexmpp_sasl.c b/src/rexmpp_sasl.c index cf5d1fe..20c4ba0 100644 --- a/src/rexmpp_sasl.c +++ b/src/rexmpp_sasl.c @@ -8,6 +8,7 @@ */ #include +#include #include "config.h" #include "rexmpp.h" diff --git a/src/rexmpp_tls.c b/src/rexmpp_tls.c index e1de5ea..9234e92 100644 --- a/src/rexmpp_tls.c +++ b/src/rexmpp_tls.c @@ -8,6 +8,7 @@ #include #include +#include #include "config.h" diff --git a/src/rexmpp_xml.c b/src/rexmpp_xml.c index 4907d4e..a7572fc 100644 --- a/src/rexmpp_xml.c +++ b/src/rexmpp_xml.c @@ -8,6 +8,7 @@ #include #include +#include #include "rexmpp.h" #include "rexmpp_utf8.h" #include "rexmpp_xml.h" @@ -533,7 +534,7 @@ rexmpp_xml_t *rexmpp_xml_parse (const char *str, int str_len) { struct rexmpp_xml_builder builder = { NULL, NULL }; rexmpp_xml_parser_ctx_t parser = rexmpp_xml_parser_new(&builder_sax, &builder); - rexmpp_xml_parser_feed(parser, str, str_len); + rexmpp_xml_parser_feed(parser, str, str_len, 1); rexmpp_xml_parser_free(parser); if (builder.current != NULL) { /* The parsing is not complete. */ @@ -552,13 +553,14 @@ rexmpp_xml_t *rexmpp_xml_read_fd (FILE *fd) { } char *buf; - size_t len = 0; + size_t init_len = 0; + ssize_t buf_len = 0; do { - len = getline(&buf, &len, fd); - if (len > 0) { - rexmpp_xml_parser_feed(parser, buf, len); + buf_len = getline(&buf, &init_len, fd); + if (buf_len > 0) { + rexmpp_xml_parser_feed(parser, buf, buf_len, 0); } - } while (len > 0 && + } while (buf_len > 0 && ! (builder.root != NULL && builder.current == NULL) ); rexmpp_xml_parser_free(parser); diff --git a/src/rexmpp_xml.rs b/src/rexmpp_xml.rs index 717501d..8938e57 100644 --- a/src/rexmpp_xml.rs +++ b/src/rexmpp_xml.rs @@ -15,8 +15,8 @@ use super::{rexmpp}; #[repr(C)] pub struct RexmppXMLQName { - name: *mut c_char, - namespace: *mut c_char + pub name: *mut c_char, + pub namespace: *mut c_char } impl Copy for RexmppXMLQName { } @@ -36,9 +36,9 @@ impl Clone for RexmppXMLQName { #[repr(C)] pub struct RexmppXMLAttribute { - qname: RexmppXMLQName, - value: *mut c_char, - next: *mut RexmppXMLAttribute + pub qname: RexmppXMLQName, + pub value: *mut c_char, + pub next: *mut RexmppXMLAttribute } impl Copy for RexmppXMLAttribute { } @@ -56,16 +56,16 @@ impl Clone for RexmppXMLAttribute { #[derive(Copy, Clone)] #[derive(PartialEq)] #[repr(C)] -enum NodeType { +pub enum NodeType { Element, Text } #[repr(C)] -struct RexmppXMLAltElem { - qname: RexmppXMLQName, - attributes: *mut RexmppXMLAttribute, - children: *mut RexmppXML +pub struct RexmppXMLAltElem { + pub qname: RexmppXMLQName, + pub attributes: *mut RexmppXMLAttribute, + pub children: *mut RexmppXML } impl Copy for RexmppXMLAltElem { } @@ -99,16 +99,16 @@ impl Clone for RexmppXMLAltElem { #[derive(Copy, Clone)] #[repr(C)] -union RexmppXMLAlt { - elem: RexmppXMLAltElem, - text: *mut c_char +pub union RexmppXMLAlt { + pub elem: RexmppXMLAltElem, + pub text: *mut c_char } #[repr(C)] pub struct RexmppXML { - node_type: NodeType, - alt: RexmppXMLAlt, - next: *mut RexmppXML + pub node_type: NodeType, + pub alt: RexmppXMLAlt, + pub next: *mut RexmppXML } impl Copy for RexmppXML { } @@ -129,7 +129,7 @@ impl Clone for RexmppXML { } #[no_mangle] -extern "C" +pub extern "C" fn rexmpp_xml_qname_free (qname_ptr: *mut RexmppXMLQName) { match unsafe { qname_ptr.as_mut() } { None => return, @@ -147,7 +147,7 @@ fn rexmpp_xml_qname_free (qname_ptr: *mut RexmppXMLQName) { } #[no_mangle] -extern "C" +pub extern "C" fn rexmpp_xml_attribute_free (attr_ptr: *mut RexmppXMLAttribute) { if attr_ptr == ptr::null_mut() { return; @@ -161,7 +161,7 @@ fn rexmpp_xml_attribute_free (attr_ptr: *mut RexmppXMLAttribute) { } #[no_mangle] -extern "C" +pub extern "C" fn rexmpp_xml_attribute_free_list (mut attr_ptr: *mut RexmppXMLAttribute) { let mut next; while attr_ptr != ptr::null_mut() { @@ -172,7 +172,7 @@ fn rexmpp_xml_attribute_free_list (mut attr_ptr: *mut RexmppXMLAttribute) { } #[no_mangle] -extern "C" +pub extern "C" fn rexmpp_xml_free (node_ptr: *mut RexmppXML) { if node_ptr == ptr::null_mut() { return; @@ -198,7 +198,7 @@ fn rexmpp_xml_free (node_ptr: *mut RexmppXML) { } #[no_mangle] -extern "C" +pub extern "C" fn rexmpp_xml_free_list (mut node_ptr: *mut RexmppXML) { let mut next; while node_ptr != ptr::null_mut() { @@ -209,7 +209,7 @@ fn rexmpp_xml_free_list (mut node_ptr: *mut RexmppXML) { } #[no_mangle] -extern "C" +pub extern "C" fn rexmpp_xml_clone (node_ptr: *mut RexmppXML) -> *mut RexmppXML { if node_ptr == ptr::null_mut() { return ptr::null_mut(); @@ -218,7 +218,7 @@ fn rexmpp_xml_clone (node_ptr: *mut RexmppXML) -> *mut RexmppXML { } #[no_mangle] -extern "C" +pub extern "C" fn rexmpp_xml_clone_list (mut node_ptr: *mut RexmppXML) -> *mut RexmppXML { if node_ptr == ptr::null_mut() { return ptr::null_mut(); @@ -236,7 +236,7 @@ fn rexmpp_xml_clone_list (mut node_ptr: *mut RexmppXML) -> *mut RexmppXML { #[no_mangle] -extern "C" +pub extern "C" fn rexmpp_xml_new_text (str: *const c_char) -> *mut RexmppXML { let node = RexmppXML { node_type: NodeType::Text, @@ -248,7 +248,7 @@ fn rexmpp_xml_new_text (str: *const c_char) -> *mut RexmppXML { } #[no_mangle] -extern "C" +pub extern "C" fn rexmpp_xml_new_text_len (str: *const c_char, len: usize) -> *mut RexmppXML { let node = RexmppXML { node_type: NodeType::Text, @@ -260,7 +260,7 @@ fn rexmpp_xml_new_text_len (str: *const c_char, len: usize) -> *mut RexmppXML { } #[no_mangle] -extern "C" fn rexmpp_xml_add_child (node: *mut RexmppXML, +pub extern "C" fn rexmpp_xml_add_child (node: *mut RexmppXML, child: *mut RexmppXML) -> () { let mut last_ptr : &mut *mut RexmppXML = unsafe { &mut ((*node).alt.elem.children) }; @@ -271,7 +271,7 @@ extern "C" fn rexmpp_xml_add_child (node: *mut RexmppXML, } #[no_mangle] -extern "C" fn rexmpp_xml_add_text (node: *mut RexmppXML, +pub extern "C" fn rexmpp_xml_add_text (node: *mut RexmppXML, str: *const c_char) -> c_int { let text_node : *mut RexmppXML = rexmpp_xml_new_text(str); if text_node != ptr::null_mut() { @@ -282,7 +282,7 @@ extern "C" fn rexmpp_xml_add_text (node: *mut RexmppXML, } #[no_mangle] -extern "C" fn rexmpp_xml_add_text_len (node: *mut RexmppXML, +pub extern "C" fn rexmpp_xml_add_text_len (node: *mut RexmppXML, str: *const c_char, len: usize) -> c_int { let text_node : *mut RexmppXML = rexmpp_xml_new_text_len(str, len); @@ -294,7 +294,7 @@ extern "C" fn rexmpp_xml_add_text_len (node: *mut RexmppXML, } #[no_mangle] -extern "C" +pub extern "C" fn rexmpp_xml_new_elem (name: *const c_char, namespace: *const c_char) -> *mut RexmppXML { let node = RexmppXML { @@ -320,7 +320,7 @@ fn rexmpp_xml_new_elem (name: *const c_char, } #[no_mangle] -extern "C" +pub extern "C" fn rexmpp_xml_attr_new (name: *const c_char, namespace: *const c_char, value: *const c_char) -> *mut RexmppXMLAttribute { @@ -340,7 +340,7 @@ fn rexmpp_xml_attr_new (name: *const c_char, } #[no_mangle] -extern "C" +pub extern "C" fn rexmpp_xml_add_attr_ns (node: *mut RexmppXML, name: *const c_char, namespace: *const c_char, @@ -358,7 +358,7 @@ fn rexmpp_xml_add_attr_ns (node: *mut RexmppXML, } #[no_mangle] -extern "C" +pub extern "C" fn rexmpp_xml_remove_attr_ns (node: *mut RexmppXML, name: *const c_char, namespace: *const c_char) -> c_int { @@ -382,7 +382,7 @@ fn rexmpp_xml_remove_attr_ns (node: *mut RexmppXML, } #[no_mangle] -extern "C" +pub extern "C" fn rexmpp_xml_add_attr (node: *mut RexmppXML, name: *const c_char, value: *const c_char) -> c_int { @@ -390,7 +390,7 @@ fn rexmpp_xml_add_attr (node: *mut RexmppXML, } #[no_mangle] -extern "C" +pub extern "C" fn rexmpp_xml_remove_attr (node: *mut RexmppXML, name: *const c_char) -> c_int { rexmpp_xml_remove_attr_ns(node, name, ptr::null_mut()) @@ -571,7 +571,7 @@ fn rexmpp_xml_serialize_str (node_ptr: *const RexmppXML, } #[no_mangle] -extern "C" +pub extern "C" fn rexmpp_xml_serialize (node_ptr: *const RexmppXML, pretty: bool) -> *mut c_char @@ -584,7 +584,7 @@ fn rexmpp_xml_serialize (node_ptr: *const RexmppXML, } #[no_mangle] -extern "C" +pub extern "C" fn rexmpp_xml_add_id (s: *mut rexmpp::Rexmpp, node: *mut RexmppXML) -> *mut RexmppXML { @@ -603,7 +603,7 @@ fn rexmpp_xml_add_id (s: *mut rexmpp::Rexmpp, node: *mut RexmppXML) } #[no_mangle] -extern "C" +pub extern "C" fn rexmpp_xml_write_file (path: *const c_char, node: *const RexmppXML) -> c_int @@ -623,7 +623,7 @@ fn rexmpp_xml_write_file (path: *const c_char, } #[no_mangle] -extern "C" +pub extern "C" fn rexmpp_xml_siblings_count (mut node: *const RexmppXML) -> c_uint { let mut i : c_uint = 0; while node != ptr::null() { @@ -634,7 +634,7 @@ fn rexmpp_xml_siblings_count (mut node: *const RexmppXML) -> c_uint { } #[no_mangle] -extern "C" +pub extern "C" fn rexmpp_xml_match (node_ptr: *const RexmppXML, namespace: *const c_char, name: *const c_char) -> c_int { @@ -673,7 +673,7 @@ fn rexmpp_xml_match (node_ptr: *const RexmppXML, } #[no_mangle] -extern "C" +pub extern "C" fn rexmpp_xml_attr_match (attr: *const RexmppXMLAttribute, namespace: *const c_char, name: *const c_char) -> c_int { @@ -708,7 +708,7 @@ fn rexmpp_xml_attr_match (attr: *const RexmppXMLAttribute, } #[no_mangle] -extern "C" +pub extern "C" fn rexmpp_xml_is_stanza (node: *const RexmppXML) -> c_int { if rexmpp_xml_match(node, CString::new("jabber:client").expect("CString::new failed").as_ptr(), @@ -726,7 +726,7 @@ fn rexmpp_xml_is_stanza (node: *const RexmppXML) -> c_int { } #[no_mangle] -extern "C" +pub extern "C" fn rexmpp_xml_error (error_type: *const c_char, condition: *const c_char) -> *mut RexmppXML { let error : *mut RexmppXML = @@ -749,7 +749,7 @@ fn rexmpp_xml_error (error_type: *const c_char, condition: *const c_char) } #[no_mangle] -extern "C" +pub extern "C" fn rexmpp_xml_find_attr (node_ptr: *mut RexmppXML, name: *const c_char, namespace: *const c_char) @@ -773,7 +773,7 @@ fn rexmpp_xml_find_attr (node_ptr: *mut RexmppXML, } #[no_mangle] -extern "C" +pub extern "C" fn rexmpp_xml_find_attr_val_ns (node: *mut RexmppXML, name: *const c_char, namespace: *const c_char) @@ -787,7 +787,7 @@ fn rexmpp_xml_find_attr_val_ns (node: *mut RexmppXML, } #[no_mangle] -extern "C" +pub extern "C" fn rexmpp_xml_find_attr_val (node: *mut RexmppXML, name: *const c_char) -> *const c_char { @@ -795,7 +795,7 @@ fn rexmpp_xml_find_attr_val (node: *mut RexmppXML, } #[no_mangle] -extern "C" +pub extern "C" fn rexmpp_xml_find_child (node_ptr: *mut RexmppXML, namespace: *const c_char, name: *const c_char) @@ -819,7 +819,7 @@ fn rexmpp_xml_find_child (node_ptr: *mut RexmppXML, #[no_mangle] -extern "C" +pub extern "C" fn rexmpp_xml_eq (n1: *const RexmppXML, n2: *const RexmppXML) -> bool { if n1 == n2 { return true; @@ -865,10 +865,10 @@ fn rexmpp_xml_eq (n1: *const RexmppXML, n2: *const RexmppXML) -> bool { if strcmp(name1, name2) != 0 { return false; } // Compare namespaces - if (namespace1 != namespace2 && + if namespace1 != namespace2 && (namespace1 == ptr::null_mut() || namespace2 == ptr::null_mut() || - strcmp(namespace1, namespace2) != 0)) + strcmp(namespace1, namespace2) != 0) { return false; } // Compare attributes let mut attr1 = attributes1; @@ -914,7 +914,7 @@ fn rexmpp_xml_eq (n1: *const RexmppXML, n2: *const RexmppXML) -> bool { } #[no_mangle] -extern "C" +pub extern "C" fn rexmpp_xml_children (node: *const RexmppXML) -> *mut RexmppXML { if node != ptr::null_mut() @@ -925,7 +925,7 @@ fn rexmpp_xml_children (node: *const RexmppXML) } #[no_mangle] -extern "C" +pub extern "C" fn rexmpp_xml_first_elem_child (node: *mut RexmppXML) -> *mut RexmppXML { let mut child: *mut RexmppXML = rexmpp_xml_children(node); @@ -939,7 +939,7 @@ fn rexmpp_xml_first_elem_child (node: *mut RexmppXML) } #[no_mangle] -extern "C" +pub extern "C" fn rexmpp_xml_next_elem_sibling (node: *mut RexmppXML) -> *mut RexmppXML { if node == ptr::null_mut() { @@ -956,7 +956,7 @@ fn rexmpp_xml_next_elem_sibling (node: *mut RexmppXML) } #[no_mangle] -extern "C" +pub extern "C" fn rexmpp_xml_text (node: *mut RexmppXML) -> *mut c_char { if node != ptr::null_mut() @@ -967,14 +967,14 @@ fn rexmpp_xml_text (node: *mut RexmppXML) } #[no_mangle] -extern "C" +pub extern "C" fn rexmpp_xml_text_child (node: *mut RexmppXML) -> *mut c_char { rexmpp_xml_text(rexmpp_xml_children(node)) } #[no_mangle] -extern "C" +pub extern "C" fn rexmpp_xml_reverse_list (mut node: *mut RexmppXML) -> *mut RexmppXML { let mut next; @@ -991,7 +991,7 @@ fn rexmpp_xml_reverse_list (mut node: *mut RexmppXML) } #[no_mangle] -extern "C" +pub extern "C" fn rexmpp_xml_reverse_children (node: *mut RexmppXML) -> *mut RexmppXML { unsafe { @@ -999,7 +999,7 @@ fn rexmpp_xml_reverse_children (node: *mut RexmppXML) return node; } (*node).alt.elem.children = - rexmpp_xml_reverse_list((*node).alt.elem.children);; + rexmpp_xml_reverse_list((*node).alt.elem.children); let mut cur = node; while cur != ptr::null_mut() { diff --git a/src/rexmpp_xml_parser.c b/src/rexmpp_xml_parser.c index d30d630..b2eaf8b 100644 --- a/src/rexmpp_xml_parser.c +++ b/src/rexmpp_xml_parser.c @@ -308,11 +308,12 @@ rexmpp_xml_parser_ctx_t rexmpp_xml_parser_reset (rexmpp_xml_parser_ctx_t ctx) { void rexmpp_xml_parser_feed (rexmpp_xml_parser_ctx_t ctx, const char *chunk, - size_t len) + size_t len, + int final) { #if defined(USE_LIBXML2) - xmlParseChunk(ctx->xml_parser, chunk, len, 0); + xmlParseChunk(ctx->xml_parser, chunk, len, final); #elif defined(USE_EXPAT) - XML_Parse(ctx->xml_parser, chunk, len, 0); + XML_Parse(ctx->xml_parser, chunk, len, final); #endif } diff --git a/src/rexmpp_xml_parser.h b/src/rexmpp_xml_parser.h index 07464a2..66627ab 100644 --- a/src/rexmpp_xml_parser.h +++ b/src/rexmpp_xml_parser.h @@ -42,6 +42,8 @@ struct rexmpp_xml_parser_ctx { xmlParserCtxtPtr xml_parser; #elif defined(USE_EXPAT) XML_Parser xml_parser; +#else + void *xml_parser; #endif rexmpp_xml_parser_handlers_t handlers; void *user_data; @@ -72,7 +74,8 @@ void rexmpp_xml_parser_free (rexmpp_xml_parser_ctx_t ctx); void rexmpp_xml_parser_feed (rexmpp_xml_parser_ctx_t ctx, const char *chunk, - size_t len); + size_t len, + int final); /** @brief Resets a parser context diff --git a/src/rexmpp_xml_parser.rs b/src/rexmpp_xml_parser.rs new file mode 100644 index 0000000..3c393de --- /dev/null +++ b/src/rexmpp_xml_parser.rs @@ -0,0 +1,146 @@ +extern crate libc; +extern crate rxml; +use libc::{free, strndup}; +use std::ptr; +use std::os::raw::{c_char, c_void}; +use std::ffi::{CStr, CString}; +use std::slice; +use rxml::{FeedParser, Error, ResolvedEvent, XmlVersion, EventRead, CData}; +use std::io; +use std::sync::Arc; +use super::{rexmpp_xml}; + +type RexmppXMLParserElementStart = unsafe extern "C" +fn (data: *mut c_void, + name: *const c_char, + namespace: *const c_char, + attributes: *mut rexmpp_xml::RexmppXMLAttribute) -> (); + +type RexmppXMLParserElementEnd = unsafe extern "C" +fn (data: *mut c_void) -> (); + +type RexmppXMLParserCharacters = unsafe extern "C" +fn (data: *mut c_void, + ch: *const c_char, + len: usize) -> (); + +#[repr(C)] +struct RexmppXMLParserHandlers { + elem_start: RexmppXMLParserElementStart, + elem_end: RexmppXMLParserElementEnd, + text: RexmppXMLParserCharacters +} + +#[repr(C)] +struct RexmppXMLParserCtx { + xml_parser: *mut FeedParser, + handlers: *mut RexmppXMLParserHandlers, + user_data: *mut c_void +} + +#[no_mangle] +extern "C" +fn rexmpp_xml_parser_new (handlers: *mut RexmppXMLParserHandlers, + data: *mut c_void) + -> *mut RexmppXMLParserCtx +{ + let mut fp = FeedParser::default(); + let ctx = RexmppXMLParserCtx { + xml_parser: Box::into_raw(Box::new(fp)), + handlers: handlers, + user_data: data + }; + Box::into_raw(Box::new(ctx)) +} + +#[no_mangle] +extern "C" +fn rexmpp_xml_parser_free (ctx: *mut RexmppXMLParserCtx) { + unsafe { free(ctx as *mut c_void) }; +} + +#[no_mangle] +extern "C" +fn rexmpp_xml_parser_feed (ctx: *mut RexmppXMLParserCtx, + chunk: *const c_char, + len: usize, + is_final: bool) +{ + unsafe { + // todo: maybe duplicate the string, since apparently a + // mutable one is expected by the parser. + let mut buf : &[u8] = slice::from_raw_parts(chunk as *mut u8, len); + let user_data_ptr = (*ctx).user_data; + let handlers = (*ctx).handlers; + (*((*ctx).xml_parser)).parse_all(&mut buf, is_final, |ev| { + match ev { + ResolvedEvent::StartElement(_, (namespace, name), attrs) => + { + let name_str = name.to_string(); + let ns_opt_cstr : Option = match namespace { + None => None, + Some(ns_arc_name) => { + match CString::new(ns_arc_name.to_string()) { + Ok(cstr) => Some(cstr), + Err(_) => None + } + } + }; + match CString::new(name_str) { + Ok(name_cstr) => { + let name_cstr_ptr = name_cstr.as_ptr(); + let namespace_cstr_ptr = + match ns_opt_cstr { + None => ptr::null_mut(), + // "ref" is important to use here, + // otherwise the pointer will be + // wrong. + Some(ref ns_cstr) => ns_cstr.as_ptr() + }; + let mut attributes = ptr::null_mut(); + for ((_, attr_name), attr_val) in attrs.iter() { + match (CString::new(attr_name.to_string()), + CString::new(attr_val.to_string())) { + (Ok(attr_name_cstr), Ok(attr_val_cstr)) => { + let attr = + rexmpp_xml::rexmpp_xml_attr_new + (attr_name_cstr.as_ptr(), + ptr::null_mut(), + attr_val_cstr.as_ptr()); + (*attr).next = attributes; + attributes = attr; + }, + _ => () + } + } + ((*handlers).elem_start) + (user_data_ptr, + name_cstr_ptr, + namespace_cstr_ptr, + attributes); + }, + Err(_) => () + } + }, + ResolvedEvent::EndElement(_) => + ((*handlers).elem_end)(user_data_ptr), + ResolvedEvent::Text(_, cd) => + ((*handlers).text)( + user_data_ptr, + cd.as_ptr() as *const i8, + cd.len() + ), + _ => () + } + }); + } +} + +#[no_mangle] +extern "C" +fn rexmpp_xml_parser_reset (ctx_raw: *mut RexmppXMLParserCtx) + -> *mut RexmppXMLParserCtx +{ + let ctx = unsafe { Box::from_raw(ctx_raw) }; + rexmpp_xml_parser_new((*ctx).handlers, (*ctx).user_data) +} -- cgit v1.2.3