From 67364acc7eeb51ee26b6fdab466ccd930a32f904 Mon Sep 17 00:00:00 2001 From: Daniel Silverstone Date: Sat, 26 Nov 2022 14:06:43 +0000 Subject: (calc): Update bytecode for calc() to be in an lwc_string 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 --- src/parse/properties/utils.c | 89 ++++++++++++++++++++++++++++++++------------ test/dump.h | 29 +++++++++------ 2 files changed, 84 insertions(+), 34 deletions(-) diff --git a/src/parse/properties/utils.c b/src/parse/properties/utils.c index fe5ee6b..fa8ffbe 100644 --- a/src/parse/properties/utils.c +++ b/src/parse/properties/utils.c @@ -1362,16 +1362,17 @@ cleanup: 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); @@ -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; @@ -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); @@ -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; @@ -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); @@ -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; @@ -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 { @@ -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; @@ -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); @@ -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; @@ -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; @@ -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); @@ -1578,6 +1597,12 @@ 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; @@ -1585,12 +1610,12 @@ css_error css__parse_calc(css_language *c, 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; @@ -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; } diff --git a/test/dump.h b/test/dump.h index a1fdd1f..eac0a9f 100644 --- a/test/dump.h +++ b/test/dump.h @@ -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, "+ "); @@ -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; @@ -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); -- cgit v1.2.3