TINE offers a wide range of system recognized data types as shown in the list below.
Compound Data Types
In addition to the fundemental (primitive) data types (e.g. short, float, double, etc.) there are a number of compound format types. For instance, the fundemental types can be paired with a long integer given rise to data formats such as FLTINT (a float value plus a long integer value). Such data types might be important when transfering archived data for example, where the returned data consists of a value plus a UTC timestamp, or for instance when returning a value and a status code. There are also a set of fix-length string format types, such as NAME32, which deliver (an array of) ascii character strings of the given length. There are also a range of data triplets and quadruplets (such as INTFLTINT or NAME16FI or DADDRESS) which are useful in certain circumstances. The most complex format type offered systematically is DUSTRING, offering a quadruplet of data types plus an 80-character string.
User-defined Data Types
In addition to the data type offered, TINE allows user-defined data structures (format CF_STRUCT).
The issue here is the recognition of data sets by client and server over the network. If the client asks for N of something, both sides must know how big (how many bytes) that something is. Furthermore both sides must know how to make sure all the bytes end up in the right order for the platform in question. This is guaranteed to work if you stick to data of a standard format or one of the control system types. If you want to define your own data structure type and use it, things are a bit more complicated but can also work just fine if you pay attention on both the client and server ends.
The first step on each end is to register the structure. You do this at initialization time by declaring a structure tag name and filling in the sizes and locations of the individual elements. Then when a client sends or asks for a structure and it sends the structure tag along with the request, the server knows all about the structure and how to handle it. As an example, we’ll look at another snippet from the sineqm.c routine.
Using tagged structures also has the side benefit of allowing queries from the client-side to determine the structure of the structure. Essentially a client can discover all it needs to know as to how to handle the structure. (see AcquireAndRegisterStruct()).
typedef struct
{
float a[3];
long b[2];
short c[1];
short reserved;
char d[32];
} Test1Struct;
#define Test1StructSize ((sizeof(float)*3) +\
(sizeof(long)*2) +\
(sizeof(short)*1) +\
(sizeof(short)*1) +\
32)
#define MAX_TEST1 10
#define quit(i) { printf("Register struct: out of memory\n"); exit(i); }
void registerStructs(void)
{
if (
AddFieldToStruct(
"TEST1",OFFSETIN(Test1Struct,reserved),1,CF_SHORT,
"reserved")) quit(1);
}
The registerStructs() function above is to be called in an initialization routine on both the client and server end. The client can then simply pass a pointer to (an array of ) the structure in question. The server will then see (an array of ) the structure in question.
The server equipment function might do something like this:
int registerProperties(void)
{
memset(&dout,0,
sizeof(
DTYPE));
strncpy(dout.
dTag,
"TEST1",TAG_NAME_SIZE);
}
int eqm(
char *devName,
char * devProperty,
DTYPE *dout,
DTYPE *din,
short access)
{
int devnr,prpid;
switch (prpid)
{
case PRP_STRUCTTEST:
{
if (!strncmp(dout->
dTag,
"TEST1",TAG_NAME_SIZE))
{
if (access & CA_WRITE)
{
memcpy(&MyTest,din->
data.
vptr,
sizeof(Test1Struct));
}
printf(
"structure TEST1 requested (%d elements)\n",dout->
dArrayLength);
{
((Test1Struct *)(dout->
data.
vptr))[i].a[0] = MyTest.a[0] + cnt + i;
((Test1Struct *)(dout->
data.
vptr))[i].a[1] = MyTest.a[1] + cnt + i;
((Test1Struct *)(dout->
data.
vptr))[i].a[2] = MyTest.a[2] + cnt + i;
((Test1Struct *)(dout->
data.
vptr))[i].b[0] = MyTest.b[0] + cnt + i;
((Test1Struct *)(dout->
data.
vptr))[i].b[1] = MyTest.b[1] + cnt + i;
((Test1Struct *)(dout->
data.
vptr))[i].c[0] = MyTest.c[0] + cnt + i;
strcpy(((Test1Struct *)(dout->
data.
vptr))[i].d,MyTest.d);
}
}
else
{
printf("Untagged structure received !!\n");
}
return 0;
A client application wishing to receive this structure might do something like:
...
Test1Struct st[10];
int i, k, cc;
registerStructs();
strcpy(dout.
dTag,
"TEST1");
cc =
ExecLinkEx(
"/TEST/TestServer/device0",
"StructTest",&dout,NULL,CA_READ,200);
if (cc != 0)
{
printf("Link error : %s\n",erlst[cc]);
return;
}
...
Java examples can be found here. Visual Basic examples can be found here. C# examples can be found here. MatLab examples can be found here.
Tagged structures can be composed of any other TINE data type, and in particular other (registered) tagged structures. In java, the registration API is essentially independent of data type as the 'addField()' method is overloaded to take any type including other TTaggedStructures. In C, one also uses the 'AddFieldToStruct()' routine to register all of the individual fields, regardless of data type, but here one has to pay attention when registering fields which are also structures. In this case, the data type CF_STRUCT only signals that the field is a structure but do does specify 'which' structure. The structure tag is in this case passed along with the field, using the special syntax '<structure tag>field name'.
As an example, consider the following structure, composed of two other structures:
typedef struct
{
int a;
float b;
char t[16];
} StHdr;
typedef struct
{
int c;
float d;
} StBod;
typedef struct
{
StHdr hdr;
StBod body[4];
} StCmp;
typedef struct
{
float amplitude;
float frequency;
float noise;
float phase;
int numberCalls;
char description[64];
} SineInfo;
#define quit(i) { printf("Register struct: out of memory\n"); exit(i); }
void registerStructs(void)
{
static int done = 0;
if (done) return;
done = TRUE;
if (
AddFieldToStruct(
"SineInfo",OFFSETIN(SineInfo,amplitude),1,CF_FLOAT,
"amplitude")) quit(1);
if (
AddFieldToStruct(
"SineInfo",OFFSETIN(SineInfo,frequency),1,CF_FLOAT,
"frequency")) quit(1);
if (
AddFieldToStruct(
"SineInfo",OFFSETIN(SineInfo,noise),1,CF_FLOAT,
"noise")) quit(1);
if (
AddFieldToStruct(
"SineInfo",OFFSETIN(SineInfo,phase),1,CF_FLOAT,
"phase")) quit(1);
if (
AddFieldToStruct(
"SineInfo",OFFSETIN(SineInfo,numberCalls),1,CF_LONG,
"numberCalls")) quit(1);
if (
AddFieldToStruct(
"SineInfo",OFFSETIN(SineInfo,description),64,CF_TEXT,
"description")) quit(1);
if (
AddFieldToStruct(
"StCmp",OFFSETIN(StCmp,hdr),1,CF_STRUCT,
"<StHdr>hdr")) quit(1);
if (
AddFieldToStruct(
"StCmp",OFFSETIN(StCmp,body),4,CF_STRUCT,
"<StBod>body")) quit(1);
}
SineInfo sineInfoTable[NUM_DEVICES];
void init(void)
{
int i;
registerStructs();
strcpy(dout.
dTag,
"SineInfo");
strcpy(dout.
dTag,
"StCmp");
}
Tagged structures can also be composed of so-called variable length format types, such as CF_STRING (an free, mutable string) or CF_AIMAGE (an adjustable image type) or CF_ASPECTRUM (an adjustable spectrum type). For instance consider the following structure registration:
typedef struct
{
float amplitude;
float frequency;
float noise;
float phase;
char *strfields[4];
} FUNKYSTRUCT;
#define quit(i) { printf("Register struct: out of memory\n"); exit(i); }
void registerStructs(void)
{
static int done = 0;
if (done) return;
done = TRUE;
if (addFieldToStruct("Funky",OFFSETIN(FUNKYSTRUCT,amplitude),1,CF_FLOAT,"amplitude")) quit(1);
if (addFieldToStruct("Funky",OFFSETIN(FUNKYSTRUCT,frequency),1,CF_FLOAT,"frequency")) quit(1);
if (addFieldToStruct("Funky",OFFSETIN(FUNKYSTRUCT,noise),1,CF_FLOAT,"noise")) quit(1);
if (addFieldToStruct("Funky",OFFSETIN(FUNKYSTRUCT,phase),1,CF_FLOAT,"phase")) quit(1);
if (addFieldToStruct("Funky",OFFSETIN(FUNKYSTRUCT,strfields),4,CF_STRING,"strings")) quit(1);
if (addFieldToStruct("Funky",OFFSETIN(FUNKYSTRUCT,imgfield),1,CF_AIMAGE,"image")) quit(1);
if (sealTaggedStruct("Funky",sizeof(FUNKYSTRUCT),10)) quit(1);
}
SineInfo sineInfoTable[NUM_DEVICES];
void init(void)
{
int i;
registerStructs();
strcpy(dout.
dTag,
"Funky");
RegisterPropertyInformation(SINEQM_TAG,
"FunkyInfo",&dout,NULL,CA_READ,AT_SCALAR,0,
"Sine Curve and other Information",PRP_FUNKYINFO,NULL);
strcpy(dout.
dTag,
"StCmp");
}
Here, there the structure as defined in C code contains pointers. The string field is an array of free strings (array of pointers) and the image field contains a pointer to the image frame. Using this structure to send items implies the (temporary) assigning of the pointer references and using this structure to receive items implies that the references assigned following the call completion or callback are 'volatile' and the associated data should be copied into a 'safe' location prior to the next call or callback.
A server processing such a structure might do something similar to the following:
int registerProperties(void)
{
memset(&dout,0,
sizeof(
DTYPE));
strncpy(dout.
dTag,
"TEST1",TAG_NAME_SIZE);
strcpy(dout.
dTag,
"Funky");
}
#define NUM_VALUES 100000
BYTE frame[NUM_VALUES];
int gImageFrameSize = NUM_VALUES;
void pushImageBytes(
DIMAGE *img)
{
static int imgSeed = 1;
int i;
for (i=0; i<NUM_VALUES; i++) frame[i] = imgSeed+i;
imgSeed = (imgSeed + 1) % 155;
}
int eqm(
char *devName,
char * devProperty,
DTYPE *dout,
DTYPE *din,
short access)
{
int devnr,prpid;
FUNKYSTRUCT *fs;
switch (prpid)
{
case PRP_FUNKYINFO:
{
printf("amplitude: %g\n",fs->amplitude);
printf("frequency: %g\n",fs->frequency);
printf("phase: %g\n",fs->phase);
printf("noise: %g\n",fs->noise);
printf("%s\n",fs->strfields[0]);
printf("%s\n",fs->strfields[1]);
printf("%s\n",fs->strfields[2]);
printf("%s\n",fs->strfields[3]);
memcpy(&gImage,fs->imgfield,IMAGE_HDR_SIZE);
if (fs->imgfield.frameBufferSize < NUM_VALUES)
{
memcpy(frame,fs->imgfield.frameBuffer,fs->imgfield.frameBufferSize);
gImageFrameSize = fs->imgfield.frameBufferSize;
}
}
{
{
memset(&fs[i],0,sizeof(FUNKYSTRUCT));
fs[i].amplitude = sineInfoTable[(i+devnr)%NUM_DEVICES].amplitude;
fs[i].frequency = sineInfoTable[(i+devnr)%NUM_DEVICES].frequency;
fs[i].phase = sineInfoTable[(i+devnr)%NUM_DEVICES].phase;
fs[i].noise = sineInfoTable[(i+devnr)%NUM_DEVICES].noise;
fs[i].strfields[0] = sineInfoTable[(i+devnr)%NUM_DEVICES].description;
fs[i].strfields[1] = "and another string";
fs[i].strfields[2] = "and yet another";
fs[i].strfields[3] = "just a filler";
pushImageBytes(&fs[i].imgfield);
}
}
return 0;
A client wishing to receive such a structure might do something like:
BYTE frame[10][100000];
...
FUNKYSTRUCT st[10];
int i, k, cc;
registerStructs();
strcpy(dout.
dTag,
"Funky");
cc =
ExecLinkEx(testTarget,
"FunkyInfo",&dout,NULL,CA_READ,200);
if (cc != 0)
{
printf("Link error : %s\n",erlst[cc]);
return;
}
{
printf("[%d] ampl %g freg %g noise %g phase %g\n",i,st[i].amplitude,st[i].frequency,st[i].noise,st[i].phase);
for (k=0; k<4; k++)
{
printf("[%d,%d] %s\n",i,k,st[i].strfields[k]);
}
printf("cam port id %d\n",st[i].imgfield.sourceHeader.cameraPortId);
if (st[i].imgfield.frameBufferSize < 100000)
{
memcpy(frame[i],st[i].imgfield.frameBuffer[0],st[i].imgfield.frameBufferSize);
}
}
...
Special Format Types
Some special purpose data types are also available for use. These include the variable length formats CF_SPECTRUM which passes a USTRING header plus a variable length of float values and CF_IMAGE which passes a DIMAGE header plus a variable length video frame (byte array). A pre-packaged data type DSPECTRUM offers a float array of 4096 bytes, otherwise the user is free to make use of the format and map to a USTRING + float array of any dimension of his choosing. Using the DIMAGE data type requires passing the location of the buffer to hold the video frame which must contain enough room to buffer the maximum sized video frame.
In addition, one can specifically make use of the adjustable variants of SPECTRUM or IMAGE for use in arrays. These correspond to the format type specifications CF_ASPECTRUM and CF_AIMAGE, and map to the data type definitions ASPETRUM and DIMAGE. Note that both CA_ASPECTRUM and CF_AIMAGE take the number of array elements as the 'dArrayLength' field of the DTYPE object (C-Lib) or TDataType object (jave, .NET).
int getspectarray(void)
{
int i, cc;
cc =
ExecLinkEx(
"/TEST/SineServer/SineGen0",
"SineSpectrum",&dout,NULL,CA_READ|CA_MUTABLE,1000);
if (cc == 0)
{
{
printf("%s (%g): %d values\n",asp[i].comment,asp[i].s_inc,asp[i].spectBufferSize);
displaySineSpectrum(asp[i].spectBufferSize,asp[i].spectBuffer);
}
}
}
Bit fields make use of the format types CF_BITFIELD8, CF_BITFIELD16, and CF_BITFIELD32. Bit fields registered similar to structures, with the exception that the object length is known a priori. under most circumstance the users does not make use of the data type DBITFIELD but uses either the registration routines OpenBitField() and AddFieldToBitField() or the access routines GetFieldFromBitfield() and GetBitfieldAsString().
The data type CF_HISTORY is a special format used for archive data retrieval and is designed to be able to provide a data timestamp and other data stamps and to carry any other format type. This is used exclusively in archive calls.
The data type CF_STRING can be used to transport non-fixed length string arrays. Fixed length string arrays (e.g. arrays of NAME16, NAME32, NAME64, or USTRING entities) are often the most efficient way of passing arrays of string data, as they can be easily traversed, individual elements can be easily located, and there is no sudden memory reallocation when the carried string lengths change. However, the ability to transfer and to think in terms of an array of strings of any length is freqently desireable (no matter how inefficent it might turn out to be). Keep in mind that a string itself is fundementally an array of characters terminated by the character '0'. So a string array becomes an array of pointers. The TINE format CF_STRING will manage all of the necessary string (re-)allocation for the caller. An example of server code written in C making use of CF_STRING is given below. We see that even in C this is a straightforward matter, even when forced to deal with pointers and the like.
char *testStrings[] =
{ "string number 1","string number 2","string number 3","string number 4",
"really and truly, fantastically, incredibly, unimaginatively, you-wouldn't-believe-it's-possible, long string 5",
"really and truly, fantastically, incredibly, unimaginatively, you-wouldn't-believe-it's-possible, long string 6",
"really and truly, fantastically, incredibly, unimaginatively, you-wouldn't-believe-it's-possible, long string 7",
"really and truly, fantastically, incredibly, unimaginatively, you-wouldn't-believe-it's-possible, long string 8",
"str 9",
"str 10"
};
int numStrings = sizeof(testStrings)/sizeof(testStrings[0]);
int eqm(
char *devName,
char * devProperty,
DTYPE *dout,
DTYPE *din,
short access)
{
int devnr,prpid;
switch (prpid)
{
case PRP_STRINGARRAY:
{
{
}
}
return 0;
}
}
An example of client code receiving a string array using CF_STRING is given below.
char *strings[10];
int cc, i;
cc =
ExecLinkEx(
"/TEST/WinSineServer/SineGen0",
"StringArray",&dout,NULL,CA_READ,1000);
printf("call returned: %d\n",cc);
if (cc == 0)
{
for (i=0; i<10; i++) printf("%s\n",strings[i]);
}
CF_STRING may also be used within tagged structures.
List of format type macro definitions:
- CF_NULL
- typedef C: NULL vb: vbNull java: null
- size: 0 bytes
- accepted text representation: "NULL" or empty string
- CF_TEXT (alias CF_CHAR)
- typedef c: char vb: String java: char
- size: 1 byte
- In Visual Basic beware of unicode character representation!
- accepted text representation in database files: "TEXT", "CHAR"
- CF_BYTE (alias CF_INT8)
- typedef c: BYTE vb: Byte java: byte
- size: 1 byte
- accepted text representation in database files: "BYTE", "INT8"
- CF_BIT
- typedef c: BYTE vb: Byte java: byte
- size: 1 bit
- BIT format returns a 0 or 1 and is carried as a 4-byte integer
- accepted text representation in database files: "BIT"
- CF_INT16 (alias CF_SHORT, CF_INTEGER)
- typedef c: short vb: Integer java: short
- size: 2 bytes
- accepted text representation in database files: "INT16", "SHORT"
- CF_INT32 (alias CF_LONG)
- typedef c: long vb: Long java: int
- size: 4 bytes
- accepted text representation in database files: "INT32", "LONG"
- CF_INT64 (alias CF_DLONG)
- typedef c: (depends on platform) vb6: (doesn't exist) java: long
- size: 8 bytes
- accepted text representation in database files: "INT64", "DLONG"
- CF_BOOLEAN
- typedef c: long vb: Long java: int
- size: 4 bytes
- accepted text representation in database files: "BOOLEAN"
- CF_FLOAT
- typedef c: float vb: Single java: float
- size: 4 bytes
- accepted text representation in database files: "FLOAT", "SINGLE"
- CF_DOUBLE
- typedef c: double vb: Double java: double
- size: 8 bytes
- accepted text representation in database files: "DOUBLE"
- CF_STRUCT
- typedef c: struct vb: Type java: class
- size: 1 byte
- If 'tagged structures' are used then the size is the size of the structure in bytes.
- accepted text representation in database files: "STRUCT"
- CF_NAME8 (alias CF_CHAR8, CF_STRING8)
- typedef NAME8
- size: 8 bytes
- accepted text representation in database files: "NAME8", "CHAR8"
- CF_NAME16 (alias CF_CHAR16, CF_STRING16)
- typedef NAME16
- size: 16 bytes
- accepted text representation in database files: "NAME16", "CHAR16"
- CF_NAME32 (alias CF_CHAR32, CF_STRING32)
- typedef NAME32
- size: 32 bytes
- accepted text representation in database files: "NAME32", "CHAR32"
- CF_NAME48 (alias CF_CHAR48, CF_STRING48)
- typedef NAME48
- size: 48 bytes
- accepted text representation in database files: "NAME48", "CHAR48"
- CF_NAME64 (alias CF_CHAR64, CF_STRING64)
- typedef NAME64
- size: 64 bytes
- accepted text representation in database files: "NAME64", "CHAR64"
- CF_FLTFLT (alias CF_FF, CF_XY, CF_POINT)
- typedef FLTFLT
- size: 8 bytes (1 float + 1 float)
- accepted text representation in database files: "FLTFLT", "XY", "POINT"
- CF_FLTINT (alias CF_FI)
- typedef FLTINT
- size: 8 bytes (1 float + 1 long integer)
- accepted text representation in database files: "FLTINT", "FI"
- CF_LNGINT (alias INTINT, CF_II, CF_LI, CF_LL)
- typedef LNGINT
- size: 8 bytes (1 long interger + 1 long integer)
- accepted text representation in database files: "LNGINT", "INTINT", "II"
- CF_DBLDBL
- typedef DBLDBL
- size: 16 bytes (1 double + 1 double)
- accepted text representation in database files: "DBLDBL"
- CF_NAME8I (alias CF_CHAR8I)
- typedef NAME8I
- size: 12 bytes (8 chars + 1 long integer)
- accepted text representation in database files: "NAME8I", "CHAR8I"
- CF_NAME16I (alias CF_CHAR16I)
- typedef NAME16I
- size: 20 bytes (16 chars + 1 long integer)
- accepted text representation in database files: "NAME16I", "CHAR16I"
- CF_NAME32I (alias CF_CHAR32I)
- typedef NAME32I
- size: 36 bytes (32 chars + 1 long integer)
- accepted text representation in database files: "NAME32I", "CHAR32I"
- CF_NAME48I (alias CF_CHAR48I)
- typedef NAME48I
- size: 52 bytes (48 chars + 1 long integer)
- accepted text representation in database files: "NAME48I", "CHAR48I"
- CF_NAME64I (alias CF_CHAR64I)
- typedef NAME64I
- size: 68 bytes (64 chars + 1 long integer)
- accepted text representation in database files: "NAME64I", "CHAR64I"
- CF_NAME16FI (alias CF_NAMEFI, CF_CHAR16FI, CF_STRING16FI)
- typedef NAME16FI
- size: 24 bytes (16 chars + 1 float + 1 long integer)
- accepted text representation in database files: "NAME16FI", "CHAR16FI", "NAME16FLTINT"
- CF_NAME16II (alias CF_NAMEII, CF_CHAR16II, CF_STRING16II)
- typedef NAME16II
- size: 24 bytes (16 chars + 1 long integer + 1 long integer)
- accepted text representation in database files: "NAME16II", "CHAR16II", "NAME16INTINT"
- CF_NAME16DBLDBL (alias CF_NAMEDBLDBL)
- typedef NAME16DBLDBL
- size: 32 bytes (16 chars + 1 double + 1 double)
- accepted text representation in database files: "NAME16DBLDBL"
- CF_NAME32DBLDBL (alias CF_CHAR32DBLDBL, CF_STRING32DBLDBL)
- typedef NAME32DBLDBL
- size: 48 bytes (32 chars + 1 double + 1 double)
- accepted text representation in database files: "NAME32DBLDBL"
- CF_NAME64DBLDBL (alias CF_CHAR64DBLDBL, CF_STRING64DBLDBL)
- typedef NAME64DBLDBL
- size: 80 bytes (64 chars + 1 double + 1 double)
- accepted text representation in database files: "NAME64DBLDBL"
- CF_INTFLTINT (alias CF_TDS, CF_IFI)
- typedef INTFLTINT
- size: 12 bytes (1 long integer + 1 float + 1 long integer)
- accepted text representation in database files: "INTFLTINT", "IFI", "TDS"
- CF_FLTFLTINT (alias CF_XYS, CF_FFI)
- typedef FLTFLTINT
- size: 12 bytes (1 float + 1 float + 1 long integer)
- accepted text representation in database files: "FLTFLTINT", "FFI", "XYS"
- CF_FLTINTINT (alias CF_FII, CF_FIS)
- typedef FLTINTINT
- size: 12 bytes (1 float + 1 long integer + 1 long integer)
- accepted text representation in database files: "FLTINTINT", "FIS"
- CF_INTINTINT (alias CF_III)
- typedef INTINTINT
- size: 12 bytes (1 long integer + 1 long integer + 1 long integer)
- accepted text representation in database files: "INTINTINT", "III"
- CF_FILTER (alias CF_IFFF, CF_INTFLTFLTFLT)
- typedef DFILTER
- size: 16 bytes (1 long integer + 1 float + 1 float + 1 float)
- accepted text representation in database files: "INTFLTFLTFLT", "IFFF", "FILTER"
- CF_ADDRESS (alias CF_IIII, CF_INTINTINTINT)
- typedef DADDRESS
- size: 16 bytes (1 long integer + 1 long integer + 1 long integer + 1 long integer)
- accepted text representation in database files: "INTINTINT", "IIII", "ADDRESS"
- CF_WINDOW (alias CF_TTII)
- typedef DWINDOW
- size: 16 bytes (1 long integer + 1 long integer + 1 long integer + 1 long integer)
- accepted text representation in database files: "WINDOW", "TTII"
- CF_FWINDOW (alias CF_IIFF CF_INTINTFLTFLT)
- typedef FWINDOW
- size: 16 bytes (1 long integer + 1 long integer + 1 float + 1 float)
- accepted text representation in database files: "FWINDOW", "INTINTFLTFLT", "IIFF"
- CF_FLTINTFLTINT (alias CF_FIFI)
- typedef FLTINTFLTINT
- size: 16 bytes (1 float + 1 long integer + 1 float + 1 long integer)
- accepted text representation in database files: "FLTINTFLTINT", "FIFI"
- CF_USTRING
- typedef DUSTRING
- size: 96 bytes (80 chars + 1 long integer + 1 float + 1 float + 1 long integer)
- accepted text representation in database files: "USTRING"
- CF_SPECTRUM
- typedef DSPECTRUM
- size: 16480 bytes (DUSTRING + 4096 floats)
- accepted text representation in database files: "SPECTRUM"
- CF_ASPECTRUM
- typedef ASPECTRUM
- size: 104 bytes + adjustable float array
- accepted text representation in database files: "ASPECTRUM"
- CF_UNAME (alias CF_IFFFNAME CF_IFFFNAME16)
- typedef DUNAME
- size: 32 bytes (1 long integer + 1 float + 1 float + 1 float + 1 16 char name)
- accepted text representation in database files: "UNAME", "IFFFNAME", "INTFLTFLTFLTNAME"
- CF_XML
- typedef c: char vb: String java: char
- size: 1 byte
- accepted text representation in database files: "XML"
- CF_DBLDBLDBL
- typedef DBLDBLDBL
- size: 24 bytes
- accepted text representation in database files: "DBLDBLDBL"
- CF_NAME64DBLDBLDBL (alias CF_CHAR64DBLDBLDBL, CF_STRING64DBLDBLDBL)
- typedef NAME64DBLDBLDBL
- size: 88 bytes
- accepted text representation in database files: "NAME64DBLDBLDBL"
- CF_BITFIELD8
- typedef DBITFIELD
- size: 1 byte
- accepted text representation in database files: "BITFIELD8"
- CF_BITFIELD16
- typedef DBITFIELD
- size: 2 bytes
- accepted text representation in database files: "BITFIELD16"
- CF_BITFIELD32
- typedef DBITFIELD
- size: 4 bytes
- accepted text representation in database files: "BITFIELD32"
- CF_BITFIELD64 (not yet implemented)
- typedef DBITFIELD
- size: 8 byte
- accepted text representation in database files: "BITFIELD64"
- CF_NAME64DBL (alias CF_CHAR64DBL, CF_STRING64DBL)
- typedef NAME64DBL
- size: 72 bytes
- accepted text representation in database files: "NAME64DBL"
- CF_IMAGE
- typedef DIMAGE
- size: 6000188 bytes (188 bytes header + 6 MB frame)
- accepted text representation in database files: "IMAGE"
- CF_AIMAGE
- typedef DIMAGE
- size: 196 bytes + adjustable image frame array
- accepted text representation in database files: "AIMAGE"
- CF_HISTORY
- typedef none (12-byte history header + carried type)
- size: 12 bytes + carried format
- (do not use in database files!)
- CF_STRING
- typedef *char[]
- size: 1 byte (dArrayLength gives total string capacity)
- accepted text representation in database files: "STRING"
- CF_KEYVALUE
- typedef *char[]
- size: 1 byte (dArrayLength gives total string capacity)
- accepted text representation in database files: "KEYVALUE"
- note: nominally equivalent to type CF_STRING but should contain a ':' separator between a 'key' token and a 'value' token.