Coverage Report

Created: 2023-05-28 06:42

/src/netcdf-c/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
int
112
NC_class_alignment(int ncclass, size_t* alignp)
113
0
{
114
0
    int stat = NC_NOERR;
115
0
    NCalignment* align = NULL;
116
0
    int index = 0;
117
0
    if(!NC_alignments_computed)
118
0
  NC_compute_alignments();
119
0
    switch (ncclass) {
120
0
      case NC_BYTE: index = NC_UCHARINDEX; break;
121
0
      case NC_CHAR: index = NC_CHARINDEX; break;
122
0
      case NC_SHORT: index = NC_SHORTINDEX; break;
123
0
      case NC_INT: index = NC_INTINDEX; break;
124
0
      case NC_FLOAT: index = NC_FLOATINDEX; break;
125
0
      case NC_DOUBLE: index = NC_DOUBLEINDEX; break;
126
0
      case NC_UBYTE: index = NC_UCHARINDEX; break;
127
0
      case NC_USHORT: index = NC_USHORTINDEX; break;
128
0
      case NC_UINT: index = NC_UINTINDEX; break;
129
0
      case NC_INT64: index = NC_LONGLONGINDEX; break;
130
0
      case NC_UINT64: index = NC_ULONGLONGINDEX; break;
131
0
      case NC_STRING: index = NC_PTRINDEX; break;
132
      /* Here class matters */
133
0
      case NC_VLEN: index = NC_NCVLENINDEX; break;
134
0
      case NC_OPAQUE: index = NC_UCHARINDEX; break;
135
0
      case NC_ENUM: /* fall thru */
136
0
      case NC_COMPOUND: /* fall thru */
137
0
      default:
138
0
  nclog(NCLOGERR,"nc_class_alignment: class code %d cannot be aligned",ncclass);
139
0
  goto done;
140
0
    }
141
0
    align = &vec[index];
142
0
    if(alignp) *alignp = align->alignment;
143
0
done:
144
0
    return stat;
145
0
}
146
147
void
148
NC_compute_alignments(void)
149
1
{
150
1
    if(NC_alignments_computed) return;
151
    /* Compute the alignments for all the common C data types*/
152
    /* First for the struct*/
153
    /* initialize*/
154
1
    memset((void*)&set,0,sizeof(set));
155
1
    memset((void*)vec,0,sizeof(vec));
156
157
1
    COMP_ALIGNMENT(set.charalign,char);
158
1
    COMP_ALIGNMENT(set.ucharalign,unsigned char);
159
1
    COMP_ALIGNMENT(set.shortalign,short);
160
1
    COMP_ALIGNMENT(set.ushortalign,unsigned short);
161
1
    COMP_ALIGNMENT(set.intalign,int);
162
1
    COMP_ALIGNMENT(set.uintalign,unsigned int);
163
1
    COMP_ALIGNMENT(set.longlongalign,long long);
164
1
    COMP_ALIGNMENT(set.ulonglongalign,unsigned long long);
165
1
    COMP_ALIGNMENT(set.floatalign,float);
166
1
    COMP_ALIGNMENT(set.doublealign,double);
167
1
    COMP_ALIGNMENT(set.ptralign,void*);
168
1
    COMP_ALIGNMENT(set.ncvlenalign,nc_vlen_t);
169
170
    /* Then the vector*/
171
1
    COMP_ALIGNMENT(vec[NC_CHARINDEX],char);
172
1
    COMP_ALIGNMENT(vec[NC_UCHARINDEX],unsigned char); 
173
1
    COMP_ALIGNMENT(vec[NC_SHORTINDEX],short);
174
1
    COMP_ALIGNMENT(vec[NC_USHORTINDEX],unsigned short);
175
1
    COMP_ALIGNMENT(vec[NC_INTINDEX],int);
176
1
    COMP_ALIGNMENT(vec[NC_UINTINDEX],unsigned int);
177
1
    COMP_ALIGNMENT(vec[NC_LONGLONGINDEX],long long);
178
1
    COMP_ALIGNMENT(vec[NC_ULONGLONGINDEX],unsigned long long);
179
1
    COMP_ALIGNMENT(vec[NC_FLOATINDEX],float);
180
1
    COMP_ALIGNMENT(vec[NC_DOUBLEINDEX],double);
181
1
    COMP_ALIGNMENT(vec[NC_PTRINDEX],void*);
182
1
    COMP_ALIGNMENT(vec[NC_NCVLENINDEX],nc_vlen_t);
183
1
    NC_alignments_computed = 1;
184
1
}
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*
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
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 *
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
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*/