LCOV - code coverage report
Current view: top level - libreoffice/workdir/unxlngi6.pro/UnpackedTarball/langtag/liblangtag - lt-trie.c (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 55 147 37.4 %
Date: 2012-12-17 Functions: 8 16 50.0 %
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-trie.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 <string.h>
      19             : #include "lt-mem.h"
      20             : #include "lt-messages.h"
      21             : #include "lt-trie.h"
      22             : 
      23             : 
      24             : typedef struct _lt_trie_node_t  lt_trie_node_t;
      25             : struct _lt_trie_node_t {
      26             :         lt_mem_t           parent;
      27             :         lt_trie_node_t    *node[255];
      28             :         lt_pointer_t       data;
      29             :         char               index_;
      30             : };
      31             : struct _lt_trie_t {
      32             :         lt_mem_t        parent;
      33             :         lt_trie_node_t *root;
      34             : };
      35             : 
      36             : /*< private >*/
      37             : static lt_trie_node_t *
      38       41020 : lt_trie_node_new(char index_)
      39             : {
      40       41020 :         lt_trie_node_t *retval = lt_mem_alloc_object(sizeof (lt_trie_node_t));
      41             : 
      42       41020 :         if (retval) {
      43       41020 :                 retval->index_ = index_;
      44             :         }
      45             : 
      46       41020 :         return retval;
      47             : }
      48             : 
      49             : #if 0
      50             : static lt_trie_node_t *
      51             : lt_trie_node_ref(lt_trie_node_t *node)
      52             : {
      53             :         lt_return_val_if_fail (node != NULL, NULL);
      54             : 
      55             :         return lt_mem_ref(&node->parent);
      56             : }
      57             : #endif
      58             : 
      59             : static void
      60       41020 : lt_trie_node_unref(lt_trie_node_t *node)
      61             : {
      62       41020 :         if (node)
      63       41020 :                 lt_mem_unref(&node->parent);
      64       41020 : }
      65             : 
      66             : static lt_bool_t
      67      142084 : lt_trie_node_add(lt_trie_node_t    *node,
      68             :                  const char        *key,
      69             :                  lt_pointer_t       data,
      70             :                  lt_destroy_func_t  func,
      71             :                  lt_bool_t          replace)
      72             : {
      73             :         int index_;
      74             : 
      75      142084 :         lt_return_val_if_fail (node != NULL, FALSE);
      76      142084 :         lt_return_val_if_fail (key != NULL, FALSE);
      77             : 
      78      142084 :         index_ = *key - 1;
      79      142084 :         if (*key == 0) {
      80       35204 :                 if (node->data && !replace) {
      81           0 :                         return FALSE;
      82             :                 } else {
      83       35204 :                         if (node->data) {
      84           0 :                                 lt_mem_delete_ref(&node->parent, node->data);
      85             :                         }
      86       35204 :                         node->data = data;
      87       35204 :                         if (func)
      88       35204 :                                 lt_mem_add_ref(&node->parent, data, func);
      89             : 
      90       35204 :                         return TRUE;
      91             :                 }
      92             :         }
      93      106880 :         if (!node->node[index_]) {
      94       40992 :                 node->node[index_] = lt_trie_node_new(index_);
      95       40992 :                 if (!node->node[index_])
      96           0 :                         return FALSE;
      97       40992 :                 lt_mem_add_ref(&node->parent, node->node[index_],
      98             :                                (lt_destroy_func_t)lt_trie_node_unref);
      99       40992 :                 lt_mem_add_weak_pointer(&node->node[index_]->parent,
     100       40992 :                                         (lt_pointer_t *)&node->node[index_]);
     101             :         }
     102             : 
     103      106880 :         return lt_trie_node_add(node->node[index_], key + 1, data, func, replace);
     104             : }
     105             : 
     106             : static lt_bool_t
     107           0 : lt_trie_node_remove(lt_trie_node_t *node,
     108             :                     lt_trie_node_t *parent,
     109             :                     const char     *key)
     110             : {
     111             :         int i, index_;
     112           0 :         lt_bool_t found = FALSE;
     113             : 
     114           0 :         lt_return_val_if_fail (node != NULL, FALSE);
     115           0 :         lt_return_val_if_fail (key != NULL, FALSE);
     116             : 
     117           0 :         index_ = *key - 1;
     118           0 :         if (*key == 0) {
     119           0 :                 if (!node->data)
     120           0 :                         return FALSE;
     121           0 :                 lt_mem_delete_ref(&node->parent, node->data);
     122           0 :                 node->data = NULL;
     123           0 :                 for (i = 0; i < 255; i++) {
     124           0 :                         found |= node->node[i] != NULL;
     125             :                 }
     126           0 :                 if (!found)
     127           0 :                         lt_mem_delete_ref(&parent->parent, node);
     128           0 :                 return TRUE;
     129             :         }
     130           0 :         if (!node->node[index_])
     131           0 :                 return FALSE;
     132             : 
     133           0 :         return lt_trie_node_remove(node->node[index_], node, key + 1);
     134             : }
     135             : 
     136             : static const lt_pointer_t
     137         230 : lt_trie_node_lookup(lt_trie_node_t *node,
     138             :                     const char     *key)
     139             : {
     140             :         int index_;
     141             : 
     142         230 :         lt_return_val_if_fail (node != NULL, NULL);
     143         230 :         lt_return_val_if_fail (key != NULL, NULL);
     144             : 
     145         230 :         index_ = *key - 1;
     146         230 :         if (*key == 0)
     147          36 :                 return node->data;
     148         194 :         if (!node->node[index_])
     149          32 :                 return NULL;
     150             : 
     151         162 :         return lt_trie_node_lookup(node->node[index_], key + 1);
     152             : }
     153             : 
     154             : /*< protected >*/
     155             : 
     156             : /*< public >*/
     157             : lt_trie_t *
     158          28 : lt_trie_new(void)
     159             : {
     160          28 :         return lt_mem_alloc_object(sizeof (lt_trie_t));
     161             : }
     162             : 
     163             : lt_trie_t *
     164           0 : lt_trie_ref(lt_trie_t *trie)
     165             : {
     166           0 :         lt_return_val_if_fail (trie != NULL, NULL);
     167             : 
     168           0 :         return lt_mem_ref(&trie->parent);
     169             : }
     170             : 
     171             : void
     172          28 : lt_trie_unref(lt_trie_t *trie)
     173             : {
     174          28 :         if (trie)
     175          28 :                 lt_mem_unref(&trie->parent);
     176          28 : }
     177             : 
     178             : lt_bool_t
     179           0 : lt_trie_add(lt_trie_t         *trie,
     180             :             const char        *key,
     181             :             lt_pointer_t       data,
     182             :             lt_destroy_func_t  func)
     183             : {
     184           0 :         lt_return_val_if_fail (trie != NULL, FALSE);
     185           0 :         lt_return_val_if_fail (key != NULL, FALSE);
     186           0 :         lt_return_val_if_fail (data != NULL, FALSE);
     187             : 
     188           0 :         if (!trie->root) {
     189           0 :                 if ((trie->root = lt_trie_node_new(0)) == NULL)
     190           0 :                         return FALSE;
     191           0 :                 lt_mem_add_ref(&trie->parent, trie->root,
     192             :                                (lt_destroy_func_t)lt_trie_node_unref);
     193           0 :                 lt_mem_add_weak_pointer(&trie->root->parent, (lt_pointer_t *)&trie->root);
     194             :         }
     195             : 
     196           0 :         return lt_trie_node_add(trie->root, key, data, func, FALSE);
     197             : }
     198             : 
     199             : lt_bool_t
     200       35204 : lt_trie_replace(lt_trie_t         *trie,
     201             :                 const char        *key,
     202             :                 lt_pointer_t       data,
     203             :                 lt_destroy_func_t  func)
     204             : {
     205       35204 :         lt_return_val_if_fail (trie != NULL, FALSE);
     206       35204 :         lt_return_val_if_fail (key != NULL, FALSE);
     207       35204 :         lt_return_val_if_fail (data != NULL, FALSE);
     208             : 
     209       35204 :         if (!trie->root) {
     210          28 :                 if ((trie->root = lt_trie_node_new(0)) == NULL)
     211           0 :                         return FALSE;
     212          28 :                 lt_mem_add_ref(&trie->parent, trie->root,
     213             :                                (lt_destroy_func_t)lt_trie_node_unref);
     214             :         }
     215             : 
     216       35204 :         return lt_trie_node_add(trie->root, key, data, func, TRUE);
     217             : }
     218             : 
     219             : lt_bool_t
     220           0 : lt_trie_remove(lt_trie_t  *trie,
     221             :                const char *key)
     222             : {
     223           0 :         lt_return_val_if_fail (trie != NULL, FALSE);
     224           0 :         lt_return_val_if_fail (key != NULL, FALSE);
     225           0 :         lt_return_val_if_fail (*key != 0, FALSE);
     226             : 
     227           0 :         if (!trie->root)
     228           0 :                 return FALSE;
     229             : 
     230           0 :         return lt_trie_node_remove(trie->root, NULL, key);
     231             : }
     232             : 
     233             : lt_pointer_t
     234          68 : lt_trie_lookup(lt_trie_t  *trie,
     235             :                const char *key)
     236             : {
     237          68 :         lt_return_val_if_fail (trie != NULL, NULL);
     238          68 :         lt_return_val_if_fail (key != NULL, NULL);
     239             : 
     240          68 :         if (!trie->root)
     241           0 :                 return NULL;
     242             : 
     243          68 :         return lt_trie_node_lookup(trie->root, key);
     244             : }
     245             : 
     246             : lt_list_t *
     247           0 : lt_trie_keys(lt_trie_t *trie)
     248             : {
     249             :         lt_trie_iter_t iter;
     250           0 :         lt_list_t *retval = NULL;
     251             :         lt_pointer_t key;
     252             : 
     253           0 :         lt_return_val_if_fail (trie != NULL, NULL);
     254             : 
     255           0 :         if (trie->root)
     256           0 :                 return NULL;
     257             : 
     258           0 :         lt_trie_iter_init(&iter, trie);
     259             : 
     260           0 :         while (lt_trie_iter_next(&iter, &key, NULL)) {
     261           0 :                 retval = lt_list_append(retval, key, free);
     262             :         }
     263             : 
     264           0 :         lt_trie_iter_finish(&iter);
     265             : 
     266           0 :         return retval;
     267             : }
     268             : 
     269             : lt_trie_iter_t *
     270           0 : lt_trie_iter_init(lt_trie_iter_t *iter,
     271             :                   lt_trie_t      *trie)
     272             : {
     273             :         int i;
     274             : 
     275           0 :         lt_return_val_if_fail (iter != NULL, NULL);
     276           0 :         lt_return_val_if_fail (trie != NULL, NULL);
     277             : 
     278           0 :         iter->pos_str = lt_string_new(NULL);
     279           0 :         iter->stack = NULL;
     280           0 :         if (trie->root) {
     281           0 :                 lt_trie_node_t *node = trie->root;
     282             : 
     283           0 :                 for (i = 0; i < 255; i++) {
     284           0 :                         if (node->node[i])
     285           0 :                                 iter->stack = lt_list_append(iter->stack, node->node[i], NULL);
     286             :                 }
     287             :                 /* add a terminator */
     288           0 :                 iter->stack = lt_list_append(iter->stack, NULL, NULL);
     289             :         }
     290             : 
     291           0 :         return iter;
     292             : }
     293             : 
     294             : void
     295           0 : lt_trie_iter_finish(lt_trie_iter_t *iter)
     296             : {
     297           0 :         lt_return_if_fail (iter != NULL);
     298             : 
     299           0 :         if (iter->stack)
     300           0 :                 lt_list_free(iter->stack);
     301           0 :         lt_string_unref(iter->pos_str);
     302             : }
     303             : 
     304             : lt_bool_t
     305           0 : lt_trie_iter_next(lt_trie_iter_t *iter,
     306             :                   lt_pointer_t   *key,
     307             :                   lt_pointer_t   *value)
     308             : {
     309             :         int i;
     310           0 :         lt_trie_node_t *node = NULL;
     311             : 
     312           0 :         lt_return_val_if_fail (iter != NULL, FALSE);
     313             : 
     314             :         while (1) {
     315           0 :                 if (lt_list_length(iter->stack) == 0)
     316           0 :                         break;
     317           0 :                 iter->stack = lt_list_pop(iter->stack, (lt_pointer_t *)&node);
     318           0 :                 if (node) {
     319           0 :                         lt_string_append_c(iter->pos_str, node->index_);
     320             :                 } else {
     321           0 :                         lt_string_truncate(iter->pos_str, -1);
     322           0 :                         continue;
     323             :                 }
     324           0 :                 for (i = 0; i < 255; i++) {
     325           0 :                         if (node->node[i])
     326           0 :                                 iter->stack = lt_list_append(iter->stack, node->node[i], NULL);
     327             :                 }
     328             :                 /* add a terminator */
     329           0 :                 iter->stack = lt_list_append(iter->stack, NULL, NULL);
     330           0 :                 if (node->data) {
     331           0 :                         if (key) {
     332           0 :                                 *key = strdup(lt_string_value(iter->pos_str));
     333             :                         }
     334           0 :                         if (value)
     335           0 :                                 *value = node->data;
     336             : 
     337           0 :                         return TRUE;
     338             :                 }
     339           0 :         }
     340             : 
     341           0 :         return FALSE;
     342             : }

Generated by: LCOV version 1.10