changeset 95:cb5d3d66ea04

Merge
author David Demelier <markand@malikania.fr>
date Thu, 12 Jan 2012 20:12:48 +0100
parents 820426789f17 (current diff) f5339bdc5cb1 (diff)
children dcaf2c61c902
files module.c module.h
diffstat 9 files changed, 327 insertions(+), 237 deletions(-) [+]
line wrap: on
line diff
--- a/array.c	Thu Jan 12 15:42:08 2012 +0100
+++ b/array.c	Thu Jan 12 20:12:48 2012 +0100
@@ -26,26 +26,57 @@
 
 static int	array_grow(struct array *);
 
-struct array *
-array_new(enum array_type type, size_t unit, int length)
+int
+array_init(struct array *arr, size_t unit)
 {
-	struct array *arr;
+	if (unit == 0)
+		return -1;
 
-	if (unit == 0 || (arr = malloc(sizeof (struct array))) == NULL)
-		return NULL;
-
-	memset(arr, 0, sizeof (struct array));
-	arr->type	= type;
-	arr->bsize	= (length == 0) ? ARRAY_DEFAULT_BSIZE : length;
 	arr->unit	= unit;
 	arr->size	= OFFSET(arr->bsize);
 
-	if ((arr->data = malloc(arr->size)) == NULL) {
-		free(arr);
-		return NULL;
-	}
+	/* Set defaults if needed */
+	arr->bsize	= (arr->bsize <= 0) ? ARRAY_DEFAULT_BSIZE : arr->bsize;
+	arr->malloc	= (arr->malloc == NULL) ? &malloc : arr->malloc;
+	arr->realloc	= (arr->realloc == NULL) ? &realloc : arr->realloc;
+
+	if ((arr->data = arr->malloc(arr->size)) == NULL)
+		return -1;
+
+	return 0;
+}
+
+/*
+ * Valid options that can be set for an array :
+ * l -> optional array block size of type int
+ * m -> malloc function that must matches void * (*malloc)(size_t)
+ * r -> realloc function that must matches void * (*realloc)(void *, size_t)
+ * t -> type of array of type enum array_type
+ */
 
-	return arr;
+void
+array_set(struct array *arr, const char *fmt, ...)
+{
+	va_list ap;
+	const char *p;
+
+	va_start(ap, fmt);
+	for (p = fmt; *p != '\0'; ++p)
+		switch (*p) {
+		case 'l':
+			arr->bsize = va_arg(ap, int);
+			break;
+		case 'm':
+			arr->malloc = va_arg(ap, void *(*)(size_t));
+			break;
+		case 'r':
+			arr->realloc = va_arg(ap, void *(*)(void *, size_t));
+			break;
+		case 't':
+			arr->type = va_arg(ap, enum array_type);
+		default:
+			break;
+		}
 }
 
 /*
@@ -178,7 +209,7 @@
 	 * function.
 	 */
 
-	if ((tmp = malloc(arr->unit)) == NULL)
+	if ((tmp = arr->malloc(arr->unit)) == NULL)
 		return -1;
 
 	memcpy((char *)tmp, (char *)arr->data + OFFSET(i1), arr->unit);
@@ -282,8 +313,6 @@
 
 	if (arr->data)
 		free(arr->data);
-
-	free(arr);
 }
 
 /*
@@ -299,7 +328,7 @@
 		return 0;
 
 	if (arr->type == ARRAY_AUTO) {
-		if ((arr->data = realloc(arr->data, arr->size +
+		if ((arr->data = arr->realloc(arr->data, arr->size +
 		    OFFSET(arr->bsize))) == NULL)
 			return -1;
 
--- a/array.h	Thu Jan 12 15:42:08 2012 +0100
+++ b/array.h	Thu Jan 12 20:12:48 2012 +0100
@@ -23,11 +23,15 @@
 extern "C" {
 #endif
 
+#include <stdarg.h>
+
+#ifndef ARRAY_DEFAULT_BSIZE
 #define ARRAY_DEFAULT_BSIZE	128
+#endif
 
 enum array_type {
-	ARRAY_FIXED	= 0,
-	ARRAY_AUTO	= 1
+	ARRAY_AUTO	= 0,
+	ARRAY_FIXED	= 1
 };
 
 struct array {
@@ -37,26 +41,31 @@
 	size_t		size;	/* current buffer size (allocated memory) */
 	size_t		unit;	/* unit size (sizeof the object) */
 	int		bsize;	/* block size (used when growing array) */
-	int		i;	/* only for ARRAY_FOREACH(_R) */
+	int		i;	/* only for ARRAY_FOREACH */
+
+	/* Own allocation functions */
+	void * (*malloc)(size_t);
+	void * (*realloc)(void *, size_t);
 };
 
 typedef void (*array_map_fn)(void *, void *);
 typedef int (*array_cmp_fn)(void *, void *);
 
-struct array	*array_new(enum array_type, size_t, int);
-int		array_push(struct array *, const void *);
-int		array_insert(struct array *, const void *, int);
-int		array_append(struct array *, const void *);
-void		array_pop(struct array *);
-void		array_unqueue(struct array *);
-void		array_remove(struct array *, int);
-void		array_unref(struct array *, const void *);
-int		array_iswap(struct array *, int, int);
-int		array_pswap(struct array *, const void *, const void *);
-void		array_map(const struct array *, array_map_fn, void *);
-int		array_find(const struct array *, array_cmp_fn, void *, void *);
-void		array_clear(struct array *);
-void		array_free(struct array *);
+int	array_init(struct array *, size_t);
+void	array_set(struct array *, const char *, ...);
+int	array_push(struct array *, const void *);
+int	array_insert(struct array *, const void *, int);
+int	array_append(struct array *, const void *);
+void	array_pop(struct array *);
+void	array_unqueue(struct array *);
+void	array_remove(struct array *, int);
+void	array_unref(struct array *, const void *);
+int	array_iswap(struct array *, int, int);
+int	array_pswap(struct array *, const void *, const void *);
+void	array_map(const struct array *, array_map_fn, void *);
+int	array_find(const struct array *, array_cmp_fn, void *, void *);
+void	array_clear(struct array *);
+void	array_free(struct array *);
 
 #define ARRAY_HEAD(a, type)							\
 	(((type *)a->data)[0])
@@ -66,14 +75,10 @@
 	((type *)(a)->data)[((i) < 0)						\
 	    ? 0 : ((i) >= (a)->length) ? (a)->length - 1 : (i)]
 
-#define ARRAY_FOREACH_R(a, var)							\
-	for ((a)->i = 0, var = ARRAY_TAIL((a));					\
-	    (a)->i < (a)->length; ++(a)->i, --var)
-
-#define ARRAY_FOREACH(a, var, type)						\
-	for ((a)->i = 0, var = ARRAY_HEAD((a), type);				\
+#define ARRAY_FOREACH(a, var)							\
+	for ((a)->i = 0, (var) = (a)->data;					\
 		(a)->i < (a)->length;						\
-		++(a)->i, var = ARRAY_INDEX((a), (a)->i, type))
+		++(a)->i, ++(var))
 
 /* Only for ARRAY_FIXED */
 #define ARRAY_FULL(a)								\
--- a/err.h	Thu Jan 12 15:42:08 2012 +0100
+++ b/err.h	Thu Jan 12 20:12:48 2012 +0100
@@ -37,8 +37,10 @@
  * a warning like `a may be used uninitialized'.
  */
 
-#ifdef __GNUC__
+#if defined(__GNUC__)
 #  define __at_noreturn	__attribute__ ((noreturn))
+#elif defined(_MSC_VER)
+#  define __at_noreturn	__declspec(noreturn)
 #endif
 
 /*
--- a/ini.c	Thu Jan 12 15:42:08 2012 +0100
+++ b/ini.c	Thu Jan 12 20:12:48 2012 +0100
@@ -26,9 +26,9 @@
 
 #include "ini.h"
 
-/* --------------------------------------------------------
- * structure definitions
- * -------------------------------------------------------- */
+/* -------------------------------------------------------- */
+/* structure definitions				    */
+/* -------------------------------------------------------- */
 
 struct ini_option {
 	char		*key;		/* option name */
@@ -59,11 +59,11 @@
 	STAILQ_HEAD(, ini_section) sections;
 };
 
-static char	iniError[1024 + 1];
+static char	ini_error[1024 + 1];
 
-/* --------------------------------------------------------
- * prototypes
- * -------------------------------------------------------- */
+/* -------------------------------------------------------- */
+/* prototypes						    */
+/* -------------------------------------------------------- */
 
 static void	*ini_read(struct ini_config *, FILE *);
 static int	ini_getline(struct ini_config *, FILE *);
@@ -119,7 +119,7 @@
  */
 
 char **
-ini_get_sections_names(struct ini_config *conf, int *number)
+ini_get_sections_names(const struct ini_config *conf, int *number)
 {
 	struct ini_section *s;
 	char **list;
@@ -129,6 +129,10 @@
 	STAILQ_FOREACH(s, &conf->sections, next)
 		++ i;
 
+	/* For safety */
+	if (number != NULL)
+		*number = 0;
+
 	if ((list = calloc(i + 1, sizeof (char *))) == NULL)
 		return NULL;
 
@@ -188,7 +192,7 @@
  */
 
 struct ini_section *
-ini_select_section(struct ini_config *conf, const char *section)
+ini_select_section(const struct ini_config *conf, const char *section)
 {
 	struct ini_section *s;
 
@@ -207,7 +211,7 @@
  */
 
 char *
-ini_option_once(struct ini_config *conf, const char *sect, const char *key)
+ini_get_option_once(const struct ini_config *conf, const char *sect, const char *key)
 {
 	struct ini_option *o;
 	struct ini_section *s;
@@ -228,7 +232,7 @@
  */
 
 char **
-ini_get_option_names(struct ini_section *section, int *nb)
+ini_get_option_names(const struct ini_section *section, int *nb)
 {
 	char **list;
 	struct ini_option *o;
@@ -238,6 +242,9 @@
 	STAILQ_FOREACH(o, &section->options, next)
 		++ i;
 
+	if (nb != NULL)
+		*nb = i;
+
 	if ((list = calloc(i + 1, sizeof (char *))) == NULL)
 		return NULL;
 
@@ -258,7 +265,7 @@
  */
 
 char *
-ini_get_option(struct ini_section *section, const char *key)
+ini_get_option(const struct ini_section *section, const char *key)
 {
 	struct ini_option *o;
 
@@ -270,16 +277,101 @@
 }
 
 /*
+ * These section provide very small API to convert value
+ * and store them to the dst pointer. Because you can also
+ * use your own handlers, the user data here can't be used.
+ */
+
+void
+ini_value_dispatch(struct ini_config *config, struct ini_handler *hdrs, int length)
+{
+	const char *sectionName;
+	int i;
+	char *value;
+	struct ini_section *section;
+
+	sectionName = NULL;
+	for (i = 0; i < length; ++i) {
+		/* Do not select the same section for performance. */
+		if (sectionName == NULL || strcmp(hdrs[i].section, sectionName) != 0) {
+			sectionName	= hdrs[i].section;
+			section		= ini_select_section(config, hdrs[i].section);
+		}
+
+		/* Skip the section if does not exists in the config */
+		if (section == NULL)
+			continue;
+
+		value = ini_get_option(section, hdrs[i].option);
+		hdrs[i].handler(hdrs[i].dst, value, hdrs[i].userdata);
+	}
+}
+
+void
+ini_convert_bool(void *dst, const char *value, void *dummy)
+{
+	char *p = dst;
+
+	if (value == NULL)
+		return ;
+
+	if (strcmp(value, "yes") == 0 ||
+	    strcmp(value, "true") == 0 ||
+	    strcmp(value, "1") == 0)
+		*p = 1;
+	else
+		*p = 0;
+	(void)dummy;
+}
+
+void
+ini_convert_int(void *dst, const char *value, void *dummy)
+{
+	int *p = dst;
+
+	if (value == NULL)
+		return ;
+
+	*p = (int) strtol(value, NULL, 10);
+	(void)dummy;
+}
+
+void
+ini_convert_short(void *dst, const char *value, void *dummy)
+{
+	short *p = dst;
+
+	if (value == NULL)
+		return ;
+
+	*p = (short) strtol(value, NULL, 10);
+	(void)dummy;
+}
+
+void
+ini_convert_string(void *dst, const char *value, void *dummy)
+{
+	char **p = dst;
+
+	if (value == NULL)
+		*p = NULL;
+	else
+		*p = strdup(value);
+
+	(void)dummy;
+}
+
+/*
  * Return the last error or "No error" if there is not error at all.
  */
 
 char *
-ini_error(void)
+ini_get_error(void)
 {
-	if (iniError[0] == '\0')
+	if (ini_error[0] == '\0')
 		return "No error";
 
-	return iniError;
+	return ini_error;
 }
 
 void
@@ -410,8 +502,10 @@
 			handler = &ini_switch;
 		else if (!conf->ignore)
 			handler = &ini_register;
-		else
+		else {
 			handler = NULL;
+			++ lp;
+		}
 
 		/* Success or not? */
 		if (handler != NULL && handler(conf, &lp) < 0)
@@ -522,7 +616,8 @@
 	/* Find end of option value */
 	token = *endValue;
 	if (token == '\'' || token == '"') {
-		for (*lp = ++endValue; *endValue != token && *endValue != '\0'; ++endValue)
+		for (*lp = ++endValue; *endValue != token &&
+		    *endValue != '\0'; ++endValue)
 			continue;
 
 		length = endValue - *lp;
@@ -533,7 +628,8 @@
 		else
 			WARN(conf, "line %d: missing '%c'\n", conf->lineno, token);
 	} else {
-		for (*lp = endValue; !isspace(*endValue) && *endValue != '\0'; ++endValue)
+		for (*lp = endValue; !isspace(*endValue) && *endValue != '\0' && 
+		    *endValue != '#' && *endValue != ';'; ++endValue)
 			continue;
 
 		length = endValue - *lp;
@@ -588,11 +684,11 @@
 		fclose(fp);
 
 	va_start(ap, fmt);
-	vsnprintf(iniError, 1024, fmt, ap);
+	vsnprintf(ini_error, 1024, fmt, ap);
 	va_end(ap);
 
 	/* Directly print error if VERBOSE is enabled */
-	WARN(conf, "%s\n", iniError);
+	WARN(conf, "%s\n", ini_error);
 
 	free(conf);
 
--- a/ini.h	Thu Jan 12 15:42:08 2012 +0100
+++ b/ini.h	Thu Jan 12 20:12:48 2012 +0100
@@ -26,6 +26,16 @@
 struct ini_config;
 struct ini_section;
 
+struct ini_handler {
+	const char	*section;	/* section to query */
+	const char	*option;	/* option to check */
+	void		*dst;		/* where to store */
+
+	/* Conversion function */
+	void (*handler)(void *, const char *, void *);
+	void		*userdata;	/* optional user data */
+};
+
 /* --------------------------------------------------------
  * struct ini_config functions.
  * -------------------------------------------------------- */
@@ -34,31 +44,75 @@
 ini_load(const char *, int);
 
 char **
-ini_get_sections_names(struct ini_config *, int *);
+ini_get_sections_names(const struct ini_config *, int *);
 
 struct ini_section **
 ini_get_sections(const struct ini_config *, const char *, int *);
 
 struct ini_section *
-ini_select_section(struct ini_config *, const char *);
+ini_select_section(const struct ini_config *, const char *);
 
 char *
-ini_get_option_once(struct ini_config *, const char *, const char *);
+ini_get_option_once(const struct ini_config *, const char *, const char *);
 
 void
 ini_free(struct ini_config *, int, int);
 
-char *
-ini_error(void);
-
 /* --------------------------------------------------------
  * struct ini_section functions.
  * -------------------------------------------------------- */
 
 char **
-ini_get_option_names(struct ini_section *, int *);
+ini_get_option_names(const struct ini_section *, int *);
+
+char *
+ini_get_option(const struct ini_section *, const char *key);
+
+/* --------------------------------------------------------
+ * convenient api to query and convert data
+ * -------------------------------------------------------- */
 
 char *
-ini_get_option(struct ini_section *, const char *key);
+ini_get_error(void);
+
+/*
+ * For the config, read all available value and store them in
+ * the array ini_handler.
+ */
+
+void
+ini_value_dispatch(struct ini_config *, struct ini_handler *, int);
+
+/*
+ * Convert to bool. dst must be (char *).
+ * It converts "yes" "true" "1" or opposites. Only lower
+ * case is supported right now.
+ */
+
+void
+ini_convert_bool(void *, const char *, void *);
+
+/*
+ * Convert to a int. dst must be (int *).
+ */
+
+void
+ini_convert_int(void *, const char *, void *);
+
+/*
+ * Convert to a short. dst must be (short *).
+ */
+
+void
+ini_convert_short(void *, const char *, void *);
+
+/*
+ * Convert to a char *. dst must be (char **). This
+ * function use strdup() you need to free the dst
+ * pointer.
+ */
+
+void
+ini_convert_string(void *, const char *, void *);
 
 #endif /* _INI_H_ */
--- a/module.c	Thu Jan 12 15:42:08 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,73 +0,0 @@
-/*
- * module.c -- portable functions to manipulate dynamic libraries
- *
- * Copyright (c) 2011, David Demelier <markand@malikania.fr>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-
-#include "module.h"
-
-struct module *
-module_load(const char *path, int flags)
-{
-	struct module *mod;
-
-	if ((mod = malloc(sizeof (struct module))) == NULL)
-		return NULL;
-
-	/* Flags are not supported on Windows */
-#if defined(_WIN32) || defined(__WIN32__)
-	(void) flags;
-	mod->handler = LoadLibrary(path);
-#else
-	mod->handler = dlopen(path, flags);
-#endif
-
-	if (!(mod->handler)) {
-		module_free(mod);
-		return NULL;
-	}
-
-	return mod;
-}
-
-int
-module_find(struct module *mod, const char *sym)
-{
-#if defined(_WIN32) || defined(__WIN32__)
-	mod->sym = GetProcAddress(mod->handler, sym);
-#else
-	mod->sym = dlsym(mod->handler, sym);
-#endif
-
-	if (!(mod->sym))
-		return -1;
-
-	return 0;
-}
-
-void
-module_free(struct module *mod)
-{
-#if defined(_WIN32) || defined(__WIN32__)
-	FreeLibrary(mod->handler);
-#else
-	dlclose(mod->handler);
-#endif
-
-	free(mod);
-}
--- a/module.h	Thu Jan 12 15:42:08 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,59 +0,0 @@
-/*
- * module.h -- portable functions to manipulate dynamic libraries
- *
- * Copyright (c) 2011, David Demelier <markand@malikania.fr>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef _MODULE_H_
-#define _MODULE_H_
-
-#if defined(_WIN32) || defined(__WIN32__)
-#include <windows.h>
-#else
-#include <dlfcn.h>
-#endif
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* Unsupported on windows */
-#if defined(_WIN32) || defined(__WIN32__)
-#define	MOD_LAZY	1
-#define MOD_NOW		1
-#else
-#define	MOD_LAZY	RTLD_LAZY
-#define MOD_NOW		RTLD_NOW
-#endif
-
-struct module {
-#if defined(_WIN32) || defined(__WIN32__)
-	HMODULE	handler;
-	FARPROC	sym;
-#else
-	void	*handler;
-	void	*sym;
-#endif
-};
-
-struct module	*module_load(const char *, int);
-int		module_find(struct module *, const char *);
-void		module_free(struct module *);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _MODULE_H_ */
--- a/parray.c	Thu Jan 12 15:42:08 2012 +0100
+++ b/parray.c	Thu Jan 12 20:12:48 2012 +0100
@@ -26,26 +26,55 @@
 
 static int	parray_grow(struct parray *);
 
-struct parray *
-parray_new(enum parray_type type, int length)
+int
+parray_init(struct parray *arr)
 {
-	struct parray *arr;
+	/* Set defaults if needed */
+	arr->bsize	= (arr->bsize <= 0) ? PARRAY_DEFAULT_BSIZE : arr->bsize;
+	arr->malloc	= (arr->malloc == NULL) ? &malloc : arr->malloc;
+	arr->realloc	= (arr->realloc == NULL) ? &realloc : arr->realloc;
 
-	if ((arr = malloc(sizeof (struct parray))) == NULL)
-		return NULL;
-
-	memset(arr, 0, sizeof (struct parray));
-
-	arr->type	= type;
-	arr->bsize	= (length == 0) ? PARRAY_DEFAULT_BSIZE : length;
 	arr->size	= LENGTH(arr->bsize);
 
-	if ((arr->datas = calloc(arr->bsize, sizeof (void *))) == NULL) {
-		free(arr);
-		return NULL;
-	}
+	if ((arr->datas = arr->malloc(arr->size)) == NULL)
+		return -1;
+
+	memset(arr->datas, 0, arr->bsize);
+
+	return 0;
+}
+
+/*
+ * Valid options that can be set for an array :
+ * l -> optional array block size of type int
+ * m -> malloc function that must matches void * (*malloc)(size_t)
+ * r -> realloc function that must matches void * (*realloc)(void *, size_t)
+ * t -> type of array of type enum array_type
+ */
 
-	return arr;
+void
+parray_set(struct parray *arr, const char *fmt, ...)
+{
+	va_list ap;
+	const char *p;
+
+	va_start(ap, fmt);
+	for (p = fmt; *p != '\0'; ++p)
+		switch (*p) {
+		case 'l':
+			arr->bsize = va_arg(ap, int);
+			break;
+		case 'm':
+			arr->malloc = va_arg(ap, void * (*)(size_t));
+			break;
+		case 'r':
+			arr->realloc = va_arg(ap, void *(*)(void *, size_t));
+			break;
+		case 't':
+			arr->type = va_arg(ap, enum parray_type);
+		default:
+			break;
+		}
 }
 
 /*
@@ -263,8 +292,6 @@
 
 	if (arr->datas)
 		free(arr->datas);
-
-	free(arr);
 }
 
 /*
@@ -280,7 +307,7 @@
 		return 0;
 
 	if (arr->type == PARRAY_AUTO) {
-		if ((arr->datas = realloc(arr->datas, arr->size +
+		if ((arr->datas = arr->realloc(arr->datas, arr->size +
 		    LENGTH(arr->bsize))) == NULL)
 			return -1;
 
--- a/parray.h	Thu Jan 12 15:42:08 2012 +0100
+++ b/parray.h	Thu Jan 12 20:12:48 2012 +0100
@@ -23,11 +23,15 @@
 extern "C" {
 #endif
 
+#include <stdarg.h>
+
+#ifndef PARRAY_DEFAULT_BSIZE
 #define PARRAY_DEFAULT_BSIZE	128
+#endif
 
 enum parray_type {
-	PARRAY_FIXED	= 0,
-	PARRAY_AUTO	= 1
+	PARRAY_AUTO	= 0,
+	PARRAY_FIXED	= 1
 };
 
 struct parray {
@@ -37,25 +41,30 @@
 	size_t		size;		/* current buffer size (allocated memory) */
 	int		bsize;		/* block size (used when growing array) */
 	int		i;		/* only for PARRAY_FOREACH(_R) */
+
+	/* Own allocation functions */
+	void * (*malloc)(size_t);
+	void * (*realloc)(void *, size_t);
 };
 
 typedef void (*parray_map_fn)(void *, void *);
 typedef int (*parray_cmp_fn)(void *, void *);
 
-struct parray	*parray_new(enum parray_type, int);
-int		parray_push(struct parray *, void *);
-int		parray_insert(struct parray *, void *, int);
-int		parray_append(struct parray *, void *);
-void		parray_pop(struct parray *);
-void		parray_unqueue(struct parray *);
-void		parray_remove(struct parray *, int);
-void		parray_unref(struct parray *, const void *);
-int		parray_iswap(struct parray *, int, int);
-int		parray_pswap(struct parray *, const void *, const void *);
-void		parray_map(const struct parray *, parray_map_fn, void *);
-int		parray_find(const struct parray *, parray_cmp_fn, void **, void *);
-void		parray_clear(struct parray *);
-void		parray_free(struct parray *);
+int	parray_init(struct parray *);
+void	parray_set(struct parray *, const char *, ...);
+int	parray_push(struct parray *, void *);
+int	parray_insert(struct parray *, void *, int);
+int	parray_append(struct parray *, void *);
+void	parray_pop(struct parray *);
+void	parray_unqueue(struct parray *);
+void	parray_remove(struct parray *, int);
+void	parray_unref(struct parray *, const void *);
+int	parray_iswap(struct parray *, int, int);
+int	parray_pswap(struct parray *, const void *, const void *);
+void	parray_map(const struct parray *, parray_map_fn, void *);
+int	parray_find(const struct parray *, parray_cmp_fn, void **, void *);
+void	parray_clear(struct parray *);
+void	parray_free(struct parray *);
 
 #define PARRAY_HEAD(a)								\
 	(a->datas[0])