[librsvg: 4/5] Move class/id indexes into Attributes
- From: Marge Bot <marge-bot src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [librsvg: 4/5] Move class/id indexes into Attributes
- Date: Fri, 22 Jul 2022 19:40:54 +0000 (UTC)
commit 3af3832ec09afcea6e75956febd693bbc04758fe
Author: Michael Howell <michael notriddle com>
Date: Thu Jul 21 14:55:08 2022 -0700
Move class/id indexes into Attributes
Part-of: <https://gitlab.gnome.org/GNOME/librsvg/-/merge_requests/715>
src/element.rs | 47 ++++++----------------------------
src/xml/attributes.rs | 70 ++++++++++++++++++++++++++++++++-------------------
src/xml/mod.rs | 2 +-
3 files changed, 53 insertions(+), 66 deletions(-)
---
diff --git a/src/element.rs b/src/element.rs
index 8b993cb6c..4619cda8e 100644
--- a/src/element.rs
+++ b/src/element.rs
@@ -42,7 +42,7 @@ use crate::shapes::{Circle, Ellipse, Line, Path, Polygon, Polyline, Rect};
use crate::structure::{ClipPath, Group, Link, Mask, NonRendering, Svg, Switch, Symbol, Use};
use crate::style::Style;
use crate::text::{TRef, TSpan, Text};
-use crate::xml::{AttributeIndex, Attributes};
+use crate::xml::Attributes;
// After creating/parsing a Element, it will be in a success or an error state.
// We represent this with a Result, aliased as a ElementResult. There is no
@@ -94,8 +94,6 @@ pub trait Draw {
pub struct ElementInner<T: SetAttributes + Draw> {
element_name: QualName,
- id_idx: Option<AttributeIndex>, // id attribute from XML element
- class_idx: Option<AttributeIndex>, // class attribute from XML element
attributes: Attributes,
specified_values: SpecifiedValues,
important_styles: HashSet<QualName>,
@@ -110,16 +108,12 @@ pub struct ElementInner<T: SetAttributes + Draw> {
impl<T: SetAttributes + Draw> ElementInner<T> {
fn new(
element_name: QualName,
- id_idx: Option<AttributeIndex>,
- class_idx: Option<AttributeIndex>,
attributes: Attributes,
result: Result<(), ElementError>,
element_impl: T,
) -> ElementInner<T> {
let mut e = Self {
element_name,
- id_idx,
- class_idx,
attributes,
specified_values: Default::default(),
important_styles: Default::default(),
@@ -153,13 +147,11 @@ impl<T: SetAttributes + Draw> ElementInner<T> {
}
fn get_id(&self) -> Option<&str> {
- self.id_idx
- .and_then(|id_idx| self.attributes.get_by_index(id_idx))
+ self.attributes.get_id()
}
fn get_class(&self) -> Option<&str> {
- self.class_idx
- .and_then(|class_idx| self.attributes.get_by_index(class_idx))
+ self.attributes.get_class()
}
fn inherit_xml_lang(&mut self, parent: Option<Node>) {
@@ -453,18 +445,7 @@ impl Element {
///
/// This operation does not fail. Unknown element names simply produce a [`NonRendering`]
/// element.
- pub fn new(name: &QualName, attrs: Attributes) -> Element {
- let mut id_idx = None;
- let mut class_idx = None;
-
- for (idx, attr, _) in attrs.iter_indexed() {
- match attr.expanded() {
- expanded_name!("", "id") => id_idx = Some(idx),
- expanded_name!("", "class") => class_idx = Some(idx),
- _ => (),
- }
- }
-
+ pub fn new(name: &QualName, mut attrs: Attributes) -> Element {
let (create_fn, flags): (ElementCreateFn, ElementCreateFlags) = if name.ns == ns!(svg) {
match ELEMENT_CREATORS.get(name.local.as_ref()) {
// hack in the SVG namespace for supported element names
@@ -480,12 +461,12 @@ impl Element {
};
if flags == ElementCreateFlags::IgnoreClass {
- class_idx = None;
+ attrs.clear_class();
};
// sizes::print_sizes();
- create_fn(name, attrs, id_idx, class_idx)
+ create_fn(name, attrs)
}
pub fn element_name(&self) -> &QualName {
@@ -604,20 +585,13 @@ impl fmt::Display for Element {
macro_rules! e {
($name:ident, $element_type:ident) => {
- pub fn $name(
- element_name: &QualName,
- attributes: Attributes,
- id_idx: Option<AttributeIndex>,
- class_idx: Option<AttributeIndex>,
- ) -> Element {
+ pub fn $name(element_name: &QualName, attributes: Attributes) -> Element {
let mut element_impl = <$element_type>::default();
let result = element_impl.set_attributes(&attributes);
let element = Element::$element_type(Box::new(ElementInner::new(
element_name.clone(),
- id_idx,
- class_idx,
attributes,
result,
element_impl,
@@ -701,12 +675,7 @@ mod creators {
use creators::*;
-type ElementCreateFn = fn(
- element_name: &QualName,
- attributes: Attributes,
- id_idx: Option<AttributeIndex>,
- class_idx: Option<AttributeIndex>,
-) -> Element;
+type ElementCreateFn = fn(element_name: &QualName, attributes: Attributes) -> Element;
#[derive(Copy, Clone, PartialEq)]
enum ElementCreateFlags {
diff --git a/src/xml/attributes.rs b/src/xml/attributes.rs
index 1ef0e7616..9c8ebe96b 100644
--- a/src/xml/attributes.rs
+++ b/src/xml/attributes.rs
@@ -3,7 +3,9 @@
use std::slice;
use std::str;
-use markup5ever::{namespace_url, LocalName, Namespace, Prefix, QualName};
+use markup5ever::{
+ expanded_name, local_name, namespace_url, ns, LocalName, Namespace, Prefix, QualName,
+};
use string_cache::DefaultAtom;
use crate::error::{ImplementationLimit, LoadingError};
@@ -16,20 +18,17 @@ use crate::util::{opt_utf8_cstr, utf8_cstr};
/// string_cache crate.
pub type AttributeValue = DefaultAtom;
-/// Type used to store an index into the attributes list.
-///
-/// Searching by name requires a linear scan, while looking up by index happens in
-/// constant time.
-#[derive(Clone, Copy)]
-pub struct AttributeIndex(u16);
-
/// Iterable wrapper for libxml2's representation of attribute/value.
///
/// See the [`new_from_xml2_attributes`] function for information.
///
/// [`new_from_xml2_attributes`]: #method.new_from_xml2_attributes
#[derive(Clone)]
-pub struct Attributes(Box<[(QualName, AttributeValue)]>);
+pub struct Attributes {
+ attrs: Box<[(QualName, AttributeValue)]>,
+ id_idx: Option<u16>,
+ class_idx: Option<u16>,
+}
/// Iterator from `Attributes.iter`.
pub struct AttributesIter<'a>(slice::Iter<'a, (QualName, AttributeValue)>);
@@ -37,7 +36,11 @@ pub struct AttributesIter<'a>(slice::Iter<'a, (QualName, AttributeValue)>);
impl Attributes {
#[cfg(test)]
pub fn new() -> Attributes {
- Attributes([].into())
+ Attributes {
+ attrs: [].into(),
+ id_idx: None,
+ class_idx: None,
+ }
}
/// Creates an iterable `Attributes` from the C array of borrowed C strings.
@@ -61,6 +64,8 @@ impl Attributes {
attrs: *const *const libc::c_char,
) -> Result<Attributes, LoadingError> {
let mut array = Vec::with_capacity(n_attributes);
+ let mut id_idx = None;
+ let mut class_idx = None;
if n_attributes > limits::MAX_LOADED_ATTRIBUTES {
return Err(LoadingError::LimitExceeded(
@@ -102,40 +107,53 @@ impl Attributes {
let value_str = str::from_utf8_unchecked(value_slice);
let value_atom = DefaultAtom::from(value_str);
+ let idx = array.len() as u16;
+ match qual_name.expanded() {
+ expanded_name!("", "id") => id_idx = Some(idx),
+ expanded_name!("", "class") => class_idx = Some(idx),
+ _ => (),
+ }
+
array.push((qual_name, value_atom));
}
}
}
- Ok(Attributes(array.into()))
+ Ok(Attributes {
+ attrs: array.into(),
+ id_idx,
+ class_idx,
+ })
}
/// Returns the number of attributes.
pub fn len(&self) -> usize {
- self.0.len()
+ self.attrs.len()
}
/// Creates an iterator that yields `(QualName, &'a str)` tuples.
pub fn iter(&self) -> AttributesIter<'_> {
- AttributesIter(self.0.iter())
+ AttributesIter(self.attrs.iter())
}
- /// Creates an iterator that yields `(AttributeIndex, QualName, &'a str)` tuples.
- pub fn iter_indexed(&self) -> impl Iterator<Item = (AttributeIndex, QualName, &'_ str)> + '_ {
- self.iter().enumerate().map(|(index, (name, value))| {
- let index = AttributeIndex(
- index
- .try_into()
- .expect("overlong indexes are filtered at creation time"),
- );
- (index, name, value)
+ pub fn get_id(&self) -> Option<&str> {
+ self.id_idx.and_then(|idx| {
+ self.attrs
+ .get(usize::from(idx))
+ .map(|(_name, value)| &value[..])
+ })
+ }
+
+ pub fn get_class(&self) -> Option<&str> {
+ self.class_idx.and_then(|idx| {
+ self.attrs
+ .get(usize::from(idx))
+ .map(|(_name, value)| &value[..])
})
}
- pub fn get_by_index(&self, idx: AttributeIndex) -> Option<&str> {
- self.0
- .get(usize::from(idx.0))
- .map(|(_name, value)| &value[..])
+ pub fn clear_class(&mut self) {
+ self.class_idx = None;
}
}
diff --git a/src/xml/mod.rs b/src/xml/mod.rs
index 6a414a736..8a6c7ed40 100644
--- a/src/xml/mod.rs
+++ b/src/xml/mod.rs
@@ -33,7 +33,7 @@ mod attributes;
mod xml2;
mod xml2_load;
-pub use attributes::{AttributeIndex, Attributes};
+pub use attributes::Attributes;
#[derive(Clone)]
enum Context {
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]