BEA Logo BEA MessageQ Release 5.0

  Corporate Info  |  News  |  Solutions  |  Products  |  Partners  |  Services  |  Events  |  Download  |  How To Buy

 

   MessageQ Doc Home   |   FML Programmer's Guide   |   Previous Topic   |   Next Topic   |   Contents   

Field Manipulation Functions

 

Introduction

This chapter describes all FML32 functions exception run-time mapping (which is described in Chapter 4). In this chapter you will learn:

FML and FML32

There are two variants of FML. The original FML interface is based on 16-bit values for the length of fields and contains information identifying fields (hence FML16). FML16 is limited to 8191 unique fields, individual field lengths of up to 64K bytes, and a total fielded buffer size of 64K.

A second interface, FML32, uses 32-bit values for field lengths and identifiers. It allows for about 30 million fields, and field and buffer lengths of about 2 billion bytes. The definitions, types, and function prototypes for FML32 are in fml32.h. Functions live in -lfml32.

BEA MessageQ supports only FML32. Do not use 16-bit FML functions in developing MessageQ applications.

The names of all definitions, types, and functions for FML32 have a "32" suffix (for example, MAXFBLEN32, FBFR32, FLDID32, FLDLEN32, Fchg32(), and error code Ferror32()). Also the environment variables are suffixed with "32" (for example, FLDTBLDIR32 and FIELDTBLS32). For FML32, a fielded buffer pointer is of type "FBFR32 *", a field length has the type FLDLEN32, and the number of occurrences of a field has the type FLDOCC32. Also note that the default required alignment for FML32 buffers is 4-byte alignment.

FML32 Parameters

To make it easier to remember the parameters for the FML32 functions, a convention has been adopted for the sequence of function parameters. FML32 parameters appear in the following sequence:

  1. For functions that require a pointer to a fielded buffer (FBFR32), this parameter is first. If a function takes two fielded buffer pointers (such as the transfer functions), the destination buffer comes first followed by the source buffer. A fielded buffer pointer must point to an area that is aligned on a short boundary (or an error is returned with Ferror32() set to FALIGNERR) and the area must be a fielded buffer (or an error is returned with Ferror32() set to FNOTFLD).

  2. For the input/output functions, a pointer to a stream follows the fielded buffer pointer.

  3. For functions that need one, a field identifier (type FLDID32) appears next (in the case of Fnext32(), it is a pointer to a field identifier).

  4. For functions that need a field occurrence (type FLDOCC32), this parameter comes next (for Fnext32(), it is a pointer to an occurrence number).

  5. In functions where a field value is passed to or from the function, a pointer to the beginning of the field value is given next (defined as a character pointer but may be cast from any other pointer type).

  6. When a field value is passed to a function that contains a character array (carray) field, you must specify its length as the next parameter (type FLDLEN32). For functions that retrieve a field value, a pointer to the length of the retrieval buffer must be passed to the function and this length parameter is set to the length of the value retrieved.

  7. A few functions require special parameters and differ from the preceding conventions; these special parameters appear after the above parameters and will be discussed in the individual function descriptions.

  8. The following NULL values are defined for the various field types: 0 for short and long; 0.0 for float and double; \0 for string (1 byte in length); and a zero-length string for carray.

Field Identifier Mapping Functions

Several functions allow the programmer to query field tables or field identifiers for information about fields during program execution.

Fldid32

Fldid32() returns the field identifier for a given valid field name and loads the field name/fieldid mapping tables from the field table files, if they do not already exist:

FLDID32
Fldid32(char *name)

where name is a valid field name.

The space used by the mapping tables in memory can be freed using the Fnmid_unload32() function. Note that these tables are separate from the tables loaded and used by the Fname32() function.

Fname32

Fname32() returns the field name for a given valid field identifier and loads the fieldid/name mapping tables from the field table files, if they do not already exist:

char *
Fname32(FLDID32 fieldid)

where fieldid is a valid field identifier.

The space used by the mapping tables in memory can be freed using the Fidnm_unload32() function. Note that these tables are separate from the tables loaded and used by the Fldid32() function.

Fldno32

Fldno32() extracts the field number from a given field identifier:

FLDOCC32
Fldno32(FLDID32 fieldid)

where fieldid is a valid field identifier.

Fldtype32

Fldtype32() extracts the field type (an integer, as defined in fml32.h) from a given field identifier.

int
Fldtype32(FLDID32 fieldid)

where fieldid is a valid field identifier.

Table 5-1 shows the possible values returned by Fldtype32() and their meanings.

Table 5-1 Field Types Returned by Fldtype

Return Value

Meaning

0

short integer

1

long integer

2

character

3

single-precision float

4

double-precision float

5

null-terminated string

6

character array

Ftype32

Ftype32() returns a pointer to a string containing the name of the type of a field given a field identifier:

char *
Ftype32(FLDID32 fieldid)

where fieldid is a valid field identifier.

For example:

char *typename
. . .
typename = Ftype32(fieldid);

returns a pointer to one of the following strings: short, long, char, float, double, string, or carray.

Fmkfldid32

As part of an application generator, or to reconstruct a field identifier, it might be useful to be able to make a field identifier from a type specification and an available field number. Fmkfldid32() provides this functionality:

FLDID32
Fmkfldid32(int type, FLDID32 num)

where

t type is a valid type (an integer; see Fldtype32(), above)

t num is a field number (it should be an unused field number, to avoid confusion with existing fields)

Buffer Allocation and Initialization

Most FML32 functions require a pointer to a fielded buffer as an argument. The typedef FBFR32 is available for declaring such pointers, as in this example:

FBFR32 *fbfr32;

In this chapter, the variable fbfr32 will be used to mean a pointer to a fielded buffer.

Never attempt to declare fielded buffers themselves, only pointers to them. The functions used to reserve space for fielded buffers are explained in the following pages, but first we will describe a function that can be used to determine whether a given buffer is in fact a fielded buffer.

Fielded32

Fielded32() is used to test whether the specified buffer is fielded.

int
Fielded32(FBFR32 *fbfr32)

Fielded32() returns true (1) if the buffer is fielded. If the buffer is not fielded, Fielded32() returns false (0) and does not set Ferror32().

Fneeded32

The amount of memory to allocate for a fielded buffer depends on the maximum number of fields that buffer will contain and the total amount of space needed for all the field values. The function Fneeded can be used to determine the amount of space (in bytes) needed for a fielded buffer; it takes the number of fields and the space needed for all field values (in bytes) as arguments.

long
Fneeded32(FLDOCC32 F, FLDLEN32 V)

where

t F is the number of fields

t V is the space for field values, in bytes

The space needed for field values is computed by estimating the amount of space that would be required by each field value if stored in standard structures (for example, a long is stored as a long and needs four bytes). For a variable length field, you should estimate the average amount of space needed. The space calculated by Fneeded includes a fixed overhead for each field in addition to the space needed for the field values.

Once you obtain the estimate of space from Fneeded32(), you can allocate the desired number of bytes using malloc(3) and set up a pointer to the allocated memory space. For example, the following allocates space for a fielded buffer large enough to contain 25 fields and 300 bytes of values:

#define NF 25
#define NV 300
extern char *malloc;
. . .
if((fbfr32 = (FBFR32 *)malloc(Fneeded32(NF, NV))) == NULL)
F_error("pgm_name"); /* no space to allocate buffer */

However, this allocated memory space is not yet a fielded buffer. Finit32() must be used to initialize it.

Finit32

The Finit32() function initializes an allocated memory space as a fielded buffer.

int
Finit32(FBFR32 *fbfr32, FLDLEN32 buflen)

where

t fbfr32 is a pointer to an uninitialized fielded buffer

t buflen is the length of the buffer, in bytes

A call to Finit32() to initialize the memory space allocated in the example above (in the Fneeded32() section) would look like the following:

Finit32(fbfr32, Fneeded32(NF, NV));

Now fbfr32 points to an initialized, empty fielded buffer. Up to Fneeded32(NF, NV) bytes minus a small amount are available in the buffer to hold fields.

Note: The numbers used in the malloc(3) call (see the example in the Fneeded32() section) and Finit32() call must be the same.

Falloc32

Calls to Fneeded32(), malloc(3) and Finit32() may be replaced by a single call to Falloc32(), which allocates the desired amount of space and initializes the buffer.

FBFR32 *
Falloc32(FLDOCC32
F, FLDLEN32 V)

where

t F is the number of fields

t V is the space for field values, in bytes

A call to Falloc32() that would replace the examples above would look like the following:

extern FBFR32 *Falloc32;
. . .
if((fbfr32 = Falloc32(NF, NV)) == NULL)
F_error("pgm_name"); /* couldn't allocate buffer */

Storage allocated with Falloc32() (or Fneeded32(), malloc(3) and Finit32()) should be freed with Ffree32().

Ffree32

Ffree32() is used to free memory space allocated as a fielded buffer.

int
Ffree32(FBFR32 *fbfr32)

where fbfr32 is a pointer to a fielded buffer

For example:

 #include  <fml32.h>
. . .
if(Ffree32(fbfr32) 0)
F_error("pgm_name"); /* not fielded buffer */

Ffree32() is recommended as opposed to free(3), because Ffree32() will invalidate a fielded buffer whereas free(3) will not. It is necessary to invalidate fielded buffers because malloc(3) re-uses memory that has been freed, without clearing it. Thus, if free(3) were used, it would be possible for malloc to return a piece of memory that looks like a valid fielded buffer, but is not.

Space for a fielded buffer may also be reserved directly. The buffer must begin on a short boundary.

The following code is analogous to the preceding example but Fneeded32() cannot be used to size the static buffer since it is not a macro.

/* the first line aligns the buffer */
static short buffer[500/sizeof(short)];
FBFR32 *fbfr32=(FBFR32 *)buffer;
. . .
Finit32(fbfr32, 500);

It should be emphasized that the following code is quite wrong:

FBFR32 badfbfr;
. . .
Finit32(&badfbfr, Fneeded32(NF, NV));

The structure for FBFR32 is not defined in the user header files so this code will produce a compilation error.

Fsizeof32

Fsizeof32() returns the size of a fielded buffer in bytes:

long
Fsizeof32(FBFR32 *fbfr32)

where fbfr32 is a pointer to a fielded buffer

For example:

long bytes;
. . .
bytes = Fsizeof32(fbfr32);

Fsizeof32() returns the same number that Fneeded32() returned when the fielded buffer was originally allocated.

Funused32

Funused32() may be used to determine how much space is available in a fielded buffer for additional data:

long
Funused32(FBFR32 *fbfr32)

where fbfr32 is a pointer to a fielded buffer

For example:

long unused;
. . .
unused = Funused32(fbfr32);

Note that Funused32() does not indicate where, in the buffer, the unused bytes are located; it indicates only the number of unused bytes.

Fused32

Fused32() may be used to determine how much space is used in a fielded buffer for data and overhead:

long
Fused32(FBFR32 *fbfr32)

where fbfr32 is a pointer to a fielded buffer

For example:

long used;
. . .
used = Fused32(fbfr32);

Note that Fused32() does not indicate where, in the buffer, the used bytes are located; it indicates only the number of used bytes.

Frealloc32

At some point (such as during the addition of a new field value) the buffer may run out of space. Frealloc32() can be used to increase (or decrease) the size of the buffer:

FBFR32 *
Frealloc32(FBFR32 *fbfr32, FLDOCC32 nf, FLDLEN32 nv)

where

t fbfr32 is a pointer to a fielded buffer

t nf is the new number of fields or 0

t nv is the new space for field values, in bytes

For example:

FBFR32 *newfbfr32;
. . .
if((newfbfr32 = Frealloc32(fbfr32, NF+5, NV+300)) == NULL)
F_error32("pgm_name"); /* couldn't re-allocate space */
else
fbfr32 = newfbfr32; /* assign new pointer to old */

In this case, the application needed to remember the number of fields and the number of bytes of space previously allocated for field values. Note that the arguments to Frealloc32() (as with its counterpart realloc(3)) are absolute values, not increments. This example will not work if space needs to be re-allocated several times.

The following example shows a second way of incrementing the allocated space:

/* define the increment size when buffer out of space */
#define INCR 400
FBFR32 *newfbfr32;
. . .
if((newfbfr32 = Frealloc32(fbfr32, 0, Fsizeof(fbfr32)+INCR)) == NULL)
F_error32("pgm_name"); /* couldn't re-allocate space */
else
fbfr32 = newfbfr32; /* assign new pointer to old */

Note that you do not need to know the number of fields or the amount of space for field values with which the buffer was last initialized. Thus, the easiest way to increase the size is to use the current size plus the increment as the space for field values. The above example could be executed as many times as needed without remembering past executions or values. The user need not call Finit32() after calling Frealloc32().

If the amount of additional space requested in the call to Frealloc32() is contiguous to the old buffer, newfbfr32 and fbfr32 in the examples above will be the same. However, defensive programming dictates that the user should declare newfbfr32 as a safeguard against the case where either a new value or NULL is returned. If Frealloc32() fails, do not use fbfr32 again.

Note: You cannot reduce the size of a fielded buffer to less than the amount of space (in bytes) currently being used in the buffer.

Functions for Moving Fielded Buffers

The only restriction on the location of fielded buffers is that they must be aligned on a short boundary. Otherwise, fielded buffers are position-independent and may be moved freely around in memory.

Fmove32

If src points to a fielded buffer and dest points to an area of storage big enough to hold it, then the following might be used to move the fielded buffer:

FBFR32 *src;
char *dest;
. . .
memcpy(dest, src, Fsizeof32(src));

The function memcpy (one of the C runtime memory management functions) moves the number of bytes indicated by its third argument from the area pointed to by its second argument to the area pointed to by its first argument.

While memcpy may be used to copy a fielded buffer, the destination copy of the buffer looks just like the source copy. In particular, for example, the destination copy has the same number of unused bytes as the source buffer.

Fmove32() acts like memcpy, but does not need an explicit length (it is computed):

int
Fmove32(char *dest, FBFR32 *src)

where

t dest is a pointer to the destination buffer

t src is a pointer to the source fielded buffer

For example:

FBFR32 *src;
char *dest;
. . .
if(Fmove32(dest,src) < 0)
F_error("pgm_name");

Fmove32() checks that the source buffer is indeed a fielded buffer, but does not modify the source buffer in any way.

The destination buffer need not be a fielded buffer (that is, it need not have been allocated using Falloc32()), but it must be aligned on a short boundary (4-byte alignment for FML32). Thus, Fmove32() provides an alternative to Fcpy32() (see below) when it is desired to copy a fielded buffer to a non-fielded buffer, but Fmove32() does not check to make sure there is enough room in the destination buffer to receive the source buffer.

Fcpy32

Fcpy32() is used to overwrite one fielded buffer with another:

int
Fcpy32(FBFR32 *dest, FBFR32 *src)

where

t dest is a pointer to the destination fielded buffer

t src is a pointer to the source fielded buffer

Fcpy32() preserves the overall buffer length of the overwritten fielded buffer; thus, Fcpy32() is useful for expanding or reducing the size of a fielded buffer. For example:

FBFR32 *src, *dest;
. . .
if(Fcpy32(dest, src) 0)
F_error32("pgm_name");

Unlike Fmove32(), where dest could point to an uninitialized area, Fcpy32() expects dest to point to an initialized fielded buffer (allocated using Falloc32()) and also checks to see that it is big enough to accommodate the data from the source buffer.

Note: You cannot reduce the size of a fielded buffer to less than the amount of space (in bytes) currently being used in the buffer.

As with Fmove32(), the source buffer is not modified by Fcpy32().

Field Access and Modification Functions

This section discusses how to update and access fielded buffers using the field types of the fields without doing any conversions. The functions that allow you to convert data from one type to another upon transfer to/from a fielded buffer are listed under "Conversion Functions" later in this chapter.

Fadd32

The Fadd32() function adds a new field value to the fielded buffer.

int
Fadd32(FBFR32 *fbfr32, FLDID32 fieldid, char *value, FLDLEN32 len)

where

t fbfr32 is a pointer to a fielded buffer

t fieldid is a field identifier

t value is a pointer to a new value. Its type is shown as char*, but when it is used, its type must be the same type as the value to be added (see below)

t len is the length of the value if its type is FLD_CARRAY

If no occurrence of the field exists in the buffer, then the field is added. If one or more occurrences of the field already exist, then the value is added as a new occurrence of the field, and is assigned an occurrence number 1 greater than the current highest occurrence. (To add a specific occurrence, Fchg32() must be used.)

Fadd32(), like all other functions that take or return a field value, expects a pointer to a field value, never the value itself.

If the field type is such that the field length is fixed (short, long, char, float, or double) or can be determined (string), the field length need not be given (it is ignored). If the field type is a character array, the length must be specified; the length is defined as type FLDLEN32. For example:

FLDID32 fieldid, Fldid32;
FBFR32 *fbfr32;
. . .
fieldid = Fldid32("fieldname");
if(Fadd32(fbfr32, fieldid, "new value", (FLDLEN32)9) < 0)
F_error32("pgm_name");

gets the field identifier for the desired field and adds the field value to the buffer.

It is assumed (by default) that the native type of the field is a character array so that the length of the value must be passed to the function. If the value being added is not a character array, the type of value must reflect the type of the value it points to; for instance, the following example adds a long field value:

long lval;
. . .
lval = 123456789;
if(Fadd32(fbfr32, fieldid, lval, (FLDLEN32)0) < 0)
F_error32("pgm_name");

For character array fields, null fields may be indicated by a length of 0. For string fields, the null string may be stored since the NULL terminating byte is actually stored as part of the field value: a string consisting of only the NULL terminating byte is considered to have a length of 1. For all other types (fixed length types), you may choose some special value that is interpreted by the application as a NULL, but the size of the value will be taken from its field type (e.g., length of four for a long) regardless of what value is actually passed. Passing a NULL value address will result in an error (FEINVAL).

Fappend32

The Fappend32() function appends a new field value to the fielded buffer.

int
Fappend32(FBFR32 *fbfr32, FLDID32 fieldid, char *value, FLDLEN32 len)

where

t fbfr32 is a pointer to a fielded buffer

t fieldid is a field identifier

t value is a pointer to a new value. Its type is shown as char *, but when it is used, its type must be the same type as the value to be appended (see below)

t len is the length of the value if its type is FLD_CARRAY

Fappend32() appends a new occurrence of the field fieldid with a value located at value to the fielded buffer and puts the buffer into append mode. Append mode provides optimized buffer construction for large buffers constructed of many rows of a common set of fields. A buffer that is in append mode is restricted as to what operations may be performed on the buffer. Only calls to the following FML32 routines are allowed in append mode: Fappend32(), Findex32(), Funindex32(), Ffree32(), Fused32(), Funused32() and Fsizeof32(). Calls to Findex32() or Funindex32() will end append mode. The following example shows the construction of a 500-row buffer with five fields per row using Fappend32().

for (i=0; i 500 ;i++) {
if ((Fappend32(fbfr32, LONGFLD1, &lval1[i], (FLDLEN32)0) < 0) ||
(Fappend32(fbfr32, LONGFLD2, &lval2[i], (FLDLEN32)0) < 0) ||
(Fappend32(fbfr32, STRFLD1, &str1[i], (FLDLEN32)0) < 0) ||
(Fappend32(fbfr32, STRFLD2, &str2[i], (FLDLEN32)0) < 0) ||
(Fappend32(fbfr32, LONGFLD3, &lval3[i], (FLDLEN32)0) < 0)) {
F_error32("pgm_name");
break;
}
}
Findex32(fbfr32, 0);

Fappend32(), like all other functions that take or return a field value, expects a pointer to a field value, never the value itself.

If the field type is such that the field length is fixed (short, long, char, float, or double) or can be determined (string), the field length need not be given (it is ignored). If the field type is a character array, the length must be specified; the length is defined as type FLDLEN32.

It is assumed (by default) that the native type of the field is a character array so that the length of the value must be passed to the function. If the value being appended is not a character array, the type of value must reflect the type of the value it points to.

For character array fields, null fields may be indicated by a length of 0. For string fields, the null string may be stored since the NULL terminating byte is actually stored as part of the field value: a string consisting of only the NULL terminating byte is considered to have a length of 1. For all other types (fixed length types), you may choose some special value that is interpreted by the application as a NULL, but the size of the value will be taken from its field type (e.g., length of four for a long) regardless of what value is actually passed. Passing a NULL value address will result in an error, (FEINVAL).

Fchg32

Fchg32() changes the value of a field in the buffer.

int
Fchg32(FBFR32 *fbfr32, FLDID32 fieldid, FLDOCC32 oc, char *value, FLDLEN32 len)

where

t fbfr32 is a pointer to a fielded buffer

t fieldid is a field identifier

t oc is the occurrence number of the field

t value is a pointer to a new value. Its type is shown as char *, but when it is used, its type must be the same type as the value to be added (see Fadd32())

t len is the length of the value if its type is FLD_CARRAY

For example, to change a field of type carray to a new value stored in value:

FBFR32 *fbfr32;
FLDID32 fieldid;
FLDOCC32 oc;
FLDLEN32 len;
char value[50];
. . .
strcpy(value, "new value");
flen = strlen(value);
if(Fchg32(fbfr32, fieldid, oc, value, len) < 0)
F_error32("pgm_name");

If oc is -1, then the field value is added as a new occurrence to the buffer. If oc is 0 or greater and the field is found, then the field value is modified to the new value specified. If oc is 0 or greater and the field is not found, then NULL occurrences are added to the buffer until the value can be added as the specified occurrence. For example, changing field occurrence 3 for a field that does not exist on a buffer will cause three NULL occurrences to be added (occurrences 0, 1 and 2), followed by occurrence 3 with the specified field value. Null values consist of the NULL string "\0" (1 byte in length) for string and character values, 0 for long and short fields, 0.0 for float and double values, and a zero-length string for a character array.

The new or modified value is contained in value. If it is a character array, its length is given in len (len is ignored for other field types). If the value pointer is NULL and the field is found, then the field is deleted. If the field occurrence to be deleted is not found, it is considered an error (FNOTPRES).

The buffer must have enough room to contain the modified or added field value, or an error is returned (FNOSPACE).

Fcmp32

Fcmp32() compares the field identifiers and field values of two fielded buffers.

int
Fcmp32(FBFR32 *fbfr321, FBFR32 *fbfr322)

where

t fbfr321 and fbfr322 are pointers to fielded buffers

The function returns a 0 if the buffers are identical; it returns a -1 on any of the following conditions:

t the fieldid of a fbfr321 field is less than the field id of the corresponding field of fbfr322

t the value of a fbfr321 field is less than the value of the corresponding field of fbfr322

t fbfr1 is shorter than fbfr322

Fcmp32() returns a 1 if the reverse of any of the above conditions is true (for example, if the field ID of a fbfr322 field is less than the field ID of the corresponding field of fbfr321, and so on).

Fdel32

The Fdel32() function deletes the specified field occurrence.

int
Fdel32(FBFR32 *fbfr32, FLDID32 fieldid, FLDOCC32 oc)

where

t fbfr32 is a pointer to a fielded buffer

t fieldid is a field identifier

t oc is the occurrence number

For example,

FLDOCC32 occurrence;
. . .
occurrence=0;
if(Fdel32(fbfr32, fieldid, occurrence) < 0)
F_error32("pgm_name");

deletes the first occurrence of the field indicated by the specified field identifier. If it does not exist, the function returns -1 (Ferror32() is set to FNOTPRES).

Fdelall32

Fdelall32() deletes all occurrences of the specified field from the buffer:

int
Fdelall32(FBFR32 *fbfr32, FLDID32 fieldid)

where

t fbfr32 is a pointer to a fielded buffer

t fieldid is a field identifier

For example:

if(Fdelall32(fbfr32, fieldid) < 0)
F_error32("pgm_name"); /* field not present */

If the field is not found, the function returns -1 (Ferror32() is set to FNOTPRES).

Fdelete32

Fdelete32() deletes all occurrences of all fields listed in the array of field identifiers, fieldid[]:

int
Fdelete32(FBFR32 *fbfr32, FLDID32 *fieldid)

where

t fbfr32 is a pointer to a fielded buffer

t fieldid is a pointer to the list of field identifiers to be deleted

The update is done directly to the fielded buffer. The array of field identifiers does not need to be in any specific order, but the last entry in the array must be field identifier 0 (BADFLDID). For example:

#include "fld.tbl.h"
FBFR32 *dest;
FLDID32 fieldid[20];
. . .
fieldid[0] = A; /* field id for field A */
fieldid[1] = D; /* field id for field D */
fieldid[2] = BADFLDID; /* sentinel value */
if(Fdelete32(dest, fieldid) < 0)
F_error32("pgm_name");

If the destination buffer has fields A, B, C, and D, this example will result in a buffer that contains only occurrences of fields B and C.

Fdelete32() is a more efficient way of deleting several fields from a buffer than using several Fdelall32() calls.

Ffind32

Ffind32() finds the value of the specified field occurrence in the buffer:

char *
Ffind32(FBFR32 *fbfr32, FLDID32 fieldid, FLDOCC32 oc, FLDLEN32 *len)

where

t fbfr32 is a pointer to a fielded buffer

t fieldid is a field identifier

t oc is the occurrence number

t len is the length of the value found

In the declaration above the return value to Ffind32() is shown as a character pointer data type (char* in C). The actual type of the pointer returned is the same as the type of the value it points to.

An example of the use of the function is:

#include "fld.tbl.h"
FBFR32 *fbfr32;
FLDLEN32 len;
char* Ffind32, *value;
. . .
if((value=Ffind32(fbfr32,ZIP,0, &len)) == NULL)
F_error32("pgm_name");

If the field is found, its length is returned in len (if len is NULL, the length is not returned), and its location is returned as the value of the function. If the field is not found, NULL is returned, and Ferror32() is set to FNOTPRES.

Ffind32() is useful for gaining "read-only" access to a field. The value returned by Ffind32() should not be used to modify the buffer. Field value modification should be done only by the function Fadd32() or Fchg32().

The value returned by Ffind32() is valid only so long as the buffer remains unmodified. The value is guaranteed to be aligned on a short boundary but may not be aligned on a long or double boundary, even if the field is of that type (see the conversion functions described later in this document for aligned values). On processors that require proper alignment of variables, referencing the value when not aligned properly will cause a system error, as in the following example:

long *l1,l2;
FLDLEN32 length;
char *Ffind32;
. . .
if((l1=(long *)Ffind32(fbfr32, ZIP, 0, &length)) == NULL)
F_error32("pgm_name");
else
l2 = *l1;

and should be re-written as:

if((l1==(long *)Ffind32(fbfr32, ZIP, 0, &length)) == NULL)
F_error32("pgm_name");
else
memcpy(&l2,l1,sizeof(long));

Ffindlast32

This function finds the last occurrence of a field in a fielded buffer and returns a pointer to the field, as well as the occurrence number and length of the field occurrence:

char *
Ffindlast32(FBFR32 *fbfr32, FLDID32 fieldid, FLDOCC32 *oc, FLDLEN32 *len)

where

t fbfr32 is a pointer to a fielded buffer

t fieldid is a field identifier

t oc is a pointer to the occurrence number of the last field occurrence found

t len is a pointer to the length of the value found

In the declaration above the return value to Ffindlast is shown as a character pointer data type (char* in C). The actual type of the pointer returned is the same as the type of the value it points to.

Ffindlast32() acts like Ffind32(), except that you do not specify a field occurrence. Instead, both the occurrence number and the value of the last field occurrence are returned. However, if you specify NULL for occurrence on calling the function, the occurrence number will not be returned.

The value returned by Ffindlast32() is valid only as long as the buffer remains unchanged.

Ffindocc32

Ffindocc32() looks at occurrences of the specified field on the buffer and returns the occurrence number of the first field occurrence that matches the user-specified field value:

FLDOCC32
Ffindocc32(FBFR32 *fbfr32, FLDID32 fieldid, char *value, FLDLEN32 len;)

where

t fbfr32 is a pointer to a fielded buffer

t fieldid is a field identifier

t value is a pointer to a new value. Its type is shown as char*, but when it is used, its type must be the same type as the value to be added (see Fadd32())

t len is the length of the value if type carray

For example,

#include "fld.tbl.h"
FBFR32 *fbfr32;
FLDOCC32 oc;
long zipvalue;
. . .
zipvalue = 123456;
if((oc=Ffindocc32(fbfr32,ZIP,&zipvalue, 0)) < 0)
F_error32("pgm_name");

would set oc to the occurrence for the specified zip code.

Regular expressions are supported for string fields. For example,

#include "fld.tbl.h"
FBFR32 *fbfr32;
FLDOCC32 oc;
char *name;
. . .
name = "J.*"
if ((oc = Ffindocc32(fbfr32, NAME, name, 1)) < 0)
F_error("pgm_name");

would set oc to the occurrence of NAME that starts with "J".

Note: To enable pattern matching on strings, the fourth argument to Ffindocc32() must be nonzero. If it is zero, a simple string compare is performed. If the field value is not found, -1 is returned.

For upward compatibility, a circumflex ( ^ ) and dollar sign ($) are assumed to surround the regular expression; thus, the above example is actually interpreted as "^(J.*)$". This means that the regular expression must match the entire string value in the field.

Fget32

Fget32() should be used to retrieve a field from a fielded buffer when the value is to be modified:

int
Fget32(FBFR32 *fbfr32, FLDID32 fieldid, FLDOCC32 oc, char *loc, FLDLEN32 *maxlen)

where

t fbfr32 is a pointer to a fielded buffer

t fieldid is a field identifier

t oc is the occurrence number

t loc is a pointer to a buffer to copy the field value into

t maxlen is a pointer to the length of the source buffer on calling the function, and a pointer to the length of the field on return

The caller provides Fget32 with a pointer to a private buffer, as well as the length of the buffer. If maxlen is specified as NULL, then it is assumed that the destination buffer is large enough to accommodate the field value, and its length is not returned.

Fget32() returns an error if the desired field is not in the buffer (FNOTPRES), or if the destination buffer is too small (FNOSPACE). For example,

FLDLEN32 len;
char value[100];
. . .
len=sizeof(value);
if(Fget32(fbfr32, ZIP, 0, value, &len) < 0)
F_error32("pgm_name");

gets the zip code assuming it is stored as a character array (carray) or string. If it is stored as a long, then it would be retrieved by:

FLDLEN32 len;
long value;
. . .
len = sizeof(value);
if(Fget32(fbfr32, ZIP, 0, value, &len) < 0)
F_error32("pgm_name");

Fgetalloc32

Like Fget32(), Fgetalloc32() finds and makes a copy of a buffer field, but it acquires space for the field via a call to malloc(3):

char *
Fgetalloc32(FBFR32 *fbfr32, FLDID32 fieldid, FLDOCC32 oc, FLDLEN32 *extralen)

where

t fbfr32 is a pointer to a fielded buffer

t fieldid is a field identifier

t oc is the occurrence number

t extralen is a pointer to the additional length to be acquired on calling the function, and a pointer to the actual length acquired on return

In the declaration above the return value to Fgetalloc32() is shown as a character pointer data type (char* in C). The actual type of the pointer returned is the same as the type of the value to which it points.

On success, Fgetalloc32() returns a valid pointer to the copy of the properly aligned buffer field; on error it returns NULL. If malloc(3) fails, Fgetalloc32() returns an error (Ferror32() is set to FMALLOC).

The last parameter to Fgetalloc32() specifies an extra amount of space to be acquired if, for instance, the gotten value is to be expanded before re-insertion into the fielded buffer. On success, the length of the allocated buffer is returned in extralen. For example:

FLDLEN32 extralen;
FBFR32 *fieldbfr
char *Fgetalloc32;
. . .
extralen = 0;
if (fieldbfr = (FBFR32 *)Fgetalloc32(fbfr32, ZIP, 0, &extralen) == NULL)
F_error32("pgm_name");

It is the responsibility of the caller to free space acquired by Fgetalloc32().

Fgetlast32

Fgetlast32() is used to retrieve the last occurrence of a field from a fielded buffer when the value is to be modified:

int
Fgetlast32(FBFR32 *fbfr32, FLDID32 fieldid, FLDOCC32 *oc, char *loc, FLDLEN32 *maxlen)

where

t fbfr32 is a pointer to a fielded buffer

t fieldid is a field identifier

t oc is a pointer to the occurrence number of the last field occurrence

t loc is a pointer to a buffer to copy the field value into

t maxlen is a pointer to the length of the source buffer on calling the function, and a pointer to the length of the field on return

The caller provides Fgetlast32() with a pointer to a private buffer, as well as the length of the buffer. Fgetlast32() acts like Fget32(), except that you do not specify a field occurrence. Instead, both the occurrence number and the value of the last field occurrence are returned. However, if you specify NULL for occ on calling the function, the occurrence number will not be returned.

Fnext32

Fnext32() finds the next field in the buffer after the specified field occurrence:

int
Fnext32(FBFR32 *fbfr32, FLDID32 *fieldid, FLDOCC32 *oc, char *value, FLDLEN32 *len)

where

t fbfr32 is a pointer to a fielded buffer

t fieldid is a pointer to a field identifier

t oc is a pointer to the occurrence number

t value is a pointer of the same type as the value contained in the next field

t len is a pointer to the length of *value

A fieldid of FIRSTFLDID should be specified to get the first field in a buffer; the field identifier and occurrence number of the first field occurrence are returned in the corresponding parameters; if the field is not NULL, its value is copied into the memory location addressed by the value pointer; the len parameter is used to determine if value has enough space allocated to contain the field value (Ferror32() is set to FNOSPACE if it does not); and, the length of the value is returned in the len parameter. Note that if the value of the field is non-null, then the len parameter is also assumed to contain the length of the currently allocated space for value.

If the field value is NULL, then the value and length parameters are not changed.

If no more fields are found, Fnext32() returns 0 (end of buffer) and fieldid, occurrence, and value are left unchanged.

If the value parameter is not NULL, the length parameter is also assumed to be non-NULL.

The following example reads all field occurrences in the buffer:

FLDID32 fieldid;
FLDOCC32 occurrence;
char *value[100];
FLDLEN32 len;
. . .
for(fieldid=FIRSTFLDID,len=sizeof(value);
Fnext32(fbfr32,fieldid,&occurrence,value,&len) > 0;
len=sizeof(value)) {
/* code for each field occurrence */
}

Fnum32

Fnum32() returns the number of fields contained in the specified buffer, or -1 on error:

FLDOCC32
Fnum(FBFR32 *fbfr32)

where

t fbfr32 is a pointer to a fielded buffer

For example:

if((cnt=Fnum32(fbfr32)) < 0)
F_error32("pgm_name");
else
fprintf(stdout,"%d fields in buffer\n",cnt);

would print the number of fields in the specified buffer.

Foccur32

Foccur32() returns the number of occurrences for the specified field in the buffer:

FLDOCC32
Foccur32(FBFR32 *fbfr32, FLDID32 fieldid)

where

t fbfr32 is a pointer to a fielded buffer

t fieldid is a field identifier

Zero is returned if the field does not occur in the buffer and -1 is returned on error. For example:

FLDOCC32 cnt;
. . .
if((cnt=Foccur32(fbfr32,ZIP)) < 0)
F_error32("pgm_name");
else
fprintf(stdout,"Field ZIP occurs %d times in buffer\n",cnt);

would print the number of occurrences of the field ZIP in the specified buffer.

Fpres32

Fpres32() returns true (1) if the specified field occurrence exists and false (0) otherwise:

int
Fpres32(FBFR32 *fbfr32, FLDID32 fieldid, FLDOCC32 oc)

where

t fbfr32 is a pointer to a fielded buffer

t fieldid is a field identifier

t oc is the occurrence number

For example:

Fpres32(fbfr32,ZIP,0)

would return true if the field ZIP exists in the fielded buffer pointed to by fbfr32.

Fvals32 and Fvall32

Fvals32() works like Ffind32() for string values but guarantees that a pointer to a value is returned. Fvall32() works like Ffind32() for long and short values, but returns the actual value of the field as a long, instead of a pointer to the value.

char* 
Fvals32(FBFR32 *fbfr32,FLDID32 fieldid,FLDOCC32 oc)

char*
Fvall32(FBFR32 *fbfr32,FLDID32 fieldid,FLDOCC32 oc)

where in both functions

t fbfr32 is a pointer to a fielded buffer

t fieldid is a field identifier

t oc is the occurrence number

For Fvals32(), if the specified field occurrence is not found, the NULL string, \0, is returned. This function is useful for passing the value of a field to another function without checking the return value. This function is valid only for fields of type string; the NULL string is automatically returned for other field types (i.e., no conversion is done).

For Fvall32(), if the specified field occurrence is not found, then 0 is returned. This function is useful for passing the value of a field to another function without checking the return value. This function is valid only for fields of type long and short; 0 is automatically returned for other field types (that is, no conversion is done).

Buffer Update Functions

The functions listed in this section access and update entire fielded buffers, rather than individual fields in the buffers. These functions use at most three parameters, dest, src, and fieldid, where

t dest is a pointer to a destination fielded buffer

t src is a pointer to a source fielded buffer

t fieldid is a field identifier or an array of field identifiers

Fconcat32

Fconcat32() adds fields from the source buffer to the fields that already exist in the destination buffer.

int
Fconcat32(FBFR32 *dest, FBFR32 *src)

Occurrences in the destination buffer are maintained (i.e., retained and not modified) and new occurrences from the source buffer are added with greater occurrence numbers than any existing occurrences for each field (the fields are maintained in field identifier order).

In the following example:

FBFR32 *src, *dest;
. . .
if(Fconcat32(dest,src) < 0)
F_error32("pgm_name");

if dest has fields A, B, and two occurrences of C, and src has fields A, C, and D, the resultant dest will have two occurrences of field A (destination field A and source field A), field B, three occurrences of field C (two from dest and the third from src), and field D.

This operation will fail if there is not enough space to contain the new fields (FNOSPACE); in this case, the destination buffer remains unchanged.

Fjoin32

Fjoin32() is used to join two fielded buffers based on matching fieldid/occurrence.

int
Fjoin32(FBFR32 *dest, FBFR32 *src)

For fields that match on fieldid/occurrence, the field value is updated in the destination buffer with the value from the source buffer. Fields in the destination buffer that have no corresponding fieldid/occurrence in the source buffer are deleted. Fields in the source buffer that have no corresponding fieldid/occurrence in the destination buffer are not added to the destination buffer. Thus,

if(Fjoin32(dest,src) < 0)
F_error32("pgm_name");

Using the input buffers in the previous example will result in a destination buffer that has source field value A and source field value C. This function may fail due to lack of space if the new values are larger than the old (FNOSPACE); in this case, the destination buffer will have been modified. However, if this happens, the destination buffer may be re-allocated (using Frealloc32()) and the Fjoin32() function may be repeated. (Even if the destination buffer has been partially updated, repeating the function will give the correct results.)

Fojoin32

Fojoin32() is similar to Fjoin32(), but it does not delete fields from the destination buffer that have no corresponding fieldid/occurrence in the source buffer.

int
Fojoin32(FBFR32 *dest, FBFR32 *src)

Note that fields that exist in the source buffer that have no corresponding fieldid/occurrence in the destination buffer are not added to the destination buffer. For example:

if(Fojoin32(dest,src) < 0)
F_error32("pgm_name");

Using the input buffers from the previous example, dest will contain the source field value A, the destination field value B, the source field value C, and the second destination field value C. As with Fjoin32(), this function can fail for lack of space (FNOSPACE) and can be re-issued again after allocating more space to complete the operation.

Fproj32

Fproj32() is used to update a buffer in place so that only the desired fields are kept (in other words, so that the result is a projection on specified fields).

int
Fproj32(FBFR32 *fbfr32, FLDID32 *fieldid)

These fields are specified in an array of field identifiers passed to the function. The update is performed directly in the fielded buffer. For example:

#include "fld.tbl.h"
FBFR32 *fbfr32;
FLDID32 fieldid[20];
. . .
fieldid[0] = A; /* field id for field A */
fieldid[1] = D; /* field id for field D */
fieldid[2] = BADFLDID; /* sentinel value */
if(Fproj32(fbfr32, fieldid) < 0)
F_error32("pgm_name");

If the buffer has fields A, B, C, and D, the example results in a buffer that contains only occurrences of fields A and D. Note that the entries in the array of field identifiers do not need to be in any specific order, but the last value in the array of field identifiers must be field identifier 0 (BADFLDID).

Fprojcpy32

Fprojcpy32() is similar to Fproj32() but the projection is done into a destination buffer.

int
Fprojcpy32(FBFR32 *dest, FBFR32 *src, FLDID32 *fieldid)

Any fields in the destination buffer are first deleted and the results of the projection on the source buffer are copied into the destination buffer. Using the above example,

if(Fprojcpy32(dest, src, fieldid) < 0)
F_error32("pgm_name");

will place the results of the projection in the destination buffer. The entries in the array of field identifiers may be re-arranged; the field identifier array is sorted if they are not in numeric order.

Fupdate32

Fupdate32() updates the destination buffer with the field values in the source buffer.

int
Fupdate32(FBFR32 *dest, FBFR32 *src)

For fields that match on fieldid/occurrence, the field value is updated in the destination buffer with the value in the source buffer (like Fjoin32()). Fields in the destination buffer for which there are no corresponding fields on the source buffer are left untouched (as in Fojoin32()). Fields in the source buffer for which there are no corresponding field on the destination buffer are added to the destination buffer (as in Fconcat32()). For example:

if(Fupdate32(dest,src) < 0)
F_error32("pgm_name");

If the src buffer has fields A, C, and D, and the dest buffer has fields A, B, and two occurrences of C, the updated destination buffer will contain: the source field value A, the destination field value B, the source field value C, the second destination field value C, and the source field value D.

Conversion Functions

FML32 provides a set of routines that perform data conversion upon reading or writing a fielded buffer.

Generally, the functions behave like their non-conversion counterparts, except that they provide conversion from a user type to the native field type when writing to a buffer, and from the native type to a user type when reading from a buffer.

The native type of a field is the type specified for it in its field table entry and encoded in its field identifier. (The only exception to this rule is CFfindocc32(), which, although it is a read operation, converts from the user-specified type to the native type before calling Ffindocc32().) The function names are the same as their non-conversion FML32 counterparts except that they have a "C" prefix.

CFadd32

The CFadd32() function adds a user supplied item to a buffer creating a new field occurrence within the buffer:

int
CFadd32(FBFR32 *fbfr32, FLDID32 fieldid, char *value, FLDLEN32 len, int type)

where

t fbfr32 is a pointer to a fielded buffer

t fieldid is the field identifier of the field to be added

t value is a pointer to the value to be added

t len is the length of the value, if of type carray

t type is the type of the value

Before the field addition, the data item is converted from a user supplied type to the type specified in the field table as the fielded buffer storage type of the field. If the source type is FLD_CARRAY (character array), the length argument should be set to the length of the array. For example,

if(CFadd32(fbfr32,ZIP,"12345",(FLDLEN32)0,FLD_STRING) < 0)
F_error32("pgm_name");

If the ZIP (zip code) field were stored in a fielded buffer as a long integer, the function would convert "12345" to a long integer representation, before adding it to the fielded buffer pointed to by fbfr32. (Note that the field value length is given as 0 since the function can determine it; the length is needed only for type FLD_CARRAY.) The following code fragment:

long zipval;
. . .
zipval = 12345;
if(CFadd32(fbfr32,ZIP,&zipval,(FLDLEN32)0,FLD_LONG) < 0)
F_error32("pgm_name");

puts the same value into the fielded buffer, but does so by presenting it as a long, instead of as a string. Note that the value must first be put into a variable, since C does not permit the construct &12345L. CFadd32() returns 1 on success, and -1 on error, in which case Ferror32() is set appropriately.

CFchg32

The function CFchg32() acts like CFadd32(), except that it changes the value of a field (after conversion of the supplied value):

int
CFchg32(FBFR32 *fbfr32, FLDID32 fieldid, FLDOCC32 oc, char *value, FLDLEN32 len, int type)

where

t fbfr32 is a pointer to a fielded buffer

t fieldid is the field identifier of the field to be changed

t oc is the occurrence number of the field to be changed

t value is a pointer to the value to be added

t len is the length of the value, if of type carray

t type is the type of the value

For example,

FLDOCC32 occurrence;
long zipval;
. . .
zipval = 12345;
occurrence = 0;
if(CFchg32(fbfr32,ZIP,occurrence,&zipval,(FLDLEN32)0,FLD_LONG) < 0)
F_error32("pgm_name");

would change the first occurrence (occurrence 0) of field ZIP to the specified value, doing any needed conversion.

If the specified occurrence is not found, then null occurrences are added to pad the buffer with multiple occurrences until the value can be added as the specified occurrence.

CFget32

CFget32() is the conversion analog of Fget32(). The difference is that it copies a converted value to the user-supplied buffer:

int
CFget32(FBFR32 *fbfr32, FLDID32 fieldid, FLDOCC32 oc, char *buf, FLDLEN32 *len, int type)

where

t fbfr32 is a pointer to a fielded buffer

t fieldid is the field identifier of the field to be retrieved

t oc is the occurrence number of the field

t buf is a pointer to the post-conversion buffer

t len is the length of the value, if of type carray

t type is the type of the value

Using the previous example,

FLDLEN32 len;
. . .
len=sizeof(zipval);
if(CFget32(fbfr32,ZIP,occurrence,&zipval,&len,FLD_LONG) < 0)
F_error32("pgm_name");

would get the value that was just stored in the buffer, no matter what format, and convert it back to a long integer. If the length pointer is NULL, then the length of the value retrieved and converted is not returned.

CFgetalloc32

CFgetalloc32() is like Fgetalloc32(); you are responsible for freeing the malloc'd space for the returned (converted) value with free:

char *
CFgetalloc32(FBFR32 *fbfr32, FLDID32 fieldid, FLDOCC32 oc, int type, FLDLEN32 *extralen)

where

t fbfr32 is a pointer to a fielded buffer

t fieldid is the field identifier of the field to be converted

t oc is the occurrence number of the field

t type is the type to which the value is converted

t extralen on calling the function is a pointer to the extra allocation amount; on return, it is a pointer to the size of the total allocated area

In the declaration above the return value to CFgetalloc32() is shown as a character pointer data type (char* in C). The actual type of the pointer returned is the same as the type of the value to which it points.

The previously stored value could be retrieved into space allocated automatically for you by the following code:

char *value;
FLDLEN32 extra;
. . .
extra = 25;
if((value=CFgetalloc32(fbfr32,ZIP,0,FLD_LONG,&extra)) == NULL)
F_error32("pgm_name");

The value extra in the function call indicates that the function should not only allocate enough space for the retrieved value but an additional 25 bytes and the total amount of space allocated will be returned in this variable.

CFfind32

CFfind32() returns a pointer to a converted value of the desired field:

char *
CFfind32(FBFR32 *fbfr32, FLDID32 fieldid, FLDOCC32 oc, FLDLEN32 len, int type)

where

t fbfr32 is a pointer to a fielded buffer

t fieldid is the field identifier of the field to be retrieved

t oc is the occurrence number of the field

t len is the length of the post-conversion value

t type is the type to which the value is converted

In the declaration above the return value to CFfind32() is shown as a character pointer data type (char* in C). The actual type of the pointer returned is the same as the type of the value to which it points.

Like Ffind32(), this pointer should be considered read only. For example:

char *CFfind32;
FLDLEN32 len;
long *value;
. . .
if((value=(long *)CFfind32(fbfr32,ZIP,occurrence,&len,FLD_LONG))== NULL)
F_error32("pgm_name");

would return a pointer to a long containing the value of the first occurrence of the ZIP field. If the length pointer is NULL, then the length of the value found is not returned. Unlike Ffind32(), the value returned is guaranteed to be properly aligned for the corresponding user-specified type.

Note: The duration of the validity of the pointer returned by CFfind32() is guaranteed only until the next buffer operation, even if it is non-destructive, since the converted value is retained in a single private buffer. This differs from the value returned by Ffind32(), which is guaranteed until the next modification of the buffer.

CFfindocc32

CFfindocc32() looks at occurrences of the specified field in the buffer and returns the occurrence number of the first field occurrence that matches the user-specified field value after it has been converted (it is converted to the type of the field identifier).

FLDOCC32
CFfindocc32(FBFR32 *fbfr32, FLDID32 fieldid, char *value, FLDLEN32 len, int type)

where

t fbfr32 is a pointer to a fielded buffer

t fieldid is the field identifier of the field to be retrieved

t value is a pointer to the unconverted matching value

t len is the length of the unconverted matching value

t type is the type of the unconverted matching value

For example,

#include "fld.tbl.h"
FBFR32 *fbfr32;
FLDOCC32 oc;
char zipvalue[20];
. . .
strcpy(zipvalue,"123456");
if((oc=CFfindocc32(fbfr32,ZIP,zipvalue,0,FLD_STRING)) < 0)
F_error32("pgm_name");

would convert the string to the type of fieldid ZIP (possibly a long) and set oc to the occurrence for the specified zip code. If the field value is not found, -1 is returned.

Note: Since CFfindocc32() converts the user-specified value to the native field type before examining the field values, regular expressions will work only when the user-specified type and the native field type are both FLD_STRING. Thus, CFfindocc32() has no utility with regular expressions.

Converting Strings

A set of functions (Fadds32(), Fchgs32(), Fgets32(), Fgetsa32(), and Ffinds32()) has been provided to handle the case of conversion to/from a user type of FLD_STRING. These functions call their non-string-function counterparts, providing a type of FLD_STRING, and a len of 0. Note that the duration of the validity of the pointer returned by Ffinds32() is the same as that described for CFfind32().

Ftypcvt32

The functions CFadd32(), CFchg32(), CFget32(), CFgetalloc32(), and CFfind32() use the function Ftypcvt32() to perform the appropriate data conversion. The synopsis of Ftypcvt32() usage is as follows (it does not follow the parameter order conventions):

char *
Ftypcvt32(FLDLEN32 *tolen, int totype, char *fromval, int fromtype, FLDLEN32 fromlen)

where

t tolen is a pointer to the length of the converted value

t totype is the type to which to convert

t fromval is a pointer to the value from which to convert

t fromtype is the type from which to convert

t fromlen is the length of the from value if the from type is FLD_CARRAY

Ftypcvt32() converts from the value *fromval, which has type fromtype, and length fromlen if fromtype is type FLD_CARRAY (otherwise fromlen is inferred from fromtype), to a value of type totype. Ftypcvt32() returns a pointer to the converted value, and sets *tolen to the converted length, upon success. Upon failure, Ftypcvt32() returns NULL. As an example of how Ftypcvt is used, the function CFchg32() is presented:


CFchg32(fbfr32,fieldid,oc,value,len,type)
FBFR32 *fbfr32; /* fielded buffer */
FLDID32 fieldid; /* field to be changed */
FLDOCC32 oc; /* occurrence of field to be changed */
char *value; /* location of new value */
FLDLEN32 len; /* length of new value */
int type; /* type of new value */
{
char *convloc; /* location of post-conversion value */
FLDLEN32 convlen; /* length of post-conversion value */
extern char *Ftypcvt32;

/* convert value to fielded buffer type */
if((convloc = Ftypcvt32(&convlen,FLDTYPE(fieldid),value,type,len)) == NULL)
return(-1);

if(Fchg32(fbfr32,fieldid,oc,convloc,convlen) < 0)
return(-1);
return(1);
}

The user may call Ftypcvt32 directly to do field value conversion without adding or modifying a fielded buffer.

Conversion Rules

A description of conversion rules is now presented. In this description, oldval represents a pointer to the data item being converted, and newval a pointer to the post-conversion value:

t When both types are identical, *newval is identical to *oldval.

t When both types are numeric (that is, when the values of both types are long, short, float, or double), the conversion is done by the C assignment operator, with proper type casting. For example, converting a short to a float is done by:

*((float *)newval) = *((short *) oldval)

t When converting from a numeric to a string, an appropriate sprintf is used. For example, converting a short to a string is done by:

sprintf(newval,"%d",*((short *)oldval))

t When converting from a string to a numeric, the appropriate function (for example, atof, atol) is used, with the result assigned to a typecasted receiving location, for example:

*((float *)newval) = atof(oldval)

t When converting from type char to any numeric type, or from a numeric type to a char, the char is considered to be a "shorter short." For example,

*((float *)newval) = *((char *)oldval)

is the method used to convert a char to a float. Similarly,

*((char *)newval) = *((short *)oldval)

is used to convert a short to a char.

t A char is converted to a string by appending a NULL character. In this regard, a char is not a "shorter short." If it were, assignment would be done by converting it to a short, and then converting the short to a string via sprintf. In the same sense, a string is converted to a char by assigning the first character of the string to the character.

t The carray type is used to store an arbitrary sequence of bytes. In this sense, it can encode any user data type. Nevertheless, the following conversions are specified for carray types:

Table 5-2 summarizes the conversion rules presented in this section.

Table 5-2 Summary of Conversion Rules

src typ

dest type

-

char

short

long

float

double

string

carray

dec_t

char

-

cast

cast

cast

cast

st[0]=c

array[0]=c

d

short

cast

-

cast

cast

cast

sprintf

sprintf

d

long

cast

cast

-

c