2 /* $NetBSD: citrus_mapper.c,v 1.7 2008/07/25 14:05:25 christos Exp $ */
5 * Copyright (c)2003 Citrus Project,
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 #include <sys/cdefs.h>
31 #include <sys/types.h>
33 #include <sys/queue.h>
42 #include "citrus_namespace.h"
43 #include "citrus_types.h"
44 #include "citrus_region.h"
45 #include "citrus_lock.h"
46 #include "citrus_memstream.h"
47 #include "citrus_bcs.h"
48 #include "citrus_mmap.h"
49 #include "citrus_module.h"
50 #include "citrus_hash.h"
51 #include "citrus_mapper.h"
53 #define _CITRUS_MAPPER_DIR "mapper.dir"
55 #define CM_HASH_SIZE 101
56 #define REFCOUNT_PERSISTENT -1
58 struct _citrus_mapper_area {
59 _CITRUS_HASH_HEAD(, _citrus_mapper, CM_HASH_SIZE) ma_cache;
64 * _citrus_mapper_create_area:
69 _citrus_mapper_create_area(
70 struct _citrus_mapper_area *__restrict *__restrict rma,
71 const char *__restrict area)
73 struct _citrus_mapper_area *ma;
85 snprintf(path, (size_t)PATH_MAX, "%s/%s", area, _CITRUS_MAPPER_DIR);
87 ret = stat(path, &st);
91 ma = malloc(sizeof(*ma));
96 ma->ma_dir = strdup(area);
97 if (ma->ma_dir == NULL) {
102 _CITRUS_HASH_INIT(&ma->ma_cache, CM_HASH_SIZE);
114 * lookup_mapper_entry:
115 * lookup mapper.dir entry in the specified directory.
117 * line format of iconv.dir file:
119 * mapper : mapper name.
120 * module : mapper module name.
121 * arg : argument for the module (generally, description file name)
125 lookup_mapper_entry(const char *dir, const char *mapname, void *linebuf,
126 size_t linebufsize, const char **module, const char **variable)
129 struct _memstream ms;
136 /* create mapper.dir path */
137 snprintf(path, (size_t)PATH_MAX, "%s/%s", dir, _CITRUS_MAPPER_DIR);
139 /* open read stream */
140 ret = _map_file(&r, path);
144 _memstream_bind(&ms, &r);
146 /* search the line matching to the map name */
147 cp = _memstream_matchline(&ms, mapname, &len, 0);
152 if (!len || len > linebufsize - 1) {
158 /* get module name */
160 cq = _bcs_skip_nonws_len(cp, &len);
161 strlcpy(p, cp, (size_t)(cq - cp + 1));
166 cp = _bcs_skip_ws_len(cq, &len);
167 strlcpy(p, cp, len + 1);
178 * simply close a mapper. (without handling hash)
181 mapper_close(struct _citrus_mapper *cm)
186 (*cm->cm_ops->mo_uninit)(cm);
189 _citrus_unload_module(cm->cm_module);
197 * simply open a mapper. (without handling hash)
200 mapper_open(struct _citrus_mapper_area *__restrict ma,
201 struct _citrus_mapper * __restrict * __restrict rcm,
202 const char * __restrict module,
203 const char * __restrict variable)
205 struct _citrus_mapper *cm;
206 _citrus_mapper_getops_t getops;
209 /* initialize mapper handle */
210 cm = malloc(sizeof(*cm));
214 cm->cm_module = NULL;
216 cm->cm_closure = NULL;
217 cm->cm_traits = NULL;
222 ret = _citrus_load_module(&cm->cm_module, module);
227 getops = (_citrus_mapper_getops_t)
228 _citrus_find_getops(cm->cm_module, module, "mapper");
233 cm->cm_ops = malloc(sizeof(*cm->cm_ops));
238 ret = (*getops)(cm->cm_ops);
242 if (!cm->cm_ops->mo_init ||
243 !cm->cm_ops->mo_uninit ||
244 !cm->cm_ops->mo_convert ||
245 !cm->cm_ops->mo_init_state)
248 /* allocate traits structure */
249 cm->cm_traits = malloc(sizeof(*cm->cm_traits));
250 if (cm->cm_traits == NULL) {
254 /* initialize the mapper */
255 ret = (*cm->cm_ops->mo_init)(ma, cm, ma->ma_dir,
256 (const void *)variable, strlen(variable) + 1,
257 cm->cm_traits, sizeof(*cm->cm_traits));
271 * _citrus_mapper_open_direct:
275 _citrus_mapper_open_direct(struct _citrus_mapper_area *__restrict ma,
276 struct _citrus_mapper * __restrict * __restrict rcm,
277 const char * __restrict module, const char * __restrict variable)
280 return (mapper_open(ma, rcm, module, variable));
287 hash_func(const char *key)
290 return (_string_hash_func(key, CM_HASH_SIZE));
297 match_func(struct _citrus_mapper *cm, const char *key)
300 return (strcmp(cm->cm_key, key));
304 * _citrus_mapper_open:
305 * open a mapper with looking up "mapper.dir".
308 _citrus_mapper_open(struct _citrus_mapper_area *__restrict ma,
309 struct _citrus_mapper * __restrict * __restrict rcm,
310 const char * __restrict mapname)
312 struct _citrus_mapper *cm;
313 char linebuf[PATH_MAX];
314 const char *module, *variable;
321 /* search in the cache */
322 hashval = hash_func(mapname);
323 _CITRUS_HASH_SEARCH(&ma->ma_cache, cm, cm_entry, match_func, mapname,
333 /* search mapper entry */
334 ret = lookup_mapper_entry(ma->ma_dir, mapname, linebuf,
335 (size_t)PATH_MAX, &module, &variable);
341 ret = mapper_open(ma, &cm, module, variable);
345 cm->cm_key = strdup(mapname);
346 if (cm->cm_key == NULL) {
352 /* insert to the cache */
354 _CITRUS_HASH_INSERT(&ma->ma_cache, cm, cm_entry, hashval);
365 * _citrus_mapper_close:
366 * close the specified mapper.
369 _citrus_mapper_close(struct _citrus_mapper *cm)
374 if (cm->cm_refcount == REFCOUNT_PERSISTENT)
376 if (cm->cm_refcount > 0) {
377 if (--cm->cm_refcount > 0)
379 _CITRUS_HASH_REMOVE(cm, cm_entry);
389 * _citrus_mapper_set_persistent:
390 * set persistent count.
393 _citrus_mapper_set_persistent(struct _citrus_mapper * __restrict cm)
397 cm->cm_refcount = REFCOUNT_PERSISTENT;