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
_tnf_check_array(tnf_datum_t datum)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 *
get_array_info(tnf_datum_t datum,struct taginfo ** basep,struct taginfo ** eltp,struct taginfo ** elt_basep)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
tnf_get_element_count(tnf_datum_t datum)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
tnf_get_element(tnf_datum_t datum,unsigned index)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
tnf_get_element_type(tnf_datum_t datum)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 *
tnf_get_chars(tnf_datum_t datum)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
tnf_get_elements(tnf_datum_t datum)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