summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordefanor <defanor@uberspace.net>2023-09-09 13:54:01 +0300
committerdefanor <defanor@uberspace.net>2023-09-09 13:54:01 +0300
commiteb6f5e7f1127783c347e31d8de506d583cc69c59 (patch)
treee3585e106c6b1d6ffabd7bf1fdfa62c851ae0369
parentaaae19eb8462c784daab0cf9afddc934fdbd1b75 (diff)
Use rxml for XML parsing when building with Rust
-rw-r--r--README24
-rw-r--r--configure.ac23
-rw-r--r--examples/basic.c1
-rw-r--r--src/Cargo.toml1
-rw-r--r--src/Makefile.am8
-rw-r--r--src/rexmpp.c2
-rw-r--r--src/rexmpp_console.c1
-rw-r--r--src/rexmpp_dns.c1
-rw-r--r--src/rexmpp_http_upload.c1
-rw-r--r--src/rexmpp_roster.c1
-rw-r--r--src/rexmpp_rust.rs1
-rw-r--r--src/rexmpp_sasl.c1
-rw-r--r--src/rexmpp_tls.c1
-rw-r--r--src/rexmpp_xml.c14
-rw-r--r--src/rexmpp_xml.rs114
-rw-r--r--src/rexmpp_xml_parser.c7
-rw-r--r--src/rexmpp_xml_parser.h5
-rw-r--r--src/rexmpp_xml_parser.rs146
18 files changed, 263 insertions, 89 deletions
diff --git a/README b/README
index f170859..267b945 100644
--- a/README
+++ b/README
@@ -12,11 +12,25 @@ rely on any particular UI, should be flexible and not stay in the way
of implementing additional XEPs on top of it, and should try to make
it easy to implement a decent client application using it.
-Current dependencies: libxml2 or libexpat, libgcrypt. Optionally
-gsasl, libunbound or c-ares, gnutls with gnutls-dane or openssl,
-icu-i18n, gpgme, curl, libnice (with glib), libsrtp2. For use of the
-alternative Rust implementations, rustc and cargo, with libc and errno
-Rust libraries.
+Mandatory dependencies:
+
+- libxml2, libexpat, or rxml (Rust)
+- libgcrypt
+
+Optional dependencies:
+
+- gsasl
+- libunbound or c-ares
+- gnutls with gnutls-dane or openssl
+- icu-i18n
+- gpgme
+- curl
+- libnice (with glib)
+- libsrtp2
+
+For use of the alternative Rust implementations, rustc and cargo
+should be available, and the following Rust libraries will be pulled:
+libc, errno, rxml.
A rough roadmap:
diff --git a/configure.ac b/configure.ac
index ed9f44c..656eb7d 100644
--- a/configure.ac
+++ b/configure.ac
@@ -13,31 +13,30 @@ AC_CONFIG_FILES([Makefile src/Makefile tests/Makefile rexmpp.pc Doxyfile])
AC_PROG_CC
AM_PROG_AR
+
+# Checks for libraries and related parameters.
+
AC_ARG_WITH([rust],
AS_HELP_STRING([--with-rust],
[use available Rust implementations of modules]))
+AC_ARG_WITH([expat],
+ AS_HELP_STRING([--with-expat], [use libexpat instead of libxml2]))
AS_IF([test "x$with_rust" == "xyes"],
[AC_PATH_PROG([RUSTC], [rustc], [notfound])
AS_IF([test "x$RUSTC" == "xnotfound"], [AC_MSG_ERROR([rustc is required])])
AC_PATH_PROG([CARGO], [cargo], [notfound])
AS_IF([test "x$CARGO" == "xnotfound"], [AC_MSG_ERROR([cargo is required])])
- AC_DEFINE([USE_RUST], [1], [Use Rust sources over C ones])])
+ AC_DEFINE([USE_RUST], [1], [Use Rust sources over C ones])],
+ [AS_IF([test "x$with_expat" == "xyes"],
+ [PKG_CHECK_MODULES([EXPAT], [expat],
+ [AC_DEFINE([USE_EXPAT], [1], [Use libexpat])])],
+ [PKG_CHECK_MODULES([LIBXML2], [libxml-2.0],
+ [AC_DEFINE([USE_LIBXML2], [1], [Use libxml2])])])])
AM_CONDITIONAL([USE_RUST], [test "x$with_rust" == "xyes"])
LT_INIT
-# Checks for libraries and related parameters.
-
-AC_ARG_WITH([expat],
- AS_HELP_STRING([--with-expat], [use libexpat instead of libxml2]))
-
-AS_IF([test "x$with_expat" == "xyes"],
- [PKG_CHECK_MODULES([EXPAT], [expat],
- [AC_DEFINE([USE_EXPAT], [1], [Use libexpat])])],
- [PKG_CHECK_MODULES([LIBXML2], [libxml-2.0],
- [AC_DEFINE([USE_LIBXML2], [1], [Use libxml2])])])
-
AM_PATH_LIBGCRYPT
diff --git a/examples/basic.c b/examples/basic.c
index 528cdf9..a529c22 100644
--- a/examples/basic.c
+++ b/examples/basic.c
@@ -12,6 +12,7 @@
#include <syslog.h>
#include <gsasl.h>
#include <time.h>
+#include <stdlib.h>
#include <rexmpp.h>
#include <rexmpp_xml.h>
#include <rexmpp_sasl.h>
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 <string.h>
+#include <stdlib.h>
#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 <memory.h>
+#include <stdlib.h>
#include <syslog.h>
#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 <string.h>
#include <libgen.h>
#include <errno.h>
+#include <stdlib.h>
#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 <syslog.h>
#include <string.h>
+#include <stdlib.h>
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 <syslog.h>
+#include <stdlib.h>
#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 <syslog.h>
#include <string.h>
+#include <stdlib.h>
#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 <string.h>
#include <stdio.h>
+#include <stdlib.h>
#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<CString> = 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)
+}