1 /* $FreeBSD$ */ 2 /* $NetBSD: citrus_mapper_serial.c,v 1.2 2003/07/12 15:39:20 tshiozak Exp $ */ 3 4 /*- 5 * Copyright (c)2003 Citrus Project, 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 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. 16 * 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 27 * SUCH DAMAGE. 28 */ 29 30 #include <sys/cdefs.h> 31 #include <sys/queue.h> 32 33 #include <assert.h> 34 #include <errno.h> 35 #include <limits.h> 36 #include <stdio.h> 37 #include <stdlib.h> 38 #include <string.h> 39 40 #include "citrus_namespace.h" 41 #include "citrus_types.h" 42 #include "citrus_bcs.h" 43 #include "citrus_module.h" 44 #include "citrus_region.h" 45 #include "citrus_memstream.h" 46 #include "citrus_mmap.h" 47 #include "citrus_hash.h" 48 #include "citrus_mapper.h" 49 #include "citrus_mapper_serial.h" 50 51 /* ---------------------------------------------------------------------- */ 52 53 _CITRUS_MAPPER_DECLS(mapper_serial); 54 _CITRUS_MAPPER_DEF_OPS(mapper_serial); 55 56 #define _citrus_mapper_parallel_mapper_init \ 57 _citrus_mapper_serial_mapper_init 58 #define _citrus_mapper_parallel_mapper_uninit \ 59 _citrus_mapper_serial_mapper_uninit 60 #define _citrus_mapper_parallel_mapper_init_state \ 61 _citrus_mapper_serial_mapper_init_state 62 static int _citrus_mapper_parallel_mapper_convert( 63 struct _citrus_mapper * __restrict, _index_t * __restrict, 64 _index_t, void * __restrict); 65 _CITRUS_MAPPER_DEF_OPS(mapper_parallel); 66 #undef _citrus_mapper_parallel_mapper_init 67 #undef _citrus_mapper_parallel_mapper_uninit 68 #undef _citrus_mapper_parallel_mapper_init_state 69 70 71 /* ---------------------------------------------------------------------- */ 72 73 struct maplink { 74 STAILQ_ENTRY(maplink) ml_entry; 75 struct _mapper *ml_mapper; 76 }; 77 STAILQ_HEAD(maplist, maplink); 78 79 struct _citrus_mapper_serial { 80 struct maplist sr_mappers; 81 }; 82 83 int 84 _citrus_mapper_serial_mapper_getops(struct _citrus_mapper_ops *ops) 85 { 86 87 memcpy(ops, &_citrus_mapper_serial_mapper_ops, 88 sizeof(_citrus_mapper_serial_mapper_ops)); 89 90 return (0); 91 } 92 93 int 94 _citrus_mapper_parallel_mapper_getops(struct _citrus_mapper_ops *ops) 95 { 96 97 memcpy(ops, &_citrus_mapper_parallel_mapper_ops, 98 sizeof(_citrus_mapper_parallel_mapper_ops)); 99 100 return (0); 101 } 102 103 static void 104 uninit(struct _citrus_mapper_serial *sr) 105 { 106 struct maplink *ml; 107 108 while ((ml = STAILQ_FIRST(&sr->sr_mappers)) != NULL) { 109 STAILQ_REMOVE_HEAD(&sr->sr_mappers, ml_entry); 110 _mapper_close(ml->ml_mapper); 111 free(ml); 112 } 113 } 114 115 static int 116 parse_var(struct _citrus_mapper_area *__restrict ma, 117 struct _citrus_mapper_serial *sr, struct _memstream *ms) 118 { 119 struct _region r; 120 struct maplink *ml; 121 char mapname[PATH_MAX]; 122 int ret; 123 124 STAILQ_INIT(&sr->sr_mappers); 125 while (1) { 126 /* remove beginning white spaces */ 127 _memstream_skip_ws(ms); 128 if (_memstream_iseof(ms)) 129 break; 130 /* cut down a mapper name */ 131 _memstream_chr(ms, &r, ','); 132 snprintf(mapname, sizeof(mapname), "%.*s", 133 (int)_region_size(&r), (char *)_region_head(&r)); 134 /* remove trailing white spaces */ 135 mapname[_bcs_skip_nonws(mapname)-mapname] = '\0'; 136 /* create a new mapper record */ 137 ml = malloc(sizeof(*ml)); 138 if (ml == NULL) 139 return (errno); 140 ret = _mapper_open(ma, &ml->ml_mapper, mapname); 141 if (ret) { 142 free(ml); 143 return (ret); 144 } 145 /* support only 1:1 and stateless converter */ 146 if (_mapper_get_src_max(ml->ml_mapper) != 1 || 147 _mapper_get_dst_max(ml->ml_mapper) != 1 || 148 _mapper_get_state_size(ml->ml_mapper) != 0) { 149 free(ml); 150 return (EINVAL); 151 } 152 STAILQ_INSERT_TAIL(&sr->sr_mappers, ml, ml_entry); 153 } 154 return (0); 155 } 156 157 static int 158 /*ARGSUSED*/ 159 _citrus_mapper_serial_mapper_init(struct _citrus_mapper_area *__restrict ma __unused, 160 struct _citrus_mapper * __restrict cm, const char * __restrict dir __unused, 161 const void * __restrict var, size_t lenvar, 162 struct _citrus_mapper_traits * __restrict mt, size_t lenmt) 163 { 164 struct _citrus_mapper_serial *sr; 165 struct _memstream ms; 166 struct _region r; 167 168 if (lenmt < sizeof(*mt)) 169 return (EINVAL); 170 171 sr = malloc(sizeof(*sr)); 172 if (sr == NULL) 173 return (errno); 174 175 _region_init(&r, __DECONST(void *, var), lenvar); 176 _memstream_bind(&ms, &r); 177 if (parse_var(ma, sr, &ms)) { 178 uninit(sr); 179 free(sr); 180 return (EINVAL); 181 } 182 cm->cm_closure = sr; 183 mt->mt_src_max = mt->mt_dst_max = 1; /* 1:1 converter */ 184 mt->mt_state_size = 0; /* stateless */ 185 186 return (0); 187 } 188 189 static void 190 /*ARGSUSED*/ 191 _citrus_mapper_serial_mapper_uninit(struct _citrus_mapper *cm) 192 { 193 194 if (cm && cm->cm_closure) { 195 uninit(cm->cm_closure); 196 free(cm->cm_closure); 197 } 198 } 199 200 static int 201 /*ARGSUSED*/ 202 _citrus_mapper_serial_mapper_convert(struct _citrus_mapper * __restrict cm, 203 _index_t * __restrict dst, _index_t src, void * __restrict ps __unused) 204 { 205 struct _citrus_mapper_serial *sr; 206 struct maplink *ml; 207 int ret; 208 209 sr = cm->cm_closure; 210 STAILQ_FOREACH(ml, &sr->sr_mappers, ml_entry) { 211 ret = _mapper_convert(ml->ml_mapper, &src, src, NULL); 212 if (ret != _MAPPER_CONVERT_SUCCESS) 213 return (ret); 214 } 215 *dst = src; 216 return (_MAPPER_CONVERT_SUCCESS); 217 } 218 219 static int 220 /*ARGSUSED*/ 221 _citrus_mapper_parallel_mapper_convert(struct _citrus_mapper * __restrict cm, 222 _index_t * __restrict dst, _index_t src, void * __restrict ps __unused) 223 { 224 struct _citrus_mapper_serial *sr; 225 struct maplink *ml; 226 _index_t tmp; 227 int ret; 228 229 sr = cm->cm_closure; 230 STAILQ_FOREACH(ml, &sr->sr_mappers, ml_entry) { 231 ret = _mapper_convert(ml->ml_mapper, &tmp, src, NULL); 232 if (ret == _MAPPER_CONVERT_SUCCESS) { 233 *dst = tmp; 234 return (_MAPPER_CONVERT_SUCCESS); 235 } else if (ret == _MAPPER_CONVERT_ILSEQ) 236 return (_MAPPER_CONVERT_ILSEQ); 237 } 238 return (_MAPPER_CONVERT_NONIDENTICAL); 239 } 240 241 static void 242 /*ARGSUSED*/ 243 _citrus_mapper_serial_mapper_init_state(void) 244 { 245 246 } 247