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++)
219 if (buf[i] ==
'G' && i < bytes_read -
G2C_MAGIC_HEADER_LEN && buf[i + 1] ==
'R' && buf[i + 2] ==
'I' && buf[i + 3] ==
'B')
222 *bytes_to_msg = ftell_pos + i;
223 grib_version = buf[i + 7];
224 LOG((3,
"bytes_to_msg %ld grib_version %d", *bytes_to_msg, grib_version));
225 if (grib_version != 1 && grib_version != 2)
234 if (msg_found && buf[i] ==
'7' && i < bytes_read -
G2C_MAGIC_HEADER_LEN && buf[i + 1] ==
'7' && buf[i + 2] ==
'7' && buf[i + 3] ==
'7')
237 *bytes_in_msg = ftell_pos + i - *bytes_to_msg + 4;
238 LOG((3,
"bytes_in_msg %ld", *bytes_in_msg));
291g2c_get_msg(
int g2cid,
size_t skip_bytes,
size_t max_bytes,
size_t *bytes_to_msg,
292 size_t *bytes_in_msg,
unsigned char **cbuf)
301 LOG((2,
"g2c_get_msg g2cid %d skip_bytes %ld max_bytes %ld", g2cid, skip_bytes,
310 g2int bytes_to_msg_g, bytes_in_msg_g;
313 *bytes_to_msg = bytes_to_msg_g;
314 *bytes_in_msg = bytes_in_msg_g;
316 LOG((4,
"*bytes_to_msg %ld *bytes_in_msg %ld", *bytes_to_msg, *bytes_in_msg));
319 if (*bytes_in_msg == 0)
323 if (!(*cbuf = malloc(*bytes_in_msg)))
327 if (fseek(
g2c_file[g2cid].f, (off_t)*bytes_to_msg, SEEK_SET))
330 int my_errno = errno;
331 LOG((0,
"fseek error %s", strerror(my_errno)));
337 if ((bytes_read = fread(*cbuf, 1, *bytes_in_msg,
g2c_file[g2cid].f)) != *bytes_in_msg)
343 for (i = 0; i < 10; i++)
344 LOG((4,
"cbuf[%d] = %2x", i, (*cbuf)[i]));
422 d0 = &(sec3_info->
dim[0]);
423 d1 = &(sec3_info->
dim[1]);
431 LOG((5,
"determine_dim allocating storage for lat/lon values"));
434 if (!(d0->
value = malloc(d0->
len *
sizeof(
float))))
437 for (d = 1; d < d0->
len; d++)
442 if (!(d1->
value = malloc(d1->
len *
sizeof(
float))))
445 for (d = 1; d < d1->
len; d++)
488 if (!rw_flag && sec->
sec_num != 3)
491 LOG((6,
"g2c_rw_section3_metadata starting to %s section 3 at file position %ld",
492 rw_flag ?
"write" :
"read", ftell(f)));
514 LOG((5,
"rw_section3_metadata source_grid_def %d num_data_points %d num_opt %d interp_list %d grid_def %d",
526 if (!(sec->
template = calloc(
sizeof(
long long int) * maplen, 1)))
531 for (t = 0; t < maplen; t++)
547 LOG((6,
"finished reading or writing section 3 at file position %ld", ftell(f)));
584 if (!rw_flag && sec->
sec_num != 4)
587 LOG((3,
"read_section4_metadata rw_flag %d", rw_flag));
603 LOG((6,
"reading section 4 starting at file position %ld", ftell(f)));
610 LOG((5,
"read_section4_metadata num_coord %d prod_def %d", sec4_info->
num_coord, sec4_info->
prod_def));
615 LOG((5,
"pds template maplen %d", maplen));
621 if (!(sec->
template = calloc(
sizeof(
long long int) * maplen, 1)))
626 for (t = 0; t < maplen; t++)
673 LOG((5,
"g2c_rw_section5_metadata rw_flag %d at file position %ld", rw_flag,
691 LOG((5,
"g2c_rw_section5_metadata num_data_points %d data_def %d",
697 LOG((5,
"grid template maplen %d", maplen));
703 if (!(sec->
template = calloc(
sizeof(
long long int) * maplen, 1)))
708 for (t = 0; t < maplen; t++)
753 LOG((4,
"g2c_rw_section6_metadata rw_flag %d at file position %ld", rw_flag,
769 LOG((4,
"g2c_rw_section6_metadata indicator %d", sec6_info->
indicator));
795 size_t bytes_to_sec,
unsigned char sec_num)
800 LOG((4,
"add_section sec_id %d sec_len %d, bytes_to_sec %ld, sec_num %d",
801 sec_id, sec_len, bytes_to_sec, sec_num));
876 unsigned char sec_num = 1;
879 LOG((3,
"g2c_rw_section1_metadata rw_flag %d", rw_flag));
887 if (!rw_flag && sec_num != 1)
943 LOG((6,
"read_msg_metadata file position %ld", ftell(msg->
file->
f)));
952 if (fseek(msg->
file->
f, 9, SEEK_CUR))
961 while (total_read < msg->bytes_in_msg -
FOUR_BYTES)
963 unsigned int sec_len;
964 unsigned char sec_num;
966 LOG((4,
"reading new section at file position %ld", ftell(msg->
file->
f)));
974 if (sec_len != 926365495)
979 LOG((4,
"sec_len %d sec_num %d", sec_len, sec_num));
982 if ((ret =
add_section(msg->
file->
f, msg, sec_id++, sec_len, total_read, sec_num)))
986 total_read += sec_len;
987 LOG((4,
"total_read %d", total_read));
1023 LOG((4,
"add_msg msg_num %d bytes_to_msg %ld bytes_in_msg %ld read_file %d",
1024 msg_num, bytes_to_msg, bytes_in_msg, read_file));
1046 my_msg->
file = file;
1082 size_t file_pos = 0;
1083 size_t bytes_to_msg, bytes_in_msg;
1087 if (
g2c_file[g2cid].g2cid != g2cid)
1090 LOG((4,
"read_metadata g2cid %d", g2cid));
1093 for (msg_num = 0; !ret; msg_num++)
1096 if ((ret =
g2c_seekmsg(g2cid, file_pos, &bytes_to_msg, &bytes_in_msg)))
1098 LOG((5,
"msg_num %d bytes_to_msg %ld bytes_in_msg %ld", msg_num, bytes_to_msg,
1106 if ((ret =
add_msg(&
g2c_file[g2cid], msg_num, bytes_to_msg, bytes_in_msg,
1112 file_pos = bytes_to_msg + bytes_in_msg;
1113 LOG((6,
"file_pos %ld", file_pos));
1153 LOG((3,
"g2c_add_file path %s mode %d", path, mode));
1194 LOG((2,
"g2c_open path %s mode %d", path, mode));
1226g2c_create(
const char *path,
int cmode,
int *g2cid)
1237 LOG((2,
"g2c_create path %s cmode %d", path, cmode));
1243 if ((f = fopen(path,
"r")))
1258 if (!(
g2c_file[my_g2cid].f = fopen(path,
"bw+")))
1300 if (
g2c_file[g2cid].g2cid != g2cid)
1322 LOG((5,
"free_metadata freeing storage for lat/lon values"));
1367 if (
g2c_file[g2cid].g2cid != g2cid)
1370 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.