static css_error node_has_attribute_prefix(void *pw, void *node,
const css_qname *qname, lwc_string *prefix,
bool *match);
+static css_error node_has_attribute_suffix(void *pw, void *node,
+ const css_qname *qname, lwc_string *suffix,
+ bool *match);
/**
return CSS_OK;
}
+
+
+/**
+ * Test the given node for an attribute whose value end with the
+ * given suffix
+ *
+ * This will return true (via the "match" pointer) if the libdom node
+ * has an attribute with the given name and whose value ends with
+ * the given suffix string. The comparison is case-sensitive. This
+ * corresponds to [attr$=value] in CSS.
+ *
+ * \param pw Pointer to the current SVG parser state
+ * \param node Libdom SVG node to test
+ * \param qname Attribute name to check for
+ * \param suffix Value suffix to check for
+ * \param match Pointer to the test result
+ *
+ * \return Returns CSS_OK if successful and CSS_NOMEM if we cannot
+ * intern the attribute name (which usually indicates memory
+ * exhaustion)
+ */
+css_error node_has_attribute_suffix(void *pw, void *node,
+ const css_qname *qname, lwc_string *suffix,
+ bool *match)
+{
+ UNUSED(pw);
+ dom_string *name;
+ dom_string *attr_val;
+ dom_exception err;
+ const char *avdata; /* attribute value data */
+ size_t avdata_len; /* length of that attribute value data */
+ size_t suffixlen; /* length of "suffix" */
+
+ /* convenience pointer we'll use when matching the suffix */
+ const char *suffix_start;
+
+ suffixlen = lwc_string_length(suffix);
+ if (suffixlen == 0) {
+ /* In this case, the spec says that "if 'val' is the
+ * empty string, it will never represent anything." */
+ return CSS_OK;
+ }
+
+ /* Intern the attribute name as a dom_string so we can
+ * use dom_element_get_attribute() */
+ err = dom_string_create_interned(
+ (const uint8_t *) lwc_string_data(qname->name),
+ lwc_string_length(qname->name),
+ &name);
+ if (err != DOM_NO_ERR) {
+ return CSS_NOMEM;
+ }
+
+ err = dom_element_get_attribute((dom_node *)node, name, &attr_val);
+ if ((err != DOM_NO_ERR) || (attr_val == NULL)) {
+ /* There was an error getting the attribute's value or
+ * the attribute doesn't exist. So, no match? */
+ dom_string_unref(name);
+ *match = false;
+ return CSS_OK;
+ }
+
+ /* Otherwise, we have the attribute value from the given node,
+ * and the first thing we want to do is check to see if the
+ * whole thing matches the suffix. */
+ dom_string_unref(name);
+ *match = dom_string_lwc_isequal(attr_val, suffix);
+
+ /* If not, check to see if an, uh, suffix matches the
+ * suffix */
+ if (*match == false) {
+ avdata = dom_string_data(attr_val);
+ avdata_len = dom_string_byte_length(attr_val);
+
+ suffix_start = (char *)(avdata + avdata_len - suffixlen);
+
+ if ((avdata_len >= suffixlen) &&
+ (strncasecmp(suffix_start,
+ lwc_string_data(suffix),
+ suffixlen) == 0)) {
+ /* Use strncasecmp to compare only the last
+ * "n" characters, where "n" is the length of
+ * the suffix. */
+ *match = true;
+ }
+ }
+
+ dom_string_unref(attr_val);
+
+ return CSS_OK;
+}