Skip to content

Commit

Permalink
(calc): Update bytecode for calc() to be in an lwc_string
Browse files Browse the repository at this point in the history
In order to permit us to share calc expressions between styles
and computed styles, without copying, we embed the calc expression
bytecode into an lwc string.  This is effectively using lwc_string
as an interned byte buffer, there may be a nicer way to do this in
the future.

Signed-off-by: Daniel Silverstone <[email protected]>
  • Loading branch information
kinnison authored and tlsa committed Nov 27, 2022
1 parent 9434b1d commit 67364ac
Show file tree
Hide file tree
Showing 2 changed files with 84 additions and 34 deletions.
89 changes: 66 additions & 23 deletions src/parse/properties/utils.c
Original file line number Diff line number Diff line change
Expand Up @@ -1362,16 +1362,17 @@ css_error css__comma_list_to_style(css_language *c,
static css_error
css__parse_calc_sum(css_language *c,
const parserutils_vector *vector, int *ctx,
css_style *result);
parserutils_buffer *result);

static css_error
css__parse_calc_number(
const parserutils_vector *vector, int *ctx,
css_style *result)
parserutils_buffer *result)
{
const css_token *token;
css_fixed num;
size_t consumed;
css_code_t push = CALC_PUSH_NUMBER;

/* Consume the number token */
token = parserutils_vector_iterate(vector, ctx);
Expand All @@ -1386,13 +1387,18 @@ css__parse_calc_number(
return CSS_INVALID;
}

return css__stylesheet_style_vappend(result, 2, (css_code_t) CALC_PUSH_NUMBER, (css_code_t)num);
return css_error_from_parserutils_error(
parserutils_buffer_appendv(result, 2,
&push, sizeof(push),
&num, sizeof(num)
)
);
}

static css_error
css__parse_calc_value(css_language *c,
const parserutils_vector *vector, int *ctx,
css_style *result)
parserutils_buffer *result)
{
css_error error;
int orig_ctx = *ctx;
Expand Down Expand Up @@ -1426,6 +1432,7 @@ css__parse_calc_value(css_language *c,
{
css_fixed length = 0;
uint32_t unit = 0;
css_code_t push = CALC_PUSH_VALUE;
*ctx = orig_ctx;

error = css__parse_unit_specifier(c, vector, ctx, UNIT_CALC_NUMBER, &length, &unit);
Expand All @@ -1434,7 +1441,14 @@ css__parse_calc_value(css_language *c,
return error;
}

error = css__stylesheet_style_vappend(result, 3, (css_code_t) CALC_PUSH_VALUE, length, unit);
error = css_error_from_parserutils_error(
parserutils_buffer_appendv(result, 3,
&push, sizeof(push),
&length, sizeof(length),
&unit, sizeof(unit)
)
);

}
break;

Expand All @@ -1455,12 +1469,11 @@ css__parse_calc_value(css_language *c,
static css_error
css__parse_calc_product(css_language *c,
const parserutils_vector *vector, int *ctx,
css_style *result)
parserutils_buffer *result)
{
css_error error = CSS_OK;
const css_token *token;
bool multiplication;

css_code_t operator;

/* First parse a value */
error = css__parse_calc_value(c, vector, ctx, result);
Expand All @@ -1480,9 +1493,9 @@ css__parse_calc_product(css_language *c,
tokenIsChar(token, '-'))
break;
else if (tokenIsChar(token, '*'))
multiplication = true;
operator = CALC_MULTIPLY;
else if (tokenIsChar(token, '/'))
multiplication = false;
operator = CALC_DIVIDE;
else {
error = CSS_INVALID;
break;
Expand All @@ -1492,7 +1505,7 @@ css__parse_calc_product(css_language *c,

consumeWhitespace(vector, ctx);

if (multiplication) {
if (operator == CALC_MULTIPLY) {
/* parse another value */
error = css__parse_calc_value(c, vector, ctx, result);
} else {
Expand All @@ -1502,8 +1515,9 @@ css__parse_calc_product(css_language *c,
break;

/* emit the multiplication/division operator */
error = css__stylesheet_style_append(result,
(css_code_t) (multiplication ? CALC_MULTIPLY : CALC_DIVIDE));
error = css_error_from_parserutils_error(
parserutils_buffer_append(result, (const uint8_t *)&operator, sizeof(operator))
);
} while (1);
/* We've fallen off, either we had an error or we're left with ')' */
return error;
Expand All @@ -1513,12 +1527,11 @@ css__parse_calc_product(css_language *c,
css_error
css__parse_calc_sum(css_language *c,
const parserutils_vector *vector, int *ctx,
css_style *result)
parserutils_buffer *result)
{
css_error error = CSS_OK;
const css_token *token;
bool addition;

css_code_t operator;

/* First parse a product */
error = css__parse_calc_product(c, vector, ctx, result);
Expand All @@ -1535,9 +1548,9 @@ css__parse_calc_sum(css_language *c,
} else if (tokenIsChar(token, ')'))
break;
else if (tokenIsChar(token, '+'))
addition = true;
operator = CALC_ADD;
else if (tokenIsChar(token, '-'))
addition = false;
operator = CALC_SUBTRACT;
else {
error = CSS_INVALID;
break;
Expand All @@ -1552,7 +1565,9 @@ css__parse_calc_sum(css_language *c,
break;

/* emit the addition/subtraction operator */
error = css__stylesheet_style_append(result, (css_code_t) (addition ? CALC_ADD : CALC_SUBTRACT));
error = css_error_from_parserutils_error(
parserutils_buffer_append(result, (const uint8_t *)&operator, sizeof(operator))
);
} while (1);
/* We've fallen off, either we had an error or we're left with ')' */
return error;
Expand All @@ -1569,6 +1584,10 @@ css_error css__parse_calc(css_language *c,
const css_token *token;
css_error error = CSS_OK;
css_style *calc_style = NULL;
parserutils_buffer *calc_buffer = NULL;
lwc_string *calc_expr = NULL;
uint32_t expr_index = 0;
css_code_t finish = CALC_FINISH;

consumeWhitespace(vector, ctx);

Expand All @@ -1578,19 +1597,25 @@ css_error css__parse_calc(css_language *c,
return CSS_INVALID;
}

if (parserutils_buffer_create(&calc_buffer) != PARSERUTILS_OK) {
/* Since &calc_buffer is valid, the only error case is NONMEM */
*ctx = orig_ctx;
return CSS_NOMEM;
}

error = css__stylesheet_style_create(c->sheet, &calc_style);
if (error != CSS_OK)
goto cleanup;

error = css__stylesheet_style_append(calc_style, property);
if (error != CSS_OK)
goto cleanup;

error = css__stylesheet_style_append(calc_style, (css_code_t) unit);
if (error != CSS_OK)
goto cleanup;

error = css__parse_calc_sum(c, vector, ctx, calc_style);
error = css__parse_calc_sum(c, vector, ctx, calc_buffer);
if (error != CSS_OK)
goto cleanup;

Expand All @@ -1602,17 +1627,35 @@ css_error css__parse_calc(css_language *c,
goto cleanup;
}

/* Append the indicator that the calc is finished */
error = css_error_from_parserutils_error(
parserutils_buffer_append(calc_buffer, (const uint8_t *)&finish, sizeof(finish))
);
if (error != CSS_OK)
goto cleanup;

/* Swallow that close paren */
parserutils_vector_iterate(vector, ctx);

/* Append the indicator that the calc is finished */
error = css__stylesheet_style_append(calc_style, (css_code_t) CALC_FINISH);
/* Create the lwc string representing the calculation and store it in */
error = css_error_from_lwc_error(
lwc_intern_string((const char *)calc_buffer->data, calc_buffer->length, &calc_expr)
);
if (error != CSS_OK)
goto cleanup;

/* This always takes ownership of calc_expr, so we should not use after this */
error = css__stylesheet_string_add(calc_style->sheet, calc_expr, &expr_index);
if (error != CSS_OK)
goto cleanup;

css__stylesheet_style_append(calc_style, (css_code_t) expr_index);

error = css__stylesheet_merge_style(result, calc_style);
cleanup:
css__stylesheet_style_destroy(calc_style);
parserutils_buffer_destroy(calc_buffer);
/* We do not need to clean up calc_expr, it will never leak */
if (error != CSS_OK) {
*ctx = orig_ctx;
}
Expand Down
29 changes: 18 additions & 11 deletions test/dump.h
Original file line number Diff line number Diff line change
Expand Up @@ -803,15 +803,23 @@ void dump_bytecode(css_style *style, char **ptr, uint32_t depth)
} else if (getFlagValue(opv) == FLAG_VALUE_UNSET) {
*ptr += sprintf(*ptr, "unset");
} else if (isCalc(opv)) {
lwc_string *calc_expr = NULL;
const uint8_t *codeptr = NULL;
css_code_t calc_opcode;
uint32_t unit, snum;
/* First entry is a unit */
uint32_t unit = *((uint32_t *)bytecode);
unit = *((uint32_t *)bytecode);
ADVANCE(sizeof(unit));
/* Second entry is an lwc_string of the expression */
snum = *((uint32_t *)bytecode);
ADVANCE(sizeof(snum));
css__stylesheet_string_get(style->sheet, snum, &calc_expr);
codeptr = (const uint8_t *)lwc_string_data(calc_expr);
*ptr += sprintf(*ptr, "/* -> ");
dump_unit(0, unit, ptr);
*ptr += sprintf(*ptr, " */ calc(");
css_code_t calc_opcode;
while ((calc_opcode = *((css_code_t *)bytecode)) != CALC_FINISH) {
ADVANCE(sizeof(calc_opcode));
while ((calc_opcode = *((css_code_t *)codeptr)) != CALC_FINISH) {
codeptr += sizeof(calc_opcode);
switch (calc_opcode) {
case CALC_ADD:
*ptr += sprintf(*ptr, "+ ");
Expand All @@ -826,17 +834,17 @@ void dump_bytecode(css_style *style, char **ptr, uint32_t depth)
*ptr += sprintf(*ptr, "/ ");
break;
case CALC_PUSH_VALUE: {
css_fixed num = *((css_fixed *)bytecode);
ADVANCE(sizeof(num));
uint32_t unit = *((uint32_t *)bytecode);
ADVANCE(sizeof(unit));
css_fixed num = *((css_fixed *)codeptr);
codeptr += sizeof(num);
uint32_t unit = *((uint32_t *)codeptr);
codeptr += sizeof(unit);
dump_unit(num, unit, ptr);
*ptr += sprintf(*ptr, " ");
break;
}
case CALC_PUSH_NUMBER: {
css_fixed num = *((css_fixed *)bytecode);
ADVANCE(sizeof(num));
css_fixed num = *((css_fixed *)codeptr);
codeptr += sizeof(num);
dump_number(num, ptr);
*ptr += sprintf(*ptr, " ");
break;
Expand All @@ -846,7 +854,6 @@ void dump_bytecode(css_style *style, char **ptr, uint32_t depth)
break;
}
}
ADVANCE(sizeof(calc_opcode));
*ptr += sprintf(*ptr, "=)");
} else {
value = getValue(opv);
Expand Down

0 comments on commit 67364ac

Please sign in to comment.