X-Git-Url: http://git.jankratochvil.net/?a=blobdiff_plain;f=src%2Flibcaptive%2Finclude%2Fcaptive%2Fmacros.h;h=8292a8f76b0e7ab4e67bd578f7ddf9cce194b2c1;hb=a2dd38f86df22c46ae18f3ad7d9850eaacb02b92;hp=58d0971c8728a6e5cc7d99ea57f9eba25800c8a8;hpb=2abdd1d7d723cd2a874b658cfe7f2d68461dd572;p=captive.git diff --git a/src/libcaptive/include/captive/macros.h b/src/libcaptive/include/captive/macros.h index 58d0971..8292a8f 100644 --- a/src/libcaptive/include/captive/macros.h +++ b/src/libcaptive/include/captive/macros.h @@ -24,6 +24,10 @@ #include #include #include +#include /* for memset() */ +#include +#include +#include /* for g_snprintf(); glib-2.2.x+ it also has in */ G_BEGIN_DECLS @@ -48,12 +52,13 @@ G_BEGIN_DECLS * captive_newn: * @objp: Variable with the pointer to the objects wished to be allocated. * Original value is discarded. - * @n: Numbers of objects to be allocated. Value %0 is permitted (g_free() effect). + * @n: Numbers of objects to be allocated. Value %0 is permitted (%NULL assignment effect). * - * Macto to allocate @n objects of type *@objp and to assign the resulting pointer to @objp. + * Macro to allocate @n objects of type *@objp and to assign the resulting pointer to @objp. * Allocated memory may contain garbage. * * @Returns: Initialized @objp value as the memory of size #sizeof(typeof(*objp))*n. + * Value %NULL is returned iff @n==%0; */ #define captive_newn(objp,n) ((objp)=g_new(typeof(*(objp)),(n))) @@ -62,12 +67,13 @@ G_BEGIN_DECLS * captive_new0n: * @objp: Variable with the pointer to the objects wished to be allocated and precleared. * Original value is discarded. - * @n: Numbers of objects to be allocated. Value %0 is permitted (g_free() effect). + * @n: Numbers of objects to be allocated. Value %0 is permitted (%NULL assignment effect). * * Macro to allocate @n objects of type *@objp and to assign the resulting pointer to @objp. * Allocated memory is precleared. * * @Returns: Initialized @objp value as the cleared memory of size #sizeof(typeof(*objp))*n. + * Value %NULL is returned iff @n==%0; */ #define captive_new0n(objp,n) ((objp)=g_new0(typeof(*(objp)),(n))) @@ -84,8 +90,13 @@ G_BEGIN_DECLS * passed as zero. * * @Returns: Initialized @objp value as the memory of size #sizeof(typeof(*objp))*n. + * Value %NULL is returned iff @n==%0; */ -#define captive_renewn(objp,n) ((objp)=g_renew(typeof(*(objp)),(objp),(n))) +#define captive_renewn(objp,n) ({ \ + typeof(&(objp)) _captive_renewn_objpp=&(objp); \ + *_captive_renewn_objpp=g_renew(typeof(*(objp)),*_captive_renewn_objpp,(n)); \ + (*_captive_renewn_objpp); \ + }) /** @@ -93,10 +104,11 @@ G_BEGIN_DECLS * @objp: Variable with the pointer to the object wished to be allocated. * Original value is discarded. * - * Macto to allocate one object of type *@objp and to assign the resulting pointer to @objp. + * Macro to allocate one object of type *@objp and to assign the resulting pointer to @objp. * Allocated memory may contain garbage. Equivalent to captive_newn(objp,1) call. * * @Returns: Initialized @objp value as the memory of size #sizeof(typeof(*objp)). + * Value %NULL is never returned. */ #define captive_new(objp) (captive_newn((objp),1)) @@ -110,11 +122,112 @@ G_BEGIN_DECLS * Allocated memory is precleared. Equivalent to captive_new0n(objp,1) call. * * @Returns: Initialized @objp value as the cleared memory of size #sizeof(typeof(*objp)). + * Value %NULL is never returned. */ #define captive_new0(objp) (captive_new0n((objp),1)) /** + * captive_newn_alloca: + * @objp: Variable with the pointer to the objects wished to be allocated. + * Original value is discarded. + * @n: Numbers of objects to be allocated. Value %0 is permitted (%NULL assignment effect). + * + * Macro to allocate @n objects of type *@objp and to assign the resulting pointer to @objp. + * Allocated memory may contain garbage. + * + * Memory is allocated on the stack frame by g_alloca() and it will be automatically deallocated + * during exit of current function (or current block if variable sized variables present there). + * You cannot deallocate or reallocate such memory in any other way. + * + * @Returns: Initialized @objp value as the memory of size #sizeof(typeof(*objp))*n. + * Value %NULL is returned iff @n==%0; + */ +#define captive_newn_alloca(objp,n) ({ \ + gsize _captive_newn_alloca_n=(n); \ + /* Fix 'g_alloca(0)!=NULL': */ \ + ((objp)=(!_captive_newn_alloca_n ? NULL : g_alloca(sizeof(*(objp))*_captive_newn_alloca_n))); \ + }) + + +/** + * captive_new0n_alloca: + * @objp: Variable with the pointer to the objects wished to be allocated and precleared. + * Original value is discarded. + * @n: Numbers of objects to be allocated. Value %0 is permitted (%NULL assignment effect). + * + * Macro to allocate @n objects of type *@objp and to assign the resulting pointer to @objp. + * Allocated memory is precleared. + * + * Memory is allocated on the stack frame by g_alloca() and it will be automatically deallocated + * during exit of current function (or current block if variable sized variables present there). + * You cannot deallocate or reallocate such memory in any other way. + * + * @Returns: Initialized @objp value as the cleared memory of size #sizeof(typeof(*objp))*n. + * Value %NULL is returned iff @n==%0; + */ +#define captive_new0n_alloca(objp,n) ({ \ + typeof(&(objp)) _captive_new0n_alloca_objpp=&(objp); \ + captive_newn_alloca(*_captive_new0n_alloca_objpp,(n)); \ + CAPTIVE_MEMZERO(*_captive_new0n_alloca_objpp); \ + (*_captive_new0n_alloca_objpp); \ + }) + + +/** + * captive_new_alloca: + * @objp: Variable with the pointer to the object wished to be allocated. + * Original value is discarded. + * + * Macro to allocate one object of type *@objp and to assign the resulting pointer to @objp. + * Allocated memory may contain garbage. Equivalent to captive_newn_alloca(objp,1) call. + * + * Memory is allocated on the stack frame by g_alloca() and it will be automatically deallocated + * during exit of current function (or current block if variable sized variables present there). + * You cannot deallocate or reallocate such memory in any other way. + * + * @Returns: Initialized @objp value as the memory of size #sizeof(typeof(*objp)). + * Value %NULL is never returned. + */ +#define captive_new_alloca(objp) (captive_newn_alloca((objp),1)) + + +/** + * captive_new0_alloca: + * @objp: Variable with the pointer to the object wished to be allocated and precleared. + * Original value is discarded. + * + * Macro to allocate one object of type *@objp and to assign the resulting pointer to @objp. + * Allocated memory is precleared. Equivalent to captive_new0n_alloca(objp,1) call. + * + * @Returns: Initialized @objp value as the cleared memory of size #sizeof(typeof(*objp)). + */ +#define captive_new0_alloca(objp) (captive_new0n_alloca((objp),1)) + + +/** + * captive_memdup: + * @destp: Variable with the pointer to the target object wished to be allocated. + * Original value is discarded. + * @srcp: Pointer to the source object to be copied to @destp. + * + * Macro to similiar to g_memdup() but the object size is detected automatically. + * Size of @destp object and @srcp object must be the same. + * + * You must free the allocated memory of @destp by g_free(). + * + * @Returns: Initialized @destp value as the copied memory of size #sizeof(typeof(*srcp)). + */ +#define captive_memdup(destp,srcp) ({ \ + typeof(&(destp)) _captive_captive_memdup_destpp=&(destp); \ + g_assert(sizeof(*(destp))==sizeof(*(srcp))); \ + captive_new(*_captive_captive_memdup_destpp); \ + memcpy(*_captive_captive_memdup_destpp,(srcp),sizeof(*(srcp))); \ + (*_captive_captive_memdup_destpp); \ + }) + + +/** * captive_va_arg: * @objp: Variable to be filled from the next argument of @ap. * @ap: Initialized #va_list type. @@ -126,6 +239,128 @@ G_BEGIN_DECLS */ #define captive_va_arg(objp,ap) ((objp)=va_arg((ap),typeof(objp))) + +/** + * CAPTIVE_MEMZERO: + * @objp: Pointer to the variable to be cleared. + * + * Clears the sizeof(*@objp) bytes of the given pointer with memset(). + * Pass _pointer_ to the object to be cleared. + */ +#define CAPTIVE_MEMZERO(objp) (memset((objp),0,sizeof(*(objp)))) + + +/** + * captive_printf_alloca: + * @format: Format string. See the sprintf() documentation. + * @args...: Arguments for @format. See the sprintf() documentation. + * + * Format the given format string @format as in sprintf(). + * Output buffer is allocated automatically and it does not need to be deallocated + * manually as it is managed by g_alloca(). + * + * @Returns: Formatted output string located in g_alloca() memory. + */ +#define captive_printf_alloca(format,args...) ({ \ + gsize _captive_printf_alloca_size=captive_nv_printf_string_upper_bound((format) , ## args); \ + gchar *_captive_printf_alloca_r=g_alloca(_captive_printf_alloca_size); \ + g_snprintf(_captive_printf_alloca_r,_captive_printf_alloca_size,(format) , ## args); \ + (const gchar *)_captive_printf_alloca_r; \ + }) +static inline gsize captive_nv_printf_string_upper_bound(const gchar *format,...) G_GNUC_PRINTF(1,0) G_GNUC_UNUSED; +static inline gsize captive_nv_printf_string_upper_bound(const gchar *format,...) +{ +va_list ap; +gsize r; + + va_start(ap,format); + r=g_printf_string_upper_bound(format,ap); + va_end(ap); + return r; +} + + +/** + * captive_strdup_alloca: + * @string: #const #gchar * string to duplicate. + * + * Macro to do g_strdup() equivalent in g_alloca() style. + * + * Memory is allocated on the stack frame by g_alloca() and it will be automatically deallocated + * during exit of current function (or current block if variable sized variables present there). + * You cannot deallocate or reallocate such memory in any other way. + * + * @Returns: Duplicated @string. You may modify its items if the length is not changed. + */ +#define captive_strdup_alloca(string) ({ \ + const gchar *_captive_strdup_alloca_string=(string); \ + const gchar *_captive_strdup_alloca_r=g_alloca(strlen(_captive_strdup_alloca_string)+1); \ + strcpy((gchar *)_captive_strdup_alloca_r,_captive_strdup_alloca_string); \ + (const gchar *)(_captive_strdup_alloca_r); \ + }) + + +/** + * CAPTIVE_ROUND_DOWN: + * @pointer: Arbitrary pointer type. + * @fragment: Amount of 'sizeof(char)' to align @pointer down to. + * This size will be typically a power of 2. + * Value less or equal to %0 is forbidden. + * + * General pointer down-rounding macro. Already aligned pointer is left as is. + * + * glib NOTE: YOU MAY NOT STORE POINTERS IN INTEGERS. + * + * @Returns: Down-rounded @pointer to the integer multiple of @fragment. + * Resulting pointer has the same type as @pointer. + */ +#define CAPTIVE_ROUND_DOWN(pointer,fragment) \ + ((typeof(pointer))(((guint32)(pointer))-CAPTIVE_ROUND_DOWN_EXCEEDING((pointer),(fragment)))) +#define CAPTIVE_ROUND_DOWN64(pointer,fragment) \ + ((typeof(pointer))(((guint64)(pointer))-CAPTIVE_ROUND_DOWN_EXCEEDING64((pointer),(fragment)))) + + +/** + * CAPTIVE_ROUND_DOWN_EXCEEDING: + * @pointer: Arbitrary pointer type. + * @fragment: Amount of 'sizeof(char)' to detect down-alignment amount of @pointer for. + * This size will be typically a power of 2. + * Value less or equal to %0 is forbidden. + * + * Detects current non-aligned amount of data exceeding over integer multiple of @fragment. + * It will return value %0 for an aligned pointer. + * + * glib NOTE: YOU MAY NOT STORE POINTERS IN INTEGERS. + * + * @Returns: #gsize typed number of bytes exceeding over integer multiple of @fragment. + */ +#define CAPTIVE_ROUND_DOWN_EXCEEDING(pointer,fragment) \ + ((gsize)(((guint32)(pointer))%(fragment))) +#define CAPTIVE_ROUND_DOWN_EXCEEDING64(pointer,fragment) \ + ((gsize)(((guint64)(pointer))%(fragment))) + + +/** + * CAPTIVE_ROUND_UP: + * @pointer: Arbitrary pointer type. + * @fragment: Amount of 'sizeof(char)' to align @pointer up to. + * This size will be typically a power of 2. + * Value less or equal to %0 is forbidden. + * + * General pointer up-rounding macro. Already aligned pointer is left as is. + * + * glib NOTE: YOU MAY NOT STORE POINTERS IN INTEGERS. + * + * @Returns: Up-rounded @pointer to the integer multiple of @fragment. + * Resulting pointer has the same type as @pointer. + */ +#define CAPTIVE_ROUND_UP(pointer,fragment) \ + /* new retyping as 'pointer' gets passed as 'char *' to CAPTIVE_ROUND_DOWN(). */ \ + ((typeof(pointer))(CAPTIVE_ROUND_DOWN(((guint32)(pointer))+(fragment)-1,(fragment)))) +#define CAPTIVE_ROUND_UP64(pointer,fragment) \ + /* new retyping as 'pointer' gets passed as 'char *' to CAPTIVE_ROUND_DOWN(). */ \ + ((typeof(pointer))(CAPTIVE_ROUND_DOWN64(((guint64)(pointer))+(fragment)-1,(fragment)))) + G_END_DECLS