/src/gdal/netcdf-c-4.7.4/libdispatch/doffsets.c
Line | Count | Source (jump to first uncovered line) |
1 | | /********************************************************************* |
2 | | * Copyright 2018, UCAR/Unidata |
3 | | * See netcdf/COPYRIGHT file for copying and redistribution conditions. |
4 | | * $Header: /upc/share/CVS/netcdf-3/ncgen/offsets.c,v 1.1 2009/09/25 18:22:40 dmh Exp $ |
5 | | *********************************************************************/ |
6 | | |
7 | | /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * |
8 | | * Copyright by The HDF Group. * |
9 | | * Copyright by the Board of Trustees of the University of Illinois. * |
10 | | * All rights reserved. * |
11 | | * * |
12 | | * This file is part of HDF5. The full HDF5 copyright notice, including * |
13 | | * terms governing use, modification, and redistribution, is contained in * |
14 | | * the files COPYING and Copyright.html. COPYING can be found at the root * |
15 | | * of the source code distribution tree; Copyright.html can be found at the * |
16 | | * root level of an installed copy of the electronic HDF5 document set and * |
17 | | * is linked from the top-level documents page. It can also be found at * |
18 | | * http://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have * |
19 | | * access to either file, you may request a copy from help@hdfgroup.org. * |
20 | | * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ |
21 | | |
22 | | /* |
23 | | This code is a variantion of the H5detect.c code from HDF5. |
24 | | Author: D. Heimbigner 10/7/2008 |
25 | | */ |
26 | | |
27 | | #include "config.h" |
28 | | #include <stdlib.h> |
29 | | #include <stdio.h> |
30 | | #include <string.h> |
31 | | #include <assert.h> |
32 | | #include "nclog.h" |
33 | | |
34 | | #ifdef OFFSETTEST |
35 | | |
36 | | static void* emalloc(size_t); |
37 | | |
38 | | typedef int nc_type; |
39 | | typedef struct nc_vlen_t { |
40 | | size_t len; |
41 | | void* p; |
42 | | } nc_vlen_t; |
43 | | |
44 | | #define NC_NAT 0 /* NAT = 'Not A Type' (c.f. NaN) */ |
45 | | #define NC_BYTE 1 /* signed 1 byte integer */ |
46 | | #define NC_CHAR 2 /* ISO/ASCII character */ |
47 | | #define NC_SHORT 3 /* signed 2 byte integer */ |
48 | | #define NC_INT 4 /* signed 4 byte integer */ |
49 | | #define NC_FLOAT 5 /* single precision floating point number */ |
50 | | #define NC_DOUBLE 6 /* double precision floating point number */ |
51 | | #define NC_UBYTE 7 /* unsigned 1 byte int */ |
52 | | #define NC_USHORT 8 /* unsigned 2-byte int */ |
53 | | #define NC_UINT 9 /* unsigned 4-byte int */ |
54 | | #define NC_INT64 10 /* signed 8-byte int */ |
55 | | #define NC_UINT64 11 /* unsigned 8-byte int */ |
56 | | #define NC_STRING 12 /* string */ |
57 | | #define NC_STRING 12 /* string */ |
58 | | #define NC_VLEN 13 |
59 | | #define NC_OPAQUE 14 |
60 | | #define NC_ENUM 15 |
61 | | #define NC_COMPOUND 16 |
62 | | #endif |
63 | | |
64 | | #include "netcdf.h" |
65 | | #include "ncoffsets.h" |
66 | | |
67 | | |
68 | | /* |
69 | | The heart of this is the following macro, |
70 | | which computes the offset of a field x |
71 | | when preceded by a char field. |
72 | | The assumptions appear to be as follows: |
73 | | 1. the offset produced in this situation indicates |
74 | | the alignment for x relative in such a way that it |
75 | | depends only on the types that precede it in the struct. |
76 | | 2. the compiler does not reorder fields. |
77 | | 3. arrays are tightly packed. |
78 | | 4. nested structs are alignd according to their first member |
79 | | (this actually follows from C language requirement that |
80 | | a struct can legally be cast to an instance of its first member). |
81 | | Given the alignments for the various common primitive types, |
82 | | it is assumed that one can use them anywhere to construct |
83 | | the layout of a struct of such types. |
84 | | It seems to work for HDF5 for a wide variety of machines. |
85 | | Note that technically, this is compiler dependent, but in practice |
86 | | all compilers seem to mimic the gcc rules. |
87 | | */ |
88 | | |
89 | 24 | #define COMP_ALIGNMENT(DST,TYPE) {\ |
90 | 24 | struct {char f1; TYPE x;} tmp; \ |
91 | 24 | DST.type_name = #TYPE ; \ |
92 | 24 | DST.alignment = (size_t)((char*)(&(tmp.x)) - (char*)(&tmp));} |
93 | | |
94 | | #if 0 |
95 | | char* ctypenames[NCTYPES] = { |
96 | | (char*)NULL, |
97 | | "char","unsigned char", |
98 | | "short","unsigned short", |
99 | | "int","unsigned int", |
100 | | "long long","unsigned long long", |
101 | | "float","double", |
102 | | "void*","nc_vlen_t" |
103 | | }; |
104 | | #endif |
105 | | |
106 | | static NCtypealignvec vec[NC_NCTYPES]; |
107 | | static NCtypealignset set; |
108 | | static int NC_alignments_computed = 0; |
109 | | |
110 | | /* Argument is a netcdf type class, except compound|ENUM */ |
111 | | size_t |
112 | | NC_class_alignment(int ncclass) |
113 | 0 | { |
114 | 0 | NCalignment* align = NULL; |
115 | 0 | int index = 0; |
116 | 0 | if(!NC_alignments_computed) |
117 | 0 | NC_compute_alignments(); |
118 | 0 | switch (ncclass) { |
119 | 0 | case NC_BYTE: index = NC_UCHARINDEX; break; |
120 | 0 | case NC_CHAR: index = NC_CHARINDEX; break; |
121 | 0 | case NC_SHORT: index = NC_SHORTINDEX; break; |
122 | 0 | case NC_INT: index = NC_INTINDEX; break; |
123 | 0 | case NC_FLOAT: index = NC_FLOATINDEX; break; |
124 | 0 | case NC_DOUBLE: index = NC_DOUBLEINDEX; break; |
125 | 0 | case NC_UBYTE: index = NC_UCHARINDEX; break; |
126 | 0 | case NC_USHORT: index = NC_USHORTINDEX; break; |
127 | 0 | case NC_UINT: index = NC_UINTINDEX; break; |
128 | 0 | case NC_INT64: index = NC_LONGLONGINDEX; break; |
129 | 0 | case NC_UINT64: index = NC_ULONGLONGINDEX; break; |
130 | 0 | case NC_STRING: index = NC_PTRINDEX; break; |
131 | | /* Here class matters */ |
132 | 0 | case NC_VLEN: index = NC_NCVLENINDEX; break; |
133 | 0 | case NC_OPAQUE: index = NC_UCHARINDEX; break; |
134 | 0 | case NC_ENUM: /* fall thru */ |
135 | 0 | case NC_COMPOUND: /* fall thru */ |
136 | 0 | default: |
137 | 0 | nclog(NCLOGERR,"nc_class_alignment: class code %d cannot be aligned",ncclass); |
138 | 0 | return 0; |
139 | 0 | } |
140 | 0 | align = &vec[index]; |
141 | 0 | return align->alignment; |
142 | 0 | } |
143 | | |
144 | | void |
145 | | NC_compute_alignments(void) |
146 | 1 | { |
147 | 1 | if(NC_alignments_computed) return; |
148 | | /* Compute the alignments for all the common C data types*/ |
149 | | /* First for the struct*/ |
150 | | /* initialize*/ |
151 | 1 | memset((void*)&set,0,sizeof(set)); |
152 | 1 | memset((void*)vec,0,sizeof(vec)); |
153 | | |
154 | 1 | COMP_ALIGNMENT(set.charalign,char); |
155 | 1 | COMP_ALIGNMENT(set.ucharalign,unsigned char); |
156 | 1 | COMP_ALIGNMENT(set.shortalign,short); |
157 | 1 | COMP_ALIGNMENT(set.ushortalign,unsigned short); |
158 | 1 | COMP_ALIGNMENT(set.intalign,int); |
159 | 1 | COMP_ALIGNMENT(set.uintalign,unsigned int); |
160 | 1 | COMP_ALIGNMENT(set.longlongalign,long long); |
161 | 1 | COMP_ALIGNMENT(set.ulonglongalign,unsigned long long); |
162 | 1 | COMP_ALIGNMENT(set.floatalign,float); |
163 | 1 | COMP_ALIGNMENT(set.doublealign,double); |
164 | 1 | COMP_ALIGNMENT(set.ptralign,void*); |
165 | 1 | COMP_ALIGNMENT(set.ncvlenalign,nc_vlen_t); |
166 | | |
167 | | /* Then the vector*/ |
168 | 1 | COMP_ALIGNMENT(vec[NC_CHARINDEX],char); |
169 | 1 | COMP_ALIGNMENT(vec[NC_UCHARINDEX],unsigned char); |
170 | 1 | COMP_ALIGNMENT(vec[NC_SHORTINDEX],short); |
171 | 1 | COMP_ALIGNMENT(vec[NC_USHORTINDEX],unsigned short); |
172 | 1 | COMP_ALIGNMENT(vec[NC_INTINDEX],int); |
173 | 1 | COMP_ALIGNMENT(vec[NC_UINTINDEX],unsigned int); |
174 | 1 | COMP_ALIGNMENT(vec[NC_LONGLONGINDEX],long long); |
175 | 1 | COMP_ALIGNMENT(vec[NC_ULONGLONGINDEX],unsigned long long); |
176 | 1 | COMP_ALIGNMENT(vec[NC_FLOATINDEX],float); |
177 | 1 | COMP_ALIGNMENT(vec[NC_DOUBLEINDEX],double); |
178 | 1 | COMP_ALIGNMENT(vec[NC_PTRINDEX],void*); |
179 | 1 | COMP_ALIGNMENT(vec[NC_NCVLENINDEX],nc_vlen_t); |
180 | 1 | NC_alignments_computed = 1; |
181 | 1 | } |
182 | | |
183 | | #ifdef OFFSETTEST |
184 | | |
185 | | /* Compute the alignment of TYPE when it is preceded |
186 | | by a field of type TYPE1 |
187 | | */ |
188 | | #define COMP_ALIGNMENT1(DST,TYPE1,TYPE) {\ |
189 | | struct {TYPE1 f1; TYPE x;} tmp; \ |
190 | | DST.type_name = #TYPE ; \ |
191 | | DST.alignment = (size_t)((char*)(&(tmp.x)) - (char*)(&tmp));} |
192 | | |
193 | | /* Compute the alignment of TYPE when it is preceded |
194 | | by a field of type TYPE1 and a field of type TYPE2 |
195 | | */ |
196 | | #define COMP_ALIGNMENT2(DST,TYPE1,TYPE2,TYPE) {\ |
197 | | struct {TYPE1 f1, TYPE2 f2; TYPE x;} tmp; \ |
198 | | DST.type_name = #TYPE ; \ |
199 | | DST.alignment = (size_t)((char*)(&(tmp.x)) - (char*)(&tmp));} |
200 | | |
201 | | /* Compute the alignment of TYPE when it is preceded |
202 | | by a field of type TYPE1 and a field of type TYPE2 |
203 | | */ |
204 | | #define COMP_SIZE0(DST,TYPE1,TYPE2) {\ |
205 | | struct {TYPE1 c; TYPE2 x;} tmp; \ |
206 | | DST = sizeof(tmp); } |
207 | | |
208 | | static char* |
209 | | padname(char* name) |
210 | | { |
211 | | #define MAX 20 |
212 | | if(name == NULL) name = "null"; |
213 | | int len = strlen(name); |
214 | | if(len > MAX) len = MAX; |
215 | | char* s = (char*)emalloc(MAX+1); |
216 | | memset(s,' ',MAX); |
217 | | s[MAX+1] = '\0'; |
218 | | strncpy(s,name,len); |
219 | | return s; |
220 | | } |
221 | | |
222 | | static void |
223 | | verify(NCtypealignvec* vec) |
224 | | { |
225 | | int i,j; |
226 | | NCtypealignvec* vec16; |
227 | | NCtypealignvec* vec32; |
228 | | int* sizes8; |
229 | | int* sizes16; |
230 | | int* sizes32; |
231 | | |
232 | | vec16 = (NCtypealignvec*)emalloc(sizeof(NCtypealignvec)*NCTYPES); |
233 | | vec32 = (NCtypealignvec*)emalloc(sizeof(NCtypealignvec)*NCTYPES); |
234 | | sizes8 = (int*)emalloc(sizeof(int)*NCTYPES); |
235 | | sizes16 = (int*)emalloc(sizeof(int)*NCTYPES); |
236 | | sizes32 = (int*)emalloc(sizeof(int)*NCTYPES); |
237 | | |
238 | | COMP_SIZE0(sizes8[1],char,char); |
239 | | COMP_SIZE0(sizes8[2],unsigned char,char); |
240 | | COMP_SIZE0(sizes8[3],short,char); |
241 | | COMP_SIZE0(sizes8[4],unsigned short,char); |
242 | | COMP_SIZE0(sizes8[5],int,char); |
243 | | COMP_SIZE0(sizes8[6],unsigned int,char); |
244 | | COMP_SIZE0(sizes8[7],long long,char); |
245 | | COMP_SIZE0(sizes8[8],unsigned long long,char); |
246 | | COMP_SIZE0(sizes8[9],float,char); |
247 | | COMP_SIZE0(sizes8[10],double,char) ; |
248 | | COMP_SIZE0(sizes8[11],void*,char); |
249 | | COMP_SIZE0(sizes8[12],nc_vlen_t,char); |
250 | | |
251 | | COMP_SIZE0(sizes16[1],char,short); |
252 | | COMP_SIZE0(sizes16[2],unsigned char,short); |
253 | | COMP_SIZE0(sizes16[3],short,short); |
254 | | COMP_SIZE0(sizes16[4],unsigned short,short); |
255 | | COMP_SIZE0(sizes16[5],int,short); |
256 | | COMP_SIZE0(sizes16[6],unsigned int,short); |
257 | | COMP_SIZE0(sizes16[7],long long,short); |
258 | | COMP_SIZE0(sizes16[8],unsigned long long,short); |
259 | | COMP_SIZE0(sizes16[9],float,short); |
260 | | COMP_SIZE0(sizes16[10],double,short) ; |
261 | | COMP_SIZE0(sizes16[11],void*,short); |
262 | | COMP_SIZE0(sizes16[12],nc_vlen_t*,short); |
263 | | |
264 | | COMP_SIZE0(sizes32[1],char,int); |
265 | | COMP_SIZE0(sizes32[2],unsigned char,int); |
266 | | COMP_SIZE0(sizes32[3],short,int); |
267 | | COMP_SIZE0(sizes32[4],unsigned short,int); |
268 | | COMP_SIZE0(sizes32[5],int,int); |
269 | | COMP_SIZE0(sizes32[6],unsigned int,int); |
270 | | COMP_SIZE0(sizes32[7],long long,int); |
271 | | COMP_SIZE0(sizes32[8],unsigned long long,int); |
272 | | COMP_SIZE0(sizes32[9],float,int); |
273 | | COMP_SIZE0(sizes32[10],double,int) ; |
274 | | COMP_SIZE0(sizes32[11],void*,int); |
275 | | COMP_SIZE0(sizes32[12],nc_vlen_t*,int); |
276 | | |
277 | | COMP_ALIGNMENT1(vec16[1],char,short); |
278 | | COMP_ALIGNMENT1(vec16[2],unsigned char,short); |
279 | | COMP_ALIGNMENT1(vec16[3],short,short); |
280 | | COMP_ALIGNMENT1(vec16[4],unsigned short,short); |
281 | | COMP_ALIGNMENT1(vec16[5],int,short); |
282 | | COMP_ALIGNMENT1(vec16[6],unsigned int,short); |
283 | | COMP_ALIGNMENT1(vec32[7],long long,short); |
284 | | COMP_ALIGNMENT1(vec32[8],unsigned long long,short); |
285 | | COMP_ALIGNMENT1(vec16[9],float,short); |
286 | | COMP_ALIGNMENT1(vec16[10],double,short); |
287 | | COMP_ALIGNMENT1(vec16[11],void*,short); |
288 | | COMP_ALIGNMENT1(vec16[12],nc_vlen_t*,short); |
289 | | |
290 | | COMP_ALIGNMENT1(vec32[1],char,short); |
291 | | COMP_ALIGNMENT1(vec32[2],unsigned char,short); |
292 | | COMP_ALIGNMENT1(vec32[3],char,short); |
293 | | COMP_ALIGNMENT1(vec32[4],unsigned short,short); |
294 | | COMP_ALIGNMENT1(vec32[5],int,int); |
295 | | COMP_ALIGNMENT1(vec32[6],unsigned int,int); |
296 | | COMP_ALIGNMENT1(vec32[7],long long,int); |
297 | | COMP_ALIGNMENT1(vec32[8],unsigned long long,int); |
298 | | COMP_ALIGNMENT1(vec32[9],float,int); |
299 | | COMP_ALIGNMENT1(vec32[10],double,int); |
300 | | COMP_ALIGNMENT1(vec32[11],void*,int); |
301 | | COMP_ALIGNMENT1(vec32[12],nc_vlen_t*,int); |
302 | | |
303 | | for(i=0;i<NCTYPES;i++) { |
304 | | printf("%s: size=%2d alignment=%2d\n", |
305 | | padname(vec[i].type_name),sizes8[i],vec[i].alignment); |
306 | | } |
307 | | for(i=0;i<NCTYPES;i++) { |
308 | | printf("short vs %s: size=%2d alignment=%2d\n", |
309 | | padname(vec[i].type_name),sizes16[i],vec16[i].alignment); |
310 | | } |
311 | | for(i=0;i<NCTYPES;i++) { |
312 | | printf("int vs %s: size=%2d alignment=%2d\n", |
313 | | padname(vec[i].type_name),sizes32[i],vec32[i].alignment); |
314 | | } |
315 | | |
316 | | } |
317 | | |
318 | | void * |
319 | | emalloc(size_t bytes) { |
320 | | size_t *memory; |
321 | | memory = malloc(bytes); |
322 | | if(memory == 0) { |
323 | | printf("malloc failed\n"); |
324 | | exit(2); |
325 | | } |
326 | | return memory; |
327 | | } |
328 | | |
329 | | int |
330 | | main(int argc, char** argv) |
331 | | { |
332 | | int i; |
333 | | |
334 | | compute_alignments(); |
335 | | |
336 | | verify(vec); |
337 | | |
338 | | /* |
339 | | for(i=0;i<NCTYPES;i++) { |
340 | | printf("%s:\talignment=%d\n",vec[i].type_name,vec[i].alignment); |
341 | | } |
342 | | */ |
343 | | exit(0); |
344 | | } |
345 | | #endif /*OFFSETTEST*/ |