791 lines
23 KiB
C
791 lines
23 KiB
C
![]() |
/* -*- 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 <stdio.h>
|
||
|
#include <string.h>
|
||
|
#include "cr-term.h"
|
||
|
#include "cr-num.h"
|
||
|
#include "cr-parser.h"
|
||
|
|
||
|
/**
|
||
|
*@file
|
||
|
*Definition of the #CRTem class.
|
||
|
*/
|
||
|
|
||
|
static void
|
||
|
cr_term_clear (CRTerm * a_this)
|
||
|
{
|
||
|
g_return_if_fail (a_this);
|
||
|
|
||
|
switch (a_this->type) {
|
||
|
case TERM_NUMBER:
|
||
|
if (a_this->content.num) {
|
||
|
cr_num_destroy (a_this->content.num);
|
||
|
a_this->content.num = NULL;
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case TERM_FUNCTION:
|
||
|
if (a_this->ext_content.func_param) {
|
||
|
cr_term_destroy (a_this->ext_content.func_param);
|
||
|
a_this->ext_content.func_param = NULL;
|
||
|
}
|
||
|
case TERM_STRING:
|
||
|
case TERM_IDENT:
|
||
|
case TERM_URI:
|
||
|
case TERM_HASH:
|
||
|
if (a_this->content.str) {
|
||
|
cr_string_destroy (a_this->content.str);
|
||
|
a_this->content.str = NULL;
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case TERM_RGB:
|
||
|
if (a_this->content.rgb) {
|
||
|
cr_rgb_destroy (a_this->content.rgb);
|
||
|
a_this->content.rgb = NULL;
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case TERM_UNICODERANGE:
|
||
|
case TERM_NO_TYPE:
|
||
|
default:
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
a_this->type = TERM_NO_TYPE;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
*Instanciate a #CRTerm.
|
||
|
*@return the newly build instance
|
||
|
*of #CRTerm.
|
||
|
*/
|
||
|
CRTerm *
|
||
|
cr_term_new (void)
|
||
|
{
|
||
|
CRTerm *result = NULL;
|
||
|
|
||
|
result = g_try_malloc (sizeof (CRTerm));
|
||
|
if (!result) {
|
||
|
cr_utils_trace_info ("Out of memory");
|
||
|
return NULL;
|
||
|
}
|
||
|
memset (result, 0, sizeof (CRTerm));
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
*Parses an expresion as defined by the css2 spec
|
||
|
*and builds the expression as a list of terms.
|
||
|
*@param a_buf the buffer to parse.
|
||
|
*@return a pointer to the first term of the expression or
|
||
|
*NULL if parsing failed.
|
||
|
*/
|
||
|
CRTerm *
|
||
|
cr_term_parse_expression_from_buf (const guchar * a_buf,
|
||
|
enum CREncoding a_encoding)
|
||
|
{
|
||
|
CRParser *parser = NULL;
|
||
|
CRTerm *result = NULL;
|
||
|
enum CRStatus status = CR_OK;
|
||
|
|
||
|
g_return_val_if_fail (a_buf, NULL);
|
||
|
|
||
|
parser = cr_parser_new_from_buf ((guchar*)a_buf, strlen ((const char *) a_buf),
|
||
|
a_encoding, 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_expr (parser, &result);
|
||
|
if (status != CR_OK) {
|
||
|
if (result) {
|
||
|
cr_term_destroy (result);
|
||
|
result = NULL;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
cleanup:
|
||
|
if (parser) {
|
||
|
cr_parser_destroy (parser);
|
||
|
parser = NULL;
|
||
|
}
|
||
|
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
enum CRStatus
|
||
|
cr_term_set_number (CRTerm * a_this, CRNum * a_num)
|
||
|
{
|
||
|
g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
|
||
|
|
||
|
cr_term_clear (a_this);
|
||
|
|
||
|
a_this->type = TERM_NUMBER;
|
||
|
a_this->content.num = a_num;
|
||
|
return CR_OK;
|
||
|
}
|
||
|
|
||
|
enum CRStatus
|
||
|
cr_term_set_function (CRTerm * a_this, CRString * a_func_name,
|
||
|
CRTerm * a_func_param)
|
||
|
{
|
||
|
g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
|
||
|
|
||
|
cr_term_clear (a_this);
|
||
|
|
||
|
a_this->type = TERM_FUNCTION;
|
||
|
a_this->content.str = a_func_name;
|
||
|
a_this->ext_content.func_param = a_func_param;
|
||
|
return CR_OK;
|
||
|
}
|
||
|
|
||
|
enum CRStatus
|
||
|
cr_term_set_string (CRTerm * a_this, CRString * a_str)
|
||
|
{
|
||
|
g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
|
||
|
|
||
|
cr_term_clear (a_this);
|
||
|
|
||
|
a_this->type = TERM_STRING;
|
||
|
a_this->content.str = a_str;
|
||
|
return CR_OK;
|
||
|
}
|
||
|
|
||
|
enum CRStatus
|
||
|
cr_term_set_ident (CRTerm * a_this, CRString * a_str)
|
||
|
{
|
||
|
g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
|
||
|
|
||
|
cr_term_clear (a_this);
|
||
|
|
||
|
a_this->type = TERM_IDENT;
|
||
|
a_this->content.str = a_str;
|
||
|
return CR_OK;
|
||
|
}
|
||
|
|
||
|
enum CRStatus
|
||
|
cr_term_set_uri (CRTerm * a_this, CRString * a_str)
|
||
|
{
|
||
|
g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
|
||
|
|
||
|
cr_term_clear (a_this);
|
||
|
|
||
|
a_this->type = TERM_URI;
|
||
|
a_this->content.str = a_str;
|
||
|
return CR_OK;
|
||
|
}
|
||
|
|
||
|
enum CRStatus
|
||
|
cr_term_set_rgb (CRTerm * a_this, CRRgb * a_rgb)
|
||
|
{
|
||
|
g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
|
||
|
|
||
|
cr_term_clear (a_this);
|
||
|
|
||
|
a_this->type = TERM_RGB;
|
||
|
a_this->content.rgb = a_rgb;
|
||
|
return CR_OK;
|
||
|
}
|
||
|
|
||
|
enum CRStatus
|
||
|
cr_term_set_hash (CRTerm * a_this, CRString * a_str)
|
||
|
{
|
||
|
g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
|
||
|
|
||
|
cr_term_clear (a_this);
|
||
|
|
||
|
a_this->type = TERM_HASH;
|
||
|
a_this->content.str = a_str;
|
||
|
return CR_OK;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
*Appends a new term to the current list of #CRTerm.
|
||
|
*
|
||
|
*@param a_this the "this pointer" of the current instance
|
||
|
*of #CRTerm .
|
||
|
*@param a_new_term the term to append.
|
||
|
*@return the list of terms with the a_new_term appended to it.
|
||
|
*/
|
||
|
CRTerm *
|
||
|
cr_term_append_term (CRTerm * a_this, CRTerm * a_new_term)
|
||
|
{
|
||
|
CRTerm *cur = NULL;
|
||
|
|
||
|
g_return_val_if_fail (a_new_term, NULL);
|
||
|
|
||
|
if (a_this == NULL)
|
||
|
return a_new_term;
|
||
|
|
||
|
for (cur = a_this; cur->next; cur = cur->next) ;
|
||
|
|
||
|
cur->next = a_new_term;
|
||
|
a_new_term->prev = cur;
|
||
|
|
||
|
return a_this;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
*Prepends a term to the list of terms represented by a_this.
|
||
|
*
|
||
|
*@param a_this the "this pointer" of the current instance of
|
||
|
*#CRTerm .
|
||
|
*@param a_new_term the term to prepend.
|
||
|
*@return the head of the new list.
|
||
|
*/
|
||
|
CRTerm *
|
||
|
cr_term_prepend_term (CRTerm * a_this, CRTerm * a_new_term)
|
||
|
{
|
||
|
g_return_val_if_fail (a_this && a_new_term, NULL);
|
||
|
|
||
|
a_new_term->next = a_this;
|
||
|
a_this->prev = a_new_term;
|
||
|
|
||
|
return a_new_term;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
*Serializes the expression represented by
|
||
|
*the chained instances of #CRterm.
|
||
|
*@param a_this the current instance of #CRTerm
|
||
|
*@return the zero terminated string containing the serialized
|
||
|
*form of #CRTerm. MUST BE FREED BY THE CALLER using g_free().
|
||
|
*/
|
||
|
guchar *
|
||
|
cr_term_to_string (CRTerm const * a_this)
|
||
|
{
|
||
|
GString *str_buf = NULL;
|
||
|
CRTerm const *cur = NULL;
|
||
|
guchar *result = NULL,
|
||
|
*content = NULL;
|
||
|
|
||
|
g_return_val_if_fail (a_this, NULL);
|
||
|
|
||
|
str_buf = g_string_new (NULL);
|
||
|
g_return_val_if_fail (str_buf, NULL);
|
||
|
|
||
|
for (cur = a_this; cur; cur = cur->next) {
|
||
|
if ((cur->content.str == NULL)
|
||
|
&& (cur->content.num == NULL)
|
||
|
&& (cur->content.str == NULL)
|
||
|
&& (cur->content.rgb == NULL))
|
||
|
continue;
|
||
|
|
||
|
switch (cur->the_operator) {
|
||
|
case DIVIDE:
|
||
|
g_string_append (str_buf, " / ");
|
||
|
break;
|
||
|
|
||
|
case COMMA:
|
||
|
g_string_append (str_buf, ", ");
|
||
|
break;
|
||
|
|
||
|
case NO_OP:
|
||
|
if (cur->prev) {
|
||
|
g_string_append (str_buf, " ");
|
||
|
}
|
||
|
break;
|
||
|
default:
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
switch (cur->unary_op) {
|
||
|
case PLUS_UOP:
|
||
|
g_string_append (str_buf, "+");
|
||
|
break;
|
||
|
|
||
|
case MINUS_UOP:
|
||
|
g_string_append (str_buf, "-");
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
switch (cur->type) {
|
||
|
case TERM_NUMBER:
|
||
|
if (cur->content.num) {
|
||
|
content = cr_num_to_string (cur->content.num);
|
||
|
}
|
||
|
|
||
|
if (content) {
|
||
|
g_string_append (str_buf, (const gchar *) content);
|
||
|
g_free (content);
|
||
|
content = NULL;
|
||
|
}
|
||
|
|
||
|
break;
|
||
|
|
||
|
case TERM_FUNCTION:
|
||
|
if (cur->content.str) {
|
||
|
content = (guchar *) g_strndup
|
||
|
(cur->content.str->stryng->str,
|
||
|
cur->content.str->stryng->len);
|
||
|
}
|
||
|
|
||
|
if (content) {
|
||
|
g_string_append_printf (str_buf, "%s(",
|
||
|
content);
|
||
|
|
||
|
if (cur->ext_content.func_param) {
|
||
|
guchar *tmp_str = NULL;
|
||
|
|
||
|
tmp_str = cr_term_to_string
|
||
|
(cur->
|
||
|
ext_content.func_param);
|
||
|
|
||
|
if (tmp_str) {
|
||
|
g_string_append (str_buf,
|
||
|
(const gchar *) tmp_str);
|
||
|
g_free (tmp_str);
|
||
|
tmp_str = NULL;
|
||
|
}
|
||
|
}
|
||
|
g_string_append (str_buf, ")");
|
||
|
g_free (content);
|
||
|
content = NULL;
|
||
|
}
|
||
|
|
||
|
break;
|
||
|
|
||
|
case TERM_STRING:
|
||
|
if (cur->content.str) {
|
||
|
content = (guchar *) g_strndup
|
||
|
(cur->content.str->stryng->str,
|
||
|
cur->content.str->stryng->len);
|
||
|
}
|
||
|
|
||
|
if (content) {
|
||
|
g_string_append_printf (str_buf,
|
||
|
"\"%s\"", content);
|
||
|
g_free (content);
|
||
|
content = NULL;
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case TERM_IDENT:
|
||
|
if (cur->content.str) {
|
||
|
content = (guchar *) g_strndup
|
||
|
(cur->content.str->stryng->str,
|
||
|
cur->content.str->stryng->len);
|
||
|
}
|
||
|
|
||
|
if (content) {
|
||
|
g_string_append (str_buf, (const gchar *) content);
|
||
|
g_free (content);
|
||
|
content = NULL;
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case TERM_URI:
|
||
|
if (cur->content.str) {
|
||
|
content = (guchar *) g_strndup
|
||
|
(cur->content.str->stryng->str,
|
||
|
cur->content.str->stryng->len);
|
||
|
}
|
||
|
|
||
|
if (content) {
|
||
|
g_string_append_printf
|
||
|
(str_buf, "url(%s)", content);
|
||
|
g_free (content);
|
||
|
content = NULL;
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case TERM_RGB:
|
||
|
if (cur->content.rgb) {
|
||
|
guchar *tmp_str = NULL;
|
||
|
|
||
|
g_string_append (str_buf, "rgb(");
|
||
|
tmp_str = cr_rgb_to_string (cur->content.rgb);
|
||
|
|
||
|
if (tmp_str) {
|
||
|
g_string_append (str_buf, (const gchar *) tmp_str);
|
||
|
g_free (tmp_str);
|
||
|
tmp_str = NULL;
|
||
|
}
|
||
|
g_string_append (str_buf, ")");
|
||
|
}
|
||
|
|
||
|
break;
|
||
|
|
||
|
case TERM_UNICODERANGE:
|
||
|
g_string_append
|
||
|
(str_buf,
|
||
|
"?found unicoderange: dump not supported yet?");
|
||
|
break;
|
||
|
|
||
|
case TERM_HASH:
|
||
|
if (cur->content.str) {
|
||
|
content = (guchar *) g_strndup
|
||
|
(cur->content.str->stryng->str,
|
||
|
cur->content.str->stryng->len);
|
||
|
}
|
||
|
|
||
|
if (content) {
|
||
|
g_string_append_printf (str_buf,
|
||
|
"#%s", content);
|
||
|
g_free (content);
|
||
|
content = NULL;
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
g_string_append (str_buf,
|
||
|
"Unrecognized Term type");
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (str_buf) {
|
||
|
result =(guchar *) str_buf->str;
|
||
|
g_string_free (str_buf, FALSE);
|
||
|
str_buf = NULL;
|
||
|
}
|
||
|
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
guchar *
|
||
|
cr_term_one_to_string (CRTerm const * a_this)
|
||
|
{
|
||
|
GString *str_buf = NULL;
|
||
|
guchar *result = NULL,
|
||
|
*content = NULL;
|
||
|
|
||
|
g_return_val_if_fail (a_this, NULL);
|
||
|
|
||
|
str_buf = g_string_new (NULL);
|
||
|
g_return_val_if_fail (str_buf, NULL);
|
||
|
|
||
|
if ((a_this->content.str == NULL)
|
||
|
&& (a_this->content.num == NULL)
|
||
|
&& (a_this->content.str == NULL)
|
||
|
&& (a_this->content.rgb == NULL))
|
||
|
return NULL ;
|
||
|
|
||
|
switch (a_this->the_operator) {
|
||
|
case DIVIDE:
|
||
|
g_string_append_printf (str_buf, " / ");
|
||
|
break;
|
||
|
|
||
|
case COMMA:
|
||
|
g_string_append_printf (str_buf, ", ");
|
||
|
break;
|
||
|
|
||
|
case NO_OP:
|
||
|
if (a_this->prev) {
|
||
|
g_string_append_printf (str_buf, " ");
|
||
|
}
|
||
|
break;
|
||
|
default:
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
switch (a_this->unary_op) {
|
||
|
case PLUS_UOP:
|
||
|
g_string_append_printf (str_buf, "+");
|
||
|
break;
|
||
|
|
||
|
case MINUS_UOP:
|
||
|
g_string_append_printf (str_buf, "-");
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
switch (a_this->type) {
|
||
|
case TERM_NUMBER:
|
||
|
if (a_this->content.num) {
|
||
|
content = cr_num_to_string (a_this->content.num);
|
||
|
}
|
||
|
|
||
|
if (content) {
|
||
|
g_string_append (str_buf, (const gchar *) content);
|
||
|
g_free (content);
|
||
|
content = NULL;
|
||
|
}
|
||
|
|
||
|
break;
|
||
|
|
||
|
case TERM_FUNCTION:
|
||
|
if (a_this->content.str) {
|
||
|
content = (guchar *) g_strndup
|
||
|
(a_this->content.str->stryng->str,
|
||
|
a_this->content.str->stryng->len);
|
||
|
}
|
||
|
|
||
|
if (content) {
|
||
|
g_string_append_printf (str_buf, "%s(",
|
||
|
content);
|
||
|
|
||
|
if (a_this->ext_content.func_param) {
|
||
|
guchar *tmp_str = NULL;
|
||
|
|
||
|
tmp_str = cr_term_to_string
|
||
|
(a_this->
|
||
|
ext_content.func_param);
|
||
|
|
||
|
if (tmp_str) {
|
||
|
g_string_append_printf
|
||
|
(str_buf,
|
||
|
"%s", tmp_str);
|
||
|
g_free (tmp_str);
|
||
|
tmp_str = NULL;
|
||
|
}
|
||
|
|
||
|
g_string_append_printf (str_buf, ")");
|
||
|
g_free (content);
|
||
|
content = NULL;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
break;
|
||
|
|
||
|
case TERM_STRING:
|
||
|
if (a_this->content.str) {
|
||
|
content = (guchar *) g_strndup
|
||
|
(a_this->content.str->stryng->str,
|
||
|
a_this->content.str->stryng->len);
|
||
|
}
|
||
|
|
||
|
if (content) {
|
||
|
g_string_append_printf (str_buf,
|
||
|
"\"%s\"", content);
|
||
|
g_free (content);
|
||
|
content = NULL;
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case TERM_IDENT:
|
||
|
if (a_this->content.str) {
|
||
|
content = (guchar *) g_strndup
|
||
|
(a_this->content.str->stryng->str,
|
||
|
a_this->content.str->stryng->len);
|
||
|
}
|
||
|
|
||
|
if (content) {
|
||
|
g_string_append (str_buf, (const gchar *) content);
|
||
|
g_free (content);
|
||
|
content = NULL;
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case TERM_URI:
|
||
|
if (a_this->content.str) {
|
||
|
content = (guchar *) g_strndup
|
||
|
(a_this->content.str->stryng->str,
|
||
|
a_this->content.str->stryng->len);
|
||
|
}
|
||
|
|
||
|
if (content) {
|
||
|
g_string_append_printf
|
||
|
(str_buf, "url(%s)", content);
|
||
|
g_free (content);
|
||
|
content = NULL;
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case TERM_RGB:
|
||
|
if (a_this->content.rgb) {
|
||
|
guchar *tmp_str = NULL;
|
||
|
|
||
|
g_string_append_printf (str_buf, "rgb(");
|
||
|
tmp_str = cr_rgb_to_string (a_this->content.rgb);
|
||
|
|
||
|
if (tmp_str) {
|
||
|
g_string_append (str_buf, (const gchar *) tmp_str);
|
||
|
g_free (tmp_str);
|
||
|
tmp_str = NULL;
|
||
|
}
|
||
|
g_string_append_printf (str_buf, ")");
|
||
|
}
|
||
|
|
||
|
break;
|
||
|
|
||
|
case TERM_UNICODERANGE:
|
||
|
g_string_append_printf
|
||
|
(str_buf,
|
||
|
"?found unicoderange: dump not supported yet?");
|
||
|
break;
|
||
|
|
||
|
case TERM_HASH:
|
||
|
if (a_this->content.str) {
|
||
|
content = (guchar *) g_strndup
|
||
|
(a_this->content.str->stryng->str,
|
||
|
a_this->content.str->stryng->len);
|
||
|
}
|
||
|
|
||
|
if (content) {
|
||
|
g_string_append_printf (str_buf,
|
||
|
"#%s", content);
|
||
|
g_free (content);
|
||
|
content = NULL;
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
g_string_append_printf (str_buf,
|
||
|
"%s",
|
||
|
"Unrecognized Term type");
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
if (str_buf) {
|
||
|
result = (guchar *) str_buf->str;
|
||
|
g_string_free (str_buf, FALSE);
|
||
|
str_buf = NULL;
|
||
|
}
|
||
|
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
*Dumps the expression (a list of terms connected by operators)
|
||
|
*to a file.
|
||
|
*TODO: finish the dump. The dump of some type of terms have not yet been
|
||
|
*implemented.
|
||
|
*@param a_this the current instance of #CRTerm.
|
||
|
*@param a_fp the destination file pointer.
|
||
|
*/
|
||
|
void
|
||
|
cr_term_dump (CRTerm const * a_this, FILE * a_fp)
|
||
|
{
|
||
|
guchar *content = NULL;
|
||
|
|
||
|
g_return_if_fail (a_this);
|
||
|
|
||
|
content = cr_term_to_string (a_this);
|
||
|
|
||
|
if (content) {
|
||
|
fprintf (a_fp, "%s", content);
|
||
|
g_free (content);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
*Return the number of terms in the expression.
|
||
|
*@param a_this the current instance of #CRTerm.
|
||
|
*@return number of terms in the expression.
|
||
|
*/
|
||
|
int
|
||
|
cr_term_nr_values (CRTerm const *a_this)
|
||
|
{
|
||
|
CRTerm 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;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
*Use an index to get a CRTerm from the expression.
|
||
|
*@param a_this the current instance of #CRTerm.
|
||
|
*@param itemnr the index into the expression.
|
||
|
*@return CRTerm at position itemnr, if itemnr > number of terms - 1,
|
||
|
*it will return NULL.
|
||
|
*/
|
||
|
CRTerm *
|
||
|
cr_term_get_from_list (CRTerm *a_this, int itemnr)
|
||
|
{
|
||
|
CRTerm *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;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
*Increments the reference counter of the current instance
|
||
|
*of #CRTerm.*
|
||
|
*@param a_this the current instance of #CRTerm.
|
||
|
*/
|
||
|
void
|
||
|
cr_term_ref (CRTerm * a_this)
|
||
|
{
|
||
|
g_return_if_fail (a_this);
|
||
|
|
||
|
a_this->ref_count++;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
*Decrements the ref count of the current instance of
|
||
|
*#CRTerm. If the ref count reaches zero, the instance is
|
||
|
*destroyed.
|
||
|
*@param a_this the current instance of #CRTerm.
|
||
|
*@return TRUE if the current instance has been destroyed, FALSE otherwise.
|
||
|
*/
|
||
|
gboolean
|
||
|
cr_term_unref (CRTerm * 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_term_destroy (a_this);
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
*The destructor of the the #CRTerm class.
|
||
|
*@param a_this the "this pointer" of the current instance
|
||
|
*of #CRTerm.
|
||
|
*/
|
||
|
void
|
||
|
cr_term_destroy (CRTerm * a_this)
|
||
|
{
|
||
|
g_return_if_fail (a_this);
|
||
|
|
||
|
cr_term_clear (a_this);
|
||
|
|
||
|
if (a_this->next) {
|
||
|
cr_term_destroy (a_this->next);
|
||
|
a_this->next = NULL;
|
||
|
}
|
||
|
|
||
|
if (a_this) {
|
||
|
g_free (a_this);
|
||
|
}
|
||
|
|
||
|
}
|