1578 lines · 30.6 KB · C
RawDownload
#include <ctype.h>#include <inttypes.h>#include <stdbool.h>#include <stdio.h>#include <stdlib.h>#include <string.h> #include <libcss/libcss.h>#include <libcss/computed.h>#include <libcss/select.h>#include <libcss/stylesheet.h> #include "utils/utils.h" #include "dump_computed.h"#include "testutils.h" typedef struct attribute {	lwc_string *name;	lwc_string *value;} attribute; typedef struct node {	lwc_string *name; 	uint32_t n_classes;	lwc_string **classes; 	uint32_t n_attrs;	attribute *attrs; 	css_select_results *sr;	void *libcss_node_data; 	struct node *parent;	struct node *next;	struct node *prev;	struct node *children;	struct node *last_child;} node; typedef struct sheet_ctx {	css_stylesheet *sheet;	css_origin origin;	char *media;} sheet_ctx; typedef struct line_ctx {	size_t explen;	size_t expused;	char *exp; 	bool intree;	bool insheet;	bool inerrors;	bool inexp; 	node *tree;	node *current;	uint32_t depth; 	uint32_t n_sheets;	sheet_ctx *sheets; 	css_media media;	uint32_t pseudo_element;	node *target; 	lwc_string *attr_class;	lwc_string *attr_id;} line_ctx; static css_error node_name(void *pw, void *n, css_qname *qname){	node *node = n; 	UNUSED(pw); 	qname->name = lwc_string_ref(node->name); 	return CSS_OK;} static css_error node_classes(void *pw, void *n,		lwc_string ***classes, uint32_t *n_classes){	unsigned int i;	node *node = n;	UNUSED(pw); 	*classes = node->classes;	*n_classes = node->n_classes; 	for (i = 0; i < *n_classes; i++)		(*classes)[i] = lwc_string_ref(node->classes[i]); 	return CSS_OK; } static css_error node_id(void *pw, void *n,		lwc_string **id){	node *node = n;	uint32_t i;	line_ctx *lc = pw; 	for (i = 0; i < node->n_attrs; i++) {		bool amatch = false;		assert(lwc_string_caseless_isequal(				node->attrs[i].name, lc->attr_id, &amatch) ==				lwc_error_ok);		if (amatch == true)			break;	} 	if (i != node->n_attrs)		*id = lwc_string_ref(node->attrs[i].value);	else		*id = NULL; 	return CSS_OK;} static css_error named_ancestor_node(void *pw, void *n,		const css_qname *qname,		void **ancestor){	node *node = n;	UNUSED(pw); 	for (node = node->parent; node != NULL; node = node->parent) {		bool match = false;		assert(lwc_string_caseless_isequal(				qname->name, node->name,				&match) == lwc_error_ok);		if (match == true)			break;	} 	*ancestor = (void *) node; 	return CSS_OK;} static css_error named_parent_node(void *pw, void *n,		const css_qname *qname,		void **parent){	node *node = n;	UNUSED(pw); 	*parent = NULL;	if (node->parent != NULL) {		bool match = false;		assert(lwc_string_caseless_isequal(				qname->name, node->parent->name, &match) ==				lwc_error_ok);		if (match == true)			*parent = (void *) node->parent;	} 	return CSS_OK;} static css_error named_sibling_node(void *pw, void *n,		const css_qname *qname,		void **sibling){	node *node = n;	UNUSED(pw); 	*sibling = NULL;	if (node->prev != NULL) {		bool match = false;		assert(lwc_string_caseless_isequal(				qname->name, node->prev->name, &match) ==				lwc_error_ok);		if (match == true)			*sibling = (void *) node->prev;	} 	return CSS_OK;} static css_error named_generic_sibling_node(void *pw, void *n,		const css_qname *qname,		void **sibling){	node *node = n;	UNUSED(pw); 	for (node = node->prev; node != NULL; node = node->prev) {		bool match = false;		assert(lwc_string_caseless_isequal(				qname->name, node->name,				&match) == lwc_error_ok);		if (match == true)			break;	} 	*sibling = (void *) node; 	return CSS_OK;} static css_error parent_node(void *pw, void *n, void **parent){	node *node = n; 	UNUSED(pw); 	*parent = (void *) node->parent; 	return CSS_OK;} static css_error sibling_node(void *pw, void *n, void **sibling){	node *node = n; 	UNUSED(pw); 	*sibling = (void *) node->prev; 	return CSS_OK;} static css_error node_has_name(void *pw, void *n,		const css_qname *qname,		bool *match){	node *node = n;	UNUSED(pw); 	if (lwc_string_length(qname->name) == 1 &&			lwc_string_data(qname->name)[0] == '*')		*match = true;	else		assert(lwc_string_caseless_isequal(node->name,			qname->name, match) == lwc_error_ok); 	return CSS_OK;} static css_error node_has_class(void *pw, void *n,		lwc_string *name,		bool *match){	node *node = n;	uint32_t i;	line_ctx *ctx = pw; 	for (i = 0; i < node->n_attrs; i++) {		bool amatch = false;		assert(lwc_string_caseless_isequal(				node->attrs[i].name, ctx->attr_class,				&amatch) == lwc_error_ok);		if (amatch == true)			break;	} 	/* Classes are case-sensitive in HTML */	if (i != node->n_attrs && name == node->attrs[i].value)		*match = true;	else		*match = false; 	return CSS_OK;} static css_error node_has_id(void *pw, void *n,		lwc_string *name,		bool *match){	node *node = n;	uint32_t i;	line_ctx *ctx = pw; 	for (i = 0; i < node->n_attrs; i++) {		bool amatch = false;		assert(lwc_string_caseless_isequal(				node->attrs[i].name, ctx->attr_id, &amatch) ==				lwc_error_ok);		if (amatch == true)			break;	} 	/* IDs are case-sensitive in HTML */	if (i != node->n_attrs && name == node->attrs[i].value)		*match = true;	else		*match = false; 	return CSS_OK;} static css_error node_has_attribute(void *pw, void *n,		const css_qname *qname,		bool *match){	node *node = n;	uint32_t i;	UNUSED(pw); 	*match = false;	for (i = 0; i < node->n_attrs; i++) {		assert(lwc_string_caseless_isequal(				node->attrs[i].name, qname->name, match) ==				lwc_error_ok);		if (*match == true)			break;	} 	return CSS_OK;} static css_error node_has_attribute_equal(void *pw, void *n,		const css_qname *qname,		lwc_string *value,		bool *match){	node *node = n;	uint32_t i;	UNUSED(pw); 	*match = false; 	for (i = 0; i < node->n_attrs; i++) {		assert(lwc_string_caseless_isequal(				node->attrs[i].name, qname->name, match) ==				lwc_error_ok);		if (*match == true)			break;	} 	if (*match == true) {		assert(lwc_string_caseless_isequal(				node->attrs[i].name, value, match) ==				lwc_error_ok);	} 	return CSS_OK;} static css_error node_has_attribute_includes(void *pw, void *n,		const css_qname *qname,		lwc_string *value,		bool *match){	node *node = n;	uint32_t i;	size_t vlen = lwc_string_length(value);	UNUSED(pw); 	*match = false; 	for (i = 0; i < node->n_attrs; i++) {		assert(lwc_string_caseless_isequal(				node->attrs[i].name, qname->name, match) ==				lwc_error_ok);		if (*match == true)			break;	} 	if (*match == true) {		const char *p;		const char *start = lwc_string_data(node->attrs[i].value);		const char *end = start +				lwc_string_length(node->attrs[i].value); 		*match = false; 		for (p = start; p < end; p++) {			if (*p == ' ') {				if ((size_t) (p - start) == vlen &&						strncasecmp(start,							lwc_string_data(value),							vlen) == 0) {					*match = true;					break;				} 				start = p + 1;			}		}	} 	return CSS_OK;} static css_error node_has_attribute_dashmatch(void *pw, void *n,		const css_qname *qname,		lwc_string *value,		bool *match){	node *node = n;	uint32_t i;	size_t vlen = lwc_string_length(value);	UNUSED(pw); 	*match = false; 	for (i = 0; i < node->n_attrs; i++) {		assert(lwc_string_caseless_isequal(				node->attrs[i].name, qname->name, match) ==				lwc_error_ok);		if (*match == true)			break;	} 	if (*match == true) {		const char *p;		const char *start = lwc_string_data(node->attrs[i].value);		const char *end = start +				lwc_string_length(node->attrs[i].value); 		*match = false; 		for (p = start; p < end; p++) {			if (*p == '-') {				if ((size_t) (p - start) == vlen &&						strncasecmp(start,							lwc_string_data(value),							vlen) == 0) {					*match = true;					break;				} 				start = p + 1;			}		}	} 	return CSS_OK;} static css_error node_has_attribute_prefix(void *pw, void *n,		const css_qname *qname,		lwc_string *value,		bool *match){	node *node = n;	uint32_t i;	UNUSED(pw); 	*match = false; 	for (i = 0; i < node->n_attrs; i++) {		assert(lwc_string_caseless_isequal(				node->attrs[i].name, qname->name, match) ==				lwc_error_ok);		if (*match == true)			break;	} 	if (*match == true) {		size_t len = lwc_string_length(node->attrs[i].value);		const char *data = lwc_string_data(node->attrs[i].value); 		size_t vlen = lwc_string_length(value);		const char *vdata = lwc_string_data(value); 		if (len < vlen)			*match = false;		else			*match = (strncasecmp(data, vdata, vlen) == 0);	} 	return CSS_OK;} static css_error node_has_attribute_suffix(void *pw, void *n,		const css_qname *qname,		lwc_string *value,		bool *match){	node *node = n;	uint32_t i;	UNUSED(pw); 	*match = false; 	for (i = 0; i < node->n_attrs; i++) {		assert(lwc_string_caseless_isequal(				node->attrs[i].name, qname->name, match) ==				lwc_error_ok);		if (*match == true)			break;	} 	if (*match == true) {		size_t len = lwc_string_length(node->attrs[i].value);		const char *data = lwc_string_data(node->attrs[i].value); 		size_t vlen = lwc_string_length(value);		const char *vdata = lwc_string_data(value); 		size_t suffix_start = len - vlen; 

Lines 1–500 of 1578.