Types
The following are basic types aliased to definitive sizes accoring to
their names. _## where ## is the number of bits of the type. Most
compilers do not understand/allow _0 size definitions, so this type
only exists as a pointer type. A 'P' prefix indicates pointer, and
'S' indicates a signed value. 64 bit types are not used at this point;
this type also seems to lack a standard definition method, some use
'long long', some use '__int64', probably some other forms of definiton
do exist; at this point, none of my code uses 64 bit data.
typedef void *P_0;
typedef unsigned char _8;
typedef _8 *P_8;
typedef unsigned short _16;
typedef _16 *P_16;
typedef unsigned long _32;
typedef _32 *P_32;
typedef signed char S_8;
typedef S_8 *PS_8;
typedef signed short S_16;
typedef S_16 *PS_16;
typedef signed long S_32;
typedef S_32 *PS_32;
#if defined( __CYGWIN__ ) || defined( __LINUX__ )
typedef unsigned long long _64;
typedef signed long long S_64;
#elif defined( __BORLAND__ )
typedef unsigned __int64 _64;
typedef signed __int64 S_64;
#endif
//typedef _64 *P_64;
//typedef S_64 *PS_64;
Sometimes, one wishes to store a pointer or integer value in the
same place, this could be done with a union, and would be a more
correct solution, however I have defined a pointer sized value, to
store a pointer as an integer. Mostly this is used to pass user
data to callback functions. Under Win32 these would be like DWORD dwUser.
At some future point not far from now, this value will have to be
modified to be 64 bits to hold the pointer value... and hopefully
a standard for declaring a 64 bit value will be made.
#pragma message "Setting PTRSIZEVAL to 32 bits... pointers are this size?"
typedef _32 PTRSIZEVAL;
typedef _32 PTRSZVAL;
Some common types definitions which may change from time to time
but still represent the same data.. text strings, for now a pointer
to unsigned 8 bit values; text characters, for now an unsigned 8 bit
value. Since this program often deals with the internet or other
networks, this probably will not change for quite some time.
// may consider changing this to P_16 for unicode...
typedef P_8 TEXTSTR;
typedef _8 TEXTCHAR;
A logical value is either TRUE or it is FALSE. This type could
be represented by a single bit, however, this causes some overhead
when using compiler bit fields to test for results. Windows defines
a BOOLEAN to be a full 32 bits, which is a waste of 31 bits of space.
I still feel that space is important, and 8 bit values are the
smallest register size on an Intel platform.
typedef _8 LOGICAL; // smallest information
When this project began it had but two custom types, POINTER, and INDEX.
POINTER is of course a POINTER to anything, and INDEX is an unsigned
count designed to index an array.
typedef P_0 POINTER;
typedef _32 INDEX;
Since a pointer may never ever be less than 0, nor may it be REALLY
really big, an invalid index may be expressed with the following
defined value: INVALID_INDEX.
#define INVALID_INDEX ((_32)-1)
The idea of callbacks, or funtions which are called automatically
by events that occur... how to say this... were preverted by Windows.
For some reason - they decided that PASCAL(eww) type calls made
more sense, since it saves a couple bytes of code space. These
'CALLBACK' functions should just be standard C functions, relying
on the caller to clean up the arguments put on the stack, since
ONLY the caller knows how many arguments were actually supplied.
#ifdef _WIN32
#ifndef CALLBACK
#pragma message "Setting CALLBACK to __stcall"
#ifndef __LCC__
#define CALLBACK __stdcall
#else
#define CALLBACK
#endif
#endif
#else
#ifndef CALLBACK
#pragma message "Setting CALLBACK to c call"
#define CALLBACK
#endif
#endif
Since TRUE/FALSE are defined in windef.h, these values must be
redefined for our own use, for systems such and Linux, QNX, etc.
which do not even provide these in stddef.h.
#ifndef FALSE
#define FALSE 0
#endif
#ifndef TRUE
#define TRUE (!FALSE)
#endif
Structures
The most basic structure is a DATA block. This structure has a
size of the data stored, and an array at the end containing the
data. This structure is allocated by ( sizeof( DATA ) + bytes_to_store)
Occasionally a block of data will have to be statically declared
to a certain size, this is done with the DECLDATA macro. However,
it's reference will often have to be typecast to a PDATA type.
#define DECLDATA(name,sz) struct {_32 size; _8 data[sz];} name
typedef struct DataBlock {
_32 size; // size is sometimes a pointer value...
// this means bad thing when we change platforms...
_8 data[1]; // beginning of var data - this is created size+sizeof(VPA)
} DATA, *PDATA;
An array of pointers stored in a block of data is another basic
structure type. This structure includes a locking variable to
exclude access while it is being resized or updated, or to lock
it from update while it is being read. There are routines which
work on this type: AddLink, SetLink, GetLink, CreateList, DeleteList,
FindLink, DeleteLink. More information may be found in InsertLinkHere.
typedef struct LinkBlock
{
_32 Cnt;
_32 Lock;
POINTER pNode[1];
} LIST, *PLIST;
Where a LIST is oriented more towards random access, sometimes
a more structured access method is desired. The first structure
which is provides this is a LINKSTACK. Methods for accessing this
structure type include: CreateLinkStack, DeleteLinkStack, PeekLink,
PopLink, PushLink. More information may be found in InserLinkHere
typedef struct LinkStack
{
_32 Top;
_32 Cnt;
POINTER pNode[1];
} LINKSTACK, *PLINKSTACK;
Where a LINKSTACK stores only pointers in its stack, a DATASTACK
allocates blocks of data, and may store structures on the stack.
Methods for accessing this include: PopData, PushData, PeekData,
PeekDataEx, CreateDataStack, DeleteDataStack. More informatino on
these methods may be found in InsertLinkHere
typedef struct DataListStack
{
_32 Top; // next avail...
_32 Cnt;
_32 Size;
_8 data[1];
} DATASTACK, *PDATASTACK;
The other top most important method of storeing and retriving data
is a queue. This structure LINKQUEUE stores pointers in a first in
first out method. Methods for accessing this include: CreateLinkQueue,
DeleteLinkQueue, EnqueLink, IsQueueEmpty, DequeLink. More information
on these methods may be found in InsertLinkHere
typedef struct LinkQueue
{
_32 Top;
_32 Bottom;
_32 Cnt;
_32 Lock; // thread interlock using InterlockedExchange semaphore
POINTER pNode[2]; // need two to have distinct empty/full conditions
} LINKQUEUE, *PLINKQUEUE;
Often information about where a function was called from, often
available in __FILE__ and __LINE__ macros in most compilers. These
defines provide a standard way to pass these. These also allow
for easy removal or addition by defining a constant _DEBUG when
compiling. If the symbol is not defined, than non of the parameters
will be generated or required. These are especially used with
the memory library, which may mark the source which allocated a block
or which released a block.
DBG_SRC is used at an actual source point
DBG_VOIDSRC is used when the function being called has a (void)
parameter list
DBG_VOIDPASS is used to define the actual arguments of a function
which may use file and line information.
DBG_PASS is used to append the arguments for file and line
to the end of a function's parameters.
DEB_RELAY is used to pass the information which was given to
a routine to the next, to provide the ACTUAL(?)
caller's information.
// this is for passing FILE, LINE information to allocate
// useful during DEBUG phases only...
#ifdef _DEBUG
// these DBG_ formats are commented out from duplication in sharemem.h
#pragma message "Setting DBG_PASS and DBG_FORWARD to work"
#define DBG_SRC , __FILE__, __LINE__
#define DBG_VOIDSRC __FILE__, __LINE__
#define DBG_VOIDPASS TEXTSTR pFile, _32 nLine
#define DBG_PASS , TEXTSTR pFile, _32 nLine
#define DBG_RELAY , pFile, nLine
#else
#pragma message "Setting DBG_PASS and DBG_FORWARD to be ignored"
#define DBG_SRC
#define DBG_VOIDSRC
#define DBG_VOIDPASS void
#define DBG_PASS
#define DBG_RELAY
#endif
Since between platforms there is no 'common' method for defining
whether a routine is imported, or exported from a shared library,
these defines help when porting shared libraries between windows
and unix.
#if defined( __CYGWIN__ ) && !defined(__STATIC__)
#define LIB_EXPORT __declspec(dllexport)
#ifdef LIBRARY_DEF
#define LIB_IMPORT __declspec(dllexport)
#else
#define LIB_IMPORT __declspec(dllimport)
#endif
#else
#define LIB_EXPORT
#define LIB_IMPORT
#endif