[409] | 1 | /********************************************************************* |
---|
| 2 | * Copyright 1993, UCAR/Unidata |
---|
| 3 | * See netcdf/COPYRIGHT file for copying and redistribution conditions. |
---|
| 4 | * $Header: /upc/share/CVS/netcdf-3/libncdap3/dapalign.c,v 1.5 2009/09/23 22:26:00 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 | #include "config.h" |
---|
| 27 | #ifndef OFFSETTEST |
---|
| 28 | #include "ncdap3.h" |
---|
| 29 | #else |
---|
| 30 | #include <stdlib.h> |
---|
| 31 | #include <string.h> |
---|
| 32 | #include <assert.h> |
---|
| 33 | #endif |
---|
| 34 | |
---|
| 35 | #include "dapnc.h" |
---|
| 36 | #include "dapdebug.h" |
---|
| 37 | #include "dapalign.h" |
---|
| 38 | |
---|
| 39 | typedef struct nccalignvlen_t { |
---|
| 40 | size_t len; |
---|
| 41 | void* p; |
---|
| 42 | } nccalignvlen_t; |
---|
| 43 | |
---|
| 44 | #ifdef OFFSETTEST |
---|
| 45 | typedef int nc_type; |
---|
| 46 | #define NC_NAT 0 /* NAT = 'Not A Type' (c.f. NaN) */ |
---|
| 47 | #define NC_BYTE 1 /* signed 1 byte integer */ |
---|
| 48 | #define NC_CHAR 2 /* ISO/ASCII character */ |
---|
| 49 | #define NC_SHORT 3 /* signed 2 byte integer */ |
---|
| 50 | #define NC_INT 4 /* signed 4 byte integer */ |
---|
| 51 | #define NC_FLOAT 5 /* single precision floating point number */ |
---|
| 52 | #define NC_DOUBLE 6 /* double precision floating point number */ |
---|
| 53 | #define NC_UBYTE 7 /* unsigned 1 byte int */ |
---|
| 54 | #define NC_USHORT 8 /* unsigned 2-byte int */ |
---|
| 55 | #define NC_UINT 9 /* unsigned 4-byte int */ |
---|
| 56 | #define NC_INT64 10 /* signed 8-byte int */ |
---|
| 57 | #define NC_UINT64 11 /* unsigned 8-byte int */ |
---|
| 58 | #define NC_STRING 12 /* string */ |
---|
| 59 | #define NC_VLEN 13 |
---|
| 60 | #define NC_OPAQUE 14 |
---|
| 61 | #endif |
---|
| 62 | |
---|
| 63 | /* |
---|
| 64 | The heart of this is the following macro, |
---|
| 65 | which computes the offset of a field x |
---|
| 66 | when preceded by a char field. |
---|
| 67 | The assumptions appear to be as follows: |
---|
| 68 | 1. the offset produced in this situation indicates |
---|
| 69 | the alignment for x relative in such a way that it |
---|
| 70 | depends only on the types that precede it in the struct. |
---|
| 71 | 2. the compiler does not reorder fields. |
---|
| 72 | 3. arrays are tightly packed. |
---|
| 73 | 4. nested structs are alignd according to their first member |
---|
| 74 | (this actually follows from C language requirement that |
---|
| 75 | a struct can legally be cast to an instance of its first member). |
---|
| 76 | Given the alignments for the various common primitive types, |
---|
| 77 | it is assumed that one can use them anywhere to construct |
---|
| 78 | the layout of a struct of such types. |
---|
| 79 | It seems to work for HDF5 for a wide variety of machines. |
---|
| 80 | */ |
---|
| 81 | |
---|
| 82 | #define COMP_ALIGNMENT(DST,TYPE) {\ |
---|
| 83 | struct {char f1; TYPE x;} tmp; \ |
---|
| 84 | DST.typename = #TYPE ; \ |
---|
| 85 | DST.alignment = (size_t)((char*)(&(tmp.x)) - (char*)(&tmp));} |
---|
| 86 | |
---|
| 87 | |
---|
| 88 | #define NCCTYPECOUNT (NCCTYPENCVLEN+1) |
---|
| 89 | |
---|
| 90 | static NCtypealignvec vec[NCCTYPECOUNT]; |
---|
| 91 | static NCtypealignset set; |
---|
| 92 | static int dapaligninit = 0; |
---|
| 93 | |
---|
| 94 | unsigned int |
---|
| 95 | ncctypealignment(int nctype) |
---|
| 96 | { |
---|
| 97 | NCtypealignment* align = NULL; |
---|
| 98 | int index = 0; |
---|
| 99 | if(!dapaligninit) compute_nccalignments(); |
---|
| 100 | switch (nctype) { |
---|
| 101 | case NC_BYTE: index = NCCTYPEUCHAR; break; |
---|
| 102 | case NC_CHAR: index = NCCTYPECHAR; break; |
---|
| 103 | case NC_SHORT: index = NCCTYPESHORT; break; |
---|
| 104 | case NC_INT: index = NCCTYPEINT; break; |
---|
| 105 | case NC_FLOAT: index = NCCTYPEFLOAT; break; |
---|
| 106 | case NC_DOUBLE: index = NCCTYPEDOUBLE; break; |
---|
| 107 | case NC_UBYTE: index = NCCTYPEUCHAR; break; |
---|
| 108 | case NC_USHORT: index = NCCTYPEUSHORT; break; |
---|
| 109 | case NC_UINT: index = NCCTYPEUINT; break; |
---|
| 110 | case NC_INT64: index = NCCTYPELONGLONG; break; |
---|
| 111 | case NC_UINT64: index = NCCTYPEULONGLONG; break; |
---|
| 112 | case NC_STRING: index = NCCTYPEPTR; break; |
---|
| 113 | case NC_VLEN: index = NCCTYPENCVLEN; break; |
---|
| 114 | case NC_OPAQUE: index = NCCTYPEUCHAR; break; |
---|
| 115 | default: |
---|
| 116 | #ifndef OFFSETTEST |
---|
| 117 | PANIC1("nctypealignment: bad type code: %d",nctype); |
---|
| 118 | #else |
---|
| 119 | return 0; |
---|
| 120 | #endif |
---|
| 121 | } |
---|
| 122 | align = &vec[index]; |
---|
| 123 | return align->alignment; |
---|
| 124 | } |
---|
| 125 | |
---|
| 126 | |
---|
| 127 | void |
---|
| 128 | compute_nccalignments(void) |
---|
| 129 | { |
---|
| 130 | /* Compute the alignments for all the common C data types*/ |
---|
| 131 | /* First for the struct*/ |
---|
| 132 | /* initialize*/ |
---|
| 133 | memset((void*)&set,0,sizeof(set)); |
---|
| 134 | memset((void*)vec,0,sizeof(vec)); |
---|
| 135 | |
---|
| 136 | COMP_ALIGNMENT(set.charalign,char); |
---|
| 137 | COMP_ALIGNMENT(set.ucharalign,unsigned char); |
---|
| 138 | COMP_ALIGNMENT(set.shortalign,short); |
---|
| 139 | COMP_ALIGNMENT(set.ushortalign,unsigned short); |
---|
| 140 | COMP_ALIGNMENT(set.intalign,int); |
---|
| 141 | COMP_ALIGNMENT(set.uintalign,unsigned int); |
---|
| 142 | COMP_ALIGNMENT(set.longalign,long); |
---|
| 143 | COMP_ALIGNMENT(set.ulongalign,unsigned long); |
---|
| 144 | COMP_ALIGNMENT(set.longlongalign,long long); |
---|
| 145 | COMP_ALIGNMENT(set.ulonglongalign,unsigned long long); |
---|
| 146 | COMP_ALIGNMENT(set.floatalign,float); |
---|
| 147 | COMP_ALIGNMENT(set.doublealign,double); |
---|
| 148 | COMP_ALIGNMENT(set.ptralign,void*); |
---|
| 149 | COMP_ALIGNMENT(set.ncvlenalign,nccalignvlen_t); |
---|
| 150 | |
---|
| 151 | /* Then the vector*/ |
---|
| 152 | COMP_ALIGNMENT(vec[NCCTYPECHAR],char); |
---|
| 153 | COMP_ALIGNMENT(vec[NCCTYPEUCHAR],unsigned char); |
---|
| 154 | COMP_ALIGNMENT(vec[NCCTYPESHORT],short); |
---|
| 155 | COMP_ALIGNMENT(vec[NCCTYPEUSHORT],unsigned short); |
---|
| 156 | COMP_ALIGNMENT(vec[NCCTYPEINT],int); |
---|
| 157 | COMP_ALIGNMENT(vec[NCCTYPEUINT],unsigned int); |
---|
| 158 | COMP_ALIGNMENT(vec[NCCTYPELONG],long); |
---|
| 159 | COMP_ALIGNMENT(vec[NCCTYPEULONG],unsigned long); |
---|
| 160 | COMP_ALIGNMENT(vec[NCCTYPELONGLONG],long long); |
---|
| 161 | COMP_ALIGNMENT(vec[NCCTYPEULONGLONG],unsigned long long); |
---|
| 162 | COMP_ALIGNMENT(vec[NCCTYPEFLOAT],float); |
---|
| 163 | COMP_ALIGNMENT(vec[NCCTYPEDOUBLE],double); |
---|
| 164 | COMP_ALIGNMENT(vec[NCCTYPEPTR],void*); |
---|
| 165 | COMP_ALIGNMENT(vec[NCCTYPENCVLEN],nccalignvlen_t); |
---|
| 166 | |
---|
| 167 | dapaligninit = 1; |
---|
| 168 | } |
---|
| 169 | |
---|
| 170 | /* Compute padding */ |
---|
| 171 | int |
---|
| 172 | nccpadding(unsigned long offset, int alignment) |
---|
| 173 | { |
---|
| 174 | int pad,rem; |
---|
| 175 | rem = (alignment==0?0:(offset % alignment)); |
---|
| 176 | pad = (rem==0?0:(alignment - rem)); |
---|
| 177 | return pad; |
---|
| 178 | } |
---|
| 179 | |
---|
| 180 | #ifdef OFFSETTEST |
---|
| 181 | |
---|
| 182 | #define COMP_ALIGNMENT1(DST,TYPE1,TYPE) {\ |
---|
| 183 | struct {TYPE1 f1; TYPE x;} tmp; \ |
---|
| 184 | DST.typename = #TYPE ; \ |
---|
| 185 | DST.alignment = (size_t)((char*)(&(tmp.x)) - (char*)(&tmp));} |
---|
| 186 | |
---|
| 187 | #define COMP_ALIGNMENT2(DST,TYPE1,TYPE2,TYPE) {\ |
---|
| 188 | struct {TYPE1 f1, TYPE2 f2; TYPE x;} tmp; \ |
---|
| 189 | DST.typename = #TYPE ; \ |
---|
| 190 | DST.alignment = (size_t)((char*)(&(tmp.x)) - (char*)(&tmp));} |
---|
| 191 | |
---|
| 192 | #define COMP_SIZE0(DST,TYPE1,TYPE2) {\ |
---|
| 193 | struct {TYPE1 c; TYPE2 x;} tmp; \ |
---|
| 194 | DST = sizeof(tmp); } |
---|
| 195 | |
---|
| 196 | static char* |
---|
| 197 | padname(char* name) |
---|
| 198 | { |
---|
| 199 | #define MAX 20 |
---|
| 200 | if(name == NULL) name = "null"; |
---|
| 201 | int len = strlen(name); |
---|
| 202 | if(len > MAX) len = MAX; |
---|
| 203 | char* s = (char*)malloc(MAX+1); |
---|
| 204 | memset(s,' ',MAX); |
---|
| 205 | s[MAX+1] = '\0'; |
---|
| 206 | strncpy(s,name,len); |
---|
| 207 | return s; |
---|
| 208 | } |
---|
| 209 | |
---|
| 210 | static void |
---|
| 211 | verify(NCtypealignvec* vec) |
---|
| 212 | { |
---|
| 213 | int i,j; |
---|
| 214 | NCtypealignvec* vec16; |
---|
| 215 | NCtypealignvec* vec32; |
---|
| 216 | int* sizes8; |
---|
| 217 | int* sizes16; |
---|
| 218 | int* sizes32; |
---|
| 219 | |
---|
| 220 | vec16 = (NCtypealignvec*)malloc(sizeof(NCtypealignvec)*NCCTYPECOUNT); |
---|
| 221 | vec32 = (NCtypealignvec*)malloc(sizeof(NCtypealignvec)*NCCTYPECOUNT); |
---|
| 222 | sizes8 = (int*)malloc(sizeof(int)*NCCTYPECOUNT); |
---|
| 223 | sizes16 = (int*)malloc(sizeof(int)*NCCTYPECOUNT); |
---|
| 224 | sizes32 = (int*)malloc(sizeof(int)*NCCTYPECOUNT); |
---|
| 225 | |
---|
| 226 | COMP_SIZE0(sizes8[1],char,char); |
---|
| 227 | COMP_SIZE0(sizes8[2],unsigned char,char); |
---|
| 228 | COMP_SIZE0(sizes8[3],short,char); |
---|
| 229 | COMP_SIZE0(sizes8[4],unsigned short,char); |
---|
| 230 | COMP_SIZE0(sizes8[5],int,char); |
---|
| 231 | COMP_SIZE0(sizes8[6],unsigned int,char); |
---|
| 232 | COMP_SIZE0(sizes8[7],long,char); |
---|
| 233 | COMP_SIZE0(sizes8[8],unsigned long,char); |
---|
| 234 | COMP_SIZE0(sizes8[9],long long,char); |
---|
| 235 | COMP_SIZE0(sizes8[10],unsigned long long,char); |
---|
| 236 | COMP_SIZE0(sizes8[11],float,char); |
---|
| 237 | COMP_SIZE0(sizes8[12],double,char) ; |
---|
| 238 | COMP_SIZE0(sizes8[13],void*,char); |
---|
| 239 | COMP_SIZE0(sizes8[14],alignvlen_t,char); |
---|
| 240 | |
---|
| 241 | COMP_SIZE0(sizes16[1],char,short); |
---|
| 242 | COMP_SIZE0(sizes16[2],unsigned char,short); |
---|
| 243 | COMP_SIZE0(sizes16[3],short,short); |
---|
| 244 | COMP_SIZE0(sizes16[4],unsigned short,short); |
---|
| 245 | COMP_SIZE0(sizes16[5],int,short); |
---|
| 246 | COMP_SIZE0(sizes16[6],unsigned int,short); |
---|
| 247 | COMP_SIZE0(sizes16[7],long,short); |
---|
| 248 | COMP_SIZE0(sizes16[8],unsigned long,short); |
---|
| 249 | COMP_SIZE0(sizes16[9],long long,short); |
---|
| 250 | COMP_SIZE0(sizes16[10],unsigned long long,short); |
---|
| 251 | COMP_SIZE0(sizes16[11],float,short); |
---|
| 252 | COMP_SIZE0(sizes16[12],double,short) ; |
---|
| 253 | COMP_SIZE0(sizes16[13],void*,short); |
---|
| 254 | COMP_SIZE0(sizes16[14],alignvlen_t*,short); |
---|
| 255 | |
---|
| 256 | COMP_SIZE0(sizes32[1],char,int); |
---|
| 257 | COMP_SIZE0(sizes32[2],unsigned char,int); |
---|
| 258 | COMP_SIZE0(sizes32[3],short,int); |
---|
| 259 | COMP_SIZE0(sizes32[4],unsigned short,int); |
---|
| 260 | COMP_SIZE0(sizes32[5],int,int); |
---|
| 261 | COMP_SIZE0(sizes32[6],unsigned int,int); |
---|
| 262 | COMP_SIZE0(sizes32[7],long,int); |
---|
| 263 | COMP_SIZE0(sizes32[8],unsigned long,int); |
---|
| 264 | COMP_SIZE0(sizes32[9],long long,int); |
---|
| 265 | COMP_SIZE0(sizes32[10],unsigned long long,int); |
---|
| 266 | COMP_SIZE0(sizes32[11],float,int); |
---|
| 267 | COMP_SIZE0(sizes32[12],double,int) ; |
---|
| 268 | COMP_SIZE0(sizes32[13],void*,int); |
---|
| 269 | COMP_SIZE0(sizes32[14],alignvlen_t*,int); |
---|
| 270 | |
---|
| 271 | COMP_ALIGNMENT1(vec16[1],char,short); |
---|
| 272 | COMP_ALIGNMENT1(vec16[2],unsigned char,short); |
---|
| 273 | COMP_ALIGNMENT1(vec16[3],short,short); |
---|
| 274 | COMP_ALIGNMENT1(vec16[4],unsigned short,short); |
---|
| 275 | COMP_ALIGNMENT1(vec16[5],int,short); |
---|
| 276 | COMP_ALIGNMENT1(vec16[6],unsigned int,short); |
---|
| 277 | COMP_ALIGNMENT1(vec32[7],long,short); |
---|
| 278 | COMP_ALIGNMENT1(vec32[8],unsigned long,short); |
---|
| 279 | COMP_ALIGNMENT1(vec32[9],long long,short); |
---|
| 280 | COMP_ALIGNMENT1(vec32[10],unsigned long long,short); |
---|
| 281 | COMP_ALIGNMENT1(vec16[11],float,short); |
---|
| 282 | COMP_ALIGNMENT1(vec16[12],double,short); |
---|
| 283 | COMP_ALIGNMENT1(vec16[13],void*,short); |
---|
| 284 | COMP_ALIGNMENT1(vec16[14],alignvlen_t*,short); |
---|
| 285 | |
---|
| 286 | COMP_ALIGNMENT1(vec32[1],char,short); |
---|
| 287 | COMP_ALIGNMENT1(vec32[2],unsigned char,short); |
---|
| 288 | COMP_ALIGNMENT1(vec32[3],char,short); |
---|
| 289 | COMP_ALIGNMENT1(vec32[4],unsigned short,short); |
---|
| 290 | COMP_ALIGNMENT1(vec32[5],int,int); |
---|
| 291 | COMP_ALIGNMENT1(vec32[6],unsigned int,int); |
---|
| 292 | COMP_ALIGNMENT1(vec32[7],long,int); |
---|
| 293 | COMP_ALIGNMENT1(vec32[8],unsigned long,int); |
---|
| 294 | COMP_ALIGNMENT1(vec32[9],long long,int); |
---|
| 295 | COMP_ALIGNMENT1(vec32[10],unsigned long long,int); |
---|
| 296 | COMP_ALIGNMENT1(vec32[11],float,int); |
---|
| 297 | COMP_ALIGNMENT1(vec32[12],double,int); |
---|
| 298 | COMP_ALIGNMENT1(vec32[13],void*,int); |
---|
| 299 | COMP_ALIGNMENT1(vec32[14],alignvlen_t*,int); |
---|
| 300 | |
---|
| 301 | for(i=0;i<NCCTYPECOUNT;i++) { |
---|
| 302 | printf("%s: size=%2d alignment=%2d\n", |
---|
| 303 | padname(vec[i].typename),sizes8[i],vec[i].alignment); |
---|
| 304 | } |
---|
| 305 | for(i=0;i<NCCTYPECOUNT;i++) { |
---|
| 306 | printf("short vs %s: size=%2d alignment=%2d\n", |
---|
| 307 | padname(vec[i].typename),sizes16[i],vec16[i].alignment); |
---|
| 308 | } |
---|
| 309 | for(i=0;i<NCCTYPECOUNT;i++) { |
---|
| 310 | printf("int vs %s: size=%2d alignment=%2d\n", |
---|
| 311 | padname(vec[i].typename),sizes32[i],vec32[i].alignment); |
---|
| 312 | } |
---|
| 313 | |
---|
| 314 | } |
---|
| 315 | |
---|
| 316 | int |
---|
| 317 | main(int argc, char** argv) |
---|
| 318 | { |
---|
| 319 | int i; |
---|
| 320 | |
---|
| 321 | compute_nccalignments(); |
---|
| 322 | |
---|
| 323 | verify(vec); |
---|
| 324 | |
---|
| 325 | /* |
---|
| 326 | for(i=0;i<NCCTYPECOUNT;i++) { |
---|
| 327 | printf("%s:\talignment=%d\n",vec[i].typename,vec[i].alignment); |
---|
| 328 | } |
---|
| 329 | */ |
---|
| 330 | exit(0); |
---|
| 331 | } |
---|
| 332 | #endif /*OFFSETTEST*/ |
---|