185 lines
3.6 KiB
C
Executable File
185 lines
3.6 KiB
C
Executable File
/*
|
|
* Copyright (c) 1994, by Sun Microsytems, Inc.
|
|
*/
|
|
|
|
#pragma ident "@(#)array.c 1.11 94/10/04 SMI"
|
|
|
|
#include "libtnf.h"
|
|
|
|
/*
|
|
* XXX This module assumes that all arrays are self-sized records.
|
|
*/
|
|
|
|
/*
|
|
*
|
|
*/
|
|
|
|
static struct taginfo * get_array_info(
|
|
tnf_datum_t,
|
|
struct taginfo **base,
|
|
struct taginfo **elt,
|
|
struct taginfo **elt_base);
|
|
|
|
/*
|
|
* XXX Assumes arrays are (self-sized) records
|
|
*/
|
|
|
|
void
|
|
_tnf_check_array(tnf_datum_t datum)
|
|
{
|
|
struct taginfo *info;
|
|
|
|
CHECK_RECORD(datum); /* XXX */
|
|
|
|
info = DATUM_INFO(datum);
|
|
|
|
if (!INFO_ARRAY(info))
|
|
_tnf_error(DATUM_TNF(datum), TNF_ERR_TYPEMISMATCH);
|
|
|
|
}
|
|
|
|
/*
|
|
* Helper
|
|
*/
|
|
|
|
static struct taginfo *
|
|
get_array_info(
|
|
tnf_datum_t datum,
|
|
struct taginfo **basep,
|
|
struct taginfo **eltp,
|
|
struct taginfo **elt_basep)
|
|
{
|
|
struct taginfo *info, *base, *elt, *elt_base;
|
|
|
|
info = DATUM_INFO(datum);
|
|
base = INFO_DERIVED(info) ? info->base : info;
|
|
|
|
if (INFO_DERIVED(base) || (!INFO_ARRAY(base)))
|
|
_tnf_error(DATUM_TNF(datum), TNF_ERR_INTERNAL);
|
|
|
|
elt = base->base; /* XXX base slot is reused for elttype */
|
|
elt_base = INFO_DERIVED(elt) ? elt->base : elt;
|
|
|
|
*basep = base;
|
|
*eltp = elt;
|
|
*elt_basep = elt_base;
|
|
return (info);
|
|
}
|
|
|
|
/*
|
|
* Return number of elements in array
|
|
*/
|
|
|
|
unsigned
|
|
tnf_get_element_count(tnf_datum_t datum)
|
|
{
|
|
size_t hdr_size, elt_size, self_size;
|
|
struct taginfo *base, *elt, *elt_base;
|
|
|
|
CHECK_ARRAY(datum);
|
|
|
|
(void) get_array_info(datum, &base, &elt, &elt_base);
|
|
hdr_size = base->hdrsize;
|
|
elt_size = INFO_ELEMENT_SIZE(elt_base);
|
|
self_size = _tnf_get_self_size(DATUM_TNF(datum),
|
|
/* LINTED pointer cast may result in improper alignment */
|
|
DATUM_RECORD(datum));
|
|
return (((self_size - hdr_size) / elt_size));
|
|
}
|
|
|
|
/*
|
|
* Fetch indexed element
|
|
*/
|
|
|
|
tnf_datum_t
|
|
tnf_get_element(tnf_datum_t datum, unsigned index)
|
|
{
|
|
size_t hdr_size, elt_size, self_size;
|
|
struct taginfo *base, *elt, *elt_base;
|
|
unsigned count, offset;
|
|
|
|
CHECK_ARRAY(datum);
|
|
|
|
(void) get_array_info(datum, &base, &elt, &elt_base);
|
|
hdr_size = base->hdrsize;
|
|
elt_size = INFO_ELEMENT_SIZE(elt_base);
|
|
self_size = _tnf_get_self_size(DATUM_TNF(datum),
|
|
/* LINTED pointer cast may result in improper alignment */
|
|
DATUM_RECORD(datum));
|
|
|
|
count = (self_size - hdr_size) / elt_size;
|
|
|
|
if (index >= count)
|
|
_tnf_error(DATUM_TNF(datum), TNF_ERR_BADINDEX);
|
|
|
|
offset = hdr_size + (index * elt_size);
|
|
|
|
/*
|
|
* If tagged, use the tag to construct datum
|
|
*/
|
|
if (INFO_TAGGED(elt)) {
|
|
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) + offset));
|
|
/* NULL elements are allowed */
|
|
return ((rec == TNF_NULL)? TNF_DATUM_NULL :
|
|
RECORD_DATUM(tnf, rec));
|
|
} else
|
|
return (DATUM(elt, DATUM_VAL(datum) + offset));
|
|
}
|
|
|
|
/*
|
|
* Return element type of array
|
|
*/
|
|
|
|
tnf_datum_t
|
|
tnf_get_element_type(tnf_datum_t datum)
|
|
{
|
|
struct taginfo *base, *elt, *elt_base;
|
|
|
|
CHECK_ARRAY(datum);
|
|
|
|
(void) get_array_info(datum, &base, &elt, &elt_base);
|
|
|
|
return (RECORD_DATUM(DATUM_TNF(datum), elt->tag));
|
|
}
|
|
|
|
/*
|
|
* Return a char pointer for string record
|
|
*/
|
|
|
|
char *
|
|
tnf_get_chars(tnf_datum_t datum)
|
|
{
|
|
struct taginfo *info, *base, *elt, *elt_base;
|
|
|
|
CHECK_ARRAY(datum);
|
|
|
|
info = get_array_info(datum, &base, &elt, &elt_base);
|
|
|
|
if (!INFO_STRING(info))
|
|
_tnf_error(DATUM_TNF(datum), TNF_ERR_TYPEMISMATCH);
|
|
|
|
return (DATUM_VAL(datum) + base->hdrsize);
|
|
}
|
|
|
|
/*
|
|
* Return the base pointer of array
|
|
*/
|
|
|
|
caddr_t
|
|
tnf_get_elements(tnf_datum_t datum)
|
|
{
|
|
struct taginfo *base, *elt, *elt_base;
|
|
|
|
CHECK_ARRAY(datum);
|
|
|
|
(void) get_array_info(datum, &base, &elt, &elt_base);
|
|
|
|
return ((caddr_t)(DATUM_VAL(datum) + base->hdrsize));
|
|
}
|