Initial original import from: fuse-2.4.2-2.fc4
[captive.git] / src / libcaptive / include / captive / macros.h
index 96d1ce6..8292a8f 100644 (file)
@@ -26,6 +26,8 @@
 #include <stdarg.h>
 #include <string.h>    /* for memset() */
 #include <glib/galloca.h>
+#include <glib/gmessages.h>
+#include <glib/gutils.h>       /* for g_snprintf(); glib-2.2.x+ it also has in <glib/gprintf.h> */
 
 
 G_BEGIN_DECLS
@@ -142,7 +144,7 @@ G_BEGIN_DECLS
  * Value %NULL is returned iff @n==%0;
  */
 #define captive_newn_alloca(objp,n) ({ \
-               size_t _captive_newn_alloca_n=(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))); \
                })
@@ -204,6 +206,28 @@ G_BEGIN_DECLS
 
 
 /**
+ * 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.
@@ -225,6 +249,118 @@ G_BEGIN_DECLS
  */
 #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