]> git.ipfire.org Git - thirdparty/strongswan.git/blame - src/libstrongswan/utils/enum.c
Update copyright headers after acquisition by secunet
[thirdparty/strongswan.git] / src / libstrongswan / utils / enum.c
CommitLineData
c795c4e5 1/*
db7ef624 2 * Copyright (C) 2006 Martin Willi
19ef2aec
TB
3 *
4 * Copyright (C) secunet Security Networks AG
c795c4e5
MW
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2 of the License, or (at your
9 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * for more details.
15 */
4750f6c6 16
db7ef624 17#include <stddef.h>
60356f33 18#include <stdio.h>
6f74bfd6 19
f9efac2b 20#include <library.h>
7137fd96 21#include <collections/enumerator.h>
9ee8b3b4 22#include <utils/utils.h>
f9efac2b 23
db7ef624 24#include "enum.h"
c795c4e5 25
db7ef624 26/**
f9efac2b 27 * See header.
c795c4e5 28 */
f9efac2b 29char *enum_to_name(enum_name_t *e, int val)
c795c4e5 30{
de1c492a
MW
31 if (!e)
32 {
33 return NULL;
34 }
60356f33 35 do
c795c4e5 36 {
60356f33 37 if (val >= e->first && val <= e->last)
c795c4e5 38 {
60356f33 39 return e->names[val - e->first];
c795c4e5
MW
40 }
41 }
60356f33
MW
42 while ((e = e->next));
43 return NULL;
c795c4e5 44}
6f74bfd6 45
f9efac2b
MW
46/**
47 * See header.
48 */
064fe9c9 49bool enum_from_name_as_int(enum_name_t *e, const char *name, int *val)
f9efac2b
MW
50{
51 do
52 {
dc1b2eb2 53 int i, count = e->last - e->first + 1;
f9efac2b
MW
54
55 for (i = 0; i < count; i++)
56 {
9947a1f2 57 if (name && strcaseeq(name, e->names[i]))
f9efac2b 58 {
064fe9c9
MW
59 *val = e->first + i;
60 return TRUE;
f9efac2b
MW
61 }
62 }
63 }
64 while ((e = e->next));
064fe9c9 65 return FALSE;
f9efac2b
MW
66}
67
4dc72f5e
TE
68/**
69 * Get the position of a flag name using offset calculation
70 */
927103ec 71static int find_flag_pos(u_int first, u_int val)
4dc72f5e
TE
72{
73 int offset = 0;
74
927103ec 75 while (first != 0x01)
4dc72f5e 76 {
927103ec 77 first = first >> 1;
4dc72f5e
TE
78 offset++;
79 }
927103ec
TB
80 /* skip the first name as that's used if no flag is set */
81 return 1 + val - offset;
4dc72f5e
TE
82}
83
60356f33 84/**
d25ce370 85 * Described in header.
6f74bfd6 86 */
4dc72f5e
TE
87char *enum_flags_to_string(enum_name_t *e, u_int val, char *buf, size_t len)
88{
89 char *pos = buf, *delim = "";
90 int i, wr;
91
92 if (e->next != ENUM_FLAG_MAGIC)
93 {
94 if (snprintf(buf, len, "(%d)", (int)val) >= len)
95 {
96 return NULL;
97 }
98 return buf;
99 }
100
d23c0ea8 101 if (snprintf(buf, len, "%s", e->names[0]) >= len)
4dc72f5e
TE
102 {
103 return NULL;
104 }
105
106 for (i = 0; val; i++)
107 {
108 u_int flag = 1 << i;
109
110 if (val & flag)
111 {
112 char *name = NULL, hex[32];
113
114 if (flag >= (u_int)e->first && flag <= (u_int)e->last)
115 {
116 name = e->names[find_flag_pos(e->first, i)];
117 }
118 else
119 {
120 snprintf(hex, sizeof(hex), "(0x%X)", flag);
121 name = hex;
122 }
123 if (name)
124 {
125 wr = snprintf(pos, len, "%s%s", delim, name);
126 if (wr >= len)
127 {
128 return NULL;
129 }
130 len -= wr;
131 pos += wr;
132 delim = " | ";
133 }
134 val &= ~flag;
135 }
136 }
137 return buf;
138}
139
7137fd96
TB
140/*
141 * Described in header
142 */
143bool enum_flags_from_string_as_int(enum_name_t *e, const char *str, u_int *val)
144{
145 enumerator_t *enumerator;
146 char *name;
147
148 *val = 0;
149
150 if (!str || !*str)
151 {
152 return TRUE;
153 }
154 else if (e->next != ENUM_FLAG_MAGIC)
155 {
156 return enum_from_name_as_int(e, str, val);
157 }
158
159 enumerator = enumerator_create_token(str, "|", " ");
160 while (enumerator->enumerate(enumerator, &name))
161 {
162 u_int flag, i;
163 bool found = FALSE;
164
165 if (strcaseeq(name, e->names[0]))
166 { /* accept name used if no flags are set */
167 continue;
168 }
169 for (i = 1, flag = e->first; flag <= e->last; i++, flag <<= 1)
170 {
171 if (e->names[i] && strcaseeq(name, e->names[i]))
172 {
173 *val |= flag;
174 found = TRUE;
175 break;
176 }
177 }
178 if (!found)
179 {
180 enumerator->destroy(enumerator);
181 return FALSE;
182 }
183 }
184 enumerator->destroy(enumerator);
185 return TRUE;
186}
187
4dc72f5e
TE
188/**
189 * See header.
190 */
1b40b74d 191int enum_printf_hook(printf_hook_data_t *data, printf_hook_spec_t *spec,
d25ce370 192 const void *const *args)
6f74bfd6 193{
ccd61203
AS
194 enum_name_t *ed = *((enum_name_t**)(args[0]));
195 int val = *((int*)(args[1]));
4dc72f5e 196 char *name, buf[512];
ccd61203 197
de1c492a 198 if (ed && ed->next == ENUM_FLAG_MAGIC)
4dc72f5e
TE
199 {
200 name = enum_flags_to_string(ed, val, buf, sizeof(buf));
201 if (name == NULL)
202 {
203 snprintf(buf, sizeof(buf), "(0x%X)", val);
204 name = buf;
205 }
206 }
207 else
60356f33 208 {
4dc72f5e
TE
209 name = enum_to_name(ed, val);
210 if (name == NULL)
211 {
212 snprintf(buf, sizeof(buf), "(%d)", val);
213 name = buf;
214 }
ccd61203 215 }
2232d885 216 if (spec->minus)
ccd61203 217 {
2232d885 218 return print_in_hook(data, "%-*s", spec->width, name);
552cc11b 219 }
2232d885 220 return print_in_hook(data, "%*s", spec->width, name);
552cc11b 221}