/* -*- Mode: C; indent-tabs-mode:nil; c-basic-offset: 8-*- */
/*
* This file is part of The Croco Library
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of version 2.1 of the GNU Lesser General Public
* License as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA
*
* Author: Dodji Seketeli
* See COPYRIGHTS file for copyright information.
*/
#include <string.h>
#include "cr-utils.h"
#include "cr-om-parser.h"
/**
*@CROMParser:
*
*The definition of the CSS Object Model Parser.
*This parser uses (and sits) the SAC api of libcroco defined
*in cr-parser.h and cr-doc-handler.h
*/
struct _CROMParserPriv {
CRParser *parser;
};
#define PRIVATE(a_this) ((a_this)->priv)
/*
*Forward declaration of a type defined later
*in this file.
*/
struct _ParsingContext;
typedef struct _ParsingContext ParsingContext;
static ParsingContext *new_parsing_context (void);
static void destroy_context (ParsingContext * a_ctxt);
static void unrecoverable_error (CRDocHandler * a_this);
static void error (CRDocHandler * a_this);
static void property (CRDocHandler * a_this,
CRString * a_name,
CRTerm * a_expression,
gboolean a_important);
static void end_selector (CRDocHandler * a_this,
CRSelector * a_selector_list);
static void start_selector (CRDocHandler * a_this,
CRSelector * a_selector_list);
static void start_font_face (CRDocHandler * a_this,
CRParsingLocation *a_location);
static void end_font_face (CRDocHandler * a_this);
static void end_document (CRDocHandler * a_this);
static void start_document (CRDocHandler * a_this);
static void charset (CRDocHandler * a_this,
CRString * a_charset,
CRParsingLocation *a_location);
static void start_page (CRDocHandler * a_this, CRString * a_page,
CRString * a_pseudo_page,
CRParsingLocation *a_location);
static void end_page (CRDocHandler * a_this, CRString * a_page,
CRString * a_pseudo_page);
static void start_media (CRDocHandler * a_this,
GList * a_media_list,
CRParsingLocation *a_location);
static void end_media (CRDocHandler * a_this,
GList * a_media_list);
static void import_style (CRDocHandler * a_this,
GList * a_media_list,
CRString * a_uri,
CRString * a_uri_default_ns,
CRParsingLocation *a_location);
struct _ParsingContext {
CRStyleSheet *stylesheet;
CRStatement *cur_stmt;
CRStatement *cur_media_stmt;
};
/********************************************
*Private methods
********************************************/
static ParsingContext *
new_parsing_context (void)
{
ParsingContext *result = NULL;
result = g_try_malloc (sizeof (ParsingContext));
if (!result) {
cr_utils_trace_info ("Out of Memory");
return NULL;
}
memset (result, 0, sizeof (ParsingContext));
return result;
}
static void
destroy_context (ParsingContext * a_ctxt)
{
g_return_if_fail (a_ctxt);
if (a_ctxt->stylesheet) {
cr_stylesheet_destroy (a_ctxt->stylesheet);
a_ctxt->stylesheet = NULL;
}
if (a_ctxt->cur_stmt) {
cr_statement_destroy (a_ctxt->cur_stmt);
a_ctxt->cur_stmt = NULL;
}
g_free (a_ctxt);
}
static enum CRStatus
cr_om_parser_init_default_sac_handler (CROMParser * a_this)
{
CRDocHandler *sac_handler = NULL;
gboolean created_handler = FALSE;
enum CRStatus status = CR_OK;
g_return_val_if_fail (a_this && PRIVATE (a_this)
&& PRIVATE (a_this)->parser,
CR_BAD_PARAM_ERROR);
status = cr_parser_get_sac_handler (PRIVATE (a_this)->parser,
&sac_handler);
g_return_val_if_fail (status == CR_OK, status);
if (!sac_handler) {
sac_handler = cr_doc_handler_new ();
created_handler = TRUE;
}
/*
*initialyze here the sac handler.
*/
sac_handler->start_document = start_document;
sac_handler->end_document = end_document;
sac_handler->start_selector = start_selector;
sac_handler->end_selector = end_selector;
sac_handler->property = property;
sac_handler->start_font_face = start_font_face;
sac_handler->end_font_face = end_font_face;
sac_handler->error = error;
sac_handler->unrecoverable_error = unrecoverable_error;
sac_handler->charset = charset;
sac_handler->start_page = start_page;
sac_handler->end_page = end_page;
sac_handler->start_media = start_media;
sac_handler->end_media = end_media;
sac_handler->import_style = import_style;
if (created_handler) {
status = cr_parser_set_sac_handler (PRIVATE (a_this)->parser,
sac_handler);
cr_doc_handler_unref (sac_handler);
}
return status;
}
static void
start_document (CRDocHandler * a_this)
{
ParsingContext *ctxt = NULL;
CRStyleSheet *stylesheet = NULL;
g_return_if_fail (a_this);
ctxt = new_parsing_context ();
g_return_if_fail (ctxt);
stylesheet = cr_stylesheet_new (NULL);
ctxt->stylesheet = stylesheet;
cr_doc_handler_set_ctxt (a_this, ctxt);
}
static void
start_font_face (CRDocHandler * a_this,
CRParsingLocation *a_location)
{
enum CRStatus status = CR_OK;
ParsingContext *ctxt = NULL;
ParsingContext **ctxtptr = NULL;
(void) a_location;
g_return_if_fail (a_this);
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);
g_return_if_fail (ctxt->cur_stmt == NULL);
ctxt->cur_stmt =
cr_statement_new_at_font_face_rule (ctxt->stylesheet, NULL);
g_return_if_fail (ctxt->cur_stmt);
}
static void
end_font_face (CRDocHandler * a_this)
{
enum CRStatus status = CR_OK;
ParsingContext *ctxt = NULL;
ParsingContext **ctxtptr = NULL;
CRStatement *stmts = NULL;
g_return_if_fail (a_this);
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);
g_return_if_fail
(ctxt->cur_stmt
&& ctxt->cur_stmt->type == AT_FONT_FACE_RULE_STMT
&& ctxt->stylesheet);
stmts = cr_statement_append (ctxt->stylesheet->statements,
ctxt->cur_stmt);
if (!stmts)
goto error;
ctxt->stylesheet->statements = stmts;
stmts = NULL;
ctxt->cur_stmt = NULL;
return;
error:
if (ctxt->cur_stmt) {
cr_statement_destroy (ctxt->cur_stmt);
ctxt->cur_stmt = NULL;
}
if (!stmts) {
cr_statement_destroy (stmts);
stmts = NULL;
}
}
static void
end_document (CRDocHandler * a_this)
{
enum CRStatus status = CR_OK;
ParsingContext *ctxt = NULL;
ParsingContext **ctxtptr = 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);
if (!ctxt->stylesheet || ctxt->cur_stmt)
goto error;
status = cr_doc_handler_set_result (a_this, ctxt->stylesheet);
g_return_if_fail (status == CR_OK);
ctxt->stylesheet = NULL;
destroy_context (ctxt);
cr_doc_handler_set_ctxt (a_this, NULL);
return;
error:
if (ctxt) {
destroy_context (ctxt);
}
}
static void
charset (CRDocHandler * a_this, CRString * a_charset,
CRParsingLocation *a_location)
{
enum CRStatus status = CR_OK;
CRStatement *stmt = NULL,
*stmt2 = NULL;
CRString *charset = NULL;
ParsingContext *ctxt = NULL;
ParsingContext **ctxtptr = NULL;
(void) a_location;
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);
g_return_if_fail (ctxt->stylesheet);
charset = cr_string_dup (a_charset) ;
stmt = cr_statement_new_at_charset_rule (ctxt->stylesheet, charset);
g_return_if_fail (stmt);
stmt2 = cr_statement_append (ctxt->stylesheet->statements, stmt);
if (!stmt2) {
if (stmt) {
cr_statement_destroy (stmt);
stmt = NULL;
}
if (charset) {
cr_string_destroy (charset);
}
return;
}
ctxt->stylesheet->statements = stmt2;
stmt2 = NULL;
}
static void
start_page (CRDocHandler * a_this,
CRString * a_page,
CRString * a_pseudo,
CRParsingLocation *a_location)
{
enum CRStatus status = CR_OK;
ParsingContext *ctxt = NULL;
ParsingContext **ctxtptr = NULL;
(void) a_location;
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);
g_return_if_fail (ctxt->cur_stmt == NULL);
ctxt->cur_stmt = cr_statement_new_at_page_rule
(ctxt->stylesheet, NULL, NULL, NULL);
if (a_page) {
ctxt->cur_stmt->kind.page_rule->name =
cr_string_dup (a_page) ;
if (!ctxt->cur_stmt->kind.page_rule->name) {
goto error;
}
}
if (a_pseudo) {
ctxt->cur_stmt->kind.page_rule->pseudo =
cr_string_dup (a_pseudo) ;
if (!ctxt->cur_stmt->kind.page_rule->pseudo) {
goto error;
}
}
return;
error:
if (ctxt->cur_stmt) {
cr_statement_destroy (ctxt->cur_stmt);
ctxt->cur_stmt = NULL;
}
}
static void
end_page (CRDocHandler * a_this,
CRString * a_page,
CRString * a_pseudo_page)
{
enum CRStatus status = CR_OK;
ParsingContext *ctxt = NULL;
ParsingContext **ctxtptr = NULL;
CRStatement *stmt = NULL;
(void) a_page;
(void) a_pseudo_page;
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);
g_return_if_fail (ctxt->cur_stmt
&& ctxt->cur_stmt->type == AT_PAGE_RULE_STMT
&& ctxt->stylesheet);
stmt = cr_statement_append (ctxt->stylesheet->statements,
ctxt->cur_stmt);
if (stmt) {
ctxt->stylesheet->statements = stmt;
stmt = NULL;
ctxt->cur_stmt = NULL;
}
if (ctxt->cur_stmt) {
cr_statement_destroy (ctxt->cur_stmt);
ctxt->cur_stmt = NULL;
}
a_page = NULL; /*keep compiler happy */
a_pseudo_page = NULL; /*keep compiler happy */
}
static void
start_media (CRDocHandler * a_this,
GList * a_media_list,
CRParsingLocation *a_location)
{
enum CRStatus status = CR_OK;
ParsingContext *ctxt = NULL;
ParsingContext **ctxtptr = NULL;
GList *media_list = NULL;
(void) a_location;
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);
g_return_if_fail (ctxt
&& ctxt->cur_stmt == NULL
&& ctxt->cur_media_stmt == NULL
&& ctxt->stylesheet);
if (a_media_list) {
/*duplicate the media_list */
media_list = cr_utils_dup_glist_of_cr_string
(a_media_list);
}
ctxt->cur_media_stmt =
cr_statement_new_at_media_rule
(ctxt->stylesheet, NULL, media_list);
}
static void
end_media (CRDocHandler * a_this, GList * a_media_list)
{
enum CRStatus status = CR_OK;
ParsingContext *ctxt = NULL;
ParsingContext **ctxtptr = NULL;
CRStatement *stmts = NULL;
(void) a_media_list;
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);
g_return_if_fail (ctxt
&& ctxt->cur_media_stmt
&& ctxt->cur_media_stmt->type == AT_MEDIA_RULE_STMT
&& ctxt->stylesheet);
stmts = cr_statement_append (ctxt->stylesheet->statements,
ctxt->cur_media_stmt);
if (!stmts) {
cr_statement_destroy (ctxt->cur_media_stmt);
ctxt->cur_media_stmt = NULL;
}
ctxt->stylesheet->statements = stmts;
stmts = NULL;
ctxt->cur_stmt = NULL ;
ctxt->cur_media_stmt = NULL ;
a_media_list = NULL;
}
static void
import_style (CRDocHandler * a_this,
GList * a_media_list,
CRString * a_uri,
CRString * a_uri_default_ns,
CRParsingLocation *a_location)
{
enum CRStatus status = CR_OK;
CRString *uri = NULL;
CRStatement *stmt = NULL,
*stmt2 = NULL;
ParsingContext *ctxt = NULL;
ParsingContext **ctxtptr = NULL;
GList *media_list = NULL ;
(void) a_uri_default_ns;
(void) a_location;
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);
g_return_if_fail (ctxt->stylesheet);
uri = cr_string_dup (a_uri) ;
if (a_media_list)
media_list = cr_utils_dup_glist_of_cr_string (a_media_list) ;
stmt = cr_statement_new_at_import_rule
(ctxt->stylesheet, uri, media_list, NULL);
if (!stmt)
goto error;
if (ctxt->cur_stmt) {
stmt2 = cr_statement_append (ctxt->cur_stmt, stmt);
if (!stmt2)
goto error;
ctxt->cur_stmt = stmt2;
stmt2 = NULL;
stmt = NULL;
} else {
stmt2 = cr_statement_append (ctxt->stylesheet->statements,
stmt);
if (!stmt2)
goto error;
ctxt->stylesheet->statements = stmt2;
stmt2 = NULL;
stmt = NULL;
}
return;
error:
if (uri) {
cr_string_destroy (uri);
}
if (stmt) {
cr_statement_destroy (stmt);
stmt = NULL;
}
a_uri_default_ns = NULL; /*keep compiler happy */
}
static void
start_selector (CRDocHandler * a_this, CRSelector * a_selector_list)
{
enum CRStatus status = CR_OK ;
ParsingContext *ctxt = NULL;
ParsingContext **ctxtptr = 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);
if (ctxt->cur_stmt) {
/*hmm, this should be NULL so free it */
cr_statement_destroy (ctxt->cur_stmt);
ctxt->cur_stmt = NULL;
}
ctxt->cur_stmt = cr_statement_new_ruleset
(ctxt->stylesheet, a_selector_list, NULL, NULL);
}
static void
end_selector (CRDocHandler * a_this, CRSelector * a_selector_list)
{
enum CRStatus status = CR_OK;
ParsingContext *ctxt = NULL;
ParsingContext **ctxtptr = NULL;
(void) a_selector_list;
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);
g_return_if_fail (ctxt->cur_stmt && ctxt->stylesheet);
if (ctxt->cur_stmt) {
CRStatement *stmts = NULL;
if (ctxt->cur_media_stmt) {
CRAtMediaRule *media_rule = NULL;
media_rule = ctxt->cur_media_stmt->kind.media_rule;
stmts = cr_statement_append
(media_rule->rulesets, ctxt->cur_stmt);
if (!stmts) {
cr_utils_trace_info
("Could not append a new statement");
cr_statement_destroy (media_rule->rulesets);
ctxt->cur_media_stmt->
kind.media_rule->rulesets = NULL;
return;
}
media_rule->rulesets = stmts;
ctxt->cur_stmt = NULL;
} else {
stmts = cr_statement_append
(ctxt->stylesheet->statements,
ctxt->cur_stmt);
if (!stmts) {
cr_utils_trace_info
("Could not append a new statement");
cr_statement_destroy (ctxt->cur_stmt);
ctxt->cur_stmt = NULL;
return;
}
ctxt->stylesheet->statements = stmts;
ctxt->cur_stmt = NULL;
}
}
a_selector_list = NULL; /*keep compiler happy */
}
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;
}
}
static void
error (CRDocHandler * a_this)
{
enum CRStatus status = CR_OK;
ParsingContext *ctxt = NULL;
ParsingContext **ctxtptr = 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);
if (ctxt->cur_stmt) {
cr_statement_destroy (ctxt->cur_stmt);
ctxt->cur_stmt = NULL;
}
}
static void
unrecoverable_error (CRDocHandler * a_this)
{
enum CRStatus status = CR_OK;
ParsingContext *ctxt = NULL;
ParsingContext **ctxtptr = NULL;
ctxtptr = &ctxt;
status = cr_doc_handler_get_ctxt (a_this, (gpointer *) ctxtptr);
g_return_if_fail (status == CR_OK);
if (ctxt) {
if (ctxt->stylesheet) {
status = cr_doc_handler_set_result
(a_this, ctxt->stylesheet);
g_return_if_fail (status == CR_OK);
}
g_free (ctxt);
cr_doc_handler_set_ctxt (a_this, NULL);
}
}
/********************************************
*Public methods
********************************************/
/**
* cr_om_parser_new:
*@a_input: the input stream.
*
*Constructor of the CROMParser.
*Returns the newly built instance of #CROMParser.
*/
CROMParser *
cr_om_parser_new (CRInput * a_input)
{
CROMParser *result = NULL;
enum CRStatus status = CR_OK;
result = g_try_malloc (sizeof (CROMParser));
if (!result) {
cr_utils_trace_info ("Out of memory");
return NULL;
}
memset (result, 0, sizeof (CROMParser));
PRIVATE (result) = g_try_malloc (sizeof (CROMParserPriv));
if (!PRIVATE (result)) {
cr_utils_trace_info ("Out of memory");
goto error;
}
memset (PRIVATE (result), 0, sizeof (CROMParserPriv));
PRIVATE (result)->parser = cr_parser_new_from_input (a_input);
if (!PRIVATE (result)->parser) {
cr_utils_trace_info ("parsing instanciation failed");
goto error;
}
status = cr_om_parser_init_default_sac_handler (result);
if (status != CR_OK) {
goto error;
}
return result;
error:
if (result) {
cr_om_parser_destroy (result);
}
return NULL;
}
/**
* cr_om_parser_parse_buf:
*@a_this: the current instance of #CROMParser.
*@a_buf: the in memory buffer to parse.
*@a_len: the length of the in memory buffer in number of bytes.
*@a_enc: the encoding of the in memory buffer.
*@a_result: out parameter the resulting style sheet
*
*Parses the content of an in memory buffer.
*
*Returns CR_OK upon successfull completion, an error code otherwise.
*/
enum CRStatus
cr_om_parser_parse_buf (CROMParser * a_this,
const guchar * a_buf,
gulong a_len,
enum CREncoding a_enc, CRStyleSheet ** a_result)
{
enum CRStatus status = CR_OK;
g_return_val_if_fail (a_this && a_result, CR_BAD_PARAM_ERROR);
if (!PRIVATE (a_this)->parser) {
PRIVATE (a_this)->parser = cr_parser_new (NULL);
}
status = cr_parser_parse_buf (PRIVATE (a_this)->parser,
a_buf, a_len, a_enc);
if (status == CR_OK) {
CRStyleSheet *result = NULL;
CRStyleSheet **resultptr = NULL;
CRDocHandler *sac_handler = NULL;
cr_parser_get_sac_handler (PRIVATE (a_this)->parser,
&sac_handler);
g_return_val_if_fail (sac_handler, CR_ERROR);
resultptr = &result;
status = cr_doc_handler_get_result (sac_handler,
(gpointer *) resultptr);
g_return_val_if_fail (status == CR_OK, status);
if (result)
*a_result = result;
}
return status;
}
/**
* cr_om_parser_simply_parse_buf:
*@a_buf: the css2 in memory buffer.
*@a_len: the length of the in memory buffer.
*@a_enc: the encoding of the in memory buffer.
*@a_result: out parameter. The resulting css2 style sheet.
*
*The simpler way to parse an in memory css2 buffer.
*
*Returns CR_OK upon successfull completion, an error code otherwise.
*/
enum CRStatus
cr_om_parser_simply_parse_buf (const guchar * a_buf,
gulong a_len,
enum CREncoding a_enc,
CRStyleSheet ** a_result)
{
CROMParser *parser = NULL;
enum CRStatus status = CR_OK;
parser = cr_om_parser_new (NULL);
if (!parser) {
cr_utils_trace_info ("Could not create om parser");
cr_utils_trace_info ("System possibly out of memory");
return CR_ERROR;
}
status = cr_om_parser_parse_buf (parser, a_buf, a_len,
a_enc, a_result);
if (parser) {
cr_om_parser_destroy (parser);
parser = NULL;
}
return status;
}
/**
* cr_om_parser_parse_file:
*@a_this: the current instance of the cssom parser.
*@a_file_uri: the uri of the file.
*(only local file paths are suppported so far)
*@a_enc: the encoding of the file.
*@a_result: out parameter. A pointer
*the build css object model.
*
*Parses a css2 stylesheet contained
*in a file.
*
* Returns CR_OK upon succesful completion, an error code otherwise.
*/
enum CRStatus
cr_om_parser_parse_file (CROMParser * a_this,
const guchar * a_file_uri,
enum CREncoding a_enc, CRStyleSheet ** a_result)
{
enum CRStatus status = CR_OK;
g_return_val_if_fail (a_this && a_file_uri && a_result,
CR_BAD_PARAM_ERROR);
if (!PRIVATE (a_this)->parser) {
PRIVATE (a_this)->parser = cr_parser_new_from_file
(a_file_uri, a_enc);
}
status = cr_parser_parse_file (PRIVATE (a_this)->parser,
a_file_uri, a_enc);
if (status == CR_OK) {
CRStyleSheet *result = NULL;
CRStyleSheet **resultptr = NULL;
CRDocHandler *sac_handler = NULL;
cr_parser_get_sac_handler (PRIVATE (a_this)->parser,
&sac_handler);
g_return_val_if_fail (sac_handler, CR_ERROR);
resultptr = &result;
status = cr_doc_handler_get_result
(sac_handler, (gpointer *) resultptr);
g_return_val_if_fail (status == CR_OK, status);
if (result)
*a_result = result;
}
return status;
}
/**
* cr_om_parser_simply_parse_file:
*@a_file_path: the css2 local file path.
*@a_enc: the file encoding.
*@a_result: out parameter. The returned css stylesheet.
*Must be freed by the caller using cr_stylesheet_destroy.
*
*The simpler method to parse a css2 file.
*
*Returns CR_OK upon successfull completion, an error code otherwise.
*Note that this method uses cr_om_parser_parse_file() so both methods
*have the same return values.
*/
enum CRStatus
cr_om_parser_simply_parse_file (const guchar * a_file_path,
enum CREncoding a_enc,
CRStyleSheet ** a_result)
{
CROMParser *parser = NULL;
enum CRStatus status = CR_OK;
parser = cr_om_parser_new (NULL);
if (!parser) {
cr_utils_trace_info ("Could not allocate om parser");
cr_utils_trace_info ("System may be out of memory");
return CR_ERROR;
}
status = cr_om_parser_parse_file (parser, a_file_path,
a_enc, a_result);
if (parser) {
cr_om_parser_destroy (parser);
parser = NULL;
}
return status;
}
/**
* cr_om_parser_parse_paths_to_cascade:
*@a_this: the current instance of #CROMParser
*@a_author_path: the path to the author stylesheet
*@a_user_path: the path to the user stylesheet
*@a_ua_path: the path to the User Agent stylesheet
*@a_encoding: the encoding of the sheets.
*@a_result: out parameter. The resulting cascade if the parsing
*was okay
*
*Parses three sheets located by their paths and build a cascade
*
*Returns CR_OK upon successful completion, an error code otherwise
*/
enum CRStatus
cr_om_parser_parse_paths_to_cascade (CROMParser * a_this,
const guchar * a_author_path,
const guchar * a_user_path,
const guchar * a_ua_path,
enum CREncoding a_encoding,
CRCascade ** a_result)
{
enum CRStatus status = CR_OK;
/*0->author sheet, 1->user sheet, 2->UA sheet */
CRStyleSheet *sheets[3];
guchar *paths[3];
CRCascade *result = NULL;
gint i = 0;
g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
memset (sheets, 0, sizeof (CRStyleSheet*) * 3);
paths[0] = (guchar *) a_author_path;
paths[1] = (guchar *) a_user_path;
paths[2] = (guchar *) a_ua_path;
for (i = 0; i < 3; i++) {
status = cr_om_parser_parse_file (a_this, paths[i],
a_encoding, &sheets[i]);
if (status != CR_OK) {
if (sheets[i]) {
cr_stylesheet_unref (sheets[i]);
sheets[i] = NULL;
}
continue;
}
}
result = cr_cascade_new (sheets[0], sheets[1], sheets[2]);
if (!result) {
for (i = 0; i < 3; i++) {
cr_stylesheet_unref (sheets[i]);
sheets[i] = 0;
}
return CR_ERROR;
}
*a_result = result;
return CR_OK;
}
/**
* cr_om_parser_simply_parse_paths_to_cascade:
*@a_author_path: the path to the author stylesheet
*@a_user_path: the path to the user stylesheet
*@a_ua_path: the path to the User Agent stylesheet
*@a_encoding: the encoding of the sheets.
*@a_result: out parameter. The resulting cascade if the parsing
*was okay
*
*Parses three sheets located by their paths and build a cascade
*
*Returns CR_OK upon successful completion, an error code otherwise
*/
enum CRStatus
cr_om_parser_simply_parse_paths_to_cascade (const guchar * a_author_path,
const guchar * a_user_path,
const guchar * a_ua_path,
enum CREncoding a_encoding,
CRCascade ** a_result)
{
enum CRStatus status = CR_OK;
CROMParser *parser = NULL;
parser = cr_om_parser_new (NULL);
if (!parser) {
cr_utils_trace_info ("could not allocated om parser");
cr_utils_trace_info ("System may be out of memory");
return CR_ERROR;
}
status = cr_om_parser_parse_paths_to_cascade (parser,
a_author_path,
a_user_path,
a_ua_path,
a_encoding, a_result);
if (parser) {
cr_om_parser_destroy (parser);
parser = NULL;
}
return status;
}
/**
* cr_om_parser_destroy:
*@a_this: the current instance of #CROMParser.
*
*Destructor of the #CROMParser.
*/
void
cr_om_parser_destroy (CROMParser * a_this)
{
g_return_if_fail (a_this && PRIVATE (a_this));
if (PRIVATE (a_this)->parser) {
cr_parser_destroy (PRIVATE (a_this)->parser);
PRIVATE (a_this)->parser = NULL;
}
if (PRIVATE (a_this)) {
g_free (PRIVATE (a_this));
PRIVATE (a_this) = NULL;
}
if (a_this) {
g_free (a_this);
a_this = NULL;
}
}