1 /* $NetBSD: citrus_mapper_serial.c,v 1.2 2003/07/12 15:39:20 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.2 2003/07/12 15:39:20 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 64 static 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 75 struct maplink { 76 SIMPLEQ_ENTRY(maplink) ml_entry; 77 struct _mapper *ml_mapper; 78 }; 79 SIMPLEQ_HEAD(maplist, maplink); 80 81 struct _citrus_mapper_serial { 82 struct maplist sr_mappers; 83 }; 84 85 int 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 98 int 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 111 static void 112 uninit(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 123 static int 124 parse_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 165 static 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 201 static 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 211 static 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 233 static 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 258 static void 259 /*ARGSUSED*/ 260 _citrus_mapper_serial_mapper_init_state(struct _citrus_mapper * __restrict cm, 261 void * __restrict ps) 262 { 263 } 264