NCEPLIBS-g2c  1.6.4
g2_addgrid.c
Go to the documentation of this file.
1 
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include "grib2.h"
11 
65 g2int
66 g2_addgrid(unsigned char *cgrib, g2int *igds, g2int *igdstmpl, g2int *ideflist,
67  g2int idefnum)
68 {
69  g2int ierr = 0;
70  static unsigned char G = 0x47; /* 'G' */
71  static unsigned char R = 0x52; /* 'R' */
72  static unsigned char I = 0x49; /* 'I' */
73  static unsigned char B = 0x42; /* 'B' */
74  static unsigned char seven = 0x37; /* '7' */
75 
76  static g2int one = 1, three = 3, miss = 65535;
77  g2int lensec3, iofst, ibeg, lencurr, len;
78  g2int i, j, temp, ilen, isecnum, nbits;
79  gtemplate *mapgrid = 0;
80 
81  /* Check to see if beginning of GRIB message exists. */
82  if (cgrib[0] != G || cgrib[1] != R || cgrib[2] != I || cgrib[3] != B)
83  {
84  printf("g2_addgrid: GRIB not found in given message.\n");
85  printf("g2_addgrid: Call to routine gribcreate required to initialize GRIB messge.\n");
86  ierr = -1;
87  return(ierr);
88  }
89 
90  /* Get current length of GRIB message. */
91  gbit(cgrib, &lencurr, 96, 32);
92 
93  /* Check to see if GRIB message is already complete. */
94  if (cgrib[lencurr - 4] == seven && cgrib[lencurr - 3] == seven &&
95  cgrib[lencurr - 2] == seven && cgrib[lencurr - 1] == seven)
96  {
97  printf("g2_addgrid: GRIB message already complete. Cannot add new section.\n");
98  ierr = -2;
99  return(ierr);
100  }
101 
102  /* Loop through all current sections of the GRIB message to find
103  * the last section number. */
104  len = 16; /* length of Section 0 */
105  for (;;)
106  {
107  /* Get section number and length of next section. */
108  iofst = len * 8;
109  gbit(cgrib, &ilen, iofst, 32);
110  iofst = iofst + 32;
111  gbit(cgrib, &isecnum, iofst, 8);
112  len = len + ilen;
113  /* Exit loop if last section reached. */
114  if (len == lencurr) break;
115  /* If byte count for each section doesn't match current total
116  * length, then there is a problem. */
117  if (len > lencurr)
118  {
119  printf("g2_addgrid: Section byte counts don''t add to total.\n");
120  printf("g2_addgrid: Sum of section byte counts = %ld\n", len);
121  printf("g2_addgrid: Total byte count in Section 0 = %ld\n", lencurr);
122  ierr = -3;
123  return(ierr);
124  }
125  }
126 
127  /* Section 3 can only be added after sections 1, 2 and 7. */
128  if (isecnum != 1 && isecnum != 2 && isecnum != 7)
129  {
130  printf("g2_addgrid: Section 3 can only be added after Section 1, 2 or 7.\n");
131  printf("g2_addgrid: Section ',isecnum,' was the last found in given GRIB message.\n");
132  ierr = -4;
133  return(ierr);
134  }
135 
136  /* Add Section 3 - Grid Definition Section. */
137  ibeg = lencurr * 8; /* Calculate offset for beginning of section 3 */
138  iofst = ibeg + 32; /* leave space for length of section */
139  sbit(cgrib, &three, iofst, 8); /* Store section number (3) */
140  iofst = iofst + 8;
141  sbit(cgrib, igds+0, iofst, 8); /* Store source of Grid def. */
142  iofst = iofst + 8;
143  sbit(cgrib, igds+1, iofst, 32); /* Store number of data pts. */
144  iofst = iofst + 32;
145  sbit(cgrib, igds+2, iofst, 8); /* Store number of extra octets. */
146  iofst = iofst + 8;
147  sbit(cgrib, igds+3, iofst, 8); /* Store interp. of extra octets. */
148  iofst = iofst + 8;
149 
150  /* if Octet 6 is not equal to zero, Grid Definition Template may
151  * not be supplied. */
152  if (igds[0] == 0)
153  sbit(cgrib, igds+4, iofst, 16); /* Store Grid Def Template num. */
154  else
155  sbit(cgrib, &miss, iofst, 16); /* Store missing value as Grid Def Template num. */
156  iofst = iofst + 16;
157 
158  /* Get Grid Definition Template. */
159  if (igds[0] == 0)
160  {
161  if (!(mapgrid = getgridtemplate(igds[4])))
162  { /* undefined template */
163  ierr = -5;
164  return ierr;
165  }
166 
167  /* Extend the Grid Definition Template, if necessary. The
168  * number of values in a specific template may vary depending
169  * on data specified in the "static" part of the template. */
170  if (mapgrid->needext)
171  {
172  free(mapgrid);
173  mapgrid = extgridtemplate(igds[4], igdstmpl);
174  }
175  }
176 
177  /* Pack up each input value in array igdstmpl into the
178  * appropriate number of octets, which are specified in
179  * corresponding entries in array mapgrid. */
180  for (i = 0; i < mapgrid->maplen; i++)
181  {
182  nbits = abs(mapgrid->map[i]) * 8;
183  if ((mapgrid->map[i] >= 0) || (igdstmpl[i] >= 0))
184  sbit(cgrib, igdstmpl+i, iofst, nbits);
185  else
186  {
187  sbit(cgrib, &one, iofst, 1);
188  temp = abs(igdstmpl[i]);
189  sbit(cgrib, &temp, iofst+1, nbits-1);
190  }
191  iofst = iofst + nbits;
192  }
193 
194  /* Pack template extension, if appropriate. */
195  j = mapgrid->maplen;
196  if (mapgrid->needext && mapgrid->extlen > 0)
197  {
198  for (i = 0; i < mapgrid->extlen; i++)
199  {
200  nbits = abs(mapgrid->ext[i]) * 8;
201  if (mapgrid->ext[i] >= 0 || igdstmpl[j] >= 0)
202  sbit(cgrib, igdstmpl + j, iofst, nbits);
203  else
204  {
205  sbit(cgrib, &one, iofst, 1);
206  temp = abs(igdstmpl[j]);
207  sbit(cgrib, &temp, iofst + 1, nbits - 1);
208  }
209  iofst = iofst + nbits;
210  j++;
211  }
212  }
213  free(mapgrid);
214 
215  /* If requested, insert optional list of numbers defining number
216  * of points in each row or column. This is used for non regular
217  * grids. */
218  if (igds[2] != 0)
219  {
220  nbits = igds[2] * 8;
221  sbits(cgrib, ideflist, iofst, nbits, 0, idefnum);
222  iofst = iofst + (nbits * idefnum);
223  }
224 
225  /* Calculate length of section 3 and store it in octets 1-4 of section 3. */
226  lensec3 = (iofst - ibeg) / 8;
227  sbit(cgrib, &lensec3, ibeg, 32);
228 
229  /* Update current byte total of message in Section 0. */
230  lencurr += lensec3;
231  sbit(cgrib, &lencurr, 96, 32);
232 
233  return lencurr;
234 }
g2int g2_addgrid(unsigned char *cgrib, g2int *igds, g2int *igdstmpl, g2int *ideflist, g2int idefnum)
This routine packs up a Grid Definition Section (Section 3) and adds it to a GRIB2 message.
Definition: g2_addgrid.c:66
void gbit(unsigned char *in, g2int *iout, g2int iskip, g2int nbyte)
Get bits - unpack bits: Extract arbitrary size values from a packed bit string, right justifying each...
Definition: gbits.c:20
void sbit(unsigned char *out, g2int *in, g2int iskip, g2int nbyte)
Store bits - put arbitrary size values into a packed bit string, taking the low order bits from each ...
Definition: gbits.c:38
void sbits(unsigned char *out, g2int *in, g2int iskip, g2int nbyte, g2int nskip, g2int n)
Store bits - put arbitrary size values into a packed bit string, taking the low order bits from each ...
Definition: gbits.c:114
Header file for NCEPLIBS-g2c library.
g2int * ext
Number of octets of each entry in the extension part of the template.
Definition: grib2.h:52
g2int extlen
Number of entries in the template extension.
Definition: grib2.h:48
g2int * map
Number of octets of each entry in the static part of the template.
Definition: grib2.h:42
g2int needext
Indicates whether or not the template needs to be extended.
Definition: grib2.h:45
g2int maplen
Number of entries in the static part of the template.
Definition: grib2.h:38
int64_t g2int
Long integer type.
Definition: grib2.h:20
Struct for GRIB template.
Definition: grib2.h:28
gtemplate * extgridtemplate(g2int number, g2int *list)
This subroutine generates the remaining octet map for a given Grid Definition Template,...
gtemplate * getgridtemplate(g2int number)
This subroutine returns grid template information for a specified Grid Definition Template for [Secti...
Definition: gridtemplates.c:75