LCOV - code coverage report
Current view: top level - libreoffice/workdir/unxlngi6.pro/UnpackedTarball/langtag/liblangtag - lt-grandfathered-db.c (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 88 114 77.2 %
Date: 2012-12-17 Functions: 5 5 100.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-grandfathered-db.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 <string.h>
      18             : #include <libxml/xpath.h>
      19             : #include "lt-error.h"
      20             : #include "lt-grandfathered.h"
      21             : #include "lt-grandfathered-private.h"
      22             : #include "lt-mem.h"
      23             : #include "lt-messages.h"
      24             : #include "lt-trie.h"
      25             : #include "lt-utils.h"
      26             : #include "lt-xml.h"
      27             : #include "lt-grandfathered-db.h"
      28             : 
      29             : 
      30             : /**
      31             :  * SECTION: lt-grandfathered-db
      32             :  * @Short_Description: An interface to access Grandfathered Database
      33             :  * @Title: Database - Grandfathered
      34             :  *
      35             :  * This class provides an interface to access Grandfathered database.
      36             :  * which has been registered under RFC 3066 and mostly deprecated.
      37             :  */
      38             : struct _lt_grandfathered_db_t {
      39             :         lt_mem_t   parent;
      40             :         lt_xml_t  *xml;
      41             :         lt_trie_t *grandfathered_entries;
      42             : };
      43             : 
      44             : /*< private >*/
      45             : static lt_bool_t
      46           4 : lt_grandfathered_db_parse(lt_grandfathered_db_t  *grandfathereddb,
      47             :                           lt_error_t            **error)
      48             : {
      49           4 :         lt_bool_t retval = TRUE;
      50           4 :         xmlDocPtr doc = NULL;
      51           4 :         xmlXPathContextPtr xctxt = NULL;
      52           4 :         xmlXPathObjectPtr xobj = NULL;
      53           4 :         lt_error_t *err = NULL;
      54             :         int i, n;
      55             : 
      56           4 :         lt_return_val_if_fail (grandfathereddb != NULL, FALSE);
      57             : 
      58           4 :         doc = lt_xml_get_subtag_registry(grandfathereddb->xml);
      59           4 :         xctxt = xmlXPathNewContext(doc);
      60           4 :         if (!xctxt) {
      61           0 :                 lt_error_set(&err, LT_ERR_OOM,
      62             :                              "Unable to create an instance of xmlXPathContextPtr.");
      63           0 :                 goto bail;
      64             :         }
      65           4 :         xobj = xmlXPathEvalExpression((const xmlChar *)"/registry/grandfathered", xctxt);
      66           4 :         if (!xobj) {
      67           0 :                 lt_error_set(&err, LT_ERR_FAIL_ON_XML,
      68             :                              "No valid elements for %s",
      69             :                              doc->name);
      70           0 :                 goto bail;
      71             :         }
      72           4 :         n = xmlXPathNodeSetGetLength(xobj->nodesetval);
      73             : 
      74         108 :         for (i = 0; i < n; i++) {
      75         104 :                 xmlNodePtr ent = xmlXPathNodeSetItem(xobj->nodesetval, i);
      76             :                 xmlNodePtr cnode;
      77         104 :                 xmlChar *tag = NULL, *desc = NULL, *preferred = NULL;
      78         104 :                 lt_grandfathered_t *le = NULL;
      79             :                 char *s;
      80             : 
      81         104 :                 if (!ent) {
      82           0 :                         lt_error_set(&err, LT_ERR_FAIL_ON_XML,
      83             :                                      "Unable to obtain the xml node via XPath.");
      84           0 :                         goto bail;
      85             :                 }
      86         104 :                 cnode = ent->children;
      87        1264 :                 while (cnode != NULL) {
      88        1056 :                         if (xmlStrcmp(cnode->name, (const xmlChar *)"tag") == 0) {
      89         104 :                                 if (tag) {
      90           0 :                                         lt_warning("Duplicate tag element in grandfathered: previous value was '%s'",
      91             :                                                    tag);
      92             :                                 } else {
      93         104 :                                         tag = xmlNodeGetContent(cnode);
      94             :                                 }
      95        1800 :                         } else if (xmlStrcmp(cnode->name, (const xmlChar *)"added") == 0 ||
      96        1116 :                                    xmlStrcmp(cnode->name, (const xmlChar *)"text") == 0 ||
      97         268 :                                    xmlStrcmp(cnode->name, (const xmlChar *)"deprecated") == 0) {
      98             :                                 /* ignore it */
      99         184 :                         } else if (xmlStrcmp(cnode->name, (const xmlChar *)"description") == 0) {
     100             :                                 /* wonder if many descriptions helps something. or is it a bug? */
     101         104 :                                 if (!desc)
     102         104 :                                         desc = xmlNodeGetContent(cnode);
     103          80 :                         } else if (xmlStrcmp(cnode->name, (const xmlChar *)"preferred-value") == 0) {
     104          80 :                                 if (preferred) {
     105           0 :                                         lt_warning("Duplicate preferred-value element in grandfathered: previous value was '%s'",
     106             :                                                    preferred);
     107             :                                 } else {
     108          80 :                                         preferred = xmlNodeGetContent(cnode);
     109             :                                 }
     110             :                         } else {
     111           0 :                                 lt_warning("Unknown node under /registry/grandfathered: %s", cnode->name);
     112             :                         }
     113        1056 :                         cnode = cnode->next;
     114             :                 }
     115         104 :                 if (!tag) {
     116           0 :                         lt_warning("No tag node: description = '%s', preferred-value = '%s'",
     117             :                                    desc, preferred);
     118           0 :                         goto bail1;
     119             :                 }
     120         104 :                 if (!desc) {
     121           0 :                         lt_warning("No description node: tag = '%s', preferred-value = '%s'",
     122             :                                    tag, preferred);
     123           0 :                         goto bail1;
     124             :                 }
     125         104 :                 le = lt_grandfathered_create();
     126         104 :                 if (!le) {
     127           0 :                         lt_error_set(&err, LT_ERR_OOM,
     128             :                                      "Unable to create an instance of lt_grandfathered_t.");
     129           0 :                         goto bail1;
     130             :                 }
     131         104 :                 lt_grandfathered_set_tag(le, (const char *)tag);
     132         104 :                 lt_grandfathered_set_name(le, (const char *)desc);
     133         104 :                 if (preferred)
     134          80 :                         lt_grandfathered_set_preferred_tag(le, (const char *)preferred);
     135             : 
     136         104 :                 s = strdup(lt_grandfathered_get_tag(le));
     137         104 :                 lt_trie_replace(grandfathereddb->grandfathered_entries,
     138         104 :                                 lt_strlower(s),
     139         104 :                                 lt_grandfathered_ref(le),
     140             :                                 (lt_destroy_func_t)lt_grandfathered_unref);
     141         104 :                 free(s);
     142             :           bail1:
     143         104 :                 if (tag)
     144         104 :                         xmlFree(tag);
     145         104 :                 if (desc)
     146         104 :                         xmlFree(desc);
     147         104 :                 if (preferred)
     148          80 :                         xmlFree(preferred);
     149         104 :                 lt_grandfathered_unref(le);
     150             :         }
     151             :   bail:
     152           4 :         if (lt_error_is_set(err, LT_ERR_ANY)) {
     153           0 :                 if (error)
     154           0 :                         *error = lt_error_ref(err);
     155             :                 else
     156           0 :                         lt_error_print(err, LT_ERR_ANY);
     157           0 :                 lt_error_unref(err);
     158           0 :                 retval = FALSE;
     159             :         }
     160             : 
     161           4 :         if (xobj)
     162           4 :                 xmlXPathFreeObject(xobj);
     163           4 :         if (xctxt)
     164           4 :                 xmlXPathFreeContext(xctxt);
     165             : 
     166           4 :         return retval;
     167             : }
     168             : 
     169             : /*< public >*/
     170             : /**
     171             :  * lt_grandfathered_db_new:
     172             :  *
     173             :  * Create a new instance of a #lt_grandfathered_db_t.
     174             :  *
     175             :  * Returns: (transfer full): a new instance of #lt_grandfathered_db_t.
     176             :  */
     177             : lt_grandfathered_db_t *
     178           4 : lt_grandfathered_db_new(void)
     179             : {
     180           4 :         lt_grandfathered_db_t *retval = lt_mem_alloc_object(sizeof (lt_grandfathered_db_t));
     181             : 
     182           4 :         if (retval) {
     183           4 :                 lt_error_t *err = NULL;
     184             : 
     185           4 :                 retval->grandfathered_entries = lt_trie_new();
     186           4 :                 lt_mem_add_ref(&retval->parent, retval->grandfathered_entries,
     187             :                                (lt_destroy_func_t)lt_trie_unref);
     188             : 
     189           4 :                 retval->xml = lt_xml_new();
     190           4 :                 if (!retval->xml) {
     191           0 :                         lt_grandfathered_db_unref(retval);
     192           0 :                         retval = NULL;
     193             :                         goto bail;
     194             :                 }
     195           4 :                 lt_mem_add_ref(&retval->parent, retval->xml,
     196             :                                (lt_destroy_func_t)lt_xml_unref);
     197             : 
     198           4 :                 lt_grandfathered_db_parse(retval, &err);
     199           4 :                 if (lt_error_is_set(err, LT_ERR_ANY)) {
     200           0 :                         lt_error_print(err, LT_ERR_ANY);
     201           0 :                         lt_grandfathered_db_unref(retval);
     202           0 :                         retval = NULL;
     203           0 :                         lt_error_unref(err);
     204             :                 }
     205             :         }
     206             :   bail:
     207             : 
     208           4 :         return retval;
     209             : }
     210             : 
     211             : /**
     212             :  * lt_grandfathered_db_ref:
     213             :  * @grandfathereddb: a #lt_grandfathered_db_t.
     214             :  *
     215             :  * Increases the reference count of @grandfathereddb.
     216             :  *
     217             :  * Returns: (transfer none): the same @grandfathereddb object.
     218             :  */
     219             : lt_grandfathered_db_t *
     220          24 : lt_grandfathered_db_ref(lt_grandfathered_db_t *grandfathereddb)
     221             : {
     222          24 :         lt_return_val_if_fail (grandfathereddb != NULL, NULL);
     223             : 
     224          24 :         return lt_mem_ref(&grandfathereddb->parent);
     225             : }
     226             : 
     227             : /**
     228             :  * lt_grandfathered_db_unref:
     229             :  * @grandfathereddb: a #lt_grandfathered_db_t.
     230             :  *
     231             :  * Decreases the reference count of @grandfathereddb. when its reference count
     232             :  * drops to 0, the object is finalized (i.e. its memory is freed).
     233             :  */
     234             : void
     235          28 : lt_grandfathered_db_unref(lt_grandfathered_db_t *grandfathereddb)
     236             : {
     237          28 :         if (grandfathereddb)
     238          28 :                 lt_mem_unref(&grandfathereddb->parent);
     239          28 : }
     240             : 
     241             : /**
     242             :  * lt_grandfathered_db_lookup:
     243             :  * @grandfathereddb: a #lt_grandfathered_db_t.
     244             :  * @tag: a tag name to lookup.
     245             :  *
     246             :  * Lookup @lt_grandfathered_t if @tag is valid and registered into the database.
     247             :  *
     248             :  * Returns: (transfer full): a #lt_grandfathered_t that meets with @tag.
     249             :  *                           otherwise %NULL.
     250             :  */
     251             : lt_grandfathered_t *
     252          24 : lt_grandfathered_db_lookup(lt_grandfathered_db_t *grandfathereddb,
     253             :                            const char            *tag)
     254             : {
     255             :         lt_grandfathered_t *retval;
     256             :         char *s;
     257             : 
     258          24 :         lt_return_val_if_fail (grandfathereddb != NULL, NULL);
     259          24 :         lt_return_val_if_fail (tag != NULL, NULL);
     260             : 
     261          24 :         s = strdup(tag);
     262          24 :         retval = lt_trie_lookup(grandfathereddb->grandfathered_entries,
     263          24 :                                 lt_strlower(s));
     264          24 :         free(s);
     265          24 :         if (retval)
     266           2 :                 return lt_grandfathered_ref(retval);
     267             : 
     268          22 :         return NULL;
     269             : }

Generated by: LCOV version 1.10