Coverage Report

Created: 2024-02-29 06:05

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