1219019Sgabor/* $FreeBSD$ */ 2219019Sgabor/* $NetBSD: citrus_mapper_serial.c,v 1.2 2003/07/12 15:39:20 tshiozak Exp $ */ 3219019Sgabor 4219019Sgabor/*- 5219019Sgabor * Copyright (c)2003 Citrus Project, 6219019Sgabor * All rights reserved. 7219019Sgabor * 8219019Sgabor * Redistribution and use in source and binary forms, with or without 9219019Sgabor * modification, are permitted provided that the following conditions 10219019Sgabor * are met: 11219019Sgabor * 1. Redistributions of source code must retain the above copyright 12219019Sgabor * notice, this list of conditions and the following disclaimer. 13219019Sgabor * 2. Redistributions in binary form must reproduce the above copyright 14219019Sgabor * notice, this list of conditions and the following disclaimer in the 15219019Sgabor * documentation and/or other materials provided with the distribution. 16219019Sgabor * 17219019Sgabor * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18219019Sgabor * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19219019Sgabor * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20219019Sgabor * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21219019Sgabor * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22219019Sgabor * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23219019Sgabor * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24219019Sgabor * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25219019Sgabor * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26219019Sgabor * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27219019Sgabor * SUCH DAMAGE. 28219019Sgabor */ 29219019Sgabor 30219019Sgabor#include <sys/cdefs.h> 31219019Sgabor#include <sys/queue.h> 32219019Sgabor 33219019Sgabor#include <assert.h> 34219019Sgabor#include <errno.h> 35219019Sgabor#include <limits.h> 36219019Sgabor#include <stdio.h> 37219019Sgabor#include <stdlib.h> 38219019Sgabor#include <string.h> 39219019Sgabor 40219019Sgabor#include "citrus_namespace.h" 41219019Sgabor#include "citrus_types.h" 42219019Sgabor#include "citrus_bcs.h" 43219019Sgabor#include "citrus_module.h" 44219019Sgabor#include "citrus_region.h" 45219019Sgabor#include "citrus_memstream.h" 46219019Sgabor#include "citrus_mmap.h" 47219019Sgabor#include "citrus_hash.h" 48219019Sgabor#include "citrus_mapper.h" 49219019Sgabor#include "citrus_mapper_serial.h" 50219019Sgabor 51219019Sgabor/* ---------------------------------------------------------------------- */ 52219019Sgabor 53219019Sgabor_CITRUS_MAPPER_DECLS(mapper_serial); 54219019Sgabor_CITRUS_MAPPER_DEF_OPS(mapper_serial); 55219019Sgabor 56219019Sgabor#define _citrus_mapper_parallel_mapper_init \ 57219019Sgabor _citrus_mapper_serial_mapper_init 58219019Sgabor#define _citrus_mapper_parallel_mapper_uninit \ 59219019Sgabor _citrus_mapper_serial_mapper_uninit 60219019Sgabor#define _citrus_mapper_parallel_mapper_init_state \ 61219019Sgabor _citrus_mapper_serial_mapper_init_state 62219019Sgaborstatic int _citrus_mapper_parallel_mapper_convert( 63219019Sgabor struct _citrus_mapper * __restrict, _index_t * __restrict, 64219019Sgabor _index_t, void * __restrict); 65219019Sgabor_CITRUS_MAPPER_DEF_OPS(mapper_parallel); 66219019Sgabor#undef _citrus_mapper_parallel_mapper_init 67219019Sgabor#undef _citrus_mapper_parallel_mapper_uninit 68219019Sgabor#undef _citrus_mapper_parallel_mapper_init_state 69219019Sgabor 70219019Sgabor 71219019Sgabor/* ---------------------------------------------------------------------- */ 72219019Sgabor 73219019Sgaborstruct maplink { 74219019Sgabor STAILQ_ENTRY(maplink) ml_entry; 75219019Sgabor struct _mapper *ml_mapper; 76219019Sgabor}; 77219019SgaborSTAILQ_HEAD(maplist, maplink); 78219019Sgabor 79219019Sgaborstruct _citrus_mapper_serial { 80219019Sgabor struct maplist sr_mappers; 81219019Sgabor}; 82219019Sgabor 83219019Sgaborint 84219019Sgabor_citrus_mapper_serial_mapper_getops(struct _citrus_mapper_ops *ops) 85219019Sgabor{ 86219019Sgabor 87219019Sgabor memcpy(ops, &_citrus_mapper_serial_mapper_ops, 88219019Sgabor sizeof(_citrus_mapper_serial_mapper_ops)); 89219019Sgabor 90219019Sgabor return (0); 91219019Sgabor} 92219019Sgabor 93219019Sgaborint 94219019Sgabor_citrus_mapper_parallel_mapper_getops(struct _citrus_mapper_ops *ops) 95219019Sgabor{ 96219019Sgabor 97219019Sgabor memcpy(ops, &_citrus_mapper_parallel_mapper_ops, 98219019Sgabor sizeof(_citrus_mapper_parallel_mapper_ops)); 99219019Sgabor 100219019Sgabor return (0); 101219019Sgabor} 102219019Sgabor 103219019Sgaborstatic void 104219019Sgaboruninit(struct _citrus_mapper_serial *sr) 105219019Sgabor{ 106219019Sgabor struct maplink *ml; 107219019Sgabor 108219019Sgabor while ((ml = STAILQ_FIRST(&sr->sr_mappers)) != NULL) { 109219019Sgabor STAILQ_REMOVE_HEAD(&sr->sr_mappers, ml_entry); 110219019Sgabor _mapper_close(ml->ml_mapper); 111219019Sgabor free(ml); 112219019Sgabor } 113219019Sgabor} 114219019Sgabor 115219019Sgaborstatic int 116219019Sgaborparse_var(struct _citrus_mapper_area *__restrict ma, 117219019Sgabor struct _citrus_mapper_serial *sr, struct _memstream *ms) 118219019Sgabor{ 119219019Sgabor struct _region r; 120219019Sgabor struct maplink *ml; 121219019Sgabor char mapname[PATH_MAX]; 122219019Sgabor int ret; 123219019Sgabor 124219019Sgabor STAILQ_INIT(&sr->sr_mappers); 125219019Sgabor while (1) { 126219019Sgabor /* remove beginning white spaces */ 127219019Sgabor _memstream_skip_ws(ms); 128219019Sgabor if (_memstream_iseof(ms)) 129219019Sgabor break; 130219019Sgabor /* cut down a mapper name */ 131219019Sgabor _memstream_chr(ms, &r, ','); 132219019Sgabor snprintf(mapname, sizeof(mapname), "%.*s", 133219019Sgabor (int)_region_size(&r), (char *)_region_head(&r)); 134219019Sgabor /* remove trailing white spaces */ 135219019Sgabor mapname[_bcs_skip_nonws(mapname)-mapname] = '\0'; 136219019Sgabor /* create a new mapper record */ 137219019Sgabor ml = malloc(sizeof(*ml)); 138219019Sgabor if (ml == NULL) 139219019Sgabor return (errno); 140219019Sgabor ret = _mapper_open(ma, &ml->ml_mapper, mapname); 141219019Sgabor if (ret) { 142219019Sgabor free(ml); 143219019Sgabor return (ret); 144219019Sgabor } 145219019Sgabor /* support only 1:1 and stateless converter */ 146219019Sgabor if (_mapper_get_src_max(ml->ml_mapper) != 1 || 147219019Sgabor _mapper_get_dst_max(ml->ml_mapper) != 1 || 148219019Sgabor _mapper_get_state_size(ml->ml_mapper) != 0) { 149219019Sgabor free(ml); 150219019Sgabor return (EINVAL); 151219019Sgabor } 152219019Sgabor STAILQ_INSERT_TAIL(&sr->sr_mappers, ml, ml_entry); 153219019Sgabor } 154219019Sgabor return (0); 155219019Sgabor} 156219019Sgabor 157219019Sgaborstatic int 158219019Sgabor/*ARGSUSED*/ 159219019Sgabor_citrus_mapper_serial_mapper_init(struct _citrus_mapper_area *__restrict ma __unused, 160219019Sgabor struct _citrus_mapper * __restrict cm, const char * __restrict dir __unused, 161219019Sgabor const void * __restrict var, size_t lenvar, 162219019Sgabor struct _citrus_mapper_traits * __restrict mt, size_t lenmt) 163219019Sgabor{ 164219019Sgabor struct _citrus_mapper_serial *sr; 165219019Sgabor struct _memstream ms; 166219019Sgabor struct _region r; 167219019Sgabor 168219019Sgabor if (lenmt < sizeof(*mt)) 169219019Sgabor return (EINVAL); 170219019Sgabor 171219019Sgabor sr = malloc(sizeof(*sr)); 172219019Sgabor if (sr == NULL) 173219019Sgabor return (errno); 174219019Sgabor 175219019Sgabor _region_init(&r, __DECONST(void *, var), lenvar); 176219019Sgabor _memstream_bind(&ms, &r); 177219019Sgabor if (parse_var(ma, sr, &ms)) { 178219019Sgabor uninit(sr); 179219019Sgabor free(sr); 180219019Sgabor return (EINVAL); 181219019Sgabor } 182219019Sgabor cm->cm_closure = sr; 183219019Sgabor mt->mt_src_max = mt->mt_dst_max = 1; /* 1:1 converter */ 184219019Sgabor mt->mt_state_size = 0; /* stateless */ 185219019Sgabor 186219019Sgabor return (0); 187219019Sgabor} 188219019Sgabor 189219019Sgaborstatic void 190219019Sgabor/*ARGSUSED*/ 191219019Sgabor_citrus_mapper_serial_mapper_uninit(struct _citrus_mapper *cm) 192219019Sgabor{ 193219019Sgabor 194219019Sgabor if (cm && cm->cm_closure) { 195219019Sgabor uninit(cm->cm_closure); 196219019Sgabor free(cm->cm_closure); 197219019Sgabor } 198219019Sgabor} 199219019Sgabor 200219019Sgaborstatic int 201219019Sgabor/*ARGSUSED*/ 202219019Sgabor_citrus_mapper_serial_mapper_convert(struct _citrus_mapper * __restrict cm, 203219019Sgabor _index_t * __restrict dst, _index_t src, void * __restrict ps __unused) 204219019Sgabor{ 205219019Sgabor struct _citrus_mapper_serial *sr; 206219019Sgabor struct maplink *ml; 207219019Sgabor int ret; 208219019Sgabor 209219019Sgabor sr = cm->cm_closure; 210219019Sgabor STAILQ_FOREACH(ml, &sr->sr_mappers, ml_entry) { 211219019Sgabor ret = _mapper_convert(ml->ml_mapper, &src, src, NULL); 212219019Sgabor if (ret != _MAPPER_CONVERT_SUCCESS) 213219019Sgabor return (ret); 214219019Sgabor } 215219019Sgabor *dst = src; 216219019Sgabor return (_MAPPER_CONVERT_SUCCESS); 217219019Sgabor} 218219019Sgabor 219219019Sgaborstatic int 220219019Sgabor/*ARGSUSED*/ 221219019Sgabor_citrus_mapper_parallel_mapper_convert(struct _citrus_mapper * __restrict cm, 222219019Sgabor _index_t * __restrict dst, _index_t src, void * __restrict ps __unused) 223219019Sgabor{ 224219019Sgabor struct _citrus_mapper_serial *sr; 225219019Sgabor struct maplink *ml; 226219019Sgabor _index_t tmp; 227219019Sgabor int ret; 228219019Sgabor 229219019Sgabor sr = cm->cm_closure; 230219019Sgabor STAILQ_FOREACH(ml, &sr->sr_mappers, ml_entry) { 231219019Sgabor ret = _mapper_convert(ml->ml_mapper, &tmp, src, NULL); 232219019Sgabor if (ret == _MAPPER_CONVERT_SUCCESS) { 233219019Sgabor *dst = tmp; 234219019Sgabor return (_MAPPER_CONVERT_SUCCESS); 235219019Sgabor } else if (ret == _MAPPER_CONVERT_ILSEQ) 236219019Sgabor return (_MAPPER_CONVERT_ILSEQ); 237219019Sgabor } 238219019Sgabor return (_MAPPER_CONVERT_NONIDENTICAL); 239219019Sgabor} 240219019Sgabor 241219019Sgaborstatic void 242219019Sgabor/*ARGSUSED*/ 243219019Sgabor_citrus_mapper_serial_mapper_init_state(void) 244219019Sgabor{ 245219019Sgabor 246219019Sgabor} 247