/*	Public domain	*/

#ifndef _AGAR_CORE_DB_H_
#define _AGAR_CORE_DB_H_

#include <agar/config/ag_serialization.h>
#ifdef AG_SERIALIZATION

#include <agar/core/begin.h>

struct ag_db;

/* Database data item (e.g., key or value) */
typedef struct ag_dbt {
	void *_Nonnull data;
	AG_Size        size;
	AG_SIZE_PADDING(_pad);
} AG_Dbt;

typedef int (*AG_DbIterateFn)(const AG_Dbt *_Nonnull,
                              const AG_Dbt *_Nonnull,
			      void         *_Nullable arg);

typedef struct ag_db_class {
	struct ag_object_class _inherit;
	const char *_Nonnull name;	/* Database method name */
	const char *_Nonnull descr;	/* Short description */
	enum ag_db_key_mode {
		AG_DB_KEY_DATA,		/* Variable-length data */
		AG_DB_KEY_NUMBER,	/* Logical record number */
		AG_DB_KEY_STRING	/* Legal C string */
	} keyMode;
	enum ag_db_record_mode {
		AG_DB_REC_VARIABLE,	/* Variable-length records */
		AG_DB_REC_FIXED		/* Fixed-length records */
	} recMode;
	int  (*_Nullable open)(void *_Nonnull, const char *_Nonnull, Uint);
	void (*_Nullable close)(void *_Nonnull);
	int  (*_Nullable sync)(void *_Nonnull);
	int  (*_Nonnull  exists)(void *_Nonnull, const AG_Dbt *_Nonnull);
	int  (*_Nonnull  get)(void *_Nonnull, const AG_Dbt *_Nonnull,
	                      AG_Dbt *_Nonnull);
	int  (*_Nonnull  put)(void *_Nonnull, const AG_Dbt *_Nonnull,
	                      const AG_Dbt *_Nonnull);
	int  (*_Nonnull  del)(void *_Nonnull, const AG_Dbt *_Nonnull);
	int  (*_Nullable iterate)(void *_Nonnull, _Nonnull AG_DbIterateFn,
	                          void *_Nullable);
} AG_DbClass;

typedef struct ag_db {
	struct ag_object _inherit;
	Uint flags;
#define AG_DB_OPEN	0x01		/* Database is open */
#define AG_DB_READONLY	0x02		/* Open in read-only mode */
	Uint32 _pad;
} AG_Db;

#define   AGDB(o)        ((AG_Db *)(o))
#define  AGcDB(o)        ((const AG_Db *)(o))
#define  AG_DB_ISA(o)    (((AGOBJECT(o)->cid & 0xff000000) >> 24) == 0x03)
#define  AG_DB_SELF()    AGDB(  AG_OBJECT(0,         "AG_Db:*") )
#define  AG_DB_PTR(n)    AGDB(  AG_OBJECT((n),       "AG_Db:*") )
#define  AG_DB_NAMED(n)  AGDB(  AG_OBJECT_NAMED((n), "AG_Db:*") )
#define AG_cDB_SELF()   AGcDB( AG_cOBJECT(0,         "AG_Db:*") )
#define AG_cDB_PTR(n)   AGcDB( AG_cOBJECT((n),       "AG_Db:*") )
#define AG_cDB_NAMED(n) AGcDB( AG_cOBJECT_NAMED((n), "AG_Db:*") )

#define AGDB_CLASS(o) ((AG_DbClass *)AGOBJECT(o)->cls)

/* Begin generated block */
__BEGIN_DECLS
extern DECLSPEC AG_DbClass agDbClass;
extern DECLSPEC AG_DbClass agDbHashClass;
extern DECLSPEC AG_DbClass agDbBtreeClass;
extern DECLSPEC AG_DbClass agDbMySQLClass;
extern DECLSPEC AG_Db *_Nullable AG_DbNew(const char *_Nonnull);
extern DECLSPEC int AG_DbOpen(AG_Db *_Nonnull, const char *_Nonnull, Uint);
extern DECLSPEC void AG_DbClose(AG_Db *_Nonnull);
extern DECLSPEC int AG_DbSync(AG_Db *_Nonnull);
extern DECLSPEC int AG_DbExists(AG_Db *_Nonnull, AG_Dbt *_Nonnull);
extern DECLSPEC int AG_DbGet(AG_Db *_Nonnull, const AG_Dbt *_Nonnull, AG_Dbt *_Nonnull);
extern DECLSPEC int AG_DbPut(AG_Db *_Nonnull, const AG_Dbt *_Nonnull, const AG_Dbt *_Nonnull);
extern DECLSPEC int AG_DbDel(AG_Db *_Nonnull, const AG_Dbt *_Nonnull);
extern DECLSPEC int AG_DbIterate(AG_Db *_Nonnull, _Nonnull AG_DbIterateFn, void *_Nullable);
__END_DECLS
/* Close generated block */

#include <agar/core/close.h>
#endif /* AG_SERIALIZATION */
#endif /* _AGAR_CORE_DB_H_ */
