PV-WAVE Foundation > Programmer Guide > Working with Data Files > External Data Representation (XDR) Files
External Data Representation (XDR) Files
Normally, binary data is not portable between different machine architectures because of differences in the way different machines represent binary data. It is, however, possible to produce binary files that are portable, by specifying the Xdr keyword with the OPEN procedures. XDR represents a compromise between the extremes of ASCII and binary I/O.
XDR (eXternal Data Representation, developed by Sun Microsystems, Inc.) is a scheme under which all binary data is written using a standard “canonical” representation. PV‑WAVE understands this standard representation and has the ability to convert between it and the internal representation of the machine upon which it runs.
XDR converts between the internal (hardware) and standard external (network) binary representations for data, instead of simply using the machine’s internal representation. Thus, it is much more portable than pure binary data, although it is still limited to those machines that support XDR.
 
note
XDR is not as efficient as pure binary I/O because it does involve the overhead of converting between the network and hardware binary representations. Nevertheless, it is still much more efficient than ASCII I/O because conversion to and from ASCII characters is much more involved than converting between binary representations.
Opening XDR Files
Since XDR adds extra “bookkeeping” information to data stored in the file, and because the binary representation used may not agree with that of the machine being used, it does not make sense to access an XDR file without using the Xdr keyword.
To use the XDR format, you must specify the Xdr keyword when opening the file. For example:
OPENW, /Xdr, 1, 'data.dat'
 
note
OPENW and OPENU normally open files for both input and output. However, XDR files can only be open in one direction at a time. Thus, using these procedures with the Xdr keyword results in a file open for output only, and the only I/O data transfer routines that can be used is WRITEU. OPENR works in the usual way.
Transferring Data To and From XDR Files
The primary differences in the way PV-WAVE I/O procedures work with XDR files, as opposed to other data files, are listed below:
*The only I/O data transfer routines that can be used with a file opened for XDR are READU and WRITEU.
*The length of strings is saved and restored along with the string. This means that you do not have to initialize a string of the correct length before reading a string from the XDR file. (This is necessary with normal binary I/O, and is described in "Binary Transfer of String Variables".)
*Reading binary XDR data into a PV-WAVE LONG variable in PV-WAVE 64-bit causes 8 bytes to be extracted from the XDR file. In order to read 4 byte values from a binary XDR file you must pass the READ routine a PV-WAVE INT32 variable.
*For the sake of efficiency, byte data is transferred as a single unit. Therefore, byte variables must be initialized to a length that matches the data to be input. Otherwise, an error message is displayed. See the following example for more details.
Example—Reading Byte Data from an XDR File
For example, given the statements:
; Open a file for XDR output.
OPENW, /Xdr, 1, 'data.dat'
 
; Write a 10-element byte array.
WRITEU, 1, BINDGEN(10)
; Close the file ...
CLOSE, 1
; . . . and re-open it for input.
OPENR, /Xdr, 1, 'data.dat'
the following statements:
; Define b as a byte scalar.
b = 0B
; Try to read the first byte only.
READU, 1, b
; Close the file.
CLOSE, 1
will result in the error:
%End of file encountered. Unit: 1.
File: data.dat
%Execution halted at $MAIN$   (READU).
Instead, it is necessary to read the entire byte array back in one operation using statements such as:
; Define b as a byte array.
b = BYTARR(10)
; Read the whole array back at once.
READU, 1, b
; Close the file.
CLOSE, 1
 
note
This restriction (in other words, the necessity of transferring byte data as a single unit) does not apply to the other data types.
Example—Reading C-generated XDR Data with PV-WAVE
This example demonstrates how to write XDR data with a C program and read the subsequent file with PV-WAVE.
C Program Write
The following C program produces a file containing different types of data using XDR. The usual error checking is omitted for the sake of brevity.
#include <stdio.h>
#include <rpc/rpc.h>
/* For more information about xdr_wave_complex( ) and xdr_wave_string( ), refer to following section.*/
[xdr_wave_complex() and xdr_wave_string() included here]
main()
{
	 static struct {       /* output data */
unsigned char c;
short s;
long l;
float f;
double d;
struct complex { float r, i } cmp;
char *str;
} data = {1, 2, 3, 4, 5.0, { 6.0, 7.0}, "Hello" };
/* Length of a character */
u_int c_len = sizeof (unsigned char);
/* Address of byte field */
char *c_data = (char *) &data.c; 
/* stdio stream pointer */
FILE *outfile;
/* XDR handle */
XDR xdrs;
/* Open stdio stream and XDR handle */
outfile = fopen("data.dat", "w");
xdrstdio_create(&xdrs, outfile, XDR_ENCODE);
/* Output the data */
(void) xdr_bytes(&xdrs, &c_data, &c_len, c_len);
(void) xdr_short(&xdrs, (char *) &data.s);
(void) xdr_long(&xdrs, (char *) &data.l);
(void) xdr_float(&xdrs, (char *) &data.f);
(void) xdr_double(&xdrs, (char *) &data.d);
(void) xdr_wave_complex(&xdrs, (char *) &data.cmp);
(void) xdr_wave_string(&xdrs, &data.str);
/* Close XDR handle and stdio stream */
xdr_destroy(&xdrs);
(void) fclose(outfile);
}
Running this program creates the file data.dat containing the XDR data.
PV-WAVE Read
The following PV-WAVE statements can be used to read this file and print its contents to the screen:
; Create structure containing correct types.
data = {s, c:0B, s:0, l:0L, f:0.0, d:0.0D, $ 
cmp:COMPLEX(0), str:' '}
; Open the file for input.
OPENR, /Xdr, 1, 'data.dat'
; Read the data.
READU, 1, data
; Close the file.
CLOSE, 1
; Show the results.
PRINT, data
Executing these PV-WAVE statements produces the output:
	{ 1     2     3     4.00000	     5.0000000
	(6.00000, 	7.00000) Hello}
XDR Conventions for Programmers
PV-WAVE uses certain conventions for reading and writing XDR files. If you use XDR only to exchange data in and out of PV-WAVE, you don’t need to be concerned about these conventions because PV-WAVE takes care of it for you.
However, if you want to create PV-WAVE compatible XDR files from other languages, you need to know the actual XDR routines used by PV-WAVE for various data types. These routine names are summarized in Table 9-14: XDR Routines Used by PV‑WAVE:
 
XDR Routines Used by PV‑WAVE  
Data Type
XDR Routine
BYTE
xdr_bytes( )
INT
xdr_short( )
INT32
xdr_long( )
LONG
xdr_long( ), if !XDR_LONG is set to 32
xdr_hyper( ) or xdr_longlong( ), if !XDR_LONG is set to 64
FLOAT
xdr_float( )
DOUBLE
xdr_double( )
COMPLEX
xdr_wave_complex( ) *
STRING
xdr_wave_string( ) *
The asterisk (*) indicates compound routines.
 
note
For further details about XDR, consult the XDR documentation for your machine. If you are a Sun workstation user, consult the Network Programming manual.
XDR Routines for Transferring Complex and String Data
The routines used for types complex and string are not primitive XDR routines. Their definitions are shown in the following C code:
bool_t xdr_wave_complex(xdrs, p)
XDR *xdrs;
struct complex { float r, i } *p;
{
return(xdr_float(xdrs, (char *) &p->r)&&
       xdr_float(xdrs, (char *) &p->i));
}
 
bool_t xdr_wave_string(xdrs, p)
XDR *xdrs;
char **p;
{
int input = (xdrs->x_op == XDR_DECODE);
short length;
/* If writing, obtain the length */
if (!input) length = strlen(*p);
/* Transfer the string length */
if (!xdr_short(xdrs, (char *) &length)) return(FALSE);
/* If reading, obtain room for the string */
if (input)
{
*p = malloc((unsigned) (length + 1));
*p[length] = '\0';/* Null termination */
}
/* If nonzero, return string length */
return (length ? xdr_string(xdrs, p, length) : TRUE);
}