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(*(uint64_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));
1205 LOG((2,
"g2c_open path %s mode %d", path, mode));
1237g2c_create(
const char *path,
int cmode,
int *g2cid)
1248 LOG((2,
"g2c_create path %s cmode %d", path, cmode));
1254 if ((f = fopen(path,
"r")))
1269 if (!(
g2c_file[my_g2cid].f = fopen(path,
"bw+")))
1280 g2c_file[my_g2cid].g2cid = my_g2cid;
1311 if (
g2c_file[g2cid].g2cid != g2cid)
1333 LOG((5,
"free_metadata freeing storage for lat/lon values"));
1378 if (
g2c_file[g2cid].g2cid != g2cid)
1381 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.
G2C_FILE_INFO_T g2c_file[G2C_MAX_FILES+1]
Global file 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.
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_section3_info G2C_SECTION3_INFO_T
Information about Section 3 GRID DEFINITION SECTION.
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.
struct g2c_file_info G2C_FILE_INFO_T
This is the information about each open file.
#define FOUR_BYTES
Four bytes.
#define MUTEX_UNLOCK(m)
Pthreads not enabled, so do nothing.
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.
struct g2c_dim_info G2C_DIM_INFO_T
Keep information about dimensions defined in section 3.
int num_local
Number of local sections in the message.
unsigned char sig_ref_time
Significance of reference time.
#define LATITUDE
Latitude.
struct g2c_section_info G2C_SECTION_INFO_T
Information about a section 3 through 7 in a GRIB2 message.
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).
struct g2c_section5_info G2C_SECTION5_INFO_T
Information about Section 5 DATA REPRESENTATION SECTION.
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.
struct g2c_section4_info G2C_SECTION4_INFO_T
Information about Section 4 PRODUCT DEFINITION SECTION.
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.
struct g2c_message_info G2C_MESSAGE_INFO_T
This is the information about each message.
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.
#define hton64(x)
Byte swap 64-bit ints.
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.
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.
struct g2c_section6_info G2C_SECTION6_INFO_T
Information about Section 6 BIT-MAP SECTION.
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).
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.