/src/netcdf-c/libdispatch/doffsets.c
| Line | Count | Source | 
| 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*/ |