-
Notifications
You must be signed in to change notification settings - Fork 1
/
read_geogrid.c
142 lines (119 loc) · 3.79 KB
/
read_geogrid.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
/* File: read_geogrid.c
Sample subroutine to read an array from the geogrid binary format.
Notes: Depending on the compiler and compiler flags, the name of
the read_geogrid() routine may need to be adjusted with respect
to the number of trailing underscores when calling from Fortran.
Michael G. Duda, NCAR/MMM
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#ifdef _UNDERSCORE
#define read_geogrid read_geogrid_
#endif
#ifdef _DOUBLEUNDERSCORE
#define read_geogrid read_geogrid__
#endif
#undef BIG_ENDIAN
#undef LITTLE_ENDIAN
#define BIG_ENDIAN 0
#define LITTLE_ENDIAN 1
int read_geogrid(
char * fname, /* The name of the file to read from */
int * len, /* The length of the filename */
float * rarray, /* The array to be filled */
int * nx, /* x-dimension of the array */
int * ny, /* y-dimension of the array */
int * nz, /* z-dimension of the array */
int * isigned, /* 0=unsigned data, 1=signed data */
int * endian, /* 0=big endian, 1=little endian */
float * scalefactor, /* value to multiply array elements by before truncation to integers */
int * wordsize, /* number of bytes to use for each array element */
int * status)
{
int i, ival, cnt, narray;
int A2, B2;
int A3, B3, C3;
int A4, B4, C4, D4;
unsigned char * c;
char local_fname[1024];
FILE * bfile;
*status = 0;
narray = (*nx) * (*ny) * (*nz);
/* Make a null-terminated local copy of the filename */
strncpy(local_fname,fname,*len);
local_fname[*len]='\0';
/* Attempt to open file for reading */
if (!(bfile = fopen(local_fname,"rb")))
{
*status = 1;
return 1;
}
/* Allocate memory to hold bytes from file and read data */
c = (unsigned char *)malloc(sizeof(unsigned char)*(*wordsize) * narray);
cnt = fread((void *)c, sizeof(unsigned char), narray*(*wordsize), bfile);
fclose(bfile);
if (cnt == 0)
{
*status = 1;
return 1;
}
/*
Set up byte offsets for each wordsize depending on byte order.
A, B, C, D give the offsets of the LSB through MSB (i.e., for
word ABCD, A=MSB, D=LSB) in the array from the beginning of a word
*/
if (*endian == BIG_ENDIAN) {
A2 = 0; B2 = 1;
A3 = 0; B3 = 1; C3 = 2;
A4 = 0; B4 = 1; C4 = 2; D4 = 3;
}
else {
B2 = 0; A2 = 1;
C3 = 0; B3 = 1; A3 = 2;
D4 = 0; C4 = 1; B4 = 2; A4 = 3;
}
/* Convert words from native byte order */
switch(*wordsize) {
case 1:
for(i=0; i<narray; i++)
{
ival = (int)(c[i]);
if ((*isigned) && (ival > (1 << 7))) ival -= (1 << 8);
rarray[i] = (float)ival;
}
break;
case 2:
for(i=0; i<narray; i++)
{
ival = (int)((c[2*i+A2]<<8) | (c[2*i+B2]));
if ((*isigned) && (ival > (1 << 15))) ival -= (1 << 16);
rarray[i] = (float)ival;
}
break;
case 3:
for(i=0; i<narray; i++)
{
ival = (int)((c[3*i+A3]<<16) | (c[3*i+B3]<<8) | c[3*i+C3]);
if ((*isigned) * (ival > (1 << 23))) ival -= (1 << 24);
rarray[i] = (float)ival;
}
break;
case 4:
for(i=0; i<narray; i++)
{
ival = (int)((c[4*i+A4]<<24) | (c[4*i+B4]<<16) | (c[4*i+C4]<<8) | c[4*i+D4]);
if ((*isigned) && (ival > (1 << 31))) ival -= (1 << 32);
rarray[i] = (float)ival;
}
break;
}
free(c);
/* Scale real-valued array by scalefactor */
if (*scalefactor != 1.0)
{
for (i=0; i<narray; i++)
rarray[i] = rarray[i] * (*scalefactor);
}
return 0;
}