/src/freeradius-server/src/lib/server/section.c
Line | Count | Source |
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: 9cd81fe1998a541c6d12744e5f27e1b295e40328 $ |
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: 9cd81fe1998a541c6d12744e5f27e1b295e40328 $") |
26 | | |
27 | | #include <freeradius-devel/server/section.h> |
28 | | |
29 | | #define IDENT_ANY_CMP(_a, _b) \ |
30 | 0 | (((_a) == CF_IDENT_ANY) < ((_b) == CF_IDENT_ANY)) - (((_a) == CF_IDENT_ANY) > ((_b) == CF_IDENT_ANY)) |
31 | | |
32 | | #define NULL_CMP(_a, _b) \ |
33 | 0 | (((_a) == NULL) < ((_b) == NULL)) - (((_a) == NULL) > ((_b) == NULL)) |
34 | | |
35 | | /** Compare two sections |
36 | | * |
37 | | * - Sections are sorted by name1, then name2. |
38 | | * - NULLs sort before non-NULLs. |
39 | | * - CF_IDENT_ANY sort after non-CF_IDENT_ANY. |
40 | | * - Any other comparisons are lexicographic. |
41 | | * |
42 | | * @param[in] one First section name. |
43 | | * @param[in] two Second section name. |
44 | | * |
45 | | * @return < 0 if one < two, 0 if one == two, > 0 if one > two. |
46 | | */ |
47 | | int8_t section_name_cmp(void const *one, void const *two) |
48 | 0 | { |
49 | 0 | section_name_t const *a = one; |
50 | 0 | section_name_t const *b = two; |
51 | 0 | int ret; |
52 | | |
53 | | /* |
54 | | * name1 isn't allowed to be NULL, for wildcard matches |
55 | | * we use CF_IDENT_ANY. |
56 | | */ |
57 | 0 | fr_assert(a->name1 && b->name1); |
58 | | |
59 | | /* |
60 | | * Straight comparison between sections. |
61 | | */ |
62 | 0 | ret = CMP(a, b); |
63 | 0 | if (ret == 0) return 0; |
64 | | |
65 | | /* |
66 | | * Fastpath for static strings and CF_IDENT_ANY |
67 | | */ |
68 | 0 | if (a->name1 == b->name1) goto name2; |
69 | | |
70 | | /* |
71 | | * If either identifier is CF_IDENT_ANY, we can't strcmp. |
72 | | */ |
73 | 0 | if ((a->name1 == CF_IDENT_ANY) || (b->name1 == CF_IDENT_ANY)) { |
74 | 0 | ret = IDENT_ANY_CMP(b->name1, a->name1); |
75 | 0 | if (ret != 0) return ret; |
76 | 0 | } else { |
77 | 0 | ret = strcmp(a->name1, b->name1); |
78 | 0 | if (ret != 0) return CMP(ret, 0); |
79 | 0 | } |
80 | | |
81 | 0 | name2: |
82 | | /* |
83 | | * Second identifier can be NULL. |
84 | | * |
85 | | * NULL name2s sort first. |
86 | | */ |
87 | 0 | ret = NULL_CMP(a->name2, b->name2); |
88 | 0 | if (ret != 0) return ret; |
89 | | |
90 | 0 | if (a->name2 == b->name2) return 0; |
91 | | |
92 | 0 | if ((a->name2 == CF_IDENT_ANY) || (b->name2 == CF_IDENT_ANY)) { |
93 | 0 | return IDENT_ANY_CMP(b->name2, a->name2); /* Can't strcmp */ |
94 | 0 | } |
95 | | |
96 | 0 | return CMP(strcmp(a->name2, b->name2), 0); |
97 | 0 | } |