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

#include <ctype.h>

#include "cdi.h"
8
#include "cdi_int.h"
Uwe Schulzweida's avatar
Uwe Schulzweida committed
9
#include "cdf.h"
10
11
#include "dmemory.h"
#include "error.h"
Uwe Schulzweida's avatar
Uwe Schulzweida committed
12
#include "stream_grb.h"
Uwe Schulzweida's avatar
Uwe Schulzweida committed
13
14
15
16
17
#include "stream_cdf.h"
#include "stream_srv.h"
#include "stream_ext.h"
#include "stream_ieg.h"
#include "file.h"
Uwe Schulzweida's avatar
Uwe Schulzweida committed
18
#include "cgribex.h"
Uwe Schulzweida's avatar
Uwe Schulzweida committed
19
#include "gribapi.h"
Uwe Schulzweida's avatar
Uwe Schulzweida committed
20
21
22
23
24
#include "cdf.h"
#include "service.h"
#include "extra.h"
#include "ieg.h"
#include "vlist.h"
25
#include "resource_handle.h"
Uwe Schulzweida's avatar
Uwe Schulzweida committed
26

27
28
#include "namespace.h"

29
30
#include <string.h>

31
32
33
34
#define  MAX_FNAMES  3

FILE *popen(const char *command, const char *type);
int pclose(FILE *stream);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
35

Thomas Jahns's avatar
Thomas Jahns committed
36
37
static void
cdiPrintDefaults(void)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
38
{
39
40
41
42
  fprintf (stderr, "default instID     :  %d\n", cdiDefaultInstID);
  fprintf (stderr, "default modelID    :  %d\n", cdiDefaultModelID);
  fprintf (stderr, "default tableID    :  %d\n", cdiDefaultTableID);
  fprintf (stderr, "default missval    :  %g\n", cdiDefaultMissval);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
43
44
45
46
47
}


void cdiDebug(int level)
{
48
  if ( level == 1 || (level &  2) ) CDI_Debug = 1;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
49

50
  if ( CDI_Debug ) Message("debug level %d", level);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
51

52
  if ( level == 1 || (level &  4) ) memDebug(1);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
53

54
  if ( level == 1 || (level &  8) ) fileDebug(1);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
55

56
  if ( level == 1 || (level & 16) )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
    {
#if  defined  (HAVE_LIBGRIB)
      gribSetDebug(1);
#endif
#if  defined  (HAVE_LIBNETCDF)
      cdfDebug(1);
#endif
#if  defined  (HAVE_LIBSERVICE)
      srvDebug(1);
#endif
#if  defined  (HAVE_LIBEXTRA)
      extDebug(1);
#endif
#if  defined  (HAVE_LIBIEG)
      iegDebug(1);
#endif
    }

  if ( CDI_Debug )
    {
      cdiPrintDefaults();
      cdiPrintDatatypes();
    }
}


83
84
85
86
87
88
89
90
91
92
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
int cdiHaveFiletype(int filetype)
{
  int status = 0;

  switch (filetype)
    {
#if  defined  (HAVE_LIBSERVICE)
    case FILETYPE_SRV:  { status = 1; break; }
#endif
#if  defined  (HAVE_LIBEXTRA)
    case FILETYPE_EXT:  { status = 1; break; }
#endif
#if  defined  (HAVE_LIBIEG)
    case FILETYPE_IEG:  { status = 1; break; }
#endif
#if  defined  (HAVE_LIBGRIB)
#if  defined  (HAVE_LIBGRIB_API) || defined  (HAVE_LIBCGRIBEX)
    case FILETYPE_GRB:  { status = 1; break; }
#endif
#if  defined  (HAVE_LIBGRIB_API)
    case FILETYPE_GRB2: { status = 1; break; }
#endif
#endif
#if  defined  (HAVE_LIBNETCDF)
    case FILETYPE_NC:   { status = 1; break; }
#if  defined  (HAVE_NETCDF2)
    case FILETYPE_NC2:  { status = 1; break; }
#endif
#if  defined  (HAVE_NETCDF4)
    case FILETYPE_NC4:  { status = 1; break; }
    case FILETYPE_NC4C: { status = 1; break; }
#endif
#endif
    default: { status = 0; break; }
    }

  return (status);
}


Uwe Schulzweida's avatar
Uwe Schulzweida committed
123
124
125
126
#undef  IsBigendian
#define IsBigendian()  ( u_byteorder.c[sizeof(long) - 1] )


127
128
static
int getByteorder(int byteswap)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
{
  static union {unsigned long l; unsigned char c[sizeof(long)];} u_byteorder = {1};
  int byteorder = -1;

  if ( IsBigendian() )
    {
      if ( byteswap ) byteorder = CDI_LITTLEENDIAN;
      else            byteorder = CDI_BIGENDIAN;
    }
  else
    {
      if ( byteswap ) byteorder = CDI_BIGENDIAN;
      else            byteorder = CDI_LITTLEENDIAN;
    }

  return (byteorder);
}


148
149
static
int getFiletype(const char *filename, int *byteorder)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
150
151
152
153
{
  int filetype = CDI_EUFTYPE;
  int fileID;
  int swap = 0;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
154
  int version;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
155
  long recpos;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
156
  char buffer[8];
Uwe Schulzweida's avatar
Uwe Schulzweida committed
157
158
159
160
161

  fileID = fileOpen(filename, "r");

  if ( fileID == CDI_UNDEFID )
    {
162
      if ( memcmp(filename, "http:", 5) == 0 )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
163
164
165
166
167
	return (FILETYPE_NC);
      else
	return (CDI_ESYSTEM);
    }

Uwe Schulzweida's avatar
Uwe Schulzweida committed
168
  if ( fileRead(fileID, buffer, 8) != 8 ) return (CDI_EUFTYPE);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
169
170
171

  fileRewind(fileID);

172
  if ( memcmp(buffer, "GRIB", 4) == 0 )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
173
    {
Uwe Schulzweida's avatar
Uwe Schulzweida committed
174
175
176
177
      version = buffer[7];
      if ( version <= 1 )
	{
	  filetype = FILETYPE_GRB;
178
	  if ( CDI_Debug ) Message("found GRIB file = %s, version %d", filename, version);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
179
	}
Uwe Schulzweida's avatar
Uwe Schulzweida committed
180
181
182
      else if ( version == 2 )
	{
	  filetype = FILETYPE_GRB2;
183
	  if ( CDI_Debug ) Message("found GRIB2 file = %s", filename);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
184
	}
Uwe Schulzweida's avatar
Uwe Schulzweida committed
185
    }
186
  else if ( memcmp(buffer, "CDF\001", 4) == 0 )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
187
188
    {
      filetype = FILETYPE_NC;
189
      if ( CDI_Debug ) Message("found CDF1 file = %s", filename);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
190
    }
191
  else if ( memcmp(buffer, "CDF\002", 4) == 0 )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
192
193
    {
      filetype = FILETYPE_NC2;
194
      if ( CDI_Debug ) Message("found CDF2 file = %s", filename);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
195
    }
196
  else if ( memcmp(buffer+1, "HDF", 3) == 0 )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
197
    {
198
      filetype = FILETYPE_NC4;
199
      if ( CDI_Debug ) Message("found HDF file = %s", filename);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
200
201
202
203
204
    }
#if  defined  (HAVE_LIBSERVICE)
  else if ( srvCheckFiletype(fileID, &swap) )
    {
      filetype = FILETYPE_SRV;
205
      if ( CDI_Debug ) Message("found SRV file = %s", filename);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
206
207
208
209
210
211
    }
#endif
#if  defined  (HAVE_LIBEXTRA)
  else if ( extCheckFiletype(fileID, &swap) )
    {
      filetype = FILETYPE_EXT;
212
      if ( CDI_Debug ) Message("found EXT file = %s", filename);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
213
214
215
216
217
218
    }
#endif
#if  defined  (HAVE_LIBIEG)
  else if ( iegCheckFiletype(fileID, &swap) )
    {
      filetype = FILETYPE_IEG;
219
      if ( CDI_Debug ) Message("found IEG file = %s", filename);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
220
221
    }
#endif
Uwe Schulzweida's avatar
Uwe Schulzweida committed
222
  else if ( gribCheckSeek(fileID, &recpos, &version) == 0 )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
223
    {
Uwe Schulzweida's avatar
Uwe Schulzweida committed
224
225
226
      if ( version <= 1 )
	{
	  filetype = FILETYPE_GRB;
227
	  if ( CDI_Debug ) Message("found seeked GRIB file = %s", filename);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
228
	}
Uwe Schulzweida's avatar
Uwe Schulzweida committed
229
      else if ( version == 2 )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
230
231
	{
	  filetype = FILETYPE_GRB2;
232
	  if ( CDI_Debug ) Message("found seeked GRIB2 file = %s", filename);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
233
	}
Uwe Schulzweida's avatar
Uwe Schulzweida committed
234
235
236
237
238
239
240
241
242
243
    }

  fileClose(fileID);

  *byteorder = getByteorder(swap);

  return (filetype);
}


244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
int _readline_(FILE *fp, char *line, int len)
{
  int ichar, ipos = 0;

  while ( (ichar = fgetc(fp)) != EOF )
    {
      if ( ichar == '\n' ) break;
      line[ipos++] = ichar;
      if ( ipos >= len )
        {
          fprintf(stderr, "readline Warning: end of line not found (maxlen = %d)!\n", len);
          break;
        }
    }
  line[ipos] = 0;

  if ( feof(fp) && ipos == 0 ) return (0);

  return (1);
}

#define  MAX_LINE  4096

int get_fnames(const char *argument, char *fnames[], int max_fnames)
{
  int num_fnames = 0;
  int len;
  int nfiles = 0;
  int i, j;
  const char *pch;
  char line[MAX_LINE];

  len = (int) strlen(argument);
  for ( i = 0; i < len; ++i )
    if ( argument[i] == ':' ) break;

  if ( i < len )
    {
      pch = &argument[i+1];
      len -= (i+1);
284
      if ( len && ( memcmp(argument, "filelist:", i) == 0 ||
285
		    memcmp(argument, "flist:", i) == 0 ) )
286
287
288
289
290
291
292
	{
	  for ( i = 0; i < len; ++i ) if ( pch[i] == ',' ) nfiles++;

	  if ( nfiles == 0 )
	    {
	      FILE *fp;
	      fp = fopen(pch, "r");
293
	      if ( fp == NULL ) Error("Open failed on %s", pch);
294
295

	      if ( CDI_Debug )
296
		Message("Reading file names from %s", pch);
297
298
299
300
301
302
303
304

	      rewind(fp);

	      nfiles = 0;
	      while ( _readline_(fp, line, MAX_LINE) )
		{
		  if ( line[0] == '#' || line[0] == '\0' ||
		       line[0] == ' ' ) continue;
305

306
307
		  if ( nfiles >= max_fnames )
		    {
308
		      Warning("Too many input files (limit: %d)", max_fnames);
309
310
311
312
313
		      break;
		    }
		  fnames[nfiles] = strdupx(line);
		  nfiles++;
		}
314

315
316
	      fclose(fp);

317
	      if ( nfiles == 0 ) Error("No input file found in %s", pch);
318
319
320
321
	    }
	  else
	    {
	      char xline[65536];
322

323
324
	      strcpy(xline, pch);
	      for ( i = 0; i < len; i++ ) if ( xline[i] == ',' ) xline[i] = 0;
325

326
327
328
	      nfiles++;
	      if ( nfiles >= max_fnames )
		{
329
		  Warning("Too many input files (limit: %d)", max_fnames);
330
331
332
333
334
335
336
337
338
339
340
		  nfiles = max_fnames;
		}

	      i = 0;
	      for ( j = 0; j < nfiles; j++ )
		{
		  fnames[j] = strdupx(&xline[i]);
		  i += strlen(&xline[i]) + 1;
		}
	    }
	}
341
      else if ( len && memcmp(argument, "ls:", i) == 0 )
342
343
344
	{
	  char command[4096];
	  FILE *pfp;
345

346
347
348
349
	  strcpy(command, "ls ");
	  strcat(command, pch);

	  pfp = popen(command, "r");
350
	  if ( pfp == NULL ) SysError("popen %s failed", command);
351

352
353
354
355
356
	  nfiles = 0;
	  while ( _readline_(pfp, line, MAX_LINE) )
	    {
	      if ( nfiles >= max_fnames )
		{
357
		  Warning("Too many input files (limit: %d)", max_fnames);
358
359
360
361
362
363
		  break;
		}
	      fnames[nfiles++] = strdupx(line);
	    }

	  pclose(pfp);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
364
	  /*
365
366
	  for ( j = 0; j < nfiles; j++ )
	    fnames[j] = fnames[j];
Uwe Schulzweida's avatar
Uwe Schulzweida committed
367
	  */
368
369
370
371
	}
    }

  num_fnames = nfiles;
372

373
374
375
  return (num_fnames);
}

Uwe Schulzweida's avatar
Uwe Schulzweida committed
376
377
378
379
380
381
/*
@Function  streamInqFiletype
@Title     Get the filetype

@Prototype int streamInqFiletype(int streamID)
@Parameter
Deike Kleberg's avatar
Deike Kleberg committed
382
    @Item  streamID  Stream ID, from a previous call to @fref{streamOpenRead} or @fref{streamOpenWrite}.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
383
384

@Description
385
The function @func{streamInqFiletype} returns the filetype of a stream.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
386
387

@Result
388
@func{streamInqFiletype} returns the type of the file format,
Uwe Schulzweida's avatar
Uwe Schulzweida committed
389
one of the set of predefined CDI file format types.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
390
The valid CDI file format types are @func{FILETYPE_GRB}, @func{FILETYPE_GRB2}, @func{FILETYPE_NC}, @func{FILETYPE_NC2},
Deike Kleberg's avatar
Deike Kleberg committed
391
@func{FILETYPE_NC4}, @func{FILETYPE_NC4C}, @func{FILETYPE_SRV}, @func{FILETYPE_EXT} and @func{FILETYPE_IEG}.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
392
393
394
395
396

@EndFunction
*/
int streamInqFiletype(int streamID)
{
Uwe Schulzweida's avatar
Uwe Schulzweida committed
397
  stream_t *streamptr;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
398
399

  streamptr = stream_to_pointer(streamID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
400

401
  stream_check_ptr(__func__, streamptr);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
402

Uwe Schulzweida's avatar
Uwe Schulzweida committed
403
  return (streamptr->filetype);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
}


int getByteswap(int byteorder)
{
  static union {unsigned long l; unsigned char c[sizeof(long)];} u_byteorder = {1};
  int byteswap = 0;

  if ( IsBigendian() )
    {
      if ( byteorder == CDI_LITTLEENDIAN ) byteswap = TRUE;
    }
  else
    {
      if ( byteorder == CDI_BIGENDIAN ) byteswap = TRUE;
    }

  return (byteswap);
}

424
425
426
427
428
429
/*
@Function  streamDefByteorder
@Title     Define the byte order

@Prototype void streamDefByteorder(int streamID, int byteorder)
@Parameter
430
    @Item  streamID  Stream ID, from a previous call to @fref{streamOpenWrite}.
431
432
433
434
435
436
437
438
439
    @Item  byteorder The byte order of a dataset, one of the CDI constants @func{CDI_BIGENDIAN} and
                     @func{CDI_LITTLEENDIAN}.

@Description
The function @func{streamDefByteorder} defines the byte order of a binary dataset
with the file format type @func{FILETYPE_SRV}, @func{FILETYPE_EXT} or @func{FILETYPE_IEG}.

@EndFunction
*/
Uwe Schulzweida's avatar
Uwe Schulzweida committed
440
441
void streamDefByteorder(int streamID, int byteorder)
{
Thomas Jahns's avatar
Thomas Jahns committed
442
  int filetype;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
443
  stream_t *streamptr;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
444

Uwe Schulzweida's avatar
Uwe Schulzweida committed
445
  streamptr = stream_to_pointer(streamID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
446

447
  stream_check_ptr(__func__, streamptr);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
448

449
  if ( reshGetStatus ( streamID, &streamOps ) == RESH_CLOSED )
450
    {
451
      Warning("%s", "Operation not executed.");
452
453
454
      return;
    }

Uwe Schulzweida's avatar
Uwe Schulzweida committed
455
456
  streamptr->byteorder = byteorder;
  filetype = streamptr->filetype;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
457
458
459
460
461
462

  switch (filetype)
    {
#if  defined  (HAVE_LIBSERVICE)
    case FILETYPE_SRV:
      {
Uwe Schulzweida's avatar
Uwe Schulzweida committed
463
	srvrec_t *srvp = streamptr->record->srvp;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
464
465
466
467
468
469
470
471
	srvp->byteswap = getByteswap(byteorder);

	break;
      }
#endif
#if  defined  (HAVE_LIBEXTRA)
    case FILETYPE_EXT:
      {
Uwe Schulzweida's avatar
Uwe Schulzweida committed
472
	extrec_t *extp = streamptr->record->extp;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
473
474
475
476
477
478
479
480
	extp->byteswap = getByteswap(byteorder);

	break;
      }
#endif
#if  defined  (HAVE_LIBIEG)
    case FILETYPE_IEG:
      {
Uwe Schulzweida's avatar
Uwe Schulzweida committed
481
	iegrec_t *iegp = streamptr->record->iegp;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
482
483
484
485
486
487
488
489
	iegp->byteswap = getByteswap(byteorder);

	break;
      }
#endif
    }
}

490
491
492
493
494
495
/*
@Function  streamInqByteorder
@Title     Get the byte order

@Prototype int streamInqByteorder(int streamID)
@Parameter
Deike Kleberg's avatar
Deike Kleberg committed
496
    @Item  streamID  Stream ID, from a previous call to @fref{streamOpenRead} or @fref{streamOpenWrite}.
497
498
499
500
501
502
503
504
505
506
507

@Description
The function @func{streamInqByteorder} returns the byte order of a binary dataset
with the file format type @func{FILETYPE_SRV}, @func{FILETYPE_EXT} or @func{FILETYPE_IEG}.

@Result
@func{streamInqByteorder} returns the type of the byte order.
The valid CDI byte order types are @func{CDI_BIGENDIAN} and @func{CDI_LITTLEENDIAN}

@EndFunction
*/
Uwe Schulzweida's avatar
Uwe Schulzweida committed
508
509
int streamInqByteorder(int streamID)
{
Uwe Schulzweida's avatar
Uwe Schulzweida committed
510
  stream_t *streamptr;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
511
512

  streamptr = stream_to_pointer(streamID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
513

514
  stream_check_ptr(__func__, streamptr);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
515

Uwe Schulzweida's avatar
Uwe Schulzweida committed
516
  return (streamptr->byteorder);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
517
518
519
520
521
}


char *streamFilesuffix(int filetype)
{
522
523
  // static char *fileSuffix[] = {"", ".grb", ".g2", ".nc", ".nc", ".nc4", ".nc4", ".srv", ".ext", ".ieg"};
  static char *fileSuffix[] = {"", ".grb", ".grb", ".nc", ".nc", ".nc", ".nc", ".srv", ".ext", ".ieg"};
Uwe Schulzweida's avatar
Uwe Schulzweida committed
524
  int size = (int) (sizeof(fileSuffix)/sizeof(char *));
Uwe Schulzweida's avatar
Uwe Schulzweida committed
525
526
527
528
529
530
531
532
533
534

  if ( filetype > 0 && filetype < size )
    return (fileSuffix[filetype]);
  else
    return (fileSuffix[0]);
}


char *streamFilename(int streamID)
{
Uwe Schulzweida's avatar
Uwe Schulzweida committed
535
  stream_t *streamptr;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
536

Uwe Schulzweida's avatar
Uwe Schulzweida committed
537
  streamptr = stream_to_pointer(streamID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
538

539
  stream_check_ptr(__func__, streamptr);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
540
541

  return (streamptr->filename);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
542
543
}

544
static
Uwe Schulzweida's avatar
Uwe Schulzweida committed
545
546
547
548
int cdiInqTimeSize(int streamID)
{
  int ntsteps;
  int tsID = 0, nrecs;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
549
  stream_t *streamptr;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
550
551

  streamptr = stream_to_pointer(streamID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
552

553
  stream_check_ptr(__func__, streamptr);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
554

Uwe Schulzweida's avatar
Uwe Schulzweida committed
555
  ntsteps = streamptr->ntsteps;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
556
557
558
559

  if ( ntsteps == CDI_UNDEFID )
    while ( (nrecs = streamInqTimestep(streamID, tsID++)) )

Uwe Schulzweida's avatar
Uwe Schulzweida committed
560
  ntsteps = streamptr->ntsteps;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
561
562
563
564

  return (ntsteps);
}

565
566
static
int cdiInqContents(stream_t * streamptr)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
567
568
569
570
571
572
{
  int filetype;
  int vlistID;
  int taxisID;
  int status = 0;

Uwe Schulzweida's avatar
Uwe Schulzweida committed
573
  filetype = streamptr->filetype;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
574
575
576
577
578

  switch (filetype)
    {
#if  defined  (HAVE_LIBGRIB)
    case FILETYPE_GRB:
Uwe Schulzweida's avatar
Uwe Schulzweida committed
579
580
    case FILETYPE_GRB2:
      {
581
        status = grbInqContents(streamptr);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
582
583
584
	break;
      }
#endif
Uwe Schulzweida's avatar
Uwe Schulzweida committed
585
586
587
#if  defined  (HAVE_LIBSERVICE)
    case FILETYPE_SRV:
      {
588
        status = srvInqContents(streamptr);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
589
590
591
592
593
594
	break;
      }
#endif
#if  defined  (HAVE_LIBEXTRA)
    case FILETYPE_EXT:
      {
595
        status = extInqContents(streamptr);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
596
597
598
599
600
601
	break;
      }
#endif
#if  defined  (HAVE_LIBIEG)
    case FILETYPE_IEG:
      {
602
        status = iegInqContents(streamptr);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
603
604
605
606
607
608
	break;
      }
#endif
#if  defined  (HAVE_LIBNETCDF)
    case FILETYPE_NC:
    case FILETYPE_NC2:
609
    case FILETYPE_NC4:
Deike Kleberg's avatar
Deike Kleberg committed
610
    case FILETYPE_NC4C:
Uwe Schulzweida's avatar
Uwe Schulzweida committed
611
      {
612
        status = cdfInqContents(streamptr);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
613
614
615
616
617
618
	break;
      }
#endif
    default:
      {
	if ( CDI_Debug )
619
	  Message("%s support not compiled in!", strfiletype(filetype));
Uwe Schulzweida's avatar
Uwe Schulzweida committed
620
621

	status = CDI_ELIBNAVAIL;
622
        break;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
623
624
625
626
627
      }
    }

  if ( status == 0 )
    {
628
      vlistID = streamptr->vlistID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
629
630
      taxisID = vlistInqTaxis(vlistID);
      if ( taxisID != -1 )
631
632
633
634
635
636
637
        {
          taxis_t *taxisptr1 = &streamptr->tsteps[0].taxis;
          taxis_t *taxisptr2 = taxisPtr(taxisID);
          ptaxisCopy(taxisptr2, taxisptr1);
          if ( taxisptr1->name     ) taxisptr2->name = taxisptr1->name;
          if ( taxisptr1->longname ) taxisptr2->longname = taxisptr1->longname;
        }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
638
639
640
641
642
    }

  return (status);
}

643
int cdiStreamOpenDefaultDelegate(const char *filename, const char *filemode,
644
645
                                 int filetype, stream_t *streamptr,
                                 int recordBufIsToBeCreated)
646
647
648
{
  int fileID;
  switch (filetype)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
649
650
    {
#if  defined  (HAVE_LIBGRIB)
651
652
653
654
655
    case FILETYPE_GRB:
    case FILETYPE_GRB2:
      {
        fileID = gribOpen(filename, filemode);
        if ( fileID < 0 ) fileID = CDI_ESYSTEM;
656
657
658
659
660
        if (recordBufIsToBeCreated)
          {
            streamptr->record = (Record *) malloc(sizeof(Record));
            streamptr->record->buffer = NULL;
          }
661
662
        break;
      }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
663
664
#endif
#if  defined  (HAVE_LIBSERVICE)
665
666
667
668
    case FILETYPE_SRV:
      {
        fileID = fileOpen(filename, filemode);
        if ( fileID < 0 ) fileID = CDI_ESYSTEM;
669
670
671
672
673
674
        if (recordBufIsToBeCreated)
          {
            streamptr->record = (Record *) malloc(sizeof(Record));
            streamptr->record->buffer = NULL;
            streamptr->record->srvp   = srvNew();
          }
675
676
        break;
      }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
677
678
#endif
#if  defined  (HAVE_LIBEXTRA)
679
680
681
682
    case FILETYPE_EXT:
      {
        fileID = fileOpen(filename, filemode);
        if ( fileID < 0 ) fileID = CDI_ESYSTEM;
683
684
685
686
687
688
        if (recordBufIsToBeCreated)
          {
            streamptr->record = (Record *) malloc(sizeof(Record));
            streamptr->record->buffer = NULL;
            streamptr->record->extp   = extNew();
          }
689
690
        break;
      }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
691
692
#endif
#if  defined  (HAVE_LIBIEG)
693
694
695
696
    case FILETYPE_IEG:
      {
        fileID = fileOpen(filename, filemode);
        if ( fileID < 0 ) fileID = CDI_ESYSTEM;
697
698
699
700
701
702
        if (recordBufIsToBeCreated)
          {
            streamptr->record = (Record *) malloc(sizeof(Record));
            streamptr->record->buffer = NULL;
            streamptr->record->iegp   = iegNew();
          }
703
704
        break;
      }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
705
706
#endif
#if  defined  (HAVE_LIBNETCDF)
707
708
709
710
711
712
713
714
715
716
717
718
719
    case FILETYPE_NC:
      {
        fileID = cdfOpen(filename, filemode);
        break;
      }
    case FILETYPE_NC2:
      {
        fileID = cdfOpen64(filename, filemode);
        break;
      }
    case FILETYPE_NC4:
    case FILETYPE_NC4C:
      {
720
        fileID = cdf4Open(filename, filemode, &filetype);
721
        break;
722
723
724
725
726
727
728
      }
#endif
    default:
      {
        if ( CDI_Debug ) Message("%s support not compiled in!", strfiletype(filetype));
        return (CDI_ELIBNAVAIL);
      }
729
    }
730
731
732

  streamptr->filetype = filetype;

733
734
735
736
737
738
739
740
741
  return fileID;
}


int streamOpen(const char *filename, const char *filemode, int filetype)
{
  int fileID = CDI_UNDEFID;
  int streamID = CDI_ESYSTEM;
  int status;
742
  stream_t *streamptr = stream_new_entry();
743

744
745
746
747
748
749
750
  if ( CDI_Debug )
    Message("Open %s mode %c file %s", strfiletype(filetype), (int) *filemode, filename);

  if ( ! filename || ! filemode || filetype < 0 ) return (CDI_EINVAL);

  {
    int (*streamOpenDelegate)(const char *filename, const char *filemode,
751
752
                              int filetype, stream_t *streamptr, int recordBufIsToBeCreated)
      = (int (*)(const char *, const char *, int, stream_t *, int))
753
      namespaceSwitchGet(NSSWITCH_STREAM_OPEN_BACKEND).func;
754

755
    fileID = streamOpenDelegate(filename, filemode, filetype, streamptr, 1);
756
757
758
  }

  if (fileID < 0)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
759
    {
760
761
      free(streamptr->record);
      stream_delete_entry(streamptr);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
762
763
764
765
      streamID = fileID;
    }
  else
    {
766
767
      streamID  = streamptr->self;

768
      if ( streamID < 0 ) return (CDI_ELIMIT);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
769

Uwe Schulzweida's avatar
Uwe Schulzweida committed
770
771
772
      streamptr->filemode = tolower(*filemode);
      streamptr->filename = strdupx(filename);
      streamptr->fileID   = fileID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
773

Uwe Schulzweida's avatar
Uwe Schulzweida committed
774
      if ( streamptr->filemode == 'r' )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
775
	{
776
	  vlist_t *vlistptr;
777
778
779
780
781
	  int vlistID;
	  vlistID = vlistCreate();
	  if ( vlistID < 0 ) return(CDI_ELIMIT);

	  streamptr->vlistID = vlistID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
782
	  /* cdiReadByteorder(streamID); */
783
	  status = cdiInqContents(streamptr);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
784
	  if ( status < 0 ) return (status);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
785
	  vlistptr = vlist_to_pointer(streamptr->vlistID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
786
787
788
	  vlistptr->ntsteps = streamNtsteps(streamID);
	}
    }
789

Uwe Schulzweida's avatar
Uwe Schulzweida committed
790
791
792
793
  return (streamID);
}


794
static int streamOpenA(const char *filename, const char *filemode, int filetype)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
795
796
797
798
{
  int fileID = CDI_UNDEFID;
  int streamID = CDI_ESYSTEM;
  int status;
799
  stream_t *streamptr = stream_new_entry();
800
  vlist_t *vlistptr;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
801
802

  if ( CDI_Debug )
803
    Message("Open %s file (mode=%c); filename: %s", strfiletype(filetype), (int) *filemode, filename);
804
  if ( CDI_Debug ) printf("streamOpenA: %s\n", filename); // seg fault without this line on thunder/squall with "cdo cat x y"
Uwe Schulzweida's avatar
Uwe Schulzweida committed
805
806
807

  if ( ! filename || ! filemode || filetype < 0 ) return (CDI_EINVAL);

808
809
  {
    int (*streamOpenDelegate)(const char *filename, const char *filemode,
810
811
                              int filetype, stream_t *streamptr, int recordBufIsToBeCreated)
      = (int (*)(const char *, const char *, int, stream_t *, int))
812
      namespaceSwitchGet(NSSWITCH_STREAM_OPEN_BACKEND).func;
813

814
    fileID = streamOpenDelegate(filename, "r", filetype, streamptr, 1);
815
  }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
816

817
  if ( fileID == CDI_UNDEFID || fileID == CDI_ELIBNAVAIL || fileID == CDI_ESYSTEM ) return (fileID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
818

819
  streamID = streamptr->self;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
820

821
822
823
824
825
826
827
828
829
830
  streamptr->filemode = tolower(*filemode);
  streamptr->filename = strdupx(filename);
  streamptr->fileID   = fileID;

  streamptr->vlistID = vlistCreate();
  /* cdiReadByteorder(streamID); */
  status = cdiInqContents(streamptr);
  if ( status < 0 ) return (status);
  vlistptr = vlist_to_pointer(streamptr->vlistID);
  vlistptr->ntsteps = cdiInqTimeSize(streamID);
831

832
833
  {
    void (*streamCloseDelegate)(stream_t *streamptr, int recordBufIsToBeDeleted)
834
835
      = (void (*)(stream_t *, int))
      namespaceSwitchGet(NSSWITCH_STREAM_CLOSE_BACKEND).func;
836

837
838
    streamCloseDelegate(streamptr, 0);
  }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
839
840
841
842
843

  switch (filetype)
    {
#if  defined  (HAVE_LIBGRIB)
    case FILETYPE_GRB:
Uwe Schulzweida's avatar
Uwe Schulzweida committed
844
    case FILETYPE_GRB2:
Uwe Schulzweida's avatar
Uwe Schulzweida committed
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
      {
        fileID = gribOpen(filename, filemode);
	break;
      }
#endif
#if  defined  (HAVE_LIBSERVICE)
    case FILETYPE_SRV:
      {
        fileID = fileOpen(filename, filemode);
	break;
      }
#endif
#if  defined  (HAVE_LIBEXTRA)
    case FILETYPE_EXT:
      {
        fileID = fileOpen(filename, filemode);
	break;
      }
#endif
#if  defined  (HAVE_LIBIEG)
    case FILETYPE_IEG:
      {
        fileID = fileOpen(filename, filemode);
	break;
      }
#endif
#if  defined  (HAVE_LIBNETCDF)
    case FILETYPE_NC:
      {
	fileID = cdfOpen(filename, filemode);
875
	streamptr->ncmode = 2;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
876
877
878
879
880
	break;
      }
    case FILETYPE_NC2:
      {
	fileID = cdfOpen64(filename, filemode);
881
	streamptr->ncmode = 2;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
882
883
	break;
      }
884
    case FILETYPE_NC4:
Deike Kleberg's avatar
Deike Kleberg committed
885
    case FILETYPE_NC4C:
886
      {
Deike Kleberg's avatar
Deike Kleberg committed
887
	fileID = cdf4Open(filename, filemode, &filetype);
888
	streamptr->ncmode = 2;
889
890
	break;
      }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
891
892
893
#endif
    default:
      {
894
	if ( CDI_Debug ) Message("%s support not compiled in!", strfiletype(filetype));
Uwe Schulzweida's avatar
Uwe Schulzweida committed
895
896
897
898
899
900
901
	return (CDI_ELIBNAVAIL);
      }
    }

  if ( fileID == CDI_UNDEFID )
    streamID = CDI_UNDEFID;
  else
902
    streamptr->fileID = fileID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
903
904
905
906
907
908

  return (streamID);
}

/*
@Function  streamOpenRead
Uwe Schulzweida's avatar
Uwe Schulzweida committed
909
@Title     Open a dataset for reading
Uwe Schulzweida's avatar
Uwe Schulzweida committed
910

Uwe Schulzweida's avatar
Uwe Schulzweida committed
911
@Prototype int streamOpenRead(const char *path)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
912
@Parameter
Deike Kleberg's avatar
Deike Kleberg committed
913
    @Item  path  The name of the dataset to be read.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
914
915

@Description
916
The function @func{streamOpenRead} opens an existing dataset for reading.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
917
918

@Result
919
Upon successful completion @func{streamOpenRead} returns an identifier to the
Uwe Schulzweida's avatar
Uwe Schulzweida committed
920
921
922
923
open stream. Otherwise, a negative number with the error status is returned.

@Errors
@List
Deike Kleberg's avatar
Deike Kleberg committed
924
925
926
927
   @Item  CDI_ESYSTEM     Operating system error.
   @Item  CDI_EINVAL      Invalid argument.
   @Item  CDI_EUFILETYPE  Unsupported file type.
   @Item  CDI_ELIBNAVAIL  Library support not compiled in.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
928
929
930
@EndList

@Example
931
932
Here is an example using @func{streamOpenRead} to open an existing netCDF
file named @func{foo.nc} for reading:
Uwe Schulzweida's avatar
Uwe Schulzweida committed
933
934

@Source
Uwe Schulzweida's avatar
Uwe Schulzweida committed
935
#include "cdi.h"
Uwe Schulzweida's avatar
Uwe Schulzweida committed
936
937
938
939
940
941
942
943
944
   ...
int streamID;
   ...
streamID = streamOpenRead("foo.nc");
if ( streamID < 0 ) handle_error(streamID);
   ...
@EndSource
@EndFunction
*/
945
int streamOpenRead(const char *filenames)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
946
947
948
{
  int filetype, byteorder;
  int streamID;
949
  int num_fnames = 0;
950
951
  char *fnames[MAX_FNAMES];
  const char *filename;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
952
  stream_t *streamptr = NULL;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
953

954
955
  cdiInitialize();

956
  //num_fnames = get_fnames(filenames, fnames, MAX_FNAMES);
957
958
959
960
961

  if ( num_fnames == 0 )
    filename = filenames;
  else
    {
962
      int i;
963
      for ( i = 0; i < num_fnames; ++i ) printf("fnames: %d %s\n", i, fnames[i]);
964
965
966
      filename = fnames[0];
    }

Uwe Schulzweida's avatar
Uwe Schulzweida committed
967
968
969
970
971
972
  filetype = getFiletype(filename, &byteorder);

  if ( filetype < 0 ) return (filetype);

  streamID = streamOpen(filename, "r", filetype);

Uwe Schulzweida's avatar
Uwe Schulzweida committed
973
974
975
976
  if ( streamID >= 0 )
    {
      streamptr = stream_to_pointer(streamID);
      streamptr->byteorder = byteorder;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
977
978
979
980
981
982
983
984
985

      if ( num_fnames > 0 )
	{
	  int i;
	  streamptr->nfiles = num_fnames;
	  streamptr->fnames = (char **) malloc(num_fnames*sizeof(char *));
	  for ( i = 0; i < num_fnames; ++i )
	    streamptr->fnames[i] = fnames[i];
	}
Uwe Schulzweida's avatar
Uwe Schulzweida committed
986
    }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
987
988
989
990
991
992
993
994
995

  return (streamID);
}


int streamOpenAppend(const char *filename)
{
  int filetype, byteorder;
  int streamID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
996
  stream_t *streamptr;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
997

998
999
  cdiInitialize();

Uwe Schulzweida's avatar
Uwe Schulzweida committed
1000
1001
1002
1003
1004
1005
  filetype = getFiletype(filename, &byteorder);

  if ( filetype < 0 ) return (filetype);

  streamID = streamOpenA(filename, "a", filetype);

1006
1007
1008
1009
1010
  if ( streamID >= 0 )
    {
      streamptr = stream_to_pointer(streamID);
      streamptr->byteorder = byteorder;
    }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1011
1012
1013
1014
1015
1016

  return (streamID);
}

/*
@Function  streamOpenWrite
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1017
@Title     Create a new dataset
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1018

Uwe Schulzweida's avatar
Uwe Schulzweida committed
1019
@Prototype int streamOpenWrite(const char *path, int filetype)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1020
@Parameter
Deike Kleberg's avatar
Deike Kleberg committed
1021
    @Item  path      The name of the new dataset.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1022
    @Item  filetype  The type of the file format, one of the set of predefined CDI file format types.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1023
                     The valid CDI file format types are @func{FILETYPE_GRB}, @func{FILETYPE_GRB2}, @func{FILETYPE_NC},
Deike Kleberg's avatar
Deike Kleberg committed
1024
                     @func{FILETYPE_NC2}, @func{FILETYPE_NC4}, @func{FILETYPE_NC4C}, @func{FILETYPE_SRV},
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1025
                     @func{FILETYPE_EXT} and @func{FILETYPE_IEG}.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1026
1027

@Description
1028
The function @func{streamOpenWrite} creates a new datset.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1029
@Result
1030
Upon successful completion @func{streamOpenWrite} returns an identifier to the
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1031
1032
1033
1034
open stream. Otherwise, a negative number with the error status is returned.

@Errors
@List
Deike Kleberg's avatar
Deike Kleberg committed
1035
1036
1037
1038
   @Item  CDI_ESYSTEM     Operating system error.
   @Item  CDI_EINVAL      Invalid argument.
   @Item  CDI_EUFILETYPE  Unsupported file type.
   @Item  CDI_ELIBNAVAIL  Library support not compiled in.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1039
1040
1041
@EndList

@Example
1042
Here is an example using @func{streamOpenWrite} to create a new netCDF file
1043
named @func{foo.nc} for writing:
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1044
1045

@Source
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1046
#include "cdi.h"
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
   ...
int streamID;
   ...
streamID = streamOpenWrite("foo.nc", FILETYPE_NC);
if ( streamID < 0 ) handle_error(streamID);
   ...
@EndSource
@EndFunction
*/
int streamOpenWrite(const char *filename, int filetype)
{
1058
1059
  cdiInitialize();

Uwe Schulzweida's avatar
Uwe Schulzweida committed
1060
1061
1062
  return (streamOpen(filename, "w", filetype));
}

1063
void
1064
cdiStreamCloseDefaultDelegate(stream_t *streamptr, int recordBufIsToBeDeleted)
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
{
  int fileID   = streamptr->fileID;
  int filetype = streamptr->filetype;
  if ( fileID == CDI_UNDEFID )
    Warning("File %s not open!", streamptr->filename);
  else
    switch (filetype)
      {
#if  defined  (HAVE_LIBGRIB)
      case FILETYPE_GRB:
      case FILETYPE_GRB2:
        {
          gribClose(fileID);
1078
1079
          if (recordBufIsToBeDeleted)
            gribContainersDelete(streamptr);
1080
1081
1082
1083
1084
1085
1086
          break;
        }
#endif
#if  defined  (HAVE_LIBSERVICE)
      case FILETYPE_SRV:
        {
          fileClose(fileID);
1087
1088
          if (recordBufIsToBeDeleted)
            srvDelete(streamptr->record->srvp);
1089
1090
1091
1092
1093
1094
1095
          break;
        }
#endif
#if  defined  (HAVE_LIBEXTRA)
      case FILETYPE_EXT:
        {
          fileClose(fileID);
1096
1097
          if (recordBufIsToBeDeleted)
            extDelete(streamptr->record->extp);
1098
1099
1100
1101
1102
1103
1104
          break;
        }
#endif
#if  defined  (HAVE_LIBIEG)
      case FILETYPE_IEG:
        {
          fileClose(fileID);
1105
1106
          if (recordBufIsToBeDeleted)
            iegDelete(streamptr->record->iegp);
1107
1108
1109
1110
1111
1112
1113
1114
1115
          break;
        }
#endif
#if  defined  (HAVE_LIBNETCDF)
      case FILETYPE_NC:
      case FILETYPE_NC2:
      case FILETYPE_NC4:
      case FILETYPE_NC4C:
        {
1116
          cdfClose(fileID);
1117
1118
1119
1120
1121
          break;
        }
#endif
      default:
        {
1122
          Error("%s support not compiled in (fileID = %d)!", strfiletype(filetype), fileID);
1123
1124
1125
1126
1127
1128
          break;
        }
      }
}


Uwe Schulzweida's avatar
Uwe Schulzweida committed
1129
1130
/*
@Function  streamClose
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1131
@Title     Close an open dataset
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1132
1133
1134

@Prototype  void streamClose(int streamID)
@Parameter
Deike Kleberg's avatar
Deike Kleberg committed
1135
    @Item  streamID  Stream ID, from a previous call to @fref{streamOpenRead} or @fref{streamOpenWrite}.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1136
1137

@Description
1138
The function @func{streamClose} closes an open dataset.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1139
1140
1141
1142
1143
1144
1145

@EndFunction
*/
void streamClose(int streamID)
{
  int index;
  int vlistID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1146
  stream_t *streamptr;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1147
1148

  streamptr = stream_to_pointer(streamID);
1149

1150
  stream_check_ptr(__func__, streamptr);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1151
1152

  if ( CDI_Debug )
Thomas Jahns's avatar
Thomas Jahns committed
1153
    Message("streamID = %d filename = %s", streamID, streamptr->filename);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1154

1155
  vlistID  = streamptr->vlistID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1156

1157
  void (*streamCloseDelegate)(stream_t *streamptr, int recordBufIsToBeDeleted)
1158
1159
    = (void (*)(stream_t *, int))
    namespaceSwitchGet(NSSWITCH_STREAM_CLOSE_BACKEND).func;
1160

1161
  if ( streamptr->filetype != -1 ) streamCloseDelegate(streamptr, 1);
1162

1163
  if ( streamptr->record )
1164
1165
1166
    {
      if ( streamptr->record->buffer )
        free(streamptr->record->buffer);
1167

1168
1169
      free(streamptr->record);
    }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1170

Uwe Schulzweida's avatar
Uwe Schulzweida committed
1171
1172
  streamptr->filetype = 0;
  if ( streamptr->filename ) free(streamptr->filename);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1173

Uwe Schulzweida's avatar
Uwe Schulzweida committed
1174
  for ( index = 0; index < streamptr->nvars; index++ )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1175
    {
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1176
1177
1178
1179
      if ( streamptr->vars[index].level )
	free(streamptr->vars[index].level);
      if ( streamptr->vars[index].lindex )
	free(streamptr->vars[index].lindex);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1180
    }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1181
  free(streamptr->vars);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1182

Uwe Schulzweida's avatar
Uwe Schulzweida committed
1183
  for ( index = 0; index < streamptr->ntsteps; ++index )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1184
    {
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1185
1186
1187
1188
      if ( streamptr->tsteps[index].records )
	free(streamptr->tsteps[index].records);
      if ( streamptr->tsteps[index].recIDs )
	free(streamptr->tsteps[index].recIDs);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1189
    }
1190

Uwe Schulzweida's avatar
Uwe Schulzweida committed
1191
  if ( streamptr->tsteps ) free(streamptr->tsteps);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1192

Uwe Schulzweida's avatar
Uwe Schulzweida committed
1193
1194
1195
1196
1197
1198
1199
1200
  if ( streamptr->nfiles > 0 )
    {
      for ( index = 0; index < streamptr->nfiles; ++index )
	free(streamptr->fnames[index]);

      free(streamptr->fnames);
    }

Uwe Schulzweida's avatar
Uwe Schulzweida committed
1201
1202
  if ( vlistID != -1 )
    {
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1203
1204
1205
1206
1207
1208
      if ( streamptr->filemode != 'w' )
	if ( vlistInqTaxis(vlistID) != -1 )
	  {
	    taxisDestroy(vlistInqTaxis(vlistID));
	  }

1209
      vlistDestroy(vlistID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1210
    }
Uwe Schulzweida's avatar
bug fix    
Uwe Schulzweida committed
1211
1212

  stream_delete_entry(streamptr);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1213
1214
}

Thomas Jahns's avatar
Thomas Jahns committed
1215
void cdiStreamSync_(stream_t *streamptr)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1216
{
Thomas Jahns's avatar
Thomas Jahns committed
1217
1218
1219
1220
  int fileID   = streamptr->fileID;
  int filetype = streamptr->filetype;
  int vlistID  = streamptr->