cdf.c 5.48 KB
Newer Older
1 2
#ifdef  HAVE_CONFIG_H
#include "config.h"
Uwe Schulzweida's avatar
Uwe Schulzweida committed
3 4 5 6 7 8
#endif

#include <ctype.h>

#include "cdf.h"
#include "cdi.h"
9
#include "cdi_int.h"
Uwe Schulzweida's avatar
Uwe Schulzweida committed
10 11 12 13 14
#include "cdf_int.h"


const char *cdfLibraryVersion(void)
{
15
#ifdef  HAVE_LIBNETCDF
16
  return nc_inq_libvers();
Uwe Schulzweida's avatar
Uwe Schulzweida committed
17
#else
18
  return "library undefined";
Uwe Schulzweida's avatar
Uwe Schulzweida committed
19 20 21
#endif
}

22 23
#ifdef  HAVE_H5GET_LIBVERSION
#ifdef  __cplusplus
Uwe Schulzweida's avatar
Uwe Schulzweida committed
24 25 26
extern "C" {
#endif
  int H5get_libversion(unsigned *, unsigned *, unsigned *);
27
#ifdef  __cplusplus
Uwe Schulzweida's avatar
Uwe Schulzweida committed
28 29 30
}
#endif
#endif
Uwe Schulzweida's avatar
Uwe Schulzweida committed
31 32 33

const char *hdfLibraryVersion(void)
{
34
#ifdef  HAVE_H5GET_LIBVERSION
Uwe Schulzweida's avatar
Uwe Schulzweida committed
35
  static char hdf_libvers[256];
36 37 38 39 40 41
  static int linit = 0;
  if (!linit)
    {
      linit = 1;
      unsigned majnum, minnum, relnum;
      H5get_libversion(&majnum, &minnum, &relnum);
42
#ifdef  HAVE_NC4HDF5_THREADSAFE
43
      sprintf(hdf_libvers, "%u.%u.%u threadsafe", majnum, minnum, relnum);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
44
#else
45
      sprintf(hdf_libvers, "%u.%u.%u", majnum, minnum, relnum);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
46
#endif
47 48
    }

49
  return hdf_libvers;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
50
#else
51
  return "library undefined";
Uwe Schulzweida's avatar
Uwe Schulzweida committed
52 53 54
#endif
}

Uwe Schulzweida's avatar
Uwe Schulzweida committed
55 56 57 58 59 60 61 62 63

int CDF_Debug   = 0;    /* If set to 1, debugging           */


void cdfDebug(int debug)
{
  CDF_Debug = debug;

  if ( CDF_Debug )
64
    Message("debug level %d", debug);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
65 66
}

67
#ifdef  HAVE_LIBNETCDF
Uwe Schulzweida's avatar
Uwe Schulzweida committed
68
static
Uwe Schulzweida's avatar
Uwe Schulzweida committed
69 70 71
void cdfComment(int ncid)
{
  static char comment[256] = "Climate Data Interface version ";
Uwe Schulzweida's avatar
Uwe Schulzweida committed
72
  static bool init = false;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
73 74 75

  if ( ! init )
    {
Uwe Schulzweida's avatar
Uwe Schulzweida committed
76
      init = true;
Thomas Jahns's avatar
Thomas Jahns committed
77
      const char *libvers = cdiLibraryVersion();
Uwe Schulzweida's avatar
Uwe Schulzweida committed
78

Uwe Schulzweida's avatar
Uwe Schulzweida committed
79
      if ( ! isdigit((int) *libvers) )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
80 81
	strcat(comment, "??");
      else
Uwe Schulzweida's avatar
Uwe Schulzweida committed
82
	strcat(comment, libvers);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
83
      strcat(comment, " (https://mpimet.mpg.de/cdi)");
Uwe Schulzweida's avatar
Uwe Schulzweida committed
84 85 86 87
    }

  cdf_put_att_text(ncid, NC_GLOBAL, "CDI", strlen(comment), comment);
}
88
#endif
Uwe Schulzweida's avatar
Uwe Schulzweida committed
89

Thomas Jahns's avatar
Thomas Jahns committed
90
static int cdfOpenFile(const char *filename, const char *mode, int *filetype)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
91 92
{
  int ncid = -1;
93
#ifdef  HAVE_LIBNETCDF
94
  int fmode = tolower(*mode);
95
  int writemode = NC_CLOBBER;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
96
  int readmode = NC_NOWRITE;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
97 98 99 100 101

  if ( filename == NULL )
    ncid = CDI_EINVAL;
  else
    {
102
      switch (fmode)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
103 104
	{
	case 'r':
105
          {
106
            const int status = cdf_open(filename, readmode, &ncid);
107 108 109 110 111 112 113
            if ( status > 0 && ncid < 0 ) ncid = CDI_ESYSTEM;
#ifdef  HAVE_NETCDF4
            else
              {
                int format;
                (void) nc_inq_format(ncid, &format);
                if ( format == NC_FORMAT_NETCDF4_CLASSIC )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
114
                  *filetype = CDI_FILETYPE_NC4C;
115
              }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
116
#endif
Uwe Schulzweida's avatar
Uwe Schulzweida committed
117
          }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
118 119
	  break;
	case 'w':
120
#ifdef  NC_64BIT_OFFSET
121
	  if      ( *filetype == CDI_FILETYPE_NC2  ) writemode |= NC_64BIT_OFFSET;
122
#endif
Uwe Schulzweida's avatar
Uwe Schulzweida committed
123 124 125
#ifdef  NC_64BIT_DATA
	  if      ( *filetype == CDI_FILETYPE_NC5  ) writemode |= NC_64BIT_DATA;
#endif
126
#ifdef  HAVE_NETCDF4
127 128
	  if      ( *filetype == CDI_FILETYPE_NC4  ) writemode |= NC_NETCDF4;
	  else if ( *filetype == CDI_FILETYPE_NC4C ) writemode |= NC_NETCDF4 | NC_CLASSIC_MODEL;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
129 130
#endif
	  cdf_create(filename, writemode, &ncid);
131
	  if ( CDO_version_info ) cdfComment(ncid);
132
          cdf_put_att_text(ncid, NC_GLOBAL, "Conventions", 6, "CF-1.6");
Uwe Schulzweida's avatar
Uwe Schulzweida committed
133 134 135 136 137 138 139 140 141 142
	  break;
	case 'a':
	  cdf_open(filename, NC_WRITE, &ncid);
	  break;
	default:
	  ncid = CDI_EINVAL;
	}
    }
#endif

143
  return ncid;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
144 145 146
}


147
int cdfOpen(const char *filename, const char *mode, int filetype)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
148 149
{
  int fileID = -1;
150
  bool open_file = true;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
151 152

  if ( CDF_Debug )
153
    Message("Open %s with mode %c", filename, *mode);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
154

155 156
#ifdef  HAVE_LIBNETCDF
#ifndef  NC_64BIT_OFFSET
Uwe Schulzweida's avatar
Uwe Schulzweida committed
157
  if ( filetype == CDI_FILETYPE_NC2 ) open_file = false;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
158
#endif
159
#ifndef  NC_64BIT_DATA
Uwe Schulzweida's avatar
Uwe Schulzweida committed
160
  if ( filetype == CDI_FILETYPE_NC5 ) open_file = false;
161
#endif
Uwe Schulzweida's avatar
Uwe Schulzweida committed
162 163
#endif

164 165 166
  if ( open_file )
    {
      fileID = cdfOpenFile(filename, mode, &filetype);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
167

168
      if ( CDF_Debug )
169
        Message("File %s opened with id %d", filename, fileID);
170 171 172 173 174
    }
  else
    {
      fileID = CDI_ELIBNAVAIL;
    }
175

176
  return fileID;
177 178
}

179 180 181 182
static
int cdf4CheckLibVersions(void)
{
  int status = 0;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
183
#ifdef HAVE_NETCDF4
184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208
#ifdef HAVE_H5GET_LIBVERSION
  static int checked = 0;
  if (!checked)
    {
      checked = 1;
      unsigned majnum, minnum, relnum;

      sscanf(nc_inq_libvers(), "%u.%u.%u", &majnum, &minnum, &relnum);
      //printf("netCDF %u.%u.%u\n", majnum, minnum, relnum);
      const unsigned ncmaxver = 4 * 1000000 + 4 * 1000;
      const unsigned nclibver = majnum * 1000000 + minnum * 1000 + relnum;

      if (nclibver <= ncmaxver)
        {
          H5get_libversion(&majnum, &minnum, &relnum);
          const unsigned hdf5maxver = 1 * 1000000 + 10 * 1000;
          const unsigned hdf5libver = majnum * 1000000 + minnum * 1000 + relnum;

          if (hdf5libver >= hdf5maxver)
            {
              fprintf(stderr, "NetCDF library 4.4.0 or earlier, combined with libhdf5 1.10.0 or greater not supported!\n");
              status = 1;
            }
        }
    }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
209
#endif
210 211 212
#endif
  return status;
}
213

214
int cdf4Open(const char *filename, const char *mode, int *filetype)
215 216
{
  int fileID = -1;
217
  bool open_file = false;
218

219
  if ( CDF_Debug ) Message("Open %s with mode %c", filename, *mode);
220

221
#ifdef  HAVE_NETCDF4
222
  open_file = true;
223 224
#endif

225 226
  if ( open_file )
    {
227 228 229 230 231 232 233 234 235
      if (cdf4CheckLibVersions() == 0)
        {
          fileID = cdfOpenFile(filename, mode, filetype);
          if ( CDF_Debug ) Message("File %s opened with id %d", filename, fileID);
        }
      else
        {
          fileID = CDI_EUFTYPE;
        }
236 237 238 239 240
    }
  else
    {
      fileID = CDI_ELIBNAVAIL;
    }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
241

242
  return fileID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
243 244 245
}


Thomas Jahns's avatar
Thomas Jahns committed
246
static void cdfCloseFile(int fileID)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
247
{
248
#ifdef  HAVE_LIBNETCDF
Uwe Schulzweida's avatar
Uwe Schulzweida committed
249 250 251 252 253 254 255 256
  cdf_close(fileID);
#endif
}

void cdfClose(int fileID)
{
  cdfCloseFile(fileID);
}
257 258 259 260 261 262 263 264 265
/*
 * Local Variables:
 * c-file-style: "Java"
 * c-basic-offset: 2
 * indent-tabs-mode: nil
 * show-trailing-whitespace: t
 * require-trailing-newline: t
 * End:
 */