]> git.ipfire.org Git - people/ms/network.git/blame - src/networkd/string.h
string: Define an own type for string tables
[people/ms/network.git] / src / networkd / string.h
CommitLineData
4237caa2
MT
1/*#############################################################################
2# #
3# IPFire.org - A linux based firewall #
4# Copyright (C) 2023 IPFire Network Development Team #
5# #
6# This program is free software: you can redistribute it and/or modify #
7# it under the terms of the GNU General Public License as published by #
8# the Free Software Foundation, either version 3 of the License, or #
9# (at your option) any later version. #
10# #
11# This program is distributed in the hope that it will be useful, #
12# but WITHOUT ANY WARRANTY; without even the implied warranty of #
13# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
14# GNU General Public License for more details. #
15# #
16# You should have received a copy of the GNU General Public License #
17# along with this program. If not, see <http://www.gnu.org/licenses/>. #
18# #
19#############################################################################*/
20
21#ifndef NETWORKD_STRING_H
22#define NETWORKD_STRING_H
23
5ef56cff 24#include <ctype.h>
e4eebc6e 25#include <errno.h>
4237caa2 26#include <stdarg.h>
e4eebc6e
MT
27#include <stdio.h>
28#include <string.h>
4237caa2 29
00b5de56
MT
30#define nw_string_vformat(s, format, ...) \
31 __nw_string_vformat(s, sizeof(s), format, __VA_ARGS__)
32
4237caa2
MT
33static inline int __nw_string_vformat(char* s, const size_t length,
34 const char* format, va_list args) {
35 // Write string to buffer
36 const ssize_t required = vsnprintf(s, length, format, args);
37
38 // Catch any errors
39 if (required < 0)
40 return 1;
41
42 // Check if the entire string could be written
43 if ((size_t)required >= length) {
44 errno = ENOMEM;
45 return 1;
46 }
47
48 // Success
49 return 0;
50}
51
52#define nw_string_format(s, format, ...) \
53 __nw_string_format(s, sizeof(s), format, __VA_ARGS__)
54
55static inline int __nw_string_format(char* s, const size_t length,
56 const char* format, ...) {
57 va_list args;
58 int r;
59
60 // Call __nw_string_vformat
61 va_start(args, format);
62 r = __nw_string_vformat(s, length, format, args);
63 va_end(args);
64
65 return r;
66}
67
68#define nw_string_set(s, value) __nw_string_set(s, sizeof(s), value)
69
70static inline int __nw_string_set(char* s, const size_t length, const char* value) {
71 // If value is NULL, we will overwrite the buffer with just zeros
72 if (!value) {
73 for (unsigned int i = 0; i < length; i++)
74 s[i] = '\0';
75
76 return 0;
77 }
78
79 // Otherwise just copy
80 return __nw_string_format(s, length, "%s", value);
81}
82
5ef56cff
MT
83static inline int nw_string_lstrip(char* s) {
84 char* p = s;
85
86 // Count any leading spaces
87 while (*p && isspace(*p))
88 p++;
89
90 // Move the string to the beginning of the buffer
91 while (*p)
92 *s++ = *p++;
93
94 // Terminate the string
95 *s = '\0';
96
97 return 0;
98}
99
100static inline int nw_string_rstrip(char* s) {
101 ssize_t l = strlen(s) - 1;
102
103 while (l >= 0 && isspace(s[l]))
104 s[l--] = '\0';
105
106 return 0;
107}
108
109static inline int nw_string_strip(char* s) {
110 int r;
111
112 r = nw_string_lstrip(s);
113 if (r)
114 return r;
115
116 r = nw_string_rstrip(s);
117 if (r)
118 return r;
119
120 return 0;
121}
122
c7761af8
MT
123static inline void nw_string_empty(char* s) {
124 if (s)
125 *s = '\0';
126}
127
f9975100
MT
128/*
129 Tables
130*/
131
644eb1c8 132typedef struct nw_string_table {
f9975100
MT
133 const int id;
134 const char* string;
644eb1c8 135} nw_string_table_t;
f9975100
MT
136
137static inline const char* nw_string_table_lookup_string(
644eb1c8
MT
138 const nw_string_table_t* table, const int id) {
139 const nw_string_table_t* entry = NULL;
f9975100
MT
140
141 for (entry = table; entry->string; entry++)
142 if (entry->id == id)
143 return entry->string;
144
145 return NULL;
146}
147
148static inline int nw_string_table_lookup_id(
644eb1c8
MT
149 const nw_string_table_t* table, const char* string) {
150 const nw_string_table_t* entry = NULL;
f9975100
MT
151
152 for (entry = table; entry->string; entry++)
153 if (strcmp(entry->string, string) == 0)
154 return entry->id;
155
156 return -1;
157}
158
159#define NW_STRING_TABLE_LOOKUP_ID(type, table, method) \
160 __attribute__((unused)) static type method(const char* s) { \
161 return nw_string_table_lookup_id(table, s); \
162 }
163
164#define NW_STRING_TABLE_LOOKUP_STRING(type, table, method) \
165 __attribute__((unused)) static const char* method(const type id) { \
166 return nw_string_table_lookup_string(table, id); \
167 }
168
169#define NW_STRING_TABLE_LOOKUP(type, table) \
170 NW_STRING_TABLE_LOOKUP_ID(type, table, table ## _from_string) \
171 NW_STRING_TABLE_LOOKUP_STRING(type, table, table ## _to_string)
172
00b5de56
MT
173/*
174 Paths
175*/
176
177#define nw_path_join(s, first, second) \
178 __nw_path_join(s, sizeof(s), first, second)
179
180static inline int __nw_path_join(char* s, const size_t length,
181 const char* first, const char* second) {
182 if (!first)
183 return __nw_string_format(s, length, "%s", second);
184
185 if (!second)
186 return __nw_string_format(s, length, "%s", first);
187
188 // Remove leading slashes from second argument
189 while (*second == '/')
190 second++;
191
192 return __nw_string_format(s, length, "%s/%s", first, second);
193}
194
c791afc8
MT
195static inline const char* nw_path_basename(const char* path) {
196 const char* basename = strrchr(path, '/');
197 if (!basename)
198 return NULL;
199
200 return basename + 1;
201}
202
4237caa2 203#endif /* NETWORKD_STRING_H */