NCEPLIBS-g2c  1.8.0
g2cfile.c
Go to the documentation of this file.
1 
7 #include "grib2_int.h"
8 
11 
14 
16 #define MIN(a,b) ((a) < (b) ? (a) : (b))
17 
19 #define READ_BUF_SIZE 4092
20 
22 #define BYTES_TO_DISCIPLINE 6
23 
25 MUTEX(m);
26 
27 #define G2C_SEEKMSG_BUFSIZE 4092
31 
55 int
56 g2c_seekmsg(int g2cid, size_t skip, size_t *offset, size_t *msglen)
57 {
58  size_t k4;
59  int k, lim;
60  int end;
61  unsigned char *cbuf;
62  size_t bytes_read = G2C_SEEKMSG_BUFSIZE;
63  size_t my_msglen = 0, my_offset = 0, ipos;
64 
65  /* Find the open file struct. */
66  if (g2c_file[g2cid].g2cid != g2cid)
67  return G2C_EBADID;
68 
69  LOG((3, "g2c_seekgb skip %ld", skip));
70 
71  /* Get memory to read in some of the file. */
72  if (!(cbuf = malloc(G2C_SEEKMSG_BUFSIZE)))
73  return G2C_ENOMEM;
74 
75  ipos = skip;
76 
77  /* Loop until grib message is found. */
78  while (my_msglen == 0 && bytes_read == G2C_SEEKMSG_BUFSIZE)
79  {
80  /* Read partial section. */
81  if (fseek(g2c_file[g2cid].f, ipos, SEEK_SET))
82  {
83  free(cbuf);
84  return G2C_EFILE;
85  }
86  bytes_read = fread(cbuf, sizeof(unsigned char), G2C_SEEKMSG_BUFSIZE, g2c_file[g2cid].f);
87  lim = bytes_read - 8;
88 
89  /* Look for 'GRIB...2' in partial section. */
90  for (k = 0; k < lim; k++)
91  {
92  if (!strncmp((char *)&cbuf[k], G2C_MAGIC_HEADER, strlen(G2C_MAGIC_HEADER)) && cbuf[k + 7] == 2)
93  {
94  /* Find the length of the message. This is stored as
95  * an 8-byte big-endian integer starting at positon
96  * 8 in cbuf. */
97  my_msglen = hton64(*(size_t *)&cbuf[k + 8]);
98 
99  LOG((4, "my_msglen %ld", my_msglen));
100 
101  /* Read the last 4 bytes of the message. */
102  if (fseek(g2c_file[g2cid].f, ipos + k + my_msglen - 4, SEEK_SET))
103  {
104  free(cbuf);
105  return G2C_EFILE;
106  }
107 
108  if ((k4 = fread(&end, 4, 1, g2c_file[g2cid].f)) != 1)
109  {
110  free(cbuf);
111  return G2C_EFILE;
112  }
113 
114  /* Look for '7777' at end of grib message. */
115  if (k4 == 1 && end == 926365495)
116  {
117  /* GRIB message found. */
118  my_offset = ipos + k;
119  LOG((4, "found end of message my_offset %ld", my_offset));
120  break;
121  }
122  }
123  }
124  ipos = ipos + lim;
125  }
126 
127  /* Free resources. */
128  free(cbuf);
129 
130  /* Return information to the caller. */
131  if (offset)
132  *offset = my_offset;
133  if (msglen)
134  *msglen = my_msglen;
135 
136  return G2C_NOERROR;
137 }
138 
163 int
164 g2c_find_msg2(int g2cid, size_t skip_bytes, size_t max_bytes, size_t *bytes_to_msg,
165  size_t *bytes_in_msg)
166 {
167  size_t bytes_to_read = MIN(READ_BUF_SIZE, max_bytes);
168  size_t bytes_read;
169  unsigned char *buf;
170  int grib_version;
171  int eof = 0;
172  int msg_found = 0;
173  size_t num_blocks;
174  size_t ftell_pos;
175  int i;
176  int done = 0;
177  int ret = G2C_NOERROR;
178 
179  /* Check inputs. */
180  if (!bytes_to_msg || !bytes_in_msg)
181  return G2C_EINVAL;
182 
183  /* Find the open file struct. */
184  if (g2c_file[g2cid].g2cid != g2cid)
185  return G2C_EBADID;
186 
187  /* Skip some bytes if desired. */
188  if (fseek(g2c_file[g2cid].f, (off_t)skip_bytes, SEEK_SET))
189  return G2C_ERROR;
190 
191  /* Allocate storage to read into. */
192  if (!(buf = calloc(bytes_to_read, sizeof(char))))
193  return G2C_ENOMEM;
194 
195  for (num_blocks = 0; !eof && !done; num_blocks++)
196  {
197  /* Read some bytes. If we don't get the number expected, either a
198  * read error occured, or we reached the end of file. */
199  if ((ftell_pos = ftell(g2c_file[g2cid].f)) == -1)
200  return G2C_EFILE;
201  LOG((4, "before read ftell() is %ld (0x%x) reading %ld bytes", ftell_pos,
202  ftell_pos, bytes_to_read));
203  if ((bytes_read = fread(buf, 1, bytes_to_read, g2c_file[g2cid].f)) != bytes_to_read)
204  {
205  if (ferror(g2c_file[g2cid].f))
206  ret = G2C_EFILE;
207  eof++;
208  }
209 
210  /* Scan for 'GRIB2' in the bytes we have read. */
211  if (!ret)
212  {
213  for (i = 0; i < bytes_read; i++)
214  {
215 #ifdef LOGGING
216  /* if (i < 10) LOG((3, "buf[%ld] = %2.2x", i, buf[i])); */
217 #endif
218  /* Find the beginning of a GRIB message. */
219  if (buf[i] == 'G' && i < bytes_read - G2C_MAGIC_HEADER_LEN
220  && buf[i + 1] == 'R' && buf[i + 2] == 'I' && buf[i + 3] == 'B')
221  {
222  msg_found++;
223  *bytes_to_msg = ftell_pos + i;
224  grib_version = buf[i + 7];
225  LOG((3, "bytes_to_msg %ld grib_version %d", *bytes_to_msg, grib_version));
226  if (grib_version != 1 && grib_version != 2)
227  {
228  ret = G2C_EMSG;
229  done++;
230  break;
231  }
232  }
233 
234  /* Find the end of a GRIB message. And then we're done. */
235  if (msg_found && buf[i] == '7' && i < bytes_read - G2C_MAGIC_HEADER_LEN
236  && buf[i + 1] == '7' && buf[i + 2] == '7' && buf[i + 3] == '7')
237  {
238  msg_found--;
239  *bytes_in_msg = ftell_pos + i - *bytes_to_msg + 4;
240  LOG((3, "bytes_in_msg %ld", *bytes_in_msg));
241  ret = G2C_NOERROR;
242  done++;
243  break;
244  }
245  }
246  }
247 
248  /* Back up 8 bytes in case the "GRIB" magic header occurred
249  * within the last 8 bytes of the previous read. */
250  if (!done)
251  if (fseek(g2c_file[g2cid].f, (off_t)(ftell(g2c_file[g2cid].f) - G2C_MAGIC_HEADER_LEN),
252  SEEK_SET))
253  return G2C_ERROR;
254  }
255 
256  /* Free storage. */
257  free(buf);
258 
259  return ret;
260 }
261 
292 int
293 g2c_get_msg(int g2cid, size_t skip_bytes, size_t max_bytes, size_t *bytes_to_msg,
294  size_t *bytes_in_msg, unsigned char **cbuf)
295 {
296  size_t bytes_read;
297  int ret = G2C_NOERROR;
298 
299  /* Check inputs. */
300  if (!bytes_to_msg || !bytes_in_msg || !cbuf || max_bytes < G2C_MIN_MAX_BYTES)
301  return G2C_EINVAL;
302 
303  LOG((2, "g2c_get_msg g2cid %d skip_bytes %ld max_bytes %ld", g2cid, skip_bytes,
304  max_bytes));
305 
306  /* Find the open file struct. */
307  if (g2c_file[g2cid].g2cid != g2cid)
308  return G2C_EBADID;
309 
310  /* Find the start and length of the GRIB message. */
311  {
312  g2int bytes_to_msg_g, bytes_in_msg_g;
313  seekgb(g2c_file[g2cid].f, (g2int)skip_bytes, (g2int)max_bytes, &bytes_to_msg_g,
314  &bytes_in_msg_g);
315  *bytes_to_msg = bytes_to_msg_g;
316  *bytes_in_msg = bytes_in_msg_g;
317  }
318  LOG((3, "*bytes_to_msg %ld *bytes_in_msg %ld", *bytes_to_msg, *bytes_in_msg));
319 
320  /* If no message was found, return an error. */
321  if (*bytes_in_msg == 0)
322  return G2C_ENOMSG;
323 
324  /* Allocate storage for the GRIB message. */
325  if (!(*cbuf = malloc(*bytes_in_msg)))
326  return G2C_ENOMEM;
327 
328  /* Position file at start of GRIB message. */
329  if (fseek(g2c_file[g2cid].f, (off_t)*bytes_to_msg, SEEK_SET))
330  {
331 #ifdef LOGGING
332  int my_errno = errno;
333  LOG((0, "fseek error %s", strerror(my_errno)));
334 #endif
335  return G2C_ERROR;
336  }
337 
338  /* Read the message from the file into the buffer. */
339  if ((bytes_read = fread(*cbuf, 1, *bytes_in_msg, g2c_file[g2cid].f)) != *bytes_in_msg)
340  return G2C_EFILE;
341 
342 #ifdef LOGGING
343  {
344  int i;
345  for (i = 0; i < 10; i++)
346  LOG((4, "cbuf[%d] = %2x", i, (*cbuf)[i]));
347  }
348 #endif
349 
350  return ret;
351 }
352 
364 static int
366 {
367  int i;
368  int ret;
369 
370  /* Check input. */
371  if (!g2cid)
372  return G2C_EINVAL;
373 
374  /* Find a new g2cid. */
375  for (i = 0; i < G2C_MAX_FILES + 1; i++)
376  {
377  int id = (i + g2c_next_g2cid) % (G2C_MAX_FILES + 1);
378 
379  /* Is this ID available? If so, we're done. */
380  if (!g2c_file[id].g2cid)
381  {
382  *g2cid = id;
383  g2c_next_g2cid = id + 1;
384  ret = G2C_NOERROR;
385  break;
386  }
387  }
388 
389  /* If we couldn't find one, all available files are already
390  * open. */
391  if (i == G2C_MAX_FILES + 1)
392  ret = G2C_ETOOMANYFILES;
393 
394  return ret;
395 }
396 
397 
417 static int
419 {
420  G2C_DIM_INFO_T *d0, *d1;
421  G2C_SECTION3_INFO_T *sec3_info;
422  int d;
423 
424  sec3_info = (G2C_SECTION3_INFO_T *)(sec->sec_info);
425  d0 = &(sec3_info->dim[0]);
426  d1 = &(sec3_info->dim[1]);
427 
428  /* Based on the grid definition template number, and the contents
429  * of the template, decide the len, name, and values of the two
430  * dimensions. */
431  switch (sec3_info->grid_def)
432  {
433  case 0:
434  LOG((5, "determine_dim allocating storage for lat/lon values"));
435  d0->len = sec->template[8];
436  strncpy(d0->name, LATITUDE, G2C_MAX_NAME);
437  if (!(d0->value = malloc(d0->len * sizeof(float))))
438  return G2C_ENOMEM;
439  d0->value[0] = sec->template[11];
440  for (d = 1; d < d0->len; d++)
441  d0->value[d] = d0->value[d - 1] - sec->template[16];
442 
443  d1->len = sec->template[7];
444  strncpy(d1->name, LONGITUDE, G2C_MAX_NAME);
445  if (!(d1->value = malloc(d1->len * sizeof(float))))
446  return G2C_ENOMEM;
447  d1->value[0] = sec->template[12];
448  for (d = 1; d < d1->len; d++)
449  d1->value[d] = d1->value[d - 1] - sec->template[17];
450  break;
451  default:
452  break;
453  }
454 
455  return G2C_NOERROR;
456 }
457 
480 int
481 g2c_rw_section3_metadata(FILE *f, int rw_flag, G2C_SECTION_INFO_T *sec)
482 {
483  G2C_SECTION3_INFO_T *sec3_info = NULL;
484  int maplen, needsext, map[G2C_MAX_GDS_TEMPLATE_MAPLEN];
485  int t;
486  int ret;
487 
488  /* Check input. */
489  if (!f || !sec)
490  return G2C_EINVAL;
491  if (!rw_flag && sec->sec_num != 3)
492  return G2C_EINVAL;
493 
494  LOG((6, "g2c_rw_section3_metadata starting to %s section 3 at file position %ld",
495  rw_flag ? "write" : "read", ftell(f)));
496 
497  /* If reading, allocate storage for a new section 3. */
498  if (!rw_flag)
499  {
500  if (!(sec3_info = calloc(sizeof(G2C_SECTION3_INFO_T), 1)))
501  return G2C_ENOMEM;
502  }
503  else
504  sec3_info = sec->sec_info;
505 
506  /* Read or write section 3. */
507  if ((ret = g2c_file_io_ubyte(f, rw_flag, &sec3_info->source_grid_def)))
508  return ret;
509  if ((ret = g2c_file_io_uint(f, rw_flag, &sec3_info->num_data_points)))
510  return ret;
511  if ((ret = g2c_file_io_ubyte(f, rw_flag, &sec3_info->num_opt)))
512  return ret;
513  if ((ret = g2c_file_io_ubyte(f, rw_flag, &sec3_info->interp_list)))
514  return ret;
515  if ((ret = g2c_file_io_ushort(f, rw_flag, &sec3_info->grid_def)))
516  return ret;
517  LOG((5, "rw_section3_metadata source_grid_def %d num_data_points %d num_opt %d interp_list %d grid_def %d",
518  sec3_info->source_grid_def, sec3_info->num_data_points, sec3_info->num_opt, sec3_info->interp_list,
519  sec3_info->grid_def));
520 
521  /* Look up the information about this grid. */
522  if ((ret = g2c_get_grid_template(sec3_info->grid_def, &maplen, map, &needsext)))
523  return ret;
524 
525  /* When reading, allocate space to hold the template info. */
526  if (!rw_flag)
527  {
528  sec->template_len = maplen;
529  if (!(sec->template = calloc(sizeof(long long int) * maplen, 1)))
530  return G2C_ENOMEM;
531  }
532 
533  /* Read or write the template info. */
534  for (t = 0; t < maplen; t++)
535  {
536  if ((ret = g2c_file_io_template(f, rw_flag, map[t], &sec->template[t])))
537  return ret;
538  LOG((7, "template[%d] %d", t, sec->template[t]));
539  }
540 
541  /* Attach sec3_info to our section data. */
542  if (!rw_flag)
543  sec->sec_info = sec3_info;
544 
545  /* Figure out the dimensions, if we can. */
546  if (!rw_flag)
547  if ((ret = determine_dims(sec)))
548  return ret;
549 
550  LOG((6, "finished reading or writing section 3 at file position %ld", ftell(f)));
551  return G2C_NOERROR;
552 }
553 
576 int
577 g2c_rw_section4_metadata(FILE *f, int rw_flag, G2C_SECTION_INFO_T *sec)
578 {
579  G2C_SECTION4_INFO_T *sec4_info;
580  int maplen, needsext, map[G2C_MAX_PDS_TEMPLATE_MAPLEN];
581  int t;
582  int ret;
583 
584  /* Check input. */
585  if (!f || !sec)
586  return G2C_EINVAL;
587  if (!rw_flag && sec->sec_num != 4)
588  return G2C_EINVAL;
589 
590  LOG((3, "read_section4_metadata rw_flag %d", rw_flag));
591 
592  /* When reading, allocate storage for a new section 4. */
593  if (!rw_flag)
594  {
595  if (!(sec4_info = calloc(sizeof(G2C_SECTION4_INFO_T), 1)))
596  return G2C_ENOMEM;
597  }
598  else
599  sec4_info = sec->sec_info;
600 
601  /* When reading, assign a number to this field, and count the
602  * number of fields in the message. */
603  if (!rw_flag)
604  sec4_info->field_num = sec->msg->num_fields++;
605 
606  LOG((6, "reading section 4 starting at file position %ld", ftell(f)));
607 
608  /* Read section 4. */
609  if ((ret = g2c_file_io_ushort(f, rw_flag, &sec4_info->num_coord)))
610  return ret;
611  if ((ret = g2c_file_io_ushort(f, rw_flag, &sec4_info->prod_def)))
612  return ret;
613  LOG((5, "read_section4_metadata num_coord %d prod_def %d", sec4_info->num_coord, sec4_info->prod_def));
614 
615  /* Look up the information about this grid. */
616  if ((ret = g2c_get_pds_template(sec4_info->prod_def, &maplen, map, &needsext)))
617  return ret;
618  LOG((5, "pds template maplen %d", maplen));
619 
620  /* When reading, allocate space to hold the template info. */
621  if (!rw_flag)
622  {
623  sec->template_len = maplen;
624  if (!(sec->template = calloc(sizeof(long long int) * maplen, 1)))
625  return G2C_ENOMEM;
626  }
627 
628  /* Read or write the template info. */
629  for (t = 0; t < maplen; t++)
630  {
631  if ((ret = g2c_file_io_template(f, rw_flag, map[t], &sec->template[t])))
632  return ret;
633  LOG((7, "template[%d] %d", t, sec->template[t]));
634  }
635 
636  /* When reading, attach sec4_info to our section data. */
637  if (!rw_flag)
638  sec->sec_info = sec4_info;
639 
640  return G2C_NOERROR;
641 }
642 
665 int
666 g2c_rw_section5_metadata(FILE *f, int rw_flag, G2C_SECTION_INFO_T *sec)
667 {
668  G2C_SECTION5_INFO_T *sec5_info;
669  int maplen, needsext, map[G2C_MAX_PDS_TEMPLATE_MAPLEN];
670  int t;
671  int ret;
672 
673  /* Check input. */
674  if (!f || !sec)
675  return G2C_EINVAL;
676  LOG((5, "g2c_rw_section5_metadata rw_flag %d at file position %ld", rw_flag,
677  ftell(f)));
678 
679  /* When reading, allocate storage for a new section 5. When
680  * writing, get a pointer to the exitsing sec5_info. */
681  if (!rw_flag)
682  {
683  if (!(sec5_info = calloc(sizeof(G2C_SECTION5_INFO_T), 1)))
684  return G2C_ENOMEM;
685  }
686  else
687  sec5_info = sec->sec_info;
688 
689  /* Read section 5. */
690  if ((ret = g2c_file_io_uint(f, rw_flag, &sec5_info->num_data_points)))
691  return ret;
692  if ((ret = g2c_file_io_ushort(f, rw_flag, &sec5_info->data_def)))
693  return ret;
694  LOG((5, "g2c_rw_section5_metadata num_data_points %d data_def %d",
695  sec5_info->num_data_points, sec5_info->data_def));
696 
697  /* Look up the information about this grid. */
698  if ((ret = g2c_get_drs_template(sec5_info->data_def, &maplen, map, &needsext)))
699  return ret;
700  LOG((5, "grid template maplen %d", maplen));
701 
702  /* WHen reading, allocate space to hold the template info. */
703  if (!rw_flag)
704  {
705  sec->template_len = maplen;
706  if (!(sec->template = calloc(sizeof(long long int) * maplen, 1)))
707  return G2C_ENOMEM;
708  }
709 
710  /* Read or write the template info. */
711  for (t = 0; t < maplen; t++)
712  {
713  if ((ret = g2c_file_io_template(f, rw_flag, map[t], &sec->template[t])))
714  return ret;
715  LOG((7, "template[%d] %d", t, sec->template[t]));
716  }
717 
718  /* When reading, attach sec5_info to our section data. */
719  if (!rw_flag)
720  sec->sec_info = sec5_info;
721 
722  return G2C_NOERROR;
723 }
724 
747 int
748 g2c_rw_section6_metadata(FILE *f, int rw_flag, G2C_SECTION_INFO_T *sec)
749 {
750  G2C_SECTION6_INFO_T *sec6_info;
751  int ret;
752 
753  /* Check input. */
754  if (!f || !sec)
755  return G2C_EINVAL;
756  LOG((6, "g2c_rw_section6_metadata rw_flag %d at file position %ld", rw_flag,
757  ftell(f)));
758 
759  /* When reading, allocate storage for a new section 6. When
760  * writing, get a pointer to the exitsing sec6_info. */
761  if (!rw_flag)
762  {
763  if (!(sec6_info = calloc(sizeof(G2C_SECTION6_INFO_T), 1)))
764  return G2C_ENOMEM;
765  }
766  else
767  sec6_info = sec->sec_info;
768 
769  /* Read section 6. */
770  if ((ret = g2c_file_io_ubyte(f, rw_flag, &sec6_info->indicator)))
771  return ret;
772  LOG((5, "g2c_rw_section6_metadata indicator %d", sec6_info->indicator));
773 
774  /* When reading, attach sec6_info to our section data. */
775  if (!rw_flag)
776  sec->sec_info = sec6_info;
777 
778  return G2C_NOERROR;
779 }
780 
796 int
797 add_section(FILE *f, G2C_MESSAGE_INFO_T *msg, int sec_id, unsigned int sec_len,
798  size_t bytes_to_sec, unsigned char sec_num)
799 {
800  G2C_SECTION_INFO_T *sec;
801  int ret;
802 
803  LOG((3, "add_section sec_id %d sec_len %d, bytes_to_sec %ld, sec_num %d",
804  sec_id, sec_len, bytes_to_sec, sec_num));
805 
806  /* Allocate storage for a new section. */
807  if (!(sec = calloc(sizeof(G2C_SECTION_INFO_T), 1)))
808  return G2C_ENOMEM;
809 
810  /* Add sec to end of linked list. */
811  if (!msg->sec)
812  msg->sec = sec;
813  else
814  {
816 
817  for (s = msg->sec; s->next; s = s->next)
818  ;
819  s->next = sec;
820  sec->prev = s;
821  }
822 
823  /* Remember values. */
824  sec->msg = msg;
825  sec->sec_id = sec_id;
826  sec->sec_len = sec_len;
827  sec->sec_num = sec_num;
828  sec->bytes_to_sec = bytes_to_sec;
829 
830  switch (sec_num)
831  {
832  case 1:
833  break;
834  case 2:
835  msg->num_local++;
836  break;
837  case 3:
838  if ((ret = g2c_rw_section3_metadata(f, G2C_FILE_READ, sec)))
839  return ret;
840  break;
841  case 4:
842  if ((ret = g2c_rw_section4_metadata(f, G2C_FILE_READ, sec)))
843  return ret;
844  break;
845  case 5:
846  if ((ret = g2c_rw_section5_metadata(f, G2C_FILE_READ, sec)))
847  return ret;
848  break;
849  case 6:
850  if ((ret = g2c_rw_section6_metadata(f, G2C_FILE_READ, sec)))
851  return ret;
852  break;
853  case 7:
854  break;
855  default:
856  return G2C_EBADSECTION;
857  }
858 
859  return G2C_NOERROR;
860 }
861 
876 int
877 g2c_rw_section1_metadata(FILE *f, int rw_flag, G2C_MESSAGE_INFO_T *msg)
878 {
879  unsigned char sec_num = 1;
880  int ret;
881 
882  LOG((2, "g2c_rw_section1_metadata rw_flag %d", rw_flag));
883 
884  /* Read the section. */
885  if ((ret = g2c_file_io_uint(f, rw_flag, (unsigned int *)&msg->sec1_len)))
886  return ret;
887 
888  if ((ret = g2c_file_io_ubyte(f, rw_flag, &sec_num)))
889  return ret;
890  if (!rw_flag && sec_num != 1) /* When reading sec num must be 1. */
891  return G2C_ENOSECTION;
892  if ((ret = g2c_file_io_short(f, rw_flag, &msg->center)))
893  return ret;
894  if ((ret = g2c_file_io_short(f, rw_flag, &msg->subcenter)))
895  return ret;
896  if ((ret = g2c_file_io_ubyte(f, rw_flag, &msg->master_version)))
897  return ret;
898  if ((ret = g2c_file_io_ubyte(f, rw_flag, &msg->local_version)))
899  return ret;
900  if ((ret = g2c_file_io_ubyte(f, rw_flag, &msg->sig_ref_time)))
901  return ret;
902  if ((ret = g2c_file_io_short(f, rw_flag, &msg->year)))
903  return ret;
904  if ((ret = g2c_file_io_ubyte(f, rw_flag, &msg->month)))
905  return ret;
906  if ((ret = g2c_file_io_ubyte(f, rw_flag, &msg->day)))
907  return ret;
908  if ((ret = g2c_file_io_ubyte(f, rw_flag, &msg->hour)))
909  return ret;
910  if ((ret = g2c_file_io_ubyte(f, rw_flag, &msg->minute)))
911  return ret;
912  if ((ret = g2c_file_io_ubyte(f, rw_flag, &msg->second)))
913  return ret;
914  if ((ret = g2c_file_io_ubyte(f, rw_flag, &msg->status)))
915  return ret;
916  if ((ret = g2c_file_io_ubyte(f, rw_flag, &msg->type)))
917  return ret;
918 
919  /* Section 1 may contain optional numbers at the end of the
920  * section. The sec1_len tells us if there are extra values. If
921  * so, skip them. */
922  if (msg->sec1_len > G2C_SECTION1_BYTES)
923  fseek(f, msg->sec1_len - G2C_SECTION1_BYTES, SEEK_CUR);
924 
925  return G2C_NOERROR;
926 }
927 
939 static int
941 {
942  int total_read = G2C_SECTION0_BYTES;
943  int sec_id = 0;
944  int ret;
945 
946  LOG((6, "read_msg_metadata file position %ld", ftell(msg->file->f)));
947 
948  /* Read section 0. */
949  if (fseek(msg->file->f, msg->bytes_to_msg + BYTES_TO_DISCIPLINE, SEEK_SET))
950  return G2C_EFILE;
951  if ((fread(&msg->discipline, ONE_BYTE, 1, msg->file->f)) != 1)
952  return G2C_EFILE;
953 
954  /* Skip to section 1. */
955  if (fseek(msg->file->f, 9, SEEK_CUR))
956  return G2C_EFILE;
957 
958  /* Read section 1. */
959  if ((ret = g2c_rw_section1_metadata(msg->file->f, G2C_FILE_READ, msg)))
960  return ret;
961  total_read += msg->sec1_len;
962 
963  /* Read the sections. */
964  while (total_read < msg->bytes_in_msg - FOUR_BYTES)
965  {
966  unsigned int sec_len;
967  unsigned char sec_num;
968 
969  LOG((4, "reading new section at file position %ld", ftell(msg->file->f)));
970 
971  /* Read section length. */
972  if ((ret = g2c_file_io_uint(msg->file->f, G2C_FILE_READ, &sec_len)))
973  return ret;
974 
975  /* A section length of 926365495 indicates we've reached
976  * section 8, the end of the message. */
977  if (sec_len != 926365495)
978  {
979  /* Read section number. */
980  if ((ret = g2c_file_io_ubyte(msg->file->f, G2C_FILE_READ, &sec_num)))
981  return ret;
982  LOG((4, "sec_len %d sec_num %d", sec_len, sec_num));
983 
984  /* Add a new section to our list of sections. */
985  if ((ret = add_section(msg->file->f, msg, sec_id++, sec_len, total_read, sec_num)))
986  return G2C_EBADSECTION;
987 
988  /* Skip to next section. */
989  total_read += sec_len;
990  LOG((4, "total_read %d", total_read));
991  if (fseek(msg->file->f, msg->bytes_to_msg + total_read, SEEK_SET))
992  return G2C_EFILE;
993  }
994  else
995  break;
996  }
997 
998  return G2C_NOERROR;
999 }
1000 
1019 int
1020 add_msg(G2C_FILE_INFO_T *file, int msg_num, size_t bytes_to_msg, size_t bytes_in_msg,
1021  int read_file, G2C_MESSAGE_INFO_T **msg)
1022 {
1023  G2C_MESSAGE_INFO_T *my_msg;
1024  int ret;
1025 
1026  LOG((3, "add_msg msg_num %d bytes_to_msg %ld bytes_in_msg %ld read_file %d",
1027  msg_num, bytes_to_msg, bytes_in_msg, read_file));
1028 
1029  /* Allocate storage for a new message. */
1030  if (!(my_msg = calloc(sizeof(G2C_MESSAGE_INFO_T), 1)))
1031  return G2C_ENOMEM;
1032 
1033  /* Add my_msg to end of linked list. */
1034  if (!file->msg)
1035  file->msg = my_msg;
1036  else
1037  {
1038  G2C_MESSAGE_INFO_T *m;
1039 
1040  for (m = file->msg; m->next; m = m->next)
1041  ;
1042  m->next = my_msg;
1043  }
1044 
1045  /* Remember values. */
1046  my_msg->msg_num = msg_num;
1047  my_msg->bytes_to_msg = bytes_to_msg;
1048  my_msg->bytes_in_msg = bytes_in_msg;
1049  my_msg->file = file;
1050 
1051  /* Read message metadata. We do this if we are opening a GRIB2
1052  * data file, but not if we are reading a GRIB2 index file. */
1053  if (read_file)
1054  if ((ret = read_msg_metadata(my_msg)))
1055  return ret;
1056 
1057  /* Increment number of messages in the file. */
1058  my_msg->file->num_messages++;
1059 
1060  /* Return pointer to caller, if desired. */
1061  if (msg)
1062  *msg = my_msg;
1063 
1064  return G2C_NOERROR;
1065 }
1066 
1081 static int
1082 read_metadata(int g2cid)
1083 {
1084  size_t msg_num;
1085  size_t file_pos = 0;
1086  size_t bytes_to_msg, bytes_in_msg;
1087  int ret = G2C_NOERROR;
1088 
1089  /* Find the open file struct. */
1090  if (g2c_file[g2cid].g2cid != g2cid)
1091  return G2C_EBADID;
1092 
1093  LOG((2, "read_metadata g2cid %d", g2cid));
1094 
1095  /* Read each message in the file. */
1096  for (msg_num = 0; !ret; msg_num++)
1097  {
1098  /* Find the message. */
1099  if ((ret = g2c_seekmsg(g2cid, file_pos, &bytes_to_msg, &bytes_in_msg)))
1100  return ret;
1101  LOG((3, "msg_num %d bytes_to_msg %ld bytes_in_msg %ld", msg_num, bytes_to_msg,
1102  bytes_in_msg));
1103 
1104  /* When there are 0 bytes_in_msg, we are done. */
1105  if (!bytes_in_msg)
1106  break;
1107 
1108  /* Add new message to our list of messages. */
1109  if ((ret = add_msg(&g2c_file[g2cid], msg_num, bytes_to_msg, bytes_in_msg,
1110  1, NULL)))
1111  return ret;
1112 
1113  /* Move the file position to the end of this message, ready to
1114  * scan for the next message. */
1115  file_pos = bytes_to_msg + bytes_in_msg;
1116  LOG((6, "file_pos %ld", file_pos));
1117  }
1118 
1119  /* If we run out of messages, that's success. */
1120  if (ret == G2C_ENOMSG)
1121  ret = G2C_NOERROR;
1122 
1123 #ifdef LOGGING
1124  /* Print the file contents for library debugging. */
1125  g2c_log_file(g2cid);
1126 #endif
1127 
1128  return ret;
1129 }
1130 
1145 int
1146 g2c_add_file(const char *path, int mode, int *g2cid)
1147 {
1148  int ret;
1149 
1150  /* Check inputs. */
1151  if (strlen(path) > G2C_MAX_NAME)
1152  return G2C_ENAMETOOLONG;
1153  if (!g2cid)
1154  return G2C_EINVAL;
1155 
1156  LOG((1, "g2c_add_file path %s mode %d", path, mode));
1157 
1158  /* Find a file ID. */
1159  if ((ret = find_available_g2cid(g2cid)))
1160  return ret;
1161 
1162  /* Open the file. */
1163  if (!(g2c_file[*g2cid].f = fopen(path, (mode & G2C_WRITE ? "rb+" : "rb"))))
1164  return G2C_EFILE;
1165 
1166  /* Copy the path. */
1167  strncpy(g2c_file[*g2cid].path, path, G2C_MAX_NAME);
1168 
1169  /* Remember the id. */
1170  g2c_file[*g2cid].g2cid = *g2cid;
1171 
1172  /* Initialize other values in struct. */
1173  g2c_file[*g2cid].msg = NULL;
1174  g2c_file[*g2cid].num_messages = 0;
1175 
1176  return G2C_NOERROR;
1177 }
1178 
1192 int
1193 g2c_open(const char *path, int mode, int *g2cid)
1194 {
1195  int ret;
1196 
1197  /* If using threading, lock the mutex. */
1198  MUTEX_LOCK(m);
1199 
1200  /* Open the file and add it to the list of open files. */
1201  ret = g2c_add_file(path, mode, g2cid);
1202 
1203  /* Read the metadata. */
1204  if (!ret)
1205  ret = read_metadata(*g2cid);
1206 
1207  /* If using threading, unlock the mutex. */
1208  MUTEX_UNLOCK(m);
1209 
1210  return ret;
1211 }
1212 
1213 #if 0
1226 int
1227 g2c_create(const char *path, int cmode, int *g2cid)
1228 {
1229  int my_g2cid;
1230  int ret;
1231 
1232  /* Check inputs. */
1233  if (strlen(path) > G2C_MAX_NAME)
1234  return G2C_ENAMETOOLONG;
1235  if (!g2cid)
1236  return G2C_EINVAL;
1237 
1238  LOG((1, "g2c_create path %s cmode %d", path, cmode));
1239 
1240  /* If NOCLOBBER, check if file exists. */
1241  if (cmode & G2C_NOCLOBBER)
1242  {
1243  FILE *f;
1244  if ((f = fopen(path, "r")))
1245  {
1246  fclose(f);
1247  return G2C_EFILE;
1248  }
1249  }
1250 
1251  /* If using threading, lock the mutex. */
1252  MUTEX_LOCK(m);
1253 
1254  /* Find a file ID. */
1255  ret = find_available_g2cid(&my_g2cid);
1256 
1257  /* Create the file. */
1258  if (!ret)
1259  if (!(g2c_file[my_g2cid].f = fopen(path, "bw+")))
1260  ret = G2C_EFILE;
1261 
1262  if (!ret)
1263  {
1264  /* Read the metadata. */
1265 
1266  /* Copy the path. */
1267  strncpy(g2c_file[my_g2cid].path, path, G2C_MAX_NAME);
1268 
1269  /* Remember the id. */
1270  g2c_file[my_g2cid].g2cid = my_g2cid;
1271 
1272  /* Pass id back to user. */
1273  *g2cid = my_g2cid;
1274  }
1275 
1276  /* If using threading, unlock the mutex. */
1277  MUTEX_UNLOCK(m);
1278 
1279  return G2C_NOERROR;
1280 }
1281 #endif
1282 
1293 static int
1294 free_metadata(int g2cid)
1295 {
1296  G2C_MESSAGE_INFO_T *msg;
1297 
1298  /* Check input. */
1299  if (g2cid > G2C_MAX_FILES)
1300  return G2C_EBADID;
1301  if (g2c_file[g2cid].g2cid != g2cid)
1302  return G2C_EBADID;
1303 
1304  /* Free message resources. */
1305  msg = g2c_file[g2cid].msg;
1306  while (msg)
1307  {
1308  G2C_MESSAGE_INFO_T *mtmp;
1309  G2C_SECTION_INFO_T *sec;
1310 
1311  /* Free section metadata. */
1312  sec = msg->sec;
1313  while (sec)
1314  {
1315  G2C_SECTION_INFO_T *stmp;
1316 
1317  stmp = sec->next;
1318  if (sec->template)
1319  free(sec->template);
1320  /* Free dim info in section 3. */
1321  if (sec->sec_num == 3)
1322  {
1323  LOG((5, "free_metadata freeing storage for lat/lon values"));
1324  float *v0 = ((G2C_SECTION3_INFO_T *)(sec->sec_info))->dim[0].value;
1325  float *v1 = ((G2C_SECTION3_INFO_T *)(sec->sec_info))->dim[1].value;
1326  if (v0)
1327  free(v0);
1328  if (v1)
1329  free(v1);
1330  }
1331  if (sec->sec_info)
1332  free(sec->sec_info);
1333  free(sec);
1334  sec = stmp;
1335  }
1336 
1337  /* Free message. */
1338  mtmp = msg->next;
1339  free(msg);
1340  msg = mtmp;
1341  }
1342 
1343  return G2C_NOERROR;
1344 }
1345 
1356 int
1357 g2c_close(int g2cid)
1358 {
1359  int ret = G2C_NOERROR;
1360 
1361  /* Check input. */
1362  if (g2cid > G2C_MAX_FILES)
1363  return G2C_EBADID;
1364 
1365  /* If using threading, lock the mutex. */
1366  MUTEX_LOCK(m);
1367 
1368  if (g2c_file[g2cid].g2cid != g2cid)
1369  ret = G2C_EBADID;
1370 
1371  LOG((1, "g2c_close %d", g2cid));
1372 
1373  /* Free resources. */
1374  if (!ret)
1375  ret = free_metadata(g2cid);
1376 
1377  /* Close the file. */
1378  if (!ret)
1379  if (fclose(g2c_file[g2cid].f))
1380  ret = G2C_EFILE;
1381 
1382  /* Reset the file data. */
1383  if (!ret)
1384  {
1385  g2c_file[g2cid].path[0] = 0;
1386  g2c_file[g2cid].g2cid = 0;
1387  g2c_file[g2cid].num_messages = 0;
1388  g2c_file[g2cid].f = NULL;
1389  }
1390 
1391  /* If using threading, unlock the mutex. */
1392  MUTEX_UNLOCK(m);
1393 
1394  return ret;
1395 }
int g2c_get_drs_template(int drs_template_num, int *maplen, int *map, int *needext)
Get DRS template information.
Definition: drstemplates.c:261
int g2c_open(const char *path, int mode, int *g2cid)
Open an existing GRIB2 file.
Definition: g2cfile.c:1193
#define MIN(a, b)
Find a minimum.
Definition: g2cfile.c:16
#define READ_BUF_SIZE
Default size of read-buffer.
Definition: g2cfile.c:19
static int determine_dims(G2C_SECTION_INFO_T *sec)
Determine the dimension information from the section 3 metadata.
Definition: g2cfile.c:418
MUTEX(m)
Define mutex for thread-safety.
static int read_msg_metadata(G2C_MESSAGE_INFO_T *msg)
Read the file to get metadata about a message.
Definition: g2cfile.c:940
int g2c_rw_section6_metadata(FILE *f, int rw_flag, G2C_SECTION_INFO_T *sec)
Read or write the metadata from section 6 (Data Representation Section) of a GRIB2 message.
Definition: g2cfile.c:748
int g2c_close(int g2cid)
Close a GRIB2 file, freeing resources.
Definition: g2cfile.c:1357
G2C_FILE_INFO_T g2c_file[G2C_MAX_FILES+1]
Global file information.
Definition: g2cfile.c:10
int add_msg(G2C_FILE_INFO_T *file, int msg_num, size_t bytes_to_msg, size_t bytes_in_msg, int read_file, G2C_MESSAGE_INFO_T **msg)
Add new message to linked list.
Definition: g2cfile.c:1020
int g2c_get_msg(int g2cid, size_t skip_bytes, size_t max_bytes, size_t *bytes_to_msg, size_t *bytes_in_msg, unsigned char **cbuf)
Search a file for the next GRIB1 or GRIB2 message, and read it, allocating space in memory to hold th...
Definition: g2cfile.c:293
int add_section(FILE *f, G2C_MESSAGE_INFO_T *msg, int sec_id, unsigned int sec_len, size_t bytes_to_sec, unsigned char sec_num)
Add metadata about a new section 3, 4, 5, 6, or 7.
Definition: g2cfile.c:797
#define BYTES_TO_DISCIPLINE
Number of bytes to discipline field in GRIB2 message.
Definition: g2cfile.c:22
int g2c_find_msg2(int g2cid, size_t skip_bytes, size_t max_bytes, size_t *bytes_to_msg, size_t *bytes_in_msg)
Search a file for the next GRIB1 or GRIB2 message.
Definition: g2cfile.c:164
static int free_metadata(int g2cid)
Free resources holding the file metadata.
Definition: g2cfile.c:1294
int g2c_rw_section5_metadata(FILE *f, int rw_flag, G2C_SECTION_INFO_T *sec)
Read or write the metadata from section 5 (Data Representation Section) of a GRIB2 message.
Definition: g2cfile.c:666
static int read_metadata(int g2cid)
Read metadata from a GRIB2 file being opened with g2c_open().
Definition: g2cfile.c:1082
int g2c_rw_section1_metadata(FILE *f, int rw_flag, G2C_MESSAGE_INFO_T *msg)
Read Section 1.
Definition: g2cfile.c:877
int g2c_add_file(const char *path, int mode, int *g2cid)
Open a GRIB2 file and add it to the list of open files.
Definition: g2cfile.c:1146
static int find_available_g2cid(int *g2cid)
Find a g2cid to use for a newly opened or created file.
Definition: g2cfile.c:365
int g2c_seekmsg(int g2cid, size_t skip, size_t *offset, size_t *msglen)
Search a file for the next GRIB2 Message.
Definition: g2cfile.c:56
int g2c_rw_section3_metadata(FILE *f, int rw_flag, G2C_SECTION_INFO_T *sec)
Read the metadata from section 3 (Grid Definition Section) of a GRIB2 message.
Definition: g2cfile.c:481
int g2c_rw_section4_metadata(FILE *f, int rw_flag, G2C_SECTION_INFO_T *sec)
Read or write the metadata from section 4 (Product Definition Section) of a GRIB2 message.
Definition: g2cfile.c:577
#define G2C_SEEKMSG_BUFSIZE
Size of buffer used in g2c_seekmsg().
Definition: g2cfile.c:27
int g2c_next_g2cid
Next g2cid file ID - used when opening or creating a file.
Definition: g2cfile.c:13
int g2c_file_io_ushort(FILE *f, int write, unsigned short *var)
Read or write a big-endian unsigned short to an open GRIB2 file, with conversion between native and b...
Definition: g2cio.c:294
int g2c_file_io_template(FILE *f, int rw_flag, int map, long long int *template_value)
Read or write a big-endian 4-byte int or unsigned int from or to an open file, with conversion betwee...
Definition: g2cio.c:408
int g2c_file_io_short(FILE *f, int write, short *var)
Read or write a big-endian signed short to an open GRIB2 file, with conversion between native and big...
Definition: g2cio.c:273
int g2c_file_io_ubyte(FILE *f, int write, unsigned char *var)
Read or write a big-endian unsigned byte to an open GRIB2 file, with conversion between native and bi...
Definition: g2cio.c:337
int g2c_file_io_uint(FILE *f, int write, unsigned int *var)
Read or write a big-endian 4-byte unsigned int to an open GRIB2 file, with conversion between native ...
Definition: g2cio.c:251
int g2c_log_file(int g2cid)
Print a summary of the contents of an open GRIB2 file.
Definition: g2cutil.c:188
#define G2C_EMSG
Error decoding GRIB message.
Definition: grib2.h:501
#define G2C_MAX_FILES
Maximum number of open files.
Definition: grib2.h:289
#define G2C_NOCLOBBER
Don't destroy existing file.
Definition: grib2.h:294
#define G2C_ENOMSG
No GRIB message found.
Definition: grib2.h:502
#define G2C_ENAMETOOLONG
Name too long.
Definition: grib2.h:495
#define G2C_WRITE
Set read-write access for g2c_open().
Definition: grib2.h:292
#define G2C_ENOSECTION
Cannot find section.
Definition: grib2.h:506
#define G2C_EFILE
File I/O error.
Definition: grib2.h:497
#define G2C_MAX_GDS_TEMPLATE_MAPLEN
Maximum grid template map length.
Definition: grib2.h:308
#define G2C_ENOMEM
Out of memory.
Definition: grib2.h:500
#define G2C_ERROR
General error code, returned for some test errors.
Definition: grib2.h:492
#define G2C_MAX_NAME
Maximum length of a name.
Definition: grib2.h:290
#define G2C_EINVAL
Invalid input.
Definition: grib2.h:496
#define G2C_ETOOMANYFILES
Trying to open too many files.
Definition: grib2.h:499
#define G2C_EBADSECTION
Invalid section number.
Definition: grib2.h:509
#define G2C_MAX_PDS_TEMPLATE_MAPLEN
Maximum template map length.
Definition: grib2.h:310
#define G2C_SECTION0_BYTES
Number of bytes in section 0.
Definition: grib2.h:297
int64_t g2int
Long integer type.
Definition: grib2.h:33
#define G2C_EBADID
Bad ID.
Definition: grib2.h:498
#define G2C_NOERROR
No error.
Definition: grib2.h:491
#define G2C_SECTION1_BYTES
Number of bytes in section 1 (not including reserved, optional data at the end of the section).
Definition: grib2.h:301
Header file with internal function prototypes NCEPLIBS-g2c library.
#define G2C_FILE_READ
Read.
Definition: grib2_int.h:129
struct g2c_section_info * next
Pointer to next in list.
Definition: grib2_int.h:176
struct g2c_section_info * sec
List of section metadata.
Definition: grib2_int.h:162
size_t len
Length of dimension.
Definition: grib2_int.h:186
short subcenter
Originating subcenter.
Definition: grib2_int.h:150
int sec_id
ID of the section (0-based).
Definition: grib2_int.h:170
#define G2C_MAGIC_HEADER_LEN
Full length of magic header string (includes GRIB version byte).
Definition: grib2_int.h:42
G2C_DIM_INFO_T dim[2]
Dimension information.
Definition: grib2_int.h:201
unsigned char master_version
GRIB master tables version number.
Definition: grib2_int.h:151
#define FOUR_BYTES
Four bytes.
Definition: grib2_int.h:52
#define MUTEX_UNLOCK(m)
Pthreads not enabled, so do nothing.
Definition: grib2_int.h:117
char path[G2C_MAX_NAME+1]
Path of the file.
Definition: grib2_int.h:238
unsigned char type
Type of processed data in this GRIB message.
Definition: grib2_int.h:161
unsigned short grid_def
Grid definition template number (= N) (See Table 3.1).
Definition: grib2_int.h:199
unsigned char hour
Hour.
Definition: grib2_int.h:157
#define G2C_MAGIC_HEADER
GRIB magic header string.
Definition: grib2_int.h:39
unsigned char minute
Minute.
Definition: grib2_int.h:158
unsigned int num_data_points
Number of data points.
Definition: grib2_int.h:196
size_t num_messages
Number of messages in the file.
Definition: grib2_int.h:240
unsigned short num_coord
Number of coordinate values after template.
Definition: grib2_int.h:209
int num_local
Number of local sections in the message.
Definition: grib2_int.h:141
unsigned char sig_ref_time
Significance of reference time.
Definition: grib2_int.h:153
#define LATITUDE
Latitude.
Definition: grib2_int.h:56
unsigned char num_opt
Number of octets for optional list of numbers defining number of points.
Definition: grib2_int.h:197
unsigned char discipline
Discipline from section 0.
Definition: grib2_int.h:138
int g2cid
ID of the file.
Definition: grib2_int.h:237
char name[G2C_MAX_NAME+1]
Name of dimension.
Definition: grib2_int.h:187
unsigned char interp_list
Interpetation of list of numbers defining number of points (See Table 3.11).
Definition: grib2_int.h:198
size_t bytes_in_msg
Number of bytes in this message.
Definition: grib2_int.h:137
struct g2c_section_info * prev
Pointer to previous in list.
Definition: grib2_int.h:177
int num_fields
Number of fields in the message.
Definition: grib2_int.h:140
unsigned char sec_num
Section number.
Definition: grib2_int.h:173
#define G2C_MIN_MAX_BYTES
Minimum acceptable value for max_bytes parameter of g2c_get_msg().
Definition: grib2_int.h:36
unsigned int num_data_points
Number of data points where one or more values are specified in Section 7 when a bit map is present,...
Definition: grib2_int.h:221
void * sec_info
Pointer to struct specific for section 3, 4, 5, 6, or 7.
Definition: grib2_int.h:175
float * value
Array of dimension values.
Definition: grib2_int.h:188
unsigned char indicator
Bit map indicator.
Definition: grib2_int.h:231
unsigned int sec_len
Length of the section (in bytes).
Definition: grib2_int.h:171
short year
Year.
Definition: grib2_int.h:154
size_t bytes_to_sec
Number of bytes from start of message to this section.
Definition: grib2_int.h:172
unsigned char status
Production Status of Processed data in the GRIB message.
Definition: grib2_int.h:160
#define LONGITUDE
Longitude.
Definition: grib2_int.h:59
G2C_MESSAGE_INFO_T * msg
Information about each message in the file.
Definition: grib2_int.h:241
#define ONE_BYTE
One byte.
Definition: grib2_int.h:50
#define LOG(e)
Ignore logging to stdout.
Definition: grib2_int.h:426
unsigned char second
Second.
Definition: grib2_int.h:159
unsigned char day
Day.
Definition: grib2_int.h:156
FILE * f
FILE pointer to open file.
Definition: grib2_int.h:239
unsigned char source_grid_def
Source of grid definition (See Table 3.0).
Definition: grib2_int.h:195
int template_len
Number of entries in template.
Definition: grib2_int.h:179
unsigned char local_version
Version number of GRIB local tables used to augment Master Tables.
Definition: grib2_int.h:152
#define hton64(y)
Byte swap 64-bit ints.
Definition: grib2_int.h:127
unsigned char month
Month.
Definition: grib2_int.h:155
size_t msg_num
Number of message in file (0-based).
Definition: grib2_int.h:135
unsigned short data_def
Data representation template number (See Table 5.0).
Definition: grib2_int.h:222
size_t bytes_to_msg
Number of bytes to skip in the file, to get to this message.
Definition: grib2_int.h:136
#define MUTEX_LOCK(m)
Pthreads not enabled, so do nothing.
Definition: grib2_int.h:114
long long int * template
Grid, product, or data template.
Definition: grib2_int.h:178
int sec1_len
Length of section 1.
Definition: grib2_int.h:148
struct g2c_message_info * next
Pointer to next in list.
Definition: grib2_int.h:164
G2C_MESSAGE_INFO_T * msg
Pointer to contianing message.
Definition: grib2_int.h:174
short center
Originating center.
Definition: grib2_int.h:149
struct g2c_file_info * file
Pointer to containing file.
Definition: grib2_int.h:163
unsigned short prod_def
Product definition template number (See Table 4.0).
Definition: grib2_int.h:210
Keep information about dimensions defined in section 3.
Definition: grib2_int.h:184
This is the information about each open file.
Definition: grib2_int.h:236
This is the information about each message.
Definition: grib2_int.h:134
Information about Section 3 GRID DEFINITION SECTION.
Definition: grib2_int.h:194
Information about Section 4 PRODUCT DEFINITION SECTION.
Definition: grib2_int.h:207
Information about Section 5 DATA REPRESENTATION SECTION.
Definition: grib2_int.h:217
Information about Section 6 BIT-MAP SECTION.
Definition: grib2_int.h:228
Information about a section 3 through 7 in a GRIB2 message.
Definition: grib2_int.h:169
int g2c_get_grid_template(int grid_template_num, int *maplen, int *map, int *needext)
Get grid template information.
int g2c_get_pds_template(int pds_template_num, int *maplen, int *map, int *needext)
Get PDS template information.
Definition: pdstemplates.c:816
void seekgb(FILE *lugb, g2int iseek, g2int mseek, g2int *lskip, g2int *lgrib)
Search a file for the next GRIB Message.
Definition: seekgb.c:46