-/* This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
-
- (C) 2001 by The Genes Development Team
- Original author: Peter Verthez (Peter.Verthez@advalvas.be)
-*/
+/* Conversion between encodings.
+ Copyright (C) 2001,2002 The Genes Development Team
+ This file is part of the Gedcom parser library.
+ Contributed by Peter Verthez <Peter.Verthez@advalvas.be>, 2001.
+
+ The Gedcom parser library is free software; you can redistribute it
+ and/or modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The Gedcom parser library is distributed in the hope that it will be
+ useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the Gedcom parser library; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
/* $Id$ */
/* $Name$ */
#include <string.h>
#include <iconv.h>
-#include <search.h>
#include <stdio.h>
#include <limits.h>
#include <stdlib.h>
#include "gedcom_internal.h"
#include "encoding.h"
+#include "hash.h"
-#define INTERNAL_ENCODING "UTF8"
#define ENCODING_CONF_FILE "gedcom.enc"
#define GCONV_SEARCH_PATH "GCONV_PATH"
#define MAXBUF 255
static iconv_t cd_to_internal = (iconv_t) -1;
-static void *encoding_mapping = NULL;
static ENCODING the_enc = ONE_BYTE;
-
-struct node {
- char *gedcom_name;
- char *iconv_name;
-};
+static hash_t *encodings = NULL;
char* charwidth_string[] = { "1", "2_HILO", "2_LOHI" };
-int node_compare(const void *node1, const void *node2)
+hnode_t *node_alloc(void *c __attribute__((unused)))
+{
+ return malloc(sizeof *node_alloc(NULL));
+}
+
+void node_free(hnode_t *n, void *c __attribute__((unused)))
{
- return strcmp(((const struct node *) node1)->gedcom_name,
- ((const struct node *) node2)->gedcom_name);
+ free((void*)hnode_getkey(n));
+ free(hnode_get(n));
+ free(n);
}
void add_encoding(char *gedcom_n, char* charwidth, char *iconv_n)
{
- void **datum;
- struct node *nodeptr = (struct node *) malloc(sizeof *nodeptr);
- nodeptr->gedcom_name = (char *) malloc(strlen(gedcom_n)
- + strlen(charwidth) + 3);
- nodeptr->iconv_name = (char *) malloc(strlen(iconv_n) + 1);
+ char *key, *val;
+
+ key = (char *) malloc(strlen(gedcom_n) + strlen(charwidth) + 3);
+ val = (char *) malloc(strlen(iconv_n) + 1);
+
/* sprintf is safe here (malloc'ed before) */
- sprintf(nodeptr->gedcom_name, "%s(%s)", gedcom_n, charwidth);
- strcpy(nodeptr->iconv_name, iconv_n);
- datum = tsearch(nodeptr, &encoding_mapping, node_compare);
- if ((datum == NULL) || (*datum != nodeptr)) {
- gedcom_warning("Duplicate entry found for encoding '%s', ignoring",
+ sprintf(key, "%s(%s)", gedcom_n, charwidth);
+ strcpy(val, iconv_n);
+
+ if (hash_lookup(encodings, key)) {
+ gedcom_warning(_("Duplicate entry found for encoding '%s', ignoring"),
gedcom_n);
+ free(key);
+ free(val);
+ }
+ else {
+ hash_alloc_insert(encodings, key, val);
}
}
char* get_encoding(char* gedcom_n, ENCODING enc)
{
- void **datum;
- struct node search_node;
- char *buffer;
- buffer = (char*)malloc(strlen(gedcom_n) + strlen(charwidth_string[enc]) + 3);
+ char *key;
+ hnode_t *node;
+
+ key = (char*)malloc(strlen(gedcom_n) + strlen(charwidth_string[enc]) + 3);
/* sprintf is safe here (malloc'ed before) */
- sprintf(buffer, "%s(%s)", gedcom_n, charwidth_string[enc]);
- search_node.gedcom_name = buffer;
- datum = tfind(&search_node, &encoding_mapping, node_compare);
- free(buffer);
- if (datum == NULL) {
- gedcom_error("No encoding found for '%s'", gedcom_n);
- return NULL;
+ sprintf(key, "%s(%s)", gedcom_n, charwidth_string[enc]);
+
+ node = hash_lookup(encodings, key);
+ free(key);
+ if (node) {
+ return hnode_get(node);
}
else {
- return ((const struct node *) *datum)->iconv_name;
+ gedcom_error(_("No encoding defined for '%s'"), gedcom_n);
+ return NULL;
+ }
+}
+
+void cleanup_encodings()
+{
+ hash_free(encodings);
+}
+
+/* Let function be called before main() */
+void update_gconv_search_path() __attribute__ ((constructor));
+
+void update_gconv_search_path()
+{
+ char *gconv_path;
+ /* Add gedcom data directory to gconv search path */
+ gconv_path = getenv(GCONV_SEARCH_PATH);
+ if (gconv_path == NULL || strstr(gconv_path, PKGDATADIR) == NULL) {
+ char *new_gconv_path;
+ if (gconv_path == NULL) {
+ new_gconv_path = (char *)malloc(strlen(GCONV_SEARCH_PATH)
+ + strlen(PKGDATADIR)
+ + 2);
+ sprintf(new_gconv_path, "%s=%s", GCONV_SEARCH_PATH, PKGDATADIR);
+ }
+ else {
+ new_gconv_path = (char *)malloc(strlen(GCONV_SEARCH_PATH)
+ + strlen(gconv_path)
+ + strlen(PKGDATADIR)
+ + 3);
+ sprintf(new_gconv_path, "%s=%s:%s",
+ GCONV_SEARCH_PATH, gconv_path, PKGDATADIR);
+ }
+ /* Ignore failures of putenv (can't do anything about it anyway) */
+ putenv(new_gconv_path);
}
}
void init_encodings()
{
- if (encoding_mapping == NULL) {
+ if (encodings == NULL) {
FILE *in;
char buffer[MAXBUF + 1];
char gedcom_n[MAXBUF + 1];
char charwidth[MAXBUF + 1];
char iconv_n[MAXBUF + 1];
- char *gconv_path;
-
- /* Add gedcom data directory to gconv search path */
- gconv_path = getenv(GCONV_SEARCH_PATH);
- if (gconv_path == NULL || strstr(gconv_path, PKGDATADIR) == NULL) {
- char *new_gconv_path;
- if (gconv_path == NULL) {
- new_gconv_path = (char *)malloc(strlen(GCONV_SEARCH_PATH)
- + strlen(PKGDATADIR)
- + 2);
- sprintf(new_gconv_path, "%s=%s", GCONV_SEARCH_PATH, PKGDATADIR);
- }
- else {
- new_gconv_path = (char *)malloc(strlen(GCONV_SEARCH_PATH)
- + strlen(gconv_path)
- + strlen(PKGDATADIR)
- + 3);
- sprintf(new_gconv_path, "%s=%s:%s",
- GCONV_SEARCH_PATH, gconv_path, PKGDATADIR);
- }
- if (putenv(new_gconv_path) != 0) {
- gedcom_warning("Failed updating environment variable %s",
- GCONV_SEARCH_PATH);
- }
- printf("%s\n", new_gconv_path);
- }
+
+ atexit(cleanup_encodings);
+
+ encodings = hash_create(HASHCOUNT_T_MAX, NULL, NULL);
+ hash_set_allocator(encodings, node_alloc, node_free, NULL);
/* Open gedcom configuration file and read */
in = fopen(ENCODING_CONF_FILE, "r");
in = fopen(path, "r");
}
if (in == NULL) {
- gedcom_warning("Could not open encoding configuration file '%s'",
+ gedcom_warning(_("Could not open encoding configuration file '%s'"),
ENCODING_CONF_FILE);
}
else {
+ line_no = 1;
while (fgets(buffer, sizeof(buffer), in) != NULL) {
if (buffer[strlen(buffer) - 1] != '\n') {
- gedcom_error("Line too long in encoding configuration file '%s'",
+ gedcom_error(_("Line too long in encoding configuration file '%s'"),
ENCODING_CONF_FILE);
return;
}
add_encoding(gedcom_n, charwidth, iconv_n);
}
else {
- gedcom_error("Missing data in encoding configuration file '%s'",
+ gedcom_error(_("Missing data in encoding configuration file '%s'"),
ENCODING_CONF_FILE);
return;
}
conv_buf_size = 0;
cd_to_internal = iconv_open(INTERNAL_ENCODING, encoding);
if (cd_to_internal == (iconv_t) -1) {
- gedcom_error("Error opening conversion context for encoding %s: %s",
+ gedcom_error(_("Error opening conversion context for encoding %s: %s"),
encoding, strerror(errno));
}
}