LCOV - code coverage report
Current view: top level - libreoffice/workdir/unxlngi6.pro/UnpackedTarball/langtag/liblangtag - lt-xml.c (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 129 182 70.9 %
Date: 2012-12-17 Functions: 8 9 88.9 %
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-xml.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             : #ifndef _WIN32
      18             : #include <pthread.h>
      19             : #else
      20             : #include <windows.h>
      21             : #endif
      22             : #include <sys/stat.h>
      23             : #include <libxml/parser.h>
      24             : #include <libxml/xpath.h>
      25             : #include "lt-error.h"
      26             : #include "lt-mem.h"
      27             : #include "lt-messages.h"
      28             : #include "lt-database.h"
      29             : #include "lt-string.h"
      30             : #include "lt-xml.h"
      31             : 
      32             : 
      33             : struct _lt_xml_t {
      34             :         lt_mem_t  parent;
      35             :         xmlDocPtr subtag_registry;
      36             :         xmlDocPtr cldr_bcp47_calendar;
      37             :         xmlDocPtr cldr_bcp47_collation;
      38             :         xmlDocPtr cldr_bcp47_currency;
      39             :         xmlDocPtr cldr_bcp47_number;
      40             :         xmlDocPtr cldr_bcp47_timezone;
      41             :         xmlDocPtr cldr_bcp47_transform;
      42             :         xmlDocPtr cldr_bcp47_variant;
      43             :         xmlDocPtr cldr_supplemental_likelysubtags;
      44             : };
      45             : 
      46             : static lt_xml_t *__xml = NULL;
      47             : #ifndef _WIN32
      48             : static pthread_mutex_t __lt_xml_lock = PTHREAD_MUTEX_INITIALIZER;
      49             : #endif
      50             : 
      51             : /*< private >*/
      52             : static lt_bool_t
      53           4 : lt_xml_read_subtag_registry(lt_xml_t  *xml,
      54             :                             lt_error_t   **error)
      55             : {
      56             :         lt_string_t *regfile;
      57           4 :         xmlParserCtxtPtr xmlparser = NULL;
      58           4 :         xmlDocPtr doc = NULL;
      59           4 :         lt_error_t *err = NULL;
      60             : 
      61           4 :         lt_return_val_if_fail (xml != NULL, FALSE);
      62             : 
      63           4 :         regfile = lt_string_new(NULL);
      64             : #ifdef GNOME_ENABLE_DEBUG
      65             :         LT_STMT_START {
      66             :                 struct stat st;
      67             : 
      68             :                 lt_string_append_filename(regfile,
      69             :                                           BUILDDIR,
      70             :                                           "data", "language-subtag-reegistry.xml", NULL);
      71             :                 if (stat(lt_string_value(regfile), &st) == -1) {
      72             :                         lt_string_clear(regfile);
      73             : #endif
      74           4 :         lt_string_append_filename(regfile,
      75             :                                   lt_db_get_datadir(),
      76             :                                   "language-subtag-registry.xml", NULL);
      77             : #ifdef GNOME_ENABLE_DEBUG
      78             :                 }
      79             :         } LT_STMT_END;
      80             : #endif
      81           4 :         xmlparser = xmlNewParserCtxt();
      82           4 :         if (!xmlparser) {
      83           0 :                 lt_error_set(&err, LT_ERR_OOM,
      84             :                              "Unable to create an instance of xmlParserCtxt.");
      85           0 :                 goto bail;
      86             :         }
      87           4 :         doc = xmlCtxtReadFile(xmlparser, lt_string_value(regfile), "UTF-8", 0);
      88           4 :         if (!doc) {
      89           0 :                 lt_error_set(&err, LT_ERR_FAIL_ON_XML,
      90             :                              "Unable to read the xml file: %s",
      91             :                              lt_string_value(regfile));
      92           0 :                 goto bail;
      93             :         }
      94           4 :         xml->subtag_registry = doc;
      95           4 :         lt_mem_add_ref(&xml->parent, xml->subtag_registry,
      96             :                        (lt_destroy_func_t)xmlFreeDoc);
      97             : 
      98             :   bail:
      99           4 :         lt_string_unref(regfile);
     100           4 :         if (xmlparser)
     101           4 :                 xmlFreeParserCtxt(xmlparser);
     102             : 
     103           4 :         if (lt_error_is_set(err, LT_ERR_ANY)) {
     104           0 :                 if (error)
     105           0 :                         *error = lt_error_ref(err);
     106             :                 else
     107           0 :                         lt_error_print(err, LT_ERR_ANY);
     108           0 :                 lt_error_unref(err);
     109             : 
     110           0 :                 return FALSE;
     111             :         }
     112             : 
     113           4 :         return TRUE;
     114             : }
     115             : 
     116             : static lt_bool_t
     117          44 : lt_xml_read_cldr_bcp47(lt_xml_t     *xml,
     118             :                        const char   *filename,
     119             :                        xmlDocPtr    *doc,
     120             :                        lt_error_t  **error)
     121             : {
     122             :         lt_string_t *regfile;
     123          44 :         xmlParserCtxtPtr xmlparser = NULL;
     124          44 :         lt_error_t *err = NULL;
     125             : 
     126          44 :         lt_return_val_if_fail (xml != NULL, FALSE);
     127             : 
     128          44 :         regfile = lt_string_new(NULL);
     129             : #ifdef GNOME_ENABLE_DEBUG
     130             :         LT_STMT_START {
     131             :                 struct stat st;
     132             : 
     133             :                 lt_string_append_filename(regfile,
     134             :                                           SRCDIR, "data", "common", "bcp47",
     135             :                                           filename, NULL);
     136             :                 if (stat(lt_string_value(regfile), &st) == -1) {
     137             :                         lt_string_clear(regfile);
     138             : #endif
     139          44 :         lt_string_append_filename(regfile,
     140             :                                   lt_db_get_datadir(),
     141             :                                   "common", "bcp47", filename, NULL);
     142             : #ifdef GNOME_ENABLE_DEBUG
     143             :                 }
     144             :         } LT_STMT_END;
     145             : #endif
     146          44 :         xmlparser = xmlNewParserCtxt();
     147          44 :         if (!xmlparser) {
     148           0 :                 lt_error_set(&err, LT_ERR_OOM,
     149             :                              "Unable to create an instance of xmlParserCtxt.");
     150           0 :                 goto bail;
     151             :         }
     152          44 :         *doc = xmlCtxtReadFile(xmlparser, lt_string_value(regfile), "UTF-8", 0);
     153          44 :         if (!*doc) {
     154           0 :                 lt_error_set(&err, LT_ERR_FAIL_ON_XML,
     155             :                              "Unable to read the xml file: %s",
     156             :                              lt_string_value(regfile));
     157           0 :                 goto bail;
     158             :         }
     159          44 :         lt_mem_add_ref(&xml->parent, *doc,
     160             :                        (lt_destroy_func_t)xmlFreeDoc);
     161             : 
     162             :   bail:
     163          44 :         lt_string_unref(regfile);
     164          44 :         if (xmlparser)
     165          44 :                 xmlFreeParserCtxt(xmlparser);
     166             : 
     167          44 :         if (lt_error_is_set(err, LT_ERR_ANY)) {
     168           0 :                 if (error)
     169           0 :                         *error = lt_error_ref(err);
     170             :                 else
     171           0 :                         lt_error_print(err, LT_ERR_ANY);
     172           0 :                 lt_error_unref(err);
     173             : 
     174           0 :                 return FALSE;
     175             :         }
     176             : 
     177          44 :         return TRUE;
     178             : }
     179             : 
     180             : static lt_bool_t
     181           4 : lt_xml_read_cldr_supplemental(lt_xml_t     *xml,
     182             :                               const char   *filename,
     183             :                               xmlDocPtr    *doc,
     184             :                               lt_error_t  **error)
     185             : {
     186           4 :         lt_string_t *regfile = NULL;
     187           4 :         xmlParserCtxtPtr xmlparser = NULL;
     188           4 :         lt_error_t *err = NULL;
     189             : 
     190           4 :         lt_return_val_if_fail (xml != NULL, FALSE);
     191             : 
     192           4 :         regfile = lt_string_new(NULL);
     193             : #ifdef GNOME_ENABLE_DEBUG
     194             :         LT_STMT_START {
     195             :                 struct stat st;
     196             : 
     197             :                 lt_string_append_filename(regfile,
     198             :                                           SRCDIR, "data", "common", "supplemental",
     199             :                                           filename, NULL);
     200             :                 if (stat(lt_string_value(regfile), &st) == -1) {
     201             :                         lt_string_clear(regfile);
     202             : #endif
     203           4 :         lt_string_append_filename(regfile,
     204             :                                   lt_db_get_datadir(),
     205             :                                   "common", "supplemental", filename, NULL);
     206             : #ifdef GNOME_ENABLE_DEBUG
     207             :                 }
     208             :         } LT_STMT_END;
     209             : #endif
     210           4 :         xmlparser = xmlNewParserCtxt();
     211           4 :         if (!xmlparser) {
     212           0 :                 lt_error_set(&err, LT_ERR_OOM,
     213             :                              "Unable to create an instance of xmlParserCtxt.");
     214           0 :                 goto bail;
     215             :         }
     216           4 :         *doc = xmlCtxtReadFile(xmlparser, lt_string_value(regfile), "UTF-8", 0);
     217           4 :         if (!*doc) {
     218           0 :                 lt_error_set(&err, LT_ERR_FAIL_ON_XML,
     219             :                              "Unable to read the xml file: %s",
     220             :                              lt_string_value(regfile));
     221           0 :                 goto bail;
     222             :         }
     223           4 :         lt_mem_add_ref(&xml->parent, *doc,
     224             :                        (lt_destroy_func_t)xmlFreeDoc);
     225             : 
     226             :   bail:
     227           4 :         lt_string_unref(regfile);
     228           4 :         if (xmlparser)
     229           4 :                 xmlFreeParserCtxt(xmlparser);
     230             : 
     231           4 :         if (lt_error_is_set(err, LT_ERR_ANY)) {
     232           0 :                 if (error)
     233           0 :                         *error = lt_error_ref(err);
     234             :                 else
     235           0 :                         lt_error_print(err, LT_ERR_ANY);
     236           0 :                 lt_error_unref(err);
     237             : 
     238           0 :                 return FALSE;
     239             :         }
     240             : 
     241           4 :         return TRUE;
     242             : }
     243             : 
     244             : static lt_bool_t
     245          16 : _lt_xml_merge_keys(lt_xml_t    *xml,
     246             :                    xmlDocPtr    doc1,
     247             :                    xmlDocPtr    doc2,
     248             :                    lt_error_t **error)
     249             : {
     250          16 :         xmlXPathContextPtr xctxt = NULL;
     251          16 :         xmlXPathObjectPtr xobj = NULL;
     252             :         xmlNodePtr parent_node;
     253             :         int i, n;
     254          16 :         lt_bool_t retval = FALSE;
     255             : 
     256          16 :         xctxt = xmlXPathNewContext(doc1);
     257          16 :         if (!xctxt) {
     258           0 :                 lt_error_set(error, LT_ERR_OOM,
     259             :                              "Unable to create an instance of xmlXPathContextPtr");
     260           0 :                 goto bail;
     261             :         }
     262          16 :         xobj = xmlXPathEvalExpression((const xmlChar *)"/ldmlBCP47/keyword", xctxt);
     263          16 :         if (!xobj) {
     264           0 :                 lt_error_set(error, LT_ERR_FAIL_ON_XML,
     265             :                              "No valid elements for %s: keyword",
     266             :                              doc1->name);
     267           0 :                 goto bail;
     268             :         }
     269          16 :         if ((n = xmlXPathNodeSetGetLength(xobj->nodesetval)) != 1) {
     270           0 :                 lt_error_set(error, LT_ERR_FAIL_ON_XML,
     271             :                              "Too many keyword elements in %s: %s", doc1->name, doc2->name);
     272           0 :                 goto bail;
     273             :         }
     274          16 :         parent_node = xmlXPathNodeSetItem(xobj->nodesetval, 0);
     275          16 :         xmlXPathFreeObject(xobj);
     276          16 :         xmlXPathFreeContext(xctxt);
     277          16 :         xobj = NULL;
     278          16 :         xctxt = NULL;
     279             : 
     280          16 :         xctxt = xmlXPathNewContext(doc2);
     281          16 :         if (!xctxt) {
     282           0 :                 lt_error_set(error, LT_ERR_OOM,
     283             :                              "Unable to create an instance of xmlXPathContextPtr");
     284           0 :                 goto bail;
     285             :         }
     286          16 :         xobj = xmlXPathEvalExpression((const xmlChar *)"/ldmlBCP47/keyword/key", xctxt);
     287          16 :         if (!xobj) {
     288           0 :                 lt_error_set(error, LT_ERR_FAIL_ON_XML,
     289             :                              "No valid elements for %s: key",
     290             :                              doc2->name);
     291           0 :                 goto bail;
     292             :         }
     293          16 :         n = xmlXPathNodeSetGetLength(xobj->nodesetval);
     294          32 :         for (i = 0; i < n; i++) {
     295          16 :                 xmlNodePtr p = xmlDocCopyNode(xmlXPathNodeSetItem(xobj->nodesetval, i), doc1, 1);
     296             : 
     297          16 :                 xmlAddChild(parent_node, p);
     298             :         }
     299             : 
     300          16 :         retval = TRUE;
     301             :   bail:
     302          16 :         if (xobj)
     303          16 :                 xmlXPathFreeObject(xobj);
     304          16 :         if (xctxt)
     305          16 :                 xmlXPathFreeContext(xctxt);
     306          16 :         lt_mem_remove_ref(&xml->parent, doc2);
     307          16 :         xmlFreeDoc(doc2);
     308             : 
     309          16 :         return retval;
     310             : }
     311             : 
     312             : /*< public >*/
     313             : lt_xml_t *
     314          28 : lt_xml_new(void)
     315             : {
     316          28 :         lt_error_t *err = NULL;
     317             : 
     318             : #ifdef _WIN32
     319             :        HANDLE __lt_xml_lock = CreateMutex(NULL, FALSE, NULL);
     320             : #else
     321          28 :         pthread_mutex_lock(&__lt_xml_lock);
     322             : #endif
     323             : 
     324          28 :         if (__xml) {
     325             : #ifdef _WIN32
     326             :                 ReleaseMutex(__lt_xml_lock);
     327             : #else
     328          24 :                 pthread_mutex_unlock(&__lt_xml_lock);
     329             : #endif
     330          24 :                 return lt_xml_ref(__xml);
     331             :         }
     332             : 
     333           4 :         __xml = lt_mem_alloc_object(sizeof (lt_xml_t));
     334           4 :         if (__xml) {
     335           4 :                 xmlDocPtr doc = NULL;
     336             : 
     337           4 :                 lt_mem_add_weak_pointer(&__xml->parent, (lt_pointer_t *)&__xml);
     338           4 :                 if (!lt_xml_read_subtag_registry(__xml, &err))
     339             :                         goto bail;
     340           4 :                 if (!lt_xml_read_cldr_bcp47(__xml, "calendar.xml",
     341           4 :                                             &__xml->cldr_bcp47_calendar,
     342             :                                             &err))
     343             :                         goto bail;
     344           4 :                 if (!lt_xml_read_cldr_bcp47(__xml, "collation.xml",
     345           4 :                                             &__xml->cldr_bcp47_collation,
     346             :                                             &err))
     347             :                         goto bail;
     348           4 :                 if (!lt_xml_read_cldr_bcp47(__xml, "currency.xml",
     349           4 :                                             &__xml->cldr_bcp47_currency,
     350             :                                             &err))
     351             :                         goto bail;
     352           4 :                 if (!lt_xml_read_cldr_bcp47(__xml, "number.xml",
     353           4 :                                             &__xml->cldr_bcp47_number,
     354             :                                             &err))
     355             :                         goto bail;
     356           4 :                 if (!lt_xml_read_cldr_bcp47(__xml, "timezone.xml",
     357           4 :                                             &__xml->cldr_bcp47_timezone,
     358             :                                             &err))
     359             :                         goto bail;
     360           4 :                 if (!lt_xml_read_cldr_bcp47(__xml, "transform.xml",
     361           4 :                                             &__xml->cldr_bcp47_transform,
     362             :                                             &err))
     363             :                         goto bail;
     364           4 :                 if (!lt_xml_read_cldr_bcp47(__xml, "transform_ime.xml",
     365             :                                             &doc,
     366             :                                             &err))
     367             :                         goto bail;
     368           4 :                 if (!_lt_xml_merge_keys(__xml, __xml->cldr_bcp47_transform, doc, &err))
     369             :                         goto bail;
     370           4 :                 if (!lt_xml_read_cldr_bcp47(__xml, "transform_keyboard.xml",
     371             :                                             &doc,
     372             :                                             &err))
     373             :                         goto bail;
     374           4 :                 if (!_lt_xml_merge_keys(__xml, __xml->cldr_bcp47_transform, doc, &err))
     375             :                         goto bail;
     376           4 :                 if (!lt_xml_read_cldr_bcp47(__xml, "transform_mt.xml",
     377             :                                             &doc,
     378             :                                             &err))
     379             :                         goto bail;
     380           4 :                 if (!_lt_xml_merge_keys(__xml, __xml->cldr_bcp47_transform, doc, &err))
     381             :                         goto bail;
     382           4 :                 if (!lt_xml_read_cldr_bcp47(__xml, "transform_private_use.xml",
     383             :                                             &doc,
     384             :                                             &err))
     385             :                         goto bail;
     386           4 :                 if (!_lt_xml_merge_keys(__xml, __xml->cldr_bcp47_transform, doc, &err))
     387             :                         goto bail;
     388           4 :                 if (!lt_xml_read_cldr_bcp47(__xml, "variant.xml",
     389           4 :                                             &__xml->cldr_bcp47_variant,
     390             :                                             &err))
     391             :                         goto bail;
     392           4 :                 if (!lt_xml_read_cldr_supplemental(__xml, "likelySubtags.xml",
     393           4 :                                                    &__xml->cldr_supplemental_likelysubtags,
     394             :                                                    &err))
     395             :                         goto bail;
     396             :         }
     397             : 
     398             :   bail:
     399           4 :         if (lt_error_is_set(err, LT_ERR_ANY)) {
     400           0 :                 lt_error_print(err, LT_ERR_ANY);
     401           0 :                 lt_error_unref(err);
     402           0 :                 lt_xml_unref(__xml);
     403             :         }
     404             : 
     405             : #ifdef _WIN32
     406             :         ReleaseMutex(__lt_xml_lock);
     407             : #else
     408           4 :         pthread_mutex_unlock(&__lt_xml_lock);
     409             : #endif
     410           4 :         return __xml;
     411             : }
     412             : 
     413             : lt_xml_t *
     414          24 : lt_xml_ref(lt_xml_t *xml)
     415             : {
     416          24 :         lt_return_val_if_fail (xml != NULL, NULL);
     417             : 
     418          24 :         return lt_mem_ref(&xml->parent);
     419             : }
     420             : 
     421             : void
     422          28 : lt_xml_unref(lt_xml_t *xml)
     423             : {
     424          28 :         if (xml)
     425          28 :                 lt_mem_unref(&xml->parent);
     426          28 : }
     427             : 
     428             : const xmlDocPtr
     429          28 : lt_xml_get_subtag_registry(lt_xml_t *xml)
     430             : {
     431          28 :         lt_return_val_if_fail (xml != NULL, NULL);
     432             : 
     433          28 :         return xml->subtag_registry;
     434             : }
     435             : 
     436             : const xmlDocPtr
     437           0 : lt_xml_get_cldr(lt_xml_t      *xml,
     438             :                 lt_xml_cldr_t  type)
     439             : {
     440           0 :         lt_return_val_if_fail (xml != NULL, NULL);
     441             : 
     442           0 :         switch (type) {
     443             :             case LT_XML_CLDR_BCP47_CALENDAR:
     444           0 :                     return xml->cldr_bcp47_calendar;
     445             :             case LT_XML_CLDR_BCP47_COLLATION:
     446           0 :                     return xml->cldr_bcp47_collation;
     447             :             case LT_XML_CLDR_BCP47_CURRENCY:
     448           0 :                     return xml->cldr_bcp47_currency;
     449             :             case LT_XML_CLDR_BCP47_NUMBER:
     450           0 :                     return xml->cldr_bcp47_number;
     451             :             case LT_XML_CLDR_BCP47_TIMEZONE:
     452           0 :                     return xml->cldr_bcp47_timezone;
     453             :             case LT_XML_CLDR_BCP47_TRANSFORM:
     454           0 :                     return xml->cldr_bcp47_transform;
     455             :             case LT_XML_CLDR_BCP47_VARIANT:
     456           0 :                     return xml->cldr_bcp47_variant;
     457             :             case LT_XML_CLDR_SUPPLEMENTAL_LIKELY_SUBTAGS:
     458           0 :                     return xml->cldr_supplemental_likelysubtags;
     459             :             default:
     460           0 :                     break;
     461             :         }
     462             : 
     463           0 :         return NULL;
     464             : }

Generated by: LCOV version 1.10