Line |
Branch |
Exec |
Source |
1 |
|
|
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ |
2 |
|
|
/* NetworkManager -- Network link manager |
3 |
|
|
* |
4 |
|
|
* This library is free software; you can redistribute it and/or |
5 |
|
|
* modify it under the terms of the GNU Lesser General Public |
6 |
|
|
* License as published by the Free Software Foundation; either |
7 |
|
|
* version 2 of the License, or (at your option) any later version. |
8 |
|
|
* |
9 |
|
|
* This library is distributed in the hope that it will be useful, |
10 |
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
11 |
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
12 |
|
|
* Lesser General Public License for more details. |
13 |
|
|
* |
14 |
|
|
* You should have received a copy of the GNU Lesser General Public |
15 |
|
|
* License along with this library; if not, write to the |
16 |
|
|
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
17 |
|
|
* Boston, MA 02110-1301 USA. |
18 |
|
|
* |
19 |
|
|
* (C) Copyright 2014 Red Hat, Inc. |
20 |
|
|
*/ |
21 |
|
|
|
22 |
|
|
#ifndef __NM_MACROS_INTERNAL_H__ |
23 |
|
|
#define __NM_MACROS_INTERNAL_H__ |
24 |
|
|
|
25 |
|
|
#include <stdio.h> |
26 |
|
|
#include <stdlib.h> |
27 |
|
|
#include <errno.h> |
28 |
|
|
|
29 |
|
|
#define _nm_packed __attribute__ ((packed)) |
30 |
|
|
#define _nm_unused __attribute__ ((unused)) |
31 |
|
|
#define _nm_pure __attribute__ ((pure)) |
32 |
|
|
#define _nm_const __attribute__ ((const)) |
33 |
|
|
#define _nm_printf(a,b) __attribute__ ((__format__ (__printf__, a, b))) |
34 |
|
|
#define _nm_align(s) __attribute__ ((aligned (s))) |
35 |
|
|
#define _nm_alignof(type) __alignof (type) |
36 |
|
|
#define _nm_alignas(type) _nm_align (_nm_alignof (type)) |
37 |
|
|
|
38 |
|
|
#if __GNUC__ >= 7 |
39 |
|
|
#define _nm_fallthrough __attribute__ ((fallthrough)) |
40 |
|
|
#else |
41 |
|
|
#define _nm_fallthrough |
42 |
|
|
#endif |
43 |
|
|
|
44 |
|
|
/*****************************************************************************/ |
45 |
|
|
|
46 |
|
|
#ifdef thread_local |
47 |
|
|
#define _nm_thread_local thread_local |
48 |
|
|
/* |
49 |
|
|
* Don't break on glibc < 2.16 that doesn't define __STDC_NO_THREADS__ |
50 |
|
|
* see http://gcc.gnu.org/bugzilla/show_bug.cgi?id=53769 |
51 |
|
|
*/ |
52 |
|
|
#elif __STDC_VERSION__ >= 201112L && !(defined(__STDC_NO_THREADS__) || (defined(__GNU_LIBRARY__) && __GLIBC__ == 2 && __GLIBC_MINOR__ < 16)) |
53 |
|
|
#define _nm_thread_local _Thread_local |
54 |
|
|
#else |
55 |
|
|
#define _nm_thread_local __thread |
56 |
|
|
#endif |
57 |
|
|
|
58 |
|
|
/*****************************************************************************/ |
59 |
|
|
|
60 |
|
|
#include "nm-glib.h" |
61 |
|
|
|
62 |
|
|
/*****************************************************************************/ |
63 |
|
|
|
64 |
|
|
#define nm_offsetofend(t,m) (G_STRUCT_OFFSET (t,m) + sizeof (((t *) NULL)->m)) |
65 |
|
|
|
66 |
|
|
#define nm_auto(fcn) __attribute__ ((cleanup(fcn))) |
67 |
|
|
|
68 |
|
|
static inline int nm_close (int fd); |
69 |
|
|
|
70 |
|
|
/** |
71 |
|
|
* nm_auto_free: |
72 |
|
|
* |
73 |
|
|
* Call free() on a variable location when it goes out of scope. |
74 |
|
|
*/ |
75 |
|
|
#define nm_auto_free nm_auto(_nm_auto_free_impl) |
76 |
|
|
GS_DEFINE_CLEANUP_FUNCTION(void*, _nm_auto_free_impl, free) |
77 |
|
|
|
78 |
|
|
static inline void |
79 |
|
|
nm_free_secret (char *secret) |
80 |
|
|
{ |
81 |
|
|
if (secret) { |
82 |
|
|
memset (secret, 0, strlen (secret)); |
83 |
|
|
g_free (secret); |
84 |
|
|
} |
85 |
|
|
} |
86 |
|
|
|
87 |
|
|
static inline void |
88 |
|
|
_nm_auto_free_secret_impl (char **v) |
89 |
|
|
{ |
90 |
|
|
nm_free_secret (*v); |
91 |
|
|
} |
92 |
|
|
|
93 |
|
|
/** |
94 |
|
|
* nm_auto_free_secret: |
95 |
|
|
* |
96 |
|
|
* Call g_free() on a variable location when it goes out of scope. |
97 |
|
|
* Also, previously, calls memset(loc, 0, strlen(loc)) to clear out |
98 |
|
|
* the secret. |
99 |
|
|
*/ |
100 |
|
|
#define nm_auto_free_secret nm_auto(_nm_auto_free_secret_impl) |
101 |
|
|
|
102 |
|
|
static inline void |
103 |
|
|
_nm_auto_unset_gvalue_impl (GValue *v) |
104 |
|
|
{ |
105 |
|
|
g_value_unset (v); |
106 |
|
|
} |
107 |
|
|
#define nm_auto_unset_gvalue nm_auto(_nm_auto_unset_gvalue_impl) |
108 |
|
|
|
109 |
|
|
static inline void |
110 |
|
|
_nm_auto_unref_gtypeclass (gpointer v) |
111 |
|
|
{ |
112 |
|
|
if (v && *((gpointer *) v)) |
113 |
|
|
g_type_class_unref (*((gpointer *) v)); |
114 |
|
|
} |
115 |
|
|
#define nm_auto_unref_gtypeclass nm_auto(_nm_auto_unref_gtypeclass) |
116 |
|
|
|
117 |
|
|
static inline void |
118 |
|
|
_nm_auto_free_gstring_impl (GString **str) |
119 |
|
|
{ |
120 |
|
|
if (*str) |
121 |
|
|
g_string_free (*str, TRUE); |
122 |
|
|
} |
123 |
|
|
#define nm_auto_free_gstring nm_auto(_nm_auto_free_gstring_impl) |
124 |
|
|
|
125 |
|
|
static inline void |
126 |
|
|
_nm_auto_close_impl (int *pfd) |
127 |
|
|
{ |
128 |
|
|
if (*pfd >= 0) { |
129 |
|
|
int errsv = errno; |
130 |
|
|
|
131 |
|
|
(void) nm_close (*pfd); |
132 |
|
|
errno = errsv; |
133 |
|
|
} |
134 |
|
|
} |
135 |
|
|
#define nm_auto_close nm_auto(_nm_auto_close_impl) |
136 |
|
|
|
137 |
|
|
static inline void |
138 |
|
|
_nm_auto_fclose_impl (FILE **pfd) |
139 |
|
|
{ |
140 |
|
|
if (*pfd) { |
141 |
|
|
int errsv = errno; |
142 |
|
|
|
143 |
|
|
(void) fclose (*pfd); |
144 |
|
|
errno = errsv; |
145 |
|
|
} |
146 |
|
|
} |
147 |
|
|
#define nm_auto_fclose nm_auto(_nm_auto_fclose_impl) |
148 |
|
|
|
149 |
|
|
static inline void |
150 |
|
|
_nm_auto_protect_errno (int *p_saved_errno) |
151 |
|
|
{ |
152 |
|
|
errno = *p_saved_errno; |
153 |
|
|
} |
154 |
|
|
#define NM_AUTO_PROTECT_ERRNO(errsv_saved) nm_auto(_nm_auto_protect_errno) _nm_unused const int errsv_saved = (errno) |
155 |
|
|
|
156 |
|
|
/*****************************************************************************/ |
157 |
|
|
|
158 |
|
|
/* http://stackoverflow.com/a/11172679 */ |
159 |
|
|
#define _NM_UTILS_MACRO_FIRST(...) __NM_UTILS_MACRO_FIRST_HELPER(__VA_ARGS__, throwaway) |
160 |
|
|
#define __NM_UTILS_MACRO_FIRST_HELPER(first, ...) first |
161 |
|
|
|
162 |
|
|
#define _NM_UTILS_MACRO_REST(...) __NM_UTILS_MACRO_REST_HELPER(__NM_UTILS_MACRO_REST_NUM(__VA_ARGS__), __VA_ARGS__) |
163 |
|
|
#define __NM_UTILS_MACRO_REST_HELPER(qty, ...) __NM_UTILS_MACRO_REST_HELPER2(qty, __VA_ARGS__) |
164 |
|
|
#define __NM_UTILS_MACRO_REST_HELPER2(qty, ...) __NM_UTILS_MACRO_REST_HELPER_##qty(__VA_ARGS__) |
165 |
|
|
#define __NM_UTILS_MACRO_REST_HELPER_ONE(first) |
166 |
|
|
#define __NM_UTILS_MACRO_REST_HELPER_TWOORMORE(first, ...) , __VA_ARGS__ |
167 |
|
|
#define __NM_UTILS_MACRO_REST_NUM(...) \ |
168 |
|
|
__NM_UTILS_MACRO_REST_SELECT_30TH(__VA_ARGS__, \ |
169 |
|
|
TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE,\ |
170 |
|
|
TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE,\ |
171 |
|
|
TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE,\ |
172 |
|
|
TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE,\ |
173 |
|
|
TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE,\ |
174 |
|
|
TWOORMORE, TWOORMORE, TWOORMORE, ONE, throwaway) |
175 |
|
|
#define __NM_UTILS_MACRO_REST_SELECT_30TH(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21, a22, a23, a24, a25, a26, a27, a28, a29, a30, ...) a30 |
176 |
|
|
|
177 |
|
|
/*****************************************************************************/ |
178 |
|
|
|
179 |
|
|
/* http://stackoverflow.com/a/2124385/354393 */ |
180 |
|
|
|
181 |
|
|
#define NM_NARG(...) \ |
182 |
|
|
_NM_NARG(__VA_ARGS__,_NM_NARG_RSEQ_N()) |
183 |
|
|
#define _NM_NARG(...) \ |
184 |
|
|
_NM_NARG_ARG_N(__VA_ARGS__) |
185 |
|
|
#define _NM_NARG_ARG_N( \ |
186 |
|
|
_1, _2, _3, _4, _5, _6, _7, _8, _9,_10, \ |
187 |
|
|
_11,_12,_13,_14,_15,_16,_17,_18,_19,_20, \ |
188 |
|
|
_21,_22,_23,_24,_25,_26,_27,_28,_29,_30, \ |
189 |
|
|
_31,_32,_33,_34,_35,_36,_37,_38,_39,_40, \ |
190 |
|
|
_41,_42,_43,_44,_45,_46,_47,_48,_49,_50, \ |
191 |
|
|
_51,_52,_53,_54,_55,_56,_57,_58,_59,_60, \ |
192 |
|
|
_61,_62,_63,N,...) N |
193 |
|
|
#define _NM_NARG_RSEQ_N() \ |
194 |
|
|
63,62,61,60, \ |
195 |
|
|
59,58,57,56,55,54,53,52,51,50, \ |
196 |
|
|
49,48,47,46,45,44,43,42,41,40, \ |
197 |
|
|
39,38,37,36,35,34,33,32,31,30, \ |
198 |
|
|
29,28,27,26,25,24,23,22,21,20, \ |
199 |
|
|
19,18,17,16,15,14,13,12,11,10, \ |
200 |
|
|
9,8,7,6,5,4,3,2,1,0 |
201 |
|
|
|
202 |
|
|
/*****************************************************************************/ |
203 |
|
|
|
204 |
|
|
#if defined (__GNUC__) |
205 |
|
|
#define _NM_PRAGMA_WARNING_DO(warning) G_STRINGIFY(GCC diagnostic ignored warning) |
206 |
|
|
#elif defined (__clang__) |
207 |
|
|
#define _NM_PRAGMA_WARNING_DO(warning) G_STRINGIFY(clang diagnostic ignored warning) |
208 |
|
|
#endif |
209 |
|
|
|
210 |
|
|
/* you can only suppress a specific warning that the compiler |
211 |
|
|
* understands. Otherwise you will get another compiler warning |
212 |
|
|
* about invalid pragma option. |
213 |
|
|
* It's not that bad however, because gcc and clang often have the |
214 |
|
|
* same name for the same warning. */ |
215 |
|
|
|
216 |
|
|
#if defined (__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) |
217 |
|
|
#define NM_PRAGMA_WARNING_DISABLE(warning) \ |
218 |
|
|
_Pragma("GCC diagnostic push") \ |
219 |
|
|
_Pragma(_NM_PRAGMA_WARNING_DO(warning)) |
220 |
|
|
#elif defined (__clang__) |
221 |
|
|
#define NM_PRAGMA_WARNING_DISABLE(warning) \ |
222 |
|
|
_Pragma("clang diagnostic push") \ |
223 |
|
|
_Pragma(_NM_PRAGMA_WARNING_DO("-Wunknown-warning-option")) \ |
224 |
|
|
_Pragma(_NM_PRAGMA_WARNING_DO(warning)) |
225 |
|
|
#else |
226 |
|
|
#define NM_PRAGMA_WARNING_DISABLE(warning) |
227 |
|
|
#endif |
228 |
|
|
|
229 |
|
|
#if defined (__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) |
230 |
|
|
#define NM_PRAGMA_WARNING_REENABLE \ |
231 |
|
|
_Pragma("GCC diagnostic pop") |
232 |
|
|
#elif defined (__clang__) |
233 |
|
|
#define NM_PRAGMA_WARNING_REENABLE \ |
234 |
|
|
_Pragma("clang diagnostic pop") |
235 |
|
|
#else |
236 |
|
|
#define NM_PRAGMA_WARNING_REENABLE |
237 |
|
|
#endif |
238 |
|
|
|
239 |
|
|
/*****************************************************************************/ |
240 |
|
|
|
241 |
|
|
/** |
242 |
|
|
* NM_G_ERROR_MSG: |
243 |
|
|
* @error: (allow-none): the #GError instance |
244 |
|
|
* |
245 |
|
|
* All functions must follow the convention that when they |
246 |
|
|
* return a failure, they must also set the GError to a valid |
247 |
|
|
* message. For external API however, we want to be extra |
248 |
|
|
* careful before accessing the error instance. Use NM_G_ERROR_MSG() |
249 |
|
|
* which is safe to use on NULL. |
250 |
|
|
* |
251 |
|
|
* Returns: the error message. |
252 |
|
|
**/ |
253 |
|
|
static inline const char * |
254 |
|
|
NM_G_ERROR_MSG (GError *error) |
255 |
|
|
{ |
256 |
|
|
return error ? (error->message ? : "(null)") : "(no-error)"; \ |
257 |
|
|
} |
258 |
|
|
|
259 |
|
|
/*****************************************************************************/ |
260 |
|
|
|
261 |
|
|
/* macro to return strlen() of a compile time string. */ |
262 |
|
|
#define NM_STRLEN(str) ( sizeof ("" str) - 1 ) |
263 |
|
|
|
264 |
|
|
/* returns the length of a NULL terminated array of pointers, |
265 |
|
|
* like g_strv_length() does. The difference is: |
266 |
|
|
* - it operats on arrays of pointers (of any kind, requiring no cast). |
267 |
|
|
* - it accepts NULL to return zero. */ |
268 |
|
|
#define NM_PTRARRAY_LEN(array) \ |
269 |
|
|
({ \ |
270 |
|
|
typeof (*(array)) *const _array = (array); \ |
271 |
|
|
gsize _n = 0; \ |
272 |
|
|
\ |
273 |
|
|
if (_array) { \ |
274 |
|
|
_nm_unused gconstpointer _type_check_is_pointer = _array[0]; \ |
275 |
|
|
\ |
276 |
|
|
while (_array[_n]) \ |
277 |
|
|
_n++; \ |
278 |
|
|
} \ |
279 |
|
|
_n; \ |
280 |
|
|
}) |
281 |
|
|
|
282 |
|
|
/* Note: @value is only evaluated when *out_val is present. |
283 |
|
|
* Thus, |
284 |
|
|
* NM_SET_OUT (out_str, g_strdup ("hallo")); |
285 |
|
|
* does the right thing. |
286 |
|
|
*/ |
287 |
|
|
#define NM_SET_OUT(out_val, value) \ |
288 |
|
|
G_STMT_START { \ |
289 |
|
|
typeof(*(out_val)) *_out_val = (out_val); \ |
290 |
|
|
\ |
291 |
|
|
if (_out_val) { \ |
292 |
|
|
*_out_val = (value); \ |
293 |
|
|
} \ |
294 |
|
|
} G_STMT_END |
295 |
|
|
|
296 |
|
|
/*****************************************************************************/ |
297 |
|
|
|
298 |
|
|
#ifndef _NM_CC_SUPPORT_AUTO_TYPE |
299 |
|
|
#if (defined (__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 9 ))) |
300 |
|
|
#define _NM_CC_SUPPORT_AUTO_TYPE 1 |
301 |
|
|
#else |
302 |
|
|
#define _NM_CC_SUPPORT_AUTO_TYPE 0 |
303 |
|
|
#endif |
304 |
|
|
#endif |
305 |
|
|
|
306 |
|
|
#ifndef _NM_CC_SUPPORT_GENERIC |
307 |
|
|
#if (defined (__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 9 ))) || (defined (__clang__)) |
308 |
|
|
#define _NM_CC_SUPPORT_GENERIC 1 |
309 |
|
|
#else |
310 |
|
|
#define _NM_CC_SUPPORT_GENERIC 0 |
311 |
|
|
#endif |
312 |
|
|
#endif |
313 |
|
|
|
314 |
|
|
#if _NM_CC_SUPPORT_AUTO_TYPE |
315 |
|
|
#define _nm_auto_type __auto_type |
316 |
|
|
#endif |
317 |
|
|
|
318 |
|
|
#if _NM_CC_SUPPORT_GENERIC |
319 |
|
|
#define _NM_CONSTCAST_FULL_1(type, obj_expr, obj) \ |
320 |
|
|
(_Generic ((obj_expr), \ |
321 |
|
|
const void *const: ((const type *) (obj)), \ |
322 |
|
|
const void * : ((const type *) (obj)), \ |
323 |
|
|
void *const: (( type *) (obj)), \ |
324 |
|
|
void * : (( type *) (obj)), \ |
325 |
|
|
const type *const: ((const type *) (obj)), \ |
326 |
|
|
const type * : ((const type *) (obj)), \ |
327 |
|
|
type *const: (( type *) (obj)), \ |
328 |
|
|
type * : (( type *) (obj)))) |
329 |
|
|
#define _NM_CONSTCAST_FULL_2(type, obj_expr, obj, alias_type2) \ |
330 |
|
|
(_Generic ((obj_expr), \ |
331 |
|
|
const void *const: ((const type *) (obj)), \ |
332 |
|
|
const void * : ((const type *) (obj)), \ |
333 |
|
|
void *const: (( type *) (obj)), \ |
334 |
|
|
void * : (( type *) (obj)), \ |
335 |
|
|
const alias_type2 *const: ((const type *) (obj)), \ |
336 |
|
|
const alias_type2 * : ((const type *) (obj)), \ |
337 |
|
|
alias_type2 *const: (( type *) (obj)), \ |
338 |
|
|
alias_type2 * : (( type *) (obj)), \ |
339 |
|
|
const type *const: ((const type *) (obj)), \ |
340 |
|
|
const type * : ((const type *) (obj)), \ |
341 |
|
|
type *const: (( type *) (obj)), \ |
342 |
|
|
type * : (( type *) (obj)))) |
343 |
|
|
#define _NM_CONSTCAST_FULL_3(type, obj_expr, obj, alias_type2, alias_type3) \ |
344 |
|
|
(_Generic ((obj_expr), \ |
345 |
|
|
const void *const: ((const type *) (obj)), \ |
346 |
|
|
const void * : ((const type *) (obj)), \ |
347 |
|
|
void *const: (( type *) (obj)), \ |
348 |
|
|
void * : (( type *) (obj)), \ |
349 |
|
|
const alias_type2 *const: ((const type *) (obj)), \ |
350 |
|
|
const alias_type2 * : ((const type *) (obj)), \ |
351 |
|
|
alias_type2 *const: (( type *) (obj)), \ |
352 |
|
|
alias_type2 * : (( type *) (obj)), \ |
353 |
|
|
const alias_type3 *const: ((const type *) (obj)), \ |
354 |
|
|
const alias_type3 * : ((const type *) (obj)), \ |
355 |
|
|
alias_type3 *const: (( type *) (obj)), \ |
356 |
|
|
alias_type3 * : (( type *) (obj)), \ |
357 |
|
|
const type *const: ((const type *) (obj)), \ |
358 |
|
|
const type * : ((const type *) (obj)), \ |
359 |
|
|
type *const: (( type *) (obj)), \ |
360 |
|
|
type * : (( type *) (obj)))) |
361 |
|
|
#define _NM_CONSTCAST_FULL_4(type, obj_expr, obj, alias_type2, alias_type3, alias_type4) \ |
362 |
|
|
(_Generic ((obj_expr), \ |
363 |
|
|
const void *const: ((const type *) (obj)), \ |
364 |
|
|
const void * : ((const type *) (obj)), \ |
365 |
|
|
void *const: (( type *) (obj)), \ |
366 |
|
|
void * : (( type *) (obj)), \ |
367 |
|
|
const alias_type2 *const: ((const type *) (obj)), \ |
368 |
|
|
const alias_type2 * : ((const type *) (obj)), \ |
369 |
|
|
alias_type2 *const: (( type *) (obj)), \ |
370 |
|
|
alias_type2 * : (( type *) (obj)), \ |
371 |
|
|
const alias_type3 *const: ((const type *) (obj)), \ |
372 |
|
|
const alias_type3 * : ((const type *) (obj)), \ |
373 |
|
|
alias_type3 *const: (( type *) (obj)), \ |
374 |
|
|
alias_type3 * : (( type *) (obj)), \ |
375 |
|
|
const alias_type4 *const: ((const type *) (obj)), \ |
376 |
|
|
const alias_type4 * : ((const type *) (obj)), \ |
377 |
|
|
alias_type4 *const: (( type *) (obj)), \ |
378 |
|
|
alias_type4 * : (( type *) (obj)), \ |
379 |
|
|
const type *const: ((const type *) (obj)), \ |
380 |
|
|
const type * : ((const type *) (obj)), \ |
381 |
|
|
type *const: (( type *) (obj)), \ |
382 |
|
|
type * : (( type *) (obj)))) |
383 |
|
|
#define _NM_CONSTCAST_FULL_x(type, obj_expr, obj, n, ...) (_NM_CONSTCAST_FULL_##n (type, obj_expr, obj, ##__VA_ARGS__)) |
384 |
|
|
#define _NM_CONSTCAST_FULL_y(type, obj_expr, obj, n, ...) (_NM_CONSTCAST_FULL_x (type, obj_expr, obj, n, ##__VA_ARGS__)) |
385 |
|
|
#define NM_CONSTCAST_FULL( type, obj_expr, obj, ...) (_NM_CONSTCAST_FULL_y (type, obj_expr, obj, NM_NARG (dummy, ##__VA_ARGS__), ##__VA_ARGS__)) |
386 |
|
|
#else |
387 |
|
|
#define NM_CONSTCAST_FULL( type, obj_expr, obj, ...) ((type *) (obj)) |
388 |
|
|
#endif |
389 |
|
|
|
390 |
|
|
#define NM_CONSTCAST(type, obj, ...) \ |
391 |
|
|
NM_CONSTCAST_FULL(type, (obj), (obj), ##__VA_ARGS__) |
392 |
|
|
|
393 |
|
|
#if _NM_CC_SUPPORT_GENERIC |
394 |
|
|
#define NM_UNCONST_PTR(type, arg) \ |
395 |
|
|
_Generic ((arg), \ |
396 |
|
|
const type *: ((type *) (arg)), \ |
397 |
|
|
type *: ((type *) (arg))) |
398 |
|
|
#else |
399 |
|
|
#define NM_UNCONST_PTR(type, arg) \ |
400 |
|
|
((type *) (arg)) |
401 |
|
|
#endif |
402 |
|
|
|
403 |
|
|
#if _NM_CC_SUPPORT_GENERIC |
404 |
|
|
#define NM_UNCONST_PPTR(type, arg) \ |
405 |
|
|
_Generic ((arg), \ |
406 |
|
|
const type * *: ((type **) (arg)), \ |
407 |
|
|
type * *: ((type **) (arg)), \ |
408 |
|
|
const type *const*: ((type **) (arg)), \ |
409 |
|
|
type *const*: ((type **) (arg))) |
410 |
|
|
#else |
411 |
|
|
#define NM_UNCONST_PPTR(type, arg) \ |
412 |
|
|
((type **) (arg)) |
413 |
|
|
#endif |
414 |
|
|
|
415 |
|
|
#define NM_GOBJECT_CAST(type, obj, is_check, ...) \ |
416 |
|
|
({ \ |
417 |
|
|
const void *_obj = (obj); \ |
418 |
|
|
\ |
419 |
|
|
nm_assert (_obj || (is_check (_obj))); \ |
420 |
|
|
NM_CONSTCAST_FULL (type, (obj), _obj, GObject, ##__VA_ARGS__); \ |
421 |
|
|
}) |
422 |
|
|
|
423 |
|
|
#define NM_GOBJECT_CAST_NON_NULL(type, obj, is_check, ...) \ |
424 |
|
|
({ \ |
425 |
|
|
const void *_obj = (obj); \ |
426 |
|
|
\ |
427 |
|
|
nm_assert (is_check (_obj)); \ |
428 |
|
|
NM_CONSTCAST_FULL (type, (obj), _obj, GObject, ##__VA_ARGS__); \ |
429 |
|
|
}) |
430 |
|
|
|
431 |
|
|
#if _NM_CC_SUPPORT_GENERIC |
432 |
|
|
/* returns @value, if the type of @value matches @type. |
433 |
|
|
* This requires support for C11 _Generic(). If no support is |
434 |
|
|
* present, this returns @value directly. |
435 |
|
|
* |
436 |
|
|
* It's useful to check the let the compiler ensure that @value is |
437 |
|
|
* of a certain type. */ |
438 |
|
|
#define _NM_ENSURE_TYPE(type, value) (_Generic ((value), type: (value))) |
439 |
|
|
#else |
440 |
|
|
#define _NM_ENSURE_TYPE(type, value) (value) |
441 |
|
|
#endif |
442 |
|
|
|
443 |
|
|
#if _NM_CC_SUPPORT_GENERIC |
444 |
|
|
#define NM_PROPAGATE_CONST(test_expr, ptr) \ |
445 |
|
|
(_Generic ((test_expr), \ |
446 |
|
|
const typeof (*(test_expr)) *: ((const typeof (*(ptr)) *) (ptr)), \ |
447 |
|
|
default: (_Generic ((test_expr), \ |
448 |
|
|
typeof (*(test_expr)) *: (ptr))))) |
449 |
|
|
#else |
450 |
|
|
#define NM_PROPAGATE_CONST(test_expr, ptr) (ptr) |
451 |
|
|
#endif |
452 |
|
|
|
453 |
|
|
/*****************************************************************************/ |
454 |
|
|
|
455 |
|
|
#define _NM_IN_SET_EVAL_1( op, _x, y) (_x == (y)) |
456 |
|
|
#define _NM_IN_SET_EVAL_2( op, _x, y, ...) (_x == (y)) op _NM_IN_SET_EVAL_1 (op, _x, __VA_ARGS__) |
457 |
|
|
#define _NM_IN_SET_EVAL_3( op, _x, y, ...) (_x == (y)) op _NM_IN_SET_EVAL_2 (op, _x, __VA_ARGS__) |
458 |
|
|
#define _NM_IN_SET_EVAL_4( op, _x, y, ...) (_x == (y)) op _NM_IN_SET_EVAL_3 (op, _x, __VA_ARGS__) |
459 |
|
|
#define _NM_IN_SET_EVAL_5( op, _x, y, ...) (_x == (y)) op _NM_IN_SET_EVAL_4 (op, _x, __VA_ARGS__) |
460 |
|
|
#define _NM_IN_SET_EVAL_6( op, _x, y, ...) (_x == (y)) op _NM_IN_SET_EVAL_5 (op, _x, __VA_ARGS__) |
461 |
|
|
#define _NM_IN_SET_EVAL_7( op, _x, y, ...) (_x == (y)) op _NM_IN_SET_EVAL_6 (op, _x, __VA_ARGS__) |
462 |
|
|
#define _NM_IN_SET_EVAL_8( op, _x, y, ...) (_x == (y)) op _NM_IN_SET_EVAL_7 (op, _x, __VA_ARGS__) |
463 |
|
|
#define _NM_IN_SET_EVAL_9( op, _x, y, ...) (_x == (y)) op _NM_IN_SET_EVAL_8 (op, _x, __VA_ARGS__) |
464 |
|
|
#define _NM_IN_SET_EVAL_10(op, _x, y, ...) (_x == (y)) op _NM_IN_SET_EVAL_9 (op, _x, __VA_ARGS__) |
465 |
|
|
#define _NM_IN_SET_EVAL_11(op, _x, y, ...) (_x == (y)) op _NM_IN_SET_EVAL_10 (op, _x, __VA_ARGS__) |
466 |
|
|
#define _NM_IN_SET_EVAL_12(op, _x, y, ...) (_x == (y)) op _NM_IN_SET_EVAL_11 (op, _x, __VA_ARGS__) |
467 |
|
|
#define _NM_IN_SET_EVAL_13(op, _x, y, ...) (_x == (y)) op _NM_IN_SET_EVAL_12 (op, _x, __VA_ARGS__) |
468 |
|
|
#define _NM_IN_SET_EVAL_14(op, _x, y, ...) (_x == (y)) op _NM_IN_SET_EVAL_13 (op, _x, __VA_ARGS__) |
469 |
|
|
#define _NM_IN_SET_EVAL_15(op, _x, y, ...) (_x == (y)) op _NM_IN_SET_EVAL_14 (op, _x, __VA_ARGS__) |
470 |
|
|
#define _NM_IN_SET_EVAL_16(op, _x, y, ...) (_x == (y)) op _NM_IN_SET_EVAL_15 (op, _x, __VA_ARGS__) |
471 |
|
|
|
472 |
|
|
#define _NM_IN_SET_EVAL_N2(op, _x, n, ...) (_NM_IN_SET_EVAL_##n(op, _x, __VA_ARGS__)) |
473 |
|
|
#define _NM_IN_SET_EVAL_N(op, type, x, n, ...) \ |
474 |
|
|
({ \ |
475 |
|
|
type _x = (x); \ |
476 |
|
|
\ |
477 |
|
|
/* trigger a -Wenum-compare warning */ \ |
478 |
|
|
nm_assert (TRUE || _x == (x)); \ |
479 |
|
|
\ |
480 |
|
|
!!_NM_IN_SET_EVAL_N2(op, _x, n, __VA_ARGS__); \ |
481 |
|
|
}) |
482 |
|
|
|
483 |
|
|
#define _NM_IN_SET(op, type, x, ...) _NM_IN_SET_EVAL_N(op, type, x, NM_NARG (__VA_ARGS__), __VA_ARGS__) |
484 |
|
|
|
485 |
|
|
/* Beware that this does short-circuit evaluation (use "||" instead of "|") |
486 |
|
|
* which has a possibly unexpected non-function-like behavior. |
487 |
|
|
* Use NM_IN_SET_SE if you need all arguments to be evaluted. */ |
488 |
|
|
#define NM_IN_SET(x, ...) _NM_IN_SET(||, typeof (x), x, __VA_ARGS__) |
489 |
|
|
|
490 |
|
|
/* "SE" stands for "side-effect". Contrary to NM_IN_SET(), this does not do |
491 |
|
|
* short-circuit evaluation, which can make a difference if the arguments have |
492 |
|
|
* side-effects. */ |
493 |
|
|
#define NM_IN_SET_SE(x, ...) _NM_IN_SET(|, typeof (x), x, __VA_ARGS__) |
494 |
|
|
|
495 |
|
|
/* the *_TYPED forms allow to explicitly select the type of "x". This is useful |
496 |
|
|
* if "x" doesn't support typeof (bitfields) or you want to gracefully convert |
497 |
|
|
* a type using automatic type conversion rules (but not forcing the conversion |
498 |
|
|
* with a cast). */ |
499 |
|
|
#define NM_IN_SET_TYPED(type, x, ...) _NM_IN_SET(||, type, x, __VA_ARGS__) |
500 |
|
|
#define NM_IN_SET_SE_TYPED(type, x, ...) _NM_IN_SET(|, type, x, __VA_ARGS__) |
501 |
|
|
|
502 |
|
|
/*****************************************************************************/ |
503 |
|
|
|
504 |
|
|
static inline gboolean |
505 |
|
|
_NM_IN_STRSET_streq (const char *x, const char *s) |
506 |
|
|
{ |
507 |
|
|
return s && strcmp (x, s) == 0; |
508 |
|
|
} |
509 |
|
|
|
510 |
|
|
#define _NM_IN_STRSET_EVAL_1( op, _x, y) _NM_IN_STRSET_streq (_x, y) |
511 |
|
|
#define _NM_IN_STRSET_EVAL_2( op, _x, y, ...) _NM_IN_STRSET_streq (_x, y) op _NM_IN_STRSET_EVAL_1 (op, _x, __VA_ARGS__) |
512 |
|
|
#define _NM_IN_STRSET_EVAL_3( op, _x, y, ...) _NM_IN_STRSET_streq (_x, y) op _NM_IN_STRSET_EVAL_2 (op, _x, __VA_ARGS__) |
513 |
|
|
#define _NM_IN_STRSET_EVAL_4( op, _x, y, ...) _NM_IN_STRSET_streq (_x, y) op _NM_IN_STRSET_EVAL_3 (op, _x, __VA_ARGS__) |
514 |
|
|
#define _NM_IN_STRSET_EVAL_5( op, _x, y, ...) _NM_IN_STRSET_streq (_x, y) op _NM_IN_STRSET_EVAL_4 (op, _x, __VA_ARGS__) |
515 |
|
|
#define _NM_IN_STRSET_EVAL_6( op, _x, y, ...) _NM_IN_STRSET_streq (_x, y) op _NM_IN_STRSET_EVAL_5 (op, _x, __VA_ARGS__) |
516 |
|
|
#define _NM_IN_STRSET_EVAL_7( op, _x, y, ...) _NM_IN_STRSET_streq (_x, y) op _NM_IN_STRSET_EVAL_6 (op, _x, __VA_ARGS__) |
517 |
|
|
#define _NM_IN_STRSET_EVAL_8( op, _x, y, ...) _NM_IN_STRSET_streq (_x, y) op _NM_IN_STRSET_EVAL_7 (op, _x, __VA_ARGS__) |
518 |
|
|
#define _NM_IN_STRSET_EVAL_9( op, _x, y, ...) _NM_IN_STRSET_streq (_x, y) op _NM_IN_STRSET_EVAL_8 (op, _x, __VA_ARGS__) |
519 |
|
|
#define _NM_IN_STRSET_EVAL_10(op, _x, y, ...) _NM_IN_STRSET_streq (_x, y) op _NM_IN_STRSET_EVAL_9 (op, _x, __VA_ARGS__) |
520 |
|
|
#define _NM_IN_STRSET_EVAL_11(op, _x, y, ...) _NM_IN_STRSET_streq (_x, y) op _NM_IN_STRSET_EVAL_10 (op, _x, __VA_ARGS__) |
521 |
|
|
#define _NM_IN_STRSET_EVAL_12(op, _x, y, ...) _NM_IN_STRSET_streq (_x, y) op _NM_IN_STRSET_EVAL_11 (op, _x, __VA_ARGS__) |
522 |
|
|
#define _NM_IN_STRSET_EVAL_13(op, _x, y, ...) _NM_IN_STRSET_streq (_x, y) op _NM_IN_STRSET_EVAL_12 (op, _x, __VA_ARGS__) |
523 |
|
|
#define _NM_IN_STRSET_EVAL_14(op, _x, y, ...) _NM_IN_STRSET_streq (_x, y) op _NM_IN_STRSET_EVAL_13 (op, _x, __VA_ARGS__) |
524 |
|
|
#define _NM_IN_STRSET_EVAL_15(op, _x, y, ...) _NM_IN_STRSET_streq (_x, y) op _NM_IN_STRSET_EVAL_14 (op, _x, __VA_ARGS__) |
525 |
|
|
#define _NM_IN_STRSET_EVAL_16(op, _x, y, ...) _NM_IN_STRSET_streq (_x, y) op _NM_IN_STRSET_EVAL_15 (op, _x, __VA_ARGS__) |
526 |
|
|
|
527 |
|
|
#define _NM_IN_STRSET_EVAL_N2(op, _x, n, ...) (_NM_IN_STRSET_EVAL_##n(op, _x, __VA_ARGS__)) |
528 |
|
|
#define _NM_IN_STRSET_EVAL_N(op, x, n, ...) \ |
529 |
|
|
({ \ |
530 |
|
|
const char *_x = (x); \ |
531 |
|
|
( ((_x == NULL) && _NM_IN_SET_EVAL_N2 (op, ((const char *) NULL), n, __VA_ARGS__)) \ |
532 |
|
|
|| ((_x != NULL) && _NM_IN_STRSET_EVAL_N2 (op, _x, n, __VA_ARGS__)) \ |
533 |
|
|
); \ |
534 |
|
|
}) |
535 |
|
|
|
536 |
|
|
/* Beware that this does short-circuit evaluation (use "||" instead of "|") |
537 |
|
|
* which has a possibly unexpected non-function-like behavior. |
538 |
|
|
* Use NM_IN_STRSET_SE if you need all arguments to be evaluted. */ |
539 |
|
|
#define NM_IN_STRSET(x, ...) _NM_IN_STRSET_EVAL_N(||, x, NM_NARG (__VA_ARGS__), __VA_ARGS__) |
540 |
|
|
|
541 |
|
|
/* "SE" stands for "side-effect". Contrary to NM_IN_STRSET(), this does not do |
542 |
|
|
* short-circuit evaluation, which can make a difference if the arguments have |
543 |
|
|
* side-effects. */ |
544 |
|
|
#define NM_IN_STRSET_SE(x, ...) _NM_IN_STRSET_EVAL_N(|, x, NM_NARG (__VA_ARGS__), __VA_ARGS__) |
545 |
|
|
|
546 |
|
|
#define NM_STRCHAR_ALL(str, ch_iter, predicate) \ |
547 |
|
|
({ \ |
548 |
|
|
gboolean _val = TRUE; \ |
549 |
|
|
const char *_str = (str); \ |
550 |
|
|
\ |
551 |
|
|
if (_str) { \ |
552 |
|
|
for (;;) { \ |
553 |
|
|
const char ch_iter = _str[0]; \ |
554 |
|
|
\ |
555 |
|
|
if (ch_iter != '\0') { \ |
556 |
|
|
if (predicate) {\ |
557 |
|
|
_str++; \ |
558 |
|
|
continue; \ |
559 |
|
|
} \ |
560 |
|
|
_val = FALSE; \ |
561 |
|
|
} \ |
562 |
|
|
break; \ |
563 |
|
|
} \ |
564 |
|
|
} \ |
565 |
|
|
_val; \ |
566 |
|
|
}) |
567 |
|
|
|
568 |
|
|
#define NM_STRCHAR_ANY(str, ch_iter, predicate) \ |
569 |
|
|
({ \ |
570 |
|
|
gboolean _val = FALSE; \ |
571 |
|
|
const char *_str = (str); \ |
572 |
|
|
\ |
573 |
|
|
if (_str) { \ |
574 |
|
|
for (;;) { \ |
575 |
|
|
const char ch_iter = _str[0]; \ |
576 |
|
|
\ |
577 |
|
|
if (ch_iter != '\0') { \ |
578 |
|
|
if (predicate) { \ |
579 |
|
|
; \ |
580 |
|
|
} else { \ |
581 |
|
|
_str++; \ |
582 |
|
|
continue; \ |
583 |
|
|
} \ |
584 |
|
|
_val = TRUE; \ |
585 |
|
|
} \ |
586 |
|
|
break; \ |
587 |
|
|
} \ |
588 |
|
|
} \ |
589 |
|
|
_val; \ |
590 |
|
|
}) |
591 |
|
|
|
592 |
|
|
/*****************************************************************************/ |
593 |
|
|
|
594 |
|
|
/* NM_CACHED_QUARK() returns the GQuark for @string, but caches |
595 |
|
|
* it in a static variable to speed up future lookups. |
596 |
|
|
* |
597 |
|
|
* @string must be a string literal. |
598 |
|
|
*/ |
599 |
|
|
#define NM_CACHED_QUARK(string) \ |
600 |
|
|
({ \ |
601 |
|
|
static GQuark _nm_cached_quark = 0; \ |
602 |
|
|
\ |
603 |
|
|
(G_LIKELY (_nm_cached_quark != 0) \ |
604 |
|
|
? _nm_cached_quark \ |
605 |
|
|
: (_nm_cached_quark = g_quark_from_static_string (""string""))); \ |
606 |
|
|
}) |
607 |
|
|
|
608 |
|
|
/* NM_CACHED_QUARK_FCN() is essentially the same as G_DEFINE_QUARK |
609 |
|
|
* with two differences: |
610 |
|
|
* - @string must be a quoted string-literal |
611 |
|
|
* - @fcn must be the full function name, while G_DEFINE_QUARK() appends |
612 |
|
|
* "_quark" to the function name. |
613 |
|
|
* Both properties of G_DEFINE_QUARK() are non favorable, because you can no |
614 |
|
|
* longer grep for string/fcn -- unless you are aware that you are searching |
615 |
|
|
* for G_DEFINE_QUARK() and omit quotes / append _quark(). With NM_CACHED_QUARK_FCN(), |
616 |
|
|
* ctags/cscope can locate the use of @fcn (though it doesn't recognize that |
617 |
|
|
* NM_CACHED_QUARK_FCN() defines it). |
618 |
|
|
*/ |
619 |
|
|
#define NM_CACHED_QUARK_FCN(string, fcn) \ |
620 |
|
|
GQuark \ |
621 |
|
|
fcn (void) \ |
622 |
|
|
{ \ |
623 |
|
|
return NM_CACHED_QUARK (string); \ |
624 |
|
|
} |
625 |
|
|
|
626 |
|
|
/*****************************************************************************/ |
627 |
|
|
|
628 |
|
|
#define nm_streq(s1, s2) (strcmp (s1, s2) == 0) |
629 |
|
|
#define nm_streq0(s1, s2) (g_strcmp0 (s1, s2) == 0) |
630 |
|
|
|
631 |
|
|
/*****************************************************************************/ |
632 |
|
|
|
633 |
|
|
static inline GString * |
634 |
|
|
nm_gstring_prepare (GString **l) |
635 |
|
|
{ |
636 |
|
|
if (*l) |
637 |
|
|
g_string_set_size (*l, 0); |
638 |
|
|
else |
639 |
|
|
*l = g_string_sized_new (30); |
640 |
|
|
return *l; |
641 |
|
|
} |
642 |
|
|
|
643 |
|
|
static inline const char * |
644 |
|
|
nm_str_not_empty (const char *str) |
645 |
|
|
{ |
646 |
|
|
return str && str[0] ? str : NULL; |
647 |
|
|
} |
648 |
|
|
|
649 |
|
|
static inline char * |
650 |
|
|
nm_strdup_not_empty (const char *str) |
651 |
|
|
{ |
652 |
|
|
return str && str[0] ? g_strdup (str) : NULL; |
653 |
|
|
} |
654 |
|
|
|
655 |
|
|
static inline char * |
656 |
|
|
nm_str_realloc (char *str) |
657 |
|
|
{ |
658 |
|
|
gs_free char *s = str; |
659 |
|
|
|
660 |
|
|
/* Returns a new clone of @str and frees @str. The point is that @str |
661 |
|
|
* possibly points to a larger chunck of memory. We want to freshly allocate |
662 |
|
|
* a buffer. |
663 |
|
|
* |
664 |
|
|
* We could use realloc(), but that might not do anything or leave |
665 |
|
|
* @str in its memory pool for chunks of a different size (bad for |
666 |
|
|
* fragmentation). |
667 |
|
|
* |
668 |
|
|
* This is only useful when we want to keep the buffer around for a long |
669 |
|
|
* time and want to re-allocate a more optimal buffer. */ |
670 |
|
|
|
671 |
|
|
return g_strdup (s); |
672 |
|
|
} |
673 |
|
|
|
674 |
|
|
/*****************************************************************************/ |
675 |
|
|
|
676 |
|
|
#define NM_PRINT_FMT_QUOTED(cond, prefix, str, suffix, str_else) \ |
677 |
|
|
(cond) ? (prefix) : "", \ |
678 |
|
|
(cond) ? (str) : (str_else), \ |
679 |
|
|
(cond) ? (suffix) : "" |
680 |
|
|
#define NM_PRINT_FMT_QUOTE_STRING(arg) NM_PRINT_FMT_QUOTED((arg), "\"", (arg), "\"", "(null)") |
681 |
|
|
|
682 |
|
|
/*****************************************************************************/ |
683 |
|
|
|
684 |
|
|
/* glib/C provides the following kind of assertions: |
685 |
|
|
* - assert() -- disable with NDEBUG |
686 |
|
|
* - g_return_if_fail() -- disable with G_DISABLE_CHECKS |
687 |
|
|
* - g_assert() -- disable with G_DISABLE_ASSERT |
688 |
|
|
* but they are all enabled by default and usually even production builds have |
689 |
|
|
* these kind of assertions enabled. It also means, that disabling assertions |
690 |
|
|
* is an untested configuration, and might have bugs. |
691 |
|
|
* |
692 |
|
|
* Add our own assertion macro nm_assert(), which is disabled by default and must |
693 |
|
|
* be explicitly enabled. They are useful for more expensive checks or checks that |
694 |
|
|
* depend less on runtime conditions (that is, are generally expected to be true). */ |
695 |
|
|
|
696 |
|
|
#ifndef NM_MORE_ASSERTS |
697 |
|
|
#define NM_MORE_ASSERTS 0 |
698 |
|
|
#endif |
699 |
|
|
|
700 |
|
|
#if NM_MORE_ASSERTS |
701 |
|
|
#define nm_assert(cond) G_STMT_START { g_assert (cond); } G_STMT_END |
702 |
|
|
#define nm_assert_se(cond) G_STMT_START { if (G_LIKELY (cond)) { ; } else { g_assert (FALSE && (cond)); } } G_STMT_END |
703 |
|
|
#define nm_assert_not_reached() G_STMT_START { g_assert_not_reached (); } G_STMT_END |
704 |
|
|
#else |
705 |
|
|
#define nm_assert(cond) G_STMT_START { if (FALSE) { if (cond) { } } } G_STMT_END |
706 |
|
|
#define nm_assert_se(cond) G_STMT_START { if (G_LIKELY (cond)) { ; } } G_STMT_END |
707 |
|
|
#define nm_assert_not_reached() G_STMT_START { ; } G_STMT_END |
708 |
|
|
#endif |
709 |
|
|
|
710 |
|
|
/*****************************************************************************/ |
711 |
|
|
|
712 |
|
|
#define NM_GOBJECT_PROPERTIES_DEFINE_BASE(...) \ |
713 |
|
|
typedef enum { \ |
714 |
|
|
_PROPERTY_ENUMS_0, \ |
715 |
|
|
__VA_ARGS__ \ |
716 |
|
|
_PROPERTY_ENUMS_LAST, \ |
717 |
|
|
} _PropertyEnums; \ |
718 |
|
|
static GParamSpec *obj_properties[_PROPERTY_ENUMS_LAST] = { NULL, } |
719 |
|
|
|
720 |
|
|
#define NM_GOBJECT_PROPERTIES_DEFINE(obj_type, ...) \ |
721 |
|
|
NM_GOBJECT_PROPERTIES_DEFINE_BASE (__VA_ARGS__); \ |
722 |
|
|
static inline void \ |
723 |
|
|
_notify (obj_type *obj, _PropertyEnums prop) \ |
724 |
|
|
{ \ |
725 |
|
|
nm_assert (G_IS_OBJECT (obj)); \ |
726 |
|
|
nm_assert ((gsize) prop < G_N_ELEMENTS (obj_properties)); \ |
727 |
|
|
g_object_notify_by_pspec ((GObject *) obj, obj_properties[prop]); \ |
728 |
|
|
} |
729 |
|
|
|
730 |
|
|
/*****************************************************************************/ |
731 |
|
|
|
732 |
|
|
#define _NM_GET_PRIVATE(self, type, is_check, ...) (&(NM_GOBJECT_CAST_NON_NULL (type, (self), is_check, ##__VA_ARGS__)->_priv)) |
733 |
|
|
#if _NM_CC_SUPPORT_AUTO_TYPE |
734 |
|
|
#define _NM_GET_PRIVATE_PTR(self, type, is_check, ...) \ |
735 |
|
|
({ \ |
736 |
|
|
_nm_auto_type _self = NM_GOBJECT_CAST_NON_NULL (type, (self), is_check, ##__VA_ARGS__); \ |
737 |
|
|
\ |
738 |
|
|
NM_PROPAGATE_CONST (_self, _self->_priv); \ |
739 |
|
|
}) |
740 |
|
|
#else |
741 |
|
|
#define _NM_GET_PRIVATE_PTR(self, type, is_check, ...) (NM_GOBJECT_CAST_NON_NULL (type, (self), is_check, ##__VA_ARGS__)->_priv) |
742 |
|
|
#endif |
743 |
|
|
|
744 |
|
|
/*****************************************************************************/ |
745 |
|
|
|
746 |
|
|
static inline gpointer |
747 |
|
|
nm_g_object_ref (gpointer obj) |
748 |
|
|
{ |
749 |
|
|
/* g_object_ref() doesn't accept NULL. */ |
750 |
|
|
if (obj) |
751 |
|
|
g_object_ref (obj); |
752 |
|
|
return obj; |
753 |
|
|
} |
754 |
|
|
#define nm_g_object_ref(obj) ((typeof (obj)) nm_g_object_ref (obj)) |
755 |
|
|
|
756 |
|
|
static inline void |
757 |
|
|
nm_g_object_unref (gpointer obj) |
758 |
|
|
{ |
759 |
|
|
/* g_object_unref() doesn't accept NULL. Usually, we workaround that |
760 |
|
|
* by using g_clear_object(), but sometimes that is not convenient |
761 |
|
|
* (for example as destroy function for a hash table that can contain |
762 |
|
|
* NULL values). */ |
763 |
|
|
if (obj) |
764 |
|
|
g_object_unref (obj); |
765 |
|
|
} |
766 |
|
|
|
767 |
|
|
/* Assigns GObject @obj to destination @pdst, and takes an additional ref. |
768 |
|
|
* The previous value of @pdst is unrefed. |
769 |
|
|
* |
770 |
|
|
* It makes sure to first increase the ref-count of @obj, and handles %NULL |
771 |
|
|
* @obj correctly. |
772 |
|
|
* */ |
773 |
|
|
#define nm_g_object_ref_set(pp, obj) \ |
774 |
|
|
({ \ |
775 |
|
|
typeof (*(pp)) *const _pp = (pp); \ |
776 |
|
|
typeof (**_pp) *const _obj = (obj); \ |
777 |
|
|
typeof (**_pp) *_p; \ |
778 |
|
|
gboolean _changed = FALSE; \ |
779 |
|
|
\ |
780 |
|
|
if ( _pp \ |
781 |
|
|
&& ((_p = *_pp) != _obj)) { \ |
782 |
|
|
if (_obj) { \ |
783 |
|
|
nm_assert (G_IS_OBJECT (_obj)); \ |
784 |
|
|
g_object_ref (_obj); \ |
785 |
|
|
} \ |
786 |
|
|
if (_p) { \ |
787 |
|
|
nm_assert (G_IS_OBJECT (_p)); \ |
788 |
|
|
*_pp = NULL; \ |
789 |
|
|
g_object_unref (_p); \ |
790 |
|
|
} \ |
791 |
|
|
*_pp = _obj; \ |
792 |
|
|
_changed = TRUE; \ |
793 |
|
|
} \ |
794 |
|
|
_changed; \ |
795 |
|
|
}) |
796 |
|
|
|
797 |
|
|
#define nm_clear_pointer(pp, destroy) \ |
798 |
|
|
({ \ |
799 |
|
|
typeof (*(pp)) *_pp = (pp); \ |
800 |
|
|
typeof (*_pp) _p; \ |
801 |
|
|
gboolean _changed = FALSE; \ |
802 |
|
|
\ |
803 |
|
|
if ( _pp \ |
804 |
|
|
&& (_p = *_pp)) { \ |
805 |
|
|
_nm_unused gconstpointer _p_check_is_pointer = _p; \ |
806 |
|
|
\ |
807 |
|
|
*_pp = NULL; \ |
808 |
|
|
/* g_clear_pointer() assigns @destroy first to a local variable, so that |
809 |
|
|
* you can call "g_clear_pointer (pp, (GDestroyNotify) destroy);" without |
810 |
|
|
* gcc emitting a warning. We don't do that, hence, you cannot cast |
811 |
|
|
* "destroy" first. |
812 |
|
|
* |
813 |
|
|
* On the upside: you are not supposed to cast fcn, because the pointer |
814 |
|
|
* types are preserved. If you really need a cast, you should cast @pp. |
815 |
|
|
* But that is hardly ever necessary. */ \ |
816 |
|
|
(destroy) (_p); \ |
817 |
|
|
\ |
818 |
|
|
_changed = TRUE; \ |
819 |
|
|
} \ |
820 |
|
|
_changed; \ |
821 |
|
|
}) |
822 |
|
|
|
823 |
|
|
/* basically, replaces |
824 |
|
|
* g_clear_pointer (&location, g_free) |
825 |
|
|
* with |
826 |
|
|
* nm_clear_g_free (&location) |
827 |
|
|
* |
828 |
|
|
* Another advantage is that by using a macro and typeof(), it is more |
829 |
|
|
* typesafe and gives you for example a compiler warning when pp is a const |
830 |
|
|
* pointer or points to a const-pointer. |
831 |
|
|
*/ |
832 |
|
|
#define nm_clear_g_free(pp) \ |
833 |
|
|
nm_clear_pointer (pp, g_free) |
834 |
|
|
|
835 |
|
|
#define nm_clear_g_object(pp) \ |
836 |
|
|
nm_clear_pointer (pp, g_object_unref) |
837 |
|
|
|
838 |
|
|
static inline gboolean |
839 |
|
|
nm_clear_g_source (guint *id) |
840 |
|
|
{ |
841 |
|
|
guint v; |
842 |
|
|
|
843 |
|
|
if ( id |
844 |
|
|
&& (v = *id)) { |
845 |
|
|
*id = 0; |
846 |
|
|
g_source_remove (v); |
847 |
|
|
return TRUE; |
848 |
|
|
} |
849 |
|
|
return FALSE; |
850 |
|
|
} |
851 |
|
|
|
852 |
|
|
static inline gboolean |
853 |
|
|
nm_clear_g_signal_handler (gpointer self, gulong *id) |
854 |
|
|
{ |
855 |
|
|
gulong v; |
856 |
|
|
|
857 |
|
|
if ( id |
858 |
|
|
&& (v = *id)) { |
859 |
|
|
*id = 0; |
860 |
|
|
g_signal_handler_disconnect (self, v); |
861 |
|
|
return TRUE; |
862 |
|
|
} |
863 |
|
|
return FALSE; |
864 |
|
|
} |
865 |
|
|
|
866 |
|
|
static inline gboolean |
867 |
|
|
nm_clear_g_variant (GVariant **variant) |
868 |
|
|
{ |
869 |
|
|
GVariant *v; |
870 |
|
|
|
871 |
|
|
if ( variant |
872 |
|
|
&& (v = *variant)) { |
873 |
|
|
*variant = NULL; |
874 |
|
|
g_variant_unref (v); |
875 |
|
|
return TRUE; |
876 |
|
|
} |
877 |
|
|
return FALSE; |
878 |
|
|
} |
879 |
|
|
|
880 |
|
|
static inline gboolean |
881 |
|
|
nm_clear_g_cancellable (GCancellable **cancellable) |
882 |
|
|
{ |
883 |
|
|
GCancellable *v; |
884 |
|
|
|
885 |
|
|
if ( cancellable |
886 |
|
|
&& (v = *cancellable)) { |
887 |
|
|
*cancellable = NULL; |
888 |
|
|
g_cancellable_cancel (v); |
889 |
|
|
g_object_unref (v); |
890 |
|
|
return TRUE; |
891 |
|
|
} |
892 |
|
|
return FALSE; |
893 |
|
|
} |
894 |
|
|
|
895 |
|
|
/*****************************************************************************/ |
896 |
|
|
|
897 |
|
|
/* Determine whether @x is a power of two (@x being an integer type). |
898 |
|
|
* Basically, this returns TRUE, if @x has exactly one bit set. |
899 |
|
|
* For negative values and zero, this always returns FALSE. */ |
900 |
|
|
#define nm_utils_is_power_of_two(x) ({ \ |
901 |
|
|
typeof(x) __x = (x); \ |
902 |
|
|
\ |
903 |
|
|
( (__x > ((typeof(__x)) 0)) \ |
904 |
|
|
&& ((__x & (__x - (((typeof(__x)) 1)))) == ((typeof(__x)) 0))); \ |
905 |
|
|
}) |
906 |
|
|
|
907 |
|
|
/*****************************************************************************/ |
908 |
|
|
|
909 |
|
|
#define NM_UTILS_LOOKUP_DEFAULT(v) return (v) |
910 |
|
|
#define NM_UTILS_LOOKUP_DEFAULT_WARN(v) g_return_val_if_reached (v) |
911 |
|
|
#define NM_UTILS_LOOKUP_DEFAULT_NM_ASSERT(v) { nm_assert_not_reached (); return (v); } |
912 |
|
|
#define NM_UTILS_LOOKUP_ITEM(v, n) (void) 0; case v: return (n); (void) 0 |
913 |
|
|
#define NM_UTILS_LOOKUP_STR_ITEM(v, n) NM_UTILS_LOOKUP_ITEM(v, ""n"") |
914 |
|
|
#define NM_UTILS_LOOKUP_ITEM_IGNORE(v) (void) 0; case v: break; (void) 0 |
915 |
|
|
#define NM_UTILS_LOOKUP_ITEM_IGNORE_OTHER() (void) 0; default: break; (void) 0 |
916 |
|
|
|
917 |
|
|
#define _NM_UTILS_LOOKUP_DEFINE(scope, fcn_name, lookup_type, result_type, unknown_val, ...) \ |
918 |
|
|
scope result_type \ |
919 |
|
|
fcn_name (lookup_type val) \ |
920 |
|
|
{ \ |
921 |
|
|
switch (val) { \ |
922 |
|
|
(void) 0, \ |
923 |
|
|
__VA_ARGS__ \ |
924 |
|
|
(void) 0; \ |
925 |
|
|
}; \ |
926 |
|
|
{ unknown_val; } \ |
927 |
|
|
} |
928 |
|
|
|
929 |
|
|
#define NM_UTILS_LOOKUP_STR_DEFINE(fcn_name, lookup_type, unknown_val, ...) \ |
930 |
|
|
_NM_UTILS_LOOKUP_DEFINE (, fcn_name, lookup_type, const char *, unknown_val, __VA_ARGS__) |
931 |
|
|
#define NM_UTILS_LOOKUP_STR_DEFINE_STATIC(fcn_name, lookup_type, unknown_val, ...) \ |
932 |
|
|
_NM_UTILS_LOOKUP_DEFINE (static, fcn_name, lookup_type, const char *, unknown_val, __VA_ARGS__) |
933 |
|
|
|
934 |
|
|
/* Call the string-lookup-table function @fcn_name. If the function returns |
935 |
|
|
* %NULL, the numeric index is converted to string using a alloca() buffer. |
936 |
|
|
* Beware: this macro uses alloca(). */ |
937 |
|
|
#define NM_UTILS_LOOKUP_STR(fcn_name, idx) \ |
938 |
|
|
({ \ |
939 |
|
|
typeof (idx) _idx = (idx); \ |
940 |
|
|
const char *_s; \ |
941 |
|
|
\ |
942 |
|
|
_s = fcn_name (_idx); \ |
943 |
|
|
if (!_s) { \ |
944 |
|
|
_s = g_alloca (30); \ |
945 |
|
|
\ |
946 |
|
|
g_snprintf ((char *) _s, 30, "(%lld)", (long long) _idx); \ |
947 |
|
|
} \ |
948 |
|
|
_s; \ |
949 |
|
|
}) |
950 |
|
|
|
951 |
|
|
/*****************************************************************************/ |
952 |
|
|
|
953 |
|
|
/* check if @flags has exactly one flag (@check) set. You should call this |
954 |
|
|
* only with @check being a compile time constant and a power of two. */ |
955 |
|
|
#define NM_FLAGS_HAS(flags, check) \ |
956 |
|
|
( G_STATIC_ASSERT_EXPR ((check) > 0 && ((check) & ((check) - 1)) == 0), NM_FLAGS_ANY ((flags), (check)) ) |
957 |
|
|
|
958 |
|
|
#define NM_FLAGS_ANY(flags, check) ( ( ((flags) & (check)) != 0 ) ? TRUE : FALSE ) |
959 |
|
|
#define NM_FLAGS_ALL(flags, check) ( ( ((flags) & (check)) == (check) ) ? TRUE : FALSE ) |
960 |
|
|
|
961 |
|
|
#define NM_FLAGS_SET(flags, val) ({ \ |
962 |
|
|
const typeof(flags) _flags = (flags); \ |
963 |
|
|
const typeof(flags) _val = (val); \ |
964 |
|
|
\ |
965 |
|
|
_flags | _val; \ |
966 |
|
|
}) |
967 |
|
|
|
968 |
|
|
#define NM_FLAGS_UNSET(flags, val) ({ \ |
969 |
|
|
const typeof(flags) _flags = (flags); \ |
970 |
|
|
const typeof(flags) _val = (val); \ |
971 |
|
|
\ |
972 |
|
|
_flags & (~_val); \ |
973 |
|
|
}) |
974 |
|
|
|
975 |
|
|
#define NM_FLAGS_ASSIGN(flags, val, assign) ({ \ |
976 |
|
|
const typeof(flags) _flags = (flags); \ |
977 |
|
|
const typeof(flags) _val = (val); \ |
978 |
|
|
\ |
979 |
|
|
(assign) \ |
980 |
|
|
? _flags | (_val) \ |
981 |
|
|
: _flags & (~_val); \ |
982 |
|
|
}) |
983 |
|
|
|
984 |
|
|
/*****************************************************************************/ |
985 |
|
|
|
986 |
|
|
#define _NM_BACKPORT_SYMBOL_IMPL(VERSION, RETURN_TYPE, ORIG_FUNC, VERSIONED_FUNC, ARGS_TYPED, ARGS) \ |
987 |
|
|
RETURN_TYPE VERSIONED_FUNC ARGS_TYPED; \ |
988 |
|
|
RETURN_TYPE VERSIONED_FUNC ARGS_TYPED \ |
989 |
|
|
{ \ |
990 |
|
|
return ORIG_FUNC ARGS; \ |
991 |
|
|
} \ |
992 |
|
|
RETURN_TYPE ORIG_FUNC ARGS_TYPED; \ |
993 |
|
|
__asm__(".symver "G_STRINGIFY(VERSIONED_FUNC)", "G_STRINGIFY(ORIG_FUNC)"@"G_STRINGIFY(VERSION)) |
994 |
|
|
|
995 |
|
|
#define NM_BACKPORT_SYMBOL(VERSION, RETURN_TYPE, FUNC, ARGS_TYPED, ARGS) \ |
996 |
|
|
_NM_BACKPORT_SYMBOL_IMPL(VERSION, RETURN_TYPE, FUNC, _##FUNC##_##VERSION, ARGS_TYPED, ARGS) |
997 |
|
|
|
998 |
|
|
/*****************************************************************************/ |
999 |
|
|
|
1000 |
|
|
#define nm_str_skip_leading_spaces(str) \ |
1001 |
|
|
({ \ |
1002 |
|
|
typeof (*(str)) *_str = (str); \ |
1003 |
|
|
_nm_unused const char *_str_type_check = _str; \ |
1004 |
|
|
\ |
1005 |
|
|
if (_str) { \ |
1006 |
|
|
while (g_ascii_isspace (_str[0])) \ |
1007 |
|
|
_str++; \ |
1008 |
|
|
} \ |
1009 |
|
|
_str; \ |
1010 |
|
|
}) |
1011 |
|
|
|
1012 |
|
|
static inline char * |
1013 |
|
|
nm_strstrip (char *str) |
1014 |
|
|
{ |
1015 |
|
|
/* g_strstrip doesn't like NULL. */ |
1016 |
|
|
return str ? g_strstrip (str) : NULL; |
1017 |
|
|
} |
1018 |
|
|
|
1019 |
|
|
static inline const char * |
1020 |
|
|
nm_strstrip_avoid_copy (const char *str, char **str_free) |
1021 |
|
|
{ |
1022 |
|
|
gsize l; |
1023 |
|
|
char *s; |
1024 |
|
|
|
1025 |
|
|
nm_assert (str_free && !*str_free); |
1026 |
|
|
|
1027 |
|
|
if (!str) |
1028 |
|
|
return NULL; |
1029 |
|
|
|
1030 |
|
|
str = nm_str_skip_leading_spaces (str); |
1031 |
|
|
l = strlen (str); |
1032 |
|
|
if ( l == 0 |
1033 |
|
|
|| !g_ascii_isspace (str[l - 1])) |
1034 |
|
|
return str; |
1035 |
|
|
while ( l > 0 |
1036 |
|
|
&& g_ascii_isspace (str[l - 1])) |
1037 |
|
|
l--; |
1038 |
|
|
|
1039 |
|
|
s = g_new (char, l + 1); |
1040 |
|
|
memcpy (s, str, l); |
1041 |
|
|
s[l] = '\0'; |
1042 |
|
|
*str_free = s; |
1043 |
|
|
return s; |
1044 |
|
|
} |
1045 |
|
|
|
1046 |
|
|
/* g_ptr_array_sort()'s compare function takes pointers to the |
1047 |
|
|
* value. Thus, you cannot use strcmp directly. You can use |
1048 |
|
|
* nm_strcmp_p(). |
1049 |
|
|
* |
1050 |
|
|
* Like strcmp(), this function is not forgiving to accept %NULL. */ |
1051 |
|
|
static inline int |
1052 |
|
|
nm_strcmp_p (gconstpointer a, gconstpointer b) |
1053 |
|
|
{ |
1054 |
|
|
const char *s1 = *((const char **) a); |
1055 |
|
|
const char *s2 = *((const char **) b); |
1056 |
|
|
|
1057 |
|
|
return strcmp (s1, s2); |
1058 |
|
|
} |
1059 |
|
|
|
1060 |
|
|
/* like nm_strcmp_p(), suitable for g_ptr_array_sort_with_data(). |
1061 |
|
|
* g_ptr_array_sort() just casts nm_strcmp_p() to a function of different |
1062 |
|
|
* signature. I guess, in glib there are knowledgeable people that ensure |
1063 |
|
|
* that this additional argument doesn't cause problems due to different ABI |
1064 |
|
|
* for every architecture that glib supports. |
1065 |
|
|
* For NetworkManager, we'd rather avoid such stunts. |
1066 |
|
|
**/ |
1067 |
|
|
static inline int |
1068 |
|
|
nm_strcmp_p_with_data (gconstpointer a, gconstpointer b, gpointer user_data) |
1069 |
|
|
{ |
1070 |
|
|
const char *s1 = *((const char **) a); |
1071 |
|
|
const char *s2 = *((const char **) b); |
1072 |
|
|
|
1073 |
|
|
return strcmp (s1, s2); |
1074 |
|
|
} |
1075 |
|
|
|
1076 |
|
|
static inline int |
1077 |
|
|
nm_cmp_uint32_p_with_data (gconstpointer p_a, gconstpointer p_b, gpointer user_data) |
1078 |
|
|
{ |
1079 |
|
|
const guint32 a = *((const guint32 *) p_a); |
1080 |
|
|
const guint32 b = *((const guint32 *) p_b); |
1081 |
|
|
|
1082 |
|
|
if (a < b) |
1083 |
|
|
return -1; |
1084 |
|
|
if (a > b) |
1085 |
|
|
return 1; |
1086 |
|
|
return 0; |
1087 |
|
|
} |
1088 |
|
|
|
1089 |
|
|
static inline int |
1090 |
|
|
nm_cmp_int2ptr_p_with_data (gconstpointer p_a, gconstpointer p_b, gpointer user_data) |
1091 |
|
|
{ |
1092 |
|
|
/* p_a and p_b are two pointers to a pointer, where the pointer is |
1093 |
|
|
* interpreted as a integer using GPOINTER_TO_INT(). |
1094 |
|
|
* |
1095 |
|
|
* That is the case of a hash-table that uses GINT_TO_POINTER() to |
1096 |
|
|
* convert integers as pointers, and the resulting keys-as-array |
1097 |
|
|
* array. */ |
1098 |
|
|
const int a = GPOINTER_TO_INT (*((gconstpointer *) p_a)); |
1099 |
|
|
const int b = GPOINTER_TO_INT (*((gconstpointer *) p_b)); |
1100 |
|
|
|
1101 |
|
|
if (a < b) |
1102 |
|
|
return -1; |
1103 |
|
|
if (a > b) |
1104 |
|
|
return 1; |
1105 |
|
|
return 0; |
1106 |
|
|
} |
1107 |
|
|
|
1108 |
|
|
/*****************************************************************************/ |
1109 |
|
|
|
1110 |
|
|
/* Taken from systemd's UNIQ_T and UNIQ macros. */ |
1111 |
|
|
|
1112 |
|
|
#define NM_UNIQ_T(x, uniq) G_PASTE(__unique_prefix_, G_PASTE(x, uniq)) |
1113 |
|
|
#define NM_UNIQ __COUNTER__ |
1114 |
|
|
|
1115 |
|
|
/*****************************************************************************/ |
1116 |
|
|
|
1117 |
|
|
/* glib's MIN()/MAX() macros don't have function-like behavior, in that they evaluate |
1118 |
|
|
* the argument possibly twice. |
1119 |
|
|
* |
1120 |
|
|
* Taken from systemd's MIN()/MAX() macros. */ |
1121 |
|
|
|
1122 |
|
|
#define NM_MIN(a, b) __NM_MIN(NM_UNIQ, a, NM_UNIQ, b) |
1123 |
|
|
#define __NM_MIN(aq, a, bq, b) \ |
1124 |
|
|
({ \ |
1125 |
|
|
typeof (a) NM_UNIQ_T(A, aq) = (a); \ |
1126 |
|
|
typeof (b) NM_UNIQ_T(B, bq) = (b); \ |
1127 |
|
|
((NM_UNIQ_T(A, aq) < NM_UNIQ_T(B, bq)) ? NM_UNIQ_T(A, aq) : NM_UNIQ_T(B, bq)); \ |
1128 |
|
|
}) |
1129 |
|
|
|
1130 |
|
|
#define NM_MAX(a, b) __NM_MAX(NM_UNIQ, a, NM_UNIQ, b) |
1131 |
|
|
#define __NM_MAX(aq, a, bq, b) \ |
1132 |
|
|
({ \ |
1133 |
|
|
typeof (a) NM_UNIQ_T(A, aq) = (a); \ |
1134 |
|
|
typeof (b) NM_UNIQ_T(B, bq) = (b); \ |
1135 |
|
|
((NM_UNIQ_T(A, aq) > NM_UNIQ_T(B, bq)) ? NM_UNIQ_T(A, aq) : NM_UNIQ_T(B, bq)); \ |
1136 |
|
|
}) |
1137 |
|
|
|
1138 |
|
|
#define NM_CLAMP(x, low, high) __NM_CLAMP(NM_UNIQ, x, NM_UNIQ, low, NM_UNIQ, high) |
1139 |
|
|
#define __NM_CLAMP(xq, x, lowq, low, highq, high) \ |
1140 |
|
|
({ \ |
1141 |
|
|
typeof(x)NM_UNIQ_T(X,xq) = (x); \ |
1142 |
|
|
typeof(low) NM_UNIQ_T(LOW,lowq) = (low); \ |
1143 |
|
|
typeof(high) NM_UNIQ_T(HIGH,highq) = (high); \ |
1144 |
|
|
\ |
1145 |
|
|
( (NM_UNIQ_T(X,xq) > NM_UNIQ_T(HIGH,highq)) \ |
1146 |
|
|
? NM_UNIQ_T(HIGH,highq) \ |
1147 |
|
|
: (NM_UNIQ_T(X,xq) < NM_UNIQ_T(LOW,lowq)) \ |
1148 |
|
|
? NM_UNIQ_T(LOW,lowq) \ |
1149 |
|
|
: NM_UNIQ_T(X,xq)); \ |
1150 |
|
|
}) |
1151 |
|
|
|
1152 |
|
|
/*****************************************************************************/ |
1153 |
|
|
|
1154 |
|
|
static inline guint |
1155 |
|
|
nm_encode_version (guint major, guint minor, guint micro) |
1156 |
|
|
{ |
1157 |
|
|
/* analog to the preprocessor macro NM_ENCODE_VERSION(). */ |
1158 |
|
|
return (major << 16) | (minor << 8) | micro; |
1159 |
|
|
} |
1160 |
|
|
|
1161 |
|
|
static inline void |
1162 |
|
|
nm_decode_version (guint version, guint *major, guint *minor, guint *micro) |
1163 |
|
|
{ |
1164 |
|
|
*major = (version & 0xFFFF0000u) >> 16; |
1165 |
|
|
*minor = (version & 0x0000FF00u) >> 8; |
1166 |
|
|
*micro = (version & 0x000000FFu); |
1167 |
|
|
} |
1168 |
|
|
|
1169 |
|
|
/*****************************************************************************/ |
1170 |
|
|
|
1171 |
|
|
/* taken from systemd's DECIMAL_STR_MAX() |
1172 |
|
|
* |
1173 |
|
|
* Returns the number of chars needed to format variables of the |
1174 |
|
|
* specified type as a decimal string. Adds in extra space for a |
1175 |
|
|
* negative '-' prefix (hence works correctly on signed |
1176 |
|
|
* types). Includes space for the trailing NUL. */ |
1177 |
|
|
#define NM_DECIMAL_STR_MAX(type) \ |
1178 |
|
|
(2+(sizeof(type) <= 1 ? 3 : \ |
1179 |
|
|
sizeof(type) <= 2 ? 5 : \ |
1180 |
|
|
sizeof(type) <= 4 ? 10 : \ |
1181 |
|
|
sizeof(type) <= 8 ? 20 : sizeof(int[-2*(sizeof(type) > 8)]))) |
1182 |
|
|
|
1183 |
|
|
/*****************************************************************************/ |
1184 |
|
|
|
1185 |
|
|
/* if @str is NULL, return "(null)". Otherwise, allocate a buffer using |
1186 |
|
|
* alloca() of and fill it with @str. @str will be quoted with double quote. |
1187 |
|
|
* If @str is longer then @trunc_at, the string is truncated and the closing |
1188 |
|
|
* quote is instead '^' to indicate truncation. |
1189 |
|
|
* |
1190 |
|
|
* Thus, the maximum stack allocated buffer will be @trunc_at+3. */ |
1191 |
|
|
#define nm_strquote_a(trunc_at, str) \ |
1192 |
|
|
({ \ |
1193 |
|
|
const char *const _str = (str); \ |
1194 |
|
|
\ |
1195 |
|
|
(_str \ |
1196 |
|
|
? ({ \ |
1197 |
|
|
const gsize _trunc_at = (trunc_at); \ |
1198 |
|
|
const gsize _strlen_trunc = NM_MIN (strlen (_str), _trunc_at); \ |
1199 |
|
|
char *_buf; \ |
1200 |
|
|
\ |
1201 |
|
|
_buf = g_alloca (_strlen_trunc + 3); \ |
1202 |
|
|
_buf[0] = '"'; \ |
1203 |
|
|
memcpy (&_buf[1], _str, _strlen_trunc); \ |
1204 |
|
|
_buf[_strlen_trunc + 1] = _str[_strlen_trunc] ? '^' : '"'; \ |
1205 |
|
|
_buf[_strlen_trunc + 2] = '\0'; \ |
1206 |
|
|
_buf; \ |
1207 |
|
|
}) \ |
1208 |
|
|
: "(null)"); \ |
1209 |
|
|
}) |
1210 |
|
|
|
1211 |
|
|
#define nm_sprintf_buf(buf, format, ...) \ |
1212 |
|
|
({ \ |
1213 |
|
|
char * _buf = (buf); \ |
1214 |
|
|
int _buf_len; \ |
1215 |
|
|
\ |
1216 |
|
|
/* some static assert trying to ensure that the buffer is statically allocated. |
1217 |
|
|
* It disallows a buffer size of sizeof(gpointer) to catch that. */ \ |
1218 |
|
|
G_STATIC_ASSERT (G_N_ELEMENTS (buf) == sizeof (buf) && sizeof (buf) != sizeof (char *)); \ |
1219 |
|
|
_buf_len = g_snprintf (_buf, sizeof (buf), \ |
1220 |
|
|
""format"", ##__VA_ARGS__); \ |
1221 |
|
|
nm_assert (_buf_len < sizeof (buf)); \ |
1222 |
|
|
_buf; \ |
1223 |
|
|
}) |
1224 |
|
|
|
1225 |
|
|
#define nm_sprintf_bufa(n_elements, format, ...) \ |
1226 |
|
|
({ \ |
1227 |
|
|
char *_buf; \ |
1228 |
|
|
int _buf_len; \ |
1229 |
|
|
typeof (n_elements) _n_elements = (n_elements); \ |
1230 |
|
|
\ |
1231 |
|
|
_buf = g_alloca (_n_elements); \ |
1232 |
|
|
_buf_len = g_snprintf (_buf, _n_elements, \ |
1233 |
|
|
""format"", ##__VA_ARGS__); \ |
1234 |
|
|
nm_assert (_buf_len < _n_elements); \ |
1235 |
|
|
_buf; \ |
1236 |
|
|
}) |
1237 |
|
|
|
1238 |
|
|
/* aims to alloca() a buffer and fill it with printf(format, name). |
1239 |
|
|
* Note that format must not contain any format specifier except |
1240 |
|
|
* "%s". |
1241 |
|
|
* If the resulting string would be too large for stack allocation, |
1242 |
|
|
* it allocates a buffer with g_malloc() and assigns it to *p_val_to_free. */ |
1243 |
|
|
#define nm_construct_name_a(format, name, p_val_to_free) \ |
1244 |
|
|
({ \ |
1245 |
|
|
const char *const _name = (name); \ |
1246 |
|
|
char **const _p_val_to_free = (p_val_to_free); \ |
1247 |
|
|
const gsize _name_len = strlen (_name); \ |
1248 |
|
|
char *_buf2; \ |
1249 |
|
|
\ |
1250 |
|
|
nm_assert (_p_val_to_free && !*_p_val_to_free); \ |
1251 |
|
|
if (NM_STRLEN (format) + _name_len < 200) \ |
1252 |
|
|
_buf2 = nm_sprintf_bufa (NM_STRLEN (format) + _name_len, format, _name); \ |
1253 |
|
|
else { \ |
1254 |
|
|
_buf2 = g_strdup_printf (format, _name); \ |
1255 |
|
|
*_p_val_to_free = _buf2; \ |
1256 |
|
|
} \ |
1257 |
|
|
(const char *) _buf2; \ |
1258 |
|
|
}) |
1259 |
|
|
|
1260 |
|
|
/*****************************************************************************/ |
1261 |
|
|
|
1262 |
|
|
/** |
1263 |
|
|
* The boolean type _Bool is C99 while we mostly stick to C89. However, _Bool is too |
1264 |
|
|
* convenient to miss and is effectively available in gcc and clang. So, just use it. |
1265 |
|
|
* |
1266 |
|
|
* Usually, one would include "stdbool.h" to get the "bool" define which aliases |
1267 |
|
|
* _Bool. We provide this define here, because we want to make use of it anywhere. |
1268 |
|
|
* (also, stdbool.h is again C99). |
1269 |
|
|
* |
1270 |
|
|
* Using _Bool has advantages over gboolean: |
1271 |
|
|
* |
1272 |
|
|
* - commonly _Bool is one byte large, instead of gboolean's 4 bytes (because gboolean |
1273 |
|
|
* is a typedef for gint). Especially when having boolean fields in a struct, we can |
1274 |
|
|
* thereby easily save some space. |
1275 |
|
|
* |
1276 |
|
|
* - _Bool type guarantees that two "true" expressions compare equal. E.g. the follwing |
1277 |
|
|
* will not work: |
1278 |
|
|
* gboolean v1 = 1; |
1279 |
|
|
* gboolean v2 = 2; |
1280 |
|
|
* g_assert_cmpint (v1, ==, v2); // will fail |
1281 |
|
|
* For that, we often to use !! to coerce gboolean values to 0 or 1: |
1282 |
|
|
* g_assert_cmpint (!!v2, ==, TRUE); |
1283 |
|
|
* With _Bool type, this will be handled properly by the compiler. |
1284 |
|
|
* |
1285 |
|
|
* - For structs, we might want to safe even more space and use bitfields: |
1286 |
|
|
* struct s1 { |
1287 |
|
|
* gboolean v1:1; |
1288 |
|
|
* }; |
1289 |
|
|
* But the problem here is that gboolean is signed, so that |
1290 |
|
|
* v1 will be either 0 or -1 (not 1, TRUE). Thus, the following |
1291 |
|
|
* fails: |
1292 |
|
|
* struct s1 s = { .v1 = TRUE, }; |
1293 |
|
|
* g_assert_cmpint (s1.v1, ==, TRUE); |
1294 |
|
|
* It will however work just fine with bool/_Bool while retaining the |
1295 |
|
|
* notion of having a boolean value. |
1296 |
|
|
* |
1297 |
|
|
* Also, add the defines for "true" and "false". Those are nicely highlighted by the editor |
1298 |
|
|
* as special types, contrary to glib's "TRUE"/"FALSE". |
1299 |
|
|
*/ |
1300 |
|
|
|
1301 |
|
|
#ifndef bool |
1302 |
|
|
#define bool _Bool |
1303 |
|
|
#define true 1 |
1304 |
|
|
#define false 0 |
1305 |
|
|
#endif |
1306 |
|
|
|
1307 |
|
|
|
1308 |
|
|
#ifdef _G_BOOLEAN_EXPR |
1309 |
|
|
/* g_assert() uses G_LIKELY(), which in turn uses _G_BOOLEAN_EXPR(). |
1310 |
|
|
* As glib's implementation uses a local variable _g_boolean_var_, |
1311 |
|
|
* we cannot do |
1312 |
|
|
* g_assert (some_macro ()); |
1313 |
|
|
* where some_macro() itself expands to ({g_assert(); ...}). |
1314 |
|
|
* In other words, you cannot have a g_assert() inside a g_assert() |
1315 |
|
|
* without getting a -Werror=shadow failure. |
1316 |
|
|
* |
1317 |
|
|
* Workaround that by re-defining _G_BOOLEAN_EXPR() |
1318 |
|
|
**/ |
1319 |
|
|
#undef _G_BOOLEAN_EXPR |
1320 |
|
|
#define __NM_G_BOOLEAN_EXPR_IMPL(v, expr) \ |
1321 |
|
|
({ \ |
1322 |
|
|
int NM_UNIQ_T(V, v); \ |
1323 |
|
|
\ |
1324 |
|
|
if (expr) \ |
1325 |
|
|
NM_UNIQ_T(V, v) = 1; \ |
1326 |
|
|
else \ |
1327 |
|
|
NM_UNIQ_T(V, v) = 0; \ |
1328 |
|
|
NM_UNIQ_T(V, v); \ |
1329 |
|
|
}) |
1330 |
|
|
#define _G_BOOLEAN_EXPR(expr) __NM_G_BOOLEAN_EXPR_IMPL (NM_UNIQ, expr) |
1331 |
|
|
#endif |
1332 |
|
|
|
1333 |
|
|
/*****************************************************************************/ |
1334 |
|
|
|
1335 |
|
|
/** |
1336 |
|
|
* nm_steal_int: |
1337 |
|
|
* @p_val: pointer to an int type. |
1338 |
|
|
* |
1339 |
|
|
* Returns: *p_val and sets *p_val to zero the same time. |
1340 |
|
|
* Accepts %NULL, in which case also numeric 0 will be returned. |
1341 |
|
|
*/ |
1342 |
|
|
#define nm_steal_int(p_val) \ |
1343 |
|
|
({ \ |
1344 |
|
|
typeof (p_val) const _p_val = (p_val); \ |
1345 |
|
|
typeof (*_p_val) _val = 0; \ |
1346 |
|
|
\ |
1347 |
|
|
if ( _p_val \ |
1348 |
|
|
&& (_val = *_p_val)) { \ |
1349 |
|
|
*_p_val = 0; \ |
1350 |
|
|
} \ |
1351 |
|
|
_val; \ |
1352 |
|
|
}) |
1353 |
|
|
|
1354 |
|
|
static inline int |
1355 |
|
|
nm_steal_fd (int *p_fd) |
1356 |
|
|
{ |
1357 |
|
|
int fd; |
1358 |
|
|
|
1359 |
|
|
if ( p_fd |
1360 |
|
|
&& ((fd = *p_fd) >= 0)) { |
1361 |
|
|
*p_fd = -1; |
1362 |
|
|
return fd; |
1363 |
|
|
} |
1364 |
|
|
return -1; |
1365 |
|
|
} |
1366 |
|
|
|
1367 |
|
|
/** |
1368 |
|
|
* nm_close: |
1369 |
|
|
* |
1370 |
|
|
* Like close() but throws an assertion if the input fd is |
1371 |
|
|
* invalid. Closing an invalid fd is a programming error, so |
1372 |
|
|
* it's better to catch it early. |
1373 |
|
|
*/ |
1374 |
|
|
static inline int |
1375 |
|
11 |
nm_close (int fd) |
1376 |
|
|
{ |
1377 |
|
|
int r; |
1378 |
|
|
|
1379 |
|
11 |
r = close (fd); |
1380 |
|
|
nm_assert (r != -1 || fd < 0 || errno != EBADF); |
1381 |
|
11 |
return r; |
1382 |
|
|
} |
1383 |
|
|
|
1384 |
|
|
#endif /* __NM_MACROS_INTERNAL_H__ */ |
1385 |
|
|
|