[librsvg: 3/9] node.rs: Add C API for node.children() and tests



commit b42c3403ab7421a5c2b60fe4927c14804fd42040
Author: Ivan Molodetskikh <yalterz gmail com>
Date:   Thu Mar 15 21:23:51 2018 +0300

    node.rs: Add C API for node.children() and tests

 rsvg_internals/src/lib.rs  |   4 ++
 rsvg_internals/src/node.rs | 108 ++++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 111 insertions(+), 1 deletion(-)
---
diff --git a/rsvg_internals/src/lib.rs b/rsvg_internals/src/lib.rs
index be4c0105..bf09f27a 100644
--- a/rsvg_internals/src/lib.rs
+++ b/rsvg_internals/src/lib.rs
@@ -62,6 +62,10 @@ pub use mask::{
 
 pub use node::{
     rsvg_node_add_child,
+    rsvg_node_children_iter_begin,
+    rsvg_node_children_iter_end,
+    rsvg_node_children_iter_next,
+    rsvg_node_children_iter_next_back,
     rsvg_node_draw,
     rsvg_node_draw_children,
     rsvg_node_foreach_child,
diff --git a/rsvg_internals/src/node.rs b/rsvg_internals/src/node.rs
index 744cc8a1..fdde55f2 100644
--- a/rsvg_internals/src/node.rs
+++ b/rsvg_internals/src/node.rs
@@ -493,6 +493,67 @@ pub extern "C" fn rsvg_node_foreach_child(
     });
 }
 
+// This should really return Children<'a> where 'a is the lifetime of raw_node,
+// but raw pointers don't have lifetimes so there's not much we can do.
+#[no_mangle]
+pub extern "C" fn rsvg_node_children_iter_begin<'a>(
+    raw_node: *const RsvgNode,
+) -> *mut Children<'a> {
+    assert!(!raw_node.is_null());
+    let node: &RsvgNode = unsafe { &*raw_node };
+
+    Box::into_raw(Box::new(node.children()))
+}
+
+#[no_mangle]
+pub extern "C" fn rsvg_node_children_iter_end(iter: *mut Children) {
+    assert!(!iter.is_null());
+
+    unsafe { Box::from_raw(iter) };
+}
+
+#[no_mangle]
+pub extern "C" fn rsvg_node_children_iter_next(
+    iter: *mut Children,
+    out_child: *mut *mut RsvgNode,
+) -> glib_sys::gboolean {
+    assert!(!iter.is_null());
+
+    let iter = unsafe { &mut *iter };
+    if let Some(child) = iter.next() {
+        unsafe {
+            *out_child = box_node(child);
+        }
+        true.to_glib()
+    } else {
+        unsafe {
+            *out_child = ptr::null_mut();
+        }
+        false.to_glib()
+    }
+}
+
+#[no_mangle]
+pub extern "C" fn rsvg_node_children_iter_next_back(
+    iter: *mut Children,
+    out_child: *mut *mut RsvgNode,
+) -> glib_sys::gboolean {
+    assert!(!iter.is_null());
+
+    let iter = unsafe { &mut *iter };
+    if let Some(child) = iter.next_back() {
+        unsafe {
+            *out_child = box_node(child);
+        }
+        true.to_glib()
+    } else {
+        unsafe {
+            *out_child = ptr::null_mut();
+        }
+        false.to_glib()
+    }
+}
+
 #[no_mangle]
 pub extern "C" fn rsvg_node_draw_children(
     raw_node: *const RsvgNode,
@@ -510,7 +571,7 @@ mod tests {
     use super::*;
     use drawing_ctx::RsvgDrawingCtx;
     use handle::RsvgHandle;
-    use std::ptr;
+    use std::{mem, ptr};
     use std::rc::Rc;
 
     struct TestNodeImpl {}
@@ -671,4 +732,49 @@ mod tests {
         assert!(children.next().is_none());
         assert!(children.next_back().is_none());
     }
+
+    #[test]
+    fn node_children_iterator_c() {
+        let node = Rc::new(Node::new(
+            NodeType::Path,
+            None,
+            ptr::null_mut(),
+            Box::new(TestNodeImpl {}),
+        ));
+
+        let child = Rc::new(Node::new(
+            NodeType::Path,
+            Some(Rc::downgrade(&node)),
+            ptr::null_mut(),
+            Box::new(TestNodeImpl {}),
+        ));
+
+        let second_child = Rc::new(Node::new(
+            NodeType::Path,
+            Some(Rc::downgrade(&node)),
+            ptr::null_mut(),
+            Box::new(TestNodeImpl {}),
+        ));
+
+        node.add_child(&child);
+        node.add_child(&second_child);
+
+        let iter = rsvg_node_children_iter_begin(&node);
+        let mut c = unsafe { mem::uninitialized() };
+
+        let result: bool = from_glib(rsvg_node_children_iter_next(iter, &mut c));
+        assert_eq!(result, true);
+        assert!(rc_node_ptr_eq(unsafe { &*c }, &child));
+        rsvg_node_unref(c);
+
+        let result: bool = from_glib(rsvg_node_children_iter_next_back(iter, &mut c));
+        assert_eq!(result, true);
+        assert!(rc_node_ptr_eq(unsafe { &*c }, &second_child));
+        rsvg_node_unref(c);
+
+        let result: bool = from_glib(rsvg_node_children_iter_next(iter, &mut c));
+        assert_eq!(result, false);
+        let result: bool = from_glib(rsvg_node_children_iter_next_back(iter, &mut c));
+        assert_eq!(result, false);
+    }
 }


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]