#ifndef LIBPAVS__LIBPAVS_H
#define LIBPAVS__LIBPAVS_H

/*
 * PaVS - Pasky's Version System, advanced version control system
 * Copyright (C) 2003  Petr Baudis
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

#ifdef __cplusplus
extern "C" {
#endif


/* This header file contains generic definitions and utility stuff for other
 * parts of API. If you want (especially if you want to get the version
 * number), you can include it directly from your sources, but any other
 * libpavs header file wil include it as well. You will still need to include
 * all the other header files, depending on the specific functionality you
 * want to have (or <libpavs/all.h> if you are really lazy and want to bloat
 * yourself). */


/* The API is HIGHLY object-like, even if it's in plain C. You should always
 * use the "Life cycle" methods for basic manipulation with the objects. You
 * are also highly encouraged to use the supplied functions for work with the
 * object attributes instead of direct access. This will make it possible for
 * you to take advantage of possibly later introduced additional functionality
 * attached to the change, mainly planned on-demand loading of some data from
 * the file or so. */


/* The versions are versioned RCS-style, starting from 1 ;-). */

#define LIBPAVS_MAJOR	1	/* API compatibility not guaranteed */
#define LIBPAVS_MINOR	1	/* ABI compatibility not guaranteed */
#define LIBPAVS_PLEVEL	1	/* Only internal changes */


/* This library depends on librev, it operates with the objects defined in
 * that library. */

#include <librev/librev.h>

/* Check if we have the appropriate version. */
#if ((LIBREV_MAJOR != 1) || (LIBREV_MINOR < 1) || (LIBREV_PLEVEL < 1))
#error You are using too old librev! Please upgrade.
#endif

/* FIXME: This tie is not acceptable long-term. We need to generalize backends
 * support. --pasky */
#include <librcs/librcs.h>
#if ((LIBRCS_MAJOR != 1) || (LIBRCS_MINOR < 1) || (LIBRCS_PLEVEL < 1))
#error You are using too old librcs! Please upgrade.
#endif


/* Objects helper stuff. */

/* Each object's constructor (that's how you get its instance) is called by
 * {<structname>_init(...)} (the specific usage depends on the object type and is
 * desribed below for each object), which returns pointer of the object or NULL
 * upon error.  The object has also a destructor called
 * {<structname>_done(struct *)} (it doesn't return anything and it always has
 * this form), but you should always call {<structname>_dissociate(struct *)}
 * instead as described below.  The other methods are different for each object
 * and described below. */

/* Each object contains a refcount, which is incremented each time the object
 * is associated with some higher-level entity. That is, always when you insert
 * it to some other structure and you should also do it when you pass it to
 * some function and you need to know the object will still be alive when you
 * return from the function. It is decremented by the dissociation of rcs_file
 * (return from a function, removal from a structure). */
/* You should use {<structname>_associate(struct *)} and
 * {<structname>_dissociate(struct *)} for these actions, otherwise you will
 * likely have leaks and problems in future.  Also you should never call
 * {<structname>_done()} directly but rely on the {dissociate()} method to do
 * its job. */

#include <assert.h>

#define pavs_object(name,content) \
	struct pavs_##name { \
		content \
		int refcount; \
	}; \
	void pavs_##name##_done (struct pavs_##name *obj); \
	static inline void pavs_##name##_associate (struct pavs_##name *obj) { \
		assert (obj); \
		obj->refcount ++; \
	} \
	static inline void pavs_##name##_dissociate (struct pavs_##name *obj) { \
		assert (obj); \
		obj->refcount --; \
		if (obj->refcount < 0) obj->refcount = 0; \
		if (! obj->refcount) pavs_##name##_done (obj); \
	}


#ifdef __cplusplus
}
#endif

#endif
