[Previous] [Top]

3. UTS Representatives

3.1 Representative Examples
3.2 C Representative Library
3.3 Fortran Representative Library
The representative library provides the ability to encode and decode values under programmer control. They provide routines for acquiring empty representatives, disposing of representatives after use, and encoding and decoding values to and from representatives. Since UTS uses tags to label the types of the values and also stores information about the lengths of variable length types, routines are included to check for the presence of the correct tag and to extract the actual length from the represented data. In some cases this information is essential; in others, the programmer may dispense with the checks where the data is known to be of the correct type/size.

3.1 Representative Examples

For the first example, consider
    import zap prog(val rep (integer or float))
    export zap prog(val rep (integer or float))
Note the use of the keyword rep to indicate the use of the representative. To encode the value prior to calling the function zap(), the programmer would execute one of the following, depending on the type of the parameter for the call:
to encode a float:
    long rep_ptr; /* to hold the represented value */
    float float_value; /* to be placed in representative */
    ...
    /* first allocate a representative */
    get_rep(&rep_ptr);
    /* then get enough memory to hold the data */
    user_rep_new(rep_ptr, UTS_FLOAT_SIZE + UTS_TAG_SIZE);
    /* then put the data in the representative */
    uts_encode_float(rep_ptr, float_value);
    zap(rep_ptr);
to encode an integer:
    long rep_ptr; /* to hold the represented value */
    long   int_value; /* to be placed in representative */
    ...
    /* first allocate a representative */
    get_rep(&rep_ptr);
    /* then get enough memory to hold the data */
    user_rep_new(rep_ptr, UTS_INT_SIZE + UTS_TAG_SIZE);
    /* then put the data in the representative */
    uts_encode_int(rep_ptr, int_value);
    zap(rep_ptr);
To decode the value, the type must first be determined, then the value itself can be extracted and placed in a variable of the appropriate type:
    zap(rep_ptr);
        long rep_ptr; /* the representative is allocated by the stub */
    {
        float float_value;
        long int_value;
        /* attempt to extract one of the types */
        if (uts_decode_float(rep_ptr, &float_value) == 1)
            ... processing for float ...
        /* if that fails, attempt to extract the other choice */
        else (uts_decode_int(rep_ptr, &int_value) == 1)
            ... processing for integer ...
        /* if neither desired type is present, an error results */
        else
            ... error handling here ...
        /* free memory that was allocated for representative */
        dispose_rep(&rep_ptr);
            ... continue with zap() ...
Consider the problem of passing command-line arguments to a user-supplied main function. In Schooner, such a function is named user_main() and the runtime will pass user-supplied command line arguments to it. The export specification for this case would be:
    export user_main prog(val rep array [-] of string[-])
The code needed to extract the arguments must first extract the size of the array (argc), then each string in the array can be decoded.
  user_main(rep_ptr)
    long rep_ptr; /* the representative is allocated by the stub */
  {
    int i;
    long argc, num_dims = 1, str_rep;
    char **argv;
    int str_len;
 
    /* extract the size of the argv[] array */
    uts_dims(rep_ptr, &argc, &num_dims);
    if (argc != 0) {
      argv = (char **) malloc((argc + 1) * sizeof (char *));
      for (i = 0; i < argc; i++++) {
        /* extract one string from the representative
         * note it is returned as a representative itself */
        str_rep = uts_index(rep_ptr, i);
        str_len = uts_length(str_rep);
        if (str_len == -1) {
          ... error handling/reporting, bad string size ...
          return; /* so schx will shutdown components */
        }
        str_len++++; /* leave room for terminating null */
        argv[i] = (char *)malloc(str_len);
        /* now get the string from its representative */
        if (uts_decode_string(str_rep, argv[i], str_len) == -1) {
          ... error handling/reporting, bad string size ...
          return; /* so schx will shutdown components */
        }
      }
      argv[argc] = NULL;
    }
    else
      printf("user_main() received no command-line arguments\n");
    dispose_rep(&rep_ptr);
    ... continue with user_main() ...
Note: uts_dims returns the number of dimensions actually found in the represented array. In this example, this value is ignored since the array is known to be one-dimensional.

As a final example, consider the task of encoding and then decoding an array of floats where the array size is unknown at compile time. The UTS specification of such an array would be

    var rep array[-] of float
The user could then use the following two functions to handle the encoding and decoding of the values for this array:
  # include 

  encode_array(size, rep_ptr, src)
    long size;
    long rep_ptr;
    float *src;
  {
    int i, j;
 
    /* allocate space for rep_ptr, including array header */
    user_rep_new(rep_ptr, size * (UTS_FLOAT_SIZE + UTS_TAG_SIZE) + 50);
    uts_start_array(rep_ptr, 1, size); /* encode the actual array size */
    /* encode each value */
    for (i = 0; i < size; i++++)
      uts_encode_float(rep_ptr, *(src[i]));
    uts_end_array(rep_ptr); /* mark the end of the array */
    rep_fixup(rep_ptr); /* let UTS get all the internal sizes correct */
  } /* encode_array */
 
  decode_array(size, rep_ptr, dest)
    int size;
    long rep_ptr;
    float *dest;
  {
    long index;    /* index into represented array */
    int  dims,     /* to hold size of array from representative */
         num_dims; /* # of dimensions in represented array */
    int  i;
 
    num_dims = 1;
    if ( 1 != uts_dims(rep_ptr, &dims, &num_dims) ) {
      ... handle error ...
    }
    if (dims != size) {
      ... handle error ...
    }
    /* extract each value from the representative */
    for (i = 0; i < size; i++++) {
      index = uts_index(rep_ptr, i);
      if ( 1 != uts_decode_float(index, &dest[i]) ) {
          ... handle error ...
      }
    }
    dispose_rep(&rep_ptr); /* free memory alloc'd for representative */
  } /* decode_array */
Note in the above example the use of the UTS tag and size information to ensure the data being decoded is of the correct type and size. The user is free to dispense with the error checking in cases where the information is known to be correct. These checks do, however, allow for handling varying types. Arrays of more than one dimension can also be handled. If some of the dimensions are fixed and others are varying, for example, the library routines can be used to make sure the fixed dimensions are correct before proceeding with the decoding of the values of the array. Similar techniques can be used in handling records containing unknown fields or holding fields of varying types.

3.2 C Representative Library

C routines for allocating and freeing representatives, and taking care of some of the bookkeeping. In the user's code, a Representative * is declared as a long, as in the examples above.
  void get_rep(Representative **)
  void dispose_rep(Representative **)
  void user_rep_new(Representative *, int)
   int uts_append_rep(Representative *dst, Representative *src)
   int rep_fixup(Representative *)
       used to get the lengths of arrays and records correct
C routines for handling the UTS base types:
      int uts_encode_float(Representative *, float)
  ERRCODE uts_decode_float(Representative *, float *)
      int uts_encode_double(Representative *, double)
  ERRCODE uts_decode_double(Representative *, double *)
      int uts_encode_int(Representative *, long)
  ERRCODE uts_decode_int(Representative *, long *)
      int uts_encode_bool(Representative *, int)
  ERRCODE uts_decode_bool(Representative *, int *)
      int uts_encode_string(Representative *, char *)
      int uts_decode_string(Representative *, char *dst, int size)
          returns -1 if string will not fit in dst (as
          determined by size), or there is not a string present;
          else, returns the actual string length
      int uts_encode_bytes(Representative *, char *, int size)
      int uts_decode_bytes(Representative *, char *, int size)
      int uts_length(Representative *)
          returns the length of a UTS_String or UTS_Byte
C routines for handling UTS record types. Note the need to put in the start and end markers for the record, as well as the need to handle each individual field of the record. Since the length of a record is not generally known, the routine rep_fixup() can be used to get the lengths correct after all values have been placed in the representative.
    int uts_start_record(Representative *)
    int uts_end_record(Representative *)
ERRCODE uts_is_record(Representative *)
    int uts_rsize(Representative *)
        returns the number of fields in a UTS_record
   long uts_field(Representative *, int)
        selects the specified field from a UTS_Record, returns a
        Representative *; fields are numbered starting from zero.
C routines for handling UTS array types. This first set of routines handles arrays with specific contents. They will correctly encode or decode the entire array, including needed headers and tags. In those routines where they occur, num_dims is the size of dim_array[ ], and dim_array contains the size of each dimension of the array being encoded or decoded.
    int uts_encode_float_array(Representative *, float array[ ],
        int num_dims, int dim_array[ ])
    int uts_encode_double_array(Representative *, double array[ ],
        int num_dims, int dim_array[ ])
    int uts_encode_int_array(Representative *, int array[ ],
        int num_dims, int dim_array[ ])
ERRCODE uts_decode_float_array(Representative *, float array[ ],
        int num_dims, int dim_array[ ])
ERRCODE uts_decode_double_array(Representative *, double array[ ],
        int num_dims, int dim_array[ ])
ERRCODE uts_decode_int_array(Representative *, int array[ ],
        int num_dims, int dim_array[ ])
These are general routines that can be used to encode and decode arrays containing any type of elements, including arrays that contain other arrays and/or records. Note the need to put in the start and end markers for the array, as well as the need to handle each individual element of the array. Since the length of an array is not always known, the routine rep_fixup() can be used to get the lengths correct after all values have been placed in the representative.
    int uts_start_array(Representative *, int ndims,
    int dim1, [int dim2, ...])
    int uts_end_array(Representative *)
ERRCODE uts_is_array(Representative *)
ERRCODE uts_dims(Representative *, int dim_array[], int *num_dims)
        dim_array[] contains the size of each dimension
        num_dims:  in - size of dim_array[], out - number of dims
    int uts_asize(Representative *)
        returns the number of elements in a UTS_Array
   long uts_index(Representative *, int)
        selects a specified element from a UTS_Array, returns a Representative *
These are provided mostly for use by the Schooner system code; however, they are also available to the C programmer.
        int uts_encode_error(Representative *, long)
    ERRCODE uts_decode_error(Representative *, long *)
        int uts_encode_null(Representative *)
    ERRCODE uts_decode_null(Representative *)
    ERRCODE uts_is_null(Representative *)
        int uts_encode_sig(Representative *, Signature)
    ERRCODE uts_decode_sig(Representative *, Signature *)
    ERRCODE uts_is_sig(Representative *)
        int uts_encode_prog(Representative *, Prog *)
    ERRCODE uts_is_prog(Representative *)

3.3 Fortran Representative Library

Fortran routines for allocating and freeing representatives, and taking care of some of the bookkeeping. In the user's code, a Representative * is declared as an integer.
          subroutine getrep(int_var)
          subroutine disposerep(int_var)
          subroutine repnew(int_var, isize)
    integer function utsappendrep(src_int_var, dst_int_var)
    integer function repfix(int_var)
                     used to get the lengths of arrays correct
Fortran routines for handling the UTS base types:
          subroutine utsencodefloat(int_var, real_var)
    integer function utsdecodefloat(int_var, real_var)
          subroutine utsencodedouble(int_var, double_var)
    integer function utsdecodedouble(int_var, double_var)
          subroutine utsencodeint(int_var, int_var)
    integer function utsdecodeint(int_var, int_var)
    integer function utslen(int_var)
                     returns the length of a UTS_String or UTS_Byte
Fortran routines for handling UTS record types. Note the need to put in the start and end markers for the record, as well as the need to handle each individual field of the record. Since the length of a record is not generally know, the routine repfix() can be used to get the lengths correct after all values have been placed in the representative.
    integer function utsstartrecord(int_var)
    integer function utsendrecord(int_var)
    integer function utsisrecord(int_var)
    integer function utsrsize(int_var)
                     returns the number of fields in a UTS_Record
    integer function utsfield(int_var, int)
                     selects the specified field from a UTS_Record, returns
                     a Representative *
FORTRAN routines for handling UTS array types. The general routines are not complete; however, the routines for encoding and decoding various sized integer, float, and double arrays are. In those routines where they occur, numdims is the size of idim_array, and idim_array contains the size of each dimension of the array being encoded or decoded.
          subroutine utsencodefloatarray(int_var, real_array, numdims, idim_array)
    integer function utsdecodefloatarray(int_var, real_array, numdims, idim_array)
          subroutine utscomputefloatarraysize(numdims, idim_array, length)
                     length returns the number
                     of bytes for the array
          subroutine utsencodearrayheader(int_var, numdims, idim_array, size)
                     isize is the length returned
                     by utscomputefloatarraysize
    integer function utsisarray(int_var)
    integer function utsdims(int_var, idim_array, num_dim)
                     num_dims: in - size of dim_array,
                               out - number of dims
    integer function utsasize(int_var)
                     returns the number of elements
                     in a UTS_Array
    integer function:utsindex(int_var, int)
                     selects a specified element from a
                     UTS_Array, returns a Representative *
The following FORTRAN routines allow a part of a multi-dimensional array to be transmitted between FORTRAN components. They correctly handle the problem of an array of a declared size that is different from the array size that is passed to a subroutine or function. They have not been tested in passing these subset arrays to C; though, the behavior should be correct. In each routine, the idecdims array contains the declared size of the original array, and iactualdims contains the actual dimensions of the subset of the array to be encoded. isize contains the length of the subset of the array in bytes, as returned by utscomputefloatarraysize.
    subroutine utsencode2dfloatarray(irepzap, realarray, iactualdims, idecdims, isize)
    subroutine utsencode3dfloatarray(irepzap, realarray, iactualdims, idecdims, isize)
    subroutine utsencode4dfloatarray(irepzap, realarray, iactualdims, idecdims, isize)
    subroutine utsencode5dfloatarray(irepzap, realarray, iactualdims, idecdims, isize)
    subroutine utsdecode2dfloatarray(irepzap, realarray, iactualdims, idecdims)
    subroutine utsdecode3dfloatarray(irepzap, realarray, iactualdims, idecdims)
    subroutine utsdecode4dfloatarray(irepzap, realarray, iactualdims, idecdims)
    subroutine utsdecode5dfloatarray(irepzap, realarray, iactualdims, idecdims)

[Previous] [Top]