/* See LICENSE file for copyright and license details. */ #ifndef LIBSIMPLE_H #define LIBSIMPLE_H #include #include #include #include #include #include #include #include #include #include #include #include #if defined(__GNUC__) && !defined(__clang__) # define _LIBSIMPLE_GCC_ONLY(x) x #else # define _LIBSIMPLE_GCC_ONLY(x) #endif extern int libsimple_default_failure_exit; _LIBSIMPLE_GCC_ONLY(__attribute__((pure, nonnull, warn_unused_result))) void *libsimple_rawmemchr(const void *, int); #ifndef rawmemchr # define rawmemchr libsimple_rawmemchr #endif _LIBSIMPLE_GCC_ONLY(__attribute__((pure, nonnull, warn_unused_result))) void *libsimple_memrchr(const void *, int, size_t); #ifndef memrchr # define memrchr libsimple_memrchr #endif _LIBSIMPLE_GCC_ONLY(__attribute__((pure, nonnull, warn_unused_result))) void *libsimple_rawmemrchr(const void *, int, size_t); #ifndef rawmemrchr # define rawmemrchr libsimple_rawmemrchr #endif _LIBSIMPLE_GCC_ONLY(__attribute__((pure, nonnull, warn_unused_result))) char *libsimple_strchrnul(const char *, int); #ifndef strchrnul # define strchrnul libsimple_strchrnul #endif _LIBSIMPLE_GCC_ONLY(__attribute__((pure, nonnull, warn_unused_result))) static inline char *libsimple_strend(const char *__s) { return strchr(__s, '\0'); } #ifndef strend # define strend libsimple_strend #endif _LIBSIMPLE_GCC_ONLY(__attribute__((pure, nonnull, warn_unused_result))) static inline int libsimple_inchrset(int __c, const char *__s) { return __c && strchr(__s, __c); } #ifndef inchrset # define inchrset libsimple_inchrset #endif _LIBSIMPLE_GCC_ONLY(__attribute__((nonnull, warn_unused_result))) void *libsimple_memdup(const void *, size_t); #ifndef memdup # define memdup libsimple_memdup #endif _LIBSIMPLE_GCC_ONLY(__attribute__((nonnull, warn_unused_result))) char *libsimple_strndup(const char *, size_t); #ifndef strndup # define strndup libsimple_strndup #endif _LIBSIMPLE_GCC_ONLY(__attribute__((warn_unused_result))) static inline void *libsimple_mempcpy(void *__d, const void *__s, size_t __n) { return &((char *)memcpy(__d, __s, __n))[__n]; } #ifndef mempcpy # define mempcpy libsimple_mempcpy #endif #ifndef strdupa # if defined(__GNUC__) || defined(__clang__) # define strdupa(s)\ ({\ const char *__s = (s);\ size_t __n = strlen(__s) + 1;\ char *__r = alloca(__n);\ memcpy(__r, __s, __n);\ }) # endif #endif #ifndef strdupa # if defined(__GNUC__) || defined(__clang__) # define strndupa(s, n)\ ({\ const char *__s = (s);\ size_t __n = (n);\ size_t __m = strlen(__s);\ char *__r;\ __n = __n < __m ? __n : __m;\ __r = alloca(__n + 1);\ memcpy(__r, __s, __n);\ __r[n] = '\0';\ __r;\ }) # endif #endif #ifndef strdupa # if defined(__GNUC__) || defined(__clang__) # define memdupa(s, n)\ ({\ const char *__s = (s);\ size_t __n = (n);\ char *__r = alloca(__n);\ memcpy(__r, __s, __n);\ }) # endif #endif /** * Check whether a NUL-terminated string is encoded in UTF-8 * * @param string The string * @param allow_modified_nul Whether Modified UTF-8 is allowed, which allows a two-byte encoding for NUL * @return 1 if good, 0 on encoding error */ _LIBSIMPLE_GCC_ONLY(__attribute__((pure, nonnull, warn_unused_result))) int libsimple_isutf8(const char *, int); #ifndef isutf8 # define isutf8 libsimple_isutf8 #endif _LIBSIMPLE_GCC_ONLY(__attribute__((nonnull(1, 2), format(printf, 2, 3)))) int libsimple_asprintf(char **, const char *, ...); #ifndef asprintf # define asprintf libsimple_asprintf #endif _LIBSIMPLE_GCC_ONLY(__attribute__((nonnull(1, 2)))) int libsimple_vasprintf(char **, const char *, va_list); #ifndef vasprintf # define vasprintf libsimple_vasprintf #endif #ifndef asprintfa # if defined(__GNUC__) && !defined(__clang__) # define asprintfa(__fmt, ...)\ ({\ const char *__f = (__fmt);\ char *__ret = NULL;\ int __r = snprintf(NULL, 0, __f, __VA_ARGS__);\ if (__r < 0) {\ __ret;\ } else if ((size_t)__r == SIZE_MAX) {\ errno = ENOMEM;\ __ret;\ } else {\ __ret = alloca((size_t)__r + 1);\ sprintf(__ret, __f, __VA_ARGS__);\ __ret;\ }\ }) # endif #endif #ifndef vasprintfa # if defined(__GNUC__) || defined(__clang__) # define vasprintfa(__fmt, __ap)\ ({\ const char *__f = (__fmt);\ va_list __a = (__ap);\ va_list __a2;\ char *__ret = NULL;\ int __r;\ va_copy(__a2, __a);\ __r = vsnprintf(NULL, 0, __f, __a);\ if (__r < 0);\ else if ((size_t)__r == SIZE_MAX) {\ errno = ENOMEM;\ } else {\ __ret = alloca((size_t)__r + 1);\ vsprintf(__ret, __f, __a2);\ }\ va_end(__a2);\ __ret;\ }) # endif #endif _LIBSIMPLE_GCC_ONLY(__attribute__((pure, warn_unused_result))) void *libsimple_memmem(const void *, size_t, const void *, size_t); #ifndef memmem # define memmem libsimple_memmem #endif _LIBSIMPLE_GCC_ONLY(__attribute__((pure, warn_unused_result))) int libsimple_memstarts(const void *, size_t, const void *, size_t); #ifndef memstarts # define memstarts libsimple_memstarts #endif _LIBSIMPLE_GCC_ONLY(__attribute__((pure, warn_unused_result))) int libsimple_memends(const void *, size_t, const void *, size_t); #ifndef memends # define memends libsimple_memends #endif _LIBSIMPLE_GCC_ONLY(__attribute__((pure, nonnull, warn_unused_result))) int libsimple_strstarts(const char *, const char *); #ifndef strstarts # define strstarts libsimple_strstarts #endif _LIBSIMPLE_GCC_ONLY(__attribute__((pure, nonnull, warn_unused_result))) int libsimple_strends(const char *, const char *); #ifndef strends # define strends libsimple_strends #endif _LIBSIMPLE_GCC_ONLY(__attribute__((pure, nonnull, warn_unused_result))) char *libsimple_strcasestr(const char *, const char *); #ifndef strcasestr # define strcasestr libsimple_strcasestr #endif #define malloczn(CLEAR, ...) _libsimple_malloczn((CLEAR), __VA_ARGS__, (size_t)0) #define mallocn(...) malloczn(0, __VA_ARGS__) #define callocn(...) malloczn(1, __VA_ARGS__) _LIBSIMPLE_GCC_ONLY(__attribute__((warn_unused_result))) void *libsimple_vmalloczn(int, size_t, va_list); _LIBSIMPLE_GCC_ONLY(__attribute__((warn_unused_result))) static inline void *libsimple_vmallocn(size_t __n, va_list __ap) { return libsimple_vmalloczn(0, __n, __ap); } _LIBSIMPLE_GCC_ONLY(__attribute__((warn_unused_result))) static inline void *libsimple_vcallocn(size_t __n, va_list __ap) { return libsimple_vmalloczn(1, __n, __ap); } _LIBSIMPLE_GCC_ONLY(__attribute__((warn_unused_result))) static inline void * libsimple_malloczn(int __clear, size_t __n, ...) { va_list __ap; va_start(__ap, __n); return libsimple_vmalloczn(__clear, __n, __ap); va_end(__ap); } _LIBSIMPLE_GCC_ONLY(__attribute__((warn_unused_result))) static inline void * libsimple_mallocn(size_t __n, ...) { va_list __ap; va_start(__ap, __n); return libsimple_vmalloczn(0, __n, __ap); va_end(__ap); } _LIBSIMPLE_GCC_ONLY(__attribute__((warn_unused_result))) static inline void * libsimple_callocn(size_t __n, ...) { va_list __ap; va_start(__ap, __n); return libsimple_vmalloczn(1, __n, __ap); va_end(__ap); } #define reallocn(PTR, ...) _libsimple_reallocn((PTR), __VA_ARGS__, (size_t)0) _LIBSIMPLE_GCC_ONLY(__attribute__((warn_unused_result))) void *libsimple_vreallocn(void *, size_t, va_list); _LIBSIMPLE_GCC_ONLY(__attribute__((warn_unused_result))) static inline void * libsimple_reallocn(void *__ptr, size_t __n, ...) { va_list __ap; va_start(__ap, __n); return libsimple_vreallocn(__ptr, __n, __ap); va_end(__ap); } _LIBSIMPLE_GCC_ONLY(__attribute__((warn_unused_result, returns_nonnull))) void *enmalloc(int, size_t); _LIBSIMPLE_GCC_ONLY(__attribute__((warn_unused_result, returns_nonnull))) void *encalloc(int, size_t, size_t); _LIBSIMPLE_GCC_ONLY(__attribute__((warn_unused_result, returns_nonnull))) void *enrealloc(int, void *, size_t); _LIBSIMPLE_GCC_ONLY(__attribute__((nonnull, warn_unused_result, returns_nonnull))) char *enstrdup(int, const char *); _LIBSIMPLE_GCC_ONLY(__attribute__((nonnull, warn_unused_result, returns_nonnull))) char *enstrndup(int, const char *, size_t); _LIBSIMPLE_GCC_ONLY(__attribute__((warn_unused_result, returns_nonnull))) void *enmemdup(int, const void *, size_t); #define enmalloczn(STATUS, CLEAR, ...) _libsimple_enmalloczn((STATUS), (CLEAR), __VA_ARGS__, (size_t)0) #define enmallocn(STATUS, ...) _libsimple_enmallocn((STATUS), (CLEAR), __VA_ARGS__, (size_t)0) #define encallocn(STATUS, ...) _libsimple_encallocn((STATUS), (CLEAR), __VA_ARGS__, (size_t)0) #define enreallocn(STATUS, PTR, ...) _libsimple_enreallocn((STATUS), (PTR), __VA_ARGS__, (size_t)0) _LIBSIMPLE_GCC_ONLY(__attribute__((warn_unused_result, returns_nonnull))) void *libsimple_envmalloczn(int, int, size_t, va_list); _LIBSIMPLE_GCC_ONLY(__attribute__((warn_unused_result, returns_nonnull))) void *libsimple_envreallocn(int, void *, size_t, va_list); _LIBSIMPLE_GCC_ONLY(__attribute__((warn_unused_result, returns_nonnull))) static inline void *libsimple_envmallocn(int __st, size_t __n, va_list __ap) { return libsimple_envmalloczn(__st, 0, __n, __ap); } _LIBSIMPLE_GCC_ONLY(__attribute__((warn_unused_result, returns_nonnull))) static inline void *libsimple_envcallocn(int __st, size_t __n, va_list __ap) { return libsimple_envmalloczn(__st, 1, __n, __ap); } _LIBSIMPLE_GCC_ONLY(__attribute__((warn_unused_result, returns_nonnull))) static inline void * libsimple_enmalloczn(int __status, int __clear, size_t __n, ...) { va_list __ap; va_start(__ap, __n); return libsimple_envmalloczn(__status, __clear, __n, __ap); va_end(__ap); } _LIBSIMPLE_GCC_ONLY(__attribute__((warn_unused_result, returns_nonnull))) static inline void * libsimple_enmallocn(int __status, size_t __n, ...) { va_list __ap; va_start(__ap, __n); return libsimple_envmalloczn(__status, 0, __n, __ap); va_end(__ap); } _LIBSIMPLE_GCC_ONLY(__attribute__((warn_unused_result, returns_nonnull))) static inline void * libsimple_encallocn(int __status, size_t __n, ...) { va_list __ap; va_start(__ap, __n); return libsimple_envmalloczn(__status, 1, __n, __ap); va_end(__ap); } _LIBSIMPLE_GCC_ONLY(__attribute__((warn_unused_result, returns_nonnull))) static inline void * libsimple_enreallocn(int __status, void *__ptr, size_t __n, ...) { va_list __ap; va_start(__ap, __n); return libsimple_envreallocn(__status, __ptr, __n, __ap); va_end(__ap); } _LIBSIMPLE_GCC_ONLY(__attribute__((warn_unused_result, returns_nonnull))) static inline void *emalloc(size_t __n) { return enmalloc(libsimple_default_failure_exit, __n); } _LIBSIMPLE_GCC_ONLY(__attribute__((warn_unused_result, returns_nonnull))) static inline void *ecalloc(size_t __n, size_t __m) { return encalloc(libsimple_default_failure_exit, __n, __m); } _LIBSIMPLE_GCC_ONLY(__attribute__((warn_unused_result, returns_nonnull))) static inline void *erealloc(void *__ptr, size_t __n) { return enrealloc(libsimple_default_failure_exit, __ptr, __n); } _LIBSIMPLE_GCC_ONLY(__attribute__((nonnull, warn_unused_result, returns_nonnull))) static inline char *estrdup(const char *__s) { return enstrdup(libsimple_default_failure_exit, __s); } _LIBSIMPLE_GCC_ONLY(__attribute__((nonnull, warn_unused_result, returns_nonnull))) static inline char *estrndup(const char *__s, size_t __n) { return enstrndup(libsimple_default_failure_exit, __s, __n); } _LIBSIMPLE_GCC_ONLY(__attribute__((warn_unused_result, returns_nonnull))) static inline void *ememdup(const void *__s, size_t __n) { return enmemdup(libsimple_default_failure_exit, __s, __n); } #define emalloczn(CLEAR, ...) enmalloczn(libsimple_default_failure_exit, (CLEAR), __VA_ARGS__) #define emallocn(...) enmallocn(libsimple_default_failure_exit, __VA_ARGS__) #define ecallocn(...) encallocn(libsimple_default_failure_exit, __VA_ARGS__) #define ereallocn(PTR, ...) enreallocn(libsimple_default_failure_exit, (PTR), __VA_ARGS__) _LIBSIMPLE_GCC_ONLY(__attribute__((warn_unused_result, returns_nonnull))) static inline void *libsimple_evmalloczn(int __clear, size_t __n, va_list __ap) { return libsimple_envmalloczn(libsimple_default_failure_exit, __clear, __n, __ap); } _LIBSIMPLE_GCC_ONLY(__attribute__((warn_unused_result, returns_nonnull))) static inline void *libsimple_evmallocn(size_t __n, va_list __ap) { return libsimple_envcallocn(libsimple_default_failure_exit, __n, __ap); } _LIBSIMPLE_GCC_ONLY(__attribute__((warn_unused_result, returns_nonnull))) static inline void *libsimple_evcallocn(size_t __n, va_list __ap) { return libsimple_envmallocn(libsimple_default_failure_exit, __n, __ap); } _LIBSIMPLE_GCC_ONLY(__attribute__((warn_unused_result, returns_nonnull))) static inline void *libsimple_evreallocn(void *__ptr, size_t __n, va_list __ap) { return libsimple_envreallocn(libsimple_default_failure_exit, __ptr, __n, __ap); } _LIBSIMPLE_GCC_ONLY(__attribute__((warn_unused_result, returns_nonnull))) static inline void * libsimple_emalloczn(int __c, size_t __n, ...) { va_list __ap; va_start(__ap, __n); return libsimple_envmalloczn(libsimple_default_failure_exit, __c, __n, __ap); va_end(__ap); } _LIBSIMPLE_GCC_ONLY(__attribute__((warn_unused_result, returns_nonnull))) static inline void * libsimple_emallocn(size_t __n, ...) { va_list __ap; va_start(__ap, __n); return libsimple_envmalloczn(libsimple_default_failure_exit, 0, __n, __ap); va_end(__ap); } _LIBSIMPLE_GCC_ONLY(__attribute__((warn_unused_result, returns_nonnull))) static inline void * libsimple_ecallocn(size_t __n, ...) { va_list __ap; va_start(__ap, __n); return libsimple_envmalloczn(libsimple_default_failure_exit, 1, __n, __ap); va_end(__ap); } _LIBSIMPLE_GCC_ONLY(__attribute__((warn_unused_result, returns_nonnull))) static inline void * libsimple_ereallocn(void *__p, size_t __n, ...) { va_list __ap; va_start(__ap, __n); return libsimple_envreallocn(libsimple_default_failure_exit, __p, __n, __ap); va_end(__ap); } _LIBSIMPLE_GCC_ONLY(__attribute__((nonnull))) static inline char * getenv_ne(const char *__name) { char *__env = getenv(__name); return (__env && *__env) ? __env : NULL; } _LIBSIMPLE_GCC_ONLY(__attribute__((nonnull))) int vputenvf(const char *, va_list); _LIBSIMPLE_GCC_ONLY(__attribute__((nonnull))) void envputenvf(int, const char *, va_list); _LIBSIMPLE_GCC_ONLY(__attribute__((nonnull, format(printf, 1, 2)))) static inline int putenvf(const char *__fmt, ...) { va_list __ap; va_start(__ap, __fmt); return vputenvf(__fmt, __ap); va_end(__ap); } _LIBSIMPLE_GCC_ONLY(__attribute__((nonnull, format(printf, 1, 2)))) static inline void eputenvf(const char *__fmt, ...) { va_list __ap; va_start(__ap, __fmt); envputenvf(1, __fmt, __ap); va_end(__ap); } _LIBSIMPLE_GCC_ONLY(__attribute__((nonnull))) static inline void evputenvf(const char *__fmt, va_list __ap) { envputenvf(libsimple_default_failure_exit, __fmt, __ap); } _LIBSIMPLE_GCC_ONLY(__attribute__((nonnull, format(printf, 2, 3)))) static inline void enputenvf(int __status, const char *__fmt, ...) { va_list __ap; va_start(__ap, __fmt); envputenvf(__status, __fmt, __ap); va_end(__ap); } _LIBSIMPLE_GCC_ONLY(__attribute__((nonnull(1)))) void vweprintf(const char *, va_list); _LIBSIMPLE_GCC_ONLY(__attribute__((nonnull(1), format(printf, 1, 2), noreturn))) static inline void eprintf(const char *__fmt, ...) { va_list __ap; va_start(__ap, __fmt); vweprintf(__fmt, __ap); va_end(__ap); exit(libsimple_default_failure_exit); } _LIBSIMPLE_GCC_ONLY(__attribute__((nonnull(1), noreturn))) static inline void veprintf(const char *__fmt, va_list __ap) { vweprintf(__fmt, __ap); exit(libsimple_default_failure_exit); } _LIBSIMPLE_GCC_ONLY(__attribute__((nonnull(2), format(printf, 2, 3), noreturn))) static inline void enprintf(int __status, const char *__fmt, ...) { va_list __ap; va_start(__ap, __fmt); vweprintf(__fmt, __ap); va_end(__ap); exit(__status); } _LIBSIMPLE_GCC_ONLY(__attribute__((nonnull(2), noreturn))) static inline void venprintf(int __status, const char *__fmt, va_list __ap) { vweprintf(__fmt, __ap); exit(__status); } _LIBSIMPLE_GCC_ONLY(__attribute__((nonnull(1), format(printf, 1, 2)))) static inline void weprintf(const char *__fmt, ...) { va_list __ap; va_start(__ap, __fmt); vweprintf(__fmt, __ap); va_end(__ap); } #endif