#ifndef SIGSUM_XALLOC_H_INCLUDED
#define SIGSUM_XALLOC_H_INCLUDED

#include <stdlib.h>

void *
_sigsum_xalloc (size_t size);

void *
_sigsum_xrealloc (void *p, size_t size);

/* Convenience macro, to free a const pointer. Also clears the freed
   pointer, which must be an lvalue (typically, a struct field). */
#define XFREE(p) do {				\
    free ((void *)(p));				\
    (p) = NULL;					\
  } while (0)

/* This macro defines:

   * A type struct name representing a list of type elements.

   * A static function alloc_fn that appends a new (uninitialized)
     entry to the list, reallocating space if needed, and returns a
     pointer to the new entry.

   Due to possible reallocation, pointers to elements (including the
   pointer returned by alloc) are invalidated by the next call to
   alloc. In contrast, *indices* to entries are stable over
   reallocation.
 */
#define DEFINE_LIST(name, alloc_fn, type)				\
  struct name {								\
    size_t size;							\
    size_t alloc;							\
    type *list;								\
  };									\
  static type *								\
  alloc_fn (struct name *self_list)					\
  {									\
    if (self_list->size == self_list->alloc)				\
      {									\
	self_list->alloc += 10 + self_list->alloc / 2;			\
	self_list->list							\
	  = _sigsum_xrealloc (self_list->list,				\
			      self_list->alloc * sizeof (*self_list->list)); \
      }									\
    return &self_list->list[self_list->size++];				\
  }									\
  struct name /* To require a trailing semicolon after use. */



#endif /* SIGSUM_XALLOC_H_INCLUDED */
