xref: /titanic_51/usr/src/lib/libtnf/array.c (revision df14233e629298598736976c5bfcf4a31873745f)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  *	Copyright (c) 1994, by Sun Microsytems, Inc.
24  */
25 
26 #pragma	ident	"%Z%%M%	%I%	%E% SMI"
27 
28 #include "libtnf.h"
29 
30 /*
31  * XXX This module assumes that all arrays are self-sized records.
32  */
33 
34 /*
35  *
36  */
37 
38 static struct taginfo *	get_array_info(
39 	tnf_datum_t,
40 	struct taginfo **base,
41 	struct taginfo **elt,
42 	struct taginfo **elt_base);
43 
44 /*
45  * XXX Assumes arrays are (self-sized) records
46  */
47 
48 void
49 _tnf_check_array(tnf_datum_t datum)
50 {
51 	struct taginfo	*info;
52 
53 	CHECK_RECORD(datum);		/* XXX */
54 
55 	info = DATUM_INFO(datum);
56 
57 	if (!INFO_ARRAY(info))
58 		_tnf_error(DATUM_TNF(datum), TNF_ERR_TYPEMISMATCH);
59 
60 }
61 
62 /*
63  * Helper
64  */
65 
66 static struct taginfo *
67 get_array_info(
68 	tnf_datum_t datum,
69 	struct taginfo **basep,
70 	struct taginfo **eltp,
71 	struct taginfo **elt_basep)
72 {
73 	struct taginfo	*info, *base, *elt, *elt_base;
74 
75 	info	= DATUM_INFO(datum);
76 	base	= INFO_DERIVED(info) ? info->base : info;
77 
78 	if (INFO_DERIVED(base) || (!INFO_ARRAY(base)))
79 		_tnf_error(DATUM_TNF(datum), TNF_ERR_INTERNAL);
80 
81 	elt 	= base->base;	/* XXX base slot is reused for elttype */
82 	elt_base = INFO_DERIVED(elt) ? elt->base : elt;
83 
84 	*basep	= base;
85 	*eltp	= elt;
86 	*elt_basep = elt_base;
87 	return (info);
88 }
89 
90 /*
91  * Return number of elements in array
92  */
93 
94 unsigned
95 tnf_get_element_count(tnf_datum_t datum)
96 {
97 	size_t		hdr_size, elt_size, self_size;
98 	struct taginfo	*base, *elt, *elt_base;
99 
100 	CHECK_ARRAY(datum);
101 
102 	(void) get_array_info(datum, &base, &elt, &elt_base);
103 	hdr_size	= base->hdrsize;
104 	elt_size	= INFO_ELEMENT_SIZE(elt_base);
105 	self_size	= _tnf_get_self_size(DATUM_TNF(datum),
106 		/* LINTED pointer cast may result in improper alignment */
107 				DATUM_RECORD(datum));
108 	return (((self_size - hdr_size) / elt_size));
109 }
110 
111 /*
112  * Fetch indexed element
113  */
114 
115 tnf_datum_t
116 tnf_get_element(tnf_datum_t datum, unsigned index)
117 {
118 	size_t		hdr_size, elt_size, self_size;
119 	struct taginfo	*base, *elt, *elt_base;
120 	unsigned	count, offset;
121 
122 	CHECK_ARRAY(datum);
123 
124 	(void) get_array_info(datum, &base, &elt, &elt_base);
125 	hdr_size	= base->hdrsize;
126 	elt_size	= INFO_ELEMENT_SIZE(elt_base);
127 	self_size	= _tnf_get_self_size(DATUM_TNF(datum),
128 		/* LINTED pointer cast may result in improper alignment */
129 				DATUM_RECORD(datum));
130 
131 	count		= (self_size - hdr_size) / elt_size;
132 
133 	if (index >= count)
134 		_tnf_error(DATUM_TNF(datum), TNF_ERR_BADINDEX);
135 
136 	offset		= hdr_size + (index * elt_size);
137 
138 	/*
139 	 * If tagged, use the tag to construct datum
140 	 */
141 	if (INFO_TAGGED(elt)) {
142 		TNF		*tnf;
143 		tnf_ref32_t	*rec;
144 
145 		tnf = DATUM_TNF(datum);
146 		/* LINTED pointer cast may result in improper alignment */
147 		rec = _GET_REF32(tnf, (tnf_ref32_t *)
148 			(DATUM_VAL(datum) + offset));
149 		/* NULL elements are allowed */
150 		return ((rec == TNF_NULL)? TNF_DATUM_NULL :
151 			RECORD_DATUM(tnf, rec));
152 	} else
153 		return (DATUM(elt, DATUM_VAL(datum) + offset));
154 }
155 
156 /*
157  * Return element type of array
158  */
159 
160 tnf_datum_t
161 tnf_get_element_type(tnf_datum_t datum)
162 {
163 	struct taginfo	*base, *elt, *elt_base;
164 
165 	CHECK_ARRAY(datum);
166 
167 	(void) get_array_info(datum, &base, &elt, &elt_base);
168 
169 	return (RECORD_DATUM(DATUM_TNF(datum), elt->tag));
170 }
171 
172 /*
173  * Return a char pointer for string record
174  */
175 
176 char *
177 tnf_get_chars(tnf_datum_t datum)
178 {
179 	struct taginfo	*info, *base, *elt, *elt_base;
180 
181 	CHECK_ARRAY(datum);
182 
183 	info = get_array_info(datum, &base, &elt, &elt_base);
184 
185 	if (!INFO_STRING(info))
186 		_tnf_error(DATUM_TNF(datum), TNF_ERR_TYPEMISMATCH);
187 
188 	return (DATUM_VAL(datum) + base->hdrsize);
189 }
190 
191 /*
192  * Return the base pointer of array
193  */
194 
195 caddr_t
196 tnf_get_elements(tnf_datum_t datum)
197 {
198 	struct taginfo	*base, *elt, *elt_base;
199 
200 	CHECK_ARRAY(datum);
201 
202 	(void) get_array_info(datum, &base, &elt, &elt_base);
203 
204 	return ((caddr_t)(DATUM_VAL(datum) + base->hdrsize));
205 }
206