extralib.c 11.5 KB
Newer Older
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1
#include <stdio.h>
2
#include <stdlib.h>
Uwe Schulzweida's avatar
Uwe Schulzweida committed
3 4 5 6 7 8 9 10
#include <string.h>
#include <ctype.h>

#include "dmemory.h"
#include "extra.h"
#include "error.h"
#include "file.h"
#include "binary.h"
11
#include "exse.h"
Uwe Schulzweida's avatar
Uwe Schulzweida committed
12 13 14
#include "swap.h"


15 16 17
enum {
  EXT_HEADER_LEN = 4,
};
Uwe Schulzweida's avatar
Uwe Schulzweida committed
18

19 20 21 22 23
union EXT_HEADER
{
  INT32 i32[EXT_HEADER_LEN];
  INT64 i64[EXT_HEADER_LEN];
};
Uwe Schulzweida's avatar
Uwe Schulzweida committed
24

Uwe Schulzweida's avatar
Uwe Schulzweida committed
25 26 27
static int initExtLib       = 0;
static int extDefaultPrec   = 0;
static int extDefaultNumber = EXT_REAL;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
28 29


30
// A version string.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
31
#undef  LIBVERSION
32
#define LIBVERSION      1.4.2
Uwe Schulzweida's avatar
Uwe Schulzweida committed
33 34
#define XSTRING(x)	#x
#define STRING(x)	XSTRING(x)
35
static const char ext_libvers[] = STRING(LIBVERSION);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
36 37 38

const char *extLibraryVersion(void)
{
39
  return ext_libvers;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
40 41 42
}


43
static int EXT_Debug = 0;    // If set to 1, debugging
Uwe Schulzweida's avatar
Uwe Schulzweida committed
44 45 46 47


void extDebug(int debug)
{
48
  if (debug) Message("debug level %d", debug);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
49 50 51 52
  EXT_Debug = debug;
}


53 54
static
void extLibInit()
Uwe Schulzweida's avatar
Uwe Schulzweida committed
55
{
Oliver Heidmann's avatar
Oliver Heidmann committed
56
  const char *envName = "EXT_PRECISION";
Uwe Schulzweida's avatar
Uwe Schulzweida committed
57

58
  char *envString = getenv(envName);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
59 60
  if ( envString )
    {
Uwe Schulzweida's avatar
Uwe Schulzweida committed
61
      if ( strlen(envString) == 2  )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
62
	{
Uwe Schulzweida's avatar
Uwe Schulzweida committed
63
	  switch ( tolower((int) envString[0]) )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
64
	    {
Uwe Schulzweida's avatar
Uwe Schulzweida committed
65
	    case 'r':
Uwe Schulzweida's avatar
Uwe Schulzweida committed
66
	      {
Uwe Schulzweida's avatar
Uwe Schulzweida committed
67
		extDefaultNumber = EXT_REAL;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
68
		switch ( (int) envString[1] )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
69
		  {
70 71
		  case '4': extDefaultPrec = EXSE_SINGLE_PRECISION; break;
		  case '8': extDefaultPrec = EXSE_DOUBLE_PRECISION; break;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
72
		  default:
73
		    Message("Invalid digit in %s: %s", envName, envString);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
74
		  }
75
		break;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
76
	      }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
77
	    case 'c':
Uwe Schulzweida's avatar
Uwe Schulzweida committed
78
	      {
Uwe Schulzweida's avatar
Uwe Schulzweida committed
79
		extDefaultNumber = EXT_COMP;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
80
		switch ( (int) envString[1] )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
81
		  {
82 83
		  case '4': extDefaultPrec = EXSE_SINGLE_PRECISION; break;
		  case '8': extDefaultPrec = EXSE_DOUBLE_PRECISION; break;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
84
		  default:
85
		    Message("Invalid digit in %s: %s", envName, envString);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
86
		  }
87
		break;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
88 89
	      }
	    default:
90 91 92 93 94
              {
                Message("Invalid character in %s: %s", envName, envString);
                break;
              }
            }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
95 96 97 98 99 100
	}
    }

  initExtLib = 1;
}

Uwe Schulzweida's avatar
Uwe Schulzweida committed
101 102
static
void extInit(extrec_t *extp)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
103 104 105
{
  extp->checked    = 0;
  extp->byteswap   = 0;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
106 107
  extp->prec       = 0;
  extp->number     = extDefaultNumber;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
108 109 110 111 112 113
  extp->datasize   = 0;
  extp->buffersize = 0;
  extp->buffer     = NULL;
}


Uwe Schulzweida's avatar
Uwe Schulzweida committed
114
void *extNew(void)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
115 116 117
{
  if ( ! initExtLib ) extLibInit();

118
  extrec_t *extp = (extrec_t *) Malloc(sizeof(extrec_t));
Uwe Schulzweida's avatar
Uwe Schulzweida committed
119 120 121

  extInit(extp);

122
  return (void*)extp;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
123 124 125
}


Uwe Schulzweida's avatar
Uwe Schulzweida committed
126
void extDelete(void *ext)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
127
{
Uwe Schulzweida's avatar
Uwe Schulzweida committed
128
  extrec_t *extp = (extrec_t *) ext;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
129 130 131

  if ( extp )
    {
132 133
      if ( extp->buffer ) Free(extp->buffer);
      Free(extp);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
134 135 136 137 138 139
    }
}


int extCheckFiletype(int fileID, int *swap)
{
140
  size_t fact = 0;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
141 142 143 144
  size_t data =  0;
  size_t dimxy = 0;
  unsigned char buffer[40], *pbuf;

Uwe Schulzweida's avatar
Uwe Schulzweida committed
145
  if ( fileRead(fileID, buffer, 4) != 4 ) return 0;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
146

147 148
  const size_t blocklen  = (size_t) get_UINT32(buffer);
  const size_t sblocklen = (size_t) get_SUINT32(buffer);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
149

150
  if ( EXT_Debug ) Message("blocklen = %d sblocklen = %d", blocklen, sblocklen);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
151

152
  // clang-format off
Uwe Schulzweida's avatar
Uwe Schulzweida committed
153 154 155 156
  if ( blocklen == 16 )
    {
     *swap = 0;
      fact = blocklen/4;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
157
      if ( fileRead(fileID, buffer, blocklen+8) != blocklen+8 ) return 0;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
158 159 160 161 162 163 164
      pbuf = buffer+3*fact;      dimxy = (size_t) get_UINT32(pbuf);
      pbuf = buffer+blocklen+4;  data  = (size_t) get_UINT32(pbuf);
    }
  else if ( blocklen == 32 )
    {
     *swap = 0;
      fact = blocklen/4;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
165
      if ( fileRead(fileID, buffer, blocklen+8) != blocklen+8 ) return 0;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
166 167 168 169 170 171 172
      pbuf = buffer+3*fact;      dimxy = (size_t) get_UINT64(pbuf);
      pbuf = buffer+blocklen+4;  data  = (size_t) get_UINT32(pbuf);
    }
  else if ( sblocklen == 16 )
    {
     *swap = 1;
      fact = sblocklen/4;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
173
      if ( fileRead(fileID, buffer, sblocklen+8) != sblocklen+8 ) return 0;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
174 175 176 177 178 179 180
      pbuf = buffer+3*fact;       dimxy = (size_t) get_SUINT32(pbuf);
      pbuf = buffer+sblocklen+4;  data  = (size_t) get_SUINT32(pbuf);
    }
  else if ( sblocklen == 32 )
    {
     *swap = 1;
      fact = sblocklen/4;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
181
      if ( fileRead(fileID, buffer, sblocklen+8) != sblocklen+8 ) return 0;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
182 183 184
      pbuf = buffer+3*fact;       dimxy = (size_t) get_SUINT64(pbuf);
      pbuf = buffer+sblocklen+4;  data  = (size_t) get_SUINT32(pbuf);
    }
185
  // clang-format on
Uwe Schulzweida's avatar
Uwe Schulzweida committed
186 187 188 189 190

  fileRewind(fileID);

  if ( EXT_Debug )
    {
191 192
      Message("swap = %d fact = %d", *swap, fact);
      Message("dimxy = %lu data = %lu", dimxy, data);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
193 194
    }

195
  const int found = data && (dimxy*fact == data || dimxy*fact*2 == data);
196
  return found;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
197 198 199
}


Uwe Schulzweida's avatar
Uwe Schulzweida committed
200
int extInqHeader(void *ext, int *header)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
201
{
Uwe Schulzweida's avatar
Uwe Schulzweida committed
202
  extrec_t *extp = (extrec_t *) ext;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
203

204
  for (int i = 0; i < EXT_HEADER_LEN; i++) header[i] = extp->header[i];
205

206
  if ( EXT_Debug ) Message("datasize = %zu", extp->datasize);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
207

208
  return 0;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
209 210 211
}


Uwe Schulzweida's avatar
Uwe Schulzweida committed
212
int extDefHeader(void *ext, const int *header)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
213
{
Uwe Schulzweida's avatar
Uwe Schulzweida committed
214
  extrec_t *extp = (extrec_t *) ext;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
215

216
  for (int i = 0; i < EXT_HEADER_LEN; i++) extp->header[i] = header[i];
217

218
  extp->datasize = (size_t)header[3];
Uwe Schulzweida's avatar
Uwe Schulzweida committed
219
  if ( extp->number == EXT_COMP ) extp->datasize *= 2;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
220

221
  if (EXT_Debug) Message("datasize = %zu", extp->datasize);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
222

223
  return 0;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
224 225
}

226 227
static
int extInqData(extrec_t *extp, int prec, void *data)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
228 229
{
  int ierr = 0;
230 231 232 233
  const int byteswap = extp->byteswap;
  const size_t datasize = extp->datasize;
  void *buffer = extp->buffer;
  const int rprec = extp->prec;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
234

Uwe Schulzweida's avatar
Uwe Schulzweida committed
235
  switch ( rprec )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
236
    {
237
    case EXSE_SINGLE_PRECISION:
Uwe Schulzweida's avatar
Uwe Schulzweida committed
238
      {
Uwe Schulzweida's avatar
Uwe Schulzweida committed
239
	if ( sizeof(FLT32) == 4 )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
240 241 242
	  {
	    if ( byteswap ) swap4byte(buffer, datasize);

Uwe Schulzweida's avatar
Uwe Schulzweida committed
243
	    if ( rprec == prec )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
244
	      memcpy(data, buffer, datasize*sizeof(FLT32));
Uwe Schulzweida's avatar
Uwe Schulzweida committed
245
	    else
Uwe Schulzweida's avatar
Uwe Schulzweida committed
246
	      for (size_t i = 0; i < datasize; ++i)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
247 248 249 250
		((double *) data)[i] = (double) ((float *) buffer)[i];
	  }
	else
	  {
251
	    Error("not implemented for %d byte float", sizeof(FLT32));
252
	  }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
253 254
	break;
      }
255
    case EXSE_DOUBLE_PRECISION:
Uwe Schulzweida's avatar
Uwe Schulzweida committed
256
	if ( sizeof(FLT64) == 8 )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
257 258 259
	  {
	    if ( byteswap ) swap8byte(buffer, datasize);

Uwe Schulzweida's avatar
Uwe Schulzweida committed
260
	    if ( rprec == prec )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
261
	      memcpy(data, buffer, datasize*sizeof(FLT64));
Uwe Schulzweida's avatar
Uwe Schulzweida committed
262
	    else
Uwe Schulzweida's avatar
Uwe Schulzweida committed
263
	      for (size_t i = 0; i < datasize; ++i)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
264 265 266 267
		((float *) data)[i] = (float) ((double *) buffer)[i];
	  }
	else
	  {
268
	    Error("not implemented for %d byte float", sizeof(FLT64));
269
	  }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
270 271 272
	break;
    default:
      {
273
	Error("unexpected data precision %d", rprec);
274
	break;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
275 276 277
      }
    }

278
  return ierr;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
279 280 281
}


Uwe Schulzweida's avatar
Uwe Schulzweida committed
282
int extInqDataSP(void *ext, float *data)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
283
{
284
  return extInqData((extrec_t *)ext, EXSE_SINGLE_PRECISION, (void *) data);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
285 286 287
}


Uwe Schulzweida's avatar
Uwe Schulzweida committed
288
int extInqDataDP(void *ext, double *data)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
289
{
290
  return extInqData((extrec_t *)ext, EXSE_DOUBLE_PRECISION, (void *) data);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
291 292 293
}


Thomas Jahns's avatar
Thomas Jahns committed
294
static int extDefData(void *ext, int prec, const void *data)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
295
{
Uwe Schulzweida's avatar
Uwe Schulzweida committed
296
  extrec_t *extp = (extrec_t *) ext;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
297

298
  const int rprec = extDefaultPrec ? extDefaultPrec : extp->prec;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
299
  extp->prec = rprec ? rprec : prec;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
300

301
  int *header = extp->header;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
302

303
  size_t datasize = (size_t)header[3];
Uwe Schulzweida's avatar
Uwe Schulzweida committed
304
  if ( extp->number == EXT_COMP ) datasize *= 2;
305
  const size_t blocklen = datasize * (size_t)rprec;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
306 307 308

  extp->datasize = datasize;

309
  if ( extp->buffersize != blocklen )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
310
    {
311 312
      extp->buffersize = blocklen;
      extp->buffer = Realloc(extp->buffer, extp->buffersize);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
313 314
    }

Uwe Schulzweida's avatar
Uwe Schulzweida committed
315
  switch ( rprec )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
316
    {
317
    case EXSE_SINGLE_PRECISION:
Uwe Schulzweida's avatar
Uwe Schulzweida committed
318
      {
Uwe Schulzweida's avatar
Uwe Schulzweida committed
319
	if ( rprec == prec )
320
	  memcpy(extp->buffer, data, datasize*sizeof(FLT32));
Uwe Schulzweida's avatar
Uwe Schulzweida committed
321
	else
Uwe Schulzweida's avatar
Uwe Schulzweida committed
322
	  for (size_t i = 0; i < datasize; i++)
323
	    ((float *) extp->buffer)[i] = (float) ((double *) data)[i];
Uwe Schulzweida's avatar
Uwe Schulzweida committed
324 325 326

	break;
      }
327
    case EXSE_DOUBLE_PRECISION:
Uwe Schulzweida's avatar
Uwe Schulzweida committed
328
      {
Uwe Schulzweida's avatar
Uwe Schulzweida committed
329
	if ( rprec == prec )
330
	  memcpy(extp->buffer, data, datasize*sizeof(FLT64));
Uwe Schulzweida's avatar
Uwe Schulzweida committed
331
	else
Uwe Schulzweida's avatar
Uwe Schulzweida committed
332
	  for (size_t i = 0; i < datasize; i++)
333
	    ((double *) extp->buffer)[i] = (double) ((float *) data)[i];
Uwe Schulzweida's avatar
Uwe Schulzweida committed
334 335 336 337 338

	break;
      }
    default:
      {
339
	Error("unexpected data precision %d", rprec);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
340
        break;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
341 342 343
      }
    }

344
  return 0;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
345 346 347
}


Uwe Schulzweida's avatar
Uwe Schulzweida committed
348
int extDefDataSP(void *ext, const float *data)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
349
{
350
  return extDefData(ext, EXSE_SINGLE_PRECISION, (void *) data);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
351 352 353
}


Uwe Schulzweida's avatar
Uwe Schulzweida committed
354
int extDefDataDP(void *ext, const double *data)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
355
{
356
  return extDefData(ext, EXSE_DOUBLE_PRECISION, (void *) data);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
357 358 359
}


Uwe Schulzweida's avatar
Uwe Schulzweida committed
360
int extRead(int fileID, void *ext)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
361
{
Uwe Schulzweida's avatar
Uwe Schulzweida committed
362
  extrec_t *extp = (extrec_t *) ext;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
363 364 365

  if ( ! extp->checked )
    {
Uwe Schulzweida's avatar
Uwe Schulzweida committed
366
      int status = extCheckFiletype(fileID, &extp->byteswap);
367
      if ( status == 0 ) Error("Not a EXTRA file!");
Uwe Schulzweida's avatar
Uwe Schulzweida committed
368 369 370
      extp->checked = 1;
    }

371
  const int byteswap = extp->byteswap;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
372

373
  // read header record
374
  size_t blocklen = binReadF77Block(fileID, byteswap);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
375

376
  if ( fileEOF(fileID) ) return -1;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
377

Uwe Schulzweida's avatar
Uwe Schulzweida committed
378
  if ( EXT_Debug ) Message("blocklen = %lu", blocklen);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
379

380
  const size_t hprec = blocklen / EXT_HEADER_LEN;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
381

382
  extp->prec = (int)hprec;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
383

384
  union EXT_HEADER tempheader;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
385 386
  switch ( hprec )
    {
387
    case EXSE_SINGLE_PRECISION:
Uwe Schulzweida's avatar
Uwe Schulzweida committed
388
      {
389 390
	binReadInt32(fileID, byteswap, EXT_HEADER_LEN, tempheader.i32);
	for (int i = 0; i < EXT_HEADER_LEN; i++) extp->header[i] = (int)tempheader.i32[i];
Uwe Schulzweida's avatar
Uwe Schulzweida committed
391 392
	break;
      }
393
    case EXSE_DOUBLE_PRECISION:
Uwe Schulzweida's avatar
Uwe Schulzweida committed
394
      {
395 396
	binReadInt64(fileID, byteswap, EXT_HEADER_LEN, tempheader.i64);
	for (int i = 0; i < EXT_HEADER_LEN; i++) extp->header[i] = (int)tempheader.i64[i];
Uwe Schulzweida's avatar
Uwe Schulzweida committed
397 398 399 400
	break;
      }
    default:
      {
401
	Error("Unexpected header precision %d", hprec);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
402
        break;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
403 404 405
      }
    }

406
  size_t blocklen2 = binReadF77Block(fileID, byteswap);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
407 408 409

  if ( blocklen2 != blocklen )
    {
410
      Warning("Header blocklen differ (blocklen1=%d; blocklen2=%d)!", blocklen, blocklen2);
411
      if ( blocklen2 != 0 ) return -1;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
412 413
    }

414
  extp->datasize = (size_t)extp->header[3];
Uwe Schulzweida's avatar
Uwe Schulzweida committed
415

416
  if ( EXT_Debug ) Message("datasize = %zu", extp->datasize);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
417 418 419

  blocklen = binReadF77Block(fileID, byteswap);

420
  if ( extp->buffersize < blocklen )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
421
    {
422 423
      extp->buffersize = blocklen;
      extp->buffer = Realloc(extp->buffer, extp->buffersize);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
424 425
    }

426
  size_t dprec = blocklen / extp->datasize;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
427

Uwe Schulzweida's avatar
Uwe Schulzweida committed
428 429 430 431 432 433 434 435 436 437
  if ( dprec == hprec )
    {
      extp->number = EXT_REAL;
    }
  else if ( dprec == 2*hprec )
    {
      dprec /= 2;
      extp->datasize *= 2;
      extp->number = EXT_COMP;
    }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
438

439
  if ( dprec != EXSE_SINGLE_PRECISION && dprec != EXSE_DOUBLE_PRECISION )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
440
    {
441
      Warning("Unexpected data precision %d", dprec);
442
      return -1;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
443 444
    }

445
  fileRead(fileID, extp->buffer, blocklen);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
446 447 448 449 450

  blocklen2 = binReadF77Block(fileID, byteswap);

  if ( blocklen2 != blocklen )
    {
451
      Warning("Data blocklen differ (blocklen1=%d; blocklen2=%d)!", blocklen, blocklen2);
452
      if ( blocklen2 != 0 ) return -1;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
453 454
    }

455
  return 0;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
456 457 458
}


Uwe Schulzweida's avatar
Uwe Schulzweida committed
459
int extWrite(int fileID, void *ext)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
460
{
Uwe Schulzweida's avatar
Uwe Schulzweida committed
461
  extrec_t *extp = (extrec_t *) ext;
462 463 464
  union EXT_HEADER tempheader;
  const int byteswap = extp->byteswap;
  const int rprec  = extp->prec;
465 466
  int number = extp->number;
  int *header = extp->header;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
467

468
  // write header record
469
  size_t blocklen = EXT_HEADER_LEN * (size_t)rprec;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
470 471 472

  binWriteF77Block(fileID, byteswap, blocklen);

Uwe Schulzweida's avatar
Uwe Schulzweida committed
473
  switch ( rprec )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
474
    {
475
    case EXSE_SINGLE_PRECISION:
Uwe Schulzweida's avatar
Uwe Schulzweida committed
476
      {
477
	for (int i = 0; i < EXT_HEADER_LEN; i++) tempheader.i32[i] = (INT32) header[i];
478
	binWriteInt32(fileID, byteswap, EXT_HEADER_LEN, tempheader.i32);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
479 480
	break;
      }
481
    case EXSE_DOUBLE_PRECISION:
Uwe Schulzweida's avatar
Uwe Schulzweida committed
482
      {
483
	for (int i = 0; i < EXT_HEADER_LEN; i++) tempheader.i64[i] = (INT64) header[i];
484
	binWriteInt64(fileID, byteswap, EXT_HEADER_LEN, tempheader.i64);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
485 486 487 488
	break;
      }
    default:
      {
489
	Error("unexpected header precision %d", rprec);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
490
        break;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
491 492
      }
    }
493

Uwe Schulzweida's avatar
Uwe Schulzweida committed
494 495
  binWriteF77Block(fileID, byteswap, blocklen);

496 497 498
  extp->datasize = (size_t)header[3];
  if ( number == EXT_COMP ) extp->datasize *= 2;
  blocklen = extp->datasize * (size_t)rprec;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
499 500 501

  binWriteF77Block(fileID, byteswap, blocklen);

Uwe Schulzweida's avatar
Uwe Schulzweida committed
502
  switch ( rprec )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
503
    {
504
    case EXSE_SINGLE_PRECISION:
Uwe Schulzweida's avatar
Uwe Schulzweida committed
505
      {
506
	binWriteFlt32(fileID, byteswap, extp->datasize, (FLT32 *) extp->buffer);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
507 508
	break;
      }
509
    case EXSE_DOUBLE_PRECISION:
Uwe Schulzweida's avatar
Uwe Schulzweida committed
510
      {
511
	binWriteFlt64(fileID, byteswap, extp->datasize, (FLT64 *) extp->buffer);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
512 513 514 515
	break;
      }
    default:
      {
516
	Error("unexpected data precision %d", rprec);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
517
        break;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
518 519 520 521 522
      }
    }

  binWriteF77Block(fileID, byteswap, blocklen);

523
  return 0;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
524
}
525 526 527 528 529 530 531 532 533
/*
 * Local Variables:
 * c-file-style: "Java"
 * c-basic-offset: 2
 * indent-tabs-mode: nil
 * show-trailing-whitespace: t
 * require-trailing-newline: t
 * End:
 */