stream_grb.c 23 KB
Newer Older
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1
#if defined (HAVE_CONFIG_H)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
2
3
4
5
6
7
8
9
#  include "config.h"
#endif

#include <stdio.h>
#include <string.h>

#include "dmemory.h"
#include "cdi.h"
10
#include "cdi_int.h"
Uwe Schulzweida's avatar
Uwe Schulzweida committed
11
12
13
14
#include "stream_cgribex.h"
#include "stream_gribapi.h"
#include "file.h"
#include "cgribex.h"  /* gribZip gribGetZip gribGinfo */
15
#include "gribapi.h"
Thomas Jahns's avatar
Thomas Jahns committed
16
#include "namespace.h"
Deike Kleberg's avatar
Deike Kleberg committed
17

18
19
20
21
22
23
24

int grib1ltypeToZaxisType(int grib_ltype)
{
  int zaxistype = ZAXIS_GENERIC;

  switch ( grib_ltype )
    {
25
26
27
28
29
30
31
32
    case GRIB1_LTYPE_SURFACE:            { zaxistype = ZAXIS_SURFACE;                break; }
    case GRIB1_LTYPE_CLOUD_BASE:         { zaxistype = ZAXIS_CLOUD_BASE;             break; }
    case GRIB1_LTYPE_CLOUD_TOP:          { zaxistype = ZAXIS_CLOUD_TOP;              break; }
    case GRIB1_LTYPE_ISOTHERM0:          { zaxistype = ZAXIS_ISOTHERM_ZERO;          break; }
    case GRIB1_LTYPE_TOA:                { zaxistype = ZAXIS_TOA;                    break; }
    case GRIB1_LTYPE_SEA_BOTTOM:         { zaxistype = ZAXIS_SEA_BOTTOM;             break; }
    case GRIB1_LTYPE_ATMOSPHERE:         { zaxistype = ZAXIS_ATMOSPHERE;             break; }
    case GRIB1_LTYPE_MEANSEA:            { zaxistype = ZAXIS_MEANSEA;                break; }
33
    case GRIB1_LTYPE_99:
34
35
36
    case GRIB1_LTYPE_ISOBARIC:           { zaxistype = ZAXIS_PRESSURE;               break; }
    case GRIB1_LTYPE_HEIGHT:             { zaxistype = ZAXIS_HEIGHT;                 break; }
    case GRIB1_LTYPE_ALTITUDE:           { zaxistype = ZAXIS_ALTITUDE;	             break; }
Deike Kleberg's avatar
Deike Kleberg committed
37
    case GRIB1_LTYPE_SIGMA:
38
    case GRIB1_LTYPE_SIGMA_LAYER:        { zaxistype = ZAXIS_SIGMA;	             break; }
39
    case GRIB1_LTYPE_HYBRID:
40
    case GRIB1_LTYPE_HYBRID_LAYER:       { zaxistype = ZAXIS_HYBRID;	             break; }
41
    case GRIB1_LTYPE_LANDDEPTH:
42
43
44
45
46
47
48
49
    case GRIB1_LTYPE_LANDDEPTH_LAYER:    { zaxistype = ZAXIS_DEPTH_BELOW_LAND;       break; }
    case GRIB1_LTYPE_ISENTROPIC:         { zaxistype = ZAXIS_ISENTROPIC;             break; }
    case GRIB1_LTYPE_SEADEPTH:           { zaxistype = ZAXIS_DEPTH_BELOW_SEA;        break; }
    case GRIB1_LTYPE_LAKE_BOTTOM:        { zaxistype = ZAXIS_LAKE_BOTTOM;            break; }
    case GRIB1_LTYPE_SEDIMENT_BOTTOM:    { zaxistype = ZAXIS_SEDIMENT_BOTTOM;        break; }
    case GRIB1_LTYPE_SEDIMENT_BOTTOM_TA: { zaxistype = ZAXIS_SEDIMENT_BOTTOM_TA;     break; }
    case GRIB1_LTYPE_SEDIMENT_BOTTOM_TW: { zaxistype = ZAXIS_SEDIMENT_BOTTOM_TW;     break; }
    case GRIB1_LTYPE_MIX_LAYER:          { zaxistype = ZAXIS_MIX_LAYER;              break; }
50
51
52
53
54
55
56
57
58
59
60
61
    }

  return (zaxistype);
}


int grib2ltypeToZaxisType(int grib_ltype)
{
  int zaxistype = ZAXIS_GENERIC;

  switch ( grib_ltype )
    {
62
63
64
65
66
67
68
69
70
71
72
73
    case GRIB2_LTYPE_SURFACE:            { zaxistype = ZAXIS_SURFACE;                break; }
    case GRIB2_LTYPE_CLOUD_BASE:         { zaxistype = ZAXIS_CLOUD_BASE;             break; }
    case GRIB2_LTYPE_CLOUD_TOP:          { zaxistype = ZAXIS_CLOUD_TOP;              break; }
    case GRIB2_LTYPE_ISOTHERM0:          { zaxistype = ZAXIS_ISOTHERM_ZERO;          break; }
    case GRIB2_LTYPE_TOA:                { zaxistype = ZAXIS_TOA;                    break; }
    case GRIB2_LTYPE_SEA_BOTTOM:         { zaxistype = ZAXIS_SEA_BOTTOM;             break; }
    case GRIB2_LTYPE_ATMOSPHERE:         { zaxistype = ZAXIS_ATMOSPHERE;             break; }
    case GRIB2_LTYPE_MEANSEA:            { zaxistype = ZAXIS_MEANSEA;                break; }
    case GRIB2_LTYPE_ISOBARIC:           { zaxistype = ZAXIS_PRESSURE;               break; }
    case GRIB2_LTYPE_HEIGHT:             { zaxistype = ZAXIS_HEIGHT;                 break; }
    case GRIB2_LTYPE_ALTITUDE:           { zaxistype = ZAXIS_ALTITUDE;               break; }
    case GRIB2_LTYPE_SIGMA:              { zaxistype = ZAXIS_SIGMA;                  break; }
74
    case GRIB2_LTYPE_HYBRID:
75
 /* case GRIB2_LTYPE_HYBRID_LAYER: */    { zaxistype = ZAXIS_HYBRID;                 break; }
76
    case GRIB2_LTYPE_LANDDEPTH:
77
78
79
80
81
82
83
84
85
 /* case GRIB2_LTYPE_LANDDEPTH_LAYER: */ { zaxistype = ZAXIS_DEPTH_BELOW_LAND;       break; }
    case GRIB2_LTYPE_ISENTROPIC:         { zaxistype = ZAXIS_ISENTROPIC;             break; }
    case GRIB2_LTYPE_SNOW:               { zaxistype = ZAXIS_SNOW;                   break; }
    case GRIB2_LTYPE_SEADEPTH:           { zaxistype = ZAXIS_DEPTH_BELOW_SEA;        break; }
    case GRIB2_LTYPE_LAKE_BOTTOM:        { zaxistype = ZAXIS_LAKE_BOTTOM;            break; }
    case GRIB2_LTYPE_SEDIMENT_BOTTOM:    { zaxistype = ZAXIS_SEDIMENT_BOTTOM;        break; }
    case GRIB2_LTYPE_SEDIMENT_BOTTOM_TA: { zaxistype = ZAXIS_SEDIMENT_BOTTOM_TA;     break; }
    case GRIB2_LTYPE_SEDIMENT_BOTTOM_TW: { zaxistype = ZAXIS_SEDIMENT_BOTTOM_TW;     break; }
    case GRIB2_LTYPE_MIX_LAYER:          { zaxistype = ZAXIS_MIX_LAYER;              break; }
86
    case GRIB2_LTYPE_REFERENCE:          { zaxistype = ZAXIS_REFERENCE;              break; }
87
88
89
90
    }

  return (zaxistype);
}
Uwe Schulzweida's avatar
Uwe Schulzweida committed
91

Uwe Schulzweida's avatar
Uwe Schulzweida committed
92

Uwe Schulzweida's avatar
Uwe Schulzweida committed
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
int zaxisTypeToGrib1ltype(int zaxistype)
{
  int grib_ltype = -1;

  switch (zaxistype)
    {
    case ZAXIS_SURFACE:               { grib_ltype = GRIB1_LTYPE_SURFACE;            break; }
    case ZAXIS_MEANSEA:               { grib_ltype = GRIB1_LTYPE_MEANSEA;            break; }
    case ZAXIS_HEIGHT:                { grib_ltype = GRIB1_LTYPE_HEIGHT;             break; }
    case ZAXIS_ALTITUDE:              { grib_ltype = GRIB1_LTYPE_ALTITUDE;           break; }
    case ZAXIS_SIGMA:                 { grib_ltype = GRIB1_LTYPE_SIGMA;              break; }
    case ZAXIS_DEPTH_BELOW_SEA:       { grib_ltype = GRIB1_LTYPE_SEADEPTH;           break; }
    case ZAXIS_ISENTROPIC:            { grib_ltype = GRIB1_LTYPE_ISENTROPIC;         break; }
    case ZAXIS_CLOUD_BASE:            { grib_ltype = GRIB1_LTYPE_CLOUD_BASE;         break; }
    case ZAXIS_CLOUD_TOP:             { grib_ltype = GRIB1_LTYPE_CLOUD_TOP;          break; }
    case ZAXIS_ISOTHERM_ZERO:         { grib_ltype = GRIB1_LTYPE_ISOTHERM0;          break; }
    case ZAXIS_TOA:                   { grib_ltype = GRIB1_LTYPE_TOA;                break; }
    case ZAXIS_SEA_BOTTOM:            { grib_ltype = GRIB1_LTYPE_SEA_BOTTOM;         break; }
    case ZAXIS_LAKE_BOTTOM:           { grib_ltype = GRIB1_LTYPE_LAKE_BOTTOM;        break; }
    case ZAXIS_SEDIMENT_BOTTOM:       { grib_ltype = GRIB1_LTYPE_SEDIMENT_BOTTOM;    break; }
    case ZAXIS_SEDIMENT_BOTTOM_TA:    { grib_ltype = GRIB1_LTYPE_SEDIMENT_BOTTOM_TA; break; }
    case ZAXIS_SEDIMENT_BOTTOM_TW:    { grib_ltype = GRIB1_LTYPE_SEDIMENT_BOTTOM_TW; break; }
    case ZAXIS_MIX_LAYER:             { grib_ltype = GRIB1_LTYPE_MIX_LAYER;          break; }
    case ZAXIS_ATMOSPHERE:            { grib_ltype = GRIB1_LTYPE_ATMOSPHERE;         break; }
    }

  return (grib_ltype);
}


int zaxisTypeToGrib2ltype(int zaxistype)
{
  int grib_ltype = -1;

  switch (zaxistype)
    {
    case ZAXIS_SURFACE:               { grib_ltype = GRIB2_LTYPE_SURFACE;            break; }
    case ZAXIS_MEANSEA:               { grib_ltype = GRIB2_LTYPE_MEANSEA;            break; }
    case ZAXIS_HEIGHT:                { grib_ltype = GRIB2_LTYPE_HEIGHT;             break; }
    case ZAXIS_ALTITUDE:              { grib_ltype = GRIB2_LTYPE_ALTITUDE;           break; }
    case ZAXIS_SIGMA:                 { grib_ltype = GRIB2_LTYPE_SIGMA;              break; }
    case ZAXIS_DEPTH_BELOW_SEA:       { grib_ltype = GRIB2_LTYPE_SEADEPTH;           break; }
    case ZAXIS_ISENTROPIC:            { grib_ltype = GRIB2_LTYPE_ISENTROPIC;         break; }
    case ZAXIS_CLOUD_BASE:            { grib_ltype = GRIB2_LTYPE_CLOUD_BASE;         break; }
    case ZAXIS_CLOUD_TOP:             { grib_ltype = GRIB2_LTYPE_CLOUD_TOP;          break; }
    case ZAXIS_ISOTHERM_ZERO:         { grib_ltype = GRIB2_LTYPE_ISOTHERM0;          break; }
    case ZAXIS_TOA:                   { grib_ltype = GRIB2_LTYPE_TOA;                break; }
    case ZAXIS_SEA_BOTTOM:            { grib_ltype = GRIB2_LTYPE_SEA_BOTTOM;         break; }
    case ZAXIS_LAKE_BOTTOM:           { grib_ltype = GRIB2_LTYPE_LAKE_BOTTOM;        break; }
    case ZAXIS_SEDIMENT_BOTTOM:       { grib_ltype = GRIB2_LTYPE_SEDIMENT_BOTTOM;    break; }
    case ZAXIS_SEDIMENT_BOTTOM_TA:    { grib_ltype = GRIB2_LTYPE_SEDIMENT_BOTTOM_TA; break; }
    case ZAXIS_SEDIMENT_BOTTOM_TW:    { grib_ltype = GRIB2_LTYPE_SEDIMENT_BOTTOM_TW; break; }
    case ZAXIS_MIX_LAYER:             { grib_ltype = GRIB2_LTYPE_MIX_LAYER;          break; }
    case ZAXIS_ATMOSPHERE:            { grib_ltype = GRIB2_LTYPE_ATMOSPHERE;         break; }
    }

  return (grib_ltype);
}


Uwe Schulzweida's avatar
Uwe Schulzweida committed
153
154
155
156
int grbBitsPerValue(int datatype)
{
  int bitsPerValue = 16;

Uwe Schulzweida's avatar
Uwe Schulzweida committed
157
  if ( datatype == DATATYPE_CPX32 || datatype == DATATYPE_CPX64 )
158
    Error("CDI/GRIB library does not support complex numbers!");
Uwe Schulzweida's avatar
Uwe Schulzweida committed
159

Uwe Schulzweida's avatar
Uwe Schulzweida committed
160
161
162
163
164
165
166
167
168
169
170
171
172
173
  if ( datatype != CDI_UNDEFID )
    {
      if ( datatype > 0 && datatype <= 32 )
	bitsPerValue = datatype;
      else if ( datatype == DATATYPE_FLT64 )
	bitsPerValue = 24;
      else
	bitsPerValue = 16;
    }

  return (bitsPerValue);
}


Uwe Schulzweida's avatar
Uwe Schulzweida committed
174
/*
175
int grbInqRecord(stream_t * streamptr, int *varID, int *levelID)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
176
177
178
{
  int status;

179
  status = cgribexInqRecord(streamptr, varID, levelID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
180
181
182

  return (status);
}
Uwe Schulzweida's avatar
Uwe Schulzweida committed
183
*/
Uwe Schulzweida's avatar
Uwe Schulzweida committed
184

185
int grbDefRecord(stream_t * streamptr)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
186
187
188
189
190
191
192
193
{
  int status = 0;

  return (status);
}

static
int grbDecode(int filetype, unsigned char *gribbuffer, int gribsize, double *data, int gridsize,
194
	      int unreduced, int *nmiss, int *zip, double missval, int vlistID, int varID)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
195
196
197
{
  int status = 0;

198
#if  defined  (HAVE_LIBCGRIBEX)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
199
  if ( filetype == FILETYPE_GRB )
200
201
202
203
204
205
206
207
    {
#if  defined  (HAVE_LIBGRIB_API)
      extern int cdiNAdditionalGRIBKeys;
      if ( cdiNAdditionalGRIBKeys > 0 )
	Error("CGRIBEX decode does not support reading of additional GRIB keys!");
#endif
      status = cgribexDecode(gribbuffer, gribsize, data, gridsize, unreduced, nmiss, zip, missval);
    }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
208
  else
209
#endif
210
211
212
    {
      status = gribapiDecode(gribbuffer, gribsize, data, gridsize, unreduced, nmiss, zip, missval, vlistID, varID);
    }
213

Uwe Schulzweida's avatar
Uwe Schulzweida committed
214
215
216
217
  return (status);
}


218
int grbReadRecord(stream_t * streamptr, double *data, int *nmiss)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
219
220
221
222
223
224
225
226
227
228
229
{
  int status = 0;
  unsigned char *gribbuffer;
  int fileID;
  int recID, vrecID, tsID, gridID, varID;
  long recsize;
  off_t recpos;
  int gridsize;
  int vlistID;
  int zip;
  int filetype;
230
  double missval;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
231
232
233
234
235

  filetype = streamptr->filetype;

  gribbuffer = (unsigned char *) streamptr->record->buffer;

236
237
  vlistID = streamptr->vlistID;
  fileID  = streamptr->fileID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
  tsID    = streamptr->curTsID;
  vrecID  = streamptr->tsteps[tsID].curRecID;
  recID   = streamptr->tsteps[tsID].recIDs[vrecID];
  recpos  = streamptr->tsteps[tsID].records[recID].position;
  recsize = streamptr->tsteps[tsID].records[recID].size;
  varID   = streamptr->tsteps[tsID].records[recID].varID;

  gridID   = vlistInqVarGrid(vlistID, varID);
  gridsize = gridInqSize(gridID);

  streamptr->numvals += gridsize;

  fileSetPos(fileID, recpos, SEEK_SET);

  fileRead(fileID, gribbuffer, (size_t) recsize);

254
  missval = vlistInqVarMissval(vlistID, varID);
255

256
  grbDecode(filetype, gribbuffer, recsize, data, gridsize, streamptr->unreduced, nmiss, &zip, missval, vlistID, varID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
257
258
259
260
261
262
263

  streamptr->tsteps[tsID].records[recID].zip = zip;

  return (status);
}

static
264
int grbScanTimestep1(stream_t * streamptr)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
265
{
266
  int status;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
267
268
269
270
  int filetype;

  filetype  = streamptr->filetype;

271
#if  defined  (HAVE_LIBCGRIBEX)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
272
273
  if ( filetype == FILETYPE_GRB )
    {
274
      status = cgribexScanTimestep1(streamptr);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
275
276
    }
  else
277
#endif
Uwe Schulzweida's avatar
Uwe Schulzweida committed
278
    {
279
      status = gribapiScanTimestep1(streamptr);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
280
    }
281
282

  return (status);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
283
284
285
}

static
286
int grbScanTimestep2(stream_t * streamptr)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
287
288
289
290
291
292
{
  int status;
  int filetype;

  filetype  = streamptr->filetype;

293
#if  defined  (HAVE_LIBCGRIBEX)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
294
295
  if ( filetype == FILETYPE_GRB )
    {
296
      status = cgribexScanTimestep2(streamptr);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
297
298
    }
  else
299
#endif
Uwe Schulzweida's avatar
Uwe Schulzweida committed
300
    {
301
      status = gribapiScanTimestep2(streamptr);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
302
303
304
305
306
307
    }

  return (status);
}

static
308
int grbScanTimestep(stream_t * streamptr)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
309
310
311
312
313
314
{
  int status;
  int filetype;

  filetype  = streamptr->filetype;

315
#if  defined  (HAVE_LIBCGRIBEX)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
316
317
  if ( filetype == FILETYPE_GRB )
    {
318
      status = cgribexScanTimestep(streamptr);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
319
320
    }
  else
321
#endif
Uwe Schulzweida's avatar
Uwe Schulzweida committed
322
    {
323
      status = gribapiScanTimestep(streamptr);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
324
325
326
327
328
329
    }

  return (status);
}


330
int grbInqContents(stream_t * streamptr)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
331
332
333
334
{
  int fileID;
  int status = 0;

335
  fileID = streamptr->fileID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
336
337
338

  streamptr->curTsID = 0;

339
340
341
  status = grbScanTimestep1(streamptr);

  if ( status == 0 && streamptr->ntsteps == -1 ) status = grbScanTimestep2(streamptr);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
342
343
344
345
346
347
348

  fileSetPos(fileID, 0, SEEK_SET);

  return (status);
}


349
int grbInqTimestep(stream_t * streamptr, int tsID)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
350
351
352
353
{
  int ntsteps, nrecs;

  if ( tsID == 0 && streamptr->rtsteps == 0 )
354
    Error("Call to cdiInqContents missing!");
Uwe Schulzweida's avatar
Uwe Schulzweida committed
355
356

  if ( CDI_Debug )
357
    Message("tsid = %d rtsteps = %d", tsID, streamptr->rtsteps);
358

Uwe Schulzweida's avatar
Uwe Schulzweida committed
359
360
361
  ntsteps = CDI_UNDEFID;
  while ( (tsID + 1) > streamptr->rtsteps && ntsteps == CDI_UNDEFID )
    {
362
      ntsteps = grbScanTimestep(streamptr);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
      if ( ntsteps == CDI_EUFSTRUCT )
	{
	  streamptr->ntsteps = streamptr->rtsteps;
	  break;
	}
    }

  if ( tsID >= streamptr->ntsteps && streamptr->ntsteps != CDI_UNDEFID )
    {
      nrecs = 0;
    }
  else
    {
      streamptr->curTsID = tsID;
      nrecs = streamptr->tsteps[tsID].nrecs;
    }

  return (nrecs);
}


384
void grbReadVarDP(stream_t * streamptr, int varID, double *data, int *nmiss)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
385
386
387
388
389
390
391
392
393
394
395
{
  int fileID;
  int levelID, nlevs, gridID, gridsize;
  unsigned char *gribbuffer;
  int tsID, recID;
  long recsize;
  off_t recpos, currentfilepos;
  int imiss;
  int vlistID;
  int zip;
  int filetype;
396
  double missval;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
397
398
399
400
401

  filetype = streamptr->filetype;

  gribbuffer = (unsigned char *) streamptr->record->buffer;

402
403
  vlistID  = streamptr->vlistID;
  fileID   = streamptr->fileID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
404
405
406
407
408
409
410
  tsID     = streamptr->curTsID;

  nlevs    = streamptr->vars[varID].nlevs;
  gridID   = vlistInqVarGrid(vlistID, varID);
  gridsize = gridInqSize(gridID);

  if ( CDI_Debug )
411
    Message("nlevs = %d gridID = %d gridsize = %d", nlevs, gridID, gridsize);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
412
413
414
415
416
417
418
419
420
421
422
423
424
425

  currentfilepos = fileGetPos(fileID);

  *nmiss = 0;
  for ( levelID = 0; levelID < nlevs; levelID++ )
    {
      recID   = streamptr->vars[varID].level[levelID];
      recpos  = streamptr->tsteps[tsID].records[recID].position;
      recsize = streamptr->tsteps[tsID].records[recID].size;

      fileSetPos(fileID, recpos, SEEK_SET);

      fileRead(fileID, gribbuffer, recsize);

426
      missval = vlistInqVarMissval(vlistID, varID);
427

428
      grbDecode(filetype, gribbuffer, recsize, &data[levelID*gridsize], gridsize,
429
		streamptr->unreduced, &imiss, &zip, missval, vlistID, varID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
430
431
432
433
434
435
436
437
438
439

      *nmiss += imiss;

      streamptr->tsteps[tsID].records[recID].zip = zip;
    }

  fileSetPos(fileID, currentfilepos, SEEK_SET);
}


440
void grbReadVarSliceDP(stream_t * streamptr, int varID, int levelID, double *data, int *nmiss)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
441
442
443
444
445
446
447
448
449
450
{
  int fileID;
  int gridID, gridsize;
  unsigned char *gribbuffer;
  long recsize;
  off_t recpos, currentfilepos;
  int tsID, recID;
  int vlistID;
  int zip;
  int filetype;
451
  double missval;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
452
453
454
455
456

  filetype = streamptr->filetype;

  gribbuffer = (unsigned char *) streamptr->record->buffer;

457
  vlistID  = streamptr->vlistID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
458
459
460
461
462
  gridID   = vlistInqVarGrid(vlistID, varID);
  gridsize = gridInqSize(gridID);
  tsID     = streamptr->curTsID;

  if ( CDI_Debug )
463
    Message("gridID = %d gridsize = %d", gridID, gridsize);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
464

465
  fileID = streamptr->fileID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
466
467
468
469
470
471
472
473

  currentfilepos = fileGetPos(fileID);

  recID   = streamptr->vars[varID].level[levelID];
  recpos  = streamptr->tsteps[tsID].records[recID].position;
  recsize = streamptr->tsteps[tsID].records[recID].size;

  if ( recsize == 0 )
474
    Error("Internal problem! Recordsize is zero for record %d at timestep %d",
Uwe Schulzweida's avatar
Uwe Schulzweida committed
475
476
477
478
479
480
	  recID+1, tsID+1);

  fileSetPos(fileID, recpos, SEEK_SET);

  fileRead(fileID, gribbuffer, recsize);

481
  missval = vlistInqVarMissval(vlistID, varID);
482

483
  grbDecode(filetype, gribbuffer, recsize, data, gridsize, streamptr->unreduced, nmiss, &zip, missval, vlistID, varID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
484
485
486
487
488
489
490

  fileSetPos(fileID, currentfilepos, SEEK_SET);

  streamptr->tsteps[tsID].records[recID].zip = zip;
}

static
491
size_t grbEncode(int filetype, int memtype, int varID, int levelID, int vlistID, int gridID, int zaxisID,
492
		 int date, int time, int tsteptype, int numavg,
493
		 long datasize, const double *data, int nmiss, unsigned char **gribbuffer,
494
		 int ljpeg, void *gribContainer)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
495
496
{
  size_t nbytes;
497
  size_t gribbuffersize;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
498

499
#if  defined  (HAVE_LIBCGRIBEX)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
500
501
  if ( filetype == FILETYPE_GRB )
    {
502
503
504
      gribbuffersize = datasize*4+3000;
      *gribbuffer = (unsigned char *) malloc(gribbuffersize);

505
      nbytes = cgribexEncode(memtype, varID, levelID, vlistID, gridID, zaxisID,
506
			     date, time, tsteptype, numavg,
507
			     datasize, data, nmiss, *gribbuffer, gribbuffersize);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
508
509
    }
  else
510
#endif
Uwe Schulzweida's avatar
Uwe Schulzweida committed
511
    {
512
513
      if ( memtype == MEMTYPE_FLOAT ) Error("gribapiEncode() not implemented for memtype float!");

514
      nbytes = gribapiEncode(varID, levelID, vlistID, gridID, zaxisID,
515
			     date, time, tsteptype, numavg,
516
			     datasize, data, nmiss, gribbuffer, &gribbuffersize,
517
			     ljpeg, gribContainer);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
518
519
520
521
522
523
524
525
526
527
528
    }

  return (nbytes);
}

static
size_t grbSzip(int filetype, unsigned char *gribbuffer, size_t gribbuffersize)
{
  size_t nbytes = 0;
  unsigned char *buffer;
  size_t buffersize;
529
  static int lszip_warn = 1;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
530

531
  buffersize = gribbuffersize + 1000; /* compressed record can be greater than source record */
Uwe Schulzweida's avatar
Uwe Schulzweida committed
532
533
  buffer = (unsigned char *) malloc(buffersize);

534
  /*  memcpy(buffer, gribbuffer, gribbuffersize); */
535

Uwe Schulzweida's avatar
Uwe Schulzweida committed
536
537
538
539
540
541
  if ( filetype == FILETYPE_GRB )
    {
      nbytes = gribZip(gribbuffer, (long) gribbuffersize, buffer, (long) buffersize);
    }
  else
    {
542
      if ( lszip_warn ) Warning("Szip compression of GRIB2 records not implemented!");
543
      lszip_warn = 0;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
544
545
      nbytes = gribbuffersize;
    }
546

Uwe Schulzweida's avatar
Uwe Schulzweida committed
547
548
549
550
551
552
  free(buffer);

  return (nbytes);
}


553
int grb_write_var_slice(stream_t *streamptr, int varID, int levelID, int memtype, const void *data, int nmiss)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
554
555
556
557
558
559
560
561
562
563
{
  size_t nwrite;
  int fileID;
  int gridID;
  int zaxisID;
  unsigned char *gribbuffer = NULL;
  long datasize;
  int tsID;
  int vlistID;
  int date, time;
564
  int tsteptype;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
565
566
567
  int numavg = 0;
  size_t nbytes;
  int filetype;
568
569
  int ljpeg = 0;
  int ljpeg_warn = 1;
570
  void *gc = NULL;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
571

572
  filetype  = streamptr->filetype;
573
574
  fileID    = streamptr->fileID;
  vlistID   = streamptr->vlistID;
575
576
577
  gridID    = vlistInqVarGrid(vlistID, varID);
  zaxisID   = vlistInqVarZaxis(vlistID, varID);
  tsteptype = vlistInqVarTsteptype(vlistID, varID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
578

579
580
581
  tsID      = streamptr->curTsID;
  date      = streamptr->tsteps[tsID].taxis.vdate;
  time      = streamptr->tsteps[tsID].taxis.vtime;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
582
583
  if ( vlistInqVarTimave(vlistID, varID) )
    numavg = streamptr->tsteps[tsID].taxis.numavg;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
584

Uwe Schulzweida's avatar
Uwe Schulzweida committed
585
  if ( CDI_Debug )
586
    Message("gridID = %d zaxisID = %d", gridID, zaxisID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
587
588

  datasize = gridInqSize(gridID);
589
  /*
Uwe Schulzweida's avatar
Uwe Schulzweida committed
590
591
  gribbuffersize = datasize*4+3000;
  gribbuffer = (unsigned char *) malloc(gribbuffersize);
592
  */
593
594
595
596
597
598
#if  defined  (HAVE_LIBCGRIBEX)
  if ( filetype == FILETYPE_GRB )
    {
    }
  else
#endif
599
    {
600
601
602
603
#if defined (GRIBCONTAINER2D)
      gribContainer_t **gribContainers =  (gribContainer_t **) streamptr->gribContainers;
      gc = (void *) &gribContainers[varID][levelID];
#else
604
605
      gribContainer_t *gribContainers =  (gribContainer_t *) streamptr->gribContainers;
      gc = (void *) &gribContainers[varID];
606
#endif
607
608
    }

Deike Kleberg's avatar
Deike Kleberg committed
609
  if ( streamptr->comptype == COMPRESS_JPEG )
610
611
    {
      if ( filetype == FILETYPE_GRB2 )
612
613
614
	{
	  ljpeg = 1;
	}
615
616
      else
	{
617
	  if ( ljpeg_warn ) Warning("JPEG compression of GRIB1 records not available!");
618
619
620
621
	  ljpeg_warn = 0;
	}
    }

622
  nbytes = grbEncode(filetype, memtype, varID, levelID, vlistID, gridID, zaxisID, date, time, tsteptype, numavg,
Uwe Schulzweida's avatar
Uwe Schulzweida committed
623
		     datasize, (const double*) data, nmiss, &gribbuffer, ljpeg, gc);
624

Deike Kleberg's avatar
Deike Kleberg committed
625
  if ( streamptr->comptype == COMPRESS_SZIP )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
626
627
    nbytes = grbSzip(filetype, gribbuffer, nbytes);

Thomas Jahns's avatar
Thomas Jahns committed
628
629
630
  {
    size_t (*myFileWrite)(int fileID, const void *restrict buffer,
                          size_t len, int tsID)
631
632
      = (size_t (*)(int, const void *restrict, size_t, int))
      namespaceSwitchGet(NSSWITCH_FILE_WRITE).func;
Thomas Jahns's avatar
Thomas Jahns committed
633
634
    nwrite = myFileWrite(fileID, gribbuffer, nbytes, tsID);
  }
635
636

  if ( nwrite != nbytes ) perror(__func__);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
637

Uwe Schulzweida's avatar
Uwe Schulzweida committed
638
639
640
641
642
643
  if ( gribbuffer ) free(gribbuffer);

  return ((int)nwrite);
}


644
void grb_write_var(stream_t *streamptr, int varID, int memtype, const void *data, int nmiss)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
645
{
Uwe Schulzweida's avatar
Uwe Schulzweida committed
646
647
  int vlistID, gridID, zaxisID, levelID, nlevs;
  int gridsize;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
648

649
  vlistID  = streamptr->vlistID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
650
651
652
653
  gridID   = vlistInqVarGrid(vlistID, varID);
  gridsize = gridInqSize(gridID);
  zaxisID  = vlistInqVarZaxis(vlistID, varID);
  nlevs    = zaxisInqSize(zaxisID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
654
655
656

  for ( levelID = 0; levelID < nlevs; levelID++ )
    {
657
658
659
660
      if ( memtype == MEMTYPE_FLOAT )
        grb_write_var_slice(streamptr, varID, levelID, memtype, ((float*)data)+levelID*gridsize, nmiss);
      else
        grb_write_var_slice(streamptr, varID, levelID, memtype, ((double*)data)+levelID*gridsize, nmiss);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
661
662
663
664
    }
}


665
int grbCopyRecord(stream_t * streamptr2, stream_t * streamptr1)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
{
  int fileID1, fileID2;
  int tsID, recID, vrecID;
  long recsize;
  size_t gribbuffersize;
  off_t recpos;
  size_t nwrite;
  unsigned char *gribbuffer;
  int filetype;
  size_t nbytes;
  long unzipsize;
  int izip;

  filetype = streamptr1->filetype;

681
682
  fileID1 = streamptr1->fileID;
  fileID2 = streamptr2->fileID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700

  tsID    = streamptr1->curTsID;
  vrecID  = streamptr1->tsteps[tsID].curRecID;
  recID   = streamptr1->tsteps[tsID].recIDs[vrecID];
  recpos  = streamptr1->tsteps[tsID].records[recID].position;
  recsize = streamptr1->tsteps[tsID].records[recID].size;

  fileSetPos(fileID1, recpos, SEEK_SET);

  gribbuffersize = recsize == (recsize>>3)<<3 ? recsize : (1+(recsize>>3))<<3;

  gribbuffer = (unsigned char *) malloc(gribbuffersize);

  fileRead(fileID1, gribbuffer, recsize);

  nbytes = recsize;

  izip = gribGetZip(recsize, gribbuffer, &unzipsize);
701

Uwe Schulzweida's avatar
Uwe Schulzweida committed
702
  if ( izip == 0 )
Deike Kleberg's avatar
Deike Kleberg committed
703
    if ( streamptr2->comptype == COMPRESS_SZIP )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
704
705
706
707
708
      nbytes = grbSzip(filetype, gribbuffer, nbytes);

  while ( nbytes & 7 ) gribbuffer[nbytes++] = 0;

  nwrite = fileWrite(fileID2, gribbuffer, nbytes);
709
  if ( nwrite != nbytes ) perror(__func__);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
710
711
712
713
714
715
716

  free(gribbuffer);

  return ((int)nwrite);
}


717
int grb_write_record(stream_t * streamptr, int memtype, const void *data, int nmiss)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
718
719
720
721
722
723
724
{
  int status = 0;
  int varID, levelID;

  varID   = streamptr->record->varID;
  levelID = streamptr->record->levelID;

725
  status = grb_write_var_slice(streamptr, varID, levelID, memtype, data, nmiss);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
726
727
728
729
730

  return (status);
}


731
void streamInqGinfo(int streamID, int *intnum, float *fltnum, off_t *bignum)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
732
733
734
735
736
737
738
739
740
741
742
{
  int recID, vrecID, tsID;
  int filetype;
  void *gribbuffer;
  long gribbuffersize;
  off_t recpos;
  int zip;
  stream_t *streamptr;

  streamptr = stream_to_pointer(streamID);

743
  stream_check_ptr(__func__, streamptr);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758

  filetype = streamptr->filetype;

  if ( filetype == FILETYPE_GRB )
    {
      tsID    = streamptr->curTsID;
      vrecID  = streamptr->tsteps[tsID].curRecID;
      recID   = streamptr->tsteps[tsID].recIDs[vrecID];
      recpos  = streamptr->tsteps[tsID].records[recID].position;
      zip     = streamptr->tsteps[tsID].records[recID].zip;

      gribbuffer = streamptr->record->buffer;
      gribbuffersize = streamptr->record->buffersize;

      if ( zip > 0 )
759
	Error("Compressed GRIB records unsupported!");
Uwe Schulzweida's avatar
Uwe Schulzweida committed
760
      else
761
	gribGinfo(recpos, gribbuffersize, (unsigned char *) gribbuffer, intnum, fltnum, bignum);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
762
763
    }
}
764
765
766
767
768
769
770
771
772
/*
 * Local Variables:
 * c-file-style: "Java"
 * c-basic-offset: 2
 * indent-tabs-mode: nil
 * show-trailing-whitespace: t
 * require-trailing-newline: t
 * End:
 */