#ifndef LIBRCS__LIBRCS_H
#define LIBRCS__LIBRCS_H

/*
 * Copyright (c) 2003  Petr Baudis.  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
 *     copyright 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 author nor the names of the product's
 *     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.
 */

#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 librcs
 * header file will 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 <librcs/all.h> if you are really lazy and want to bloat yourself). */

/* The interface 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. */


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

#define LIBRCS_MAJOR	1	/* API compatibility not guaranteed */
#define LIBRCS_MINOR	1	/* ABI compatibility not guaranteed */
#define LIBRCS_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


/* 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 rcs_object(name_,content_) \
	struct rcs_##name_ { \
		content_ \
		int refcount; \
	}; \
	void rcs_##name_##_done (struct rcs_##name_ *obj); \
	static inline void rcs_##name_##_associate (struct rcs_##name_ *obj) { \
		assert (obj); \
		obj->refcount ++; \
	} \
	static inline void rcs_##name_##_dissociate (struct rcs_##name_ *obj) { \
		assert (obj); \
		obj->refcount --; \
		if (obj->refcount < 0) obj->refcount = 0; \
		if (! obj->refcount) rcs_##name_##_done (obj); \
	}

	
#ifdef __cplusplus
}
#endif

#endif
