From fac6e78e4235414393b828646106071de57f5a51 Mon Sep 17 00:00:00 2001 From: John Mark Bell Date: Thu, 25 Jun 2009 22:59:47 +0000 Subject: List-style shorthand parser svn path=/trunk/libcss/; revision=7994 --- src/parse/properties/generated_list.c | 173 ++++++++++++++++++++++++++++++++++ src/parse/properties/properties.c | 1 + src/parse/properties/properties.h | 3 + 3 files changed, 177 insertions(+) (limited to 'src/parse/properties') diff --git a/src/parse/properties/generated_list.c b/src/parse/properties/generated_list.c index 0ba0618..189aa55 100644 --- a/src/parse/properties/generated_list.c +++ b/src/parse/properties/generated_list.c @@ -5,6 +5,7 @@ * Copyright 2009 John-Mark Bell */ +#include #include #include "bytecode/bytecode.h" @@ -172,6 +173,178 @@ css_error parse_counter_reset(css_language *c, CSS_PROP_COUNTER_RESET, result); } +/** + * Parse list-style + * + * \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 parse_list_style(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result) +{ + int orig_ctx = *ctx; + int prev_ctx; + const css_token *token; + css_style *image = NULL; + css_style *position = NULL; + css_style *type = NULL; + css_style *ret = NULL; + uint32_t required_size; + css_error error; + + /* Firstly, handle inherit */ + token = parserutils_vector_peek(vector, *ctx); + if (token != NULL && token->type == CSS_TOKEN_IDENT && + token->ilower == c->strings[INHERIT]) { + uint32_t *bytecode; + + error = css_stylesheet_style_create(c->sheet, + 3 * sizeof(uint32_t), &ret); + if (error != CSS_OK) { + *ctx = orig_ctx; + return error; + } + + bytecode = (uint32_t *) ret->bytecode; + + *(bytecode++) = buildOPV(CSS_PROP_LIST_STYLE_IMAGE, + FLAG_INHERIT, 0); + *(bytecode++) = buildOPV(CSS_PROP_LIST_STYLE_POSITION, + FLAG_INHERIT, 0); + *(bytecode++) = buildOPV(CSS_PROP_LIST_STYLE_TYPE, + FLAG_INHERIT, 0); + + parserutils_vector_iterate(vector, ctx); + + *result = ret; + + return CSS_OK; + } else if (token == NULL) { + /* No tokens -- clearly garbage */ + *ctx = orig_ctx; + return CSS_INVALID; + } + + /* Attempt to parse the various longhand properties */ + do { + prev_ctx = *ctx; + error = CSS_OK; + + if (image == NULL && (error = parse_list_style_image(c, vector, + ctx, &image)) == CSS_OK) { + } else if (position == NULL && + (error = parse_list_style_position(c, vector, + ctx, &position)) == CSS_OK) { + } else if (type == NULL && + (error = parse_list_style_type(c, vector, ctx, + &type)) == CSS_OK) { + } + + if (error == CSS_OK) { + consumeWhitespace(vector, ctx); + + token = parserutils_vector_peek(vector, *ctx); + } else { + /* Forcibly cause loop to exit */ + token = NULL; + } + } while (*ctx != prev_ctx && token != NULL); + + /* Calculate the required size of the resultant style, + * defaulting the unspecified properties to their initial values */ + required_size = 0; + + if (image) + required_size += image->length; + else + required_size += sizeof(uint32_t); + + if (position) + required_size += position->length; + else + required_size += sizeof(uint32_t); + + if (type) + required_size += type->length; + else + required_size += sizeof(uint32_t); + + /* Create and populate it */ + error = css_stylesheet_style_create(c->sheet, required_size, &ret); + if (error != CSS_OK) + goto cleanup; + + required_size = 0; + + if (image) { + memcpy(((uint8_t *) ret->bytecode) + required_size, + image->bytecode, image->length); + required_size += image->length; + } else { + void *bc = ((uint8_t *) ret->bytecode) + required_size; + + *((uint32_t *) bc) = buildOPV(CSS_PROP_LIST_STYLE_IMAGE, + 0, LIST_STYLE_IMAGE_NONE); + required_size += sizeof(uint32_t); + } + + if (position) { + memcpy(((uint8_t *) ret->bytecode) + required_size, + position->bytecode, position->length); + required_size += position->length; + } else { + void *bc = ((uint8_t *) ret->bytecode) + required_size; + + *((uint32_t *) bc) = buildOPV(CSS_PROP_LIST_STYLE_POSITION, + 0, LIST_STYLE_POSITION_OUTSIDE); + required_size += sizeof(uint32_t); + } + + if (type) { + memcpy(((uint8_t *) ret->bytecode) + required_size, + type->bytecode, type->length); + required_size += type->length; + } else { + void *bc = ((uint8_t *) ret->bytecode) + required_size; + + *((uint32_t *) bc) = buildOPV(CSS_PROP_LIST_STYLE_TYPE, + 0, LIST_STYLE_TYPE_DISC); + required_size += sizeof(uint32_t); + } + + assert(required_size == ret->length); + + /* Write the result */ + *result = ret; + /* Invalidate ret, so that cleanup doesn't destroy it */ + ret = NULL; + + /* Clean up after ourselves */ +cleanup: + if (image) + css_stylesheet_style_destroy(c->sheet, image); + if (position) + css_stylesheet_style_destroy(c->sheet, position); + if (type) + css_stylesheet_style_destroy(c->sheet, type); + if (ret) + css_stylesheet_style_destroy(c->sheet, ret); + + if (error != CSS_OK) + *ctx = orig_ctx; + + return error; +} + /** * Parse list-style-image * diff --git a/src/parse/properties/properties.c b/src/parse/properties/properties.c index 6e7177b..0fd5747 100644 --- a/src/parse/properties/properties.c +++ b/src/parse/properties/properties.c @@ -68,6 +68,7 @@ const css_prop_handler property_handlers[LAST_PROP + 1 - FIRST_PROP] = parse_left, parse_letter_spacing, parse_line_height, + parse_list_style, parse_list_style_image, parse_list_style_position, parse_list_style_type, diff --git a/src/parse/properties/properties.h b/src/parse/properties/properties.h index 9854aed..976766d 100644 --- a/src/parse/properties/properties.h +++ b/src/parse/properties/properties.h @@ -190,6 +190,9 @@ css_error parse_letter_spacing(css_language *c, css_error parse_line_height(css_language *c, const parserutils_vector *vector, int *ctx, css_style **result); +css_error parse_list_style(css_language *c, + const parserutils_vector *vector, int *ctx, + css_style **result); css_error parse_list_style_image(css_language *c, const parserutils_vector *vector, int *ctx, css_style **result); -- cgit v1.2.3