[librsvg: 94/95] PropertyBag: Use a Vec, not a HashMap
- From: Federico Mena Quintero <federico src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [librsvg: 94/95] PropertyBag: Use a Vec, not a HashMap
- Date: Thu, 22 Feb 2018 03:21:02 +0000 (UTC)
commit 24450902aa89efbb0b6f17ab1a1530c935bb57c3
Author: Federico Mena Quintero <federico gnome org>
Date: Wed Feb 21 20:32:59 2018 -0600
PropertyBag: Use a Vec, not a HashMap
We create a Vec to hold tuples of (key, attribute, value) from the
supplied C array of strings. Since there is no lookup() operation
anymore, we only need to support iteration over this underlying Vec.
rust/src/property_bag.rs | 53 ++++++++++++++++++++++++++++++++----------------
1 file changed, 36 insertions(+), 17 deletions(-)
---
diff --git a/rust/src/property_bag.rs b/rust/src/property_bag.rs
index 680b0c88..2866a552 100644
--- a/rust/src/property_bag.rs
+++ b/rust/src/property_bag.rs
@@ -3,22 +3,22 @@ use libc;
use glib_sys;
use glib::translate::*;
-use std::collections::HashMap;
-use std::collections::hash_map;
use std::ffi::{CStr, CString};
use std::ops::Deref;
use std::ptr;
+use std::slice;
use std::str::{self, FromStr};
use attributes::Attribute;
-pub struct PropertyBag<'a>(HashMap<&'a CStr, (Attribute, &'a CStr)>);
+// We store (key, attribute, value)
+pub struct PropertyBag<'a>(Vec<(&'a CStr, Attribute, &'a CStr)>);
-pub struct OwnedPropertyBag(HashMap<CString, (Attribute, CString)>);
+pub struct OwnedPropertyBag(Vec<(CString, Attribute, CString)>);
pub struct PropertyBagIter<'a>(PropertyBagCStrIter<'a>);
-pub struct PropertyBagCStrIter<'a>(hash_map::Iter<'a, &'a CStr, (Attribute, &'a CStr)>);
+pub struct PropertyBagCStrIter<'a>(slice::Iter<'a, (&'a CStr, Attribute, &'a CStr)>);
trait Utf8CStrToStr {
fn to_str_utf8(&self) -> &str;
@@ -34,8 +34,27 @@ impl Utf8CStrToStr for CStr {
}
impl<'a> PropertyBag<'a> {
+ /// Creates an iterable `PropertyBag` from a C array of borrowed C strings.
+ ///
+ /// With libxml2's SAX parser, the caller's callback for "element start"
+ /// gets passed a `xmlChar **` of attribute/value pairs. Even indices
+ /// in the array are pointers to attribute names; odd indices are
+ /// pointers to attribute values. The array terminates with a NULL
+ /// element in an even index.
+ ///
+ /// This function is unsafe because the caller must guarantee the following:
+ ///
+ /// * `pairs` is a valid pointer, or NULL for an empty array
+ ///
+ /// * `pairs` has key/value pairs and is NULL terminated
+ ///
+ /// * Both keys and values are valid UTF-8, nul-terminated C strings
+ ///
+ /// The lifetime of the `PropertyBag` should be considered the same as the lifetime of the
+ /// `pairs` array, as the property bag does not copy the strings - it directly stores pointers
+ /// into that array's strings.
pub unsafe fn new_from_key_value_pairs(pairs: *const *const libc::c_char) -> PropertyBag<'a> {
- let mut map = HashMap::new();
+ let mut array = Vec::new();
if !pairs.is_null() {
let mut i = 0;
@@ -51,7 +70,7 @@ impl<'a> PropertyBag<'a> {
// We silently drop unknown attributes. New attributes should be added in
// build.rs.
if let Ok(attr) = Attribute::from_str(key_str.to_str_utf8()) {
- map.insert(key_str, (attr, val_str));
+ array.push((key_str, attr, val_str));
}
} else {
break;
@@ -61,27 +80,27 @@ impl<'a> PropertyBag<'a> {
}
}
- PropertyBag(map)
+ PropertyBag(array)
}
pub fn from_owned(owned: &OwnedPropertyBag) -> PropertyBag {
- let mut map = HashMap::new();
+ let mut array = Vec::new();
- for (k, &(a, ref v)) in &owned.0 {
- map.insert(k.deref(), (a, v.deref()));
+ for &(ref k, a, ref v) in &owned.0 {
+ array.push((k.deref(), a, v.deref()));
}
- PropertyBag(map)
+ PropertyBag(array)
}
pub fn to_owned(&self) -> OwnedPropertyBag {
- let mut map = HashMap::<CString, (Attribute, CString)>::new();
+ let mut array = Vec::<(CString, Attribute, CString)>::new();
- for (k, &(a, v)) in &self.0 {
- map.insert((*k).to_owned(), (a, (*v).to_owned()));
+ for &(ref k, a, ref v) in &self.0 {
+ array.push(((*k).to_owned(), a, (*v).to_owned()));
}
- OwnedPropertyBag(map)
+ OwnedPropertyBag(array)
}
pub fn ffi(&self) -> *const PropertyBag {
@@ -113,7 +132,7 @@ impl<'a> Iterator for PropertyBagCStrIter<'a> {
type Item = (&'a CStr, Attribute, &'a CStr);
fn next(&mut self) -> Option<Self::Item> {
- self.0.next().map(|(k, &(a, v))| (*k, a, v))
+ self.0.next().map(|&(k, a, v)| (k, a, v))
}
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]