/src/hdf5/src/H5Toffset.c
Line | Count | Source |
1 | | /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * |
2 | | * Copyright by The HDF Group. * |
3 | | * All rights reserved. * |
4 | | * * |
5 | | * This file is part of HDF5. The full HDF5 copyright notice, including * |
6 | | * terms governing use, modification, and redistribution, is contained in * |
7 | | * the LICENSE file, which can be found at the root of the source code * |
8 | | * distribution tree, or in https://www.hdfgroup.org/licenses. * |
9 | | * If you do not have access to either file, you may request a copy from * |
10 | | * help@hdfgroup.org. * |
11 | | * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ |
12 | | |
13 | | /* |
14 | | * Module Info: This module contains the functionality for setting & querying |
15 | | * the datatype offset for the H5T interface. |
16 | | */ |
17 | | |
18 | | #include "H5Tmodule.h" /* This source code file is part of the H5T module */ |
19 | | |
20 | | #include "H5private.h" /* Generic Functions */ |
21 | | #include "H5Eprivate.h" /* Error handling */ |
22 | | #include "H5Iprivate.h" /* IDs */ |
23 | | #include "H5Tpkg.h" /* Datatypes */ |
24 | | |
25 | | /* Static local functions */ |
26 | | static herr_t H5T__set_offset(const H5T_t *dt, size_t offset); |
27 | | |
28 | | /*------------------------------------------------------------------------- |
29 | | * Function: H5Tget_offset |
30 | | * |
31 | | * Purpose: Retrieves the bit offset of the first significant bit. The |
32 | | * significant bits of an atomic datum can be offset from the |
33 | | * beginning of the memory for that datum by an amount of |
34 | | * padding. The `offset' property specifies the number of bits |
35 | | * of padding that appear to the "right of" the value. That is, |
36 | | * if we have a 32-bit datum with 16-bits of precision having |
37 | | * the value 0x1122 then it will be laid out in memory as (from |
38 | | * small byte address toward larger byte addresses): |
39 | | * |
40 | | * Big Big Little Little |
41 | | * Endian Endian Endian Endian |
42 | | * offset=0 offset=16 offset=0 offset=16 |
43 | | * |
44 | | * 0: [ pad] [0x11] [0x22] [ pad] |
45 | | * 1: [ pad] [0x22] [0x11] [ pad] |
46 | | * 2: [0x11] [ pad] [ pad] [0x22] |
47 | | * 3: [0x22] [ pad] [ pad] [0x11] |
48 | | * |
49 | | * Return: Success: The offset (non-negative) |
50 | | * Failure: Negative |
51 | | * |
52 | | *------------------------------------------------------------------------- |
53 | | */ |
54 | | int |
55 | | H5Tget_offset(hid_t type_id) |
56 | 0 | { |
57 | 0 | H5T_t *dt; |
58 | 0 | int ret_value; |
59 | |
|
60 | 0 | FUNC_ENTER_API(-1) |
61 | | |
62 | | /* Check args */ |
63 | 0 | if (NULL == (dt = (H5T_t *)H5I_object_verify(type_id, H5I_DATATYPE))) |
64 | 0 | HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not an atomic data type"); |
65 | | |
66 | | /* Get offset */ |
67 | 0 | if ((ret_value = H5T_get_offset(dt)) < 0) |
68 | 0 | HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "can't get offset for specified datatype"); |
69 | | |
70 | 0 | done: |
71 | 0 | FUNC_LEAVE_API(ret_value) |
72 | 0 | } /* end H5Tget_offset() */ |
73 | | |
74 | | /*------------------------------------------------------------------------- |
75 | | * Function: H5T_get_offset |
76 | | * |
77 | | * Purpose: Retrieves the bit offset of the first significant bit. The |
78 | | * significant bits of an atomic datum can be offset from the |
79 | | * beginning of the memory for that datum by an amount of |
80 | | * padding. The `offset' property specifies the number of bits |
81 | | * of padding that appear to the "right of" the value. That is, |
82 | | * if we have a 32-bit datum with 16-bits of precision having |
83 | | * the value 0x1122 then it will be laid out in memory as (from |
84 | | * small byte address toward larger byte addresses): |
85 | | * |
86 | | * Big Big Little Little |
87 | | * Endian Endian Endian Endian |
88 | | * offset=0 offset=16 offset=0 offset=16 |
89 | | * |
90 | | * 0: [ pad] [0x11] [0x22] [ pad] |
91 | | * 1: [ pad] [0x22] [0x11] [ pad] |
92 | | * 2: [0x11] [ pad] [ pad] [0x22] |
93 | | * 3: [0x22] [ pad] [ pad] [0x11] |
94 | | * |
95 | | * Return: Success: The offset (non-negative) |
96 | | * Failure: Negative |
97 | | * |
98 | | *------------------------------------------------------------------------- |
99 | | */ |
100 | | int |
101 | | H5T_get_offset(const H5T_t *dt) |
102 | 0 | { |
103 | 0 | int ret_value = -1; /* Return value */ |
104 | |
|
105 | 0 | FUNC_ENTER_NOAPI(-1) |
106 | | |
107 | | /* Defer to parent*/ |
108 | 0 | while (dt->shared->parent) |
109 | 0 | dt = dt->shared->parent; |
110 | 0 | if (!H5T_IS_ATOMIC(dt->shared)) |
111 | 0 | HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "operation not defined for specified data type"); |
112 | | |
113 | | /* Offset */ |
114 | 0 | ret_value = (int)dt->shared->u.atomic.offset; |
115 | |
|
116 | 0 | done: |
117 | 0 | FUNC_LEAVE_NOAPI(ret_value) |
118 | 0 | } /* end H5T_get_offset() */ |
119 | | |
120 | | /*------------------------------------------------------------------------- |
121 | | * Function: H5Tset_offset |
122 | | * |
123 | | * Purpose: Sets the bit offset of the first significant bit. The |
124 | | * significant bits of an atomic datum can be offset from the |
125 | | * beginning of the memory for that datum by an amount of |
126 | | * padding. The `offset' property specifies the number of bits |
127 | | * of padding that appear to the "right of" the value. That is, |
128 | | * if we have a 32-bit datum with 16-bits of precision having |
129 | | * the value 0x1122 then it will be laid out in memory as (from |
130 | | * small byte address toward larger byte addresses): |
131 | | * |
132 | | * Big Big Little Little |
133 | | * Endian Endian Endian Endian |
134 | | * offset=0 offset=16 offset=0 offset=16 |
135 | | * |
136 | | * 0: [ pad] [0x11] [0x22] [ pad] |
137 | | * 1: [ pad] [0x22] [0x11] [ pad] |
138 | | * 2: [0x11] [ pad] [ pad] [0x22] |
139 | | * 3: [0x22] [ pad] [ pad] [0x11] |
140 | | * |
141 | | * If the offset is incremented then the total size is |
142 | | * incremented also if necessary to prevent significant bits of |
143 | | * the value from hanging over the edge of the data type. |
144 | | * |
145 | | * The offset of an H5T_STRING cannot be set to anything but |
146 | | * zero. |
147 | | * |
148 | | * Return: Non-negative on success/Negative on failure |
149 | | * |
150 | | *------------------------------------------------------------------------- |
151 | | */ |
152 | | herr_t |
153 | | H5Tset_offset(hid_t type_id, size_t offset) |
154 | 0 | { |
155 | 0 | H5T_t *dt; |
156 | 0 | herr_t ret_value = SUCCEED; /* Return value */ |
157 | |
|
158 | 0 | FUNC_ENTER_API(FAIL) |
159 | | |
160 | | /* Check args */ |
161 | 0 | if (NULL == (dt = (H5T_t *)H5I_object_verify(type_id, H5I_DATATYPE))) |
162 | 0 | HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not an atomic data type"); |
163 | 0 | if (H5T_STATE_TRANSIENT != dt->shared->state) |
164 | 0 | HGOTO_ERROR(H5E_ARGS, H5E_CANTINIT, FAIL, "data type is read-only"); |
165 | 0 | if (H5T_STRING == dt->shared->type && offset != 0) |
166 | 0 | HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "offset must be zero for this type"); |
167 | 0 | if (H5T_ENUM == dt->shared->type && dt->shared->u.enumer.nmembs > 0) |
168 | 0 | HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "operation not allowed after members are defined"); |
169 | 0 | if (H5T_COMPOUND == dt->shared->type || H5T_REFERENCE == dt->shared->type || |
170 | 0 | H5T_OPAQUE == dt->shared->type) |
171 | 0 | HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "operation not defined for this datatype"); |
172 | | |
173 | | /* Do the real work */ |
174 | 0 | if (H5T__set_offset(dt, offset) < 0) |
175 | 0 | HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to set offset"); |
176 | | |
177 | 0 | done: |
178 | 0 | FUNC_LEAVE_API(ret_value) |
179 | 0 | } |
180 | | |
181 | | /*------------------------------------------------------------------------- |
182 | | * Function: H5T__set_offset |
183 | | * |
184 | | * Purpose: Sets the bit offset of the first significant bit. The |
185 | | * significant bits of an atomic datum can be offset from the |
186 | | * beginning of the memory for that datum by an amount of |
187 | | * padding. The `offset' property specifies the number of bits |
188 | | * of padding that appear to the "right of" the value. That is, |
189 | | * if we have a 32-bit datum with 16-bits of precision having |
190 | | * the value 0x1122 then it will be laid out in memory as (from |
191 | | * small byte address toward larger byte addresses): |
192 | | * |
193 | | * Big Big Little Little |
194 | | * Endian Endian Endian Endian |
195 | | * offset=0 offset=16 offset=0 offset=16 |
196 | | * |
197 | | * 0: [ pad] [0x11] [0x22] [ pad] |
198 | | * 1: [ pad] [0x22] [0x11] [ pad] |
199 | | * 2: [0x11] [ pad] [ pad] [0x22] |
200 | | * 3: [0x22] [ pad] [ pad] [0x11] |
201 | | * |
202 | | * If the offset is incremented then the total size is |
203 | | * incremented also if necessary to prevent significant bits of |
204 | | * the value from hanging over the edge of the data type. |
205 | | * |
206 | | * The offset of an H5T_STRING cannot be set to anything but |
207 | | * zero. |
208 | | * |
209 | | * Return: Non-negative on success/Negative on failure |
210 | | * |
211 | | *------------------------------------------------------------------------- |
212 | | */ |
213 | | static herr_t |
214 | | H5T__set_offset(const H5T_t *dt, size_t offset) |
215 | 0 | { |
216 | 0 | herr_t ret_value = SUCCEED; /* Return value */ |
217 | |
|
218 | 0 | FUNC_ENTER_PACKAGE |
219 | | |
220 | | /* Check args */ |
221 | 0 | assert(dt); |
222 | 0 | assert(H5T_STRING != dt->shared->type || 0 == offset); |
223 | 0 | assert(H5T_REFERENCE != dt->shared->type); |
224 | 0 | assert(H5T_OPAQUE != dt->shared->type); |
225 | 0 | assert(H5T_COMPOUND != dt->shared->type); |
226 | 0 | assert(!(H5T_ENUM == dt->shared->type && 0 == dt->shared->u.enumer.nmembs)); |
227 | |
|
228 | 0 | if (dt->shared->parent) { |
229 | 0 | if (H5T__set_offset(dt->shared->parent, offset) < 0) |
230 | 0 | HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to set offset for base type"); |
231 | | |
232 | | /* Adjust size of datatype appropriately */ |
233 | 0 | if (dt->shared->type == H5T_ARRAY) |
234 | 0 | dt->shared->size = dt->shared->parent->shared->size * dt->shared->u.array.nelem; |
235 | 0 | else if (dt->shared->type == H5T_COMPLEX) |
236 | 0 | dt->shared->size = 2 * dt->shared->parent->shared->size; |
237 | 0 | else if (dt->shared->type != H5T_VLEN) |
238 | 0 | dt->shared->size = dt->shared->parent->shared->size; |
239 | 0 | } |
240 | 0 | else { |
241 | 0 | if (offset + dt->shared->u.atomic.prec > 8 * dt->shared->size) |
242 | 0 | dt->shared->size = (offset + dt->shared->u.atomic.prec + 7) / 8; |
243 | 0 | dt->shared->u.atomic.offset = offset; |
244 | 0 | } |
245 | | |
246 | 0 | done: |
247 | 0 | FUNC_LEAVE_NOAPI(ret_value) |
248 | 0 | } |