LCOV - code coverage report
Current view: top level - libreoffice/workdir/unxlngi6.pro/UnpackedTarball/langtag/liblangtag - lt-list.c (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 43 118 36.4 %
Date: 2012-12-17 Functions: 8 18 44.4 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
       2             : /* 
       3             :  * lt-list.c
       4             :  * Copyright (C) 2011-2012 Akira TAGOH
       5             :  * 
       6             :  * Authors:
       7             :  *   Akira TAGOH  <akira@tagoh.org>
       8             :  * 
       9             :  * You may distribute under the terms of either the GNU
      10             :  * Lesser General Public License or the Mozilla Public
      11             :  * License, as specified in the README file.
      12             :  */
      13             : #ifdef HAVE_CONFIG_H
      14             : #include "config.h"
      15             : #endif
      16             : 
      17             : #include <stdlib.h>
      18             : #include "lt-mem.h"
      19             : #include "lt-messages.h"
      20             : #include "lt-list.h"
      21             : 
      22             : 
      23             : /**
      24             :  * SECTION: lt-list
      25             :  * @Short_Description: linked lists
      26             :  * @Title: Doubly-Linked Lists
      27             :  *
      28             :  * The #lt_list_t object and its associated functions provide a standard
      29             :  * doubly-linked list data structure.
      30             :  */
      31             : struct _lt_list_t {
      32             :         lt_mem_t      parent;
      33             :         lt_list_t    *prev;
      34             :         lt_list_t    *next;
      35             :         lt_pointer_t  value;
      36             : };
      37             : 
      38             : /*< private >*/
      39             : static void
      40         582 : _lt_list_update(lt_pointer_t data)
      41             : {
      42         582 :         lt_list_t *list = data;
      43             : 
      44         582 :         if (list->next)
      45         112 :                 list->next->prev = list->prev;
      46         582 :         if (list->prev)
      47           0 :                 list->prev->next = list->next;
      48         582 : }
      49             : 
      50             : static lt_list_t *
      51           0 : _lt_list_sort_merge(lt_list_t         *l1,
      52             :                     lt_list_t         *l2,
      53             :                     lt_compare_func_t  func)
      54             : {
      55             :         int result;
      56           0 :         lt_list_t list, *l = &list, *lprev = NULL;
      57             : 
      58           0 :         while (l1 && l2) {
      59           0 :                 result = func(lt_list_value(l1), lt_list_value(l2));
      60           0 :                 if (result <= 0) {
      61           0 :                         l->next = l1;
      62           0 :                         l1 = lt_list_next(l1);
      63             :                 } else {
      64           0 :                         l->next = l2;
      65           0 :                         l2 = lt_list_next(l2);
      66             :                 }
      67           0 :                 l = lt_list_next(l);
      68           0 :                 l->prev = lprev;
      69           0 :                 lprev = l;
      70             :         }
      71           0 :         l->next = l1 ? l1 : l2;
      72           0 :         l->next->prev = l;
      73             : 
      74           0 :         return list.next;
      75             : }
      76             : 
      77             : /*< protected >*/
      78             : lt_list_t *
      79         582 : lt_list_new(void)
      80             : {
      81         582 :         return lt_mem_alloc_object(sizeof (lt_list_t));
      82             : }
      83             : 
      84             : /*< public >*/
      85             : 
      86             : /**
      87             :  * lt_list_ref:
      88             :  * @list: a #lt_list_t.
      89             :  *
      90             :  * Increases the reference count of @list.
      91             :  *
      92             :  * Returns: (transfer none): the same @list object.
      93             :  */
      94             : lt_list_t *
      95           0 : lt_list_ref(lt_list_t *list)
      96             : {
      97           0 :         lt_return_val_if_fail (list != NULL, NULL);
      98             : 
      99           0 :         return lt_mem_ref(&list->parent);
     100             : }
     101             : 
     102             : /**
     103             :  * lt_list_unref:
     104             :  * @list: a #lt_list_t.
     105             :  *
     106             :  * Decreases the reference count of @list. when its reference count
     107             :  * drops to 0, the object is finalized (i.e. its memory is freed).
     108             :  */
     109             : void
     110         582 : lt_list_unref(lt_list_t *list)
     111             : {
     112         582 :         if (list)
     113         582 :                 lt_mem_unref(&list->parent);
     114         582 : }
     115             : 
     116             : /**
     117             :  * lt_list_free:
     118             :  * @data: a #lt_list_t.
     119             :  *
     120             :  * Frees all of the memory used by a #lt_list_t.
     121             :  */
     122             : void
     123         486 : lt_list_free(lt_pointer_t data)
     124             : {
     125         486 :         lt_list_t *l = data, *list;
     126             : 
     127        1554 :         while (l) {
     128         582 :                 list = l;
     129         582 :                 l = l->next;
     130         582 :                 lt_list_unref(list);
     131             :         }
     132         486 : }
     133             : 
     134             : /**
     135             :  * lt_list_first:
     136             :  * @list: a #lt_list_t.
     137             :  *
     138             :  * Gets the first element in a #lt_list_t.
     139             :  *
     140             :  * Returns: (transfer none): the first element in the #lt_list_t
     141             :  *          or %NULL if the #lt_list_t has no elements.
     142             :  */
     143             : lt_list_t *
     144           0 : lt_list_first(lt_list_t *list)
     145             : {
     146           0 :         if (list) {
     147           0 :                 while (list->prev)
     148           0 :                         list = list->prev;
     149             :         }
     150             : 
     151           0 :         return list;
     152             : }
     153             : 
     154             : /**
     155             :  * lt_list_last:
     156             :  * @list: a #lt_list_t.
     157             :  *
     158             :  * Gets the last element in a #lt_list_t.
     159             :  *
     160             :  * Returns: (transfer none): the last element in the #lt_list_t
     161             :  *          or %NULL if the #lt_list_t has no elements.
     162             :  */
     163             : lt_list_t *
     164         112 : lt_list_last(lt_list_t *list)
     165             : {
     166         112 :         if (list) {
     167         560 :                 while (list->next)
     168         336 :                         list = list->next;
     169             :         }
     170             : 
     171         112 :         return list;
     172             : }
     173             : 
     174             : /**
     175             :  * lt_list_previous:
     176             :  * @list: a #lt_list_t.
     177             :  *
     178             :  * Gets the previous element in a #lt_list_t.
     179             :  *
     180             :  * Returns: (transfer none): the previous element, or %NULL if there are no previous elements.
     181             :  */
     182             : lt_list_t *
     183           0 : lt_list_previous(const lt_list_t *list)
     184             : {
     185           0 :         return list ? list->prev : NULL;
     186             : }
     187             : 
     188             : /**
     189             :  * lt_list_next:
     190             :  * @list: a #lt_list_t.
     191             :  *
     192             :  * Gets the next element in a #lt_list_t.
     193             :  *
     194             :  * Returns: (transfer none): the next element, or %NULL if there are no more elements.
     195             :  */
     196             : lt_list_t *
     197         284 : lt_list_next(const lt_list_t *list)
     198             : {
     199         284 :         return list ? list->next : NULL;
     200             : }
     201             : 
     202             : /**
     203             :  * lt_list_value:
     204             :  * @list: a #lt_list_t.
     205             :  *
     206             :  * Gets a value in a #lt_list_t.
     207             :  *
     208             :  * Returns: (transfer none): a pointer to be set to the #lt_list_t.
     209             :  */
     210             : lt_pointer_t
     211         284 : lt_list_value(const lt_list_t *list)
     212             : {
     213         284 :         lt_return_val_if_fail (list != NULL, NULL);
     214             : 
     215         284 :         return list->value;
     216             : }
     217             : 
     218             : /**
     219             :  * lt_list_length:
     220             :  * @list: a #lt_list_t.
     221             :  *
     222             :  * Gets the number of elements in a #lt_list_t.
     223             :  *
     224             :  * Returns: the number of elements in the #lt_list_t.
     225             :  */
     226             : size_t
     227           0 : lt_list_length(const lt_list_t *list)
     228             : {
     229           0 :         size_t retval = 0;
     230           0 :         const lt_list_t *l = list;
     231             : 
     232           0 :         while (l) {
     233           0 :                 l = lt_list_next(l);
     234           0 :                 retval++;
     235             :         }
     236             : 
     237           0 :         return retval;
     238             : }
     239             : 
     240             : /**
     241             :  * lt_list_append:
     242             :  * @list: a #lt_list_t.
     243             :  * @data: the data for the new element
     244             :  * @func: (scope async): the call back function to destroy @data or %NULL
     245             :  *
     246             :  * Adds a new element on to the end of the list.
     247             :  *
     248             :  * Returns: the new start of the #lt_list_t.
     249             :  */
     250             : lt_list_t *
     251         582 : lt_list_append(lt_list_t         *list,
     252             :                lt_pointer_t       data,
     253             :                lt_destroy_func_t  func)
     254             : {
     255         582 :         lt_list_t *l = lt_list_new();
     256             :         lt_list_t *last;
     257             : 
     258         582 :         l->value = data;
     259         582 :         l->next = NULL;
     260         582 :         lt_mem_add_ref(&l->parent, l, _lt_list_update);
     261         582 :         if (func)
     262         582 :                 lt_mem_add_ref(&l->parent, data, func);
     263         582 :         if (list) {
     264         112 :                 last = lt_list_last(list);
     265         112 :                 last->next = l;
     266         112 :                 l->prev = last;
     267             :         } else {
     268         470 :                 l->prev = NULL;
     269         470 :                 list = l;
     270             :         }
     271             : 
     272         582 :         return list;
     273             : }
     274             : 
     275             : #if 0
     276             : /**
     277             :  * lt_list_remove:
     278             :  * @list: a #lt_list_t.
     279             :  * @data: the data of the element to remove.
     280             :  *
     281             :  * Removes an element from a #lt_list_t.
     282             :  * If two elements contain the same data, only the first is removed.
     283             :  * If none of the elements contain the data, the #lt_list_t is unchanged.
     284             :  * This works similar to lt_list_delete() though, the difference is
     285             :  * this won't calls the finalizer to destroy the data in the element.
     286             :  *
     287             :  * Returns: the new start of the #lt_list_t.
     288             :  */
     289             : lt_list_t *
     290             : lt_list_remove(lt_list_t    *list,
     291             :                lt_pointer_t  data)
     292             : {
     293             :         lt_list_t *l = list;
     294             : 
     295             :         while (l) {
     296             :                 if (l->value == data) {
     297             :                         lt_mem_remove_ref(&l->parent, value);
     298             :                         list = lt_list_delete_link(list, l);
     299             :                         break;
     300             :                 } else {
     301             :                         l = l->next;
     302             :                 }
     303             :         }
     304             : 
     305             :         return list;
     306             : }
     307             : 
     308             : /**
     309             :  * lt_list_delete:
     310             :  * @list: a #lt_list_t.
     311             :  * @data: the data of the element to remove.
     312             :  *
     313             :  * Removes an element from a #lt_list_t.
     314             :  * If two elements contain the same data, only the first is removed.
     315             :  * If none of the elements contain the data, the #lt_list_t is unchanged.
     316             :  *
     317             :  * Returns: the new start of the #lt_list_t.
     318             :  */
     319             : lt_list_t *
     320             : lt_list_delete(lt_list_t    *list,
     321             :                lt_pointer_t  data)
     322             : {
     323             :         lt_list_t *l = list;
     324             : 
     325             :         while (l) {
     326             :                 if (l->value == data) {
     327             :                         list = lt_list_delete_link(list, l);
     328             :                         break;
     329             :                 } else {
     330             :                         l = l->next;
     331             :                 }
     332             :         }
     333             : 
     334             :         return list;
     335             : }
     336             : #endif
     337             : 
     338             : /**
     339             :  * lt_list_delete_link:
     340             :  * @list: a #lt_list_t
     341             :  * @link_: node to delete from @list
     342             :  *
     343             :  * Removes the node @link_ from the @list and frees it.
     344             :  *
     345             :  * Returns: the new head of @list
     346             :  */
     347             : lt_list_t *
     348           0 : lt_list_delete_link(lt_list_t *list,
     349             :                     lt_list_t *link_)
     350             : {
     351           0 :         if (link_) {
     352           0 :                 if (link_ == list)
     353           0 :                         list = list->next;
     354           0 :                 lt_list_unref(link_);
     355             :         }
     356             : 
     357           0 :         return list;
     358             : }
     359             : 
     360             : /**
     361             :  * lt_list_find:
     362             :  * @list: a #lt_list_t
     363             :  * @data: the element data to find
     364             :  *
     365             :  * Finds the element in a #lt_list_t which
     366             :  * contains the given data.
     367             :  *
     368             :  * Returns: the found #lt_list_t element, or %NULL if it's not found
     369             :  */
     370             : lt_list_t *
     371           0 : lt_list_find(lt_list_t          *list,
     372             :              const lt_pointer_t  data)
     373             : {
     374           0 :         while (list) {
     375           0 :                 if (list->value == data)
     376           0 :                         break;
     377           0 :                 list = list->next;
     378             :         }
     379             : 
     380           0 :         return list;
     381             : }
     382             : 
     383             : /**
     384             :  * lt_list_find_custom:
     385             :  * @list: a #lt_list_t
     386             :  * @data: the data passed to the function
     387             :  * @func: (scope call): the function to call for each element.
     388             :  *        It should return 0 when the desired element is found
     389             :  *
     390             :  * Finds an element in a #lt_list_t, using a supplied function to
     391             :  * find the desired element. It iterates over the list, calling
     392             :  * the given function which should return 0 when the desired
     393             :  * element is found. The function takes two const #lt_pointer_t
     394             :  * arguments, the #lt_list_t element's data as the first argument
     395             :  * and the given data.
     396             :  *
     397             :  * Returns: the found #lt_list_t element, or %NULL if it's not found
     398             :  */
     399             : lt_list_t *
     400           0 : lt_list_find_custom(lt_list_t          *list,
     401             :                     const lt_pointer_t  data,
     402             :                     lt_compare_func_t   func)
     403             : {
     404           0 :         lt_return_val_if_fail (func != NULL, NULL);
     405             : 
     406           0 :         while (list) {
     407           0 :                 if (!func(list->value, data))
     408           0 :                         break;
     409           0 :                 list = list->next;
     410             :         }
     411             : 
     412           0 :         return list;
     413             : }
     414             : 
     415             : /**
     416             :  * lt_list_sort:
     417             :  * @list: a #lt_list_t
     418             :  * @func: (scope call): the comparison function used to sort the #lt_list_t.
     419             :  *        This function is passed the data from 2 elements of the #lt_list_t
     420             :  *        and should return 0 if they are equal, a negative value if the
     421             :  *        first element comes before the second, or a positive value if
     422             :  *        the first element comes after the second.
     423             :  *
     424             :  * Sorts a #lt_list_t using the given comparison function.
     425             :  *
     426             :  * Returns: the start of the sorted #lt_list_t
     427             :  */
     428             : lt_list_t *
     429           0 : lt_list_sort(lt_list_t         *list,
     430             :              lt_compare_func_t  func)
     431             : {
     432             :         lt_list_t *a, *b;
     433           0 :         size_t i = 0, j = 0;
     434             : 
     435           0 :         lt_return_val_if_fail (list != NULL, NULL);
     436             : 
     437           0 :         if (!list->next)
     438           0 :                 return list;
     439             : 
     440           0 :         a = b = list;
     441           0 :         while (b->next) {
     442           0 :                 b = lt_list_next(b);
     443           0 :                 j++;
     444           0 :                 if ((j / 2) > i) {
     445           0 :                         a = lt_list_next(a);
     446           0 :                         i++;
     447             :                 }
     448             :         }
     449           0 :         b = a->next;
     450           0 :         a->next = NULL;
     451           0 :         b->prev = NULL;
     452             : 
     453           0 :         return _lt_list_sort_merge(lt_list_sort(list, func),
     454             :                                    lt_list_sort(b, func),
     455             :                                    func);
     456             : }
     457             : 
     458             : /**
     459             :  * lt_list_pop:
     460             :  * @list: a #lt_list_t
     461             :  * @data: a pointer to set the data in the first element
     462             :  *
     463             :  * Sets the data in the first element to @data and drop the element.
     464             :  *
     465             :  * Returns: the new head of @list.
     466             :  */
     467             : lt_list_t *
     468           0 : lt_list_pop(lt_list_t    *list,
     469             :             lt_pointer_t *data)
     470             : {
     471           0 :         lt_return_val_if_fail (list != NULL, NULL);
     472             : 
     473           0 :         lt_mem_remove_ref(&list->parent, list->value);
     474           0 :         if (data)
     475           0 :                 *data = list->value;
     476           0 :         list = lt_list_delete_link(list, list);
     477             : 
     478           0 :         return list;
     479             : }

Generated by: LCOV version 1.10