Nilorea Library
C utilities for networking, threading, graphics
Loading...
Searching...
No Matches
n_common.h
Go to the documentation of this file.
1/*
2 * Nilorea Library
3 * Copyright (C) 2005-2026 Castagnier Mickael
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <https://www.gnu.org/licenses/>.
17 */
18
27#ifndef __NILOREA_COMMONS__
28#define __NILOREA_COMMONS__
29
30#ifdef __cplusplus
31extern "C" {
32#endif
33
39#include <sys/types.h>
40#include <unistd.h>
41#include <stdlib.h>
42#include <malloc.h>
43#include <errno.h>
44#include <string.h>
45#include <strings.h>
46#include <stdint.h>
47#include <nilorea/n_log.h>
48#include <nilorea/n_enum.h>
49
51#if defined(_WIN32) || defined(_WIN64)
52#ifndef __windows__
53#define __windows__
54#endif
55#ifndef WEXITSTATUS
56#define WEXITSTATUS(w) (((w) >> 8) & 0xff)
57#endif
58#ifndef WIFEXITED
59#define WIFEXITED(w) (((w) & 0xff) == 0)
60#endif
61#else
62#include <alloca.h>
63#include <signal.h>
64#endif
65
66#if defined(__GNUC__) && __GNUC__ >= 7
68#define FALL_THROUGH __attribute__((fallthrough))
69#else
71#define FALL_THROUGH /* fall through */ \
72 ((void)0)
73#endif /* __GNUC__ >= 7 */
74
75#if defined(_WIN32) || defined(_WIN64)
76#if defined(_WIN64)
78#define ENV_64BITS
79#else
81#define ENV_32BITS
82#endif
83#endif
84
85#if !defined(ENV_32BITS) || !defined(ENV_64BITS)
86#if defined(__GNUC__)
87#if defined(__x86_64__) || defined(__ppc64__)
89#define __ENVBITS __ENV_64BITS
90#else
92#define __ENVBITS __ENV_32BITS
93#endif
94#endif
95#endif
96
98#define BYTEORDER_LITTLE_ENDIAN 0 // Little endian machine.
100#define BYTEORDER_BIG_ENDIAN 1 // Big endian machine.
101
102#ifndef BYTEORDER_ENDIAN
103// Detect with GCC 4.6's macro.
104#if defined(__BYTE_ORDER__)
105#if (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)
106#define BYTEORDER_ENDIAN BYTEORDER_LITTLE_ENDIAN
107#elif (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)
108#define BYTEORDER_ENDIAN BYTEORDER_BIG_ENDIAN
109#else
110#define BYTEORDER_ENDIAN BYTEORDER_LITTLE_ENDIAN
111#warning "Unknown machine byteorder endianness detected. User needs to define BYTEORDER_ENDIAN."
112#warning "Setting default to BYTEORDER_LITTLE_ENDIAN"
113#endif
114// Detect with GLIBC's endian.h.
115#elif defined(__GLIBC__)
116#include <endian.h>
117#if (__BYTE_ORDER == __LITTLE_ENDIAN)
118#define BYTEORDER_ENDIAN BYTEORDER_LITTLE_ENDIAN
119#elif (__BYTE_ORDER == __BIG_ENDIAN)
120#define BYTEORDER_ENDIAN BYTEORDER_BIG_ENDIAN
121#else
122#define BYTEORDER_ENDIAN BYTEORDER_LITTLE_ENDIAN
123#warning "Unknown machine byteorder endianness detected. User needs to define BYTEORDER_ENDIAN."
124#warning "Setting default to BYTEORDER_LITTLE_ENDIAN"
125#endif
126// Detect with _LITTLE_ENDIAN and _BIG_ENDIAN macro.
127#elif defined(_LITTLE_ENDIAN) && !defined(_BIG_ENDIAN)
128#define BYTEORDER_ENDIAN BYTEORDER_LITTLE_ENDIAN
129#elif defined(_BIG_ENDIAN) && !defined(_LITTLE_ENDIAN)
130#define BYTEORDER_ENDIAN BYTEORDER_BIG_ENDIAN
131// Detect with architecture macros.
132#elif defined(__sparc) || defined(__sparc__) || defined(_POWER) || defined(__powerpc__) || defined(__ppc__) || defined(__hpux) || defined(__hppa) || defined(_MIPSEB) || defined(_POWER) || defined(__s390__)
133#define BYTEORDER_ENDIAN BYTEORDER_BIG_ENDIAN
134#elif defined(__i386__) || defined(__alpha__) || defined(__ia64) || defined(__ia64__) || defined(_M_IX86) || defined(_M_IA64) || defined(_M_ALPHA) || defined(__amd64) || defined(__amd64__) || defined(_M_AMD64) || defined(__x86_64) || defined(__x86_64__) || defined(_M_X64) || defined(__bfin__)
135#define BYTEORDER_ENDIAN BYTEORDER_LITTLE_ENDIAN
136#elif defined(_MSC_VER) && (defined(_M_ARM) || defined(_M_ARM64))
137#define BYTEORDER_ENDIAN BYTEORDER_LITTLE_ENDIAN
138#else
139#define BYTEORDER_ENDIAN BYTEORDER_LITTLE_ENDIAN
140#warning "Unknown machine byteorder endianness detected. User needs to define BYTEORDER_ENDIAN."
141#warning "Setting default to BYTEORDER_LITTLE_ENDIAN"
142#endif
143#endif
144
145#if defined(__windows__)
146/* typedefine for unsigned category for basic native types */
148typedef unsigned int uint;
150typedef unsigned long ulong;
152typedef unsigned short ushort;
154typedef unsigned char uchar;
155#endif
156
158#ifdef _MSVC_VER
159#define FORCE_INLINE __forceinline
160#elif defined(__linux__) || defined(__windows__)
161#define FORCE_INLINE static inline __attribute__((always_inline))
162#else
163#define FORCE_INLINE static inline __attribute__((always_inline))
164#endif
165
167#ifndef true
168#define true (1 == 1)
169#endif
170
172#ifndef TRUE
173#define TRUE true
174#endif
175
177#ifndef false
178#define false (1 == 0)
179#endif
180
182#ifndef FALSE
183#define FALSE false
184#endif
185
187#ifndef EMPTY
188#define EMPTY 2
189#endif
190
192#define _str(__PTR) ((__PTR) ? (__PTR) : "NULL")
194#define _strp(__PTR) ((__PTR) ? (__PTR) : NULL)
196#define _strw(__PTR) ((__PTR) ? (__PTR) : " ")
198#define _nstr(__PTR) ((__PTR && __PTR->data) ? (__PTR->data) : "NULL")
200#define _nstrp(__PTR) ((__PTR && __PTR->data) ? (__PTR->data) : NULL)
201
203#define Malloc(__ptr, __struct, __size) \
204 { \
205 int __n_errno = 0; \
206 errno = 0; \
207 __ptr = (__struct*)calloc(__size, sizeof(__struct)); \
208 __n_errno = errno; \
209 if (!__ptr) { \
210 n_log(LOG_ERR, "( %s *)calloc( %zu , sizeof( %s ) ) %s at line %d of %s", #__ptr, __size, #__struct, (__n_errno == 0) ? "malloc error" : strerror(__n_errno), __LINE__, __FILE__); \
211 } \
212 }
213
215#define Alloca(__ptr, __size) \
216 { \
217 int __n_errno = 0; \
218 errno = 0; \
219 __ptr = alloca(__size); \
220 __n_errno = errno; \
221 if (!__ptr) { \
222 n_log(LOG_ERR, "%s=alloca( %zu ) %s at line %d of %s", #__ptr, __size, (__n_errno == 0) ? "alloca error" : strerror(__n_errno), __LINE__, __FILE__); \
223 } else { \
224 memset(__ptr, 0, __size); \
225 } \
226 }
227
230#define Realloc(__ptr, __struct, __size) \
231 ({ \
232 int __n_errno = 0; \
233 errno = 0; \
234 void* __new_ptr = ((__size) && (sizeof(__struct)) && ((__size) > SIZE_MAX / sizeof(__struct))) ? NULL : (__struct*)realloc(__ptr, (__size) * sizeof(__struct)); \
235 __n_errno = errno; \
236 if (!__new_ptr) { \
237 n_log(LOG_ERR, "( %s *)realloc( %s * sizeof( %zu ) ) %s at line %d of %s", #__ptr, #__struct, __size, (__n_errno == 0) ? "realloc error" : strerror(__n_errno), __LINE__, __FILE__); \
238 } else { \
239 __ptr = __new_ptr; \
240 } \
241 (__new_ptr != NULL) ? TRUE : FALSE; \
242 })
243
246#define Reallocz(__ptr, __struct, __old_size, __size) \
247 ({ \
248 int __n_errno = 0; \
249 errno = 0; \
250 void* __new_ptr = ((__size) && (sizeof(__struct)) && ((__size) > SIZE_MAX / sizeof(__struct))) ? NULL : (__struct*)realloc(__ptr, __size); \
251 __n_errno = errno; \
252 if (!__new_ptr) { \
253 n_log(LOG_ERR, "( %s *)realloc( %s * sizeof( %zu ) ) %s at line %d of %s", #__ptr, #__struct, __size, (__n_errno == 0) ? "realloc error" : strerror(__n_errno), __LINE__, __FILE__); \
254 } else { \
255 __ptr = __new_ptr; \
256 if (__size > __old_size) memset(((char*)__ptr + __old_size), 0, __size - __old_size); \
257 } \
258 (__new_ptr != NULL) ? TRUE : FALSE; \
259 })
260
262#define Free(__ptr) \
263 if (__ptr) { \
264 free(__ptr); \
265 __ptr = NULL; \
266 } else { \
267 n_log(LOG_DEBUG, "Free( %s ) already done or NULL at line %d of %s", #__ptr, __LINE__, __FILE__); \
268 }
269
271#define FreeNoLog(__ptr) \
272 if (__ptr) { \
273 free(__ptr); \
274 __ptr = NULL; \
275 }
276
278#define __n_assert(__ptr, __ret) \
279 if (!(__ptr)) { \
280 n_log(LOG_DEBUG, "if( !(%s) ) assert at line %d of %s", #__ptr, __LINE__, __FILE__); \
281 __ret; \
282 }
283
285#define CALL_RETRY(__retvar, __expression, __max_tries) \
286 do { \
287 int __nb_retries = 0; \
288 do { \
289 __retvar = (__expression); \
290 __nb_retries++; \
291 } while (__retvar == -1 && errno == EINTR && __nb_retries < (__max_tries)); \
292 } while (0)
293
295#define next_odd(__val) (((__val) % 2 == 0) ? ((__val) + 1) : (__val))
296
298#define next_even(__val) (((__val) % 2 == 0) ? (__val) : ((__val) + 1))
299
301#define init_error_check() \
302 static int ___error__check_flag = FALSE;
303
305#define ifnull if( !
306
308#define ifzero if( 0 ==
309
311#define iffalse if( FALSE ==
312
314#define iftrue if( TRUE ==
315
317#define checkerror() \
318 if (___error__check_flag == TRUE) { \
319 n_log(LOG_ERR, "checkerror return false at line %d of %s", __LINE__, __FILE__); \
320 goto error; \
321 }
322
324#define endif ){ \
325 ___error__check_flag = TRUE; \
326 n_log(LOG_ERR, "First err was at line %d of %s", __LINE__, __FILE__); \
327 }
328
330#define get_error() \
331 (___error__check_flag == TRUE)
332
334#define equal_if(__a, __cond, __b) \
335 if ((__a)__cond(__b)) { \
336 __a = __b; \
337 }
338
339// #define RWLOCK_DEBUG 1
340#ifdef RWLOCK_DEBUG
342#define RWLOCK_LOGLEVEL LOG_DEBUG
343#else
345#define RWLOCK_LOGLEVEL LOG_NULL
346#endif
347
349#define init_lock(__rwlock_mutex) \
350 ({ \
351 pthread_rwlockattr_t __attr; \
352 pthread_rwlockattr_init(&__attr); \
353 int __ret = 0; \
354 do { \
355 n_log(RWLOCK_LOGLEVEL, "init_lock %s", #__rwlock_mutex); \
356 __rwlock_mutex = (pthread_rwlock_t)PTHREAD_RWLOCK_INITIALIZER; \
357 __ret = pthread_rwlock_init(&(__rwlock_mutex), &__attr); \
358 if (__ret != 0) { \
359 n_log(LOG_ERR, "Error %s while initializing %s at %s:%s:%d", strerror(__ret), #__rwlock_mutex, __FILE__, __func__, __LINE__); \
360 } \
361 pthread_rwlockattr_destroy(&__attr); \
362 } while (0); \
363 __ret; \
364 })
365
367#define read_lock(__rwlock_mutex) \
368 ({ \
369 int __ret = 0; \
370 do { \
371 n_log(RWLOCK_LOGLEVEL, "read lock %s", #__rwlock_mutex); \
372 __ret = pthread_rwlock_rdlock(&(__rwlock_mutex)); \
373 if (__ret != 0) { \
374 n_log(LOG_ERR, "Error %s while read locking %s at %s:%s:%d", strerror(__ret), #__rwlock_mutex, __FILE__, __func__, __LINE__); \
375 } \
376 } while (0); \
377 __ret; \
378 })
379
381#define write_lock(__rwlock_mutex) \
382 ({ \
383 int __ret = 0; \
384 do { \
385 n_log(RWLOCK_LOGLEVEL, "write lock %s", #__rwlock_mutex); \
386 __ret = pthread_rwlock_wrlock(&(__rwlock_mutex)); \
387 if (__ret != 0) { \
388 n_log(LOG_ERR, "Error %s while write locking %s at %s:%s:%d", strerror(__ret), #__rwlock_mutex, __FILE__, __func__, __LINE__); \
389 } \
390 } while (0); \
391 __ret; \
392 })
393
395#define unlock(__rwlock_mutex) \
396 ({ \
397 int __ret = 0; \
398 do { \
399 n_log(RWLOCK_LOGLEVEL, "unlock lock %s", #__rwlock_mutex); \
400 __ret = pthread_rwlock_unlock(&(__rwlock_mutex)); \
401 if (__ret != 0) { \
402 n_log(LOG_ERR, "Error %s while unlocking %s at %s:%s:%d", strerror(__ret), #__rwlock_mutex, __FILE__, __func__, __LINE__); \
403 } \
404 } while (0); \
405 __ret; \
406 })
408#define rw_lock_destroy(__rwlock_mutex) \
409 ({ \
410 int __ret = 0; \
411 do { \
412 n_log(RWLOCK_LOGLEVEL, "destroy lock %s", #__rwlock_mutex); \
413 __ret = pthread_rwlock_destroy(&(__rwlock_mutex)); \
414 if (__ret != 0) { \
415 n_log(LOG_ERR, "Error %s while destroying %s at %s:%s:%d", strerror(__ret), #__rwlock_mutex, __FILE__, __func__, __LINE__); \
416 } \
417 } while (0); \
418 __ret; \
419 })
420
422#define SET 1234
424#define GET 4321
426#define DEFAULT 1000
428#define RUNNING 1001
430#define STOPWANTED 1002
432#define STOPPED 1003
434#define PAUSED 1004
435
437#define randomize() \
438 { \
439 srand((unsigned)time(NULL)); \
440 rand(); \
441 }
442
443#ifndef MIN
445#define MIN(a, b) (((a) < (b)) ? (a) : (b))
446#endif
447#ifndef MAX
449#define MAX(a, b) (((a) > (b)) ? (a) : (b))
450#endif
451
453#define CONCAT_BUILDER(a, b) a##b
455#define CONCAT(a, b) CONCAT_BUILDER(a, b)
456
457#if (BYTEORDER_ENDIAN == BYTEORDER_BIG_ENDIAN)
459#ifndef htonll
460#define htonll(x) (x)
461#endif
463#ifndef ntohll
464#define ntohll(x) (x)
465#endif
466#else
468#ifndef htonll
469#define htonll(x) (((uint64_t)htonl((x) & 0xFFFFFFFF) << 32) | htonl((x) >> 32))
470#endif
472#ifndef ntohll
473#define ntohll(x) (((uint64_t)ntohl((x) & 0xFFFFFFFF) << 32) | ntohl((x) >> 32))
474#endif
475#endif
476
478void n_abort(char const* format, ...);
479
481int get_computer_name(char* computer_name, size_t len);
482
484char* get_prog_name(void);
485
487char* get_prog_dir(void);
488
490int file_exist(const char* filename);
491
493int n_popen(char* cmd, size_t read_buf_size, void** nstr_output, int* ret);
494
496void log_environment(int loglevel);
497
498#ifndef __windows__
500void sigchld_handler(int sig);
504#define N_DAEMON_NO_CLOSE 2
506#define N_DAEMON_NO_STD_REDIRECT 4
508#define N_DAEMON_NO_DOUBLE_FORK 8
510#define N_DAEMON_NO_SETSID 16
512#define N_DAEMON_NO_UMASK 32
514#define N_DAEMON_NO_CHDIR 64
516#define N_DAEMON_NO_SIGCHLD_IGN 128
518#define N_DAEMON_NO_SIGCHLD_HANDLER 256
520int n_daemonize(void);
522int n_daemonize_ex(int mode);
524pid_t system_nb(const char* command, int* infp, int* outfp);
525#endif
526
528void N_HIDE_STR(char* buf, ...);
529
531char* n_get_file_extension(char path[]);
536#ifdef __cplusplus
537}
538#endif
539
540#endif // header guard
static int mode
void log_environment(int loglevel)
log environment variables at the given log level
Definition n_common.c:231
char * get_prog_name(void)
get running program name
Definition n_common.c:144
void N_HIDE_STR(char *buf,...)
reconstruct hidden string from variadic char arguments
Definition n_common.c:458
int get_computer_name(char *computer_name, size_t len)
get the computer name into the given buffer
Definition n_common.c:69
void sigchld_handler(int sig)
reap zombie processes
Definition n_common.c:252
pid_t system_nb(const char *command, int *infp, int *outfp)
non-blocking system call
Definition n_common.c:389
char * n_get_file_extension(char path[])
get the file extension from a path
Definition n_common.c:479
char * get_prog_dir(void)
get running program directory
Definition n_common.c:112
int n_daemonize_ex(int mode)
daemonize the current process with the given mode flags
Definition n_common.c:292
void n_abort(char const *format,...)
htonl for 64 bits numbers
Definition n_common.c:52
int sigchld_handler_installer()
install signal SIGCHLD handler
Definition n_common.c:266
int n_daemonize(void)
daemonize the current process
Definition n_common.c:283
int file_exist(const char *filename)
test file presence
Definition n_common.c:99
int n_popen(char *cmd, size_t read_buf_size, void **nstr_output, int *ret)
shortcut for popen usage
Definition n_common.c:179
Macro to build enums and their tostring counterparts, a reduced version of https://github....
Generic log system.