stream.c 54.2 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
#define  MAX_FNAMES  3

33
extern resOps streamOps;
Deike Kleberg's avatar
Deike Kleberg committed
34

35

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

Thomas Jahns's avatar
Thomas Jahns committed
39
40
static void
cdiPrintDefaults(void)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
41
{
42
43
44
45
  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
46
47
48
49
50
}


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

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

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

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

59
  if ( level == 1 || (level & 16) )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
    {
#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();
    }
}


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
123
124
125
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
126
127
128
129
#undef  IsBigendian
#define IsBigendian()  ( u_byteorder.c[sizeof(long) - 1] )


130
131
static
int getByteorder(int byteswap)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
{
  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);
}


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

  fileID = fileOpen(filename, "r");

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

Uwe Schulzweida's avatar
Uwe Schulzweida committed
171
  if ( fileRead(fileID, buffer, 8) != 8 ) return (CDI_EUFTYPE);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
172
173
174

  fileRewind(fileID);

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

  fileClose(fileID);

  *byteorder = getByteorder(swap);

  return (filetype);
}


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

	  if ( nfiles == 0 )
	    {
	      FILE *fp;
	      fp = fopen(pch, "r");
296
	      if ( fp == NULL ) Error("Open failed on %s", pch);
297
298

	      if ( CDI_Debug )
299
		Message("Reading file names from %s", pch);
300
301
302
303
304
305
306
307

	      rewind(fp);

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

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

318
319
	      fclose(fp);

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

326
327
	      strcpy(xline, pch);
	      for ( i = 0; i < len; i++ ) if ( xline[i] == ',' ) xline[i] = 0;
328

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

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

349
350
351
352
	  strcpy(command, "ls ");
	  strcat(command, pch);

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

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

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

  num_fnames = nfiles;
375

376
377
378
  return (num_fnames);
}

Uwe Schulzweida's avatar
Uwe Schulzweida committed
379
380
381
382
383
384
/*
@Function  streamInqFiletype
@Title     Get the filetype

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

@Description
388
The function @func{streamInqFiletype} returns the filetype of a stream.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
389
390

@Result
391
@func{streamInqFiletype} returns the type of the file format,
Uwe Schulzweida's avatar
Uwe Schulzweida committed
392
one of the set of predefined CDI file format types.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
393
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
394
@func{FILETYPE_NC4}, @func{FILETYPE_NC4C}, @func{FILETYPE_SRV}, @func{FILETYPE_EXT} and @func{FILETYPE_IEG}.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
395
396
397
398
399

@EndFunction
*/
int streamInqFiletype(int streamID)
{
Uwe Schulzweida's avatar
Uwe Schulzweida committed
400
  stream_t *streamptr;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
401
402

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

404
  stream_check_ptr(__func__, streamptr);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
405

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


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);
}

427
428
429
430
431
432
/*
@Function  streamDefByteorder
@Title     Define the byte order

@Prototype void streamDefByteorder(int streamID, int byteorder)
@Parameter
433
    @Item  streamID  Stream ID, from a previous call to @fref{streamOpenWrite}.
434
435
436
437
438
439
440
441
442
    @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
443
444
void streamDefByteorder(int streamID, int byteorder)
{
Thomas Jahns's avatar
Thomas Jahns committed
445
  int filetype;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
446
  stream_t *streamptr;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
447

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

450
  stream_check_ptr(__func__, streamptr);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
451

452
453
  if ( reshGetStatus ( streamID, &streamOps ) == CLOSED )
    {
454
      Warning("%s", "Operation not executed.");
455
456
457
      return;
    }

Uwe Schulzweida's avatar
Uwe Schulzweida committed
458
459
  streamptr->byteorder = byteorder;
  filetype = streamptr->filetype;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
460
461
462
463
464
465

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

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

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

	break;
      }
#endif
    }
}

493
494
495
496
497
498
/*
@Function  streamInqByteorder
@Title     Get the byte order

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

@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
511
512
int streamInqByteorder(int streamID)
{
Uwe Schulzweida's avatar
Uwe Schulzweida committed
513
  stream_t *streamptr;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
514
515

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

517
  stream_check_ptr(__func__, streamptr);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
518

Uwe Schulzweida's avatar
Uwe Schulzweida committed
519
  return (streamptr->byteorder);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
520
521
522
523
524
}


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

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


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

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

541
  stream_check_ptr(__func__, streamptr);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
542
543

  return (streamptr->filename);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
544
545
}

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

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

555
  stream_check_ptr(__func__, streamptr);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
556

Uwe Schulzweida's avatar
Uwe Schulzweida committed
557
  ntsteps = streamptr->ntsteps;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
558
559
560
561

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

Uwe Schulzweida's avatar
Uwe Schulzweida committed
562
  ntsteps = streamptr->ntsteps;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
563
564
565
566

  return (ntsteps);
}

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

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

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

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

  if ( status == 0 )
    {
630
      vlistID = streamptr->vlistID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
631
632
      taxisID = vlistInqTaxis(vlistID);
      if ( taxisID != -1 )
633
634
635
636
637
638
639
        {
          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
640
641
642
643
644
    }

  return (status);
}

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


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

743
744
745
746
747
748
749
  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,
750
751
                              int filetype, stream_t *streamptr, int recordBufIsToBeCreated)
      = (int (*)(const char *, const char *, int, stream_t *, int))
752
      namespaceSwitchGet(NSSWITCH_STREAM_OPEN_BACKEND).func;
753

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

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

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

Uwe Schulzweida's avatar
Uwe Schulzweida committed
769
770
771
772
      streamptr->filetype = filetype;
      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
831
  streamptr->filetype = filetype;
  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);
832

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

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

  switch (filetype)
    {
#if  defined  (HAVE_LIBGRIB)
    case FILETYPE_GRB:
Uwe Schulzweida's avatar
Uwe Schulzweida committed
845
    case FILETYPE_GRB2:
Uwe Schulzweida's avatar
Uwe Schulzweida committed
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
875
      {
        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);
876
	streamptr->ncmode = 2;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
877
878
879
880
881
	break;
      }
    case FILETYPE_NC2:
      {
	fileID = cdfOpen64(filename, filemode);
882
	streamptr->ncmode = 2;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
883
884
	break;
      }
885
    case FILETYPE_NC4:
Deike Kleberg's avatar
Deike Kleberg committed
886
    case FILETYPE_NC4C:
887
      {
Deike Kleberg's avatar
Deike Kleberg committed
888
	fileID = cdf4Open(filename, filemode, &filetype);
889
	streamptr->ncmode = 2;
890
891
	break;
      }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
892
893
894
#endif
    default:
      {
895
	if ( CDI_Debug ) Message("%s support not compiled in!", strfiletype(filetype));
Uwe Schulzweida's avatar
Uwe Schulzweida committed
896
897
898
899
900
901
902
	return (CDI_ELIBNAVAIL);
      }
    }

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

  return (streamID);
}

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

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

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

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

@Errors
@List
Deike Kleberg's avatar
Deike Kleberg committed
925
926
927
928
   @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
929
930
931
@EndList

@Example
932
933
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
934
935

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

955
956
  cdiInitialize();

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

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

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

  if ( filetype < 0 ) return (filetype);

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

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

      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
987
    }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
988
989
990
991
992
993
994
995
996

  return (streamID);
}


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

999
1000
  cdiInitialize();

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

  if ( filetype < 0 ) return (filetype);

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

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

  return (streamID);
}

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

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

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

@Errors
@List
Deike Kleberg's avatar
Deike Kleberg committed
1036
1037
1038
1039
   @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
1040
1041
1042
@EndList

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

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

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

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


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

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

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

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

  streamptr = stream_to_pointer(streamID);
1150

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

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

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

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

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

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

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

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

Uwe Schulzweida's avatar
Uwe Schulzweida committed
1175
  for ( index = 0; index < streamptr->nvars; index++ )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1176
    {
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1177
1178
1179
1180
      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
1181
    }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1182
  free(streamptr->vars);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1183

Uwe Schulzweida's avatar
Uwe Schulzweida committed
1184
  for ( index = 0; index < streamptr->ntsteps; ++index )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1185
    {
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1186
1187
1188
1189
      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
1190
    }
1191

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

Uwe Schulzweida's avatar
Uwe Schulzweida committed
1194
1195
1196
1197
1198
1199
1200
1201
  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
1202
1203
  if ( vlistID != -1 )
    {
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1204
1205
1206
1207
1208
1209
      if ( streamptr->filemode != 'w' )
	if ( vlistInqTaxis(vlistID) != -1 )
	  {
	    taxisDestroy(vlistInqTaxis(vlistID));
	  }

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

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

Thomas Jahns's avatar
Thomas Jahns committed
1216
void cdiStreamSync_(stream_t *streamptr)