Example #1
0
/**
 * Parse !important
 *
 * \param c       Parsing context
 * \param vector  Vector of tokens to process
 * \param ctx     Pointer to vector iteration context
 * \param result  Pointer to location to receive result
 * \return CSS_OK on success,
 *         CSS_INVALID if "S* ! S* important" is not at the start of the vector
 *
 * Post condition: \a *ctx is updated with the next token to process
 *                 If the input is invalid, then \a *ctx remains unchanged.
 */
css_error css__parse_important(css_language *c,
		const parserutils_vector *vector, int *ctx,
		uint8_t *result)
{
	int orig_ctx = *ctx;
	bool match = false;
	const css_token *token;

	consumeWhitespace(vector, ctx);

	token = parserutils_vector_iterate(vector, ctx);
	if (token != NULL && tokenIsChar(token, '!')) {
		consumeWhitespace(vector, ctx);

		token = parserutils_vector_iterate(vector, ctx);
		if (token == NULL || token->type != CSS_TOKEN_IDENT) {
			*ctx = orig_ctx;
			return CSS_INVALID;
		}

		if (lwc_string_caseless_isequal(token->idata, c->strings[IMPORTANT],
				&match) == lwc_error_ok && match) {
			*result |= FLAG_IMPORTANT;
		} else {
			*ctx = orig_ctx;
			return CSS_INVALID;
		}
	} else if (token != NULL) {
		*ctx = orig_ctx;
		return CSS_INVALID;
	}

	return CSS_OK;
}
Example #2
0
/**
 * Register a handler with the content factory
 *
 * \param mime_type  MIME type to handle
 * \param handler    Content handler for MIME type
 * \return NSERROR_OK on success, appropriate error otherwise
 *
 * \note Latest registration for a MIME type wins
 */
nserror content_factory_register_handler(const char *mime_type,
		const content_handler *handler)
{
	lwc_string *imime_type;
	lwc_error lerror;
	content_handler_entry *entry;
	bool match;

	lerror = lwc_intern_string(mime_type, strlen(mime_type), &imime_type);
	if (lerror != lwc_error_ok)
		return NSERROR_NOMEM;

	for (entry = content_handlers; entry != NULL; entry = entry->next) {
		if (lwc_string_caseless_isequal(imime_type, entry->mime_type,
				&match) == lwc_error_ok && match)
			break;
	}

	if (entry == NULL) {
		entry = malloc(sizeof(content_handler_entry));
		if (entry == NULL)
			return NSERROR_NOMEM;

		entry->next = content_handlers;
		content_handlers = entry;

		entry->mime_type = imime_type;
	} else {
		lwc_string_unref(imime_type);
	}

	entry->handler = handler;

	return NSERROR_OK;
}
Example #3
0
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;
}
Example #4
0
css_error node_classes(void *pw, void *n,
		lwc_string ***classes, uint32_t *n_classes)
{
	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_class, &amatch) ==
				lwc_error_ok);
		if (amatch == true)
			break;
	}

	if (i != node->n_attrs) {
		*classes = realloc(NULL, sizeof(lwc_string **));
		if (*classes == NULL)
			return CSS_NOMEM;

		*(classes[0]) = 
			lwc_string_ref(node->attrs[i].value);
		*n_classes = 1;
	} else {
		*classes = NULL;
		*n_classes = 0;
	}

	return CSS_OK;

}
Example #5
0
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;
}
Example #6
0
css_error node_count_siblings(void *pw, void *n,
		bool same_name, bool after, int32_t *count)
{
	int32_t cnt = 0;
	bool match = false;
	node *node = n;
	lwc_string *name = node->name;
	UNUSED(pw);

	if (after) {
		while (node->next != NULL) {
			if (same_name) {
				assert(lwc_string_caseless_isequal(
					name, node->next->name, &match) ==
					lwc_error_ok);

				if (match)
					cnt++;
			} else {
				cnt++;
			}

			node = node->next;
		}
	} else {
		while (node->prev != NULL) {
			if (same_name) {
				assert(lwc_string_caseless_isequal(
					name, node->prev->name, &match) ==
					lwc_error_ok);

				if (match)
					cnt++;
			} else {
				cnt++;
			}

			node = node->prev;
		}
	}

	*count = cnt;

	return CSS_OK;
}
/**
 * Parse z_index
 *
 * \param c	  Parsing context
 * \param vector  Vector of tokens to process
 * \param ctx	  Pointer to vector iteration context
 * \param result  resulting style
 * \return CSS_OK on success,
 *	   CSS_NOMEM on memory exhaustion,
 *	   CSS_INVALID if the input is not valid
 *
 * Post condition: \a *ctx is updated with the next token to process
 *		   If the input is invalid, then \a *ctx remains unchanged.
 */
css_error css__parse_z_index(css_language *c,
		const parserutils_vector *vector, int *ctx,
		css_style *result)
{
	int orig_ctx = *ctx;
	css_error error;
	const css_token *token;
	bool match;

	token = parserutils_vector_iterate(vector, ctx);
	if ((token == NULL) || ((token->type != CSS_TOKEN_IDENT) && (token->type != CSS_TOKEN_NUMBER))) {
		*ctx = orig_ctx;
		return CSS_INVALID;
	}

	if ((token->type == CSS_TOKEN_IDENT) && (lwc_string_caseless_isequal(token->idata, c->strings[INHERIT], &match) == lwc_error_ok && match)) {
			error = css_stylesheet_style_inherit(result, CSS_PROP_Z_INDEX);
	} else if ((token->type == CSS_TOKEN_IDENT) && (lwc_string_caseless_isequal(token->idata, c->strings[AUTO], &match) == lwc_error_ok && match)) {
			error = css__stylesheet_style_appendOPV(result, CSS_PROP_Z_INDEX, 0,Z_INDEX_AUTO);
	} else if (token->type == CSS_TOKEN_NUMBER) {
		css_fixed num = 0;
		size_t consumed = 0;

		num = css__number_from_lwc_string(token->idata, true, &consumed);
		/* Invalid if there are trailing characters */
		if (consumed != lwc_string_length(token->idata)) {
			*ctx = orig_ctx;
			return CSS_INVALID;
		}
		error = css__stylesheet_style_appendOPV(result, CSS_PROP_Z_INDEX, 0, Z_INDEX_SET);
		if (error != CSS_OK) {
			*ctx = orig_ctx;
			return error;
		}

		error = css__stylesheet_style_append(result, num);
	} else {
		error = CSS_INVALID;
	}

	if (error != CSS_OK)
		*ctx = orig_ctx;
	
	return error;
}
Example #8
0
/**
 * Create a path from a nsurl using amiga file handling.
 *
 * @param[in] url The url to encode.
 * @param[out] path_out A string containing the result path which should
 *                      be freed by the caller.
 * @return NSERROR_OK and the path is written to \a path or error code
 *         on faliure.
 */
static nserror amiga_nsurl_to_path(struct nsurl *url, char **path_out)
{
	lwc_string *urlpath;
	char *path;
	bool match;
	lwc_string *scheme;
	nserror res;
	char *colon;
	char *slash;

	if ((url == NULL) || (path_out == NULL)) {
		return NSERROR_BAD_PARAMETER;
	}

	scheme = nsurl_get_component(url, NSURL_SCHEME);

	if (lwc_string_caseless_isequal(scheme, corestring_lwc_file,
					&match) != lwc_error_ok)
	{
		return NSERROR_BAD_PARAMETER;
	}
	lwc_string_unref(scheme);
	if (match == false) {
		return NSERROR_BAD_PARAMETER;
	}

	urlpath = nsurl_get_component(url, NSURL_PATH);
	if (urlpath == NULL) {
		return NSERROR_BAD_PARAMETER;
	}

	res = url_unescape(lwc_string_data(urlpath) + 1, &path);
	lwc_string_unref(urlpath);
	if (res != NSERROR_OK) {
		return res;
	}

	colon = strchr(path, ':');
	if(colon == NULL)
	{
		slash = strchr(path, '/');
		if(slash)
		{
			*slash = ':';
		}
		else
		{
			int len = strlen(path);
			path[len] = ':';
			path[len + 1] = '\0';
		}
	}

	*path_out = path;

	return NSERROR_OK;
}
/**
 * Parse break_after
 *
 * \param c	  Parsing context
 * \param vector  Vector of tokens to process
 * \param ctx	  Pointer to vector iteration context
 * \param result  resulting style
 * \return CSS_OK on success,
 *	   CSS_NOMEM on memory exhaustion,
 *	   CSS_INVALID if the input is not valid
 *
 * Post condition: \a *ctx is updated with the next token to process
 *		   If the input is invalid, then \a *ctx remains unchanged.
 */
css_error css__parse_break_after(css_language *c,
		const parserutils_vector *vector, int *ctx,
		css_style *result)
{
	int orig_ctx = *ctx;
	css_error error;
	const css_token *token;
	bool match;

	token = parserutils_vector_iterate(vector, ctx);
	if ((token == NULL) || ((token->type != CSS_TOKEN_IDENT))) {
		*ctx = orig_ctx;
		return CSS_INVALID;
	}

	if ((lwc_string_caseless_isequal(token->idata, c->strings[INHERIT], &match) == lwc_error_ok && match)) {
			error = css_stylesheet_style_inherit(result, CSS_PROP_BREAK_AFTER);
	} else if ((lwc_string_caseless_isequal(token->idata, c->strings[AUTO], &match) == lwc_error_ok && match)) {
			error = css__stylesheet_style_appendOPV(result, CSS_PROP_BREAK_AFTER, 0,BREAK_AFTER_AUTO);
	} else if ((lwc_string_caseless_isequal(token->idata, c->strings[ALWAYS], &match) == lwc_error_ok && match)) {
			error = css__stylesheet_style_appendOPV(result, CSS_PROP_BREAK_AFTER, 0,BREAK_AFTER_ALWAYS);
	} else if ((lwc_string_caseless_isequal(token->idata, c->strings[AVOID], &match) == lwc_error_ok && match)) {
			error = css__stylesheet_style_appendOPV(result, CSS_PROP_BREAK_AFTER, 0,BREAK_AFTER_AVOID);
	} else if ((lwc_string_caseless_isequal(token->idata, c->strings[LEFT], &match) == lwc_error_ok && match)) {
			error = css__stylesheet_style_appendOPV(result, CSS_PROP_BREAK_AFTER, 0,BREAK_AFTER_LEFT);
	} else if ((lwc_string_caseless_isequal(token->idata, c->strings[RIGHT], &match) == lwc_error_ok && match)) {
			error = css__stylesheet_style_appendOPV(result, CSS_PROP_BREAK_AFTER, 0,BREAK_AFTER_RIGHT);
	} else if ((lwc_string_caseless_isequal(token->idata, c->strings[PAGE], &match) == lwc_error_ok && match)) {
			error = css__stylesheet_style_appendOPV(result, CSS_PROP_BREAK_AFTER, 0,BREAK_AFTER_PAGE);
	} else if ((lwc_string_caseless_isequal(token->idata, c->strings[COLUMN], &match) == lwc_error_ok && match)) {
			error = css__stylesheet_style_appendOPV(result, CSS_PROP_BREAK_AFTER, 0,BREAK_AFTER_COLUMN);
	} else if ((lwc_string_caseless_isequal(token->idata, c->strings[AVOID_PAGE], &match) == lwc_error_ok && match)) {
			error = css__stylesheet_style_appendOPV(result, CSS_PROP_BREAK_AFTER, 0,BREAK_AFTER_AVOID_PAGE);
	} else if ((lwc_string_caseless_isequal(token->idata, c->strings[AVOID_COLUMN], &match) == lwc_error_ok && match)) {
			error = css__stylesheet_style_appendOPV(result, CSS_PROP_BREAK_AFTER, 0,BREAK_AFTER_AVOID_COLUMN);
	} else {
		error = CSS_INVALID;
	}

	if (error != CSS_OK)
		*ctx = orig_ctx;
	
	return error;
}
Example #10
0
css_error node_has_name(void *pw, void *n,
		const css_qname *qname,
		bool *match)
{
	lwc_string *node = (lwc_string*)n;
	UNUSED(pw);
	assert(lwc_string_caseless_isequal(node, qname->name, match) ==
			lwc_error_ok);
	return CSS_OK;
}
Example #11
0
END_TEST

START_TEST (test_lwc_string_caseless_isequal_bad)
{
    bool result = true;

    fail_unless(lwc_string_caseless_isequal(intern_YAY, intern_one, &result) == lwc_error_ok,
                "Failure comparing 'YAY' and 'one' caselessly");
    fail_unless(result == false,
                "'YAY' ~= 'one' ?!");
}
Example #12
0
/**
 * Parse voice-family
 *
 * \param c	  Parsing context
 * \param vector  Vector of tokens to process
 * \param ctx	  Pointer to vector iteration context
 * \param result  Pointer to location to receive resulting style
 * \return CSS_OK on success,
 *	 CSS_NOMEM on memory exhaustion,
 *	 CSS_INVALID if the input is not valid
 *
 * Post condition: \a *ctx is updated with the next token to process
 *		 If the input is invalid, then \a *ctx remains unchanged.
 */
css_error css__parse_voice_family(css_language *c, 
		const parserutils_vector *vector, int *ctx, 
		css_style *result)
{
	int orig_ctx = *ctx;
	css_error error;
	const css_token *token;
	bool match;

	/* [ IDENT+ | STRING ] [ ',' [ IDENT+ | STRING ] ]* | IDENT(inherit)
	 * 
	 * In the case of IDENT+, any whitespace between tokens is collapsed to
	 * a single space
	 */

	token = parserutils_vector_iterate(vector, ctx);
	if (token == NULL || (token->type != CSS_TOKEN_IDENT &&
			token->type != CSS_TOKEN_STRING)) {
		*ctx = orig_ctx;
		return CSS_INVALID;
	}

	if (token->type == CSS_TOKEN_IDENT &&
			(lwc_string_caseless_isequal(
			token->idata, c->strings[INHERIT],
			&match) == lwc_error_ok && match)) {
		error = css_stylesheet_style_inherit(result, CSS_PROP_VOICE_FAMILY);
	} else {
		*ctx = orig_ctx;

		error = css__comma_list_to_style(c, vector, ctx,
				voice_family_reserved, voice_family_value,
				result);
		if (error != CSS_OK) {
			*ctx = orig_ctx;
			return error;
		}

		error = css__stylesheet_style_append(result, VOICE_FAMILY_END);
	}

	if (error != CSS_OK) {
		*ctx = orig_ctx;
		return error;
	}

	return CSS_OK;
}
Example #13
0
/* exported interface documented in content/content.h */
struct content_rfc5988_link *
content_find_rfc5988_link(hlcache_handle *h, lwc_string *rel)
{
	struct content *c = hlcache_handle_get_content(h);
	struct content_rfc5988_link *link = c->links;
	bool rel_match = false;

	while (link != NULL) {
		if (lwc_string_caseless_isequal(link->rel, rel,
				&rel_match) == lwc_error_ok && rel_match) {
			break;
		}
		link = link->next;
	}
	return link;
}
Example #14
0
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;
}
Example #15
0
css_error gui_system_colour(void *pw, lwc_string *name, css_color *colour)
{
	unsigned int ccount;
	bool match;

	for (ccount = 0; ccount < colour_list_len; ccount++) {
		if (lwc_string_caseless_isequal(name,
				colour_list[ccount].lwcstr,
				&match) == lwc_error_ok && match) {
			*colour = colour_list[ccount].colour;
			return CSS_OK;
		}
	}

	return CSS_INVALID;
}
Example #16
0
css_error node_has_attribute_substring(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);

		const char *last_start = data + len - vlen;

		if (len < vlen)
			*match = false;
		else {
			while (data <= last_start) {
				if (strncasecmp(data, vdata, vlen) == 0) {
					*match = true;
					break;
				}

				data++;
			}

			if (data > last_start)
				*match = false;
		}
	}

	return CSS_OK;
}
Example #17
0
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;
}
Example #18
0
/**
 * Find a handler for a MIME type.
 *
 * \param mime_type  MIME type to search for
 * \return Associated handler, or NULL if none
 */
static const content_handler *content_lookup(lwc_string *mime_type)
{
	content_handler_entry *entry;
	bool match;

	for (entry = content_handlers; entry != NULL; entry = entry->next) {
		if (lwc_string_caseless_isequal(mime_type, entry->mime_type,
					&match) == lwc_error_ok && match) {
			break;
		}
	}

	if (entry != NULL) {
		return entry->handler;
	}

	return NULL;
}
Example #19
0
/**
 * Case insensitively compare two DOM strings
 *
 * \param s1  The first string to compare
 * \param s2  The second string to compare
 * \return true if strings match, false otherwise
 */
bool dom_string_caseless_isequal(const dom_string *s1, const dom_string *s2)
{
	const uint8_t *d1 = NULL;
	const uint8_t *d2 = NULL;
	size_t len;
	const dom_string_internal *is1 = (dom_string_internal *) s1;
	const dom_string_internal *is2 = (dom_string_internal *) s2;

	if (s1 == NULL)
		is1 = &empty_string;

	if (s2 == NULL)
		is2 = &empty_string;

	if (is1->type == DOM_STRING_INTERNED && 
			is2->type == DOM_STRING_INTERNED) {
		bool match;

		if (lwc_string_caseless_isequal(is1->data.intern,
				is2->data.intern, &match) != lwc_error_ok)
			return false;

		return match;
	}

	len = dom_string_byte_length((dom_string *) is1);

	if (len != dom_string_byte_length((dom_string *)is2))
		return false;

	d1 = (const uint8_t *) dom_string_data((dom_string *) is1);
	d2 = (const uint8_t *) dom_string_data((dom_string *)is2);

	while (len > 0) {
		if (dolower(*d1) != dolower(*d2))
			return false;

		d1++;
		d2++;
		len--;
	}

	return true;
}
Example #20
0
END_TEST

START_TEST (test_lwc_string_caseless_isequal_ok1)
{
    bool result = true;
    lwc_string *new_ONE;

    fail_unless(lwc_intern_string("ONE", 3, &new_ONE) == lwc_error_ok,
                "Failure interning 'ONE'");

    fail_unless((lwc_string_isequal(intern_one, new_ONE, &result)) == lwc_error_ok);
    fail_unless(result == false,
                "'one' == 'ONE' ?!");

    fail_unless((lwc_string_caseless_isequal(intern_one, new_ONE, &result)) == lwc_error_ok,
                "Failure comparing 'one' and 'ONE' caselessly");
    fail_unless(result == true,
                "'one' !~= 'ONE' ?!");
}
Example #21
0
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;
}
Example #22
0
END_TEST

START_TEST (test_lwc_string_caseless_isequal_ok2)
{
    bool result = true;
    lwc_string *new_yay;

    fail_unless(lwc_intern_string("yay", 3, &new_yay) == lwc_error_ok,
                "Failure interning 'yay'");

    fail_unless((lwc_string_isequal(intern_YAY, new_yay, &result)) == lwc_error_ok);
    fail_unless(result == false,
                "'yay' == 'YAY' ?!");

    fail_unless((lwc_string_caseless_isequal(intern_YAY, new_yay, &result)) == lwc_error_ok,
                "Failure comparing 'yay' and 'YAY' caselessly");
    fail_unless(result == true,
                "'yay' !~= 'YAY' ?!");
}
Example #23
0
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;
}
Example #24
0
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;
}
Example #25
0
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;
}
Example #26
0
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;
}
Example #27
0
/**
 * Parse list-style-type
 *
 * \param c	  Parsing context
 * \param vector  Vector of tokens to process
 * \param ctx	  Pointer to vector iteration context
 * \param result  Pointer to location to receive resulting style
 * \return CSS_OK on success,
 *	   CSS_NOMEM on memory exhaustion,
 *	   CSS_INVALID if the input is not valid
 *
 * Post condition: \a *ctx is updated with the next token to process
 *		   If the input is invalid, then \a *ctx remains unchanged.
 */
css_error css__parse_list_style_type(css_language *c, 
		const parserutils_vector *vector, int *ctx, 
		css_style *result)
{
	int orig_ctx = *ctx;
	css_error error;
	const css_token *ident;
	uint8_t flags = 0;
	uint16_t value = 0;
	bool match;

	/* IDENT (disc, circle, square, decimal, decimal-leading-zero,
	 *	  lower-roman, upper-roman, lower-greek, lower-latin,
	 *	  upper-latin, armenian, georgian, lower-alpha, upper-alpha,
	 *	  none, inherit)
	 */
	ident = parserutils_vector_iterate(vector, ctx);
	if (ident == NULL || ident->type != CSS_TOKEN_IDENT) {
		*ctx = orig_ctx;
		return CSS_INVALID;
	}

	if ((lwc_string_caseless_isequal(
			ident->idata, c->strings[INHERIT],
			&match) == lwc_error_ok && match)) {
		flags |= FLAG_INHERIT;
	} else {
		error = css__parse_list_style_type_value(c, ident, &value);
		if (error != CSS_OK) {
			*ctx = orig_ctx;
			return error;
		}
	}

	error = css__stylesheet_style_appendOPV(result, CSS_PROP_LIST_STYLE_TYPE, flags, value);

	if (error != CSS_OK) 
		*ctx = orig_ctx;
	
	return error;
}
Example #28
0
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;
}
Example #29
0
/**
 * Parse content
 *
 * \param c	  Parsing context
 * \param vector  Vector of tokens to process
 * \param ctx	  Pointer to vector iteration context
 * \param result  Pointer to location to receive resulting style
 * \return CSS_OK on success,
 *	   CSS_NOMEM on memory exhaustion,
 *	   CSS_INVALID if the input is not valid
 *
 * Post condition: \a *ctx is updated with the next token to process
 *		   If the input is invalid, then \a *ctx remains unchanged.
 */
css_error css__parse_content(css_language *c,
		const parserutils_vector *vector, int *ctx,
		css_style *result)
{
	int orig_ctx = *ctx;
	css_error error;
	const css_token *token;
	bool match;

	/* IDENT(normal, none, inherit) | [ ... ]+ */
	token = parserutils_vector_iterate(vector, ctx);
	if (token == NULL) {
		*ctx = orig_ctx;
		return CSS_INVALID;
	}


	if ((token->type == CSS_TOKEN_IDENT) &&
	    (lwc_string_caseless_isequal(token->idata,
					 c->strings[INHERIT],
					 &match) == lwc_error_ok && match)) {
		error = css_stylesheet_style_inherit(result, CSS_PROP_CONTENT);
	} else if ((token->type == CSS_TOKEN_IDENT) &&
		   (lwc_string_caseless_isequal(token->idata,
						c->strings[NORMAL],
						&match) == lwc_error_ok && match)) {
		error = css__stylesheet_style_appendOPV(result, CSS_PROP_CONTENT, 0, CONTENT_NORMAL);
	} else if ((token->type == CSS_TOKEN_IDENT) &&
		   (lwc_string_caseless_isequal(token->idata,
						c->strings[NONE],
						&match) == lwc_error_ok && match)) {
		error = css__stylesheet_style_appendOPV(result, CSS_PROP_CONTENT, 0, CONTENT_NONE);
	} else {

/* Macro to output the value marker, awkward because we need to check
 * first to determine how the value is constructed.
 */
#define CSS_APPEND(CSSVAL) css__stylesheet_style_append(result, first?buildOPV(CSS_PROP_CONTENT, 0, CSSVAL):CSSVAL)

		bool first = true;
		int prev_ctx = orig_ctx;

		/* [
		 *   IDENT(open-quote, close-quote, no-open-quote,
		 *         no-close-quote) |
		 *   STRING |
		 *   URI |
		 *   FUNCTION(attr) IDENT ')' |
		 *   FUNCTION(counter) IDENT IDENT? ')' |
		 *   FUNCTION(counters) IDENT STRING IDENT? ')'
		 * ]+
		 */

		while (token != NULL) {
			if ((token->type == CSS_TOKEN_IDENT) &&
			    (lwc_string_caseless_isequal(
				    token->idata, c->strings[OPEN_QUOTE],
				    &match) == lwc_error_ok && match)) {

				error = CSS_APPEND(CONTENT_OPEN_QUOTE);

			} else if (token->type == CSS_TOKEN_IDENT &&
				   (lwc_string_caseless_isequal(
					   token->idata, c->strings[CLOSE_QUOTE],
					   &match) == lwc_error_ok && match)) {

				error = CSS_APPEND(CONTENT_CLOSE_QUOTE);
			} else if (token->type == CSS_TOKEN_IDENT &&
				   (lwc_string_caseless_isequal(
					   token->idata, c->strings[NO_OPEN_QUOTE],
					   &match) == lwc_error_ok && match)) {
				error = CSS_APPEND(CONTENT_NO_OPEN_QUOTE);
			} else if (token->type == CSS_TOKEN_IDENT &&
				   (lwc_string_caseless_isequal(
					   token->idata, c->strings[NO_CLOSE_QUOTE],
					   &match) == lwc_error_ok && match)) {
				error = CSS_APPEND(CONTENT_NO_CLOSE_QUOTE);
			} else if (token->type == CSS_TOKEN_STRING) {
				uint32_t snumber;

				error = css__stylesheet_string_add(c->sheet, lwc_string_ref(token->idata), &snumber);
				if (error != CSS_OK) {
					*ctx = orig_ctx;
					return error;
				}

				error = CSS_APPEND(CONTENT_STRING);
				if (error != CSS_OK) {
					*ctx = orig_ctx;
					return error;
				}

				error = css__stylesheet_style_append(result, snumber);
			} else if (token->type == CSS_TOKEN_URI) {
				lwc_string *uri;
				uint32_t uri_snumber;

				error = c->sheet->resolve(c->sheet->resolve_pw,
							  c->sheet->url,
							  token->idata, 
							  &uri);
				if (error != CSS_OK) {
					*ctx = orig_ctx;
					return error;
				}

				error = css__stylesheet_string_add(c->sheet, 
								  uri, 
								  &uri_snumber);
				if (error != CSS_OK) {
					*ctx = orig_ctx;
					return error;
				}

				error = CSS_APPEND(CONTENT_URI);
				if (error != CSS_OK) {
					*ctx = orig_ctx;
					return error;
				}

				error = css__stylesheet_style_append(result, uri_snumber);
			} else if (token->type == CSS_TOKEN_FUNCTION &&
				   (lwc_string_caseless_isequal(
					   token->idata, c->strings[ATTR],
					   &match) == lwc_error_ok && match)) {
				uint32_t snumber;

				consumeWhitespace(vector, ctx);

				/* Expect IDENT */
				token = parserutils_vector_iterate(vector, ctx);
				if (token == NULL || token->type != CSS_TOKEN_IDENT) {
					*ctx = orig_ctx;
					return CSS_INVALID;
				}

				error = css__stylesheet_string_add(c->sheet, lwc_string_ref(token->idata), &snumber);
				if (error != CSS_OK) {
					*ctx = orig_ctx;
					return error;
				}

				error = CSS_APPEND(CONTENT_ATTR);
				if (error != CSS_OK) {
					*ctx = orig_ctx;
					return error;
				}

				error = css__stylesheet_style_append(result, snumber);

				consumeWhitespace(vector, ctx);

				/* Expect ')' */
				token = parserutils_vector_iterate(vector, ctx);
				if (token == NULL || tokenIsChar(token, ')') == false) {
					*ctx = orig_ctx;
					return CSS_INVALID;
				}
			} else if (token->type == CSS_TOKEN_FUNCTION &&
				   (lwc_string_caseless_isequal(
					   token->idata, c->strings[COUNTER],
					   &match) == lwc_error_ok && match)) {
				lwc_string *name;
				uint32_t snumber;
				uint32_t opv;

				opv = CONTENT_COUNTER;

				consumeWhitespace(vector, ctx);

				/* Expect IDENT */
				token = parserutils_vector_iterate(vector, ctx);
				if (token == NULL || token->type != CSS_TOKEN_IDENT) {
					*ctx = orig_ctx;
					return CSS_INVALID;
				}

				name = token->idata;

				consumeWhitespace(vector, ctx);

				/* Possible ',' */
				token = parserutils_vector_peek(vector, *ctx);
				if (token == NULL ||
				    (tokenIsChar(token, ',') == false &&
				     tokenIsChar(token, ')') == false)) {
					*ctx = orig_ctx;
					return CSS_INVALID;
				}

				if (tokenIsChar(token, ',')) {
					uint16_t v;

					parserutils_vector_iterate(vector, ctx);

					consumeWhitespace(vector, ctx);

					/* Expect IDENT */
					token = parserutils_vector_peek(vector, *ctx);
					if (token == NULL || token->type !=
					    CSS_TOKEN_IDENT) {
						*ctx = orig_ctx;
						return CSS_INVALID;
					}

					error = css__parse_list_style_type_value(c, token, &v);
					if (error != CSS_OK) {
						*ctx = orig_ctx;
						return error;
					}

					opv |= v << CONTENT_COUNTER_STYLE_SHIFT;

					parserutils_vector_iterate(vector, ctx);

					consumeWhitespace(vector, ctx);
				} else {
					opv |= LIST_STYLE_TYPE_DECIMAL <<
						CONTENT_COUNTER_STYLE_SHIFT;
				}

				/* Expect ')' */
				token = parserutils_vector_iterate(vector, ctx);
				if (token == NULL || tokenIsChar(token,	')') == false) {
					*ctx = orig_ctx;
					return CSS_INVALID;
				}


				error = css__stylesheet_string_add(c->sheet, lwc_string_ref(name), &snumber);
				if (error != CSS_OK) {
					*ctx = orig_ctx;
					return error;
				}

				error = CSS_APPEND(opv);
				if (error != CSS_OK) {
					*ctx = orig_ctx;
					return error;
				}

				error = css__stylesheet_style_append(result, snumber);
			} else if (token->type == CSS_TOKEN_FUNCTION &&
				   (lwc_string_caseless_isequal(
					   token->idata, c->strings[COUNTERS],
					   &match) == lwc_error_ok && match)) {
				lwc_string *name;
				lwc_string *sep;
				uint32_t name_snumber;
				uint32_t sep_snumber;
				uint32_t opv;

				opv = CONTENT_COUNTERS;

				consumeWhitespace(vector, ctx);

				/* Expect IDENT */
				token = parserutils_vector_iterate(vector, ctx);
				if (token == NULL || token->type != CSS_TOKEN_IDENT) {
					*ctx = orig_ctx;
					return CSS_INVALID;
				}

				name = token->idata;

				consumeWhitespace(vector, ctx);

				/* Expect ',' */
				token = parserutils_vector_iterate(vector, ctx);
				if (token == NULL || tokenIsChar(token, ',') == false) {
					*ctx = orig_ctx;
					return CSS_INVALID;
				}

				consumeWhitespace(vector, ctx);

				/* Expect STRING */
				token = parserutils_vector_iterate(vector, ctx);
				if (token == NULL || token->type != CSS_TOKEN_STRING) {
					*ctx = orig_ctx;
					return CSS_INVALID;
				}

				sep = token->idata;

				consumeWhitespace(vector, ctx);

				/* Possible ',' */
				token = parserutils_vector_peek(vector, *ctx);
				if (token == NULL ||
				    (tokenIsChar(token, ',') == false &&
				     tokenIsChar(token, ')') == false)) {
					*ctx = orig_ctx;
					return CSS_INVALID;
				}

				if (tokenIsChar(token, ',')) {
					uint16_t v;

					parserutils_vector_iterate(vector, ctx);

					consumeWhitespace(vector, ctx);

					/* Expect IDENT */
					token = parserutils_vector_peek(vector, *ctx);
					if (token == NULL || token->type !=
					    CSS_TOKEN_IDENT) {
						*ctx = orig_ctx;
						return CSS_INVALID;
					}

					error = css__parse_list_style_type_value(c,
									    token, &v);
					if (error != CSS_OK) {
						*ctx = orig_ctx;
						return error;
					}

					opv |= v << CONTENT_COUNTERS_STYLE_SHIFT;

					parserutils_vector_iterate(vector, ctx);

					consumeWhitespace(vector, ctx);
				} else {
					opv |= LIST_STYLE_TYPE_DECIMAL <<
						CONTENT_COUNTERS_STYLE_SHIFT;
				}

				/* Expect ')' */
				token = parserutils_vector_iterate(vector, ctx);
				if (token == NULL || tokenIsChar(token, ')') == false) {
					*ctx = orig_ctx;
					return CSS_INVALID;
				}


				error = css__stylesheet_string_add(c->sheet, lwc_string_ref(name), &name_snumber);
				if (error != CSS_OK) {
					*ctx = orig_ctx;
					return error;
				}

				error = css__stylesheet_string_add(c->sheet, lwc_string_ref(sep), &sep_snumber);
				if (error != CSS_OK) {
					*ctx = orig_ctx;
					return error;
				}

				error = CSS_APPEND(opv);
				if (error != CSS_OK) {
					*ctx = orig_ctx;
					return error;
				}

				error = css__stylesheet_style_append(result, name_snumber);
				if (error != CSS_OK) {
					*ctx = orig_ctx;
					return error;
				}

				error = css__stylesheet_style_append(result, sep_snumber);
			} else if (first) {
				/* Invalid if this is the first iteration */
				error = CSS_INVALID;
			} else {
				/* Give up, ensuring current token is reprocessed */
				*ctx = prev_ctx;
				error = CSS_OK;
				break;
			}

			/* if there was an error bail */
			if (error != CSS_OK) {
				*ctx = orig_ctx;
				return error;
			}

			first = false;

			consumeWhitespace(vector, ctx);

			prev_ctx = *ctx;
			token = parserutils_vector_iterate(vector, ctx);
		} /* while */

		/* Write list terminator */
		css__stylesheet_style_append(result, CONTENT_NORMAL);
	}

	if (error != CSS_OK)
		*ctx = orig_ctx;

	return error;
}
Example #30
0
void css__parse_tree_data(line_ctx *ctx, const char *data, size_t len)
{
	const char *p = data;
	const char *end = data + len;
	const char *name = NULL;
	const char *value = NULL;
	size_t namelen = 0;
	size_t valuelen = 0;
	uint32_t depth = 0;
	bool target = false;

	/* ' '{depth+1} [ <element> '*'? | <attr> ]
	 * 
	 * <element> ::= [^=*[:space:]]+
	 * <attr>    ::= [^=*[:space:]]+ '=' [^[:space:]]*
	 */

	while (p < end && isspace(*p)) {
		depth++;
		p++;
	}
	depth--;

	/* Get element/attribute name */
	name = p;
	while (p < end && *p != '=' && *p != '*' && isspace(*p) == false) {
		namelen++;
		p++;
	}

	/* Skip whitespace */
	while (p < end && isspace(*p))
		p++;

	if (p < end && *p == '=') {
		/* Attribute value */
		p++;

		value = p;

		while (p < end && isspace(*p) == false) {
			valuelen++;
			p++;
		}
	} else if (p < end && *p == '*') {
		/* Element is target node */
		target = true;
	}

	if (value == NULL) {
		/* We have an element, so create it */
		node *n = malloc(sizeof(node));
		assert(n != NULL);

		memset(n, 0, sizeof(node));
		
		lwc_intern_string(name, namelen, &n->name);

		/* Insert it into tree */
		if (ctx->tree == NULL) {
			ctx->tree = n;
		} else {
			assert(depth > 0);
			assert(depth <= ctx->depth + 1);

			/* Find node to insert into */
			while (depth <= ctx->depth) {
				ctx->depth--;
				ctx->current = ctx->current->parent;
			}

			/* Insert into current node */
			if (ctx->current->children == NULL) {
				ctx->current->children = n;
				ctx->current->last_child = n;
			} else {
				ctx->current->last_child->next = n;
				n->prev = ctx->current->last_child;

				ctx->current->last_child = n;
			}
			n->parent = ctx->current;
		}

		ctx->current = n;
		ctx->depth = depth;

		/* Mark the target, if it's us */
		if (target)
			ctx->target = n;
	} else {
		/* New attribute */
		bool amatch = false;
		attribute *attr;
		node *n = ctx->current;

		attribute *temp = realloc(n->attrs,
				(n->n_attrs + 1) * sizeof(attribute));
		assert(temp != NULL);

		n->attrs = temp;

		attr = &n->attrs[n->n_attrs];
		
		lwc_intern_string(name, namelen, &attr->name);
		lwc_intern_string(value, valuelen, &attr->value);

		assert(lwc_string_caseless_isequal(
				n->attrs[n->n_attrs].name,
				ctx->attr_class, &amatch) == lwc_error_ok);
		if (amatch == true) {
			n->classes = realloc(NULL, sizeof(lwc_string **));
			assert(n->classes != NULL);

			n->classes[0] = lwc_string_ref(
					n->attrs[n->n_attrs].
					value);
			n->n_classes = 1;
		}

		n->n_attrs++;
	}
}