//================================================================================
// DESCRIPTION:	Resource header file
//
// AUTHOR:  Gabor Nagy
// DATE:    2026-Jul-02 03:31:26
//
// Copyright (C) 1996-2026 By Gabor Nagy. All rights reserved.
//================================================================================
#ifndef _EResource_h
#define _EResource_h

#include <stdio.h>
#include <stdarg.h>		// For varargs

#ifndef _EStrings_h
#include <EStrings.h>
#endif

#ifndef _ELists_h
#include <ELists.h>
#endif

#ifdef __cplusplus
extern "C" {
#endif


#define EResVERSION            3

#if EResVERSION >= 3
	#define  EResHEADER_SIZE  (2 + 2)  // Version, FormatFlags
#else
	#define  EResHEADER_SIZE  2        // Version
#endif

#define EResDEFINITION_MAGIC16  0xACE0
#define EResDEFINITION_MAGIC32  0xACE1
#define EResMAGIC32_OLD       0xACE4
#define EResMAGIC64_OLD       0xACE8
#define EResMAGIC32           0xACF4
#define EResMAGIC64           0xACF8

#define EResTOKEN_SIZE        2

// For byte-order independent network/file I/O and preferences I/O
//

// Resource types
//
enum
{
	EResNULL = 0,
	EResBOOLEAN,
	EResINT8,
	EResUINT8,
	EResINT16,
	EResUINT16,
	EResINT32,
	EResUINT32,
	EResINT64,
	EResUINT64,
	EResFLOAT16,
	EResFLOAT32,
	EResFLOAT64,
	EResRESERVED00,
	EResRESERVED01,

	EResFLOAT16_2,
	EResFLOAT16_3,
	EResFLOAT16_4,
	EResFLOAT32_2,
	EResFLOAT32_3,
	EResFLOAT32_4,
	EResFLOAT64_2,
	EResFLOAT64_3,
	EResFLOAT64_4,
	EResRESERVED11,
	EResRESERVED12,
	EResRESERVED13,
	EResRESERVED14,
	EResRESERVED15,

	EResSTRING,       // Statically allocated string (char name[])
	EResSTRINGPTR,    // Pointer to dynamically allocated string (char* name)
	EResSTRING16,     // Statically allocated 16-bit string (uint16_t name[])
	EResSTRING16PTR,  // Pointer to dynamically allocated string (uint16_t* name)
	EResRESERVED16,

	EResCOLOR,        // EcColor
	EResCLASS,
	EResSTRUCT,       // Nested struct with its own Resource list

	EResSET,
	EResFLEX_PTRS,
	EResFLEX_STRUCT,

	EResARGS,         // EArg list with NULL Name as a terminator

	EResGLTexture = 64,

	EResSCOPE_START = 250,  // Open scope  (i.e. a C struct {)
	EResSCOPE_END = 251,    // Close scope (i.e. a C struct })

	EResRESOURCE = 252,     // Resource with Name, Type and ClassID .Ext.Offset will specify the offset of the field in struct field that 
	EResPOINTER = 253,      // Pointer to a struct (that is not an EObject derivative, so no Name and Class fields)
	EResOBJECT = 254,       // Reflective object, derived from EObject (directly or through other base-classes)
	EResCUSTOM = 256
};


#if EIndex_BITS == 64
#define EResINDEX	EResINT64
#else
#define EResINDEX	EResINT32
#endif


/* EResFLEXIBLE:
void*'s which control string and variable pointers
types in the control string:
'C'	unsigned char
'c'	char
'I'	unsigned int
'i'	int
'S'	unsigned short
's'	short
'L'	unsigned long
'l'	long
'f'	float
'd'	double
's'	char* (string)
*/


#define EResMAX_CMDLENGTH    256
#define EResMAX_VALLENGTH   8192

#define EResLAST_TYPE  EResFLEX_STRUCT

#define EResCORETYPE_MASK  0x01FF

#define EResINDIRECT1      0x0200    // As in int*
#define EResINDIRECT2      0x0400    // As in int**
#define EResINDIRECT_MASK  0x0600    // Level of indirection mask (The number means the number of '*'s, like  int, int*, int** etc. 0 means value is stored in struct. 1 means dynamically allocated array of values, 2 means dynamic array of pointers to values etc.)

#define EResTYPE_MASK      (EResCORETYPE_MASK | EResINDIRECT_MASK)

#define EResOLD            0x0800    // Resource is old, it has a new equivalent. Read it, but don't save it

#define EResCOUNT_FUNC     0x2000    // Ext.CountFunc is a pointer to a function that tells the count (vs. an offset to an EIndex within the struct)

#define EResDYNAMIC        0x4000    // Dynamically allocated vs. statically in the struct (int* or int/int[])
#define EResCOUNT          0x8000    // More than 1 value, count stored. Only used in binary images and should NOT be specified in EResource lists

// Resource-handler actions
//
enum
{
	EResCOPY = 1,     // Copy resource
	EResPACK_SIZE,    // Tell how many bytes are necessary to pack a resource into a binary image
	EResPACK,         // Pack a resource into a machine-independent binary image
	EResUNPACK,       // Unpack a resource from a binary image
	EResTYPE_QUERY,
	EResGET_TYPE_NAME,
	EResGET_FUNC_NAME,
	EResSET_VALUE,
	EResGET_DEFAULT_VALUE_STRING
};


typedef int  (*EResourcePointerToIndexFunc)(void*);
typedef int  (*EResourceIndexToPointerFunc)(int, void**);

typedef struct EResource_S   EResource;
typedef struct EResource_S*  EResourcePtr;

typedef struct
{
	unsigned int                 ClassID;
	EResourcePointerToIndexFunc  PointerToIndex;
	EResourceIndexToPointerFunc  IndexToPointer;
} EResourceConverter;
EList_t(EResourceConverter);

typedef struct ECoreClass_S      ECoreClass;  // ECoreClass is an opaque pointer, except for code that includes EClass.h


typedef struct EResClassEntry_S         EResClassEntry;
typedef struct EResClassEntry_S*        EResClassEntryPtr;
EListA_t(EResClassEntryPtr);
typedef const struct EResClassEntry_S*  EResConstClassEntryPtr;

struct EResClassEntry_S
{
	char*              ClassName;
	const ECoreClass*  Class;
	union { int        SuperClassIndex;EResClassEntry*  SuperClass; };
	EList(, EResource, Resources);     // Resources just for this class
	EList(, EResource, AllResources);  // Resources just for this class and all of its superclasses (in superclas->subclass order)
};


#define  EResCLASS_NAME     0x0001  // For each instance, store class name (useful for debugging and for dictionaryless files / network packets)
#define  EResCLASS_INDEX16  0x0002  // For each instance, store class index
#define  EResNAMES          0x0010  // For each instance, store the type of each Resource (useful for debugging and for dictionaryless files / network packets)
#define  EResTYPES          0x0020  // For each instance, store the type of each Resource (useful for debugging and for dictionaryless files / network packets)

typedef struct ECoreObject_S       ECoreObject;
typedef struct ECoreObject_S*      ECoreObjectPtr;
EListA_t(ECoreObjectPtr);

// Used for forward-referencing during deserialization
//
typedef struct
{
	ECoreObject*   Object;           // The target Object/struct
	EResource*     Resource;         // The Resource in the target Object/struct
	ECoreObject**  ObjectRef;        // The address to put the pointer to the referenced Object

#if EObjectMEMORY_DEBUG
	ECoreClass*    Class;            // In case the Object field points to a struct that's not an ECoreObject derivative (no Class field)
#endif
} ETargetSlot;

typedef struct
{
	ECoreObject*  Object;
	EListA(, ETargetSlot, Targets);  // Objects or structs that reference this Object
} EObjectProxy;
EListA_t(EObjectProxy);

typedef struct
{
	int                  Version;
	uint16_t             FormatFlags;    // OR-ed EResCLASS_NAME, EResTYPES
	int                  HeaderSize, Size;
	int                  ScopeDepth;
	EList_s(, EResourceConverter, ResourceConverters);
	int                  Verbose;

	EListA_s(, ECoreObjectPtr, ReferencedObjects);
	EListA_s(, ECoreObjectPtr, AllObjects);

// Growable buffer for saving resources
//
	uint8_t*             Buffer;ESize  BufferBytesAllocated;

	EIndex               UnrecognizedResources_Count;

	EListA_s(, EResClassEntryPtr, Classes);

	EListA_s(, EObjectProxy, ObjectProxies);  // For forward-referencing Objects

// Dictionary entries for commonly used classes
//
	EResClassEntry*  ColorClassEntry;
} EResContext;


typedef int     (*EResResourceHandlerFunc)(EResContext* PContext, const void* PDStructAddress,  const void* PSPtr, void* PDPtr,  const int PAction);
typedef EIndex  (*EResCountFunc)(const void* PStructAddress);

#define EResFlagSAVE         0x0001
#define EResFlagINTERPOLATE  0x0002
#define EResFlagNORMALIZE    0x0004

// Resource Name, Semantic or UI fields in a list are statically allocated (i.e. don't free them)
//
#define EResNAME_STATIC      0x0100
#define EResSEMANTIC_STATIC  0x0200
#define EResUI_STATIC        0x0400

#define EResFlagLAST         EResUI_STATIC

struct EResource_S
{
	char*       Name;
	int         Type;
	void*       Address;
	int         Size;             // For EResSTRUCT. Otherwise, it should be computable and this should be set to 0
	union
	{
		void*                        Ptr;
		EIndex                       Offset;
		EIndex                       Count;
		EPointerUInt                 CountOffset;
		EResResourceHandlerFunc      ResourceHandler;
//	EResourcePointerToIndexFunc  PointerToIndexProc;
		EResCountFunc                CountFunc;
	} Ext;
	EResource*  Resources;        // For EResSTRUCT. Otherwise NULL
	uint16_t    Flags;            // EResFlagSAVE, EResFlagINTERPOLATE, EResFlagNORMALIZE
	void*       Semantic;         // Semantic / meaning
	void*       UI;               // User interface info. E.g. Xe resource list
};

EList_t(EResource);   // EResourceList
EListA_t(EResource);  // EResourceListA


typedef void    (*EResResourceCallbackFunc)(const EResource* PResource, void* PValue, void* PClientData);


//========================================================================================================
// Return the number of elements in a Resource
// For example, an EResFLOAT32 array with Count = 4 will return 4
//========================================================================================================
static inline EIndex EResource_Count(const EResource* PResource, const void* PStruct)
{
	const int  LType = PResource->Type;if(LType != EResCUSTOM)
	{
		EIndex  LCount = 1;

		if(LType & EResDYNAMIC)  // Dynamic array
		{
			if(LType & EResCOUNT_FUNC)
			{
				EResCountFunc  LCountFunc = PResource->Ext.CountFunc;

// The Resource is an array and Ext.CountFunc points to a function that returns an "EIndex" element-count
//
				LCount = LCountFunc(PStruct);
			}
			else
			{
				void*  LAddress;

				if(PStruct) LAddress = ((uint8_t*)PStruct) + (EPointerInt)PResource->Ext.Offset;
				else LAddress = PResource->Ext.Ptr;

// The Resource is an array and Ext.Offset or Ext.Ptr points to an "EIndex" element-count
//
				LCount = *((EIndex*)LAddress);
//printf("%s() %s:%d  %s%s%s %d\n", __FUNCTION__, __FILE__, __LINE__, ECodeGreen, PResource->Name, ECodeNormal, LCount);fflush(stdout);
			}
		}
		else
		{
// Static array: Ext.Count *is* the count
//
			if(PResource->Ext.Count) LCount = PResource->Ext.Count;
		}

		return(LCount);
	}

	return(1);
}


//========================================================================================================
// Find a Resource by name, in a list
// PName is compared via EStr_Equal() and PResources is parsed until a Resource->Name is NULL
//========================================================================================================
static inline EResource* EResource_ByName(const EResourceList* PResources, const char* PName)
{
	if(PResources->Count > 0)
	{
		EIndex  LRC = 0;const EIndex  LRN = PResources->Count;EResource*  LResource = PResources->Items;for(;LRC < LRN;LRC++, LResource++)
		{
			if(EStr_Equal(LResource->Name, PName)) return(LResource);
		}
	}
	return(NULL);
}


//========================================================================================================
// Find a Resource by name, in a list
// PName is compared via EStr_Equal() and PResources is parsed until a Resource->Name is NULL
//========================================================================================================
static inline EResource* EResource_ByNameAndType(EResourceList* PResources, const char* PName, const uint16_t PType)
{
	if(PResources->Count > 0)
	{
		EIndex  LRC = 0;const EIndex  LRN = PResources->Count;EResource*  LResource = PResources->Items;for(;LRC < LRN;LRC++, LResource++)
		{
			if(LResource->Type == PType)
			{
				if(EStr_Equal(LResource->Name, PName)) return(LResource);
			}
		}
	}
	return(NULL);
}


//========================================================================================================
// Find a Resource by static name, in a list
// PName is compared by pointer and PResources->Count is used for the number of Resources to check
//========================================================================================================
static inline EResource* EResource_ByNameSN(const EResourceList* PResources, const char* PName)
{
	if(PResources)
	{
		EIndex  LI = 0;const EIndex  LN = PResources->Count;EResource*  LResource = PResources->Items;for(;LI < LN;LI++, LResource++)
		{
			if(LResource->Name == PName) return(LResource);
		}
	}
	return(NULL);
}


//========================================================================
// Find a Resource by address, in a list
//========================================================================
static inline EResource* EResource_ByAddress(EResourceList* PResources, const void* PAddress)
{
	EIndex  LI = 0;const EIndex  LN = PResources->Count;EResource*  LResource = PResources->Items;for(;LI < LN;LI++, LResource++)
	{
		if(LResource->Address == PAddress) return(LResource);
	}
	return(NULL);
}


//================================================================
// Set the value of a Resource in an EObject, from an EBool
//================================================================
static inline void EResource_Set1b(void* PStructAddress, const EResource* PResource, const EBool PValue)
{
	if(PResource)
	{
// If PStructAddress is NULL, the addresses are absolute. Otherwise they're relative to PStructAddress.
//
		uint8_t*  LVariableAddress = PStructAddress ? (EPointerUInt)PStructAddress + (uint8_t*)PResource->Address : (uint8_t*)PResource->Address;
		switch(PResource->Type & (~(EResDYNAMIC|EResCOUNT|EResCOUNT_FUNC)))
		{
			case EResBOOLEAN:
				*((EBool*)LVariableAddress) = PValue;
			break;

			default:
				printf("%s() %s:%d  %sIMPLEMENT ME  %04x%s\n", __FUNCTION__, __FILE__, __LINE__, ECodeYellow, PResource->Type & (~(EResDYNAMIC|EResCOUNT|EResCOUNT_FUNC)), ECodeNormal);fflush(stdout);
			break;
		}
	}
}

//========================================================================
// Set the value of a Resource in a struct / Object, from an EBool
//========================================================================
static inline void EResource_Set1i8(void* PStructAddress, const EResource* PResource, const uint8_t PValue)
{
	if(PResource)
	{
// If PStructAddress is NULL, the addresses are absolute. Otherwise they're relative to PStructAddress.
//
		uint8_t*  LVariableAddress = PStructAddress ? (EPointerUInt)PStructAddress + (uint8_t*)PResource->Address : (uint8_t*)PResource->Address;
		switch(PResource->Type & (~(EResDYNAMIC|EResCOUNT|EResCOUNT_FUNC)))
		{
			case EResINT8:  *((uint8_t*)(LVariableAddress)) = PValue;break;
			default:  printf("%s() %s:%d  %sIMPLEMENT ME  %04x%s\n", __FUNCTION__, __FILE__, __LINE__, ECodeYellow, PResource->Type & (~(EResDYNAMIC|EResCOUNT|EResCOUNT_FUNC)), ECodeNormal);fflush(stdout);break;
		}
	}
}

//========================================================================
// Set the value of a Resource in a struct / Object, from an int
//========================================================================
static inline int EResource_Set1i(void* PStructAddress, const EResource* PResource, const int PValue)
{
	if(PResource)
	{
// If PStructAddress is NULL, the addresses are absolute. Otherwise they're relative to PStructAddress.
//
		uint8_t*  LVariableAddress = PStructAddress ? (EPointerUInt)PStructAddress + (uint8_t*)PResource->Address : (uint8_t*)PResource->Address;
		switch(PResource->Type & (~(EResDYNAMIC|EResCOUNT|EResCOUNT_FUNC)))
		{
			case EResFLOAT32:  ((float*)LVariableAddress)[0] = PValue;break;
			case EResFLOAT64:  ((double*)LVariableAddress)[0] = PValue;break;
			case EResBOOLEAN:  ((EBool*)LVariableAddress)[0] = PValue == 0 ? FALSE : TRUE;break;
			case EResINT8:     ((int8_t*)LVariableAddress)[0] = PValue;break;
			case EResUINT8:    ((uint8_t*)LVariableAddress)[0] = PValue;break;
			case EResINT16:    ((int16_t*)LVariableAddress)[0] = PValue;break;
			case EResUINT16:   ((uint16_t*)LVariableAddress)[0] = PValue;break;
			case EResINT32:    ((int32_t*)LVariableAddress)[0] = PValue;break;
			case EResUINT32:   ((uint32_t*)LVariableAddress)[0] = PValue;break;
			case EResINT64:    ((int64_t*)LVariableAddress)[0] = PValue;break;
			case EResUINT64:   ((uint64_t*)LVariableAddress)[0] = PValue;break;
			default:
				printf("%s() %s:%d  %sIMPLEMENT ME  %04x%s\n", __FUNCTION__, __FILE__, __LINE__, ECodeYellow, PResource->Type & (~(EResDYNAMIC|EResCOUNT|EResCOUNT_FUNC)), ECodeNormal);fflush(stdout);
			return(E_NOT_SUPPORTED);
		}
		return(E_SUCCESS);
	}
	else return(E_NO_DATA);
}

//========================================================================
// Set the value of a Resource in a struct / Object, from ints
//========================================================================
static inline int EResource_SetNi(void* PStructAddress, const EResource* PResource, const int* PValues, const EIndex PN)
{
	if(PResource)
	{
// If PStructAddress is NULL, the addresses are absolute. Otherwise they're relative to PStructAddress.
//
		if(PResource->Ext.Count == PN)
		{
			uint8_t*  LVariableAddress = PStructAddress ? (EPointerUInt)PStructAddress + (uint8_t*)PResource->Address : (uint8_t*)PResource->Address;
			EIndex    LI = 0;
			switch(PResource->Type & (~(EResDYNAMIC|EResCOUNT|EResCOUNT_FUNC)))
			{
				case EResFLOAT32:  for(;LI < PN;LI++) ((float*)LVariableAddress)[LI] = PValues[LI];break;
				case EResFLOAT64:  for(;LI < PN;LI++) ((double*)LVariableAddress)[LI] = PValues[LI];break;
				case EResBOOLEAN:  for(;LI < PN;LI++) ((EBool*)LVariableAddress)[LI] = PValues[LI] == 0 ? FALSE : TRUE;break;
				case EResINT8:     for(;LI < PN;LI++) ((int8_t*)LVariableAddress)[LI] = PValues[LI];break;
				case EResUINT8:    for(;LI < PN;LI++) ((uint8_t*)LVariableAddress)[LI] = PValues[LI];break;
				case EResINT16:    for(;LI < PN;LI++) ((int16_t*)LVariableAddress)[LI] = PValues[LI];break;
				case EResUINT16:   for(;LI < PN;LI++) ((uint16_t*)LVariableAddress)[LI] = PValues[LI];break;
				case EResINT32:    for(;LI < PN;LI++) ((int32_t*)LVariableAddress)[LI] = PValues[LI];break;
				case EResUINT32:   for(;LI < PN;LI++) ((uint32_t*)LVariableAddress)[LI] = PValues[LI];break;
				case EResINT64:    for(;LI < PN;LI++) ((int64_t*)LVariableAddress)[LI] = PValues[LI];break;
				case EResUINT64:   for(;LI < PN;LI++) ((int64_t*)LVariableAddress)[LI] = PValues[LI];break;
				default:
					printf("%s() %s:%d  %sIMPLEMENT ME  %04x%s\n", __FUNCTION__, __FILE__, __LINE__, ECodeYellow, PResource->Type & (~(EResDYNAMIC|EResCOUNT|EResCOUNT_FUNC)), ECodeNormal);fflush(stdout);
				return(E_NOT_SUPPORTED);
			}
		}
		return(E_SUCCESS);
	}
	else return(E_NO_DATA);
}

//========================================================================
// Det the float value of a Resource from a struct / Object
//========================================================================
static inline float EResource_Get1f(void* PStructAddress, const EResource* PResource)
{
	if(PResource)
	{
// If PStructAddress is NULL, the addresses are absolute. Otherwise they're relative to PStructAddress.
//
		uint8_t*  LVariableAddress = PStructAddress ? (EPointerUInt)PStructAddress + (uint8_t*)PResource->Address : (uint8_t*)PResource->Address;
		switch(PResource->Type & (~(EResDYNAMIC|EResCOUNT|EResCOUNT_FUNC)))
		{
			case EResFLOAT32:  return(*((float*)(LVariableAddress)));
			case EResFLOAT64:  return(*((double*)(LVariableAddress)));
/*
			case EResINT8:    *((int8_t*)LVariableAddress)         = PValue;break;
			case EResUINT8:   *((uint8_t*)LVariableAddress)        = PValue;break;
			case EResINT16:   *((int16_t*)LVariableAddress)        = PValue;break;
			case EResUINT16:  *((uint16_t*)LVariableAddress)       = PValue;break;
			case EResINT32:   *((int32_t*)LVariableAddress)        = PValue;break;
			case EResUINT32:  *((uint32_t*)LVariableAddress)       = PValue;break;
			case EResINT64:   *((int64_t*)LVariableAddress)        = PValue;break;
			case EResUINT64:  *((int64_t*)LVariableAddress)        = PValue;break;
*/
			default:
				printf("%s() %s:%d  %s%s%s  %sIMPLEMENT ME  %04x%s\n", __FUNCTION__, __FILE__, __LINE__,  ECodeGreen, PResource->Name, ECodeNormal,  ECodeYellow, PResource->Type & (~(EResDYNAMIC|EResCOUNT|EResCOUNT_FUNC)), ECodeNormal);fflush(stdout);
			return(0.0);
		}
	}
	return(0.0);
}


//========================================================================
// Set the value of a Resource in a struct / Object, from an float
//========================================================================
static inline void EResource_Set1f(void* PStructAddress, const EResource* PResource, const float PValue)
{
	if(PResource)
	{
// If PStructAddress is NULL, the addresses are absolute. Otherwise they're relative to PStructAddress.
//
		uint8_t*  LVariableAddress = PStructAddress ? (EPointerUInt)PStructAddress + (uint8_t*)PResource->Address : (uint8_t*)PResource->Address;
		switch(PResource->Type & (~(EResDYNAMIC|EResCOUNT|EResCOUNT_FUNC)))
		{
			case EResFLOAT32: *((float*)(LVariableAddress))  = PValue;break;
			case EResFLOAT64: *((double*)(LVariableAddress)) = PValue;break;
			case EResINT8:    *((int8_t*)LVariableAddress)   = PValue;break;
			case EResUINT8:   *((uint8_t*)LVariableAddress)  = PValue;break;
			case EResINT16:   *((int16_t*)LVariableAddress)  = PValue;break;
			case EResUINT16:  *((uint16_t*)LVariableAddress) = PValue;break;
			case EResINT32:   *((int32_t*)LVariableAddress)  = PValue;break;
			case EResUINT32:  *((uint32_t*)LVariableAddress) = PValue;break;
			case EResINT64:   *((int64_t*)LVariableAddress)  = PValue;break;
			case EResUINT64:  *((int64_t*)LVariableAddress)  = PValue;break;

			default:
				printf("%s() %s:%d  %s%s%s  %sIMPLEMENT ME  %04x%s\n", __FUNCTION__, __FILE__, __LINE__,  ECodeGreen, PResource->Name, ECodeNormal,  ECodeYellow, PResource->Type & (~(EResDYNAMIC|EResCOUNT|EResCOUNT_FUNC)), ECodeNormal);fflush(stdout);
			break;
		}
	}
}


static inline void EResource_Set3f(void* PStructAddress, const EResource* PResource,  const float PValue0, const float PValue1, const float PValue2)
{
	if(PResource)
	{
// If PStructAddress is NULL, the addresses are absolute. Otherwise they're relative to PStructAddress.
//
		uint8_t*  LVariableAddress = PStructAddress ? (EPointerUInt)PStructAddress + (uint8_t*)PResource->Address : (uint8_t*)PResource->Address;
		switch(PResource->Type & (~(EResDYNAMIC|EResCOUNT|EResCOUNT_FUNC)))
		{
			case EResFLOAT32_3:
				{
					float*  LAddress = (float*)LVariableAddress;
					LAddress[0] = PValue0;
					LAddress[1] = PValue1;
					LAddress[2] = PValue2;
				}
			break;

			default:  printf("%s() %s:%d  %sIMPLEMENT ME  %04x%s\n", __FUNCTION__, __FILE__, __LINE__, ECodeYellow, PResource->Type & (~(EResDYNAMIC|EResCOUNT|EResCOUNT_FUNC)), ECodeNormal);fflush(stdout);break;
		}
	}
}


#ifndef EpImage_DEF
typedef struct EpImage_S  EpImage;
#endif


typedef int  (*EIOFormanCheckFunc)(const char* PFileName, FILE* PFile,  const uint8_t* PBuffer, const EIndex PBufferSize);

// File format I/O module core (image files, videos, 3D assets etc)
//
#define EIOModuleCore\
	char*         Name;                  /* Format name                                  */\
	unsigned int  StructSize;\
	EList_s(, EResource, Resources);     /* Instance settings. E.g. JPEG quality factor  */\
\
	char*               FormatClassName;       /* E.g. "3D model", or "Image"                  */\
	char**              FileNameExtensions;    /* File name extensions                         */\
	EpImage*            Icon;\
	EIOFormanCheckFunc  FormatCheck;                 /* Check if a file is of this format */\
	int                 (*GetThumbnailImage)(const char* PFileName, FILE* PFile, const EIndex2 PDSize, const EIndex2 PSizeMax,  EpImage** PImage)

typedef struct
{
	EIOModuleCore;
} EIOModule, *EIOModulePtr;

EListA_t(EIOModulePtr);

EListA_s(extern, EIOModulePtr, E_IOModules);

#define EFileCore\
	char*       Name;\
	FILE*       File;                /* If not NULL, an open file. Otherwise check MemoryBuffer or Name */\
	EIOModule*  Format;              /* The IOModule used for handling this file format. E.g. JPEG, or .eqx */\
	uint32_t    NameStatic : 1,      /* If TRUE / 1, Name was statically allocated. Do not free */\
	            UseMemoryBuffer : 1;\
	uint8_t*    MemoryBuffer;\
	EIndex      Size                 /* The size of the file or the data in MemoryBuffer. */




#define EList_ClassGetIndex(pList, pClass)     ELst_ClassGetIndex(pList, pList##_Count, pClass)
#define EList_ClassGetIndex_s(pList, pClass)   ELst_ClassGetIndex((pList).Items, (pList).Count, pClass)

#define EList_ClassEntryFind(pList, pClass)    ELst_ClassEntryFind(pList, pList##_Count, pClass)
#define EList_ClassEntryFind_s(pList, pClass)  ELst_ClassEntryFind((pList).Items, (pList).Count, pClass)

extern int     ERes_ComponentInfo(const uint16_t PType, uint16_t* PComponentType);

extern void    EResContext_Init(EResContext* PContext);
extern void    EResContext_FreeContents(EResContext* PContext);

extern EIndex           ELst_ClassGetIndex(EResClassEntry** PClasses, const EIndex PCount, const ECoreClass* PClass);
extern EResClassEntry*  ELst_ClassEntryFind(EResClassEntry** PClasses, const EIndex PCount, const ECoreClass* PClass);
extern void             EResContext_ClassAddAChk(EResContext* PContext, const ECoreClass* PClass);

extern EIndex  ERes_BinaryImageSize(const EResContext* PContext, const EResourceList* PResources, const void* PStructAddress);
extern EIndex  ERes_BinaryImageSizeI(const EResContext* PContext, const EResourceList* PResources, const void* PStructAddress);

extern int     ERes_GetResourcesVA(va_list PVArgs, const EResourceList* PResources, uint8_t* PStruct);

extern EIndex  ERes_ToBinaryImage(EResContext* PContext, const EResourceList* PResources, const void* PStructAddress, uint8_t** PAllocatedBufferPtr, ESize* PBytesAllocatedPtr, uint8_t** PBinaryImage);
extern EIndex  ERes_ListsToBinaryImage(EResContext* PContext,  const EResourceList* PResourceLists, const EIndex PNLists,  const void* PStructAddress, uint8_t** PBufferPtr, ESize* PBytesAllocatedPtr, uint8_t** PBinaryImagePtr);

extern EIndex  ERes_ResourceListDefinitionToBinaryImage(EResContext* PContext, const EResourceList* PResources,  uint8_t** PBinaryImage);
extern EIndex  ERes_ResourceListDefinitionFromBinaryImage(EResContext* PContext, const uint8_t* PBinaryImage,  EResClassEntry* PClassEntry);

extern char*   ERes_TypeToString(const int PType, char* PStr, const int PMaxLen);

extern int     ERes_DataTypeToRichness(const int PType);

extern void    EResource_Init(EResource* PResource);

extern EBool   EResource_ToBool(const EResource* PResource, const void* PStructAddress);
extern short   EResource_ToShort(const EResource* PResource, const void* PStructAddress);
extern int     EResource_ToInt(const EResource* PResource, const void* PStructAddress);
extern float   EResource_ToFloat(const EResource* PResource, const void* PStructAddress);
extern double  EResource_ToDouble(const EResource* PResource, const void* PStructAddress);

extern EBool   ERes_Signed(const uint16_t PType);
extern EIndex  ERes_Size(const uint16_t PType);

extern EIndex  EResource_Size(const EResource* PResource);
extern EIndex  EResource_Offset(const EResourceList* PList,  const char* PSemantic, const char* PName, const int PIndex,  const EResource** PResource);
extern EIndex  EResource_OffsetByType(const EResourceList* PList,  const char* PSemantic, const char* PName, const uint16_t PType, const EIndex PCount, const int PIndex,  EResource const** PResource);
extern EIndex  EResource_OffsetByIndex(const EResourceList* PList,  const int PIndex);

extern EIndex  EResources_CountBySemantic(const EResourceList* PList,  const char* PSemantic);
extern EBool   EResources_Equal(const EResource* PResourceA, const EIndex PNumOfResourcesA,  const EResource* PResourceB, const EIndex PNumOfResourcesB);
extern EBool   EResources_Equal_p(const EResourceList* PResourcesA,  const EResourceList* PResourcesB);

extern void    EResource_Copy(const EResource* PSrc, EResource* PDst, const uint16_t PFlags);

extern int     EResource_CopyValue(const EResource* PSResource, const void* PSrcStruct, const EResource* PDResource, void* PDstStruct);
extern EIndex  EResources_CopyValues(const EResourceList* PResources, const void* PSrcStruct, void* PDstStruct);
extern EIndex  EResources_CopyValues2(const EResourceList* PSrcResources, const void* PSrcStruct,  const EResourceList* PDstResources, void* PDstStruct);

extern int     EResourceList_Copy(const EResourceList* PSrcResources, EResourceList* PDstResources,  const uint16_t PFlags, const uint16_t PUIType);
extern EIndex  EResourceList_ResourceBySemanticAndIndex(const EResourceList* PAttributes,  const char* PSemantic, const int PIndex,  EResource** PResult);
extern void    EResourceList_ListUpdateOffsets(EResourceList* PList);
extern EIndex  EResourceList_ValuesSize(const EResourceList* PList);

extern EResourceConverter*  ERes_ConverterRegister(unsigned int PClassID, EResourcePointerToIndexFunc PPointerToIndexProc, EResourceIndexToPointerFunc PIndexToPointerProc);
extern void    ERes_ConverterDeactivate(EResourceConverter* PConverter);
extern void    ERes_ConverterRemove(EResourceConverter* PConverter);
extern int     ERes_PointerToIndex(EResContext* PContext, unsigned int PResourceClassID, void* PPointer);
extern int     ERes_IndexToPointer(EResContext* PContext, unsigned int PResourceClassID, int PIndex, void** PPointerRet);

extern void    EResources_Free(EResourceList* PResources, const uint16_t PFlags);
extern void    EResources_FreeA(EResourceListA* PResources, const uint16_t PFlags);

extern void      ERes_Exit(void);
extern void      E_Float16ToFloat32(const uint16_t PI, float* PF);
extern uint16_t  E_Float32ToFloat16(const float* PFP);


extern void    ERes_ResourceWidgetsFree(const EResourceList* PResources, void* PWList);


extern int     ERes_GetArguments(const char* const* PArgs, const int PNArgs,  const EResource* PResources,  void* PStruct);
extern void    ERes_ArgsPrintUsage(const EResource* PResources, const int PDescriptionIndent);

extern void    ERes_ResourcePrint(const EResource* PResource, const void* PStructAddress);
extern void    ERes_ObjectPrintResources(const void* PStructAddress, const EResourceList* PResource, const int PIndent);


extern EBool   ERes_ReadASCII(const char* PFileName, const EResource* PResources, void* PStructAddress);
extern EBool   ERes_SaveASCII(const char* PFileName, const char* PHeaderString, const EResource* PResources, const void* PStructAddress);

extern EIndex  EResource_ToString(const EResource* PResource, const uint8_t* PStruct,  charListA* PString, EBool* PNumber);


extern int     EResource_SetS(void* PStructAddress, const EResource* PResource, const char* PValue);


typedef struct
{
	int    Value;
	char*  Name;
} ESet;

enum
{
	ESetSUCCESS = 0,
	ESetDUPLICATE_NAME,
	ESetFILE_OPEN_ERROR,
	ESetALLOC_ERROR,
	ESetNO_MORE_SPACE,
	ESetERROR,
	ESetNO_SETS,
	ESetFATAL_ERROR
};


extern int  ESet_ReadSets(const char* PPath, const char* PFileName, int (*PItemInitFunc)(void*, void*), int (*PGetItemValueFunc)(void*, void*, const char*, const char*), int (*PItemEndFunc)(void*, const int, void*, const char*, void*), const ESize PItemSize, const int PAllocIncrement, void* PTmpData,  void* PItemsRet, EIndex* PNumOfItemsRet, EIndex* PNumOfItemsAllocatedRet);



#ifdef __cplusplus
}	// Close scope of 'extern "C"' declaration
#endif

#endif  // _EResource_h
