/* -*- 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 * * See COPYRIGHTS file for copyright information. */ #include #include "cr-selector.h" #include "cr-parser.h" /** * cr_selector_new: * *@a_simple_sel: the initial simple selector list *of the current instance of #CRSelector. * *Creates a new instance of #CRSelector. * *Returns the newly built instance of #CRSelector, or *NULL in case of failure. */ CRSelector * cr_selector_new (CRSimpleSel * a_simple_sel) { CRSelector *result = NULL; result = g_try_malloc (sizeof (CRSelector)); if (!result) { cr_utils_trace_info ("Out of memory"); return NULL; } memset (result, 0, sizeof (CRSelector)); result->simple_sel = a_simple_sel; return result; } CRSelector * cr_selector_parse_from_buf (const guchar * a_char_buf, enum CREncoding a_enc) { CRParser *parser = NULL; g_return_val_if_fail (a_char_buf, NULL); parser = cr_parser_new_from_buf ((guchar*)a_char_buf, strlen (a_char_buf), a_enc, FALSE); g_return_val_if_fail (parser, NULL); return NULL; } /** * cr_selector_append: * *@a_this: the current instance of #CRSelector. *@a_new: the instance of #CRSelector to be appended. * *Appends a new instance of #CRSelector to the current selector list. * *Returns the new list. */ CRSelector * cr_selector_append (CRSelector * a_this, CRSelector * a_new) { CRSelector *cur = NULL; if (!a_this) { return a_new; } /*walk forward the list headed by a_this to get the list tail */ for (cur = a_this; cur && cur->next; cur = cur->next) ; cur->next = a_new; a_new->prev = cur; return a_this; } /** * cr_selector_prepend: * *@a_this: the current instance of #CRSelector list. *@a_new: the instance of #CRSelector. * *Prepends an element to the #CRSelector list. * *Returns the new list. */ CRSelector * cr_selector_prepend (CRSelector * a_this, CRSelector * a_new) { CRSelector *cur = NULL; a_new->next = a_this; a_this->prev = a_new; for (cur = a_new; cur && cur->prev; cur = cur->prev) ; return cur; } /** * cr_selector_append_simple_sel: * *@a_this: the current instance of #CRSelector. *@a_simple_sel: the simple selector to append. * *append a simple selector to the current #CRSelector list. * *Returns the new list or NULL in case of failure. */ CRSelector * cr_selector_append_simple_sel (CRSelector * a_this, CRSimpleSel * a_simple_sel) { CRSelector *selector = NULL; selector = cr_selector_new (a_simple_sel); g_return_val_if_fail (selector, NULL); return cr_selector_append (a_this, selector); } guchar * cr_selector_to_string (CRSelector const * a_this) { guchar *result = NULL; GString *str_buf = NULL; str_buf = g_string_new (NULL); g_return_val_if_fail (str_buf, NULL); if (a_this) { CRSelector const *cur = NULL; for (cur = a_this; cur; cur = cur->next) { if (cur->simple_sel) { guchar *tmp_str = NULL; tmp_str = cr_simple_sel_to_string (cur->simple_sel); if (tmp_str) { if (cur->prev) g_string_append (str_buf, ", "); g_string_append (str_buf, tmp_str); g_free (tmp_str); tmp_str = NULL; } } } } if (str_buf) { result = str_buf->str; g_string_free (str_buf, FALSE); str_buf = NULL; } return result; } /** * cr_selector_dump: * *@a_this: the current instance of #CRSelector. *@a_fp: the destination file. * *Serializes the current instance of #CRSelector to a file. */ void cr_selector_dump (CRSelector const * a_this, FILE * a_fp) { guchar *tmp_buf = NULL; if (a_this) { tmp_buf = cr_selector_to_string (a_this); if (tmp_buf) { fprintf (a_fp, "%s", tmp_buf); g_free (tmp_buf); tmp_buf = NULL; } } } /** * cr_selector_ref: * *@a_this: the current instance of #CRSelector. * *Increments the ref count of the current instance *of #CRSelector. */ void cr_selector_ref (CRSelector * a_this) { g_return_if_fail (a_this); a_this->ref_count++; } /** * cr_selector_unref: * *@a_this: the current instance of #CRSelector. * *Decrements the ref count of the current instance of *#CRSelector. *If the ref count reaches zero, the current instance of *#CRSelector is destroyed. * *Returns TRUE if this function destroyed the current instance *of #CRSelector, FALSE otherwise. */ gboolean cr_selector_unref (CRSelector * 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_selector_destroy (a_this); return TRUE; } return FALSE; } /** * cr_selector_destroy: * *@a_this: the current instance of #CRSelector. * *Destroys the selector list. */ void cr_selector_destroy (CRSelector * a_this) { CRSelector *cur = NULL; g_return_if_fail (a_this); /* *go and get the list tail. In the same time, free *all the simple selectors contained in the list. */ for (cur = a_this; cur && cur->next; cur = cur->next) { if (cur->simple_sel) { cr_simple_sel_destroy (cur->simple_sel); cur->simple_sel = NULL; } } if (cur) { if (cur->simple_sel) { cr_simple_sel_destroy (cur->simple_sel); cur->simple_sel = NULL; } } /*in case the list has only one element */ if (cur && !cur->prev) { g_free (cur); return; } /*walk backward the list and free each "next element" */ for (cur = cur->prev; cur && cur->prev; cur = cur->prev) { if (cur->next) { g_free (cur->next); cur->next = NULL; } } if (!cur) return; if (cur->next) { g_free (cur->next); cur->next = NULL; } g_free (cur); }