1 /* $FreeBSD: head/lib/libiconv_modules/mapper_zone/citrus_mapper_zone.c 219019 2011-02-25 00:04:39Z gabor $ */
2 /* $NetBSD: citrus_mapper_zone.c,v 1.4 2003/07/12 15:39:21 tshiozak Exp $ */
5 * Copyright (c)2003 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/queue.h>
39 #include "citrus_namespace.h"
40 #include "citrus_types.h"
41 #include "citrus_bcs.h"
42 #include "citrus_module.h"
43 #include "citrus_region.h"
44 #include "citrus_memstream.h"
45 #include "citrus_mmap.h"
46 #include "citrus_hash.h"
47 #include "citrus_mapper.h"
48 #include "citrus_mapper_zone.h"
50 /* ---------------------------------------------------------------------- */
52 _CITRUS_MAPPER_DECLS(mapper_zone
);
53 _CITRUS_MAPPER_DEF_OPS(mapper_zone
);
56 /* ---------------------------------------------------------------------- */
63 struct _citrus_mapper_zone
{
66 int32_t mz_col_offset
;
67 int32_t mz_row_offset
;
72 enum { S_BEGIN
, S_OFFSET
} ps_state
;
78 #define ps_u_imm u.u_imm
79 #define ps_s_imm u.s_imm
80 #define ps_zone u.zone
85 _citrus_mapper_zone_mapper_getops(struct _citrus_mapper_ops
*ops
)
88 memcpy(ops
, &_citrus_mapper_zone_mapper_ops
,
89 sizeof(_citrus_mapper_zone_mapper_ops
));
99 get_imm(struct _memstream
*ms
, struct _parse_state
*ps
)
102 char buf
[BUFSIZE
+ 1];
105 for (i
= 0; i
< BUFSIZE
; i
++) {
107 c
= _memstream_peek(ms
);
109 if (sign
== 0 && (c
== '+' || c
== '-')) {
113 } else if (!_bcs_isdigit(c
))
115 } else if (!_bcs_isxdigit(c
))
116 if (!(i
== 1 && c
== 'x'))
118 buf
[i
] = _memstream_getc(ms
);
121 ps
->ps_u_imm
= strtoul(buf
, &p
, 0);
125 ps
->ps_u_imm
= (unsigned long)-(long)ps
->ps_u_imm
;
130 get_tok(struct _memstream
*ms
, struct _parse_state
*ps
)
135 c
= _memstream_peek(ms
);
138 if (_bcs_isspace(c
)) {
143 switch (ps
->ps_state
) {
161 return (get_imm(ms
, ps
));
181 return (get_imm(ms
, ps
));
189 parse_zone(struct _memstream
*ms
, struct _parse_state
*ps
, struct _zone
*z
)
192 if (get_tok(ms
, ps
) != T_IMM
)
194 z
->z_begin
= ps
->ps_u_imm
;
195 if (get_tok(ms
, ps
) != '-')
197 if (get_tok(ms
, ps
) != T_IMM
)
199 z
->z_end
= ps
->ps_u_imm
;
201 if (z
->z_begin
> z
->z_end
)
208 check_rowcol(struct _zone
*z
, int32_t ofs
, uint32_t maxval
)
212 if (maxval
!= 0 && z
->z_end
>= maxval
)
217 /* this should 0x100000000 - z->z_end */
218 remain
= (z
->z_end
== 0) ? 0xFFFFFFFF :
219 0xFFFFFFFF - z
->z_end
+ 1;
221 remain
= maxval
- z
->z_end
;
222 if ((uint32_t)ofs
> remain
)
224 } else if (ofs
< 0) {
225 if (z
->z_begin
< (uint32_t)-ofs
)
233 parse_var(struct _citrus_mapper_zone
*mz
, struct _memstream
*ms
)
235 struct _parse_state ps
;
236 uint32_t colmax
, rowmax
;
239 ps
.ps_state
= S_BEGIN
;
241 if (parse_zone(ms
, &ps
, &mz
->mz_col
))
244 ret
= get_tok(ms
, &ps
);
246 /* rowzone / colzone / bits */
248 mz
->mz_row
= mz
->mz_col
;
250 if (parse_zone(ms
, &ps
, &mz
->mz_col
))
252 if (get_tok(ms
, &ps
) != '/')
254 if (get_tok(ms
, &ps
) != T_IMM
)
256 mz
->mz_col_bits
= ps
.ps_u_imm
;
257 if (mz
->mz_col_bits
< 0 || mz
->mz_col_bits
> 32)
259 ret
= get_tok(ms
, &ps
);
263 mz
->mz_col_bits
= 32;
264 mz
->mz_row
.z_begin
= mz
->mz_row
.z_end
= 0;
268 ps
.ps_state
= S_OFFSET
;
269 if (get_tok(ms
, &ps
) != T_IMM
)
271 mz
->mz_col_offset
= ps
.ps_s_imm
;
274 mz
->mz_row_offset
= mz
->mz_col_offset
;
275 if (get_tok(ms
, &ps
) != '/')
277 if (get_tok(ms
, &ps
) != T_IMM
)
279 mz
->mz_col_offset
= ps
.ps_s_imm
;
281 mz
->mz_row_offset
= 0;
282 ret
= get_tok(ms
, &ps
);
288 colmax
= (mz
->mz_col_bits
== 32) ? 0 : 1 << mz
->mz_col_bits
;
289 rowmax
= (mz
->mz_col_bits
== 0) ? 0 : 1 << (32-mz
->mz_col_bits
);
290 if (check_rowcol(&mz
->mz_col
, mz
->mz_col_offset
, colmax
))
292 if (check_rowcol(&mz
->mz_row
, mz
->mz_row_offset
, rowmax
))
300 _citrus_mapper_zone_mapper_init(struct _citrus_mapper_area
*__restrict ma __unused
,
301 struct _citrus_mapper
* __restrict cm
, const char * __restrict dir __unused
,
302 const void * __restrict var
, size_t lenvar
,
303 struct _citrus_mapper_traits
* __restrict mt
, size_t lenmt
)
305 struct _citrus_mapper_zone
*mz
;
306 struct _memstream ms
;
309 if (lenmt
< sizeof(*mt
))
312 mz
= malloc(sizeof(*mz
));
316 mz
->mz_col
.z_begin
= mz
->mz_col
.z_end
= 0;
317 mz
->mz_row
.z_begin
= mz
->mz_row
.z_end
= 0;
319 mz
->mz_row_offset
= 0;
320 mz
->mz_col_offset
= 0;
322 _region_init(&r
, __DECONST(void *, var
), lenvar
);
323 _memstream_bind(&ms
, &r
);
324 if (parse_var(mz
, &ms
)) {
329 mt
->mt_src_max
= mt
->mt_dst_max
= 1; /* 1:1 converter */
330 mt
->mt_state_size
= 0; /* stateless */
337 _citrus_mapper_zone_mapper_uninit(struct _citrus_mapper
*cm __unused
)
344 _citrus_mapper_zone_mapper_convert(struct _citrus_mapper
* __restrict cm
,
345 _citrus_index_t
* __restrict dst
, _citrus_index_t src
,
346 void * __restrict ps __unused
)
348 struct _citrus_mapper_zone
*mz
= cm
->cm_closure
;
351 if (mz
->mz_col_bits
== 32) {
354 if (col
< mz
->mz_col
.z_begin
|| col
> mz
->mz_col
.z_end
)
355 return (_CITRUS_MAPPER_CONVERT_NONIDENTICAL
);
356 if (mz
->mz_col_offset
> 0)
357 col
+= (uint32_t)mz
->mz_col_offset
;
359 col
-= (uint32_t)-mz
->mz_col_offset
;
362 col
= src
& (((uint32_t)1 << mz
->mz_col_bits
) - 1);
363 row
= src
>> mz
->mz_col_bits
;
364 if (row
< mz
->mz_row
.z_begin
|| row
> mz
->mz_row
.z_end
||
365 col
< mz
->mz_col
.z_begin
|| col
> mz
->mz_col
.z_end
)
366 return (_CITRUS_MAPPER_CONVERT_NONIDENTICAL
);
367 if (mz
->mz_col_offset
> 0)
368 col
+= (uint32_t)mz
->mz_col_offset
;
370 col
-= (uint32_t)-mz
->mz_col_offset
;
371 if (mz
->mz_row_offset
> 0)
372 row
+= (uint32_t)mz
->mz_row_offset
;
374 row
-= (uint32_t)-mz
->mz_row_offset
;
375 *dst
= col
| (row
<< mz
->mz_col_bits
);
377 return (_CITRUS_MAPPER_CONVERT_SUCCESS
);
382 _citrus_mapper_zone_mapper_init_state(void)