[librsvg] node.rs: New function rsvg_node_is_same() to compare node pointers
- From: Federico Mena Quintero <federico src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [librsvg] node.rs: New function rsvg_node_is_same() to compare node pointers
- Date: Fri, 17 Feb 2017 16:39:24 +0000 (UTC)
commit aec1ceac95759cdea7330d51c4e877e6edc93347
Author: Federico Mena Quintero <federico gnome org>
Date: Thu Feb 16 21:08:16 2017 -0600
node.rs: New function rsvg_node_is_same() to compare node pointers
On the C side, two RsvgNode* can be different and yet refer to the same
Node in the Rust code. This function can be used to test for that.
That is,
if (node_a == node_b)
is no longer valid in the C code. Instead, use this:
if (rsvg_node_is_same (node_a, node_b))
rsvg-private.h | 4 +++
rust/src/lib.rs | 1 +
rust/src/node.rs | 67 ++++++++++++++++++++++++++++++++++++++++++++++++++++-
3 files changed, 70 insertions(+), 2 deletions(-)
---
diff --git a/rsvg-private.h b/rsvg-private.h
index 1d24f2f..955fa2f 100644
--- a/rsvg-private.h
+++ b/rsvg-private.h
@@ -358,6 +358,10 @@ G_GNUC_INTERNAL
RsvgNodeType rsvg_node_get_type (RsvgNode *node);
/* Implemented in rust/src/node.rs */
+G_GNUC_INTERNAL
+gboolean rsvg_node_is_same (RsvgNode *node1, RsvgNode *node2);
+
+/* Implemented in rust/src/node.rs */
/* Call this as newref = rsvg_node_ref (node); You don't own the node anymore, just the newref! */
G_GNUC_INTERNAL
RsvgNode *rsvg_node_ref (RsvgNode *node) G_GNUC_WARN_UNUSED_RESULT;
diff --git a/rust/src/lib.rs b/rust/src/lib.rs
index a3cea12..8826619 100644
--- a/rust/src/lib.rs
+++ b/rust/src/lib.rs
@@ -59,6 +59,7 @@ pub use node::{
rsvg_node_get_parent,
rsvg_node_ref,
rsvg_node_unref,
+ rsvg_node_is_same,
rsvg_node_get_state,
rsvg_node_add_child,
rsvg_node_set_atts,
diff --git a/rust/src/node.rs b/rust/src/node.rs
index 5ede878..0eb18c0 100644
--- a/rust/src/node.rs
+++ b/rust/src/node.rs
@@ -173,9 +173,9 @@ pub extern fn rsvg_node_get_parent (raw_node: *const RsvgNode) -> *const RsvgNod
}
#[no_mangle]
-pub unsafe extern fn rsvg_node_ref (raw_node: *mut RsvgNode) -> *mut RsvgNode {
+pub extern fn rsvg_node_ref (raw_node: *mut RsvgNode) -> *mut RsvgNode {
assert! (!raw_node.is_null ());
- let node: &RsvgNode = & *raw_node;
+ let node: &RsvgNode = unsafe { & *raw_node };
box_node (node.clone ())
}
@@ -189,6 +189,30 @@ pub extern fn rsvg_node_unref (raw_node: *mut RsvgNode) -> *mut RsvgNode {
ptr::null_mut () // so the caller can do "node = rsvg_node_unref (node);" and lose access to the node
}
+// See https://github.com/rust-lang/rust/issues/36497 - this is what
+// added Rc::ptr_eq(), but we don't want to depend on unstable Rust
+// just yet.
+
+fn rc_node_ptr_eq<T: ?Sized> (this: &Rc<T>, other: &Rc<T>) -> bool {
+ let this_ptr: *const T = &**this;
+ let other_ptr: *const T = &**other;
+ this_ptr == other_ptr
+}
+
+#[no_mangle]
+pub extern fn rsvg_node_is_same (raw_node1: *const RsvgNode, raw_node2: *const RsvgNode) -> bool {
+ if raw_node1.is_null () && raw_node2.is_null () {
+ true
+ } else if !raw_node1.is_null () && !raw_node2.is_null () {
+ let node1: &RsvgNode = unsafe { & *raw_node1 };
+ let node2: &RsvgNode = unsafe { & *raw_node2 };
+
+ rc_node_ptr_eq (node1, node2)
+ } else {
+ false
+ }
+}
+
#[no_mangle]
pub extern fn rsvg_node_get_state (raw_node: *const RsvgNode) -> *mut RsvgState {
assert! (!raw_node.is_null ());
@@ -285,4 +309,43 @@ mod tests {
ref1 = unsafe { rsvg_node_unref (ref1) };
assert! (weak.upgrade ().is_none ());
}
+
+ #[test]
+ fn reffed_node_is_same_as_original_node () {
+ let node = Rc::new (Node::new (NodeType::Path,
+ None,
+ ptr::null_mut (),
+ Box::new (TestNodeImpl {})));
+
+ let mut ref1 = box_node (node);
+
+ let mut ref2 = unsafe { rsvg_node_ref (ref1) };
+
+ unsafe { assert! (rsvg_node_is_same (ref1, ref2)); }
+
+ ref1 = rsvg_node_unref (ref1);
+ ref2 = rsvg_node_unref (ref2);
+ }
+
+ #[test]
+ fn different_nodes_have_different_pointers () {
+ let node1 = Rc::new (Node::new (NodeType::Path,
+ None,
+ ptr::null_mut (),
+ Box::new (TestNodeImpl {})));
+
+ let mut ref1 = box_node (node1);
+
+ let node2 = Rc::new (Node::new (NodeType::Path,
+ None,
+ ptr::null_mut (),
+ Box::new (TestNodeImpl {})));
+
+ let mut ref2 = box_node (node2);
+
+ unsafe { assert! (!rsvg_node_is_same (ref1, ref2)); }
+
+ ref1 = rsvg_node_unref (ref1);
+ ref2 = rsvg_node_unref (ref2);
+ }
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]