summaryrefslogtreecommitdiff
path: root/src/parse/parse.c
diff options
context:
space:
mode:
authorJohn Mark Bell <jmb@netsurf-browser.org>2008-11-27 12:14:07 +0000
committerJohn Mark Bell <jmb@netsurf-browser.org>2008-11-27 12:14:07 +0000
commit7adaf92154adc7f3455769ca197f906e3d4cddaa (patch)
treeae172720c8e44a35b87b5506602768db19ec538f /src/parse/parse.c
parent79c0f3bc5c1581a6f2f6568a50e3b4f64b452541 (diff)
downloadlibcss-7adaf92154adc7f3455769ca197f906e3d4cddaa.tar.gz
libcss-7adaf92154adc7f3455769ca197f906e3d4cddaa.tar.bz2
css_string is now the same as a parserutils_dict_entry. This allows us to use dict entries directly as strings.
iChange the way in which selectors are represented. This significantly reduces memory requirements -- reducing the approximate usage count (excludes the string dictionary, which is about 360k) of allzengarden.css from 4,535,400 bytes to 2,414,312 bytes on a 64bit platform. The string dictionary is now created and owned by the stylesheet object. The parser is just given access to this so that it can store strings in it. svn path=/trunk/libcss/; revision=5809
Diffstat (limited to 'src/parse/parse.c')
-rw-r--r--src/parse/parse.c186
1 files changed, 88 insertions, 98 deletions
diff --git a/src/parse/parse.c b/src/parse/parse.c
index f12ffe5..f461302 100644
--- a/src/parse/parse.c
+++ b/src/parse/parse.c
@@ -174,17 +174,19 @@ static css_error (*parseFuncs[])(css_parser *parser) = {
/**
* Create a CSS parser
*
- * \param charset Charset of data, if known, or NULL
- * \param cs_source Source of charset information, or CSS_CHARSET_DEFAULT
- * \param alloc Memory (de)allocation function
- * \param pw Pointer to client-specific private data
- * \param parser Pointer to location to receive parser instance
+ * \param charset Charset of data, if known, or NULL
+ * \param cs_source Source of charset information, or CSS_CHARSET_DEFAULT
+ * \param dictionary Dictionary in which to intern strings (not copied)
+ * \param alloc Memory (de)allocation function
+ * \param pw Pointer to client-specific private data
+ * \param parser Pointer to location to receive parser instance
* \return CSS_OK on success,
* CSS_BADPARM on bad parameters,
* CSS_NOMEM on memory exhaustion
*/
css_error css_parser_create(const char *charset, css_charset_source cs_source,
- css_alloc alloc, void *pw, css_parser **parser)
+ parserutils_dict *dictionary, css_alloc alloc, void *pw,
+ css_parser **parser)
{
css_parser *p;
parser_state initial = { sStart, 0 };
@@ -223,21 +225,12 @@ css_error css_parser_create(const char *charset, css_charset_source cs_source,
return css_error_from_parserutils_error(perror);
}
- perror = parserutils_dict_create((parserutils_alloc) alloc, pw,
- &p->dictionary);
- if (perror != PARSERUTILS_OK) {
- parserutils_stack_destroy(p->states);
- css_lexer_destroy(p->lexer);
- parserutils_inputstream_destroy(p->stream);
- alloc(p, 0, pw);
- return css_error_from_parserutils_error(perror);
- }
+ p->dictionary = dictionary;
perror = parserutils_vector_create(sizeof(css_token),
STACK_CHUNK, (parserutils_alloc) alloc, pw,
&p->tokens);
if (perror != PARSERUTILS_OK) {
- parserutils_dict_destroy(p->dictionary);
parserutils_stack_destroy(p->states);
css_lexer_destroy(p->lexer);
parserutils_inputstream_destroy(p->stream);
@@ -261,7 +254,6 @@ css_error css_parser_create(const char *charset, css_charset_source cs_source,
if (perror != PARSERUTILS_OK) {
parserutils_stack_destroy(p->open_items);
parserutils_vector_destroy(p->tokens);
- parserutils_dict_destroy(p->dictionary);
parserutils_stack_destroy(p->states);
css_lexer_destroy(p->lexer);
parserutils_inputstream_destroy(p->stream);
@@ -298,8 +290,6 @@ css_error css_parser_destroy(css_parser *parser)
parserutils_vector_destroy(parser->tokens);
- parserutils_dict_destroy(parser->dictionary);
-
parserutils_stack_destroy(parser->states);
css_lexer_destroy(parser->lexer);
@@ -423,20 +413,20 @@ const char *css_parser_read_charset(css_parser *parser,
* Add an entry to the parser dictionary
*
* \param parser The parser instance
- * \param ptr Pointer to data
+ * \param data Pointer to data
* \param len Length, in bytes, of data
* \return Pointer to data in dictionary, or NULL on memory exhaustion
*/
-const uint8_t *css_parser_dict_add(css_parser *parser, const uint8_t *ptr,
+const uint8_t *css_parser_dict_add(css_parser *parser, const uint8_t *data,
size_t len)
{
const parserutils_dict_entry *interned;
parserutils_error perror;
- if (parser == NULL || ptr == NULL || len == 0)
+ if (parser == NULL || data == NULL || len == 0)
return NULL;
- perror = parserutils_dict_insert(parser->dictionary, ptr, len,
+ perror = parserutils_dict_insert(parser->dictionary, data, len,
&interned);
if (perror != PARSERUTILS_OK)
return NULL;
@@ -580,7 +570,7 @@ css_error getToken(css_parser *parser, const css_token **token)
return error;
if (t->type != CSS_TOKEN_S &&
- t->data.ptr != NULL && t->data.len > 0) {
+ t->data.data != NULL && t->data.len > 0) {
/* Insert token text into the dictionary */
const parserutils_dict_entry *interned;
uint8_t temp[t->data.len];
@@ -592,8 +582,8 @@ css_error getToken(css_parser *parser, const css_token **token)
case CSS_TOKEN_HASH:
case CSS_TOKEN_FUNCTION:
for (size_t i = 0; i < t->data.len; i++) {
- temp[i] = tolower(t->data.ptr[i]);
- if (temp[i] != t->data.ptr[i])
+ temp[i] = tolower(t->data.data[i]);
+ if (temp[i] != t->data.data[i])
lower = true;
}
break;
@@ -614,30 +604,30 @@ css_error getToken(css_parser *parser, const css_token **token)
perror);
}
- t->lower.ptr = interned->data;
+ t->lower.data = interned->data;
t->lower.len = interned->len;
perror = parserutils_dict_insert(
parser->dictionary,
- t->data.ptr, t->data.len,
+ t->data.data, t->data.len,
&interned);
} else {
/* Otherwise, we're not interested in case */
perror = parserutils_dict_insert(
parser->dictionary,
- t->data.ptr, t->data.len,
+ t->data.data, t->data.len,
&interned);
- t->lower.ptr = interned->data;
+ t->lower.data = interned->data;
t->lower.len = interned->len;
}
if (perror != PARSERUTILS_OK)
return css_error_from_parserutils_error(perror);
- t->data.ptr = interned->data;
+ t->data.data = interned->data;
t->data.len = interned->len;
} else if (t->type == CSS_TOKEN_S) {
- t->data.ptr = t->lower.ptr = NULL;
+ t->data.data = t->lower.data = NULL;
t->data.len = t->lower.len = 0;
}
@@ -863,7 +853,7 @@ css_error parseRuleset(css_parser *parser)
* brace. We're going to assume that that won't happen,
* however. */
if (token->type == CSS_TOKEN_CHAR && token->lower.len == 1 &&
- token->lower.ptr[0] == '{') {
+ token->lower.data[0] == '{') {
#if !defined(NDEBUG) && defined(DEBUG_EVENTS)
printf("Begin ruleset\n");
#endif
@@ -914,7 +904,7 @@ css_error parseRuleset(css_parser *parser)
return error;
if (token->type != CSS_TOKEN_CHAR || token->lower.len != 1 ||
- token->lower.ptr[0] != '{') {
+ token->lower.data[0] != '{') {
/* This should never happen, as FOLLOW(selector)
* contains only '{' */
assert(0 && "Expected {");
@@ -979,7 +969,7 @@ css_error parseRulesetEnd(css_parser *parser)
return error;
if (token->type != CSS_TOKEN_CHAR || token->lower.len != 1 ||
- token->lower.ptr[0] != '}') {
+ token->lower.data[0] != '}') {
/* This should never happen, as FOLLOW(decl-list)
* contains only '}' */
assert(0 && "Expected }");
@@ -1054,8 +1044,8 @@ css_error parseAtRule(css_parser *parser)
/* Grammar ambiguity: any0 can be followed by '{',';',')',']'.
* at-rule can only be followed by '{' and ';'. */
if (token->type == CSS_TOKEN_CHAR && token->lower.len == 1) {
- if (token->lower.ptr[0] == ')' ||
- token->lower.ptr[0] == ']') {
+ if (token->lower.data[0] == ')' ||
+ token->lower.data[0] == ']') {
parser_state to = { sAny0, Initial };
parser_state subsequent = { sAtRule, AfterAny };
@@ -1111,7 +1101,7 @@ css_error parseAtRuleEnd(css_parser *parser)
assert(0 && "Expected { or ;");
}
- if (token->lower.ptr[0] == '{') {
+ if (token->lower.data[0] == '{') {
parser_state to = { sBlock, Initial };
parser_state subsequent = { sAtRuleEnd, AfterBlock };
@@ -1120,7 +1110,7 @@ css_error parseAtRuleEnd(css_parser *parser)
return error;
return transition(parser, to, subsequent);
- } else if (token->lower.ptr[0] != ';') {
+ } else if (token->lower.data[0] != ';') {
/* Again, should never happen */
assert(0 && "Expected ;");
}
@@ -1173,7 +1163,7 @@ css_error parseBlock(css_parser *parser)
parserutils_vector_clear(parser->tokens);
if (token->type != CSS_TOKEN_CHAR || token->lower.len != 1 ||
- token->lower.ptr[0] != '{') {
+ token->lower.data[0] != '{') {
/* This should never happen, as FIRST(block) == '{' */
assert(0 && "Expected {");
}
@@ -1200,7 +1190,7 @@ css_error parseBlock(css_parser *parser)
return error;
if (token->type != CSS_TOKEN_CHAR || token->lower.len != 1 ||
- token->lower.ptr[0] != '}') {
+ token->lower.data[0] != '}') {
/* This should never happen, as
* FOLLOW(block-content) == '}' */
assert(0 && "Expected }");
@@ -1253,7 +1243,7 @@ css_error parseBlockContent(css_parser *parser)
state->substate = WS;
} else if (token->type == CSS_TOKEN_CHAR) {
if (token->lower.len == 1 &&
- token->lower.ptr[0] == '{') {
+ token->lower.data[0] == '{') {
/* Grammar ambiguity. Assume block */
parser_state to = { sBlock, Initial };
parser_state subsequent =
@@ -1277,11 +1267,11 @@ css_error parseBlockContent(css_parser *parser)
return transition(parser, to,
subsequent);
} else if (token->lower.len == 1 &&
- token->lower.ptr[0] == ';') {
+ token->lower.data[0] == ';') {
/* Grammar ambiguity. Assume semi */
state->substate = WS;
} else if (token->lower.len == 1 &&
- token->lower.ptr[0] == '}') {
+ token->lower.data[0] == '}') {
/* Grammar ambiguity. Assume end */
error = pushBack(parser, token);
if (error != CSS_OK)
@@ -1390,7 +1380,7 @@ css_error parseDeclaration(css_parser *parser)
return error;
if (token->type != CSS_TOKEN_CHAR || token->lower.len != 1 ||
- token->lower.ptr[0] != ':') {
+ token->lower.data[0] != ':') {
/* parse error -- expected : */
parser_state to = { sMalformedDecl, Initial };
@@ -1458,13 +1448,13 @@ css_error parseDeclList(css_parser *parser)
assert(0 && "Expected ; or }");
}
- if (token->lower.ptr[0] == '}') {
+ if (token->lower.data[0] == '}') {
error = pushBack(parser, token);
if (error != CSS_OK)
return error;
return done(parser);
- } else if (token->lower.ptr[0] == ';') {
+ } else if (token->lower.data[0] == ';') {
state->substate = WS;
} else {
/* Should never happen */
@@ -1504,8 +1494,8 @@ css_error parseDeclListEnd(css_parser *parser)
if (token->type != CSS_TOKEN_CHAR ||
token->lower.len != 1 ||
- (token->lower.ptr[0] != ';' &&
- token->lower.ptr[0] != '}')) {
+ (token->lower.data[0] != ';' &&
+ token->lower.data[0] != '}')) {
parser_state to = { sDeclaration, Initial };
parser_state subsequent =
{ sDeclListEnd, AfterDeclaration };
@@ -1593,8 +1583,8 @@ css_error parseValue1(css_parser *parser)
/* Grammar ambiguity -- assume ';' or '}' mark end */
if (token->type == CSS_TOKEN_CHAR &&
token->lower.len == 1 &&
- (token->lower.ptr[0] == ';' ||
- token->lower.ptr[0] == '}')) {
+ (token->lower.data[0] == ';' ||
+ token->lower.data[0] == '}')) {
/* Parse error */
parser->parseError = true;
@@ -1641,8 +1631,8 @@ css_error parseValue0(css_parser *parser)
/* Grammar ambiguity -- assume ';' or '}' mark end */
if (token->type == CSS_TOKEN_CHAR &&
token->lower.len == 1 &&
- (token->lower.ptr[0] == ';' ||
- token->lower.ptr[0] == '}')) {
+ (token->lower.data[0] == ';' ||
+ token->lower.data[0] == '}')) {
return done(parser);
}
@@ -1680,7 +1670,7 @@ css_error parseValue(css_parser *parser)
state->substate = WS;
} else if (token->type == CSS_TOKEN_CHAR &&
token->lower.len == 1 &&
- token->lower.ptr[0] == '{') {
+ token->lower.data[0] == '{') {
/* Grammar ambiguity. Assume block. */
parser_state to = { sBlock, Initial };
@@ -1741,10 +1731,10 @@ css_error parseAny0(css_parser *parser)
* assume '{', ';', ')', ']' mark end */
if (token->type == CSS_TOKEN_CHAR &&
token->lower.len == 1 &&
- (token->lower.ptr[0] == '{' ||
- token->lower.ptr[0] == ';' ||
- token->lower.ptr[0] == ')' ||
- token->lower.ptr[0] == ']')) {
+ (token->lower.data[0] == '{' ||
+ token->lower.data[0] == ';' ||
+ token->lower.data[0] == ')' ||
+ token->lower.data[0] == ']')) {
return done(parser);
}
@@ -1805,14 +1795,14 @@ css_error parseAny1(css_parser *parser)
/* Grammar ambiguity: any0 can be followed by
* '{', ';', ')', ']'. any1 can only be followed by '{'. */
if (token->type == CSS_TOKEN_CHAR && token->lower.len == 1) {
- if (token->lower.ptr[0] == ';' ||
- token->lower.ptr[0] == ')' ||
- token->lower.ptr[0] == ']') {
+ if (token->lower.data[0] == ';' ||
+ token->lower.data[0] == ')' ||
+ token->lower.data[0] == ']') {
parser_state to = { sAny, Initial };
parser_state subsequent = { sAny1, AfterAny };
return transition(parser, to, subsequent);
- } else if (token->lower.ptr[0] != '{') {
+ } else if (token->lower.data[0] != '{') {
/* parse error */
parser->parseError = true;
}
@@ -1883,10 +1873,10 @@ css_error parseAny(css_parser *parser)
state->substate = WS;
} else if (token->type == CSS_TOKEN_CHAR &&
token->lower.len == 1 &&
- (token->lower.ptr[0] == '(' ||
- token->lower.ptr[0] == '[')) {
+ (token->lower.data[0] == '(' ||
+ token->lower.data[0] == '[')) {
parser->match_char =
- token->lower.ptr[0] == '(' ? ')' : ']';
+ token->lower.data[0] == '(' ? ')' : ']';
state->substate = WS;
}
@@ -1919,7 +1909,7 @@ css_error parseAny(css_parser *parser)
/* Match correct close bracket (grammar ambiguity) */
if (token->type == CSS_TOKEN_CHAR && token->lower.len == 1 &&
- token->lower.ptr[0] == parser->match_char) {
+ token->lower.data[0] == parser->match_char) {
state->substate = WS2;
goto ws2;
}
@@ -1963,13 +1953,13 @@ css_error parseMalformedDeclaration(css_parser *parser)
if (token->type != CSS_TOKEN_CHAR ||
token->lower.len != 1 ||
- (token->lower.ptr[0] != '{' &&
- token->lower.ptr[0] != '}' &&
- token->lower.ptr[0] != '[' &&
- token->lower.ptr[0] != ']' &&
- token->lower.ptr[0] != '(' &&
- token->lower.ptr[0] != ')' &&
- token->lower.ptr[0] != ';'))
+ (token->lower.data[0] != '{' &&
+ token->lower.data[0] != '}' &&
+ token->lower.data[0] != '[' &&
+ token->lower.data[0] != ']' &&
+ token->lower.data[0] != '(' &&
+ token->lower.data[0] != ')' &&
+ token->lower.data[0] != ';'))
continue;
char want;
@@ -1979,17 +1969,17 @@ css_error parseMalformedDeclaration(css_parser *parser)
/* If the stack is empty, then we're done if we've got
* either a ';' or '}' */
if (match == NULL) {
- if (token->lower.ptr[0] == ';' ||
- token->lower.ptr[0] == '}')
+ if (token->lower.data[0] == ';' ||
+ token->lower.data[0] == '}')
break;
}
/* Regardless, if we've got a semicolon, ignore it */
- if (token->lower.ptr[0] == ';')
+ if (token->lower.data[0] == ';')
continue;
/* Get corresponding start tokens for end tokens */
- switch (token->lower.ptr[0]) {
+ switch (token->lower.data[0]) {
case '}':
want = '{';
break;
@@ -2011,7 +2001,7 @@ css_error parseMalformedDeclaration(css_parser *parser)
parser->open_items, NULL);
} else if (want == 0) {
parserutils_stack_push(parser->open_items,
- &token->lower.ptr[0]);
+ &token->lower.data[0]);
}
}
}
@@ -2057,12 +2047,12 @@ css_error parseMalformedSelector(css_parser *parser)
if (token->type != CSS_TOKEN_CHAR ||
token->lower.len != 1 ||
- (token->lower.ptr[0] != '{' &&
- token->lower.ptr[0] != '}' &&
- token->lower.ptr[0] != '[' &&
- token->lower.ptr[0] != ']' &&
- token->lower.ptr[0] != '(' &&
- token->lower.ptr[0] != ')'))
+ (token->lower.data[0] != '{' &&
+ token->lower.data[0] != '}' &&
+ token->lower.data[0] != '[' &&
+ token->lower.data[0] != ']' &&
+ token->lower.data[0] != '(' &&
+ token->lower.data[0] != ')'))
continue;
char want;
@@ -2070,7 +2060,7 @@ css_error parseMalformedSelector(css_parser *parser)
parser->open_items);
/* Get corresponding start tokens for end tokens */
- switch (token->lower.ptr[0]) {
+ switch (token->lower.data[0]) {
case '}':
want = '{';
break;
@@ -2092,7 +2082,7 @@ css_error parseMalformedSelector(css_parser *parser)
parser->open_items, NULL);
} else if (want == 0) {
parserutils_stack_push(parser->open_items,
- &token->lower.ptr[0]);
+ &token->lower.data[0]);
}
/* If we encountered a '}', there was data on the stack
@@ -2150,13 +2140,13 @@ css_error parseMalformedAtRule(css_parser *parser)
if (token->type != CSS_TOKEN_CHAR ||
token->lower.len != 1 ||
- (token->lower.ptr[0] != '{' &&
- token->lower.ptr[0] != '}' &&
- token->lower.ptr[0] != '[' &&
- token->lower.ptr[0] != ']' &&
- token->lower.ptr[0] != '(' &&
- token->lower.ptr[0] != ')' &&
- token->lower.ptr[0] != ';'))
+ (token->lower.data[0] != '{' &&
+ token->lower.data[0] != '}' &&
+ token->lower.data[0] != '[' &&
+ token->lower.data[0] != ']' &&
+ token->lower.data[0] != '(' &&
+ token->lower.data[0] != ')' &&
+ token->lower.data[0] != ';'))
continue;
char want;
@@ -2165,7 +2155,7 @@ css_error parseMalformedAtRule(css_parser *parser)
/* If we have a semicolon, then we're either done or
* need to ignore it */
- if (token->lower.ptr[0] == ';') {
+ if (token->lower.data[0] == ';') {
if (match == NULL)
break;
else
@@ -2173,7 +2163,7 @@ css_error parseMalformedAtRule(css_parser *parser)
}
/* Get corresponding start tokens for end tokens */
- switch (token->lower.ptr[0]) {
+ switch (token->lower.data[0]) {
case '}':
want = '{';
break;
@@ -2195,7 +2185,7 @@ css_error parseMalformedAtRule(css_parser *parser)
parser->open_items, NULL);
} else if (want == 0) {
parserutils_stack_push(parser->open_items,
- &token->lower.ptr[0]);
+ &token->lower.data[0]);
}
/* If we encountered a '}', there was data on the stack
@@ -2236,8 +2226,8 @@ static void tprinter(void *token)
{
css_token *t = token;
- if (t->data.ptr)
- printf("%d: %.*s", t->type, t->data.len, t->data.ptr);
+ if (t->data.data)
+ printf("%d: %.*s", t->type, t->data.len, t->data.data);
else
printf("%d", t->type);
}