facf0c92e0
Red Bear OS is a full fork. All sources must be available from git clone with zero network access. Removed gitignore rules that excluded fetched source trees under recipes/*/source/, local/recipes/kde/*/source/, local/recipes/qt/*/source/, and vendor source trees. Build artifacts (target/, build/, source.tar, *.o, *.so) remain excluded. 127291 files added — kernel, relibc, base, bootloader, pkgar, all KDE/Qt frameworks, mesa, wayland, DRM drivers, and every other recipe source.
812 lines
24 KiB
C
812 lines
24 KiB
C
/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
|
|
|
|
/* libcroco - Library for parsing and applying CSS
|
|
* Copyright (C) 2006-2019 Free Software Foundation, Inc.
|
|
*
|
|
* This file is not part of the GNU gettext program, but is used with
|
|
* GNU gettext.
|
|
*
|
|
* The original copyright notice is as follows:
|
|
*/
|
|
|
|
/*
|
|
* This file is part of The Croco Library
|
|
*
|
|
* Copyright (C) 2003-2004 Dodji Seketeli. All Rights Reserved.
|
|
*
|
|
* 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.
|
|
*/
|
|
|
|
#include <config.h>
|
|
#include <string.h>
|
|
#include "cr-declaration.h"
|
|
#include "cr-statement.h"
|
|
#include "cr-parser.h"
|
|
|
|
/**
|
|
*@CRDeclaration:
|
|
*
|
|
*The definition of the #CRDeclaration class.
|
|
*/
|
|
|
|
/**
|
|
* dump:
|
|
*@a_this: the current instance of #CRDeclaration.
|
|
*@a_fp: the destination file pointer.
|
|
*@a_indent: the number of indentation white char.
|
|
*
|
|
*Dumps (serializes) one css declaration to a file.
|
|
*/
|
|
static void
|
|
dump (CRDeclaration const * a_this, FILE * a_fp, glong a_indent)
|
|
{
|
|
guchar *str = NULL;
|
|
|
|
g_return_if_fail (a_this);
|
|
|
|
str = (guchar *) cr_declaration_to_string (a_this, a_indent);
|
|
if (str) {
|
|
fprintf (a_fp, "%s", str);
|
|
g_free (str);
|
|
str = NULL;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* cr_declaration_new:
|
|
* @a_statement: the statement this declaration belongs to. can be NULL.
|
|
*@a_property: the property string of the declaration
|
|
*@a_value: the value expression of the declaration.
|
|
*Constructor of #CRDeclaration.
|
|
*
|
|
*Returns the newly built instance of #CRDeclaration, or NULL in
|
|
*case of error.
|
|
*
|
|
*The returned CRDeclaration takes ownership of @a_property and @a_value.
|
|
*(E.g. cr_declaration_destroy on this CRDeclaration will also free
|
|
*@a_property and @a_value.)
|
|
*/
|
|
CRDeclaration *
|
|
cr_declaration_new (CRStatement * a_statement,
|
|
CRString * a_property, CRTerm * a_value)
|
|
{
|
|
CRDeclaration *result = NULL;
|
|
|
|
g_return_val_if_fail (a_property, NULL);
|
|
|
|
if (a_statement)
|
|
g_return_val_if_fail (a_statement
|
|
&& ((a_statement->type == RULESET_STMT)
|
|
|| (a_statement->type
|
|
== AT_FONT_FACE_RULE_STMT)
|
|
|| (a_statement->type
|
|
== AT_PAGE_RULE_STMT)), NULL);
|
|
|
|
result = g_try_malloc (sizeof (CRDeclaration));
|
|
if (!result) {
|
|
cr_utils_trace_info ("Out of memory");
|
|
return NULL;
|
|
}
|
|
memset (result, 0, sizeof (CRDeclaration));
|
|
result->property = a_property;
|
|
result->value = a_value;
|
|
|
|
if (a_value) {
|
|
cr_term_ref (a_value);
|
|
}
|
|
result->parent_statement = a_statement;
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* cr_declaration_parse_from_buf:
|
|
*@a_statement: the parent css2 statement of this
|
|
*this declaration. Must be non NULL and of type
|
|
*RULESET_STMT (must be a ruleset).
|
|
*@a_str: the string that contains the statement.
|
|
*@a_enc: the encoding of a_str.
|
|
*
|
|
*Parses a text buffer that contains
|
|
*a css declaration.
|
|
*Returns 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;
|
|
CRParser *parser = 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);
|
|
|
|
parser = cr_parser_new_from_buf ((guchar*)a_str, strlen ((const 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 ((const 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 {
|
|
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;
|
|
}
|
|
|
|
/**
|
|
* cr_declaration_append:
|
|
*@a_this: the current declaration list.
|
|
*@a_new: the declaration to append.
|
|
*
|
|
*Appends a new declaration to the current declarations list.
|
|
*Returns the declaration list with a_new appended to it, or NULL
|
|
*in case of error.
|
|
*/
|
|
CRDeclaration *
|
|
cr_declaration_append (CRDeclaration * a_this, CRDeclaration * a_new)
|
|
{
|
|
CRDeclaration *cur = NULL;
|
|
|
|
g_return_val_if_fail (a_new, NULL);
|
|
|
|
if (!a_this)
|
|
return a_new;
|
|
|
|
for (cur = a_this; cur && cur->next; cur = cur->next) ;
|
|
|
|
cur->next = a_new;
|
|
a_new->prev = cur;
|
|
|
|
return a_this;
|
|
}
|
|
|
|
/**
|
|
* cr_declaration_unlink:
|
|
*@a_decls: the declaration to unlink.
|
|
*
|
|
*Unlinks the declaration from the declaration list.
|
|
*case of a successfull completion, NULL otherwise.
|
|
*
|
|
*Returns a pointer to the unlinked declaration in
|
|
*/
|
|
CRDeclaration *
|
|
cr_declaration_unlink (CRDeclaration * a_decl)
|
|
{
|
|
CRDeclaration *result = a_decl;
|
|
|
|
g_return_val_if_fail (result, NULL);
|
|
|
|
/*
|
|
*some sanity checks first
|
|
*/
|
|
if (a_decl->prev) {
|
|
g_return_val_if_fail (a_decl->prev->next == a_decl, NULL);
|
|
|
|
}
|
|
if (a_decl->next) {
|
|
g_return_val_if_fail (a_decl->next->prev == a_decl, NULL);
|
|
}
|
|
|
|
/*
|
|
*now, the real unlinking job.
|
|
*/
|
|
if (a_decl->prev) {
|
|
a_decl->prev->next = a_decl->next;
|
|
}
|
|
if (a_decl->next) {
|
|
a_decl->next->prev = a_decl->prev;
|
|
}
|
|
if (a_decl->parent_statement) {
|
|
CRDeclaration **children_decl_ptr = NULL;
|
|
|
|
switch (a_decl->parent_statement->type) {
|
|
case RULESET_STMT:
|
|
if (a_decl->parent_statement->kind.ruleset) {
|
|
children_decl_ptr =
|
|
&a_decl->parent_statement->
|
|
kind.ruleset->decl_list;
|
|
}
|
|
|
|
break;
|
|
|
|
case AT_FONT_FACE_RULE_STMT:
|
|
if (a_decl->parent_statement->kind.font_face_rule) {
|
|
children_decl_ptr =
|
|
&a_decl->parent_statement->
|
|
kind.font_face_rule->decl_list;
|
|
}
|
|
break;
|
|
case AT_PAGE_RULE_STMT:
|
|
if (a_decl->parent_statement->kind.page_rule) {
|
|
children_decl_ptr =
|
|
&a_decl->parent_statement->
|
|
kind.page_rule->decl_list;
|
|
}
|
|
|
|
default:
|
|
break;
|
|
}
|
|
if (children_decl_ptr
|
|
&& *children_decl_ptr && *children_decl_ptr == a_decl)
|
|
*children_decl_ptr = (*children_decl_ptr)->next;
|
|
}
|
|
|
|
a_decl->next = NULL;
|
|
a_decl->prev = NULL;
|
|
a_decl->parent_statement = NULL;
|
|
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* cr_declaration_prepend:
|
|
* @a_this: the current declaration list.
|
|
* @a_new: the declaration to prepend.
|
|
*
|
|
* prepends a declaration to the current declaration list.
|
|
*
|
|
* Returns the list with a_new prepended or NULL in case of error.
|
|
*/
|
|
CRDeclaration *
|
|
cr_declaration_prepend (CRDeclaration * a_this, CRDeclaration * a_new)
|
|
{
|
|
CRDeclaration *cur = NULL;
|
|
|
|
g_return_val_if_fail (a_new, NULL);
|
|
|
|
if (!a_this)
|
|
return a_new;
|
|
|
|
a_this->prev = a_new;
|
|
a_new->next = a_this;
|
|
|
|
for (cur = a_new; cur && cur->prev; cur = cur->prev) ;
|
|
|
|
return cur;
|
|
}
|
|
|
|
/**
|
|
* 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);
|
|
}
|
|
|
|
/**
|
|
* cr_declaration_dump:
|
|
*@a_this: the current instance of #CRDeclaration.
|
|
*@a_fp: the destination file.
|
|
*@a_indent: the number of indentation white char.
|
|
*@a_one_per_line: whether to put one declaration per line of not .
|
|
*
|
|
*
|
|
*Dumps a declaration list to a file.
|
|
*/
|
|
void
|
|
cr_declaration_dump (CRDeclaration const * a_this, FILE * a_fp, glong a_indent,
|
|
gboolean a_one_per_line)
|
|
{
|
|
CRDeclaration const *cur = NULL;
|
|
|
|
g_return_if_fail (a_this);
|
|
|
|
for (cur = a_this; cur; cur = cur->next) {
|
|
if (cur->prev) {
|
|
if (a_one_per_line == TRUE)
|
|
fprintf (a_fp, ";\n");
|
|
else
|
|
fprintf (a_fp, "; ");
|
|
}
|
|
dump (cur, a_fp, a_indent);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* cr_declaration_dump_one:
|
|
*@a_this: the current instance of #CRDeclaration.
|
|
*@a_fp: the destination file.
|
|
*@a_indent: the number of indentation white char.
|
|
*
|
|
*Dumps the first declaration of the declaration list to a file.
|
|
*/
|
|
void
|
|
cr_declaration_dump_one (CRDeclaration const * a_this, FILE * a_fp, glong a_indent)
|
|
{
|
|
g_return_if_fail (a_this);
|
|
|
|
dump (a_this, a_fp, a_indent);
|
|
}
|
|
|
|
/**
|
|
* cr_declaration_to_string:
|
|
*@a_this: the current instance of #CRDeclaration.
|
|
*@a_indent: the number of indentation white char
|
|
*to put before the actual serialisation.
|
|
*
|
|
*Serializes the declaration into a string
|
|
*Returns the serialized form the declaration. The caller must
|
|
*free the string using g_free().
|
|
*/
|
|
gchar *
|
|
cr_declaration_to_string (CRDeclaration const * a_this, gulong a_indent)
|
|
{
|
|
GString *stringue = NULL;
|
|
|
|
gchar *str = NULL,
|
|
*result = NULL;
|
|
|
|
g_return_val_if_fail (a_this, NULL);
|
|
|
|
stringue = g_string_new (NULL);
|
|
|
|
if (a_this->property
|
|
&& a_this->property->stryng
|
|
&& a_this->property->stryng->str) {
|
|
str = g_strndup (a_this->property->stryng->str,
|
|
a_this->property->stryng->len);
|
|
if (str) {
|
|
cr_utils_dump_n_chars2 (' ', stringue,
|
|
a_indent);
|
|
g_string_append (stringue, str);
|
|
g_free (str);
|
|
str = NULL;
|
|
} else
|
|
goto error;
|
|
|
|
if (a_this->value) {
|
|
guchar *value_str = NULL;
|
|
|
|
value_str = cr_term_to_string (a_this->value);
|
|
if (value_str) {
|
|
g_string_append_printf (stringue, " : %s",
|
|
value_str);
|
|
g_free (value_str);
|
|
} else
|
|
goto error;
|
|
}
|
|
if (a_this->important == TRUE) {
|
|
g_string_append_printf (stringue, " %s",
|
|
"!important");
|
|
}
|
|
}
|
|
if (stringue && stringue->str) {
|
|
result = stringue->str;
|
|
g_string_free (stringue, FALSE);
|
|
}
|
|
return result;
|
|
|
|
error:
|
|
if (stringue) {
|
|
g_string_free (stringue, TRUE);
|
|
stringue = NULL;
|
|
}
|
|
if (str) {
|
|
g_free (str);
|
|
str = NULL;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* cr_declaration_list_to_string:
|
|
*@a_this: the current instance of #CRDeclaration.
|
|
*@a_indent: the number of indentation white char
|
|
*to put before the actual serialisation.
|
|
*
|
|
*Serializes the declaration list into a string
|
|
*/
|
|
guchar *
|
|
cr_declaration_list_to_string (CRDeclaration const * a_this, gulong a_indent)
|
|
{
|
|
CRDeclaration const *cur = NULL;
|
|
GString *stringue = NULL;
|
|
guchar *str = NULL,
|
|
*result = NULL;
|
|
|
|
g_return_val_if_fail (a_this, NULL);
|
|
|
|
stringue = g_string_new (NULL);
|
|
|
|
for (cur = a_this; cur; cur = cur->next) {
|
|
str = (guchar *) cr_declaration_to_string (cur, a_indent);
|
|
if (str) {
|
|
g_string_append_printf (stringue, "%s;", str);
|
|
g_free (str);
|
|
} else
|
|
break;
|
|
}
|
|
if (stringue && stringue->str) {
|
|
result = (guchar *) stringue->str;
|
|
g_string_free (stringue, FALSE);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* cr_declaration_list_to_string2:
|
|
*@a_this: the current instance of #CRDeclaration.
|
|
*@a_indent: the number of indentation white char
|
|
*@a_one_decl_per_line: whether to output one doc per line or not.
|
|
*to put before the actual serialisation.
|
|
*
|
|
*Serializes the declaration list into a string
|
|
*Returns the serialized form the declararation.
|
|
*/
|
|
guchar *
|
|
cr_declaration_list_to_string2 (CRDeclaration const * a_this,
|
|
gulong a_indent, gboolean a_one_decl_per_line)
|
|
{
|
|
CRDeclaration const *cur = NULL;
|
|
GString *stringue = NULL;
|
|
guchar *str = NULL,
|
|
*result = NULL;
|
|
|
|
g_return_val_if_fail (a_this, NULL);
|
|
|
|
stringue = g_string_new (NULL);
|
|
|
|
for (cur = a_this; cur; cur = cur->next) {
|
|
str = (guchar *) cr_declaration_to_string (cur, a_indent);
|
|
if (str) {
|
|
if (a_one_decl_per_line == TRUE) {
|
|
if (cur->next)
|
|
g_string_append_printf (stringue,
|
|
"%s;\n", str);
|
|
else
|
|
g_string_append (stringue,
|
|
(const gchar *) str);
|
|
} else {
|
|
if (cur->next)
|
|
g_string_append_printf (stringue,
|
|
"%s;", str);
|
|
else
|
|
g_string_append (stringue,
|
|
(const gchar *) str);
|
|
}
|
|
g_free (str);
|
|
} else
|
|
break;
|
|
}
|
|
if (stringue && stringue->str) {
|
|
result = (guchar *) stringue->str;
|
|
g_string_free (stringue, FALSE);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* cr_declaration_nr_props:
|
|
*@a_this: the current instance of #CRDeclaration.
|
|
*Return the number of properties in the declaration
|
|
*/
|
|
gint
|
|
cr_declaration_nr_props (CRDeclaration const * a_this)
|
|
{
|
|
CRDeclaration const *cur = NULL;
|
|
int nr = 0;
|
|
|
|
g_return_val_if_fail (a_this, -1);
|
|
|
|
for (cur = a_this; cur; cur = cur->next)
|
|
nr++;
|
|
return nr;
|
|
}
|
|
|
|
/**
|
|
* cr_declaration_get_from_list:
|
|
*@a_this: the current instance of #CRDeclaration.
|
|
*@itemnr: the index into the declaration list.
|
|
*
|
|
*Use an index to get a CRDeclaration from the declaration list.
|
|
*
|
|
*Returns #CRDeclaration at position itemnr,
|
|
*if itemnr > number of declarations - 1,
|
|
*it will return NULL.
|
|
*/
|
|
CRDeclaration *
|
|
cr_declaration_get_from_list (CRDeclaration * a_this, int itemnr)
|
|
{
|
|
CRDeclaration *cur = NULL;
|
|
int nr = 0;
|
|
|
|
g_return_val_if_fail (a_this, NULL);
|
|
|
|
for (cur = a_this; cur; cur = cur->next)
|
|
if (nr++ == itemnr)
|
|
return cur;
|
|
return NULL;
|
|
}
|
|
|
|
/**
|
|
* cr_declaration_get_by_prop_name:
|
|
*@a_this: the current instance of #CRDeclaration.
|
|
*@a_prop: the property name to search for.
|
|
*
|
|
*Use property name to get a CRDeclaration from the declaration list.
|
|
*Returns #CRDeclaration with property name a_prop, or NULL if not found.
|
|
*/
|
|
CRDeclaration *
|
|
cr_declaration_get_by_prop_name (CRDeclaration * a_this,
|
|
const guchar * a_prop)
|
|
{
|
|
CRDeclaration *cur = NULL;
|
|
|
|
g_return_val_if_fail (a_this, NULL);
|
|
g_return_val_if_fail (a_prop, NULL);
|
|
|
|
for (cur = a_this; cur; cur = cur->next) {
|
|
if (cur->property
|
|
&& cur->property->stryng
|
|
&& cur->property->stryng->str) {
|
|
if (!strcmp (cur->property->stryng->str,
|
|
(const char *) a_prop)) {
|
|
return cur;
|
|
}
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
/**
|
|
* cr_declaration_ref:
|
|
*@a_this: the current instance of #CRDeclaration.
|
|
*
|
|
*Increases the ref count of the current instance of #CRDeclaration.
|
|
*/
|
|
void
|
|
cr_declaration_ref (CRDeclaration * a_this)
|
|
{
|
|
g_return_if_fail (a_this);
|
|
|
|
a_this->ref_count++;
|
|
}
|
|
|
|
/**
|
|
* cr_declaration_unref:
|
|
*@a_this: the current instance of #CRDeclaration.
|
|
*
|
|
*Decrements the ref count of the current instance of #CRDeclaration.
|
|
*If the ref count reaches zero, the current instance of #CRDeclaration
|
|
*if destroyed.
|
|
*Returns TRUE if @a_this was destroyed (ref count reached zero),
|
|
*FALSE otherwise.
|
|
*/
|
|
gboolean
|
|
cr_declaration_unref (CRDeclaration * a_this)
|
|
{
|
|
g_return_val_if_fail (a_this, FALSE);
|
|
|
|
if (a_this->ref_count) {
|
|
a_this->ref_count--;
|
|
}
|
|
|
|
if (a_this->ref_count == 0) {
|
|
cr_declaration_destroy (a_this);
|
|
return TRUE;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
/**
|
|
* cr_declaration_destroy:
|
|
*@a_this: the current instance of #CRDeclaration.
|
|
*
|
|
*Destructor of the declaration list.
|
|
*/
|
|
void
|
|
cr_declaration_destroy (CRDeclaration * a_this)
|
|
{
|
|
CRDeclaration *cur = NULL;
|
|
|
|
g_return_if_fail (a_this);
|
|
|
|
/*
|
|
* Go to the last element of the list.
|
|
*/
|
|
for (cur = a_this; cur->next; cur = cur->next)
|
|
g_assert (cur->next->prev == cur);
|
|
|
|
/*
|
|
* Walk backward the list and free each "next" element.
|
|
* Meanwhile, free each property/value pair contained in the list.
|
|
*/
|
|
for (; cur; cur = cur->prev) {
|
|
g_free (cur->next);
|
|
cur->next = NULL;
|
|
|
|
if (cur->property) {
|
|
cr_string_destroy (cur->property);
|
|
cur->property = NULL;
|
|
}
|
|
|
|
if (cur->value) {
|
|
cr_term_destroy (cur->value);
|
|
cur->value = NULL;
|
|
}
|
|
}
|
|
|
|
g_free (a_this);
|
|
}
|