/* $Id$ * Include file with general macros and typedefs used through Captive project * Copyright (C) 2002 Jan Kratochvil * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; exactly version 2 of June 1991 is required * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _CAPTIVE_MACROS_H #define _CAPTIVE_MACROS_H 1 #include #include #include #include /* for memset() */ #include #include #include /* for g_snprintf(); glib-2.2.x+ it also has in */ G_BEGIN_DECLS /** * CAPTIVE_FAKEUSE: * * Prevent 'might be used uninitialized' warning. * Macro will fakes the use of the variable as sometimes GCC can't code flow * analyse #C correctly. * * * * g_some_type some_variable CAPTIVE_FAKEUSE; * * */ #define CAPTIVE_FAKEUSE =0 /** * 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 (%NULL assignment effect). * * 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))) /** * 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 (%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))) /** * captive_renewn: * @objp: Variable with the pointer to the objects wished to be reallocated. * Value %NULL is permitted (g_malloc() effect). * @n: Numbers of objects to be allocated. Value %0 is permitted (g_free() effect). * * Macro to reallocate the original memory stored in @objp * to the size @n objects of type *@objp and to assign the resulting pointer to @objp. * New allocated space may contain garbage. Both @objp and @n can be nonexclusively * 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) ({ \ typeof(&(objp)) _captive_renewn_objpp=&(objp); \ *_captive_renewn_objpp=g_renew(typeof(*(objp)),*_captive_renewn_objpp,(n)); \ (*_captive_renewn_objpp); \ }) /** * captive_new: * @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(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)) /** * captive_new0: * @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(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. * * Automatically determines the size of @objp. * Equivalent to objp=va_arg(ap,typeof(objp)) call. * * @Returns: Initialized @objp value. */ #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 #endif /* _CAPTIVE_MACROS_H */