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 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
14 * implied. See the License for the specific language governing
15 * permissions and limitations under the License.
16 *
17 * SPDX-License-Identifier: Apache-2.0
18 */
19
28#ifndef __NILOREA_COMMONS__
29#define __NILOREA_COMMONS__
30
31#ifdef __cplusplus
32extern "C" {
33#endif
34
40#include <sys/types.h>
41#include <unistd.h>
42#include <stdlib.h>
43#include <malloc.h>
44#include <errno.h>
45#include <string.h>
46#include <strings.h>
47#include <stdint.h>
48#include <nilorea/n_log.h>
49#include <nilorea/n_enum.h>
50
52#if defined(_WIN32) || defined(_WIN64)
53#ifndef __windows__
54#define __windows__
55#endif
56#ifndef WEXITSTATUS
57#define WEXITSTATUS(w) (((w) >> 8) & 0xff)
58#endif
59#ifndef WIFEXITED
60#define WIFEXITED(w) (((w) & 0xff) == 0)
61#endif
62#else
63#include <alloca.h>
64#include <signal.h>
65#endif
66
67#if defined(__GNUC__) && __GNUC__ >= 7
69#define FALL_THROUGH __attribute__((fallthrough))
70#else
72#define FALL_THROUGH /* fall through */ \
73 ((void)0)
74#endif /* __GNUC__ >= 7 */
75
76#if defined(_WIN32) || defined(_WIN64)
77#if defined(_WIN64)
79#define ENV_64BITS
80#else
82#define ENV_32BITS
83#endif
84#endif
85
86#if !defined(ENV_32BITS) || !defined(ENV_64BITS)
87#if defined(__GNUC__)
88#if defined(__x86_64__) || defined(__ppc64__)
90#define __ENVBITS __ENV_64BITS
91#else
93#define __ENVBITS __ENV_32BITS
94#endif
95#endif
96#endif
97
99#define BYTEORDER_LITTLE_ENDIAN 0 // Little endian machine.
101#define BYTEORDER_BIG_ENDIAN 1 // Big endian machine.
102
103#ifndef BYTEORDER_ENDIAN
104// Detect with GCC 4.6's macro.
105#if defined(__BYTE_ORDER__)
106#if (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)
107#define BYTEORDER_ENDIAN BYTEORDER_LITTLE_ENDIAN
108#elif (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)
109#define BYTEORDER_ENDIAN BYTEORDER_BIG_ENDIAN
110#else
111#define BYTEORDER_ENDIAN BYTEORDER_LITTLE_ENDIAN
112#warning "Unknown machine byteorder endianness detected. User needs to define BYTEORDER_ENDIAN."
113#warning "Setting default to BYTEORDER_LITTLE_ENDIAN"
114#endif
115// Detect with GLIBC's endian.h.
116#elif defined(__GLIBC__)
117#include <endian.h>
118#if (__BYTE_ORDER == __LITTLE_ENDIAN)
119#define BYTEORDER_ENDIAN BYTEORDER_LITTLE_ENDIAN
120#elif (__BYTE_ORDER == __BIG_ENDIAN)
121#define BYTEORDER_ENDIAN BYTEORDER_BIG_ENDIAN
122#else
123#define BYTEORDER_ENDIAN BYTEORDER_LITTLE_ENDIAN
124#warning "Unknown machine byteorder endianness detected. User needs to define BYTEORDER_ENDIAN."
125#warning "Setting default to BYTEORDER_LITTLE_ENDIAN"
126#endif
127// Detect with _LITTLE_ENDIAN and _BIG_ENDIAN macro.
128#elif defined(_LITTLE_ENDIAN) && !defined(_BIG_ENDIAN)
129#define BYTEORDER_ENDIAN BYTEORDER_LITTLE_ENDIAN
130#elif defined(_BIG_ENDIAN) && !defined(_LITTLE_ENDIAN)
131#define BYTEORDER_ENDIAN BYTEORDER_BIG_ENDIAN
132// Detect with architecture macros.
133#elif defined(__sparc) || defined(__sparc__) || defined(_POWER) || defined(__powerpc__) || defined(__ppc__) || defined(__hpux) || defined(__hppa) || defined(_MIPSEB) || defined(_POWER) || defined(__s390__)
134#define BYTEORDER_ENDIAN BYTEORDER_BIG_ENDIAN
135#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__)
136#define BYTEORDER_ENDIAN BYTEORDER_LITTLE_ENDIAN
137#elif defined(_MSC_VER) && (defined(_M_ARM) || defined(_M_ARM64))
138#define BYTEORDER_ENDIAN BYTEORDER_LITTLE_ENDIAN
139#else
140#define BYTEORDER_ENDIAN BYTEORDER_LITTLE_ENDIAN
141#warning "Unknown machine byteorder endianness detected. User needs to define BYTEORDER_ENDIAN."
142#warning "Setting default to BYTEORDER_LITTLE_ENDIAN"
143#endif
144#endif
145
146#if defined(__windows__)
147/* typedefine for unsigned category for basic native types */
149typedef unsigned int uint;
151typedef unsigned long ulong;
153typedef unsigned short ushort;
155typedef unsigned char uchar;
156#endif
157
159#ifdef _MSVC_VER
160#define FORCE_INLINE __forceinline
161#elif defined(__linux__) || defined(__windows__)
162#define FORCE_INLINE static inline __attribute__((always_inline))
163#else
164#define FORCE_INLINE static inline __attribute__((always_inline))
165#endif
166
168#ifndef true
169#define true (1 == 1)
170#endif
171
173#ifndef TRUE
174#define TRUE true
175#endif
176
178#ifndef false
179#define false (1 == 0)
180#endif
181
183#ifndef FALSE
184#define FALSE false
185#endif
186
188#ifndef EMPTY
189#define EMPTY 2
190#endif
191
193#define _str(__PTR) ((__PTR) ? (__PTR) : "NULL")
195#define _strp(__PTR) ((__PTR) ? (__PTR) : NULL)
197#define _strw(__PTR) ((__PTR) ? (__PTR) : " ")
199#define _nstr(__PTR) ((__PTR && __PTR->data) ? (__PTR->data) : "NULL")
201#define _nstrp(__PTR) ((__PTR && __PTR->data) ? (__PTR->data) : NULL)
202
204#define Malloc(__ptr, __struct, __size) \
205 { \
206 int __n_errno = 0; \
207 errno = 0; \
208 __ptr = (__struct*)calloc(__size, sizeof(__struct)); \
209 __n_errno = errno; \
210 if (!__ptr) { \
211 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__); \
212 } \
213 }
214
216#define Alloca(__ptr, __size) \
217 { \
218 int __n_errno = 0; \
219 errno = 0; \
220 __ptr = alloca(__size); \
221 __n_errno = errno; \
222 if (!__ptr) { \
223 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__); \
224 } else { \
225 memset(__ptr, 0, __size); \
226 } \
227 }
228
231#define Realloc(__ptr, __struct, __size) \
232 ({ \
233 int __n_errno = 0; \
234 errno = 0; \
235 void* __new_ptr = ((__size) && (sizeof(__struct)) && ((__size) > SIZE_MAX / sizeof(__struct))) ? NULL : (__struct*)realloc(__ptr, (__size) * sizeof(__struct)); \
236 __n_errno = errno; \
237 if (!__new_ptr) { \
238 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__); \
239 } else { \
240 __ptr = __new_ptr; \
241 } \
242 (__new_ptr != NULL) ? TRUE : FALSE; \
243 })
244
247#define Reallocz(__ptr, __struct, __old_size, __size) \
248 ({ \
249 int __n_errno = 0; \
250 errno = 0; \
251 void* __new_ptr = ((__size) && (sizeof(__struct)) && ((__size) > SIZE_MAX / sizeof(__struct))) ? NULL : (__struct*)realloc(__ptr, __size); \
252 __n_errno = errno; \
253 if (!__new_ptr) { \
254 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__); \
255 } else { \
256 __ptr = __new_ptr; \
257 if (__size > __old_size) memset(((char*)__ptr + __old_size), 0, __size - __old_size); \
258 } \
259 (__new_ptr != NULL) ? TRUE : FALSE; \
260 })
261
263#define Free(__ptr) \
264 if (__ptr) { \
265 free(__ptr); \
266 __ptr = NULL; \
267 } else { \
268 n_log(LOG_DEBUG, "Free( %s ) already done or NULL at line %d of %s", #__ptr, __LINE__, __FILE__); \
269 }
270
272#define FreeNoLog(__ptr) \
273 if (__ptr) { \
274 free(__ptr); \
275 __ptr = NULL; \
276 }
277
279#define __n_assert(__ptr, __ret) \
280 if (!(__ptr)) { \
281 n_log(LOG_DEBUG, "if( !(%s) ) assert at line %d of %s", #__ptr, __LINE__, __FILE__); \
282 __ret; \
283 }
284
286#define CALL_RETRY(__retvar, __expression, __max_tries) \
287 do { \
288 int __nb_retries = 0; \
289 do { \
290 __retvar = (__expression); \
291 __nb_retries++; \
292 } while (__retvar == -1 && errno == EINTR && __nb_retries < (__max_tries)); \
293 } while (0)
294
296#define next_odd(__val) (((__val) % 2 == 0) ? ((__val) + 1) : (__val))
297
299#define next_even(__val) (((__val) % 2 == 0) ? (__val) : ((__val) + 1))
300
302#define init_error_check() \
303 static int ___error__check_flag = FALSE;
304
306#define ifnull if( !
307
309#define ifzero if( 0 ==
310
312#define iffalse if( FALSE ==
313
315#define iftrue if( TRUE ==
316
318#define checkerror() \
319 if (___error__check_flag == TRUE) { \
320 n_log(LOG_ERR, "checkerror return false at line %d of %s", __LINE__, __FILE__); \
321 goto error; \
322 }
323
325#define endif ){ \
326 ___error__check_flag = TRUE; \
327 n_log(LOG_ERR, "First err was at line %d of %s", __LINE__, __FILE__); \
328 }
329
331#define get_error() \
332 (___error__check_flag == TRUE)
333
335#define equal_if(__a, __cond, __b) \
336 if ((__a)__cond(__b)) { \
337 __a = __b; \
338 }
339
340// #define RWLOCK_DEBUG 1
341#ifdef RWLOCK_DEBUG
343#define RWLOCK_LOGLEVEL LOG_DEBUG
344#else
346#define RWLOCK_LOGLEVEL LOG_NULL
347#endif
348
350#define init_lock(__rwlock_mutex) \
351 ({ \
352 pthread_rwlockattr_t __attr; \
353 pthread_rwlockattr_init(&__attr); \
354 int __ret = 0; \
355 do { \
356 n_log(RWLOCK_LOGLEVEL, "init_lock %s", #__rwlock_mutex); \
357 __rwlock_mutex = (pthread_rwlock_t)PTHREAD_RWLOCK_INITIALIZER; \
358 __ret = pthread_rwlock_init(&(__rwlock_mutex), &__attr); \
359 if (__ret != 0) { \
360 n_log(LOG_ERR, "Error %s while initializing %s at %s:%s:%d", strerror(__ret), #__rwlock_mutex, __FILE__, __func__, __LINE__); \
361 } \
362 pthread_rwlockattr_destroy(&__attr); \
363 } while (0); \
364 __ret; \
365 })
366
368#define read_lock(__rwlock_mutex) \
369 ({ \
370 int __ret = 0; \
371 do { \
372 n_log(RWLOCK_LOGLEVEL, "read lock %s", #__rwlock_mutex); \
373 __ret = pthread_rwlock_rdlock(&(__rwlock_mutex)); \
374 if (__ret != 0) { \
375 n_log(LOG_ERR, "Error %s while read locking %s at %s:%s:%d", strerror(__ret), #__rwlock_mutex, __FILE__, __func__, __LINE__); \
376 } \
377 } while (0); \
378 __ret; \
379 })
380
382#define write_lock(__rwlock_mutex) \
383 ({ \
384 int __ret = 0; \
385 do { \
386 n_log(RWLOCK_LOGLEVEL, "write lock %s", #__rwlock_mutex); \
387 __ret = pthread_rwlock_wrlock(&(__rwlock_mutex)); \
388 if (__ret != 0) { \
389 n_log(LOG_ERR, "Error %s while write locking %s at %s:%s:%d", strerror(__ret), #__rwlock_mutex, __FILE__, __func__, __LINE__); \
390 } \
391 } while (0); \
392 __ret; \
393 })
394
396#define unlock(__rwlock_mutex) \
397 ({ \
398 int __ret = 0; \
399 do { \
400 n_log(RWLOCK_LOGLEVEL, "unlock lock %s", #__rwlock_mutex); \
401 __ret = pthread_rwlock_unlock(&(__rwlock_mutex)); \
402 if (__ret != 0) { \
403 n_log(LOG_ERR, "Error %s while unlocking %s at %s:%s:%d", strerror(__ret), #__rwlock_mutex, __FILE__, __func__, __LINE__); \
404 } \
405 } while (0); \
406 __ret; \
407 })
409#define rw_lock_destroy(__rwlock_mutex) \
410 ({ \
411 int __ret = 0; \
412 do { \
413 n_log(RWLOCK_LOGLEVEL, "destroy lock %s", #__rwlock_mutex); \
414 __ret = pthread_rwlock_destroy(&(__rwlock_mutex)); \
415 if (__ret != 0) { \
416 n_log(LOG_ERR, "Error %s while destroying %s at %s:%s:%d", strerror(__ret), #__rwlock_mutex, __FILE__, __func__, __LINE__); \
417 } \
418 } while (0); \
419 __ret; \
420 })
421
423#define SET 1234
425#define GET 4321
427#define DEFAULT 1000
429#define RUNNING 1001
431#define STOPWANTED 1002
433#define STOPPED 1003
435#define PAUSED 1004
436
438#define randomize() \
439 { \
440 srand((unsigned)time(NULL)); \
441 rand(); \
442 }
443
444#ifndef MIN
446#define MIN(a, b) (((a) < (b)) ? (a) : (b))
447#endif
448#ifndef MAX
450#define MAX(a, b) (((a) > (b)) ? (a) : (b))
451#endif
452
454#define CONCAT_BUILDER(a, b) a##b
456#define CONCAT(a, b) CONCAT_BUILDER(a, b)
457
458/* On Windows, Winsock (winsock2.h) already declares htonll/ntohll as functions.
459 Defining them as macros here makes those later function declarations fail to parse
460 (the macro expands inside the prototype), so the 64-bit byte-order fallbacks are only
461 defined on non-Windows platforms; Windows code uses Winsock's htonll/ntohll. */
462#ifndef __windows__
463#if (BYTEORDER_ENDIAN == BYTEORDER_BIG_ENDIAN)
465#ifndef htonll
466#define htonll(x) (x)
467#endif
469#ifndef ntohll
470#define ntohll(x) (x)
471#endif
472#else
474#ifndef htonll
475#define htonll(x) (((uint64_t)htonl((x) & 0xFFFFFFFF) << 32) | htonl((x) >> 32))
476#endif
478#ifndef ntohll
479#define ntohll(x) (((uint64_t)ntohl((x) & 0xFFFFFFFF) << 32) | ntohl((x) >> 32))
480#endif
481#endif
482#endif /* __windows__ */
483
485void n_abort(char const* format, ...);
486
488int get_computer_name(char* computer_name, size_t len);
489
491char* get_prog_name(void);
492
494char* get_prog_dir(void);
495
497int file_exist(const char* filename);
498
500int n_popen(char* cmd, size_t read_buf_size, void** nstr_output, int* ret);
501
503void log_environment(int loglevel);
504
505#ifndef __windows__
507void sigchld_handler(int sig);
511#define N_DAEMON_NO_CLOSE 2
513#define N_DAEMON_NO_STD_REDIRECT 4
515#define N_DAEMON_NO_DOUBLE_FORK 8
517#define N_DAEMON_NO_SETSID 16
519#define N_DAEMON_NO_UMASK 32
521#define N_DAEMON_NO_CHDIR 64
523#define N_DAEMON_NO_SIGCHLD_IGN 128
525#define N_DAEMON_NO_SIGCHLD_HANDLER 256
527int n_daemonize(void);
529int n_daemonize_ex(int mode);
531pid_t system_nb(const char* command, int* infp, int* outfp);
532#endif
533
535void N_HIDE_STR(char* buf, ...);
536
538char* n_get_file_extension(char path[]);
543#ifdef __cplusplus
544}
545#endif
546
547#endif // header guard
static int mode
void log_environment(int loglevel)
log environment variables at the given log level
Definition n_common.c:232
char * get_prog_name(void)
get running program name
Definition n_common.c:145
void N_HIDE_STR(char *buf,...)
reconstruct hidden string from variadic char arguments
Definition n_common.c:459
int get_computer_name(char *computer_name, size_t len)
get the computer name into the given buffer
Definition n_common.c:70
void sigchld_handler(int sig)
reap zombie processes
Definition n_common.c:253
pid_t system_nb(const char *command, int *infp, int *outfp)
non-blocking system call
Definition n_common.c:390
char * n_get_file_extension(char path[])
get the file extension from a path
Definition n_common.c:480
char * get_prog_dir(void)
get running program directory
Definition n_common.c:113
int n_daemonize_ex(int mode)
daemonize the current process with the given mode flags
Definition n_common.c:293
void n_abort(char const *format,...)
htonl for 64 bits numbers
Definition n_common.c:53
int sigchld_handler_installer()
install signal SIGCHLD handler
Definition n_common.c:267
int n_daemonize(void)
daemonize the current process
Definition n_common.c:284
int file_exist(const char *filename)
test file presence
Definition n_common.c:100
int n_popen(char *cmd, size_t read_buf_size, void **nstr_output, int *ret)
shortcut for popen usage
Definition n_common.c:180
Macro to build enums and their tostring counterparts, a reduced version of https://github....
Generic log system.