/*
Copyright (c) 2007-2010, Dirk Krause
All rights reserved.

Redistribution and use in source and binary forms,
with or without modification, are permitted provided
that the following conditions are met:

* Redistributions of source code must retain the above
  copyright notice, this list of conditions and the
  following disclaimer.
* Redistributions in binary form must reproduce the above 
  opyright notice, this list of conditions and the following
  disclaimer in the documentation and/or other materials
  provided with the distribution.
* Neither the name of the Dirk Krause nor the names of
  contributors may be used to endorse or promote
  products derived from this software without specific
  prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
DAMAGE.
*/

/**	@file dksdbi.h Simple unique API to access different databases.

	This module provides a simple unique API to access
	GDBM, NDBM and Berkeley DB data bases. The appropriate libraries
	are used to do the real work, this module only provides an API.

	Unless otherwise stated, int functions in this module return a positive
	number to indicate success or a true condition, 0 to indicate an error
	or an unfullfilled condition.
	Pointer functions return valid pointers on success, NULL on error.
*/
#ifndef DKSDBI_H_INC
#define DKSDBI_H_INC	1

#include <dk.h>

/**	Pointer to database.
*/
typedef void *dk_sdbi_t;


/**	Traversal function.
	When traversing a database this function is invoked once for each
	key/value pair.
	The function must return the following values:
	-  0: No error, we can continue.
	-  1: Warning, we can continue.
	- -1: Error, we must stop database traversal.

	Pointer \a o is an additional data object to be changes
	during traversal.\n
	Buffer \a kp is \a kl bytes long, it receives the key.\n
	Buffer \a vp is \a vl bytes long, it receives the value.
*/
typedef int dk_sdbi_fct_t DK_PR((\
void *o, void *kp, size_t kl, void *vp, size_t vl));

#if defined(EXTERN)
#undef EXTERN
#endif
#if defined(DKSDBI_C)
#define EXTERN /* nix */
#else
#if DK_HAVE_PROTOTYPES
#define EXTERN /* nix */
#else
#define EXTERN extern
#endif
#endif
#if defined(__cplusplus)
extern "C" {
#endif



/**	Open a database and return database access structure.
	The structure is created in dynamically allocated memory,
	call dksdbi_close() to destory the structure and release the
	memory after usage.
	@param	n	Name of data base file.
	@param	t	Database type (DK_SDBI_TYPE_BDB, DK_SDBI_TYPE_NDBM,
			DK_SDBI_TYPE_GDBM or DK_SDBI_TYPE_AUTO).
	@param	a	Access mode (DK_SDBI_MODE_READ, DK_SDBI_MODE_WRITE or
			DK_SDBI_MODE_RDWR). Optionally you can or-combine
			the value with DK_SDBI_MODE_TRUNCATE to truncate
			existing database files.
	@param	m	File mode. File permissions, i.e. 0600.
	@param	b	Block size.
*/
EXTERN dk_sdbi_t
dksdbi_open DK_PR((char *n, int t, int a, int m, int b));



/**	Destroy database access structure obtained from dksdbi_open()
	and release memory.
	@param	d	Pointer to database access structure.
*/
EXTERN void
dksdbi_close DK_PR((dk_sdbi_t d));



/**	Store key/value pair in database.
	@param	p	Pointer to database access structure.
	@param	kp	Pointer to key buffer.
	@param	kl	Number of bytes in \a kp.
	@param	vp	Pointer to value buffer.
	@param	vl	Number of bytes in \a vp.
	@param	insmod	Insertion mode.
	Use 0 to allow replacements of existing entries,
	DK_SDBI_INSMOD_NO_REPLACE to deny replacements.
	@return	Flag to indicate success.
*/
EXTERN int
dksdbi_store DK_PR((dk_sdbi_t p, void *kp, size_t kl, void *vp, size_t vl, int insmod));



/**	Store key/value pair of strings in database.
	@param	d	Pointer to database access structure.
	@param	k	Pointer to key string.
	@param	v	Pointer to value string.
	@param	i	Insertion mode.
	Use 0 to allow replacements of existing entries,
	DK_SDBI_INSMOD_NO_REPLACE to deny replacements.
	@return	Flag to indicate success.
*/
EXTERN int
dksdbi_string_store DK_PR((dk_sdbi_t d, char *k, char *v, int i));



/**	Fetch key/value pair from database.
	@param	d	Pointer to database access structure.
	@param	kp	Pointer to key buffer.
	@param	kl	Number of bytes in \a kp.
	@param	vp	Pointer to buffer for result.
	@param	vl	Pointer to size variable. In: size of buffer.
			Out: number of bytes used.
	@return	Flag to indicate success.
*/
EXTERN int
dksdbi_fetch DK_PR((dk_sdbi_t d, void *kp, size_t kl, void *vp, size_t *vl));



/**	Fetch string entry from database.
	@param	d	Pointer to database access structure.
	@param	k	Pointer to key string.
	@param	v	Pointer to value buffer.
	@param	s	Size of \a v in bytes.
	@return	Flag to indicate success.
*/
EXTERN int
dksdbi_string_fetch DK_PR((dk_sdbi_t d, char *k, char *v, size_t s));



/**	Delete entry from database.
	@param	d	Pointer to database access structure.
	@param	k	Pointer to key buffer.
	@param	l	Number of bytes in \a k.
	@return	Flag to indicate success.
*/
EXTERN int
dksdbi_delete DK_PR((dk_sdbi_t d, char *k, size_t l));



/**	Delete string entry from database.
	@param	d	Pointer to database access structure.
	@param	k	Pointer to key string.
	@return	Flag to indicate success.
*/
EXTERN int
dksdbi_string_delete DK_PR((dk_sdbi_t d, char *k));



/**	Remove a database file (or file pair).
	@param	n	File name.
	@param	t	Database type (DK_SDBI_TYPE_xxx).
	@return	Flag to indicate success.
*/
EXTERN int
dksdbi_remove_file DK_PR((char *n, int t));



/**	Traverse database.
	This function walks through all database entries, the
	function \a f is called for each database entries.
	@param	d	Pointer to database access structure.
	@param	o	Pointer to object which is modified during
			database traversal.
	@param	f	Traversal function.
	@return	Flag to indicate success.
*/
EXTERN int
dksdbi_traverse DK_PR((dk_sdbi_t d, void *o, dk_sdbi_fct_t *f));



/**	Flush database to disk.
	Some database libraries provide a sync-to-disk function for this
	purposes, for other database types this function does nothing.
	@param	d	Pointer to database access structure.
	@return	Flag to indicate success.
*/
EXTERN int
dksdbi_sync DK_PR((dk_sdbi_t d));

#if defined(__cplusplus)
};
#endif

/** Database type: Choose automatically. */
#define DK_SDBI_TYPE_AUTO	0

/** Database type: Berkeley DB. */
#define DK_SDBI_TYPE_BDB	1

/** Database type: NDBM. */
#define DK_SDBI_TYPE_NDBM	2

/** Database type: GDBM. */
#define DK_SDBI_TYPE_GDBM	3

/** Database access mode: read. */
#define DK_SDBI_MODE_READ	1

/** Database access mode: write. */
#define DK_SDBI_MODE_WRITE	2

/** Database access mode: read and write. */
#define DK_SDBI_MODE_RDWR	(DK_SDBI_MODE_READ|DK_SDBI_MODE_WRITE)

/** Database access mode: Truncate existing database. */
#define DK_SDBI_MODE_TRUNCATE	4

/** Insertion mode: Do not replace exising entries. */
#define DK_SDBI_INSMOD_NO_REPLACE	1

#endif


