/** * cr_declaration_append2: *@a_this: the current declaration list. *@a_prop: the property string of the declaration to append. *@a_value: the value of the declaration to append. * *Appends a declaration to the current declaration list. *Returns the list with the new property appended to it, or NULL in *case of an error. */ CRDeclaration * cr_declaration_append2 (CRDeclaration * a_this, CRString * a_prop, CRTerm * a_value) { CRDeclaration *new_elem = NULL; if (a_this) { new_elem = cr_declaration_new (a_this->parent_statement, a_prop, a_value); } else { new_elem = cr_declaration_new (NULL, a_prop, a_value); } g_return_val_if_fail (new_elem, NULL); return cr_declaration_append (a_this, new_elem); }
/** *Parses a text buffer that contains *a css declaration. * *@param a_statement the parent css2 statement of this *this declaration. Must be non NULL and of type *RULESET_STMT (must be a ruleset). *@param a_str the string that contains the statement. *@param a_enc the encoding of a_str. *@return the parsed declaration, or NULL in case of error. */ CRDeclaration * cr_declaration_parse_from_buf (CRStatement * a_statement, const guchar * a_str, enum CREncoding a_enc) { enum CRStatus status = CR_OK; CRTerm *value = NULL; CRString *property = NULL; CRDeclaration *result = NULL; gboolean important = FALSE; g_return_val_if_fail (a_str, NULL); if (a_statement) g_return_val_if_fail (a_statement->type == RULESET_STMT, NULL); CRParser *parser = (CRParser *) cr_parser_new_from_buf ((guchar*)a_str, strlen ((char *)a_str), a_enc, FALSE); g_return_val_if_fail (parser, NULL); status = cr_parser_try_to_skip_spaces_and_comments (parser); if (status != CR_OK) goto cleanup; status = cr_parser_parse_declaration (parser, &property, &value, &important); if (status != CR_OK || !property) goto cleanup; result = cr_declaration_new (a_statement, property, value); if (result) { property = NULL; value = NULL; result->important = important; } cleanup: if (parser) { cr_parser_destroy (parser); parser = NULL; } if (property) { cr_string_destroy (property); property = NULL; } if (value) { cr_term_destroy (value); value = NULL; } return result; }
/** * cr_declaration_parse_list_from_buf: *@a_str: the input buffer that contains the list of declaration to *parse. *@a_enc: the encoding of a_str * *Parses a ';' separated list of properties declaration. *Returns the parsed list of declaration, NULL if parsing failed. */ CRDeclaration * cr_declaration_parse_list_from_buf (const guchar * a_str, enum CREncoding a_enc) { enum CRStatus status = CR_OK; CRTerm *value = NULL; CRString *property = NULL; CRDeclaration *result = NULL, *cur_decl = NULL; CRParser *parser = NULL; CRTknzr *tokenizer = NULL; gboolean important = FALSE; g_return_val_if_fail (a_str, NULL); parser = cr_parser_new_from_buf ((guchar*)a_str, strlen (a_str), a_enc, FALSE); g_return_val_if_fail (parser, NULL); status = cr_parser_get_tknzr (parser, &tokenizer); if (status != CR_OK || !tokenizer) { if (status == CR_OK) status = CR_ERROR; goto cleanup; } status = cr_parser_try_to_skip_spaces_and_comments (parser); if (status != CR_OK) goto cleanup; status = cr_parser_parse_declaration (parser, &property, &value, &important); if (status != CR_OK || !property) { if (status != CR_OK) status = CR_ERROR; goto cleanup; } result = cr_declaration_new (NULL, property, value); if (result) { property = NULL; value = NULL; result->important = important; } /*now, go parse the other declarations */ for (;;) { guint32 c = 0; cr_parser_try_to_skip_spaces_and_comments (parser); status = cr_tknzr_peek_char (tokenizer, &c); if (status != CR_OK) { if (status == CR_END_OF_INPUT_ERROR) status = CR_OK; goto cleanup; } if (c == ';') { status = cr_tknzr_read_char (tokenizer, &c); } else { break; } important = FALSE; cr_parser_try_to_skip_spaces_and_comments (parser); status = cr_parser_parse_declaration (parser, &property, &value, &important); if (status != CR_OK || !property) { if (status == CR_END_OF_INPUT_ERROR) { status = CR_OK; } break; } cur_decl = cr_declaration_new (NULL, property, value); if (cur_decl) { cur_decl->important = important; result = cr_declaration_append (result, cur_decl); property = NULL; value = NULL; cur_decl = NULL; } else { break; } } cleanup: if (parser) { cr_parser_destroy (parser); parser = NULL; } if (property) { cr_string_destroy (property); property = NULL; } if (value) { cr_term_destroy (value); value = NULL; } if (status != CR_OK && result) { cr_declaration_destroy (result); result = NULL; } return result; }
static void property (CRDocHandler * a_this, CRString * a_name, CRTerm * a_expression, gboolean a_important) { enum CRStatus status = CR_OK; ParsingContext *ctxt = NULL; ParsingContext **ctxtptr = NULL; CRDeclaration *decl = NULL, *decl2 = NULL; CRString *str = NULL; g_return_if_fail (a_this); ctxtptr = &ctxt; status = cr_doc_handler_get_ctxt (a_this, (gpointer *) ctxtptr); g_return_if_fail (status == CR_OK && ctxt); /* *make sure a current ruleset statement has been allocated *already. */ g_return_if_fail (ctxt->cur_stmt && (ctxt->cur_stmt->type == RULESET_STMT || ctxt->cur_stmt->type == AT_FONT_FACE_RULE_STMT || ctxt->cur_stmt->type == AT_PAGE_RULE_STMT)); if (a_name) { str = cr_string_dup (a_name); g_return_if_fail (str); } /*instanciates a new declaration */ decl = cr_declaration_new (ctxt->cur_stmt, str, a_expression); g_return_if_fail (decl); str = NULL; decl->important = a_important; /* *add the new declaration to the current statement *being build. */ switch (ctxt->cur_stmt->type) { case RULESET_STMT: decl2 = cr_declaration_append (ctxt->cur_stmt->kind.ruleset->decl_list, decl); if (!decl2) { cr_declaration_destroy (decl); cr_utils_trace_info ("Could not append decl to ruleset"); goto error; } ctxt->cur_stmt->kind.ruleset->decl_list = decl2; decl = NULL; decl2 = NULL; break; case AT_FONT_FACE_RULE_STMT: decl2 = cr_declaration_append (ctxt->cur_stmt->kind.font_face_rule->decl_list, decl); if (!decl2) { cr_declaration_destroy (decl); cr_utils_trace_info ("Could not append decl to ruleset"); goto error; } ctxt->cur_stmt->kind.font_face_rule->decl_list = decl2; decl = NULL; decl2 = NULL; break; case AT_PAGE_RULE_STMT: decl2 = cr_declaration_append (ctxt->cur_stmt->kind.page_rule->decl_list, decl); if (!decl2) { cr_declaration_destroy (decl); cr_utils_trace_info ("Could not append decl to ruleset"); goto error; } ctxt->cur_stmt->kind.page_rule->decl_list = decl2; decl = NULL; decl2 = NULL; break; default: goto error; break; } return; error: if (str) { g_free (str); str = NULL; } if (decl) { cr_declaration_destroy (decl); decl = NULL; } }
/** *Parses a ';' separated list of properties declaration. *@param a_str the input buffer that contains the list of declaration to *parse. *@param a_enc the encoding of a_str *@return the parsed list of declaration, NULL if parsing failed. */ CRDeclaration * cr_declaration_parse_list_from_buf (const guchar * a_str, enum CREncoding a_enc) { enum CRStatus status = CR_OK; CRTerm *value = NULL; CRString *property = NULL; CRDeclaration *result = NULL, *cur_decl = NULL; CRTknzr *tokenizer = NULL; gboolean important = FALSE; g_return_val_if_fail (a_str, NULL); CRParser *parser = (CRParser *)cr_parser_new_from_buf ((guchar*)a_str, strlen ((char *)a_str), a_enc, FALSE); g_return_val_if_fail (parser, NULL); status = cr_parser_get_tknzr (parser, &tokenizer); if (status != CR_OK || !tokenizer) { if (status == CR_OK) status = CR_ERROR; goto cleanup; } status = cr_parser_try_to_skip_spaces_and_comments (parser); if (status != CR_OK) goto cleanup; status = cr_parser_parse_declaration (parser, &property, &value, &important); if (status != CR_OK || !property) { if (status != CR_OK) status = CR_ERROR; goto cleanup; } result = cr_declaration_new (NULL, property, value); if (result) { property = NULL; value = NULL; result->important = important; } /*now, go parse the other declarations */ for (;;) { guint32 c = 0; cr_parser_try_to_skip_spaces_and_comments (parser); status = cr_tknzr_peek_char (tokenizer, &c); if (status != CR_OK) { if (status == CR_END_OF_INPUT_ERROR) status = CR_OK; goto cleanup; } if (c == ';') { status = cr_tknzr_read_char (tokenizer, &c); } else { cr_tknzr_read_char (tokenizer, &c); continue; // try to keep reading until we reach the end or a ; } important = FALSE; cr_parser_try_to_skip_spaces_and_comments (parser); status = cr_parser_parse_declaration (parser, &property, &value, &important); if (status != CR_OK || !property) { if (status == CR_END_OF_INPUT_ERROR) { status = CR_OK; // simply the end of input, do not delete what we got so far, just finish break; } else { continue; // even if one declaration is broken, it's no reason to discard others (see http://www.w3.org/TR/CSS21/syndata.html#declaration) } } cur_decl = cr_declaration_new (NULL, property, value); if (cur_decl) { cur_decl->important = important; result = cr_declaration_append (result, cur_decl); property = NULL; value = NULL; cur_decl = NULL; } else { break; } } cleanup: if (parser) { cr_parser_destroy (parser); parser = NULL; } if (property) { cr_string_destroy (property); property = NULL; } if (value) { cr_term_destroy (value); value = NULL; } if (status != CR_OK && result) { cr_declaration_destroy (result); result = NULL; } return result; }