1 /* $FreeBSD$ */ 2 /* $NetBSD: citrus_mapper_serial.c,v 1.2 2003/07/12 15:39:20 tshiozak Exp $ */ 3 4 /*- 5 * SPDX-License-Identifier: BSD-2-Clause 6 * 7 * Copyright (c)2003 Citrus Project, 8 * All rights reserved. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * SUCH DAMAGE. 30 */ 31 32 #include <sys/cdefs.h> 33 #include <sys/queue.h> 34 35 #include <assert.h> 36 #include <errno.h> 37 #include <limits.h> 38 #include <stdio.h> 39 #include <stdlib.h> 40 #include <string.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, 66 _index_t, 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 STAILQ_ENTRY(maplink) ml_entry; 77 struct _mapper *ml_mapper; 78 }; 79 STAILQ_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 { 88 89 memcpy(ops, &_citrus_mapper_serial_mapper_ops, 90 sizeof(_citrus_mapper_serial_mapper_ops)); 91 92 return (0); 93 } 94 95 int 96 _citrus_mapper_parallel_mapper_getops(struct _citrus_mapper_ops *ops) 97 { 98 99 memcpy(ops, &_citrus_mapper_parallel_mapper_ops, 100 sizeof(_citrus_mapper_parallel_mapper_ops)); 101 102 return (0); 103 } 104 105 static void 106 uninit(struct _citrus_mapper_serial *sr) 107 { 108 struct maplink *ml; 109 110 while ((ml = STAILQ_FIRST(&sr->sr_mappers)) != NULL) { 111 STAILQ_REMOVE_HEAD(&sr->sr_mappers, ml_entry); 112 _mapper_close(ml->ml_mapper); 113 free(ml); 114 } 115 } 116 117 static int 118 parse_var(struct _citrus_mapper_area *__restrict ma, 119 struct _citrus_mapper_serial *sr, struct _memstream *ms) 120 { 121 struct _region r; 122 struct maplink *ml; 123 char mapname[PATH_MAX]; 124 int ret; 125 126 STAILQ_INIT(&sr->sr_mappers); 127 while (1) { 128 /* remove beginning white spaces */ 129 _memstream_skip_ws(ms); 130 if (_memstream_iseof(ms)) 131 break; 132 /* cut down a mapper name */ 133 _memstream_chr(ms, &r, ','); 134 snprintf(mapname, sizeof(mapname), "%.*s", 135 (int)_region_size(&r), (char *)_region_head(&r)); 136 /* remove trailing white spaces */ 137 mapname[_bcs_skip_nonws(mapname)-mapname] = '\0'; 138 /* create a new mapper record */ 139 ml = malloc(sizeof(*ml)); 140 if (ml == NULL) 141 return (errno); 142 ret = _mapper_open(ma, &ml->ml_mapper, mapname); 143 if (ret) { 144 free(ml); 145 return (ret); 146 } 147 /* support only 1:1 and stateless converter */ 148 if (_mapper_get_src_max(ml->ml_mapper) != 1 || 149 _mapper_get_dst_max(ml->ml_mapper) != 1 || 150 _mapper_get_state_size(ml->ml_mapper) != 0) { 151 free(ml); 152 return (EINVAL); 153 } 154 STAILQ_INSERT_TAIL(&sr->sr_mappers, ml, ml_entry); 155 } 156 return (0); 157 } 158 159 static int 160 /*ARGSUSED*/ 161 _citrus_mapper_serial_mapper_init(struct _citrus_mapper_area *__restrict ma __unused, 162 struct _citrus_mapper * __restrict cm, const char * __restrict dir __unused, 163 const void * __restrict var, size_t lenvar, 164 struct _citrus_mapper_traits * __restrict mt, size_t lenmt) 165 { 166 struct _citrus_mapper_serial *sr; 167 struct _memstream ms; 168 struct _region r; 169 170 if (lenmt < sizeof(*mt)) 171 return (EINVAL); 172 173 sr = malloc(sizeof(*sr)); 174 if (sr == NULL) 175 return (errno); 176 177 _region_init(&r, __DECONST(void *, var), lenvar); 178 _memstream_bind(&ms, &r); 179 if (parse_var(ma, sr, &ms)) { 180 uninit(sr); 181 free(sr); 182 return (EINVAL); 183 } 184 cm->cm_closure = sr; 185 mt->mt_src_max = mt->mt_dst_max = 1; /* 1:1 converter */ 186 mt->mt_state_size = 0; /* stateless */ 187 188 return (0); 189 } 190 191 static void 192 /*ARGSUSED*/ 193 _citrus_mapper_serial_mapper_uninit(struct _citrus_mapper *cm) 194 { 195 196 if (cm && cm->cm_closure) { 197 uninit(cm->cm_closure); 198 free(cm->cm_closure); 199 } 200 } 201 202 static int 203 /*ARGSUSED*/ 204 _citrus_mapper_serial_mapper_convert(struct _citrus_mapper * __restrict cm, 205 _index_t * __restrict dst, _index_t src, void * __restrict ps __unused) 206 { 207 struct _citrus_mapper_serial *sr; 208 struct maplink *ml; 209 int ret; 210 211 sr = cm->cm_closure; 212 STAILQ_FOREACH(ml, &sr->sr_mappers, ml_entry) { 213 ret = _mapper_convert(ml->ml_mapper, &src, src, NULL); 214 if (ret != _MAPPER_CONVERT_SUCCESS) 215 return (ret); 216 } 217 *dst = src; 218 return (_MAPPER_CONVERT_SUCCESS); 219 } 220 221 static int 222 /*ARGSUSED*/ 223 _citrus_mapper_parallel_mapper_convert(struct _citrus_mapper * __restrict cm, 224 _index_t * __restrict dst, _index_t src, void * __restrict ps __unused) 225 { 226 struct _citrus_mapper_serial *sr; 227 struct maplink *ml; 228 _index_t tmp; 229 int ret; 230 231 sr = cm->cm_closure; 232 STAILQ_FOREACH(ml, &sr->sr_mappers, ml_entry) { 233 ret = _mapper_convert(ml->ml_mapper, &tmp, src, NULL); 234 if (ret == _MAPPER_CONVERT_SUCCESS) { 235 *dst = tmp; 236 return (_MAPPER_CONVERT_SUCCESS); 237 } else if (ret == _MAPPER_CONVERT_ILSEQ) 238 return (_MAPPER_CONVERT_ILSEQ); 239 } 240 return (_MAPPER_CONVERT_NONIDENTICAL); 241 } 242 243 static void 244 /*ARGSUSED*/ 245 _citrus_mapper_serial_mapper_init_state(void) 246 { 247 248 } 249