1 /* $NetBSD: citrus_prop.c,v 1.3 2006/11/22 23:47:21 tnozaki Exp $ */
2 /* $DragonFly: src/lib/libc/citrus/citrus_prop.c,v 1.1 2008/04/10 10:21:01 hasso Exp $ */
5 * Copyright (c)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
40 #include "citrus_namespace.h"
41 #include "citrus_bcs.h"
42 #include "citrus_region.h"
43 #include "citrus_memstream.h"
44 #include "citrus_prop.h"
47 _citrus_prop_type_t type
;
53 } _citrus_prop_object_t
;
56 _citrus_prop_object_init(_citrus_prop_object_t
*obj
, _citrus_prop_type_t type
)
58 _DIAGASSERT(obj
!= NULL
);
61 memset(&obj
->u
, 0, sizeof(obj
->u
));
65 _citrus_prop_object_uninit(_citrus_prop_object_t
*obj
)
67 _DIAGASSERT(obj
!= NULL
);
69 if (obj
->type
== _CITRUS_PROP_STR
)
70 free(__DECONST(void *, obj
->u
.str
));
73 static const char *xdigit
= "0123456789ABCDEF";
75 #define _CITRUS_PROP_READ_UINT_COMMON(_func_, _type_, _max_) \
77 _citrus_prop_read_##_func_##_common(struct _memstream * __restrict ms, \
78 _type_ * __restrict result, int base) \
84 _DIAGASSERT(ms != NULL); \
85 _DIAGASSERT(result != NULL); \
88 cutoff = _max_ / base; \
89 cutlim = _max_ % base; \
91 ch = _memstream_getc(ms); \
92 p = strchr(xdigit, _bcs_toupper(ch)); \
93 if (p == NULL || (n = (p - xdigit)) >= base) \
95 if (acc > cutoff || (acc == cutoff && n > cutlim)) \
100 _memstream_ungetc(ms, ch); \
104 _CITRUS_PROP_READ_UINT_COMMON(chr
, int, UCHAR_MAX
)
105 _CITRUS_PROP_READ_UINT_COMMON(num
, uint64_t, UINT64_MAX
)
106 #undef _CITRUS_PROP_READ_UINT_COMMON
108 #define _CITRUS_PROP_READ_INT(_func_, _type_) \
110 _citrus_prop_read_##_func_(struct _memstream * __restrict ms, \
111 _citrus_prop_object_t * __restrict obj) \
115 _DIAGASSERT(ms != NULL); \
116 _DIAGASSERT(obj != NULL); \
118 _memstream_skip_ws(ms); \
119 ch = _memstream_getc(ms); \
125 ch = _memstream_getc(ms); \
130 ch = _memstream_getc(ms); \
131 if (ch == 'x' || ch == 'X') { \
132 ch = _memstream_getc(ms); \
133 if (_bcs_isxdigit(ch) == 0) { \
134 _memstream_ungetc(ms, ch); \
140 } else if (_bcs_isdigit(ch) == 0) \
142 _memstream_ungetc(ms, ch); \
143 return _citrus_prop_read_##_func_##_common \
144 (ms, &obj->u._func_, base); \
146 _CITRUS_PROP_READ_INT(chr
, int)
147 _CITRUS_PROP_READ_INT(num
, uint64_t)
148 #undef _CITRUS_PROP_READ_INT
151 _citrus_prop_read_character_common(struct _memstream
* __restrict ms
,
152 int * __restrict result
)
156 _DIAGASSERT(ms
!= NULL
);
157 _DIAGASSERT(result
!= NULL
);
159 ch
= _memstream_getc(ms
);
163 ch
= _memstream_getc(ms
);
166 case 'a': *result
= '\a'; break;
167 case 'b': *result
= '\b'; break;
168 case 'f': *result
= '\f'; break;
169 case 'n': *result
= '\n'; break;
170 case 'r': *result
= '\r'; break;
171 case 't': *result
= '\t'; break;
172 case 'v': *result
= '\v'; break;
174 case '0': case '1': case '2': case '3':
175 case '4': case '5': case '6': case '7':
176 _memstream_ungetc(ms
, ch
);
179 return _citrus_prop_read_chr_common(ms
, result
, base
);
190 _citrus_prop_read_character(struct _memstream
* __restrict ms
,
191 _citrus_prop_object_t
* __restrict obj
)
195 _DIAGASSERT(ms
!= NULL
);
196 _DIAGASSERT(obj
!= NULL
);
198 _memstream_skip_ws(ms
);
199 ch
= _memstream_getc(ms
);
201 _memstream_ungetc(ms
, ch
);
202 return _citrus_prop_read_chr(ms
, obj
);
204 errnum
= _citrus_prop_read_character_common(ms
, &ch
);
208 ch
= _memstream_getc(ms
);
215 _citrus_prop_read_bool(struct _memstream
* __restrict ms
,
216 _citrus_prop_object_t
* __restrict obj
)
218 _DIAGASSERT(ms
!= NULL
);
219 _DIAGASSERT(obj
!= NULL
);
221 _memstream_skip_ws(ms
);
222 switch (_bcs_tolower(_memstream_getc(ms
))) {
224 if (_bcs_tolower(_memstream_getc(ms
)) == 'r' &&
225 _bcs_tolower(_memstream_getc(ms
)) == 'u' &&
226 _bcs_tolower(_memstream_getc(ms
)) == 'e') {
232 if (_bcs_tolower(_memstream_getc(ms
)) == 'a' &&
233 _bcs_tolower(_memstream_getc(ms
)) == 'l' &&
234 _bcs_tolower(_memstream_getc(ms
)) == 's' &&
235 _bcs_tolower(_memstream_getc(ms
)) == 'e') {
244 _citrus_prop_read_str(struct _memstream
* __restrict ms
,
245 _citrus_prop_object_t
* __restrict obj
)
247 int errnum
, quot
, ch
;
249 #define _CITRUS_PROP_STR_BUFSIZ 512
252 _DIAGASSERT(ms
!= NULL
);
253 _DIAGASSERT(obj
!= NULL
);
255 m
= _CITRUS_PROP_STR_BUFSIZ
;
260 _memstream_skip_ws(ms
);
261 quot
= _memstream_getc(ms
);
266 _memstream_ungetc(ms
, quot
);
269 case '\"': case '\'':
278 m
= _CITRUS_PROP_STR_BUFSIZ
;
279 t
= realloc(s
, n
+ m
);
286 ch
= _memstream_getc(ms
);
287 if (quot
== ch
|| (quot
== EOF
&&
288 (ch
== ';' || _bcs_isspace(ch
)))) {
291 obj
->u
.str
= (const char *)s
;
294 _memstream_ungetc(ms
, ch
);
295 errnum
= _citrus_prop_read_character_common(ms
, &ch
);
303 #undef _CITRUS_PROP_STR_BUFSIZ
306 typedef int (*_citrus_prop_read_type_t
)(struct _memstream
* __restrict
,
307 _citrus_prop_object_t
* __restrict
);
309 static const _citrus_prop_read_type_t readers
[] = {
310 _citrus_prop_read_bool
,
311 _citrus_prop_read_str
,
312 _citrus_prop_read_character
,
313 _citrus_prop_read_num
,
317 _citrus_prop_read_symbol(struct _memstream
* __restrict ms
,
318 char * __restrict s
, size_t n
)
323 _DIAGASSERT(ms
!= NULL
);
324 _DIAGASSERT(s
!= NULL
);
327 for (m
= 0; m
< n
; ++m
) {
328 ch
= _memstream_getc(ms
);
329 if (ch
!= '_' && _bcs_isalnum(ch
) == 0)
333 ch
= _memstream_getc(ms
);
334 if (ch
== '_' || _bcs_isalnum(ch
) != 0)
338 _memstream_ungetc(ms
, ch
);
345 _citrus_prop_parse_element(struct _memstream
* __restrict ms
,
346 const _citrus_prop_hint_t
* __restrict hints
,
347 void ** __restrict context
)
350 #define _CITRUS_PROP_HINT_NAME_LEN_MAX 255
351 char name
[_CITRUS_PROP_HINT_NAME_LEN_MAX
+ 1];
352 const _citrus_prop_hint_t
*hint
;
353 _citrus_prop_object_t ostart
, oend
;
355 _DIAGASSERT(ms
!= NULL
);
356 _DIAGASSERT(hints
!= NULL
);
358 errnum
= _citrus_prop_read_symbol(ms
, name
, sizeof(name
));
361 for (hint
= hints
; hint
->name
!= NULL
; ++hint
) {
362 if (_citrus_bcs_strcasecmp(name
, hint
->name
) == 0)
368 _memstream_skip_ws(ms
);
369 ch
= _memstream_getc(ms
);
370 if (ch
!= '=' && ch
!= ':')
371 _memstream_ungetc(ms
, ch
);
373 _citrus_prop_object_init(&ostart
, hint
->type
);
374 _citrus_prop_object_init(&oend
, hint
->type
);
375 errnum
= (*readers
[hint
->type
])(ms
, &ostart
);
378 _memstream_skip_ws(ms
);
379 ch
= _memstream_getc(ms
);
380 switch (hint
->type
) {
381 case _CITRUS_PROP_BOOL
:
382 case _CITRUS_PROP_STR
:
387 errnum
= (*readers
[hint
->type
])(ms
, &oend
);
390 _memstream_skip_ws(ms
);
391 ch
= _memstream_getc(ms
);
393 #define CALL0(_func_) \
395 _DIAGASSERT(hint->cb._func_.func != NULL); \
396 errnum = (*hint->cb._func_.func)(context, \
397 hint->name, ostart.u._func_); \
398 } while (/*CONSTCOND*/0)
399 #define CALL1(_func_) \
401 _DIAGASSERT(hint->cb._func_.func != NULL); \
402 errnum = (*hint->cb._func_.func)(context, \
403 hint->name, ostart.u._func_, oend.u._func_);\
404 } while (/*CONSTCOND*/0)
405 switch (hint
->type
) {
406 case _CITRUS_PROP_BOOL
: CALL0(bool); break;
407 case _CITRUS_PROP_STR
: CALL0( str
); break;
408 case _CITRUS_PROP_CHR
: CALL1( chr
); break;
409 case _CITRUS_PROP_NUM
: CALL1( num
); break;
416 _citrus_prop_object_uninit(&ostart
);
417 _citrus_prop_object_uninit(&oend
);
422 _memstream_ungetc(ms
, ch
);
427 _citrus_prop_parse_variable(const _citrus_prop_hint_t
* __restrict hints
,
428 void * __restrict context
, const void *var
, size_t lenvar
)
430 struct _memstream ms
;
433 _DIAGASSERT(hints
!= NULL
);
435 _memstream_bind_ptr(&ms
, __DECONST(void *, var
), lenvar
);
437 _memstream_skip_ws(&ms
);
438 ch
= _memstream_getc(&ms
);
439 if (ch
== EOF
|| ch
== '\0')
441 _memstream_ungetc(&ms
, ch
);
442 errnum
= _citrus_prop_parse_element(
443 &ms
, hints
, (void **)&context
);