- add hash table support.

- make use of __UNCONST() instead of LINTED.
This commit is contained in:
tshiozak 2004-09-23 16:44:26 +00:00
parent ef820af6db
commit 29be49b448
5 changed files with 182 additions and 25 deletions

View File

@ -1,9 +1,9 @@
# $NetBSD: Makefile,v 1.3 2004/01/18 08:40:40 yamt Exp $
# $NetBSD: Makefile,v 1.4 2004/09/23 16:44:26 tshiozak Exp $
.include <bsd.own.mk>
LIB= intl
SRCS= gettext.c textdomain.c gettext_iconv.c gettext_dummy.c
SRCS= gettext.c textdomain.c gettext_iconv.c gettext_dummy.c strhash.c
INCS= libintl.h
INCSDIR=/usr/include

View File

@ -1,4 +1,4 @@
/* $NetBSD: gettext.c,v 1.18 2004/01/18 08:40:40 yamt Exp $ */
/* $NetBSD: gettext.c,v 1.19 2004/09/23 16:44:26 tshiozak Exp $ */
/*-
* Copyright (c) 2000, 2001 Citrus Project,
@ -29,13 +29,14 @@
*/
#include <sys/cdefs.h>
__RCSID("$NetBSD: gettext.c,v 1.18 2004/01/18 08:40:40 yamt Exp $");
__RCSID("$NetBSD: gettext.c,v 1.19 2004/09/23 16:44:26 tshiozak Exp $");
#include <sys/param.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <sys/uio.h>
#include <assert.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
@ -189,25 +190,25 @@ fail:
if (t) {
if (c) {
snprintf(tmp, sizeof(tmp), "%s_%s.%s@%s",
l, t, c, m);
l, t, c, m);
strlcat(result, tmp, sizeof(result));
strlcat(result, ":", sizeof(result));
}
snprintf(tmp, sizeof(tmp), "%s_%s@%s", l, t, m);
snprintf(tmp, sizeof(tmp), "%s_%s@%s", l, t, m);
strlcat(result, tmp, sizeof(result));
strlcat(result, ":", sizeof(result));
}
snprintf(tmp, sizeof(tmp), "%s@%s", l, m);
snprintf(tmp, sizeof(tmp), "%s@%s", l, m);
strlcat(result, tmp, sizeof(result));
strlcat(result, ":", sizeof(result));
}
if (t) {
if (c) {
snprintf(tmp, sizeof(tmp), "%s_%s.%s", l, t, c);
snprintf(tmp, sizeof(tmp), "%s_%s.%s", l, t, c);
strlcat(result, tmp, sizeof(result));
strlcat(result, ":", sizeof(result));
}
snprintf(tmp, sizeof(tmp), "%s_%s", l, t);
snprintf(tmp, sizeof(tmp), "%s_%s", l, t);
strlcat(result, tmp, sizeof(result));
strlcat(result, ":", sizeof(result));
}
@ -309,6 +310,7 @@ mapit(path, db)
char *base;
u_int32_t magic, revision;
struct moentry *otable, *ttable;
const u_int32_t *htable;
struct moentry_h *p;
struct mo *mo;
size_t l;
@ -338,8 +340,18 @@ mapit(path, db)
close(fd);
goto fail;
}
if (read(fd, &revision, sizeof(revision)) != sizeof(revision) ||
flip(revision, magic) != MO_REVISION) {
if (read(fd, &revision, sizeof(revision)) != sizeof(revision)) {
close(fd);
goto fail;
}
switch (flip(revision, magic)) {
case MO_MAKE_REV(0, 0):
#if 0
case MO_MAKE_REV(0, 1):
case MO_MAKE_REV(1, 1):
#endif
break;
default:
close(fd);
goto fail;
}
@ -359,9 +371,12 @@ mapit(path, db)
mohandle->mo.mo_magic = mo->mo_magic;
mohandle->mo.mo_revision = flip(mo->mo_revision, magic);
mohandle->mo.mo_nstring = flip(mo->mo_nstring, magic);
mohandle->mo.mo_hsize = flip(mo->mo_hsize, magic);
/* validate otable/ttable */
/* LINTED: ignore the alignment problem. */
otable = (struct moentry *)(base + flip(mo->mo_otable, magic));
/* LINTED: ignore the alignment problem. */
ttable = (struct moentry *)(base + flip(mo->mo_ttable, magic));
if (!validate(otable, mohandle) ||
!validate(&otable[mohandle->mo.mo_nstring], mohandle)) {
@ -408,7 +423,26 @@ mapit(path, db)
goto fail;
}
}
/* allocate htable, and convert it to the host order. */
if (mohandle->mo.mo_hsize > 2) {
l = sizeof(u_int32_t) * mohandle->mo.mo_hsize;
mohandle->mo.mo_htable = (u_int32_t *)malloc(l);
if (!mohandle->mo.mo_htable) {
unmapit(db);
goto fail;
}
/* LINTED: ignore the alignment problem. */
htable = (const u_int32_t *)(base+flip(mo->mo_hoffset, magic));
for (i=0; i < mohandle->mo.mo_hsize; i++) {
mohandle->mo.mo_htable[i] = flip(htable[i], magic);
if (mohandle->mo.mo_htable[i] >=
mohandle->mo.mo_nstring+1) {
/* illegal string number. */
unmapit(db);
goto fail;
}
}
}
/* grab MIME-header and charset field */
mohandle->mo.mo_header = lookup("", db);
if (mohandle->mo.mo_header)
@ -454,22 +488,63 @@ unmapit(db)
free(mohandle->mo.mo_ttable);
if (mohandle->mo.mo_charset)
free(mohandle->mo.mo_charset);
if (mohandle->mo.mo_htable)
free(mohandle->mo.mo_htable);
memset(&mohandle->mo, 0, sizeof(mohandle->mo));
return 0;
}
/*
* calculate the step value if the hash value is conflicted.
*/
static __inline u_int32_t
calc_collision_step(u_int32_t hashval, u_int32_t hashsize)
{
_DIAGASSERT(hashsize>2);
return (hashval % (hashsize - 2)) + 1;
}
/*
* calculate the next index while conflicting.
*/
static __inline u_int32_t
calc_next_index(u_int32_t curidx, u_int32_t hashsize, u_int32_t step)
{
return curidx+step - (curidx >= hashsize-step ? hashsize : 0);
}
/* ARGSUSED */
static const char *
lookup_hash(msgid, db)
const char *msgid;
struct domainbinding *db;
{
struct mohandle *mohandle = &db->mohandle;
u_int32_t idx, hashval, step, strno;
size_t len;
/*
* XXX should try a hashed lookup here, but to do so, we need to
* look inside the GPL'ed *.c and re-implement...
*/
return NULL;
if (mohandle->mo.mo_hsize <= 2 || mohandle->mo.mo_htable == NULL)
return NULL;
hashval = __intl_string_hash(msgid);
step = calc_collision_step(hashval, mohandle->mo.mo_hsize);
idx = hashval % mohandle->mo.mo_hsize;
len = strlen(msgid);
while (/*CONSTCOND*/1) {
strno = mohandle->mo.mo_htable[idx];
if (strno == 0) {
/* unexpected miss */
return NULL;
}
strno--;
if (len <= mohandle->mo.mo_otable[strno].len &&
!strcmp(msgid, mohandle->mo.mo_otable[strno].off)) {
/* hit */
return mohandle->mo.mo_ttable[strno].off;
}
idx = calc_next_index(idx, mohandle->mo.mo_hsize, step);
}
/*NOTREACHED*/
}
static const char *
@ -576,7 +651,7 @@ dcngettext(domainname, msgid1, msgid2, n, category)
lpath = get_lang_env(cname);
if (!lpath)
goto fail;
for (db = __bindings; db; db = db->next)
if (strcmp(db->domainname, domainname) == 0)
break;
@ -650,6 +725,5 @@ found:
}
fail:
/* LINTED const cast */
return (char *)msgid;
return (char *)__UNCONST(msgid);
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: libintl_local.h,v 1.7 2004/01/18 08:40:40 yamt Exp $ */
/* $NetBSD: libintl_local.h,v 1.8 2004/09/23 16:44:26 tshiozak Exp $ */
/*-
* Copyright (c) 2000, 2001 Citrus Project,
@ -30,7 +30,9 @@
#define MO_MAGIC 0x950412de
#define MO_MAGIC_SWAPPED 0xde120495
#define MO_REVISION 0
#define MO_GET_REV_MAJOR(r) (((r) >> 16) & 0xFFFF)
#define MO_GET_REV_MINOR(r) ((r) & 0xFFFF)
#define MO_MAKE_REV(maj, min) (((maj) << 16) | (min))
#define GETTEXT_MMAP_MAX (1024 * 1024) /*XXX*/
@ -45,6 +47,13 @@ struct mo {
u_int32_t mo_ttable; /* T: translated text table offset */
u_int32_t mo_hsize; /* S: size of hashing table */
u_int32_t mo_hoffset; /* H: offset of hashing table */
/* rev 0.1 / 1.1 */
/* system dependent string support */
u_int32_t mo_sysdep_nsegs; /* number of sysdep segments */
u_int32_t mo_sysdep_segoff; /* offset of sysdep segment table */
u_int32_t mo_sysdep_nstring; /* number of strings */
u_int32_t mo_sysdep_otable; /* offset of original text table */
u_int32_t mo_sysdep_ttable; /* offset of translated text table */
} __attribute__((__packed__));
struct moentry {
@ -52,6 +61,12 @@ struct moentry {
u_int32_t off; /* offset of \0-terminated string */
} __attribute__((__packed__));
struct mosysdepstr
{
u_int32_t off; /* offset of seed text */
struct moentry segs[1]; /* text segments */
} __attribute__((__packed__));
/* libintl internal data format */
struct moentry_h {
size_t len; /* strlen(str), so region will be len + 1 */
@ -66,6 +81,8 @@ struct mo_h {
struct moentry_h *mo_ttable; /* T: translated text table offset */
const char *mo_header;
char *mo_charset;
u_int32_t mo_hsize; /* S: size of hashing table */
u_int32_t *mo_htable; /* H: hashing table */
};
struct mohandle {
@ -85,4 +102,7 @@ struct domainbinding {
extern struct domainbinding *__bindings;
extern char __current_domainname[PATH_MAX];
__BEGIN_DECLS
const char *__gettext_iconv __P((const char *, struct domainbinding *));
u_int32_t __intl_string_hash __P((const char *));
__END_DECLS

63
lib/libintl/strhash.c Normal file
View File

@ -0,0 +1,63 @@
/* $NetBSD: strhash.c,v 1.1 2004/09/23 16:44:26 tshiozak Exp $ */
/*-
* Copyright (c)2003, 2004 Citrus Project,
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
#if defined(LIBC_SCCS) && !defined(lint)
__RCSID("$NetBSD: strhash.c,v 1.1 2004/09/23 16:44:26 tshiozak Exp $");
#endif /* LIBC_SCCS and not lint */
#include <sys/param.h>
#include <sys/types.h>
#include <assert.h>
#include <stdio.h>
#include <string.h>
#include "libintl_local.h"
/*
* string hash function by P.J.Weinberger.
* this implementation is derived from src/lib/libc/citrus/citrus_db_hash.c.
*/
u_int32_t
/*ARGSUSED*/
__intl_string_hash(const char *str)
{
const u_int8_t *p;
u_int32_t hash = 0, tmp;
for (p = (const u_int8_t *)str; *p; p++) {
hash <<= 4;
hash += *p;
tmp = hash & 0xF0000000;
if (tmp != 0) {
hash ^= tmp;
hash ^= tmp >> 24;
}
}
return hash;
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: textdomain.c,v 1.10 2004/01/18 08:40:40 yamt Exp $ */
/* $NetBSD: textdomain.c,v 1.11 2004/09/23 16:44:26 tshiozak Exp $ */
/*-
* Copyright (c) 2000, 2001 Citrus Project,
@ -27,7 +27,7 @@
*/
#include <sys/cdefs.h>
__RCSID("$NetBSD: textdomain.c,v 1.10 2004/01/18 08:40:40 yamt Exp $");
__RCSID("$NetBSD: textdomain.c,v 1.11 2004/09/23 16:44:26 tshiozak Exp $");
#include <sys/param.h>
@ -98,7 +98,7 @@ bindtextdomain(domainname, dirname)
if (p)
return (p->path);
else
return _PATH_TEXTDOMAIN;
return (char *)__UNCONST(_PATH_TEXTDOMAIN);
}
strlcpy(p->path, dirname, sizeof(p->path));