1 /* $NetBSD: citrus_mapper_std.c,v 1.10 2011/11/19 18:48:39 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.10 2011/11/19 18:48:39 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
);
189 free(rc
->rc_src_rowcol
);
190 rc
->rc_src_rowcol
= NULL
;
193 ++rc
->rc_src_rowcol_len
, ++lz
;
195 m
= be32toh(rcx
->rcx_src_col_begin
);
196 n
= be32toh(rcx
->rcx_src_col_end
);
198 return set_linear_zone(lz
, m
, n
);
202 rowcol_parse_variable(struct _citrus_mapper_std_rowcol
*rc
,
205 const struct _citrus_mapper_std_rowcol_info_x
*rcx
;
206 struct _citrus_mapper_std_linear_zone
*lz
;
211 _DIAGASSERT(rc
!= NULL
);
212 _DIAGASSERT(r
!= NULL
&& _region_size(r
) == sizeof(*rcx
));
213 rcx
= _region_head(r
);
215 rc
->rc_dst_invalid
= be32toh(rcx
->rcx_dst_invalid
);
216 rc
->rc_dst_unit_bits
= be32toh(rcx
->rcx_dst_unit_bits
);
218 m
= be32toh(rcx
->rcx_src_rowcol_bits
);
221 rc
->rc_src_rowcol_bits
= m
;
222 rc
->rc_src_rowcol_mask
= n
;
224 rc
->rc_src_rowcol_len
= be32toh(rcx
->rcx_src_rowcol_len
);
225 if (rc
->rc_src_rowcol_len
> _CITRUS_MAPPER_STD_ROWCOL_MAX
)
227 rc
->rc_src_rowcol
= malloc(rc
->rc_src_rowcol_len
*
228 sizeof(*rc
->rc_src_rowcol
));
229 if (rc
->rc_src_rowcol
== NULL
)
231 for (i
= 0, lz
= rc
->rc_src_rowcol
;
232 i
< rc
->rc_src_rowcol_len
; ++i
, ++lz
) {
233 m
= be32toh(rcx
->rcx_src_rowcol
[i
].begin
),
234 n
= be32toh(rcx
->rcx_src_rowcol
[i
].end
);
235 ret
= set_linear_zone(lz
, m
, n
);
237 free(rc
->rc_src_rowcol
);
238 rc
->rc_src_rowcol
= NULL
;
246 rowcol_uninit(struct _citrus_mapper_std
*ms
)
248 struct _citrus_mapper_std_rowcol
*rc
;
249 _DIAGASSERT(ms
!= NULL
);
252 free(rc
->rc_src_rowcol
);
256 rowcol_init(struct _citrus_mapper_std
*ms
)
259 struct _citrus_mapper_std_rowcol
*rc
;
260 const struct _citrus_mapper_std_rowcol_ext_ilseq_info_x
*eix
;
262 u_int64_t table_size
;
264 struct _citrus_mapper_std_linear_zone
*lz
;
266 _DIAGASSERT(ms
!= NULL
);
267 ms
->ms_convert
= &rowcol_convert
;
268 ms
->ms_uninit
= &rowcol_uninit
;
271 /* get table region */
272 ret
= _db_lookup_by_s(ms
->ms_db
, _CITRUS_MAPPER_STD_SYM_TABLE
,
273 &rc
->rc_table
, NULL
);
280 /* get table information */
281 ret
= _db_lookup_by_s(ms
->ms_db
, _CITRUS_MAPPER_STD_SYM_INFO
, &r
, NULL
);
287 switch (_region_size(&r
)) {
288 case _CITRUS_MAPPER_STD_ROWCOL_INFO_COMPAT_SIZE
:
289 ret
= rowcol_parse_variable_compat(rc
, &r
);
291 case _CITRUS_MAPPER_STD_ROWCOL_INFO_SIZE
:
292 ret
= rowcol_parse_variable(rc
, &r
);
300 switch (rc
->rc_src_rowcol_bits
) {
301 case 8: case 16: case 32:
302 if (rc
->rc_src_rowcol_len
<= 32 / rc
->rc_src_rowcol_bits
)
309 /* ilseq extension */
310 rc
->rc_oob_mode
= _CITRUS_MAPPER_STD_OOB_NONIDENTICAL
;
311 rc
->rc_dst_ilseq
= rc
->rc_dst_invalid
;
312 ret
= _db_lookup_by_s(ms
->ms_db
,
313 _CITRUS_MAPPER_STD_SYM_ROWCOL_EXT_ILSEQ
,
315 if (ret
&& ret
!= ENOENT
)
317 if (_region_size(&r
) < sizeof(*eix
))
320 eix
= _region_head(&r
);
321 rc
->rc_oob_mode
= be32toh(eix
->eix_oob_mode
);
322 rc
->rc_dst_ilseq
= be32toh(eix
->eix_dst_ilseq
);
325 /* calcurate expected table size */
326 i
= rc
->rc_src_rowcol_len
;
327 lz
= &rc
->rc_src_rowcol
[--i
];
328 table_size
= lz
->width
;
330 lz
= &rc
->rc_src_rowcol
[--i
];
331 table_size
*= lz
->width
;
333 table_size
*= rc
->rc_dst_unit_bits
/8;
335 if (table_size
> UINT32_MAX
||
336 _region_size(&rc
->rc_table
) < table_size
)
342 typedef int (*initfunc_t
)(struct _citrus_mapper_std
*);
343 static const struct {
347 { _CITRUS_MAPPER_STD_TYPE_ROWCOL
, &rowcol_init
},
349 #define NUM_OF_TYPES ((int)(sizeof(types)/sizeof(types[0])))
353 _citrus_mapper_std_mapper_init(struct _citrus_mapper_area
*__restrict ma
,
354 struct _citrus_mapper
* __restrict cm
,
355 const char * __restrict curdir
,
356 const void * __restrict var
, size_t lenvar
,
357 struct _citrus_mapper_traits
* __restrict mt
,
363 struct _citrus_mapper_std
*ms
;
366 if (lenmt
<sizeof(*mt
)) {
370 mt
->mt_src_max
= mt
->mt_dst_max
= 1; /* 1:1 converter */
371 mt
->mt_state_size
= 0; /* stateless */
373 /* alloc mapper std structure */
374 ms
= malloc(sizeof(*ms
));
380 /* open mapper file */
381 snprintf(path
, sizeof(path
),
382 "%s/%.*s", curdir
, (int)lenvar
, (const char *)var
);
383 ret
= _map_file(&ms
->ms_file
, path
);
387 ret
= _db_open(&ms
->ms_db
, &ms
->ms_file
, _CITRUS_MAPPER_STD_MAGIC
,
388 &_db_hash_std
, NULL
);
392 /* get mapper type */
393 ret
= _db_lookupstr_by_s(ms
->ms_db
, _CITRUS_MAPPER_STD_SYM_TYPE
,
400 for (id
=0; id
<NUM_OF_TYPES
; id
++)
401 if (_bcs_strcasecmp(type
, types
[id
].t_name
) == 0)
404 if (id
== NUM_OF_TYPES
)
407 /* init the per-type structure */
408 ret
= (*types
[id
].t_init
)(ms
);
417 _db_close(ms
->ms_db
);
419 _unmap_file(&ms
->ms_file
);
428 _citrus_mapper_std_mapper_uninit(struct _citrus_mapper
*cm
)
430 struct _citrus_mapper_std
*ms
;
432 _DIAGASSERT(cm
!=NULL
&& cm
->cm_closure
!=NULL
);
436 (*ms
->ms_uninit
)(ms
);
437 _db_close(ms
->ms_db
);
438 _unmap_file(&ms
->ms_file
);
444 _citrus_mapper_std_mapper_init_state(struct _citrus_mapper
* __restrict cm
,
445 void * __restrict ps
)
451 _citrus_mapper_std_mapper_convert(struct _citrus_mapper
* __restrict cm
,
452 _index_t
* __restrict dst
, _index_t src
,
453 void * __restrict ps
)
455 struct _citrus_mapper_std
*ms
;
457 _DIAGASSERT(cm
!=NULL
&& cm
->cm_closure
!=NULL
);
461 _DIAGASSERT(ms
->ms_convert
!= NULL
);
463 return (*ms
->ms_convert
)(ms
, dst
, src
, ps
);