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