Nilorea Library
C utilities for networking, threading, graphics
Loading...
Searching...
No Matches
n_common.h
Go to the documentation of this file.
1
8#ifndef __NILOREA_COMMONS__
9#define __NILOREA_COMMONS__
10
11#ifdef __cplusplus
12extern "C" {
13#endif
14
20#include <sys/types.h>
21#include <unistd.h>
22#include <stdlib.h>
23#include <malloc.h>
24#include <errno.h>
25#include <string.h>
26#include <strings.h>
27#include <stdint.h>
28#include <nilorea/n_log.h>
29#include <nilorea/n_enum.h>
30
32#if defined(_WIN32) || defined(_WIN64)
33#ifndef __windows__
34#define __windows__
35#endif
36#ifndef WEXITSTATUS
37#define WEXITSTATUS(w) (((w) >> 8) & 0xff)
38#endif
39#ifndef WIFEXITED
40#define WIFEXITED(w) (((w) & 0xff) == 0)
41#endif
42#else
43#include <alloca.h>
44#include <signal.h>
45#endif
46
48#define __EXTENSIONS__
49
50#if defined(__GNUC__) && __GNUC__ >= 7
52#define FALL_THROUGH __attribute__((fallthrough))
53#else
55#define FALL_THROUGH /* fall through */ \
56 ((void)0)
57#endif /* __GNUC__ >= 7 */
58
59#if defined(_WIN32) || defined(_WIN64)
60#if defined(_WIN64)
62#define ENV_64BITS
63#else
65#define ENV_32BITS
66#endif
67#endif
68
69#if !defined(ENV_32BITS) || !defined(ENV_64BITS)
70#if defined(__GNUC__)
71#if defined(__x86_64__) || defined(__ppc64__)
73#define __ENVBITS __ENV_64BITS
74#else
76#define __ENVBITS __ENV_32BITS
77#endif
78#endif
79#endif
80
82#define BYTEORDER_LITTLE_ENDIAN 0 // Little endian machine.
84#define BYTEORDER_BIG_ENDIAN 1 // Big endian machine.
85
86#ifndef BYTEORDER_ENDIAN
87// Detect with GCC 4.6's macro.
88#if defined(__BYTE_ORDER__)
89#if (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)
90#define BYTEORDER_ENDIAN BYTEORDER_LITTLE_ENDIAN
91#elif (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)
92#define BYTEORDER_ENDIAN BYTEORDER_BIG_ENDIAN
93#else
94#define BYTEORDER_ENDIAN BYTEORDER_LITTLE_ENDIAN
95#warning "Unknown machine byteorder endianness detected. User needs to define BYTEORDER_ENDIAN."
96#warning "Setting default to BYTEORDER_LITTLE_ENDIAN"
97#endif
98// Detect with GLIBC's endian.h.
99#elif defined(__GLIBC__)
100#include <endian.h>
101#if (__BYTE_ORDER == __LITTLE_ENDIAN)
102#define BYTEORDER_ENDIAN BYTEORDER_LITTLE_ENDIAN
103#elif (__BYTE_ORDER == __BIG_ENDIAN)
104#define BYTEORDER_ENDIAN BYTEORDER_BIG_ENDIAN
105#else
106#define BYTEORDER_ENDIAN BYTEORDER_LITTLE_ENDIAN
107#warning "Unknown machine byteorder endianness detected. User needs to define BYTEORDER_ENDIAN."
108#warning "Setting default to BYTEORDER_LITTLE_ENDIAN"
109#endif
110// Detect with _LITTLE_ENDIAN and _BIG_ENDIAN macro.
111#elif defined(_LITTLE_ENDIAN) && !defined(_BIG_ENDIAN)
112#define BYTEORDER_ENDIAN BYTEORDER_LITTLE_ENDIAN
113#elif defined(_BIG_ENDIAN) && !defined(_LITTLE_ENDIAN)
114#define BYTEORDER_ENDIAN BYTEORDER_BIG_ENDIAN
115// Detect with architecture macros.
116#elif defined(__sparc) || defined(__sparc__) || defined(_POWER) || defined(__powerpc__) || defined(__ppc__) || defined(__hpux) || defined(__hppa) || defined(_MIPSEB) || defined(_POWER) || defined(__s390__)
117#define BYTEORDER_ENDIAN BYTEORDER_BIG_ENDIAN
118#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__)
119#define BYTEORDER_ENDIAN BYTEORDER_LITTLE_ENDIAN
120#elif defined(_MSC_VER) && (defined(_M_ARM) || defined(_M_ARM64))
121#define BYTEORDER_ENDIAN BYTEORDER_LITTLE_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#endif
128
129#if defined(__windows__)
130/* typedefine for unsigned category for basic native types */
132typedef unsigned int uint;
134typedef unsigned long ulong;
136typedef unsigned short ushort;
138typedef unsigned char uchar;
139#endif
140
142#ifdef _MSVC_VER
143#define FORCE_INLINE __forceinline
144#elif defined(__linux__) || defined(__windows__)
145#define FORCE_INLINE static inline __attribute__((always_inline))
146#else
147#define FORCE_INLINE static inline __attribute__((always_inline))
148#endif
149
151#ifndef true
152#define true (1 == 1)
153#endif
154
156#ifndef TRUE
157#define TRUE true
158#endif
159
161#ifndef false
162#define false (1 == 0)
163#endif
164
166#ifndef FALSE
167#define FALSE false
168#endif
169
171#ifndef EMPTY
172#define EMPTY 2
173#endif
174
176#define _str(__PTR) ((__PTR) ? (__PTR) : "NULL")
178#define _strp(__PTR) ((__PTR) ? (__PTR) : NULL)
180#define _strw(__PTR) ((__PTR) ? (__PTR) : " ")
182#define _nstr(__PTR) ((__PTR && __PTR->data) ? (__PTR->data) : "NULL")
184#define _nstrp(__PTR) ((__PTR && __PTR->data) ? (__PTR->data) : NULL)
185
187#define Malloc(__ptr, __struct, __size) \
188 { \
189 int __n_errno = 0; \
190 errno = 0; \
191 __ptr = (__struct*)calloc(__size, sizeof(__struct)); \
192 __n_errno = errno; \
193 if (!__ptr) { \
194 n_log(LOG_ERR, "( %s *)calloc( %ld , sizeof( %s ) ) %s at line %d of %s \n", #__ptr, __size, #__struct, (__n_errno == 0) ? "malloc error" : strerror(__n_errno), __LINE__, __FILE__); \
195 } \
196 }
197
199#define Alloca(__ptr, __size) \
200 { \
201 int __n_errno = 0; \
202 errno = 0; \
203 __ptr = alloca(__size); \
204 __n_errno = errno; \
205 if (!__ptr) { \
206 n_log(LOG_ERR, "%s=alloca( %d ) %s at line %d of %s \n", #__ptr, __size, (__n_errno == 0) ? "alloca error" : strerror(__n_errno), __LINE__, __FILE__); \
207 } else { \
208 memset(__ptr, 0, __size); \
209 } \
210 }
211
213#define Realloc(__ptr, __struct, __size) \
214 { \
215 int __n_errno = 0; \
216 errno = 0; \
217 void* __new_ptr = (__struct*)realloc(__ptr, __size * sizeof(__struct)); \
218 __n_errno = errno; \
219 if (!__new_ptr) { \
220 n_log(LOG_ERR, "( %s *)realloc( %s * sizeof( %d ) ) %s at line %d of %s \n", #__ptr, #__struct, __size, (__n_errno == 0) ? "realloc error" : strerror(__n_errno), __LINE__, __FILE__); \
221 } else { \
222 __ptr = __new_ptr; \
223 } \
224 }
225
227#define Reallocz(__ptr, __struct, __old_size, __size) \
228 { \
229 int __n_errno = 0; \
230 errno = 0; \
231 void* __new_ptr = (__struct*)realloc(__ptr, __size); \
232 __n_errno = errno; \
233 if (!__new_ptr) { \
234 n_log(LOG_ERR, "( %s *)realloc( %s * sizeof( %d ) ) %s at line %d of %s \n", #__ptr, #__struct, __size, (__n_errno == 0) ? "realloc error" : strerror(__n_errno), __LINE__, __FILE__); \
235 } else { \
236 __ptr = __new_ptr; \
237 if (__size > __old_size) memset((__ptr + __old_size), 0, __size - __old_size); \
238 } \
239 }
240
242#define Free(__ptr) \
243 if (__ptr) { \
244 free(__ptr); \
245 __ptr = NULL; \
246 } else { \
247 n_log(LOG_DEBUG, "Free( %s ) already done or NULL at line %d of %s \n", #__ptr, __LINE__, __FILE__); \
248 }
249
251#define FreeNoLog(__ptr) \
252 if (__ptr) { \
253 free(__ptr); \
254 __ptr = NULL; \
255 }
256
258#define __n_assert(__ptr, __ret) \
259 if (!(__ptr)) { \
260 n_log(LOG_DEBUG, "if( !(%s) ) assert at line %d of %s", #__ptr, __LINE__, __FILE__); \
261 __ret; \
262 }
263
265#define CALL_RETRY(__retvar, __expression, __max_tries, __delay) ({ \
266 int __nb_retries = 0; \
267 do { \
268 __retvar = (__expression); \
269 __nb_retries++; \
270 if (__retvar == -1 && errno == EINTR && __nb_retries < __max_tries) \
271 usleep(__delay); \
272 } while (__retvar == -1 && errno == EINTR && __nb_retries < __max_tries); \
273 __nb_retries; \
274})
275
277#define next_odd(__val) ((__val) % 2 == 0) ? (__val) : (__val + 1)
278
280#define next_even(__val) ((__val) % 2 == 0) ? (__val + 1) : (__val)
281
283#define init_error_check() \
284 static int ___error__check_flag = FALSE;
285
287#define ifnull if( !
288
290#define ifzero if( 0 ==
291
293#define iffalse if( FALSE ==
294
296#define iftrue if( TRUE ==
297
299#define checkerror() \
300 if (___error__check_flag == TRUE) { \
301 n_log(LOG_ERR, "checkerror return false at line %d of %s", __LINE__, __FILE__); \
302 goto error; \
303 }
304
306#define endif ){ \
307 ___error__check_flag = TRUE; \
308 n_log(LOG_ERR, "First err was at line %d of %s", __LINE__, __FILE__); \
309 }
310
312#define get_error() \
313 (___error__check_flag == TRUE)
314
316#define equal_if(__a, __cond, __b) \
317 if ((__a)__cond(__b)) { \
318 __a = __b; \
319 }
320
321// #define RWLOCK_DEBUG 1
322#ifdef RWLOCK_DEBUG
324#define RWLOCK_LOGLEVEL LOG_DEBUG
325#else
327#define RWLOCK_LOGLEVEL LOG_NULL
328#endif
329
331#define init_lock(__rwlock_mutex) \
332 ({ \
333 pthread_rwlockattr_t __attr; \
334 pthread_rwlockattr_init(&__attr); \
335 int __ret = 0; \
336 do { \
337 n_log(RWLOCK_LOGLEVEL, "init_lock %s", #__rwlock_mutex); \
338 __rwlock_mutex = (pthread_rwlock_t)PTHREAD_RWLOCK_INITIALIZER; \
339 __ret = pthread_rwlock_init(&(__rwlock_mutex), &__attr); \
340 if (__ret != 0) { \
341 n_log(LOG_ERR, "Error %s while initializing %s at %s:%s:%d", strerror(__ret), #__rwlock_mutex, __FILE__, __func__, __LINE__); \
342 } \
343 pthread_rwlockattr_destroy(&__attr); \
344 } while (0); \
345 __ret; \
346 })
347
349#define read_lock(__rwlock_mutex) \
350 ({ \
351 int __ret = 0; \
352 do { \
353 n_log(RWLOCK_LOGLEVEL, "read lock %s", #__rwlock_mutex); \
354 __ret = pthread_rwlock_rdlock(&(__rwlock_mutex)); \
355 if (__ret != 0) { \
356 n_log(LOG_ERR, "Error %s while read locking %s at %s:%s:%d", strerror(__ret), #__rwlock_mutex, __FILE__, __func__, __LINE__); \
357 } \
358 } while (0); \
359 __ret; \
360 })
361
363#define write_lock(__rwlock_mutex) \
364 ({ \
365 int __ret = 0; \
366 do { \
367 n_log(RWLOCK_LOGLEVEL, "write lock %s", #__rwlock_mutex); \
368 __ret = pthread_rwlock_wrlock(&(__rwlock_mutex)); \
369 if (__ret != 0) { \
370 n_log(LOG_ERR, "Error %s while write locking %s at %s:%s:%d", strerror(__ret), #__rwlock_mutex, __FILE__, __func__, __LINE__); \
371 } \
372 } while (0); \
373 __ret; \
374 })
375
377#define unlock(__rwlock_mutex) \
378 ({ \
379 int __ret = 0; \
380 do { \
381 n_log(RWLOCK_LOGLEVEL, "unlock lock %s", #__rwlock_mutex); \
382 __ret = pthread_rwlock_unlock(&(__rwlock_mutex)); \
383 if (__ret != 0) { \
384 n_log(LOG_ERR, "Error %s while unlocking %s at %s:%s:%d", strerror(__ret), #__rwlock_mutex, __FILE__, __func__, __LINE__); \
385 } \
386 } while (0); \
387 __ret; \
388 })
390#define rw_lock_destroy(__rwlock_mutex) \
391 ({ \
392 int __ret = 0; \
393 do { \
394 n_log(RWLOCK_LOGLEVEL, "destroy lock %s", #__rwlock_mutex); \
395 __ret = pthread_rwlock_destroy(&(__rwlock_mutex)); \
396 if (__ret != 0) { \
397 n_log(LOG_ERR, "Error %s while destroying %s at %s:%s:%d", strerror(__ret), #__rwlock_mutex, __FILE__, __func__, __LINE__); \
398 } \
399 } while (0); \
400 __ret; \
401 })
402
404#define SET 1234
406#define GET 4321
408#define DEFAULT 1000
410#define RUNNING 1001
412#define STOPWANTED 1002
414#define STOPPED 1003
416#define PAUSED 1004
417
419#define randomize() \
420 { \
421 srand((unsigned)time(NULL)); \
422 rand(); \
423 }
424
425#ifndef MIN
427#define MIN(a, b) (((a) < (b)) ? (a) : (b))
428#endif
429#ifndef MAX
431#define MAX(a, b) (((a) > (b)) ? (a) : (b))
432#endif
433
435#define CONCAT_BUILDER(a, b) a##b
437#define CONCAT(a, b) CONCAT_BUILDER(a, b)
438
439#if (BYTEORDER_ENDIAN == BYTEORDER_LITTLE_ENDIAN)
441#define htonll(x) (x)
443#define ntohll(x) (x)
444#else
446#define htonll(x) (((uint64_t)htonl((x) & 0xFFFFFFFF) << 32) | htonl((x) >> 32))
448#define ntohll(x) (((uint64_t)ntohl((x) & 0xFFFFFFFF) << 32) | ntohl((x) >> 32))
449#endif
450
451/* exit and print log to stderr */
452void n_abort(char const* format, ...);
453
454int get_computer_name(char* computer_name, size_t len);
455
456/* get running program name */
457char* get_prog_name(void);
458
459/* get running program directory */
460char* get_prog_dir(void);
461
462/* test file presence*/
463int file_exist(const char* filename);
464
465/* shortcut for popen usage */
466int n_popen(char* cmd, size_t read_buf_size, void** nstr_output, int* ret);
467
468/* log environnement */
469void log_environment(int loglevel);
470
471#ifndef __windows__
472/* reap zombie processes */
473void sigchld_handler(int sig);
474/* install signal SIGCHLD handler */
477#define N_DAEMON_NO_CLOSE 2
479#define N_DAEMON_NO_STD_REDIRECT 4
481#define N_DAEMON_NO_DOUBLE_FORK 8
483#define N_DAEMON_NO_SETSID 16
485#define N_DAEMON_NO_UMASK 32
487#define N_DAEMON_NO_CHDIR 64
489#define N_DAEMON_NO_SIGCHLD_IGN 128
491#define N_DAEMON_NO_SIGCHLD_HANDLER 256
492/* daemonize */
493int n_daemonize(void);
494/* daemonize */
495int n_daemonize_ex(int mode);
496/* non blocking system call */
497pid_t system_nb(const char* command, int* infp, int* outfp);
498#endif
499
500/* reconstruct hidden string */
501void N_HIDE_STR(char* buf, ...);
502
503char* n_get_file_extension(char path[]);
508#ifdef __cplusplus
509}
510#endif
511
512#endif // header guard
void log_environment(int loglevel)
log environment variables in syslog
Definition n_common.c:243
char * get_prog_name(void)
get current program name
Definition n_common.c:127
void N_HIDE_STR(char *buf,...)
store a hidden version of a string
Definition n_common.c:429
int get_computer_name(char *computer_name, size_t len)
abort program with a text
Definition n_common.c:55
void sigchld_handler(int sig)
Handles SIGCHLD issues when forking.
Definition n_common.c:212
pid_t system_nb(const char *command, int *infp, int *outfp)
Non blocking system call.
Definition n_common.c:361
char * n_get_file_extension(char path[])
get extension of path+filename
Definition n_common.c:450
char * get_prog_dir(void)
get current program running directory
Definition n_common.c:95
int n_daemonize_ex(int mode)
Daemonize program.
Definition n_common.c:263
void n_abort(char const *format,...)
abort program with a text
Definition n_common.c:38
int sigchld_handler_installer()
install signal SIGCHLD handler to reap zombie processes
Definition n_common.c:226
int n_daemonize(void)
Daemonize program.
Definition n_common.c:254
int file_exist(const char *filename)
test if file exist and if it's readable
Definition n_common.c:82
Macro to build enums and their tostring counterparts, a reduced version of https://github....
Generic log system.