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