The FreeRADIUS server  $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
section.c
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or modify
3  * it under the terms of the GNU General Public License as published by
4  * the Free Software Foundation; either version 2 of the License, or
5  * (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software
14  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
15  */
16 
17 /**
18  * $Id: 3dc09eb3920cd55501f63eec6c53cfae9a99e061 $
19  *
20  * @file lib/server/section.c
21  * @brief Comparison functions for sections
22  *
23  * @copyright 2024 Arran Cudbard-Bell (a.cudbardb@freeradius.org)
24  */
25 RCSID("$Id: 3dc09eb3920cd55501f63eec6c53cfae9a99e061 $")
26 
27 #include <freeradius-devel/server/section.h>
28 #include <freeradius-devel/server/cf_util.h>
29 
30 #define IDENT_ANY_CMP(_a, _b) \
31  (((_a) == CF_IDENT_ANY) < ((_b) == CF_IDENT_ANY)) - (((_a) == CF_IDENT_ANY) > ((_b) == CF_IDENT_ANY))
32 
33 #define NULL_CMP(_a, _b) \
34  (((_a) == NULL) < ((_b) == NULL)) - (((_a) == NULL) > ((_b) == NULL))
35 
36 /** Compare two sections
37  *
38  * - Sections are sorted by name1, then name2.
39  * - NULLs sort before non-NULLs.
40  * - CF_IDENT_ANY sort after non-CF_IDENT_ANY.
41  * - Any other comparisons are lexicographic.
42  *
43  * @param[in] one First section name.
44  * @param[in] two Second section name.
45  *
46  * @return < 0 if one < two, 0 if one == two, > 0 if one > two.
47  */
48 int8_t section_name_cmp(void const *one, void const *two)
49 {
50  section_name_t const *a = one;
51  section_name_t const *b = two;
52  int ret;
53 
54  /*
55  * name1 isn't allowed to be NULL, for wildcard matches
56  * we use CF_IDENT_ANY.
57  */
58  fr_assert(a->name1 && b->name1);
59 
60  /*
61  * Straight comparison between sections.
62  */
63  ret = CMP(a, b);
64  if (ret == 0) return 0;
65 
66  /*
67  * Fastpath for static strings and CF_IDENT_ANY
68  */
69  if (a->name1 == b->name1) goto name2;
70 
71  /*
72  * If either identifier is CF_IDENT_ANY, we can't strcmp.
73  */
74  if ((a->name1 == CF_IDENT_ANY) || (b->name1 == CF_IDENT_ANY)) {
75  ret = IDENT_ANY_CMP(b->name1, a->name1);
76  if (ret != 0) return ret;
77  } else {
78  ret = strcmp(a->name1, b->name1);
79  if (ret != 0) return CMP(ret, 0);
80  }
81 
82 name2:
83  /*
84  * Second identifier can be NULL.
85  *
86  * NULL name2s sort first.
87  */
88  ret = NULL_CMP(a->name2, b->name2);
89  if (ret != 0) return ret;
90 
91  if (a->name2 == b->name2) return 0;
92 
93  if ((a->name2 == CF_IDENT_ANY) || (b->name2 == CF_IDENT_ANY)) {
94  return IDENT_ANY_CMP(b->name2, a->name2); /* Can't strcmp */
95  }
96 
97  return CMP(strcmp(a->name2, b->name2), 0);
98 }
#define RCSID(id)
Definition: build.h:481
#define CMP(_a, _b)
Same as CMP_PREFER_SMALLER use when you don't really care about ordering, you just want an ordering.
Definition: build.h:110
#define CF_IDENT_ANY
Definition: cf_util.h:78
#define NULL_CMP(_a, _b)
Definition: section.c:33
#define IDENT_ANY_CMP(_a, _b)
Definition: section.c:30
int8_t section_name_cmp(void const *one, void const *two)
Compare two sections.
Definition: section.c:48
char const * name2
Second section name. Usually a packet type like 'access-request', 'access-accept',...
Definition: section.h:46
char const * name1
First section name. Usually a verb like 'recv', 'send', etc...
Definition: section.h:45
Section name identifier.
Definition: section.h:44
fr_assert(0)