1 /* $NetBSD: citrus_mapper_std.c,v 1.7 2006/09/09 14:35:17 tnozaki Exp $ */
4 * Copyright (c)2003, 2006 Citrus Project,
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
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.
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
29 #include <sys/cdefs.h>
30 #if defined(LIBC_SCCS) && !defined(lint)
31 __RCSID("$NetBSD: citrus_mapper_std.c,v 1.7 2006/09/09 14:35:17 tnozaki Exp $");
32 #endif /* LIBC_SCCS and not lint */
41 #include <machine/endian.h>
42 #include <sys/queue.h>
44 #include "citrus_namespace.h"
45 #include "citrus_types.h"
46 #include "citrus_bcs.h"
47 #include "citrus_region.h"
48 #include "citrus_mmap.h"
49 #include "citrus_module.h"
50 #include "citrus_hash.h"
51 #include "citrus_mapper.h"
52 #include "citrus_db.h"
53 #include "citrus_db_hash.h"
55 #include "citrus_mapper_std.h"
56 #include "citrus_mapper_std_file.h"
58 /* ---------------------------------------------------------------------- */
60 _CITRUS_MAPPER_DECLS(mapper_std
);
61 _CITRUS_MAPPER_DEF_OPS(mapper_std
);
64 /* ---------------------------------------------------------------------- */
67 _citrus_mapper_std_mapper_getops(struct _citrus_mapper_ops
*ops
, size_t lenops
,
68 u_int32_t expected_version
)
70 if (expected_version
<_CITRUS_MAPPER_ABI_VERSION
|| lenops
<sizeof(*ops
))
73 memcpy(ops
, &_citrus_mapper_std_mapper_ops
,
74 sizeof(_citrus_mapper_std_mapper_ops
));
79 /* ---------------------------------------------------------------------- */
83 rowcol_convert(struct _citrus_mapper_std
* __restrict ms
,
84 _index_t
* __restrict dst
, _index_t src
,
87 struct _citrus_mapper_std_rowcol
*rc
;
89 struct _citrus_mapper_std_linear_zone
*lz
;
93 _DIAGASSERT(ms
!= NULL
);
94 _DIAGASSERT(dst
!= NULL
);
95 /* ps may be unused */
98 for (i
= rc
->rc_src_rowcol_len
* rc
->rc_src_rowcol_bits
,
99 lz
= &rc
->rc_src_rowcol
[0]; i
> 0; ++lz
) {
100 i
-= rc
->rc_src_rowcol_bits
;
101 n
= (src
>> i
) & rc
->rc_src_rowcol_mask
;
102 if (n
< lz
->begin
|| n
> lz
->end
) {
103 switch (rc
->rc_oob_mode
) {
104 case _CITRUS_MAPPER_STD_OOB_NONIDENTICAL
:
105 *dst
= rc
->rc_dst_invalid
;
106 return _MAPPER_CONVERT_NONIDENTICAL
;
107 case _CITRUS_MAPPER_STD_OOB_ILSEQ
:
108 return _MAPPER_CONVERT_ILSEQ
;
110 return _MAPPER_CONVERT_FATAL
;
113 idx
= idx
* lz
->width
+ n
- lz
->begin
;
115 switch (rc
->rc_dst_unit_bits
) {
117 conv
= _region_peek8(&rc
->rc_table
, idx
);
120 conv
= be16toh(_region_peek16(&rc
->rc_table
, idx
*2));
123 conv
= be32toh(_region_peek32(&rc
->rc_table
, idx
*4));
126 return _MAPPER_CONVERT_FATAL
;
129 if (conv
== rc
->rc_dst_invalid
) {
130 *dst
= rc
->rc_dst_invalid
;
131 return _MAPPER_CONVERT_NONIDENTICAL
;
133 if (conv
== rc
->rc_dst_ilseq
)
134 return _MAPPER_CONVERT_ILSEQ
;
138 return _MAPPER_CONVERT_SUCCESS
;
142 set_linear_zone(struct _citrus_mapper_std_linear_zone
*lz
,
143 u_int32_t begin
, u_int32_t end
)
145 _DIAGASSERT(lz
!= NULL
);
152 lz
->width
= end
- begin
+ 1;
158 rowcol_parse_variable_compat(struct _citrus_mapper_std_rowcol
*rc
,
161 const struct _citrus_mapper_std_rowcol_info_compat_x
*rcx
;
162 struct _citrus_mapper_std_linear_zone
*lz
;
166 _DIAGASSERT(rc
!= NULL
);
167 _DIAGASSERT(r
!= NULL
&& _region_size(r
) == sizeof(*rcx
));
168 rcx
= _region_head(r
);
170 rc
->rc_dst_invalid
= be32toh(rcx
->rcx_dst_invalid
);
171 rc
->rc_dst_unit_bits
= be32toh(rcx
->rcx_dst_unit_bits
);
172 m
= be32toh(rcx
->rcx_src_col_bits
);
175 rc
->rc_src_rowcol_bits
= m
;
176 rc
->rc_src_rowcol_mask
= n
;
178 rc
->rc_src_rowcol
= malloc(2 *
179 sizeof(*rc
->rc_src_rowcol
));
180 if (rc
->rc_src_rowcol
== NULL
)
182 lz
= rc
->rc_src_rowcol
;
183 rc
->rc_src_rowcol_len
= 1;
184 m
= be32toh(rcx
->rcx_src_row_begin
);
185 n
= be32toh(rcx
->rcx_src_row_end
);
187 ret
= set_linear_zone(lz
, m
, n
);
190 ++rc
->rc_src_rowcol_len
, ++lz
;
192 m
= be32toh(rcx
->rcx_src_col_begin
);
193 n
= be32toh(rcx
->rcx_src_col_end
);
195 return set_linear_zone(lz
, m
, n
);
199 rowcol_parse_variable(struct _citrus_mapper_std_rowcol
*rc
,
202 const struct _citrus_mapper_std_rowcol_info_x
*rcx
;
203 struct _citrus_mapper_std_linear_zone
*lz
;
208 _DIAGASSERT(rc
!= NULL
);
209 _DIAGASSERT(r
!= NULL
&& _region_size(r
) == sizeof(*rcx
));
210 rcx
= _region_head(r
);
212 rc
->rc_dst_invalid
= be32toh(rcx
->rcx_dst_invalid
);
213 rc
->rc_dst_unit_bits
= be32toh(rcx
->rcx_dst_unit_bits
);
215 m
= be32toh(rcx
->rcx_src_rowcol_bits
);
218 rc
->rc_src_rowcol_bits
= m
;
219 rc
->rc_src_rowcol_mask
= n
;
221 rc
->rc_src_rowcol_len
= be32toh(rcx
->rcx_src_rowcol_len
);
222 if (rc
->rc_src_rowcol_len
> _CITRUS_MAPPER_STD_ROWCOL_MAX
)
224 rc
->rc_src_rowcol
= malloc(rc
->rc_src_rowcol_len
*
225 sizeof(*rc
->rc_src_rowcol
));
226 if (rc
->rc_src_rowcol
== NULL
)
228 for (i
= 0, lz
= rc
->rc_src_rowcol
;
229 i
< rc
->rc_src_rowcol_len
; ++i
, ++lz
) {
230 m
= be32toh(rcx
->rcx_src_rowcol
[i
].begin
),
231 n
= be32toh(rcx
->rcx_src_rowcol
[i
].end
);
232 ret
= set_linear_zone(lz
, m
, n
);
234 free(rc
->rc_src_rowcol
);
235 rc
->rc_src_rowcol
= NULL
;
243 rowcol_uninit(struct _citrus_mapper_std
*ms
)
245 struct _citrus_mapper_std_rowcol
*rc
;
246 _DIAGASSERT(ms
!= NULL
);
249 free(rc
->rc_src_rowcol
);
253 rowcol_init(struct _citrus_mapper_std
*ms
)
256 struct _citrus_mapper_std_rowcol
*rc
;
257 const struct _citrus_mapper_std_rowcol_ext_ilseq_info_x
*eix
;
259 u_int64_t table_size
;
261 struct _citrus_mapper_std_linear_zone
*lz
;
263 _DIAGASSERT(ms
!= NULL
);
264 ms
->ms_convert
= &rowcol_convert
;
265 ms
->ms_uninit
= &rowcol_uninit
;
268 /* get table region */
269 ret
= _db_lookup_by_s(ms
->ms_db
, _CITRUS_MAPPER_STD_SYM_TABLE
,
270 &rc
->rc_table
, NULL
);
277 /* get table information */
278 ret
= _db_lookup_by_s(ms
->ms_db
, _CITRUS_MAPPER_STD_SYM_INFO
, &r
, NULL
);
284 switch (_region_size(&r
)) {
285 case _CITRUS_MAPPER_STD_ROWCOL_INFO_COMPAT_SIZE
:
286 ret
= rowcol_parse_variable_compat(rc
, &r
);
288 case _CITRUS_MAPPER_STD_ROWCOL_INFO_SIZE
:
289 ret
= rowcol_parse_variable(rc
, &r
);
297 switch (rc
->rc_src_rowcol_bits
) {
298 case 8: case 16: case 32:
299 if (rc
->rc_src_rowcol_len
<= 32 / rc
->rc_src_rowcol_bits
)
306 /* ilseq extension */
307 rc
->rc_oob_mode
= _CITRUS_MAPPER_STD_OOB_NONIDENTICAL
;
308 rc
->rc_dst_ilseq
= rc
->rc_dst_invalid
;
309 ret
= _db_lookup_by_s(ms
->ms_db
,
310 _CITRUS_MAPPER_STD_SYM_ROWCOL_EXT_ILSEQ
,
312 if (ret
&& ret
!= ENOENT
)
314 if (_region_size(&r
) < sizeof(*eix
))
317 eix
= _region_head(&r
);
318 rc
->rc_oob_mode
= be32toh(eix
->eix_oob_mode
);
319 rc
->rc_dst_ilseq
= be32toh(eix
->eix_dst_ilseq
);
322 /* calcurate expected table size */
323 i
= rc
->rc_src_rowcol_len
;
324 lz
= &rc
->rc_src_rowcol
[--i
];
325 table_size
= lz
->width
;
327 lz
= &rc
->rc_src_rowcol
[--i
];
328 table_size
*= lz
->width
;
330 table_size
*= rc
->rc_dst_unit_bits
/8;
332 if (table_size
> UINT32_MAX
||
333 _region_size(&rc
->rc_table
) < table_size
)
339 typedef int (*initfunc_t
)(struct _citrus_mapper_std
*);
340 static const struct {
344 { _CITRUS_MAPPER_STD_TYPE_ROWCOL
, &rowcol_init
},
346 #define NUM_OF_TYPES ((int)(sizeof(types)/sizeof(types[0])))
350 _citrus_mapper_std_mapper_init(struct _citrus_mapper_area
*__restrict ma
,
351 struct _citrus_mapper
* __restrict cm
,
352 const char * __restrict curdir
,
353 const void * __restrict var
, size_t lenvar
,
354 struct _citrus_mapper_traits
* __restrict mt
,
360 struct _citrus_mapper_std
*ms
;
363 if (lenmt
<sizeof(*mt
)) {
367 mt
->mt_src_max
= mt
->mt_dst_max
= 1; /* 1:1 converter */
368 mt
->mt_state_size
= 0; /* stateless */
370 /* alloc mapper std structure */
371 ms
= malloc(sizeof(*ms
));
377 /* open mapper file */
378 snprintf(path
, sizeof(path
),
379 "%s/%.*s", curdir
, (int)lenvar
, (const char *)var
);
380 ret
= _map_file(&ms
->ms_file
, path
);
384 ret
= _db_open(&ms
->ms_db
, &ms
->ms_file
, _CITRUS_MAPPER_STD_MAGIC
,
385 &_db_hash_std
, NULL
);
389 /* get mapper type */
390 ret
= _db_lookupstr_by_s(ms
->ms_db
, _CITRUS_MAPPER_STD_SYM_TYPE
,
397 for (id
=0; id
<NUM_OF_TYPES
; id
++)
398 if (_bcs_strcasecmp(type
, types
[id
].t_name
) == 0)
401 if (id
== NUM_OF_TYPES
)
404 /* init the per-type structure */
405 ret
= (*types
[id
].t_init
)(ms
);
414 _db_close(ms
->ms_db
);
416 _unmap_file(&ms
->ms_file
);
425 _citrus_mapper_std_mapper_uninit(struct _citrus_mapper
*cm
)
427 struct _citrus_mapper_std
*ms
;
429 _DIAGASSERT(cm
!=NULL
& cm
->cm_closure
!=NULL
);
433 (*ms
->ms_uninit
)(ms
);
434 _db_close(ms
->ms_db
);
435 _unmap_file(&ms
->ms_file
);
441 _citrus_mapper_std_mapper_init_state(struct _citrus_mapper
* __restrict cm
,
442 void * __restrict ps
)
448 _citrus_mapper_std_mapper_convert(struct _citrus_mapper
* __restrict cm
,
449 _index_t
* __restrict dst
, _index_t src
,
450 void * __restrict ps
)
452 struct _citrus_mapper_std
*ms
;
454 _DIAGASSERT(cm
!=NULL
&& cm
->cm_closure
!=NULL
);
458 _DIAGASSERT(ms
->ms_convert
!= NULL
);
460 return (*ms
->ms_convert
)(ms
, dst
, src
, ps
);