16#define MIN(a,b) ((a) < (b) ? (a) : (b))
19#define READ_BUF_SIZE 4092
22#define BYTES_TO_DISCIPLINE 6
27#define G2C_SEEKMSG_BUFSIZE 4092
56g2c_seekmsg(
int g2cid,
size_t skip,
size_t *offset,
size_t *msglen)
63 size_t my_msglen = 0, my_offset = 0, ipos;
69 LOG((3,
"g2c_seekgb skip %ld", skip));
81 if (fseek(
g2c_file[g2cid].f, ipos, SEEK_SET))
90 for (k = 0; k < lim; k++)
97 my_msglen =
hton64(*(
size_t *)&cbuf[k + 8]);
99 LOG((4,
"my_msglen %ld", my_msglen));
102 if (fseek(
g2c_file[g2cid].f, ipos + k + my_msglen - 4, SEEK_SET))
108 if ((k4 = fread(&end, 4, 1,
g2c_file[g2cid].f)) != 1)
115 if (k4 == 1 && end == 926365495)
118 my_offset = ipos + k;
119 LOG((4,
"found end of message my_offset %ld", my_offset));
164g2c_find_msg2(
int g2cid,
size_t skip_bytes,
size_t max_bytes,
size_t *bytes_to_msg,
165 size_t *bytes_in_msg)
180 if (!bytes_to_msg || !bytes_in_msg)
188 if (fseek(
g2c_file[g2cid].f, (off_t)skip_bytes, SEEK_SET))
192 if (!(buf = calloc(bytes_to_read,
sizeof(
char))))
195 for (num_blocks = 0; !eof && !done; num_blocks++)
199 if ((ftell_pos = ftell(
g2c_file[g2cid].f)) == -1)
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)
213 for (i = 0; i < bytes_read; i++)
220 && buf[i + 1] ==
'R' && buf[i + 2] ==
'I' && buf[i + 3] ==
'B')
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)
236 && buf[i + 1] ==
'7' && buf[i + 2] ==
'7' && buf[i + 3] ==
'7')
239 *bytes_in_msg = ftell_pos + i - *bytes_to_msg + 4;
240 LOG((3,
"bytes_in_msg %ld", *bytes_in_msg));
293g2c_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)
303 LOG((2,
"g2c_get_msg g2cid %d skip_bytes %ld max_bytes %ld", g2cid, skip_bytes,
312 g2int bytes_to_msg_g, bytes_in_msg_g;
315 *bytes_to_msg = bytes_to_msg_g;
316 *bytes_in_msg = bytes_in_msg_g;
318 LOG((4,
"*bytes_to_msg %ld *bytes_in_msg %ld", *bytes_to_msg, *bytes_in_msg));
321 if (*bytes_in_msg == 0)
325 if (!(*cbuf = malloc(*bytes_in_msg)))
329 if (fseek(
g2c_file[g2cid].f, (off_t)*bytes_to_msg, SEEK_SET))
332 int my_errno = errno;
333 LOG((0,
"fseek error %s", strerror(my_errno)));
339 if ((bytes_read = fread(*cbuf, 1, *bytes_in_msg,
g2c_file[g2cid].f)) != *bytes_in_msg)
345 for (i = 0; i < 10; i++)
346 LOG((4,
"cbuf[%d] = %2x", i, (*cbuf)[i]));
425 d0 = &(sec3_info->
dim[0]);
426 d1 = &(sec3_info->
dim[1]);
434 LOG((5,
"determine_dim allocating storage for lat/lon values"));
437 if (!(d0->
value = malloc(d0->
len *
sizeof(
float))))
440 for (d = 1; d < d0->
len; d++)
445 if (!(d1->
value = malloc(d1->
len *
sizeof(
float))))
448 for (d = 1; d < d1->
len; d++)
491 if (!rw_flag && sec->
sec_num != 3)
494 LOG((6,
"g2c_rw_section3_metadata starting to %s section 3 at file position %ld",
495 rw_flag ?
"write" :
"read", ftell(f)));
517 LOG((5,
"rw_section3_metadata source_grid_def %d num_data_points %d num_opt %d interp_list %d grid_def %d",
529 if (!(sec->
template = calloc(
sizeof(
long long int) * maplen, 1)))
534 for (t = 0; t < maplen; t++)
550 LOG((6,
"finished reading or writing section 3 at file position %ld", ftell(f)));
587 if (!rw_flag && sec->
sec_num != 4)
590 LOG((3,
"read_section4_metadata rw_flag %d", rw_flag));
606 LOG((6,
"reading section 4 starting at file position %ld", ftell(f)));
613 LOG((5,
"read_section4_metadata num_coord %d prod_def %d", sec4_info->
num_coord, sec4_info->
prod_def));
618 LOG((5,
"pds template maplen %d", maplen));
624 if (!(sec->
template = calloc(
sizeof(
long long int) * maplen, 1)))
629 for (t = 0; t < maplen; t++)
676 LOG((5,
"g2c_rw_section5_metadata rw_flag %d at file position %ld", rw_flag,
694 LOG((5,
"g2c_rw_section5_metadata num_data_points %d data_def %d",
700 LOG((5,
"grid template maplen %d", maplen));
706 if (!(sec->
template = calloc(
sizeof(
long long int) * maplen, 1)))
711 for (t = 0; t < maplen; t++)
756 LOG((6,
"g2c_rw_section6_metadata rw_flag %d at file position %ld", rw_flag,
772 LOG((5,
"g2c_rw_section6_metadata indicator %d", sec6_info->
indicator));
798 size_t bytes_to_sec,
unsigned char sec_num)
803 LOG((4,
"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));
879 unsigned char sec_num = 1;
882 LOG((3,
"g2c_rw_section1_metadata rw_flag %d", rw_flag));
890 if (!rw_flag && sec_num != 1)
946 LOG((6,
"read_msg_metadata file position %ld", ftell(msg->
file->
f)));
955 if (fseek(msg->
file->
f, 9, SEEK_CUR))
964 while (total_read < msg->bytes_in_msg -
FOUR_BYTES)
966 unsigned int sec_len;
967 unsigned char sec_num;
969 LOG((4,
"reading new section at file position %ld", ftell(msg->
file->
f)));
977 if (sec_len != 926365495)
982 LOG((4,
"sec_len %d sec_num %d", sec_len, sec_num));
985 if ((ret =
add_section(msg->
file->
f, msg, sec_id++, sec_len, total_read, sec_num)))
989 total_read += sec_len;
990 LOG((4,
"total_read %d", total_read));
1026 LOG((4,
"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));
1049 my_msg->
file = file;
1085 size_t file_pos = 0;
1086 size_t bytes_to_msg, bytes_in_msg;
1090 if (
g2c_file[g2cid].g2cid != g2cid)
1093 LOG((4,
"read_metadata g2cid %d", g2cid));
1096 for (msg_num = 0; !ret; msg_num++)
1099 if ((ret =
g2c_seekmsg(g2cid, file_pos, &bytes_to_msg, &bytes_in_msg)))
1101 LOG((5,
"msg_num %d bytes_to_msg %ld bytes_in_msg %ld", msg_num, bytes_to_msg,
1109 if ((ret =
add_msg(&
g2c_file[g2cid], msg_num, bytes_to_msg, bytes_in_msg,
1115 file_pos = bytes_to_msg + bytes_in_msg;
1116 LOG((6,
"file_pos %ld", file_pos));
1156 LOG((3,
"g2c_add_file path %s mode %d", path, mode));
1197 LOG((2,
"g2c_open path %s mode %d", path, mode));
1229g2c_create(
const char *path,
int cmode,
int *g2cid)
1240 LOG((2,
"g2c_create path %s cmode %d", path, cmode));
1246 if ((f = fopen(path,
"r")))
1261 if (!(
g2c_file[my_g2cid].f = fopen(path,
"bw+")))
1303 if (
g2c_file[g2cid].g2cid != g2cid)
1325 LOG((5,
"free_metadata freeing storage for lat/lon values"));
1370 if (
g2c_file[g2cid].g2cid != g2cid)
1373 LOG((2,
"g2c_close %d", g2cid));
int g2c_get_drs_template(int drs_template_num, int *maplen, int *map, int *needext)
Get DRS template information.
int g2c_open(const char *path, int mode, int *g2cid)
Open an existing GRIB2 file.
#define MIN(a, b)
Find a minimum.
#define READ_BUF_SIZE
Default size of read-buffer.
static int determine_dims(G2C_SECTION_INFO_T *sec)
Determine the dimension information from the section 3 metadata.
static int read_msg_metadata(G2C_MESSAGE_INFO_T *msg)
Read the file to get metadata about a message.
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.
int g2c_close(int g2cid)
Close a GRIB2 file, freeing resources.
G2C_FILE_INFO_T g2c_file[G2C_MAX_FILES+1]
Global file information.
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.
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...
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.
#define BYTES_TO_DISCIPLINE
Number of bytes to discipline field in GRIB2 message.
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.
static int free_metadata(int g2cid)
Free resources holding the file metadata.
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.
static int read_metadata(int g2cid)
Read metadata from a GRIB2 file being opened with g2c_open().
int g2c_rw_section1_metadata(FILE *f, int rw_flag, G2C_MESSAGE_INFO_T *msg)
Read Section 1.
int g2c_add_file(const char *path, int mode, int *g2cid)
Open a GRIB2 file and add it to the list of open files.
static int find_available_g2cid(int *g2cid)
Find a g2cid to use for a newly opened or created file.
int g2c_seekmsg(int g2cid, size_t skip, size_t *offset, size_t *msglen)
Search a file for the next GRIB2 Message.
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.
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.
#define G2C_SEEKMSG_BUFSIZE
Size of buffer used in g2c_seekmsg().
int g2c_next_g2cid
Next g2cid file ID - used when opening or creating a file.
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...
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...
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...
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...
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 ...
int g2c_log_file(int g2cid)
Print a summary of the contents of an open GRIB2 file.
#define G2C_EMSG
Error decoding GRIB message.
#define G2C_MAX_FILES
Maximum number of open files.
#define G2C_NOCLOBBER
Don't destroy existing file.
#define G2C_ENOMSG
No GRIB message found.
#define G2C_ENAMETOOLONG
Name too long.
#define G2C_WRITE
Set read-write access for g2c_open().
#define G2C_ENOSECTION
Cannot find section.
#define G2C_EFILE
File I/O error.
#define G2C_MAX_GDS_TEMPLATE_MAPLEN
Maximum grid template map length.
#define G2C_ENOMEM
Out of memory.
#define G2C_ERROR
General error code, returned for some test errors.
#define G2C_MAX_NAME
Maximum length of a name.
#define G2C_EINVAL
Invalid input.
#define G2C_ETOOMANYFILES
Trying to open too many files.
#define G2C_EBADSECTION
Invalid section number.
#define G2C_MAX_PDS_TEMPLATE_MAPLEN
Maximum template map length.
#define G2C_SECTION0_BYTES
Number of bytes in section 0.
int64_t g2int
Long integer type.
#define G2C_EBADID
Bad ID.
#define G2C_NOERROR
No error.
#define G2C_SECTION1_BYTES
Number of bytes in section 1 (not including reserved, optional data at the end of the section).
Header file with internal function prototypes NCEPLIBS-g2c library.
#define G2C_FILE_READ
Read.
struct g2c_section_info * next
Pointer to next in list.
struct g2c_section_info * sec
List of section metadata.
size_t len
Length of dimension.
short subcenter
Originating subcenter.
int sec_id
ID of the section (0-based).
#define G2C_MAGIC_HEADER_LEN
Full length of magic header string (includes GRIB version byte).
G2C_DIM_INFO_T dim[2]
Dimension information.
unsigned char master_version
GRIB master tables version number.
#define FOUR_BYTES
Four bytes.
#define MUTEX_UNLOCK(m)
Pthreads not enabled, so do nothing.
char path[G2C_MAX_NAME+1]
Path of the file.
unsigned char type
Type of processed data in this GRIB message.
unsigned short grid_def
Grid definition template number (= N) (See Table 3.1).
#define G2C_MAGIC_HEADER
GRIB magic header string.
unsigned char minute
Minute.
unsigned int num_data_points
Number of data points.
size_t num_messages
Number of messages in the file.
unsigned short num_coord
Number of coordinate values after template.
int num_local
Number of local sections in the message.
unsigned char sig_ref_time
Significance of reference time.
#define LATITUDE
Latitude.
unsigned char num_opt
Number of octets for optional list of numbers defining number of points.
unsigned char discipline
Discipline from section 0.
char name[G2C_MAX_NAME+1]
Name of dimension.
unsigned char interp_list
Interpetation of list of numbers defining number of points (See Table 3.11).
size_t bytes_in_msg
Number of bytes in this message.
struct g2c_section_info * prev
Pointer to previous in list.
#define MUTEX(m)
Pthreads not enabled, so do nothing.
int num_fields
Number of fields in the message.
unsigned char sec_num
Section number.
#define G2C_MIN_MAX_BYTES
Minimum acceptable value for max_bytes parameter of g2c_get_msg().
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,...
void * sec_info
Pointer to struct specific for section 3, 4, 5, 6, or 7.
float * value
Array of dimension values.
unsigned char indicator
Bit map indicator.
unsigned int sec_len
Length of the section (in bytes).
size_t bytes_to_sec
Number of bytes from start of message to this section.
unsigned char status
Production Status of Processed data in the GRIB message.
#define LONGITUDE
Longitude.
G2C_MESSAGE_INFO_T * msg
Information about each message in the file.
#define ONE_BYTE
One byte.
#define LOG(e)
Ignore logging to stdout.
unsigned char second
Second.
FILE * f
FILE pointer to open file.
unsigned char source_grid_def
Source of grid definition (See Table 3.0).
int template_len
Number of entries in template.
unsigned char local_version
Version number of GRIB local tables used to augment Master Tables.
#define hton64(y)
Byte swap 64-bit ints.
unsigned char month
Month.
size_t msg_num
Number of message in file (0-based).
unsigned short data_def
Data representation template number (See Table 5.0).
size_t bytes_to_msg
Number of bytes to skip in the file, to get to this message.
#define MUTEX_LOCK(m)
Pthreads not enabled, so do nothing.
long long int * template
Grid, product, or data template.
int sec1_len
Length of section 1.
struct g2c_message_info * next
Pointer to next in list.
G2C_MESSAGE_INFO_T * msg
Pointer to contianing message.
short center
Originating center.
struct g2c_file_info * file
Pointer to containing file.
unsigned short prod_def
Product definition template number (See Table 4.0).
Keep information about dimensions defined in section 3.
This is the information about each open file.
This is the information about each message.
Information about Section 3 GRID DEFINITION SECTION.
Information about Section 4 PRODUCT DEFINITION SECTION.
Information about Section 5 DATA REPRESENTATION SECTION.
Information about Section 6 BIT-MAP SECTION.
Information about a section 3 through 7 in a GRIB2 message.
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.
void seekgb(FILE *lugb, g2int iseek, g2int mseek, g2int *lskip, g2int *lgrib)
Search a file for the next GRIB Message.