1 /* $NetBSD: parse_units.c,v 1.1.1.2 2014/04/24 12:45:52 pettai Exp $ */
4 * Copyright (c) 1997 - 2001 Kungliga Tekniska Högskolan
5 * (Royal Institute of Technology, Stockholm, Sweden).
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
19 * 3. Neither the name of the Institute nor the names of its contributors
20 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission.
23 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
41 #include <krb5/roken.h>
42 #include <krb5/parse_units.h>
45 * Parse string in `s' according to `units' and return value.
46 * def_unit defines the default unit.
50 parse_something (const char *s
, const struct units
*units
,
52 int (*func
)(int res
, int val
, unsigned mult
),
58 unsigned def_mult
= 1;
60 if (def_unit
!= NULL
) {
61 const struct units
*u
;
63 for (u
= units
; u
->name
; ++u
) {
64 if (strcasecmp (u
->name
, def_unit
) == 0) {
77 const struct units
*u
, *partial_unit
;
82 while(isspace((unsigned char)*p
) || *p
== ',')
85 val
= strtol(p
, &next
, 0);
93 while (isspace((unsigned char)*p
))
96 res
= (*func
)(res
, val
, def_mult
);
100 } else if (*p
== '+') {
103 } else if (*p
== '-') {
107 if (no_val_p
&& val
== 0)
109 u_len
= strcspn (p
, ", \t");
112 if (u_len
> 1 && p
[u_len
- 1] == 's')
114 for (u
= units
; u
->name
; ++u
) {
115 if (strncasecmp (p
, u
->name
, u_len
) == 0) {
116 if (u_len
== strlen (u
->name
)) {
118 res
= (*func
)(res
, val
, u
->mult
);
128 if (u
->name
== NULL
) {
131 res
= (*func
)(res
, val
, partial_unit
->mult
);
145 * The string consists of a sequence of `n unit'
149 acc_units(int res
, int val
, unsigned mult
)
151 return res
+ val
* mult
;
154 ROKEN_LIB_FUNCTION
int ROKEN_LIB_CALL
155 parse_units (const char *s
, const struct units
*units
,
156 const char *def_unit
)
158 return parse_something (s
, units
, def_unit
, acc_units
, 0, 0);
162 * The string consists of a sequence of `[+-]flag'. `orig' consists
163 * the original set of flags, those are then modified and returned as
164 * the function value.
168 acc_flags(int res
, int val
, unsigned mult
)
180 ROKEN_LIB_FUNCTION
int ROKEN_LIB_CALL
181 parse_flags (const char *s
, const struct units
*units
,
184 return parse_something (s
, units
, NULL
, acc_flags
, orig
, 1);
188 * Return a string representation according to `units' of `num' in `s'
189 * with maximum length `len'. The actual length is the function value.
193 unparse_something (int num
, const struct units
*units
, char *s
, size_t len
,
194 int (*print
) (char *, size_t, int, const char *, int),
195 int (*update
) (int, unsigned),
196 const char *zero_string
)
198 const struct units
*u
;
202 return snprintf (s
, len
, "%s", zero_string
);
204 for (u
= units
; num
> 0 && u
->name
; ++u
) {
207 divisor
= num
/ u
->mult
;
209 num
= (*update
) (num
, u
->mult
);
210 tmp
= (*print
) (s
, len
, divisor
, u
->name
, num
);
213 if (tmp
> (int) len
) {
227 print_unit (char *s
, size_t len
, int divisor
, const char *name
, int rem
)
229 return snprintf (s
, len
, "%u %s%s%s",
231 divisor
== 1 ? "" : "s",
236 update_unit (int in
, unsigned mult
)
242 update_unit_approx (int in
, unsigned mult
)
247 return update_unit (in
, mult
);
250 ROKEN_LIB_FUNCTION
int ROKEN_LIB_CALL
251 unparse_units (int num
, const struct units
*units
, char *s
, size_t len
)
253 return unparse_something (num
, units
, s
, len
,
259 ROKEN_LIB_FUNCTION
int ROKEN_LIB_CALL
260 unparse_units_approx (int num
, const struct units
*units
, char *s
, size_t len
)
262 return unparse_something (num
, units
, s
, len
,
268 ROKEN_LIB_FUNCTION
void ROKEN_LIB_CALL
269 print_units_table (const struct units
*units
, FILE *f
)
271 const struct units
*u
, *u2
;
274 for (u
= units
; u
->name
; ++u
) {
275 max_sz
= max(max_sz
, strlen(u
->name
));
278 for (u
= units
; u
->name
;) {
280 const struct units
*next
;
282 for (next
= u
+ 1; next
->name
&& next
->mult
== u
->mult
; ++next
)
287 u2
->name
&& u
->mult
% u2
->mult
!= 0;
290 if (u2
->name
== NULL
)
292 unparse_units (u
->mult
, u2
, buf
, sizeof(buf
));
293 fprintf (f
, "1 %*s = %s\n", (int)max_sz
, u
->name
, buf
);
295 fprintf (f
, "1 %s\n", u
->name
);
302 print_flag (char *s
, size_t len
, int divisor
, const char *name
, int rem
)
304 return snprintf (s
, len
, "%s%s", name
, rem
> 0 ? ", " : "");
308 update_flag (int in
, unsigned mult
)
313 ROKEN_LIB_FUNCTION
int ROKEN_LIB_CALL
314 unparse_flags (int num
, const struct units
*units
, char *s
, size_t len
)
316 return unparse_something (num
, units
, s
, len
,
322 ROKEN_LIB_FUNCTION
void ROKEN_LIB_CALL
323 print_flags_table (const struct units
*units
, FILE *f
)
325 const struct units
*u
;
327 for(u
= units
; u
->name
; ++u
)
328 fprintf(f
, "%s%s", u
->name
, (u
+1)->name
? ", " : "\n");