OpenSolaris_b135/lib/libtnf/scalar.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"

/*
 *
 */

#define	CHECK_SCALAR(datum)	check_scalar(datum)

#define	DATUM_NATIVE(x)		DATUM_TNF(datum)->file_native

/*
 *
 */

static void		check_scalar(tnf_datum_t);

static tnf_uint64_t	get_uint64(TNF *tnf, caddr_t val);

/*
 *
 */

static void
check_scalar(tnf_datum_t datum)
{
	CHECK_DATUM(datum);
	if (!INFO_SCALAR(DATUM_INFO(datum)))
		_tnf_error(DATUM_TNF(datum), TNF_ERR_TYPEMISMATCH);
	/* XXX Need to check for exact scalar type match as well */
}

/*
 * Exported scalar operations
 */

/* No swapping required: */

char
tnf_get_char(tnf_datum_t datum)
{
	CHECK_SCALAR(datum);
	return (*(char *)DATUM_VAL(datum));
}

tnf_int8_t
tnf_get_int8(tnf_datum_t datum)
{
	CHECK_SCALAR(datum);
	return (*(tnf_int8_t *)DATUM_VAL(datum));
}

tnf_int16_t
tnf_get_int16(tnf_datum_t datum)
{
	tnf_int16_t	val;

	CHECK_SCALAR(datum);
	/* LINTED pointer cast may result in improper alignment */
	val = *(tnf_int16_t *)DATUM_VAL(datum);
	return (DATUM_NATIVE(datum) ? val : _tnf_swap16(val));
}

/* 32-bit integers: */

tnf_int32_t
tnf_get_int32(tnf_datum_t datum)
{
	CHECK_SCALAR(datum);
	/* LINTED pointer cast may result in improper alignment */
	return (_GET_INT32(DATUM_TNF(datum), DATUM_VAL(datum)));
}

/* 64-bit integers: */

static tnf_uint64_t
get_uint64(TNF *tnf, caddr_t val)
{
	tnf_uint32_t	hi32, lo32; /* XXX both assumed unsigned */

	/* XXX Can't rely on address alignment */
	/* LINTED pointer cast may result in improper alignment */
	hi32 = *(tnf_uint32_t *)val;
	/* LINTED pointer cast may result in improper alignment */
	lo32 = *(tnf_uint32_t *)(val + sizeof (tnf_uint32_t));

#ifdef _LONG_LONG_HTOL
	/* eg. sparc */
	if (tnf->file_native)
		return ((((tnf_uint64_t)hi32) << 32)
			+ (tnf_uint64_t)lo32);
	else
		/* XXX Assume words are swapped as well: */
		return ((((tnf_uint64_t)_tnf_swap32(lo32)) << 32)
			+ (tnf_uint64_t)_tnf_swap32(hi32));
#else
	/* eg. i386 */
	if (tnf->file_native)
		return ((((tnf_uint64_t)lo32) << 32)
			+ (tnf_uint64_t)hi32);
	else
		/* XXX Assume words are swapped as well: */
		return ((((tnf_uint64_t)_tnf_swap32(hi32)) << 32)
			+ (tnf_uint64_t)_tnf_swap32(lo32));
#endif
}

tnf_int64_t
tnf_get_int64(tnf_datum_t datum)
{
	CHECK_SCALAR(datum);
	return (get_uint64(DATUM_TNF(datum), DATUM_VAL(datum)));
}

/* floats: */

tnf_float32_t
tnf_get_float32(tnf_datum_t datum)
{
	union {
		tnf_uint32_t	i32;
		tnf_float32_t	f32;
	} u;

	CHECK_SCALAR(datum);

	/* LINTED pointer cast may result in improper alignment */
	u.i32 = _GET_UINT32(DATUM_TNF(datum), DATUM_VAL(datum)); /* XXX */
	return (u.f32);
}

tnf_float64_t
tnf_get_float64(tnf_datum_t datum)
{
	union {
		tnf_uint64_t	i64;
		tnf_float64_t	f64;
	} u;

	CHECK_SCALAR(datum);

	u.i64 = get_uint64(DATUM_TNF(datum), DATUM_VAL(datum)); /* XXX */
	return (u.f64);
}