/*****************************************************
* unit:    struct            release 0.15            *
* STRUCT.H - Provides some big and little endian abstraction functions,
*	      for manipulating with structures.	
*   Copyright (C) 1999-2024  Jaroslav Fojtik
*****************************************************/
#ifndef _STRUCT_H_
#define _STRUCT_H_

#include "typedfs.h"


/*
#undef LO_ENDIAN	//Signalise that system is native LowEndian
#define HI_ENDIAN	//Signalise that system is native HighEndian
#define EXPAND_OPS	//hack to speed up; please note that EXPAND_OPS does not work on AMD64; works on x86.
*/

#if defined(LO_ENDIAN) && defined(HI_ENDIAN)
 #error Cannot define both LO_ENDIAN and HI_ENDIAN together!
#endif

/* Ensure that prototypes are correctly declared even for C. */
#ifdef __cplusplus
extern "C" {
#endif
/* functions from struct.c */


#ifdef EXPAND_OPS
 #ifdef LO_ENDIAN
  #define RdWORD_LoEnd(pnum,f)		fread(pnum,1,2,f)
  #define RdDWORD_LoEnd(pnum,f)		fread(pnum,1,4,f)
  #define RdQWORD_LoEnd(pnum,f)		fread(pnum,1,8,f)
  #define WrWORD_LoEnd(num,f)		fwrite(&num,1,2,f)
  #define WrDWORD_LoEnd(num,f)		fwrite(&num,1,4,f)
  #define WrQWORD_LoEnd(num,f)		fwrite(&num,1,8,f)
  #define RdFLOAT_LoEnd(pnum,f)		fread(pnum,1,4,f)
  #define WrFLOAT_LoEnd(num,f)		fwrite(&num,1,4,f)
 #endif
 #ifdef HI_ENDIAN
  #define RdWORD_HiEnd(num,f)		fread((num),1,2,f)
  #define RdDWORD_HiEnd(num,f)		fread((num),1,4,f)
/* this speedup is not working on MSB - never mind
  #define WrWORD_HiEnd(num,f)		fwrite((&num),1,2,f)
  #define WrDWORD_HiEnd(num,f)		fwrite((&num),1,4,f)
*/
 #endif
#endif

#ifndef RdWORD_LoEnd
 int RdWORD_LoEnd(uint16_t *num, FILE *f);
#endif
#ifndef RdDWORD_LoEnd
 int RdDWORD_LoEnd(uint32_t *num, FILE *f);
#endif
#ifndef RdWORD_HiEnd
 int RdWORD_HiEnd(uint16_t *num, FILE *f);
#endif
#ifndef RdDWORD_HiEnd
 int RdDWORD_HiEnd(uint32_t *num, FILE *f);
#endif

#ifndef WrWORD_LoEnd
 int WrWORD_LoEnd(uint16_t num, FILE *f);
#endif
#ifndef WrWORD_HiEnd
 int WrWORD_HiEnd(uint16_t num, FILE *f); 
#endif
#ifndef WrDWORD_LoEnd
 int WrDWORD_LoEnd(uint32_t num, FILE *f);
#endif
#ifndef WrDWORD_HiEnd
 int WrDWORD_HiEnd(uint32_t num, FILE *f);
#endif

#if defined(uint64_t_defined) || defined(uint64_t)
 #ifndef RdQORD_HiEnd
  int RdQWORD_HiEnd(uint64_t *num, FILE *f);
 #endif
 #ifndef RdQWORD_LoEnd
  int RdQWORD_LoEnd(uint64_t *num, FILE *f);
 #endif
 #ifndef WrDWORD_LoEnd
  int WrQWORD_LoEnd(uint64_t num, FILE *f);
 #endif
 #ifndef WrDWORD_HiEnd
  int WrQWORD_HiEnd(uint64_t num, FILE *f);
 #endif
#endif

#ifndef RdFLOAT_LoEnd
 #define RdFLOAT_LoEnd(pflt,file)  RdDWORD_LoEnd(((uint32_t*)pflt), file)
#endif

#ifndef RdFLOAT_HiEnd
 #define RdFLOAT_HiEnd(pflt,file)  RdDWORD_HiEnd(((uint32_t*)pflt), file)
#endif

#ifndef WrFLOAT_LoEnd
 #define WrFLOAT_LoEnd(flt,file)  WrDWORD_LoEnd((*(uint32_t*)&flt), file)
#endif

#ifndef WrFLOAT_HiEnd
 #define WrFLOAT_HiEnd(flt,file)  WrDWORD_HiEnd((*(uint32_t*)&flt), file)
#endif

uint16_t fil_sreadU16(const uint8_t *in);
uint32_t fil_sreadU32(const uint8_t *in);

int loadstruct(FILE *F,const char *description, ...);
int savestruct(FILE *F,const char *description, ...);

#ifdef __cplusplus
}
#endif


#endif