1/* $NetBSD: citrus_mapper_serial.c,v 1.1 2003/06/25 09:51:46 tshiozak Exp $ */ 2 3/*- 4 * Copyright (c)2003 Citrus Project, 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 */ 28 29#include <sys/cdefs.h> 30#if defined(LIBC_SCCS) && !defined(lint) 31__RCSID("$NetBSD: citrus_mapper_serial.c,v 1.1 2003/06/25 09:51:46 tshiozak Exp $"); 32#endif /* LIBC_SCCS and not lint */ 33 34#include <assert.h> 35#include <errno.h> 36#include <stdio.h> 37#include <stdlib.h> 38#include <string.h> 39#include <limits.h> 40#include <sys/queue.h> 41 42#include "citrus_namespace.h" 43#include "citrus_types.h" 44#include "citrus_bcs.h" 45#include "citrus_module.h" 46#include "citrus_region.h" 47#include "citrus_memstream.h" 48#include "citrus_mmap.h" 49#include "citrus_hash.h" 50#include "citrus_mapper.h" 51#include "citrus_mapper_serial.h" 52 53/* ---------------------------------------------------------------------- */ 54 55_CITRUS_MAPPER_DECLS(mapper_serial); 56_CITRUS_MAPPER_DEF_OPS(mapper_serial); 57 58#define _citrus_mapper_parallel_mapper_init \ 59 _citrus_mapper_serial_mapper_init 60#define _citrus_mapper_parallel_mapper_uninit \ 61 _citrus_mapper_serial_mapper_uninit 62#define _citrus_mapper_parallel_mapper_init_state \ 63 _citrus_mapper_serial_mapper_init_state 64static int _citrus_mapper_parallel_mapper_convert( 65 struct _citrus_mapper * __restrict, _index_t * __restrict, _index_t, 66 void * __restrict); 67_CITRUS_MAPPER_DEF_OPS(mapper_parallel); 68#undef _citrus_mapper_parallel_mapper_init 69#undef _citrus_mapper_parallel_mapper_uninit 70#undef _citrus_mapper_parallel_mapper_init_state 71 72 73/* ---------------------------------------------------------------------- */ 74 75struct maplink { 76 SIMPLEQ_ENTRY(maplink) ml_entry; 77 struct _mapper *ml_mapper; 78}; 79SIMPLEQ_HEAD(maplist, maplink); 80 81struct _citrus_mapper_serial { 82 struct maplist sr_mappers; 83}; 84 85int 86_citrus_mapper_serial_mapper_getops(struct _citrus_mapper_ops *ops, 87 size_t lenops, uint32_t expected_version) 88{ 89 if (expected_version<_CITRUS_MAPPER_ABI_VERSION || lenops<sizeof(*ops)) 90 return EINVAL; 91 92 memcpy(ops, &_citrus_mapper_serial_mapper_ops, 93 sizeof(_citrus_mapper_serial_mapper_ops)); 94 95 return 0; 96} 97 98int 99_citrus_mapper_parallel_mapper_getops(struct _citrus_mapper_ops *ops, 100 size_t lenops, uint32_t expected_version) 101{ 102 if (expected_version<_CITRUS_MAPPER_ABI_VERSION || lenops<sizeof(*ops)) 103 return EINVAL; 104 105 memcpy(ops, &_citrus_mapper_parallel_mapper_ops, 106 sizeof(_citrus_mapper_parallel_mapper_ops)); 107 108 return 0; 109} 110 111static void 112uninit(struct _citrus_mapper_serial *sr) 113{ 114 struct maplink *ml; 115 116 while ((ml = SIMPLEQ_FIRST(&sr->sr_mappers)) != NULL) { 117 SIMPLEQ_REMOVE_HEAD(&sr->sr_mappers, ml_entry); 118 _mapper_close(ml->ml_mapper); 119 free(ml); 120 } 121} 122 123static int 124parse_var(struct _citrus_mapper_area *__restrict ma, 125 struct _citrus_mapper_serial *sr, struct _memstream *ms) 126{ 127 int ret; 128 struct _region r; 129 char mapname[PATH_MAX]; 130 struct maplink *ml; 131 132 SIMPLEQ_INIT(&sr->sr_mappers); 133 while (1) { 134 /* remove beginning white spaces */ 135 _memstream_skip_ws(ms); 136 if (_memstream_iseof(ms)) 137 break; 138 /* cut down a mapper name */ 139 _memstream_chr(ms, &r, ','); 140 snprintf(mapname, sizeof(mapname), "%.*s", 141 (int)_region_size(&r), (char *)_region_head(&r)); 142 /* remove trailing white spaces */ 143 mapname[_bcs_skip_nonws(mapname)-mapname] = '\0'; 144 /* create a new mapper record */ 145 ml = malloc(sizeof(*ml)); 146 if (ml == NULL) 147 return errno; 148 ret = _mapper_open(ma, &ml->ml_mapper, mapname); 149 if (ret) { 150 free(ml); 151 return ret; 152 } 153 /* support only 1:1 and stateless converter */ 154 if (_mapper_get_src_max(ml->ml_mapper) != 1 || 155 _mapper_get_dst_max(ml->ml_mapper) != 1 || 156 _mapper_get_state_size(ml->ml_mapper) != 0) { 157 free(ml); 158 return EINVAL; 159 } 160 SIMPLEQ_INSERT_TAIL(&sr->sr_mappers, ml, ml_entry); 161 } 162 return 0; 163} 164 165static int 166/*ARGSUSED*/ 167_citrus_mapper_serial_mapper_init(struct _citrus_mapper_area *__restrict ma, 168 struct _citrus_mapper * __restrict cm, 169 const char * __restrict dir, 170 const void * __restrict var, size_t lenvar, 171 struct _citrus_mapper_traits * __restrict mt, 172 size_t lenmt) 173{ 174 struct _citrus_mapper_serial *sr; 175 struct _memstream ms; 176 struct _region r; 177 178 _DIAGASSERT(cm && dir && mt); 179 180 if (lenmt<sizeof(*mt)) 181 return EINVAL; 182 183 sr = malloc(sizeof(*sr)); 184 if (sr == NULL) 185 return errno; 186 187 _region_init(&r, (void *)var, lenvar); 188 _memstream_bind(&ms, &r); 189 if (parse_var(ma, sr, &ms)) { 190 uninit(sr); 191 free(sr); 192 return EINVAL; 193 } 194 cm->cm_closure = sr; 195 mt->mt_src_max = mt->mt_dst_max = 1; /* 1:1 converter */ 196 mt->mt_state_size = 0; /* stateless */ 197 198 return 0; 199} 200 201static void 202/*ARGSUSED*/ 203_citrus_mapper_serial_mapper_uninit(struct _citrus_mapper *cm) 204{ 205 if (cm && cm->cm_closure) { 206 uninit(cm->cm_closure); 207 free(cm->cm_closure); 208 } 209} 210 211static int 212/*ARGSUSED*/ 213_citrus_mapper_serial_mapper_convert(struct _citrus_mapper * __restrict cm, 214 _index_t * __restrict dst, _index_t src, 215 void * __restrict ps) 216{ 217 int ret; 218 struct _citrus_mapper_serial *sr; 219 struct maplink *ml; 220 221 _DIAGASSERT(cm && cm->cm_closure); 222 223 sr = cm->cm_closure; 224 SIMPLEQ_FOREACH(ml, &sr->sr_mappers, ml_entry) { 225 ret = _mapper_convert(ml->ml_mapper, &src, src, NULL); 226 if (ret != _MAPPER_CONVERT_SUCCESS) 227 return ret; 228 } 229 *dst = src; 230 return _MAPPER_CONVERT_SUCCESS; 231} 232 233static int 234/*ARGSUSED*/ 235_citrus_mapper_parallel_mapper_convert(struct _citrus_mapper * __restrict cm, 236 _index_t * __restrict dst, _index_t src, 237 void * __restrict ps) 238{ 239 int ret; 240 struct _citrus_mapper_serial *sr; 241 struct maplink *ml; 242 _index_t tmp; 243 244 _DIAGASSERT(cm && cm->cm_closure); 245 246 sr = cm->cm_closure; 247 SIMPLEQ_FOREACH(ml, &sr->sr_mappers, ml_entry) { 248 ret = _mapper_convert(ml->ml_mapper, &tmp, src, NULL); 249 if (ret == _MAPPER_CONVERT_SUCCESS) { 250 *dst = tmp; 251 return _MAPPER_CONVERT_SUCCESS; 252 } else if (ret == _MAPPER_CONVERT_ILSEQ) 253 return _MAPPER_CONVERT_ILSEQ; 254 } 255 return _MAPPER_CONVERT_NONIDENTICAL; 256} 257 258static void 259/*ARGSUSED*/ 260_citrus_mapper_serial_mapper_init_state(struct _citrus_mapper * __restrict cm, 261 void * __restrict ps) 262{ 263} 264