/*
 * Copyright 2000-2003 Sun Microsystems, Inc.  All rights reserved.
 * Use is subject to license terms.
 */

#ifndef	_SYS_NVPAIR_H
#define	_SYS_NVPAIR_H

#pragma ident	"@(#)nvpair.h	1.7	03/06/12 SMI"

#include <sys/types.h>
#include <sys/errno.h>

#ifdef _KERNEL
#include <sys/kmem.h>
#endif	/* _KERNEL */

#ifdef	__cplusplus
extern "C" {
#endif

/* Internal data types */
typedef enum {
	DATA_TYPE_UNKNOWN = 0,
	DATA_TYPE_BOOLEAN,
	DATA_TYPE_BYTE,
	DATA_TYPE_INT16,
	DATA_TYPE_UINT16,
	DATA_TYPE_INT32,
	DATA_TYPE_UINT32,
	DATA_TYPE_INT64,
	DATA_TYPE_UINT64,
	DATA_TYPE_STRING,
	DATA_TYPE_BYTE_ARRAY,
	DATA_TYPE_INT16_ARRAY,
	DATA_TYPE_UINT16_ARRAY,
	DATA_TYPE_INT32_ARRAY,
	DATA_TYPE_UINT32_ARRAY,
	DATA_TYPE_INT64_ARRAY,
	DATA_TYPE_UINT64_ARRAY,
	DATA_TYPE_STRING_ARRAY,
	DATA_TYPE_HRTIME,
	DATA_TYPE_NVLIST,
	DATA_TYPE_NVLIST_ARRAY
} data_type_t;

typedef struct {
	int32_t nvp_size;	/* size of this nvpair */
	int16_t	nvp_name_sz;	/* length of name string */
	int16_t	nvp_reserve;	/* not used */
	int32_t	nvp_value_elem;	/* number of elements for array types */
	data_type_t nvp_type;	/* type of value */
	/* name string */
	/* aligned ptr array for string arrays */
	/* aligned array of data for value */
} nvpair_t;

/* nvlist header */
typedef struct {
	int32_t		nvl_version;
	uint32_t	nvl_nvflag;	/* persistent flags */
	uint64_t	nvl_nvp;	/* ptr to next nvp if not packed */
	uint32_t	nvl_flag;
	int32_t		nvl_pad;	/* currently not used, for alignment */
} nvlist_t;

/*
 * implementation linked list for pre-packed data
 *
 * This structure is provided for information and debugging purposes only
 * and may be changed in the future.
 */
typedef struct {
	uint64_t next;	/* ensure alignment */
	nvpair_t nvp;
} i_nvp_t;


/* nvp implementation version */
#define	NV_VERSION	0

/* nvlist pack encoding */
#define	NV_ENCODE_NATIVE	0
#define	NV_ENCODE_XDR		1

/* nvlist persistent unique name flags, stored in nvl_nvflags */
#define	NV_UNIQUE_NAME		0x1
#define	NV_UNIQUE_NAME_TYPE	0x2

/* nvlist related flags */
#define	NV_FLAG_KMSLEEP		0x1

/* convenience macros */
#define	NV_ALIGN(x)		(((ulong_t)(x) + 7ul) & ~7ul)
#define	NV_ALIGN4(x)		(((x) + 3) & ~3)

#define	NVP_SIZE(nvp)		((nvp)->nvp_size)
#define	NVP_NAME(nvp)		((char *)(nvp) + sizeof (nvpair_t))
#define	NVP_TYPE(nvp)		((nvp)->nvp_type)
#define	NVP_NELEM(nvp)		((nvp)->nvp_value_elem)
#define	NVP_VALUE(nvp)		((char *)(nvp) + NV_ALIGN(sizeof (nvpair_t) \
				+ (nvp)->nvp_name_sz))

#define	NVL_VERSION(nvl)	((nvl)->nvl_version)
#define	NVL_SIZE(nvl)		((nvl)->nvl_size)
#define	NVL_FLAG(nvl)		((nvl)->nvl_flag)
#define	NVL_KMSLEEP(nvl)	(NVL_FLAG(nvl) & NV_FLAG_KMSLEEP)

/* memory allocation */
#if defined(_KERNEL) && !defined(_BOOT)
#define	nv_mem_alloc	kmem_zalloc
#define	nv_mem_free	kmem_free
#else	/* !defined(_KERNEL) || defined(_BOOT) */
extern void *nv_mem_alloc(size_t, int);
extern void nv_mem_free(void *, size_t);
#endif	/* !defined(_KERNEL) || defined(_BOOT) */

/* list management */
int nvlist_alloc(nvlist_t **nvlp, uint_t flag, int kmflag);
void nvlist_free(nvlist_t *nvl);
int nvlist_size(nvlist_t *nvl, size_t *size, int encoding);
int nvlist_pack(nvlist_t *nvl, char **bufp, size_t *buflen, int encoding,
    int kmflag);
int nvlist_unpack(char *buf, size_t bfulen, nvlist_t **nvlp, int kmflag);
int nvlist_dup(nvlist_t *nvl, nvlist_t **nvlp, int kmflag);

/* adding and removing pairs */
void nvlist_remove(nvlist_t *nvl, char *name, data_type_t type);
void nvlist_remove_all(nvlist_t *nvl, char *name);
int nvlist_add_boolean(nvlist_t *nvl, char *name);
int nvlist_add_byte(nvlist_t *nvl, char *name, uchar_t val);
int nvlist_add_int16(nvlist_t *nvl, char *name, int16_t val);
int nvlist_add_uint16(nvlist_t *nvl, char *name, uint16_t val);
int nvlist_add_int32(nvlist_t *nvl, char *name, int32_t val);
int nvlist_add_uint32(nvlist_t *nvl, char *name, uint32_t val);
int nvlist_add_int64(nvlist_t *nvl, char *name, int64_t val);
int nvlist_add_uint64(nvlist_t *nvl, char *name, uint64_t val);
int nvlist_add_string(nvlist_t *nvl, char *name, char *val);
int nvlist_add_nvlist(nvlist_t *nvl, char *name, nvlist_t *val);
int nvlist_add_byte_array(nvlist_t *nvl, char *name, uchar_t *val,
    uint_t nelem);
int nvlist_add_int16_array(nvlist_t *nvl, char *name, int16_t *val,
    uint_t nelem);
int nvlist_add_uint16_array(nvlist_t *nvl, char *name, uint16_t *val,
    uint_t nelem);
int nvlist_add_int32_array(nvlist_t *nvl, char *name, int32_t *val,
    uint_t nelem);
int nvlist_add_uint32_array(nvlist_t *nvl, char *name, uint32_t *val,
    uint_t nelem);
int nvlist_add_int64_array(nvlist_t *nvl, char *name, int64_t *val,
    uint_t nelem);
int nvlist_add_uint64_array(nvlist_t *nvl, char *name, uint64_t *val,
    uint_t nelem);
int nvlist_add_string_array(nvlist_t *nvl, char *name, char **val,
    uint_t nelem);
int nvlist_add_nvlist_array(nvlist_t *nvl, char *name, nvlist_t **val,
    uint_t nelem);
int nvlist_add_hrtime(nvlist_t *nvl, char *name, hrtime_t val);

/* lookup name-value pairs */
int nvlist_lookup_boolean(nvlist_t *nvl, char *name);
int nvlist_lookup_byte(nvlist_t *nvl, char *name, uchar_t *val);
int nvlist_lookup_int16(nvlist_t *nvl, char *name, int16_t *val);
int nvlist_lookup_uint16(nvlist_t *nvl, char *name, uint16_t *val);
int nvlist_lookup_int32(nvlist_t *nvl, char *name, int32_t *val);
int nvlist_lookup_uint32(nvlist_t *nvl, char *name, uint32_t *val);
int nvlist_lookup_int64(nvlist_t *nvl, char *name, int64_t *val);
int nvlist_lookup_uint64(nvlist_t *nvl, char *name, uint64_t *val);
int nvlist_lookup_string(nvlist_t *nvl, char *name, char **val);
int nvlist_lookup_nvlist(nvlist_t *nvl, char *name, nvlist_t **val);
int nvlist_lookup_byte_array(nvlist_t *nvl, char *name, uchar_t **val,
    uint_t *nelem);
int nvlist_lookup_int16_array(nvlist_t *nvl, char *name, int16_t **val,
    uint_t *nelem);
int nvlist_lookup_uint16_array(nvlist_t *nvl, char *name, uint16_t **val,
    uint_t *nelem);
int nvlist_lookup_int32_array(nvlist_t *nvl, char *name, int32_t **val,
    uint_t *nelem);
int nvlist_lookup_uint32_array(nvlist_t *nvl, char *name, uint32_t **val,
    uint_t *nelem);
int nvlist_lookup_int64_array(nvlist_t *nvl, char *name, int64_t **val,
    uint_t *nelem);
int nvlist_lookup_uint64_array(nvlist_t *nvl, char *name, uint64_t **val,
    uint_t *nelem);
int nvlist_lookup_string_array(nvlist_t *nvl, char *name, char ***val,
    uint_t *nelem);
int nvlist_lookup_nvlist_array(nvlist_t *nvl, char *name, nvlist_t ***val,
    uint_t *nelem);
int nvlist_lookup_hrtime(nvlist_t *nvl, char *name, hrtime_t *val);

/* processing nvpair */
nvpair_t *nvlist_next_nvpair(nvlist_t *nvl, nvpair_t *nvpair);
char *nvpair_name(nvpair_t *nvpair);
data_type_t nvpair_type(nvpair_t *nvpair);
int nvpair_value_byte(nvpair_t *nvpair, uchar_t *val);
int nvpair_value_int16(nvpair_t *nvpair, int16_t *val);
int nvpair_value_uint16(nvpair_t *nvpair, uint16_t *val);
int nvpair_value_int32(nvpair_t *nvpair, int32_t *val);
int nvpair_value_uint32(nvpair_t *nvpair, uint32_t *val);
int nvpair_value_int64(nvpair_t *nvpair, int64_t *val);
int nvpair_value_uint64(nvpair_t *nvpair, uint64_t *val);
int nvpair_value_string(nvpair_t *nvpair, char **val);
int nvpair_value_nvlist(nvpair_t *nvpair, nvlist_t **val);
int nvpair_value_byte_array(nvpair_t *nvpair, uchar_t **val, uint_t *nelem);
int nvpair_value_int16_array(nvpair_t *nvpair, int16_t **val, uint_t *nelem);
int nvpair_value_uint16_array(nvpair_t *nvpair, uint16_t **val, uint_t *nelem);
int nvpair_value_int32_array(nvpair_t *nvpair, int32_t **val, uint_t *nelem);
int nvpair_value_uint32_array(nvpair_t *nvpair, uint32_t **val, uint_t *nelem);
int nvpair_value_int64_array(nvpair_t *nvpair, int64_t **val, uint_t *nelem);
int nvpair_value_uint64_array(nvpair_t *nvpair, uint64_t **val, uint_t *nelem);
int nvpair_value_string_array(nvpair_t *nvpair, char ***val, uint_t *nelem);
int nvpair_value_nvlist_array(nvpair_t *nvpair, nvlist_t ***val, uint_t *nelem);
int nvpair_value_hrtime(nvpair_t *nvpair, hrtime_t *val);

#ifdef	__cplusplus
}
#endif

#endif	/* _SYS_NVPAIR_H */
