1 /*********************************************************************
2 * Copyright 1993, 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 #define COMP_ALIGNMENT(DST,TYPE) {\
90 struct {char f1; TYPE x;} tmp; \
91 DST.type_name = #TYPE ; \
92 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 int NC_alignments_computed = 0;
109
110 /* Argument is a netcdf type class, except compound|ENUM */
111 size_t
NC_class_alignment(int ncclass)112 NC_class_alignment(int ncclass)
113 {
114 NCalignment* align = NULL;
115 int index = 0;
116 if(!NC_alignments_computed) {
117 NC_compute_alignments();
118 NC_alignments_computed = 1;
119 }
120 switch (ncclass) {
121 case NC_BYTE: index = NC_UCHARINDEX; break;
122 case NC_CHAR: index = NC_CHARINDEX; break;
123 case NC_SHORT: index = NC_SHORTINDEX; break;
124 case NC_INT: index = NC_INTINDEX; break;
125 case NC_FLOAT: index = NC_FLOATINDEX; break;
126 case NC_DOUBLE: index = NC_DOUBLEINDEX; break;
127 case NC_UBYTE: index = NC_UCHARINDEX; break;
128 case NC_USHORT: index = NC_USHORTINDEX; break;
129 case NC_UINT: index = NC_UINTINDEX; break;
130 case NC_INT64: index = NC_LONGLONGINDEX; break;
131 case NC_UINT64: index = NC_ULONGLONGINDEX; break;
132 case NC_STRING: index = NC_PTRINDEX; break;
133 /* Here class matters */
134 case NC_VLEN: index = NC_NCVLENINDEX; break;
135 case NC_OPAQUE: index = NC_UCHARINDEX; break;
136 case NC_ENUM: /* fall thru */
137 case NC_COMPOUND: /* fall thru */
138 default:
139 nclog(NCLOGERR,"nc_class_alignment: class code %d cannot be aligned",ncclass);
140 return 0;
141 }
142 align = &vec[index];
143 return align->alignment;
144 }
145
146
147 void
NC_compute_alignments(void)148 NC_compute_alignments(void)
149 {
150 if(NC_alignments_computed) return;
151 /* Compute the alignments for all the common C data types*/
152 /* First for the struct*/
153 /* initialize*/
154 memset((void*)&set,0,sizeof(set));
155 memset((void*)vec,0,sizeof(vec));
156
157 COMP_ALIGNMENT(set.charalign,char);
158 COMP_ALIGNMENT(set.ucharalign,unsigned char);
159 COMP_ALIGNMENT(set.shortalign,short);
160 COMP_ALIGNMENT(set.ushortalign,unsigned short);
161 COMP_ALIGNMENT(set.intalign,int);
162 COMP_ALIGNMENT(set.uintalign,unsigned int);
163 COMP_ALIGNMENT(set.longlongalign,long long);
164 COMP_ALIGNMENT(set.ulonglongalign,unsigned long long);
165 COMP_ALIGNMENT(set.floatalign,float);
166 COMP_ALIGNMENT(set.doublealign,double);
167 COMP_ALIGNMENT(set.ptralign,void*);
168 COMP_ALIGNMENT(set.ncvlenalign,nc_vlen_t);
169
170 /* Then the vector*/
171 COMP_ALIGNMENT(vec[NC_CHARINDEX],char);
172 COMP_ALIGNMENT(vec[NC_UCHARINDEX],unsigned char);
173 COMP_ALIGNMENT(vec[NC_SHORTINDEX],short);
174 COMP_ALIGNMENT(vec[NC_USHORTINDEX],unsigned short);
175 COMP_ALIGNMENT(vec[NC_INTINDEX],int);
176 COMP_ALIGNMENT(vec[NC_UINTINDEX],unsigned int);
177 COMP_ALIGNMENT(vec[NC_LONGLONGINDEX],long long);
178 COMP_ALIGNMENT(vec[NC_ULONGLONGINDEX],unsigned long long);
179 COMP_ALIGNMENT(vec[NC_FLOATINDEX],float);
180 COMP_ALIGNMENT(vec[NC_DOUBLEINDEX],double);
181 COMP_ALIGNMENT(vec[NC_PTRINDEX],void*);
182 COMP_ALIGNMENT(vec[NC_NCVLENINDEX],nc_vlen_t);
183 NC_alignments_computed = 1;
184 }
185
186 #ifdef OFFSETTEST
187
188 /* Compute the alignment of TYPE when it is preceded
189 by a field of type TYPE1
190 */
191 #define COMP_ALIGNMENT1(DST,TYPE1,TYPE) {\
192 struct {TYPE1 f1; TYPE x;} tmp; \
193 DST.type_name = #TYPE ; \
194 DST.alignment = (size_t)((char*)(&(tmp.x)) - (char*)(&tmp));}
195
196 /* Compute the alignment of TYPE when it is preceded
197 by a field of type TYPE1 and a field of type TYPE2
198 */
199 #define COMP_ALIGNMENT2(DST,TYPE1,TYPE2,TYPE) {\
200 struct {TYPE1 f1, TYPE2 f2; TYPE x;} tmp; \
201 DST.type_name = #TYPE ; \
202 DST.alignment = (size_t)((char*)(&(tmp.x)) - (char*)(&tmp));}
203
204 /* Compute the alignment of TYPE when it is preceded
205 by a field of type TYPE1 and a field of type TYPE2
206 */
207 #define COMP_SIZE0(DST,TYPE1,TYPE2) {\
208 struct {TYPE1 c; TYPE2 x;} tmp; \
209 DST = sizeof(tmp); }
210
211 static char*
padname(char * name)212 padname(char* name)
213 {
214 #define MAX 20
215 if(name == NULL) name = "null";
216 int len = strlen(name);
217 if(len > MAX) len = MAX;
218 char* s = (char*)emalloc(MAX+1);
219 memset(s,' ',MAX);
220 s[MAX+1] = '\0';
221 strncpy(s,name,len);
222 return s;
223 }
224
225 static void
verify(NCtypealignvec * vec)226 verify(NCtypealignvec* vec)
227 {
228 int i,j;
229 NCtypealignvec* vec16;
230 NCtypealignvec* vec32;
231 int* sizes8;
232 int* sizes16;
233 int* sizes32;
234
235 vec16 = (NCtypealignvec*)emalloc(sizeof(NCtypealignvec)*NCTYPES);
236 vec32 = (NCtypealignvec*)emalloc(sizeof(NCtypealignvec)*NCTYPES);
237 sizes8 = (int*)emalloc(sizeof(int)*NCTYPES);
238 sizes16 = (int*)emalloc(sizeof(int)*NCTYPES);
239 sizes32 = (int*)emalloc(sizeof(int)*NCTYPES);
240
241 COMP_SIZE0(sizes8[1],char,char);
242 COMP_SIZE0(sizes8[2],unsigned char,char);
243 COMP_SIZE0(sizes8[3],short,char);
244 COMP_SIZE0(sizes8[4],unsigned short,char);
245 COMP_SIZE0(sizes8[5],int,char);
246 COMP_SIZE0(sizes8[6],unsigned int,char);
247 COMP_SIZE0(sizes8[7],long long,char);
248 COMP_SIZE0(sizes8[8],unsigned long long,char);
249 COMP_SIZE0(sizes8[9],float,char);
250 COMP_SIZE0(sizes8[10],double,char) ;
251 COMP_SIZE0(sizes8[11],void*,char);
252 COMP_SIZE0(sizes8[12],nc_vlen_t,char);
253
254 COMP_SIZE0(sizes16[1],char,short);
255 COMP_SIZE0(sizes16[2],unsigned char,short);
256 COMP_SIZE0(sizes16[3],short,short);
257 COMP_SIZE0(sizes16[4],unsigned short,short);
258 COMP_SIZE0(sizes16[5],int,short);
259 COMP_SIZE0(sizes16[6],unsigned int,short);
260 COMP_SIZE0(sizes16[7],long long,short);
261 COMP_SIZE0(sizes16[8],unsigned long long,short);
262 COMP_SIZE0(sizes16[9],float,short);
263 COMP_SIZE0(sizes16[10],double,short) ;
264 COMP_SIZE0(sizes16[11],void*,short);
265 COMP_SIZE0(sizes16[12],nc_vlen_t*,short);
266
267 COMP_SIZE0(sizes32[1],char,int);
268 COMP_SIZE0(sizes32[2],unsigned char,int);
269 COMP_SIZE0(sizes32[3],short,int);
270 COMP_SIZE0(sizes32[4],unsigned short,int);
271 COMP_SIZE0(sizes32[5],int,int);
272 COMP_SIZE0(sizes32[6],unsigned int,int);
273 COMP_SIZE0(sizes32[7],long long,int);
274 COMP_SIZE0(sizes32[8],unsigned long long,int);
275 COMP_SIZE0(sizes32[9],float,int);
276 COMP_SIZE0(sizes32[10],double,int) ;
277 COMP_SIZE0(sizes32[11],void*,int);
278 COMP_SIZE0(sizes32[12],nc_vlen_t*,int);
279
280 COMP_ALIGNMENT1(vec16[1],char,short);
281 COMP_ALIGNMENT1(vec16[2],unsigned char,short);
282 COMP_ALIGNMENT1(vec16[3],short,short);
283 COMP_ALIGNMENT1(vec16[4],unsigned short,short);
284 COMP_ALIGNMENT1(vec16[5],int,short);
285 COMP_ALIGNMENT1(vec16[6],unsigned int,short);
286 COMP_ALIGNMENT1(vec32[7],long long,short);
287 COMP_ALIGNMENT1(vec32[8],unsigned long long,short);
288 COMP_ALIGNMENT1(vec16[9],float,short);
289 COMP_ALIGNMENT1(vec16[10],double,short);
290 COMP_ALIGNMENT1(vec16[11],void*,short);
291 COMP_ALIGNMENT1(vec16[12],nc_vlen_t*,short);
292
293 COMP_ALIGNMENT1(vec32[1],char,short);
294 COMP_ALIGNMENT1(vec32[2],unsigned char,short);
295 COMP_ALIGNMENT1(vec32[3],char,short);
296 COMP_ALIGNMENT1(vec32[4],unsigned short,short);
297 COMP_ALIGNMENT1(vec32[5],int,int);
298 COMP_ALIGNMENT1(vec32[6],unsigned int,int);
299 COMP_ALIGNMENT1(vec32[7],long long,int);
300 COMP_ALIGNMENT1(vec32[8],unsigned long long,int);
301 COMP_ALIGNMENT1(vec32[9],float,int);
302 COMP_ALIGNMENT1(vec32[10],double,int);
303 COMP_ALIGNMENT1(vec32[11],void*,int);
304 COMP_ALIGNMENT1(vec32[12],nc_vlen_t*,int);
305
306 for(i=0;i<NCTYPES;i++) {
307 printf("%s: size=%2d alignment=%2d\n",
308 padname(vec[i].type_name),sizes8[i],vec[i].alignment);
309 }
310 for(i=0;i<NCTYPES;i++) {
311 printf("short vs %s: size=%2d alignment=%2d\n",
312 padname(vec[i].type_name),sizes16[i],vec16[i].alignment);
313 }
314 for(i=0;i<NCTYPES;i++) {
315 printf("int vs %s: size=%2d alignment=%2d\n",
316 padname(vec[i].type_name),sizes32[i],vec32[i].alignment);
317 }
318
319 }
320
321 void *
emalloc(size_t bytes)322 emalloc(size_t bytes) {
323 size_t *memory;
324 memory = malloc(bytes);
325 if(memory == 0) {
326 printf("malloc failed\n");
327 exit(2);
328 }
329 return memory;
330 }
331
332 int
main(int argc,char ** argv)333 main(int argc, char** argv)
334 {
335 int i;
336
337 compute_alignments();
338
339 verify(vec);
340
341 /*
342 for(i=0;i<NCTYPES;i++) {
343 printf("%s:\talignment=%d\n",vec[i].type_name,vec[i].alignment);
344 }
345 */
346 exit(0);
347 }
348 #endif /*OFFSETTEST*/
349