/* CSL - Common Sound Layer
 * Copyright (C) 2000-2001 Stefan Westerfeld and Tim Janik
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General
 * Public License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
 * Boston, MA 02111-1307, USA.
 */
#ifndef __CSL_UTILS_H__
#define __CSL_UTILS_H__

#include	<csl/csldefs.h>

#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */

/**
 * @file
 * This file defines some useful utility functions that can be used in CSL.
 */

/* --- GCC specific macros --- */

#if     __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ > 4)
/** @short GCC specific macro */
#define CSL_GNUC_PRINTF( format_idx, arg_idx )	\
  __attribute__((format (printf, format_idx, arg_idx)))
/** @short GCC specific macro */
#define CSL_GNUC_NORETURN			\
  __attribute__((noreturn))
#else
/** @short GCC specific macro */
#define CSL_GNUC_PRINTF( format_idx, arg_idx )
/** @short GCC specific macro */
#define CSL_GNUC_NORETURN
#endif


/* --- portable conversions --- */

/** @short Cast unsigned int to pointer */
#define	CSL_UINT_TO_POINTER(ifoo)	((void*) ((unsigned long) (ifoo)))
/** @short Cast int to pointer */
#define	CSL_INT_TO_POINTER(ifoo)	((void*) ((signed long) (ifoo)))
/** @short Cast pointer to int */
#define	CSL_POINTER_TO_INT(pfoo)	((int) ((signed long) (pfoo)))
/** @short Cast pointer to unsigned int */
#define	CSL_POINTER_TO_UINT(pfoo)	((unsigned int) ((unsigned long) (pfoo)))


/* --- standard utility functions --- */
void    csl_error       (const char *format,
			 ...)                   CSL_GNUC_PRINTF (1, 2) CSL_GNUC_NORETURN;
void    csl_warning     (const char *format,
			 ...)                   CSL_GNUC_PRINTF (1, 2);
void    csl_message     (const char *format,
			 ...)                   CSL_GNUC_PRINTF (1, 2);
void    csl_free        (void           *mem);
void*   csl_malloc      (unsigned int    n_bytes);
void*   csl_malloc0     (unsigned int    n_bytes);
void*   csl_realloc     (void           *mem,
			 unsigned int    n_bytes);
void*	csl_memdup	(void const	*mem,
			 unsigned int	 n_bytes);
char*   csl_strdup      (const char     *string);
void    csl_strfreevn   (unsigned int    n,
			 char          **str_p);


/**
 * Allocate storage for one or more variables of type struct.
 *
 * @param struct The type name of the struct.
 * @param n The number of struct variables to allocate.
 * @return A pointer to the newly allocated memory.
 * @see csl_new0
 * @see csl_free
 * @short Allocate storage for structs.
 */
#define	csl_new(struct, n)	(csl_malloc (sizeof (struct) * n))

/**
 * Allocate storage for one or more variables of type struct and fill
 * the memory with zeroes.
 *
 * @param struct The type name of the struct.
 * @param n The number of struct variables to allocate.
 * @return A pointer to the newly allocated memory.
 * @see csl_new
 * @see csl_free
 * @short Allocate and clear storage for structs.
 */
#define	csl_new0(struct, n)	(csl_malloc0 (sizeof (struct) * n))

/* --- debugging assertions --- */

/**
 * Check if a condition is true, and if not, call csl_error with a suitable error message.
 *
 * @param cond An expression to be evaluated
 * @see csl_error
 * @see csl_return_if_fail
 * @see csl_return_val_if_fail
 * @short Assertion check.
 */
#define	csl_assert(cond)		{ if (!(cond)) csl_error ("assertion failed: %s", # cond ); }

/**
 * Check if a condition is true, and if not, call csl_warning and return.
 *
 * @param cond An expression to be evaluated
 * @see csl_warning
 * @see csl_assert
 * @see csl_return_val_if_fail
 * @short Assertion check with return.
 */
#define	csl_return_if_fail(cond)	{ if (!(cond)) { csl_warning ("assertion failed: %s", # cond ); return; } }

/**
 * Check if a condition is true, and if not, call csl_warning and return a value.
 *
 * @param cond An expression to be evaluated
 * @param v Value to be returned if assertion fails
 * @see csl_return_if_fail
 * @see csl_return_val_if_fail
 * @short Assertion check with return of a value.
 */
#define	csl_return_val_if_fail(cond, v)	{ if (!(cond)) { csl_warning ("assertion failed: %s", # cond ); return (v); } }


/* --- debugging messages --- */

/**
 * You can enable debug messages for PCM and/or miscellaneous functions.
 * @see csl_set_debug_mask
 * @see csl_debug
 * @see csl_check_debug
 * @short Debugging levels
 */
typedef enum
{
  CSL_DEBUG_NONE	= (0),
  CSL_DEBUG_PCM		= (1 << 0),
  CSL_DEBUG_MISC	= (1 << 1)
} CslDebugFlags;

void	csl_set_debug_mask	(unsigned int    debug_mask);

CslBool	csl_check_debug		(unsigned int    debug_key);

/**
 * Return whether the specified debug level is enabled.
 * e.g. csl_check_debug(PCM);
 *
 * @param debug_key A debug level, specified as either PCM or NONE.
 * @return TRUE if the given debug level is enabled, otherwise FALSE.
 * @see csl_check_debug
 * @see csl_debug
 * @short Check debug level.
 */
#define	csl_debug(key)		(csl_check_debug (CSL_DEBUG_ ## key))

#ifdef __cplusplus
}
#endif /* __cplusplus */

#endif /* __CSL_UTILS_H__ */
