Next Up Previous Contents Index
Next: Modifying AutoCAD Up: The Portable Data Previous: Background

The Binary I/O Package

To read and write portable binary files, include the file BINIO.H in your compilation. You must include SYSTEM.H before BINIO.H. BINIO.H declares numerous functions, which are used to read and write binary data items on various systems. Each of these functions is of the form:

b_{r|w}type(fp, pointer[, args...]);

where type is the mnemonic for the internal type being written, fp is the file pointer, pointer is the pointer to the datum being read or written (must be an lvalue), and args are optional arguments required by some types. For example, when writing a character array an argument supplies its length.

Thus, to write a real (double precision floating point) number val to a file descriptor named ofile, use:

stat = b_wreal(ofile, &val);

Each of these routines returns the same status FREAD or FWRITE would: 1 for single item reads and writes, and the number of items transferred for array types. Currently defined type codes are as follows:

char
Characters. Signed convention is undefined. Canonical form in the file is a single 8 bit byte.
uchar
Unsigned characters. Used for utility 8 bit data. Canonical form in the file is a single 8 bit byte.
short
Signed 16 bit integers. Canonical form in the file is two's complement, least significant byte first, most significant byte last, two total bytes.
long
Signed 32 bit integers. Canonical form in the file is 4 bytes, starting with the least significant byte and ending with the most significant byte. Two's complement.
real
Double precision floating point numbers. 8 bytes in a file. Canonical form in the file is an 8 byte IEEE double precision number, stored with the least significant byte first and the most significant byte last.
string
An array of char items. The third argument specifies the number of characters to be read or written. Canonical form in the file is one byte per item, written in ascending order as they would be addressed by a subscript.

If the binary I/O package is to do its job, you must be honest with it: only pass the functions pointers of exactly the type they are intended to process. If you use b_wstring to write a structure, you're going to generate files just as incompatible as if you used fwrite. And you must never, never use an INT as an argument to one of these routines.

When using the binary I/O package, you must explicitly read and write every datum: there is no way to read composite data types with one I/O. Bob Elman's code in EREAD solves this problem by packing data into a buffer, then writing it with one call. Since this handles the entity data, which is by far the largest volume of data that AutoCAD reads and writes, I felt that taking a simpler approach in the binary I/O package would have no measurable impact on performance. I felt that the complexity of the mechanism in EREAD was not required for handling the other files.

On a system such as MS-DOS, whose native internal data representation agrees with the canonical format of the database file, the various read and write functions are simply #defines to the equivalent calls on FREAD or FWRITE. The variable TRANSFIO in SYSTEM.H controls this. If it is not defined, all of the binary I/O routines generate in-line calls on FREAD and FWRITE. If TRANSFIO is defined, machine specific definitions in BINIO.H are used to define the I/O routines. Compatible types such as char may still generate direct I/O calls, but incompatible types should be defined as external int-returning functions.

If a machine uses a non-IEEE floating point format, the b_rreal and b_wreal functions must convert the IEEE format in the file to and from the machine's internal representation. In addition, because the entity data I/O code in EREAD.C does not use the Binary I/O package, you must tell it to perform the conversion. You do this by adding the statement:

#define REALTRAN

in the SYSTEM.H entry for the machine. This will generate code within EREAD.C which calls two new functions your binary I/O driver must supply. Whenever a real number is being written to a file, EREAD will call:

realenc(bufptr, rvalue);

where bufptr is a ``char *'' pointing to an 8 byte buffer in which the canonical IEEE value should be stored (remember, lsb first), and rvalue is the real number value to be stored, passed in the machine's internal type for double. When a number is being read, a call is made to:

rvalue = realdec(bufptr);

in which bufptr points to an 8 byte area containing the IEEE number. Realdec must return the corresponding internal value as a double.

Each machine architecture must define a binary I/O driver providing the non-defaulted I/O routines, and if real number conversion is required, realenc and realdec. Examine the driver for the Motorola 68000 family (BIO68K.C) for an example of such a driver.


Next Up Previous Contents Index
Next: Modifying AutoCAD Up: The Portable Data Previous: Background

Editor: John Walker