Sun Microsystems, Inc.
spacerspacer
spacer www.sun.com docs.sun.com |
spacer
black dot
 
 
A.  XDR Technical Note XDR Library Primitives Strings  Previous   Contents   Next 
   
 

Byte Arrays

Often variable-length arrays of bytes are preferable to strings. Byte arrays differ from strings in the following three ways:

  • The length of the array, the byte count, is explicitly located in an unsigned integer.

  • The byte sequence is not terminated by a null character.

  • The external representation of the bytes is the same as their internal representation.

The primitive xdr_bytes() converts between the internal and external representations of byte arrays:

bool_t xdr_bytes(xdrs, bpp, lp, maxlength)
   XDR *xdrs;
   char **bpp;
   u_int *lp;
   u_int maxlength;

The usage of the first, second, and fourth parameters is identical to the first, second, and third parameters of xdr_string(). The length of the byte area is obtained by dereferencing lp when serializing; *lp is set to the byte length when deserializing.

Arrays

The XDR library package provides a primitive for handling arrays of arbitrary elements. The xdr_bytes() routine treats a subset of generic arrays, in which the size of array elements is known to be 1, and the external description of each element is built in. The generic array primitive, xdr_array() requires parameters identical to those of xdr_bytes() plus two more: the size of array elements, and an XDR routine to handle each of the elements. This routine is called to encode or decode each element of the array.

bool_t
xdr_array(xdrs, ap, lp, maxlength, elementsize, xdr_element)
   XDR *xdrs;
   char **ap;
   u_int *lp;
   u_int maxlength;
   u_int elementsize;
   bool_t (*xdr_element)();

The parameter ap is the address of the pointer to the array. If *ap is NULL when the array is being deserialized, XDR allocates an array of the appropriate size and sets *ap to that array. The element count of the array is obtained from *lp when the array is serialized; *lp is set to the array length when the array is deserialized. The parameter maxlength is the maximum number of elements that the array is allowed to have; elementsiz is the byte size of each element of the array (the C function sizeof() can be used to obtain this value). The xdr_element() routine is called to serialize, deserialize, or free each element of the array.

Before defining more constructed data types, three examples are presented.

Array Example 1

A user on a networked machine can be identified by

  • The machine name.

  • The user's UID. See the getuid(2) man page.

  • The group numbers to which the user belongs. See the getgroups(2) man page.

A structure with this information and its associated XDR routine could be coded as in the following code example.


Example A-7 Array Example #1

struct netuser {
 	char  *nu_machinename;
 	int   nu_uid;
 	u_int nu_glen;
 	int   *nu_gids;
 };
#define NLEN 255       /* machine names < 256 chars */
#define NGRPS 20       /* user can't be in > 20 groups */

bool_t
xdr_netuser(xdrs, nup)
 	XDR *xdrs;
 	struct netuser *nup;
{
 	return(xdr_string(xdrs, &nup->nu_machinename, NLEN) &&
 		    xdr_int(xdrs, &nup->nu_uid) &&
 		    xdr_array(xdrs, &nup->nu_gids, &nup->nu_glen, NGRPS,
		               sizeof (int), xdr_int));
}

Array Example 2

You could implement a party of network users as an array of netuser structure. The declaration and its associated XDR routines are as shown in the following code example.


Example A-8 Array Example #2

struct party {

 	u_int p_len;
 	struct netuser *p_nusers;
};
#define PLEN 500 /* max number of users in a party */
bool_t
xdr_party(xdrs, pp)
 	XDR *xdrs;
 	struct party *pp;
{
 	return(xdr_array(xdrs, &pp->p_nusers, &pp->p_len, PLEN,
 	 sizeof (struct netuser), xdr_netuser));
}

Array Example 3

You can combine the well-known parameters to main, argc and argv, into a structure. An array of these structures can make up a history of commands. The declarations and XDR routines might look like the following example.


Example A-9 Array Example #3

struct cmd {
 	u_int c_argc;
 	char **c_argv;
};
#define ALEN 1000           /* args cannot be > 1000 chars */
 #define NARGC 100          /* commands cannot have > 100 args */

struct history {
 	u_int h_len;
 	struct cmd *h_cmds;
};
#define NCMDS 75            /* history is no more than 75 commands */

bool_t
xdr_wrapstring(xdrs, sp)

 	XDR *xdrs;
 	char **sp;
{
 	return(xdr_string(xdrs, sp, ALEN));

}

bool_t
xdr_cmd(xdrs, cp)

 	XDR *xdrs;
 	struct cmd *cp;
{
 	return(xdr_array(xdrs, &cp->c_argv, &cp->c_argc, NARGC,
 	        sizeof (char *), xdr_wrapstring));
}
bool_t
xdr_history(xdrs, hp)

 	XDR *xdrs;
 	struct history *hp;
{
 	return(xdr_array(xdrs, &hp->h_cmds, &hp->h_len, NCMDS,
 	        sizeof (struct cmd), xdr_cmd));
}

 
 
 
  Previous   Contents   Next