/** * lt_region_db_new: * * Create a new instance of a #lt_region_db_t. * * Returns: (transfer full): a new instance of #lt_region_db_t. */ lt_region_db_t * lt_region_db_new(void) { lt_region_db_t *retval = lt_mem_alloc_object(sizeof (lt_region_db_t)); if (retval) { GError *err = NULL; lt_region_t *le; retval->region_entries = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, (GDestroyNotify)lt_region_unref); lt_mem_add_ref(&retval->parent, retval->region_entries, (lt_destroy_func_t)g_hash_table_destroy); le = lt_region_create(); lt_region_set_tag(le, "*"); lt_region_set_name(le, "Wildcard entry"); g_hash_table_replace(retval->region_entries, g_strdup(lt_region_get_tag(le)), le); le = lt_region_create(); lt_region_set_tag(le, ""); lt_region_set_name(le, "Empty entry"); g_hash_table_replace(retval->region_entries, g_strdup(lt_region_get_tag(le)), le); retval->xml = lt_xml_new(); if (!retval->xml) { lt_region_db_unref(retval); retval = NULL; goto bail; } lt_mem_add_ref(&retval->parent, retval->xml, (lt_destroy_func_t)lt_xml_unref); lt_region_db_parse(retval, &err); if (err) { g_printerr(err->message); lt_region_db_unref(retval); retval = NULL; g_error_free(err); } } bail: return retval; }
/** * lt_region_compare: * @v1: a #lt_region_t. * @v2: a #lt_region_t. * * Compare if @v1 and @v2 is the same object or not. * * Returns: %TRUE if it's the same, otherwise %FALSE. */ lt_bool_t lt_region_compare(const lt_region_t *v1, const lt_region_t *v2) { const char *s1, *s2; if (v1 == v2) return TRUE; s1 = v1 ? lt_region_get_tag(v1) : NULL; s2 = v2 ? lt_region_get_tag(v2) : NULL; if (lt_strcmp0(s1, "*") == 0 || lt_strcmp0(s2, "*") == 0) return TRUE; return lt_strcmp0(s1, s2) == 0; }
/** * lt_region_get_better_tag: * @region: a #lt_region_t. * * Obtains the better tag for use. this is a convenient function to get * the preferred-value if available. * * Returns: a tag string. */ const char * lt_region_get_better_tag(const lt_region_t *region) { const char *retval = lt_region_get_preferred_tag(region); if (!retval) retval = lt_region_get_tag(region); return retval; }
/** * lt_region_dump: * @region: a #lt_region_t. * * Dumps the container information to the standard output. */ void lt_region_dump(const lt_region_t *region) { lt_string_t *string = lt_string_new(NULL); const char *preferred = lt_region_get_preferred_tag(region); if (preferred) { if (lt_string_length(string) == 0) lt_string_append(string, " ("); lt_string_append_printf(string, "preferred-value: %s", preferred); } if (lt_string_length(string) > 0) lt_string_append(string, ")"); lt_info("Region: %s [%s]%s", lt_region_get_tag(region), lt_region_get_name(region), lt_string_value(string)); lt_string_unref(string); }
/*< private >*/ static gboolean lt_region_db_parse(lt_region_db_t *regiondb, GError **error) { gboolean retval = TRUE; xmlDocPtr doc = NULL; xmlXPathContextPtr xctxt = NULL; xmlXPathObjectPtr xobj = NULL; GError *err = NULL; int i, n; g_return_val_if_fail (regiondb != NULL, FALSE); doc = lt_xml_get_subtag_registry(regiondb->xml); xctxt = xmlXPathNewContext(doc); if (!xctxt) { g_set_error(&err, LT_ERROR, LT_ERR_OOM, "Unable to create an instance of xmlXPathContextPtr."); goto bail; } xobj = xmlXPathEvalExpression((const xmlChar *)"/registry/region", xctxt); if (!xobj) { g_set_error(&err, LT_ERROR, LT_ERR_FAIL_ON_XML, "No valid elements for %s", doc->name); goto bail; } n = xmlXPathNodeSetGetLength(xobj->nodesetval); for (i = 0; i < n; i++) { xmlNodePtr ent = xmlXPathNodeSetItem(xobj->nodesetval, i); xmlNodePtr cnode; xmlChar *subtag = NULL, *desc = NULL, *preferred = NULL; lt_region_t *le = NULL; gchar *s; if (!ent) { g_set_error(&err, LT_ERROR, LT_ERR_FAIL_ON_XML, "Unable to obtain the xml node via XPath."); goto bail; } cnode = ent->children; while (cnode != NULL) { if (xmlStrcmp(cnode->name, (const xmlChar *)"subtag") == 0) { if (subtag) { g_warning("Duplicate subtag element in region: previous value was '%s'", subtag); } else { subtag = xmlNodeGetContent(cnode); } } else if (xmlStrcmp(cnode->name, (const xmlChar *)"added") == 0 || xmlStrcmp(cnode->name, (const xmlChar *)"text") == 0 || xmlStrcmp(cnode->name, (const xmlChar *)"deprecated") == 0 || xmlStrcmp(cnode->name, (const xmlChar *)"comments") == 0) { /* ignore it */ } else if (xmlStrcmp(cnode->name, (const xmlChar *)"description") == 0) { /* wonder if many descriptions helps something. or is it a bug? */ if (!desc) desc = xmlNodeGetContent(cnode); } else if (xmlStrcmp(cnode->name, (const xmlChar *)"preferred-value") == 0) { if (preferred) { g_warning("Duplicate preferred-value element in region: previous value was '%s'", preferred); } else { preferred = xmlNodeGetContent(cnode); } } else { g_warning("Unknown node under /registry/region: %s", cnode->name); } cnode = cnode->next; } if (!subtag) { g_warning("No subtag node: description = '%s', preferred-value = '%s'", desc, preferred); goto bail1; } if (!desc) { g_warning("No description node: subtag = '%s', preferred-value = '%s'", subtag, preferred); goto bail1; } le = lt_region_create(); if (!le) { g_set_error(&err, LT_ERROR, LT_ERR_OOM, "Unable to create an instance of lt_region_t."); goto bail1; } lt_region_set_tag(le, (const gchar *)subtag); lt_region_set_name(le, (const gchar *)desc); if (preferred) lt_region_set_preferred_tag(le, (const gchar *)preferred); s = g_strdup(lt_region_get_tag(le)); g_hash_table_replace(regiondb->region_entries, lt_strlower(s), lt_region_ref(le)); bail1: if (subtag) xmlFree(subtag); if (desc) xmlFree(desc); if (preferred) xmlFree(preferred); lt_region_unref(le); } bail: if (err) { if (error) *error = g_error_copy(err); else g_warning(err->message); g_error_free(err); retval = FALSE; } if (xobj) xmlXPathFreeObject(xobj); if (xctxt) xmlXPathFreeContext(xctxt); return retval; }