LCOV - code coverage report
Current view: top level - libreoffice/workdir/unxlngi6.pro/UnpackedTarball/langtag/liblangtag - lt-extlang-db.c (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 108 137 78.8 %
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-extlang-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-extlang.h"
      21             : #include "lt-extlang-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-extlang-db.h"
      28             : 
      29             : 
      30             : /**
      31             :  * SECTION:lt-extlang-db
      32             :  * @Short_Description: An interface to access Extlang Database
      33             :  * @Title: Database - Extlang
      34             :  *
      35             :  * This class provides an interface to access Extlang database. which has been
      36             :  * registered as ISO 639 code.
      37             :  */
      38             : struct _lt_extlang_db_t {
      39             :         lt_mem_t   parent;
      40             :         lt_xml_t  *xml;
      41             :         lt_trie_t *extlang_entries;
      42             : };
      43             : 
      44             : /*< private >*/
      45             : static lt_bool_t
      46           4 : lt_extlang_db_parse(lt_extlang_db_t  *extlangdb,
      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 (extlangdb != NULL, FALSE);
      57             : 
      58           4 :         doc = lt_xml_get_subtag_registry(extlangdb->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/extlang", 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         912 :         for (i = 0; i < n; i++) {
      75         908 :                 xmlNodePtr ent = xmlXPathNodeSetItem(xobj->nodesetval, i);
      76             :                 xmlNodePtr cnode;
      77         908 :                 xmlChar *subtag = NULL, *desc = NULL, *macrolang = NULL, *preferred = NULL, *prefix = NULL;
      78         908 :                 lt_extlang_t *le = NULL;
      79             :                 char *s;
      80             : 
      81         908 :                 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         908 :                 cnode = ent->children;
      87       12604 :                 while (cnode != NULL) {
      88       10788 :                         if (xmlStrcmp(cnode->name, (const xmlChar *)"subtag") == 0) {
      89         908 :                                 if (subtag) {
      90           0 :                                         lt_warning("Duplicate subtag element in extlang: previous value was '%s'",
      91             :                                                    subtag);
      92             :                                 } else {
      93         908 :                                         subtag = xmlNodeGetContent(cnode);
      94             :                                 }
      95       18852 :                         } else if (xmlStrcmp(cnode->name, (const xmlChar *)"added") == 0 ||
      96        8972 :                                    xmlStrcmp(cnode->name, (const xmlChar *)"text") == 0) {
      97             :                                 /* ignore it */
      98        3124 :                         } else if (xmlStrcmp(cnode->name, (const xmlChar *)"description") == 0) {
      99             :                                 /* wonder if many descriptions helps something. or is it a bug? */
     100         960 :                                 if (!desc)
     101         908 :                                         desc = xmlNodeGetContent(cnode);
     102        2164 :                         } else if (xmlStrcmp(cnode->name, (const xmlChar *)"macrolanguage") == 0) {
     103         348 :                                 if (macrolang) {
     104           0 :                                         lt_warning("Duplicate macrolanguage element in extlang: previous value was '%s'",
     105             :                                                    macrolang);
     106             :                                 } else {
     107         348 :                                         macrolang = xmlNodeGetContent(cnode);
     108             :                                 }
     109        1816 :                         } else if (xmlStrcmp(cnode->name, (const xmlChar *)"preferred-value") == 0) {
     110         908 :                                 if (preferred) {
     111           0 :                                         lt_warning("Duplicate preferred-value element in extlang: previous value was '%s'",
     112             :                                                    preferred);
     113             :                                 } else {
     114         908 :                                         preferred = xmlNodeGetContent(cnode);
     115             :                                 }
     116         908 :                         } else if (xmlStrcmp(cnode->name, (const xmlChar *)"prefix") == 0) {
     117         908 :                                 if (prefix) {
     118           0 :                                         lt_warning("Duplicate prefix element in extlang: previous value was '%s'",
     119             :                                                    prefix);
     120             :                                 } else {
     121         908 :                                         prefix = xmlNodeGetContent(cnode);
     122             :                                 }
     123             :                         } else {
     124           0 :                                 lt_warning("Unknown node under /registry/extlang: %s", cnode->name);
     125             :                         }
     126       10788 :                         cnode = cnode->next;
     127             :                 }
     128         908 :                 if (!subtag) {
     129           0 :                         lt_warning("No subtag node: description = '%s', macrolanguage = '%s', preferred-value = '%s', prefix = '%s'",
     130             :                                    desc, macrolang, preferred, prefix);
     131           0 :                         goto bail1;
     132             :                 }
     133         908 :                 if (!desc) {
     134           0 :                         lt_warning("No description node: subtag = '%s', macrolanguage = '%s', preferred-value = '%s', prefix = '%s'",
     135             :                                    subtag, macrolang, preferred, prefix);
     136           0 :                         goto bail1;
     137             :                 }
     138         908 :                 le = lt_extlang_create();
     139         908 :                 if (!le) {
     140           0 :                         lt_error_set(&err, LT_ERR_OOM,
     141             :                                      "Unable to create an instance of lt_extlang_t.");
     142           0 :                         goto bail1;
     143             :                 }
     144         908 :                 lt_extlang_set_tag(le, (const char *)subtag);
     145         908 :                 lt_extlang_set_name(le, (const char *)desc);
     146         908 :                 if (macrolang)
     147         348 :                         lt_extlang_set_macro_language(le, (const char *)macrolang);
     148         908 :                 if (preferred)
     149         908 :                         lt_extlang_set_preferred_tag(le, (const char *)preferred);
     150         908 :                 if (prefix)
     151         908 :                         lt_extlang_add_prefix(le, (const char *)prefix);
     152             : 
     153         908 :                 s = strdup(lt_extlang_get_tag(le));
     154         908 :                 lt_trie_replace(extlangdb->extlang_entries,
     155         908 :                                 lt_strlower(s),
     156         908 :                                 lt_extlang_ref(le),
     157             :                                 (lt_destroy_func_t)lt_extlang_unref);
     158         908 :                 free(s);
     159             :           bail1:
     160         908 :                 if (subtag)
     161         908 :                         xmlFree(subtag);
     162         908 :                 if (desc)
     163         908 :                         xmlFree(desc);
     164         908 :                 if (macrolang)
     165         348 :                         xmlFree(macrolang);
     166         908 :                 if (preferred)
     167         908 :                         xmlFree(preferred);
     168         908 :                 if (prefix)
     169         908 :                         xmlFree(prefix);
     170         908 :                 lt_extlang_unref(le);
     171             :         }
     172             :   bail:
     173           4 :         if (lt_error_is_set(err, LT_ERR_ANY)) {
     174           0 :                 if (error)
     175           0 :                         *error = lt_error_ref(err);
     176             :                 else
     177           0 :                         lt_error_print(err, LT_ERR_ANY);
     178           0 :                 lt_error_unref(err);
     179           0 :                 retval = FALSE;
     180             :         }
     181             : 
     182           4 :         if (xobj)
     183           4 :                 xmlXPathFreeObject(xobj);
     184           4 :         if (xctxt)
     185           4 :                 xmlXPathFreeContext(xctxt);
     186             : 
     187           4 :         return retval;
     188             : }
     189             : 
     190             : /*< public >*/
     191             : /**
     192             :  * lt_extlang_db_new:
     193             :  *
     194             :  * Create a new instance of a #lt_extlang_db_t.
     195             :  *
     196             :  * Returns: (transfer full): a new instance of #lt_extlang_db_t.
     197             :  */
     198             : lt_extlang_db_t *
     199           4 : lt_extlang_db_new(void)
     200             : {
     201           4 :         lt_extlang_db_t *retval = lt_mem_alloc_object(sizeof (lt_extlang_db_t));
     202             : 
     203           4 :         if (retval) {
     204           4 :                 lt_error_t *err = NULL;
     205             :                 lt_extlang_t *le;
     206             : 
     207           4 :                 retval->extlang_entries = lt_trie_new();
     208           4 :                 lt_mem_add_ref(&retval->parent, retval->extlang_entries,
     209             :                                (lt_destroy_func_t)lt_trie_unref);
     210             : 
     211           4 :                 le = lt_extlang_create();
     212           4 :                 lt_extlang_set_tag(le, "*");
     213           4 :                 lt_extlang_set_name(le, "Wildcard entry");
     214           4 :                 lt_trie_replace(retval->extlang_entries,
     215             :                                 lt_extlang_get_tag(le),
     216             :                                 le,
     217             :                                 (lt_destroy_func_t)lt_extlang_unref);
     218           4 :                 le = lt_extlang_create();
     219           4 :                 lt_extlang_set_tag(le, "");
     220           4 :                 lt_extlang_set_name(le, "Empty entry");
     221           4 :                 lt_trie_replace(retval->extlang_entries,
     222             :                                 lt_extlang_get_tag(le),
     223             :                                 le,
     224             :                                 (lt_destroy_func_t)lt_extlang_unref);
     225             : 
     226           4 :                 retval->xml = lt_xml_new();
     227           4 :                 if (!retval->xml) {
     228           0 :                         lt_extlang_db_unref(retval);
     229           0 :                         retval = NULL;
     230             :                         goto bail;
     231             :                 }
     232           4 :                 lt_mem_add_ref(&retval->parent, retval->xml,
     233             :                                (lt_destroy_func_t)lt_xml_unref);
     234           4 :                 lt_extlang_db_parse(retval, &err);
     235           4 :                 if (err) {
     236           0 :                         lt_error_print(err, LT_ERR_ANY);
     237           0 :                         lt_extlang_db_unref(retval);
     238           0 :                         retval = NULL;
     239           0 :                         lt_error_unref(err);
     240             :                 }
     241             :         }
     242             :   bail:
     243             : 
     244           4 :         return retval;
     245             : }
     246             : 
     247             : /**
     248             :  * lt_extlang_db_ref:
     249             :  * @extlangdb: a #lt_extlang_db_t.
     250             :  *
     251             :  * Increases the reference count of @extlangdb.
     252             :  *
     253             :  * Returns: (transfer none): the same @extlangdb object.
     254             :  */
     255             : lt_extlang_db_t *
     256           4 : lt_extlang_db_ref(lt_extlang_db_t *extlangdb)
     257             : {
     258           4 :         lt_return_val_if_fail (extlangdb != NULL, NULL);
     259             : 
     260           4 :         return lt_mem_ref(&extlangdb->parent);
     261             : }
     262             : 
     263             : /**
     264             :  * lt_extlang_db_unref:
     265             :  * @extlangdb: a #lt_extlang_db_t.
     266             :  *
     267             :  * Decreases the reference count of @extlangdb. when its reference count
     268             :  * drops to 0, the object is finalized (i.e. its memory is freed).
     269             :  */
     270             : void
     271           8 : lt_extlang_db_unref(lt_extlang_db_t *extlangdb)
     272             : {
     273           8 :         if (extlangdb)
     274           8 :                 lt_mem_unref(&extlangdb->parent);
     275           8 : }
     276             : 
     277             : /**
     278             :  * lt_extlang_db_lookup:
     279             :  * @extlangdb: a #lt_extlang_db_t.
     280             :  * @subtag: a subtag name to lookup.
     281             :  *
     282             :  * Lookup @lt_extlang_t if @subtag is valid and registered into the database.
     283             :  *
     284             :  * Returns: (transfer full): a #lt_extlang_t that meets with @subtag.
     285             :  *                           otherwise %NULL.
     286             :  */
     287             : lt_extlang_t *
     288           4 : lt_extlang_db_lookup(lt_extlang_db_t *extlangdb,
     289             :                      const char      *subtag)
     290             : {
     291             :         lt_extlang_t *retval;
     292             :         char *s;
     293             : 
     294           4 :         lt_return_val_if_fail (extlangdb != NULL, NULL);
     295           4 :         lt_return_val_if_fail (subtag != NULL, NULL);
     296             : 
     297           4 :         s = strdup(subtag);
     298           4 :         retval = lt_trie_lookup(extlangdb->extlang_entries,
     299           4 :                                 lt_strlower(s));
     300           4 :         free(s);
     301           4 :         if (retval)
     302           0 :                 return lt_extlang_ref(retval);
     303             : 
     304           4 :         return NULL;
     305             : }

Generated by: LCOV version 1.10