/* Copyright (C) 2006-2010 David Sugar, Tycho Softworks.
 *
 * This file is part of libcpr.
 *
 * libcpr is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published
 * by the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * libcpr 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 Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with libcpr.  If not, see <http://www.gnu.org/licenses/>.
 */

#ifndef	_CPRTYPES_H_
#define	_CPRTYPES_H_

#include <cpr.h>

#ifdef __cplusplus
extern "C" {
#endif

struct cpr_typemap;

typedef	struct _cpr_data_
{
	struct cpr_typemap	*typeinfo;
	size_t	refcount;
	size_t	count, members;
	union {
		char data[1];
		struct _cpr_data_ *member[1];
	} value;
} *cpr_dataref;

typedef struct cpr_typemap
{
	struct cpr_typemap *next;
	const char *name;
	size_t	size;
	cpr_dataref (*create)(struct cpr_typemap *ref);
	bool (*assign)(cpr_dataref object, void *data);
	void *(*value)(cpr_dataref object);
	void (*release)(cpr_dataref object);
	void (*retain)(cpr_dataref object);
	cpr_dataref (*index)(cpr_dataref object, size_t pos);
	cpr_dataref (*map)(cpr_dataref object, cpr_dataref key);
	bool (*equal)(cpr_dataref object1, cpr_dataref object2);
}	*cpr_typeref;

typedef	cpr_dataref	cprvalue_t;
typedef	cpr_dataref	cprarray_t;
typedef	cpr_dataref	cprstring_t;
typedef cpr_dataref	cprmapped_t;

/* basic typemap templates */

__EXPORT struct cpr_typemap cpr_type_template_value;
__EXPORT struct cpr_typemap cpr_type_template_double;

/* actual types functions */

__EXPORT void cpr_stdtypes(void);
__EXPORT bool cpr_value_typemap(const char *name, size_t size, cpr_typeref temp);
__EXPORT cpr_typeref cpr_typefind(const char *name);
__EXPORT void cpr_release(cpr_dataref ref);
__EXPORT void cpr_retain(cpr_dataref ref);

/* macros for generics and common use cases */

#define	CPR_VALUE_TYPEMAP(type, temp) \
	cpr_value_typemap(#type, sizeof(type), &temp)

#define	CPR_SET_VALUE(ref, type, value) \
	do {type temp = value; _cpr_set_value(ref, #type, (void *)&value);}while(0)

#define	CPR_GET_VALUE(ref, type) \
	(*((type *)(_cpr_get_value(ref, #type)))

#define CPR_GET_POINTER(ref, type) \
	(type *)(_cpr_get_pointer(ref, #type))

#define	CPR_CREATE_VALUE(type) \
	(type *)(_cpr_create_value(#type))

#define	CPR_RELEASE(ref) \
	cpr_release(ref); ref = NULL

#define	CPR_RETAIN(ref) \
	cpr_retain(ref)

#ifdef __cplusplus
}
#endif

#endif

