OpenSolaris_b135/lib/libtnf/struct.c

/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License, Version 1.0 only
 * (the "License").  You may not use this file except in compliance
 * with the License.
 *
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 * or http://www.opensolaris.org/os/licensing.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information: Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 */
/*
 *	Copyright (c) 1994, by Sun Microsytems, Inc.
 */

#pragma	ident	"%Z%%M%	%I%	%E% SMI"

#include "libtnf.h"

/*
 *
 */

static struct slotinfo *get_slotinfo(tnf_datum_t);
static struct slot *	get_slot_named(struct slotinfo *, char *);
static struct slot *	get_slot_indexed(struct slotinfo *, unsigned);
static tnf_datum_t	get_slot(tnf_datum_t, struct slot *);

/*
 *
 */

void
_tnf_check_slots(tnf_datum_t datum)
{
	struct taginfo	*info;

	CHECK_DATUM(datum);

	info = DATUM_INFO(datum);

	/* Must be an aggregate */
	if (!(INFO_STRUCT(info) || INFO_ARRAY(info)))
		_tnf_error(DATUM_TNF(datum), TNF_ERR_TYPEMISMATCH);
}

/*
 * Helpers
 */

static struct slotinfo *
get_slotinfo(tnf_datum_t datum)
{
	struct taginfo	*info, *base_info;

	info 		= DATUM_INFO(datum);
	base_info	= INFO_DERIVED(info)? info->base: info;

	/* XXX base must not be a scalar tag */
	if (INFO_SCALAR(base_info))
		_tnf_error(DATUM_TNF(datum), TNF_ERR_BADTNF);

	return (base_info->slotinfo);
}

static struct slot *
get_slot_indexed(struct slotinfo *slotinfo, unsigned index)
{
	unsigned 	count;

	count 		= slotinfo->slot_count;
	if (index >= count)
		return (NULL);
	else
		return (&slotinfo->slots[index]);
}

static struct slot *
get_slot_named(struct slotinfo *slotinfo, char *name)
{
	unsigned 	count, i;

	count 		= slotinfo->slot_count;

	for (i = 0; i < count; i++)
		if (strcmp(name, slotinfo->slots[i].slot_name) == 0)
			return (&slotinfo->slots[i]);

	return (NULL);
}

static tnf_datum_t
get_slot(tnf_datum_t datum, struct slot *slot)
{
	if (slot == NULL) {
		_tnf_error(DATUM_TNF(datum), TNF_ERR_BADSLOT); /* XXX */
		return (TNF_DATUM_NULL);

	} else if (INFO_TAGGED(slot->slot_type)) {
		TNF		*tnf;
		tnf_ref32_t	*rec;

		tnf = DATUM_TNF(datum);
		/* LINTED pointer cast may result in improper alignment */
		rec = _GET_REF32(tnf, (tnf_ref32_t *)
			(DATUM_VAL(datum) + slot->slot_offset));
		/* NULL slots are allowed */
		return ((rec == TNF_NULL)? TNF_DATUM_NULL :
			RECORD_DATUM(tnf, rec));

	} else			/* inline */
		return DATUM(slot->slot_type,
			DATUM_VAL(datum) + slot->slot_offset);
}

/*
 *
 */

unsigned
tnf_get_slot_count(tnf_datum_t datum)
{
	struct slotinfo	*slotinfo;

	CHECK_SLOTS(datum);

	slotinfo = get_slotinfo(datum);
	return (slotinfo->slot_count);
}

/*
 *
 */

unsigned
tnf_get_slot_index(tnf_datum_t datum, char *name)
{
	struct slotinfo	*slotinfo;
	struct slot	*slot;

	CHECK_SLOTS(datum);

	slotinfo = get_slotinfo(datum);
	slot	 = get_slot_named(slotinfo, name);

	if (slot == NULL) {
		_tnf_error(DATUM_TNF(datum), TNF_ERR_BADSLOT); /* XXX */
		return (((unsigned)-1));
	} else
		return (((char *)slot - (char *)&slotinfo->slots[0])
			/ sizeof (struct slot));
}

/*
 *
 */

char *
tnf_get_slot_name(tnf_datum_t datum, unsigned index)
{
	struct slotinfo	*slotinfo;
	struct slot	*slot;

	CHECK_SLOTS(datum);

	slotinfo 	= get_slotinfo(datum);
	slot		= get_slot_indexed(slotinfo, index);

	if (slot == NULL) {
		_tnf_error(DATUM_TNF(datum), TNF_ERR_BADSLOT); /* XXX */
		return ((char *)NULL);
	} else
		return (slot->slot_name);
}

/*
 *
 */

tnf_datum_t
tnf_get_slot_named(tnf_datum_t datum, char *name)
{
	struct slotinfo	*slotinfo;
	struct slot	*slot;

	CHECK_SLOTS(datum);

	slotinfo 	= get_slotinfo(datum);
	slot		= get_slot_named(slotinfo, name);

	return (get_slot(datum, slot));
}

/*
 *
 */

tnf_datum_t
tnf_get_slot_indexed(tnf_datum_t datum, unsigned index)
{
	struct slotinfo	*slotinfo;
	struct slot	*slot;

	CHECK_SLOTS(datum);

	slotinfo 	= get_slotinfo(datum);
	slot		= get_slot_indexed(slotinfo, index);

	return (get_slot(datum, slot));
}