[librsvg: 49/95] PropertyBag: Export rsvg_property_bag_iter_*() for use from C



commit 1b9946f6a0f847698067c124fefa7c6dab965e3f
Author: Federico Mena Quintero <federico gnome org>
Date:   Tue Feb 20 19:03:55 2018 -0600

    PropertyBag: Export rsvg_property_bag_iter_*() for use from C

 rsvg-private.h           | 17 +++++++++
 rust/src/lib.rs          |  3 ++
 rust/src/property_bag.rs | 95 +++++++++++++++++++++++++++++++++++++++++++++++-
 3 files changed, 114 insertions(+), 1 deletion(-)
---
diff --git a/rsvg-private.h b/rsvg-private.h
index 995ad8b9..15d8e6d2 100644
--- a/rsvg-private.h
+++ b/rsvg-private.h
@@ -451,6 +451,23 @@ G_GNUC_INTERNAL
 void                 rsvg_property_bag_enumerate (RsvgPropertyBag bag,
                                                   RsvgPropertyBagEnumFunc func,
                                                   gpointer user_data);
+
+typedef struct RsvgPropertyBagIter *RsvgPropertyBagIter;
+
+/* Implemented in rust/src/property_bag.rs */
+G_GNUC_INTERNAL
+RsvgPropertyBagIter *rsvg_property_bag_iter_begin (RsvgPropertyBag bag);
+
+/* Implemented in rust/src/property_bag.rs */
+G_GNUC_INTERNAL
+gboolean rsvg_property_bag_iter_next (RsvgPropertyBagIter *iter,
+                                      const char **out_key,
+                                      const char **out_value);
+
+/* Implemented in rust/src/property_bag.rs */
+G_GNUC_INTERNAL
+void rsvg_property_bag_iter_end (RsvgPropertyBagIter *iter);
+
 /* for some reason this one's public... */
 GdkPixbuf *rsvg_pixbuf_from_data_with_size_data (const guchar * buff,
                                                  size_t len,
diff --git a/rust/src/lib.rs b/rust/src/lib.rs
index e49dd2f2..77ed6cd6 100644
--- a/rust/src/lib.rs
+++ b/rust/src/lib.rs
@@ -131,6 +131,9 @@ pub use pattern::{
 pub use property_bag::{
     rsvg_property_bag_enumerate,
     rsvg_property_bag_free,
+    rsvg_property_bag_iter_begin,
+    rsvg_property_bag_iter_end,
+    rsvg_property_bag_iter_next,
     rsvg_property_bag_lookup,
     rsvg_property_bag_new,
     rsvg_property_bag_size,
diff --git a/rust/src/property_bag.rs b/rust/src/property_bag.rs
index 4335222a..635b1267 100644
--- a/rust/src/property_bag.rs
+++ b/rust/src/property_bag.rs
@@ -1,5 +1,8 @@
 use libc;
 
+use glib_sys;
+use glib::translate::*;
+
 use std::collections::HashMap;
 use std::collections::hash_map;
 use std::ffi::{CStr, CString};
@@ -157,10 +160,50 @@ pub extern fn rsvg_property_bag_lookup(pbag: *const PropertyBag,
     }
 }
 
+#[no_mangle]
+pub extern fn rsvg_property_bag_iter_begin(pbag: *const PropertyBag) -> *mut PropertyBagCStrIter {
+    assert!(!pbag.is_null());
+    let pbag = unsafe { &*pbag };
+
+    Box::into_raw(Box::new(pbag.cstr_iter()))
+}
+
+#[no_mangle]
+pub extern fn rsvg_property_bag_iter_next(iter: *mut PropertyBagCStrIter,
+                                          out_key: *mut *const libc::c_char,
+                                          out_value: *mut *const libc::c_char)
+                                          -> glib_sys::gboolean
+{
+    assert!(!iter.is_null());
+    let iter = unsafe { &mut *iter };
+
+    if let Some((key, val)) = iter.next() {
+        unsafe {
+            *out_key = key.as_ptr();
+            *out_value = val.as_ptr();
+        }
+        true.to_glib()
+    } else {
+        unsafe {
+            *out_key = ptr::null();
+            *out_value = ptr::null();
+        }
+        false.to_glib()
+    }
+}
+
+#[no_mangle]
+pub extern fn rsvg_property_bag_iter_end(iter: *mut PropertyBagCStrIter) {
+    assert!(!iter.is_null());
+
+    unsafe { Box::from_raw(iter) };
+}
+
 #[cfg(test)]
 mod tests {
     use super::*;
     use std::ffi::CString;
+    use std::mem;
 
     #[test]
     fn empty_property_bag() {
@@ -194,10 +237,12 @@ mod tests {
         let mut had_alpha: bool = false;
         let mut had_beta: bool = false;
 
-        for (k, _) in pbag.iter() {
+        for (k, v) in pbag.iter() {
             if k == "alpha" {
+                assert!(v == "1");
                 had_alpha = true;
             } else if k == "beta" {
+                assert!(v == "2");
                 had_beta = true;
             }
         }
@@ -205,4 +250,52 @@ mod tests {
         assert!(had_alpha);
         assert!(had_beta);
     }
+
+    #[test]
+    fn property_bag_can_iterate_from_c() {
+        let pairs = [
+            CString::new("alpha").unwrap(),
+            CString::new("1").unwrap(),
+            CString::new("beta").unwrap(),
+            CString::new("2").unwrap(),
+        ];
+
+        let mut v = Vec::new();
+
+        for x in &pairs {
+            v.push(x.as_ptr() as *const libc::c_char);
+        }
+
+        v.push(ptr::null());
+
+        let pbag = unsafe { PropertyBag::new_from_key_value_pairs(v.as_ptr()) };
+
+        let mut had_alpha: bool = false;
+        let mut had_beta: bool = false;
+
+        let iter = rsvg_property_bag_iter_begin(&pbag as *const PropertyBag);
+
+        let mut key = unsafe { mem::uninitialized() };
+        let mut val = unsafe { mem::uninitialized() };
+
+        while from_glib(rsvg_property_bag_iter_next(iter,
+                                                    &mut key as *mut _,
+                                                    &mut val as *mut _)) {
+            let k = unsafe { CStr::from_ptr(key).to_str().unwrap() };
+            let v = unsafe { CStr::from_ptr(val).to_str().unwrap() };
+
+            if k == "alpha" {
+                assert!(v == "1");
+                had_alpha = true;
+            } else if k == "beta" {
+                assert!(v == "2");
+                had_beta = true;
+            }
+        }
+
+        rsvg_property_bag_iter_end(iter);
+
+        assert!(had_alpha);
+        assert!(had_beta);
+    }
 }


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