1 /* $FreeBSD: head/lib/libiconv_modules/mapper_std/citrus_mapper_std.c 263986 2014-04-01 10:36:11Z tijl $ */
2 /* $NetBSD: citrus_mapper_std.c,v 1.10 2011/11/19 18:48:39 tnozaki Exp $ */
5 * Copyright (c)2003, 2006 Citrus Project,
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
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.
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
30 #include <sys/cdefs.h>
31 #include <sys/endian.h>
32 #include <sys/queue.h>
42 #include "citrus_namespace.h"
43 #include "citrus_types.h"
44 #include "citrus_bcs.h"
45 #include "citrus_region.h"
46 #include "citrus_mmap.h"
47 #include "citrus_module.h"
48 #include "citrus_hash.h"
49 #include "citrus_mapper.h"
50 #include "citrus_db.h"
51 #include "citrus_db_hash.h"
53 #include "citrus_mapper_std.h"
54 #include "citrus_mapper_std_file.h"
56 /* ---------------------------------------------------------------------- */
58 _CITRUS_MAPPER_DECLS(mapper_std
);
59 _CITRUS_MAPPER_DEF_OPS(mapper_std
);
62 /* ---------------------------------------------------------------------- */
65 _citrus_mapper_std_mapper_getops(struct _citrus_mapper_ops
*ops
)
68 memcpy(ops
, &_citrus_mapper_std_mapper_ops
,
69 sizeof(_citrus_mapper_std_mapper_ops
));
74 /* ---------------------------------------------------------------------- */
78 rowcol_convert(struct _citrus_mapper_std
* __restrict ms
,
79 _index_t
* __restrict dst
, _index_t src
, void * __restrict ps __unused
)
81 struct _citrus_mapper_std_linear_zone
*lz
;
82 struct _citrus_mapper_std_rowcol
*rc
;
87 /* ps may be unused */
90 for (i
= rc
->rc_src_rowcol_len
* rc
->rc_src_rowcol_bits
,
91 lz
= &rc
->rc_src_rowcol
[0]; i
> 0; ++lz
) {
92 i
-= rc
->rc_src_rowcol_bits
;
93 n
= (src
>> i
) & rc
->rc_src_rowcol_mask
;
94 if (n
< lz
->begin
|| n
> lz
->end
) {
95 switch (rc
->rc_oob_mode
) {
96 case _CITRUS_MAPPER_STD_OOB_NONIDENTICAL
:
97 *dst
= rc
->rc_dst_invalid
;
98 return (_MAPPER_CONVERT_NONIDENTICAL
);
99 case _CITRUS_MAPPER_STD_OOB_ILSEQ
:
100 return (_MAPPER_CONVERT_ILSEQ
);
102 return (_MAPPER_CONVERT_FATAL
);
105 idx
= idx
* lz
->width
+ n
- lz
->begin
;
107 switch (rc
->rc_dst_unit_bits
) {
109 conv
= _region_peek8(&rc
->rc_table
, idx
);
112 conv
= be16toh(_region_peek16(&rc
->rc_table
, idx
*2));
115 conv
= be32toh(_region_peek32(&rc
->rc_table
, idx
*4));
118 return (_MAPPER_CONVERT_FATAL
);
121 if (conv
== rc
->rc_dst_invalid
) {
122 *dst
= rc
->rc_dst_invalid
;
123 return (_MAPPER_CONVERT_NONIDENTICAL
);
125 if (conv
== rc
->rc_dst_ilseq
)
126 return (_MAPPER_CONVERT_ILSEQ
);
130 return (_MAPPER_CONVERT_SUCCESS
);
134 set_linear_zone(struct _citrus_mapper_std_linear_zone
*lz
,
135 uint32_t begin
, uint32_t end
)
143 lz
->width
= end
- begin
+ 1;
149 rowcol_parse_variable_compat(struct _citrus_mapper_std_rowcol
*rc
,
152 const struct _citrus_mapper_std_rowcol_info_compat_x
*rcx
;
153 struct _citrus_mapper_std_linear_zone
*lz
;
157 rcx
= _region_head(r
);
159 rc
->rc_dst_invalid
= be32toh(rcx
->rcx_dst_invalid
);
160 rc
->rc_dst_unit_bits
= be32toh(rcx
->rcx_dst_unit_bits
);
161 m
= be32toh(rcx
->rcx_src_col_bits
);
164 rc
->rc_src_rowcol_bits
= m
;
165 rc
->rc_src_rowcol_mask
= n
;
167 rc
->rc_src_rowcol
= malloc(2 *
168 sizeof(*rc
->rc_src_rowcol
));
169 if (rc
->rc_src_rowcol
== NULL
)
171 lz
= rc
->rc_src_rowcol
;
172 rc
->rc_src_rowcol_len
= 1;
173 m
= be32toh(rcx
->rcx_src_row_begin
);
174 n
= be32toh(rcx
->rcx_src_row_end
);
176 ret
= set_linear_zone(lz
, m
, n
);
178 free(rc
->rc_src_rowcol
);
179 rc
->rc_src_rowcol
= NULL
;
182 ++rc
->rc_src_rowcol_len
, ++lz
;
184 m
= be32toh(rcx
->rcx_src_col_begin
);
185 n
= be32toh(rcx
->rcx_src_col_end
);
187 return (set_linear_zone(lz
, m
, n
));
191 rowcol_parse_variable(struct _citrus_mapper_std_rowcol
*rc
,
194 const struct _citrus_mapper_std_rowcol_info_x
*rcx
;
195 struct _citrus_mapper_std_linear_zone
*lz
;
200 rcx
= _region_head(r
);
202 rc
->rc_dst_invalid
= be32toh(rcx
->rcx_dst_invalid
);
203 rc
->rc_dst_unit_bits
= be32toh(rcx
->rcx_dst_unit_bits
);
205 m
= be32toh(rcx
->rcx_src_rowcol_bits
);
208 rc
->rc_src_rowcol_bits
= m
;
209 rc
->rc_src_rowcol_mask
= n
;
211 rc
->rc_src_rowcol_len
= be32toh(rcx
->rcx_src_rowcol_len
);
212 if (rc
->rc_src_rowcol_len
> _CITRUS_MAPPER_STD_ROWCOL_MAX
)
214 rc
->rc_src_rowcol
= malloc(rc
->rc_src_rowcol_len
*
215 sizeof(*rc
->rc_src_rowcol
));
216 if (rc
->rc_src_rowcol
== NULL
)
218 for (i
= 0, lz
= rc
->rc_src_rowcol
;
219 i
< rc
->rc_src_rowcol_len
; ++i
, ++lz
) {
220 m
= be32toh(rcx
->rcx_src_rowcol
[i
].begin
),
221 n
= be32toh(rcx
->rcx_src_rowcol
[i
].end
);
222 ret
= set_linear_zone(lz
, m
, n
);
224 free(rc
->rc_src_rowcol
);
225 rc
->rc_src_rowcol
= NULL
;
233 rowcol_uninit(struct _citrus_mapper_std
*ms
)
235 struct _citrus_mapper_std_rowcol
*rc
;
238 free(rc
->rc_src_rowcol
);
242 rowcol_init(struct _citrus_mapper_std
*ms
)
244 struct _citrus_mapper_std_linear_zone
*lz
;
245 struct _citrus_mapper_std_rowcol
*rc
;
246 const struct _citrus_mapper_std_rowcol_ext_ilseq_info_x
*eix
;
252 ms
->ms_convert
= &rowcol_convert
;
253 ms
->ms_uninit
= &rowcol_uninit
;
256 /* get table region */
257 ret
= _db_lookup_by_s(ms
->ms_db
, _CITRUS_MAPPER_STD_SYM_TABLE
,
258 &rc
->rc_table
, NULL
);
265 /* get table information */
266 ret
= _db_lookup_by_s(ms
->ms_db
, _CITRUS_MAPPER_STD_SYM_INFO
, &r
, NULL
);
272 switch (_region_size(&r
)) {
273 case _CITRUS_MAPPER_STD_ROWCOL_INFO_COMPAT_SIZE
:
274 ret
= rowcol_parse_variable_compat(rc
, &r
);
276 case _CITRUS_MAPPER_STD_ROWCOL_INFO_SIZE
:
277 ret
= rowcol_parse_variable(rc
, &r
);
285 switch (rc
->rc_src_rowcol_bits
) {
286 case 8: case 16: case 32:
287 if (rc
->rc_src_rowcol_len
<= 32 / rc
->rc_src_rowcol_bits
)
294 /* ilseq extension */
295 rc
->rc_oob_mode
= _CITRUS_MAPPER_STD_OOB_NONIDENTICAL
;
296 rc
->rc_dst_ilseq
= rc
->rc_dst_invalid
;
297 ret
= _db_lookup_by_s(ms
->ms_db
,
298 _CITRUS_MAPPER_STD_SYM_ROWCOL_EXT_ILSEQ
, &r
, NULL
);
299 if (ret
&& ret
!= ENOENT
)
301 if (_region_size(&r
) < sizeof(*eix
))
304 eix
= _region_head(&r
);
305 rc
->rc_oob_mode
= be32toh(eix
->eix_oob_mode
);
306 rc
->rc_dst_ilseq
= be32toh(eix
->eix_dst_ilseq
);
309 /* calcurate expected table size */
310 i
= rc
->rc_src_rowcol_len
;
311 lz
= &rc
->rc_src_rowcol
[--i
];
312 table_size
= lz
->width
;
314 lz
= &rc
->rc_src_rowcol
[--i
];
315 table_size
*= lz
->width
;
317 table_size
*= rc
->rc_dst_unit_bits
/8;
319 if (table_size
> UINT32_MAX
||
320 _region_size(&rc
->rc_table
) < table_size
)
326 typedef int (*initfunc_t
)(struct _citrus_mapper_std
*);
327 static const struct {
331 { &rowcol_init
, _CITRUS_MAPPER_STD_TYPE_ROWCOL
},
333 #define NUM_OF_TYPES ((int)(sizeof(types)/sizeof(types[0])))
337 _citrus_mapper_std_mapper_init(struct _citrus_mapper_area
*__restrict ma __unused
,
338 struct _citrus_mapper
* __restrict cm
, const char * __restrict curdir
,
339 const void * __restrict var
, size_t lenvar
,
340 struct _citrus_mapper_traits
* __restrict mt
, size_t lenmt
)
342 struct _citrus_mapper_std
*ms
;
348 if (lenmt
< sizeof(*mt
)) {
352 mt
->mt_src_max
= mt
->mt_dst_max
= 1; /* 1:1 converter */
353 mt
->mt_state_size
= 0; /* stateless */
355 /* alloc mapper std structure */
356 ms
= malloc(sizeof(*ms
));
362 /* open mapper file */
363 snprintf(path
, sizeof(path
), "%s/%.*s", curdir
, (int)lenvar
,
365 ret
= _map_file(&ms
->ms_file
, path
);
369 ret
= _db_open(&ms
->ms_db
, &ms
->ms_file
, _CITRUS_MAPPER_STD_MAGIC
,
370 &_db_hash_std
, NULL
);
374 /* get mapper type */
375 ret
= _db_lookupstr_by_s(ms
->ms_db
, _CITRUS_MAPPER_STD_SYM_TYPE
,
382 for (id
= 0; id
< NUM_OF_TYPES
; id
++)
383 if (_bcs_strcasecmp(type
, types
[id
].t_name
) == 0)
386 if (id
== NUM_OF_TYPES
)
389 /* init the per-type structure */
390 ret
= (*types
[id
].t_init
)(ms
);
399 _db_close(ms
->ms_db
);
401 _unmap_file(&ms
->ms_file
);
410 _citrus_mapper_std_mapper_uninit(struct _citrus_mapper
*cm
)
412 struct _citrus_mapper_std
*ms
;
416 (*ms
->ms_uninit
)(ms
);
417 _db_close(ms
->ms_db
);
418 _unmap_file(&ms
->ms_file
);
424 _citrus_mapper_std_mapper_init_state(void)
431 _citrus_mapper_std_mapper_convert(struct _citrus_mapper
* __restrict cm
,
432 _index_t
* __restrict dst
, _index_t src
, void * __restrict ps
)
434 struct _citrus_mapper_std
*ms
;
437 return ((*ms
->ms_convert
)(ms
, dst
, src
, ps
));