NCEPLIBS-g2c  1.6.4
g2_getfld.c
Go to the documentation of this file.
1 
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include "grib2.h"
9 
10 g2int g2_unpack1(unsigned char *,g2int *,g2int **,g2int *);
11 g2int g2_unpack2(unsigned char *,g2int *,g2int *,unsigned char **);
12 g2int g2_unpack3(unsigned char *,g2int *,g2int **,g2int **,
13  g2int *,g2int **,g2int *);
14 g2int g2_unpack4(unsigned char *,g2int *,g2int *,g2int **,
15  g2int *,g2float **,g2int *);
16 g2int g2_unpack5(unsigned char *,g2int *,g2int *,g2int *, g2int **,g2int *);
17 g2int g2_unpack6(unsigned char *,g2int *,g2int ,g2int *, g2int **);
18 g2int g2_unpack7(unsigned char *,g2int *,g2int ,g2int *,
19  g2int ,g2int *,g2int ,g2float **);
20 
101 g2int
102 g2_getfld(unsigned char *cgrib, g2int ifldnum, g2int unpack, g2int expand,
103  gribfield **gfld)
104 {
105 
106  g2int have3 = 0, have4 = 0, have5 = 0, have6 = 0, have7 = 0, ierr = 0, jerr;
107  g2int numfld = 0, j, n, istart, iofst, ipos;
108  g2int disc, ver, lensec0, lengrib, lensec, isecnum;
109  g2int *igds;
110  g2int *bmpsave;
111  g2float *newfld;
112  gribfield *lgfld;
113 
114  lgfld = malloc(sizeof(gribfield));
115  *gfld = lgfld;
116 
117  lgfld->locallen = 0;
118  lgfld->idsect = 0;
119  lgfld->local = 0;
120  lgfld->list_opt = 0;
121  lgfld->igdtmpl = 0;
122  lgfld->ipdtmpl = 0;
123  lgfld->idrtmpl = 0;
124  lgfld->coord_list = 0;
125  lgfld->bmap = 0;
126  lgfld->fld = 0;
127 
128  /* Check for valid request number. */
129  if (ifldnum <= 0) {
130  printf("g2_getfld: Request for field number must be positive.\n");
131  ierr = 3;
132  return(ierr);
133  }
134 
135  /* Check for beginning of GRIB message in the first 100 bytes. */
136  istart = -1;
137  for (j = 0; j < 100; j++) {
138  if (cgrib[j] == 'G' && cgrib[j + 1] == 'R' &&cgrib[j + 2] == 'I' &&
139  cgrib[j + 3] == 'B') {
140  istart = j;
141  break;
142  }
143  }
144  if (istart == -1) {
145  printf("g2_getfld: Beginning characters GRIB not found.\n");
146  ierr = 1;
147  return(ierr);
148  }
149 
150  /* Unpack Section 0 - Indicator Section. */
151  iofst = 8 * (istart + 6);
152  gbit(cgrib, &disc, iofst, 8); /* Discipline */
153  iofst = iofst + 8;
154  gbit(cgrib, &ver, iofst, 8); /* GRIB edition number */
155  iofst = iofst + 8;
156  iofst = iofst + 32;
157  gbit(cgrib, &lengrib, iofst, 32); /* Length of GRIB message */
158  iofst = iofst + 32;
159  lensec0 = 16;
160  ipos = istart + lensec0;
161 
162  /* Currently handles only GRIB Edition 2. */
163  if (ver != 2) {
164  printf("g2_getfld: can only decode GRIB edition 2.\n");
165  ierr = 2;
166  return(ierr);
167  }
168 
169  /* Loop through the remaining sections keeping track of the
170  * length of each. Also keep the latest Grid Definition Section
171  * info. Unpack the requested field number. */
172  for (;;) {
173  /* Check to see if we are at end of GRIB message */
174  if (cgrib[ipos] == '7' && cgrib[ipos+1] == '7' && cgrib[ipos+2] == '7' &&
175  cgrib[ipos+3] == '7') {
176  ipos = ipos+4;
177  /* If end of GRIB message not where expected, issue error */
178  if (ipos != (istart+lengrib)) {
179  printf("g2_getfld: '7777' found, but not where expected.\n");
180  ierr = 4;
181  return(ierr);
182  }
183  break;
184  }
185  /* Get length of Section and Section number */
186  iofst = (ipos - 1) * 8;
187  iofst = ipos * 8;
188  gbit(cgrib, &lensec, iofst, 32); /* Get Length of Section */
189  iofst = iofst + 32;
190  gbit(cgrib, &isecnum, iofst, 8); /* Get Section number */
191  iofst = iofst + 8;
192  /*printf(" lensec= %ld secnum= %ld \n", lensec, isecnum); */
193 
194  /* Check to see if section number is valid. */
195  if (isecnum < 1 || isecnum > 7) {
196  printf("g2_getfld: Unrecognized Section Encountered=%ld\n", isecnum);
197  ierr = 8;
198  return(ierr);
199  }
200 
201  /* If found Section 1, decode elements in Identification Section. */
202  if (isecnum == 1) {
203  iofst = iofst - 40; /* reset offset to beginning of section */
204  jerr = g2_unpack1(cgrib, &iofst, &lgfld->idsect, &lgfld->idsectlen);
205  if (jerr !=0) {
206  ierr = 15;
207  return(ierr);
208  }
209  }
210 
211  /* If found Section 2, Grab local section. Save in case this
212  * is the latest one before the requested field. */
213  if (isecnum == 2) {
214  iofst = iofst - 40; /* reset offset to beginning of section */
215  if (lgfld->local != 0)
216  free(lgfld->local);
217  jerr = g2_unpack2(cgrib, &iofst, &lgfld->locallen, &lgfld->local);
218  if (jerr != 0) {
219  ierr = 16;
220  return(ierr);
221  }
222  }
223 
224  /* If found Section 3, unpack the GDS info using the
225  * appropriate template. Save in case this is the latest grid
226  * before the requested field. */
227  if (isecnum == 3) {
228  iofst = iofst - 40; /* reset offset to beginning of section */
229  if (lgfld->igdtmpl!=0) free(lgfld->igdtmpl);
230  if (lgfld->list_opt!=0) free(lgfld->list_opt);
231  jerr = g2_unpack3(cgrib, &iofst, &igds, &lgfld->igdtmpl,
232  &lgfld->igdtlen, &lgfld->list_opt, &lgfld->num_opt);
233  if (jerr == 0) {
234  have3 = 1;
235  lgfld->griddef = igds[0];
236  lgfld->ngrdpts = igds[1];
237  lgfld->numoct_opt = igds[2];
238  lgfld->interp_opt = igds[3];
239  lgfld->igdtnum = igds[4];
240  free(igds);
241  }
242  else {
243  ierr = 10;
244  return(ierr);
245  }
246  }
247 
248  /* If found Section 4, check to see if this field is the one
249  * requested. */
250  if (isecnum == 4) {
251  numfld = numfld + 1;
252  if (numfld == ifldnum) {
253  lgfld->discipline = disc;
254  lgfld->version = ver;
255  lgfld->ifldnum = ifldnum;
256  lgfld->unpacked = unpack;
257  lgfld->expanded = 0;
258  iofst = iofst - 40; /* reset offset to beginning of section */
259  jerr = g2_unpack4(cgrib, &iofst, &lgfld->ipdtnum,
260  &lgfld->ipdtmpl, &lgfld->ipdtlen, &lgfld->coord_list,
261  &lgfld->num_coord);
262  if (jerr == 0)
263  have4 = 1;
264  else {
265  ierr = 11;
266  return(ierr);
267  }
268  }
269  }
270 
271  /* If found Section 5, check to see if this field is the one
272  * requested. */
273  if (isecnum == 5 && numfld == ifldnum) {
274  iofst = iofst-40; /* reset offset to beginning of section */
275  jerr = g2_unpack5(cgrib, &iofst, &lgfld->ndpts, &lgfld->idrtnum,
276  &lgfld->idrtmpl, &lgfld->idrtlen);
277  if (jerr == 0)
278  have5 = 1;
279  else {
280  ierr = 12;
281  return(ierr);
282  }
283  }
284 
285  /* If found Section 6, Unpack bitmap. Save in case this is
286  * the latest bitmap before the requested field. */
287  if (isecnum == 6) {
288  if (unpack) { /* unpack bitmap */
289  iofst = iofst - 40; /* reset offset to beginning of section */
290  bmpsave = lgfld->bmap; /* save pointer to previous bitmap */
291  jerr = g2_unpack6(cgrib, &iofst, lgfld->ngrdpts, &lgfld->ibmap,
292  &lgfld->bmap);
293  if (jerr == 0) {
294  have6 = 1;
295  if (lgfld->ibmap == 254) /* use previously specified bitmap */
296  if (bmpsave != 0)
297  lgfld->bmap = bmpsave;
298  else {
299  printf("g2_getfld: Prev bit-map specified, but none exist.\n");
300  ierr = 17;
301  return(ierr);
302  }
303  else /* get rid of it */
304  if (bmpsave!=0)
305  free(bmpsave);
306  }
307  else {
308  ierr = 13;
309  return(ierr);
310  }
311  }
312  else { /* do not unpack bitmap */
313  gbit(cgrib, &lgfld->ibmap, iofst, 8); /* Get BitMap Indicator */
314  have6 = 1;
315  }
316  }
317 
318  /* If found Section 7, check to see if this field is the one
319  * requested. */
320  if (isecnum == 7 && numfld == ifldnum && unpack) {
321  iofst = iofst - 40; /* reset offset to beginning of section */
322  jerr = g2_unpack7(cgrib, &iofst, lgfld->igdtnum, lgfld->igdtmpl,
323  lgfld->idrtnum, lgfld->idrtmpl, lgfld->ndpts,
324  &lgfld->fld);
325  if (jerr == 0) {
326  have7 = 1;
327  /* If bitmap is used with this field, expand data field */
328  /* to grid, if possible. */
329  if (lgfld->ibmap != 255 && lgfld->bmap != 0) {
330  if (expand == 1) {
331  n = 0;
332  newfld = calloc(lgfld->ngrdpts, sizeof(g2float));
333  for (j = 0;j<lgfld->ngrdpts;j++) {
334  if (lgfld->bmap[j] == 1)
335  newfld[j] = lgfld->fld[n++];
336  }
337  free(lgfld->fld);
338  lgfld->fld = newfld;
339  lgfld->expanded = 1;
340  }
341  else {
342  lgfld->expanded = 0;
343  }
344  }
345  else {
346  lgfld->expanded = 1;
347  }
348  }
349  else {
350  printf("g2_getfld: return from g2_unpack7 = %d \n", (int)jerr);
351  ierr = 14;
352  return(ierr);
353  }
354  }
355 
356  /* Check to see if we read pass the end of the GRIB message
357  * and missed the terminator string '7777'. */
358  ipos = ipos + lensec; /* Update beginning of section pointer */
359  if (ipos > (istart + lengrib)) {
360  printf("g2_getfld: '7777' not found at end of GRIB message.\n");
361  ierr = 7;
362  return(ierr);
363  }
364 
365  /* If unpacking requested, return when all sections have been
366  * processed. */
367  if (unpack && have3 && have4 && have5 && have6 && have7)
368  return(ierr);
369 
370  /* If unpacking is not requested, return when sections 3
371  * through 6 have been processed. */
372  if ((!unpack) && have3 && have4 && have5 && have6)
373  return(ierr);
374 
375  }
376 
377  /* If exited from above loop, the end of the GRIB message was
378  * reached before the requested field was found. */
379  printf("g2_getfld: GRIB message contained %ld different fields.\n", numfld);
380  printf("g2_getfld: The request was for field %ld.\n", ifldnum);
381  ierr = 6;
382 
383  return(ierr);
384 
385 }
g2int g2_unpack7(unsigned char *, g2int *, g2int, g2int *, g2int, g2int *, g2int, g2float **)
This subroutine unpacks Section 7 (Data Section) as defined in GRIB Edition 2.
Definition: g2_unpack7.c:65
g2int g2_unpack6(unsigned char *, g2int *, g2int, g2int *, g2int **)
This subroutine unpacks Section 6 (Bit-Map Section) as defined in GRIB Edition 2.
Definition: g2_unpack6.c:33
g2int g2_unpack1(unsigned char *, g2int *, g2int **, g2int *)
This subroutine unpacks Section 1 - Identification Section as defined in GRIB Edition 2.
Definition: g2_unpack1.c:55
g2int g2_unpack5(unsigned char *, g2int *, g2int *, g2int *, g2int **, g2int *)
This subroutine unpacks Section 5 (Data Representation Section) as defined in GRIB Edition 2.
Definition: g2_unpack5.c:42
g2int g2_unpack2(unsigned char *, g2int *, g2int *, unsigned char **)
This subroutine unpacks Section 2 (Local Use Section) as defined in GRIB Edition 2.
Definition: g2_unpack2.c:37
g2int g2_unpack3(unsigned char *, g2int *, g2int **, g2int **, g2int *, g2int **, g2int *)
This routine unpacks Section 3 (Grid Definition Section) as defined in GRIB Edition 2.
Definition: g2_unpack3.c:57
g2int g2_unpack4(unsigned char *, g2int *, g2int *, g2int **, g2int *, g2float **, g2int *)
This subroutine unpacks Section 4 (Product Definition Section) as defined in GRIB Edition 2.
Definition: g2_unpack4.c:45
g2int g2_getfld(unsigned char *cgrib, g2int ifldnum, g2int unpack, g2int expand, gribfield **gfld)
This subroutine returns all the metadata, template values, bit-map (if applicable),...
Definition: g2_getfld.c:102
void gbit(unsigned char *in, g2int *iout, g2int iskip, g2int nbyte)
Get bits - unpack bits: Extract arbitrary size values from a packed bit string, right justifying each...
Definition: gbits.c:20
Header file for NCEPLIBS-g2c library.
g2int igdtnum
Grid Definition Template Number (See Table 3.1).
Definition: grib2.h:163
g2int locallen
Length of array local.
Definition: grib2.h:125
g2int ibmap
Bitmap indicator (see Table 6.0).
Definition: grib2.h:226
g2int interp_opt
Interpretation of list for optional points definition.
Definition: grib2.h:148
g2int ngrdpts
Number of grid points in the defined grid.
Definition: grib2.h:138
g2int ifldnum
Field number within GRIB message.
Definition: grib2.h:128
g2float * coord_list
Array containing floating point values intended to document the vertical discretisation associated to...
Definition: grib2.h:191
float g2float
Float type.
Definition: grib2.h:22
g2int griddef
Source of grid definition (see Table 3.0).
Definition: grib2.h:135
g2int ipdtnum
Product Definition Template Number (see Table 4.0).
Definition: grib2.h:175
g2int * ipdtmpl
Contains the data values for the Product Definition Template specified by ipdtnum.
Definition: grib2.h:183
g2int discipline
Message Discipline (see Table 0.0).
Definition: grib2.h:67
g2int numoct_opt
Number of octets needed for each additional grid points definition.
Definition: grib2.h:143
g2int idrtlen
Number of elements in idrtmpl.
Definition: grib2.h:201
g2int unpacked
Logical value indicating whether the bitmap and data values were unpacked.
Definition: grib2.h:209
g2int idsectlen
Number of elements in idsect.
Definition: grib2.h:118
g2int ipdtlen
Number of elements in ipdtmpl - i.e.
Definition: grib2.h:179
g2int * igdtmpl
Contains the data values for the Grid Definition Template specified by igdtnum.
Definition: grib2.h:171
g2int idrtnum
Data Representation Template Number (see Table 5.0).
Definition: grib2.h:198
g2int ndpts
Number of data points unpacked and returned.
Definition: grib2.h:194
g2int * idrtmpl
Contains the data values for the Data Representation Template specified by idrtnum.
Definition: grib2.h:205
g2int * list_opt
(Used if numoct_opt .ne.
Definition: grib2.h:159
g2int version
GRIB edition number (2).
Definition: grib2.h:63
g2int * idsect
Contains the entries in the Identification Section (Section 1).
Definition: grib2.h:115
g2float * fld
Array of ndpts unpacked data points.
Definition: grib2.h:233
g2int num_coord
Number of values in array coord_list.
Definition: grib2.h:186
unsigned char * local
Pointer to character array containing contents of Local Section 2, if included.
Definition: grib2.h:122
g2int expanded
Logical value indicating whether the data field was expanded to the grid in the case where a bit-map ...
Definition: grib2.h:218
g2int num_opt
(Used if numoct_opt .ne.
Definition: grib2.h:154
g2int igdtlen
Number of elements in igdtmpl - i.e.
Definition: grib2.h:167
g2int * bmap
Integer array containing decoded bitmap, if ibmap=0 or ibap=254.
Definition: grib2.h:230
int64_t g2int
Long integer type.
Definition: grib2.h:20
Struct for GRIB field.
Definition: grib2.h:61