 /*
  * Khoros: $Id: raw.c,v 1.4 1992/03/20 23:40:37 dkhoros Exp $
  */

#if !defined(lint) && !defined(SABER)
static char rcsid[] = "Khoros: $Id: raw.c,v 1.4 1992/03/20 23:40:37 dkhoros Exp $";
#endif

 /*
  * $Log: raw.c,v $
 * Revision 1.4  1992/03/20  23:40:37  dkhoros
 * VirtualPatch5
 *
  */ 

/*
 *----------------------------------------------------------------------
 *
 * Copyright 1990, University of New Mexico.  All rights reserved.

 * Permission to copy and modify this software and its documen-
 * tation only for internal use in your organization is hereby
 * granted, provided that this notice is retained thereon and
 * on all copies.  UNM makes no representations as too the sui-
 * tability and operability of this software for any purpose.
 * It is provided "as is" without express or implied warranty.
 * 
 * UNM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FIT-
 * NESS.  IN NO EVENT SHALL UNM BE LIABLE FOR ANY SPECIAL,
 * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY OTHER DAMAGES WHAT-
 * SOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
 * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PER-
 * FORMANCE OF THIS SOFTWARE.
 * 
 * No other rights, including for example, the right to redis-
 * tribute this software and its documentation or the right to
 * prepare derivative works, are granted unless specifically
 * provided in a separate license agreement.
 *---------------------------------------------------------------------
 */

/*
#
# FILE NAME:	raw.c
# 
# AUTHORS:	Mark Young & Tom Sauer
#
# 
# DATE:		11/10/89
# 
# DESCRIPTION:
#	RAW data utilites, for read and writing raw data.
#
# 
# MODIFICATIONS:
# 
*/

#include "unmcopyright.h"	 
#include "vinclude.h"	 	

/**************************************************************
*
* MODULE NAME: 	new_read_raw
*
*     PURPOSE:
*
*       INPUT:
*	fid		file descriptor pointing to the stream in
*			which the raw floating point data is located
*	points		returns the number of points found in the raw
*			floating point data file
*	mach_type 	the machine dependancy type (IEEE, NSORDER, DECORDER)
*		        if  = -1 then no conversion is attempted.
*
*       convert_to_flaot   Only up convert when it is needed.  The up 
*                       conversion to float is necessary becuase of 
*                       limitations in load_viff_data() for complicated
*                       raw data organizations.
*
*      OUTPUT:
*
*	data		returns the data points found in the raw file
*
* CALLED FROM: main
*
* ROUTINES CALLED:
*
**************************************************************/

#define ALLOCSIZE 50000

float	*new_read_raw(fid, offset, points, type, mach_type, convert_to_float)

int 	fid, type, offset, convert_to_float;
int 	*points, mach_type;
{
	int	num_bytes, num, size;
	char	*data;
	float	*temp, *convert_raw_data();

	/* allocate memory space for data */
	size =  ALLOCSIZE;
	data = (char *) malloc ((unsigned int) size);

	/* read data and determine number of points */
	num_bytes = 0;

	do
	{
	   if (num_bytes == size)
	   {
	      size += ALLOCSIZE;
	      if (!(data = (char *) realloc(data, (unsigned) size)))
	      {
	         (void) fprintf(stderr,"Not enough memory!  Tried to malloc %d \
bytes.", size);
	         return (NULL);
	      }
	   }

	   if ((num = block_read(fid, (char *) (data + num_bytes),
			(size - num_bytes))) > 0)
	   {
	      num_bytes += num;
	   }
	} while (num > 0);

	if (offset > 0) {
	    num_bytes -= offset;
	    bcopy(&data[offset], data, num_bytes);
	}
	temp = convert_raw_data(data, type, num_bytes, points, mach_type,convert_to_float);

	/*  A new temp is malloced if it is a complicated convert, so free */
	if (convert_to_float == TRUE) free(data);

	return(temp);
}



float *convert_raw_data(data, type, num_bytes, num_points, mach_type, complex_convert)

char	*data;
int	type, num_bytes, *num_points, mach_type, complex_convert;
{
	int	i, size, unit_size, status, current_machine;
	float	*temp;

	short	*sptr;
	int	*iptr;
	float	*fptr;
	unsigned char *bptr, *cptr, c;

 /*
  * Determine current machine type.
  */
        current_machine = machtype(NULL);

        if (type == VFF_TYP_BIT)
	{
	   /*
	    *  Since the type is byte then the size is simply the number of
	    *  bytes times 8.
	    */
	   size = num_bytes*8;
	}
	else
	{
	   unit_size = getmachsize(mach_type, (unsigned long) type);
           size      = num_bytes/unit_size;

	   /*
	    *  Round down to the nearest float.  Warn the user if the last point
	    *  is not a complete float.
	    */
	   if (((num_bytes % unit_size) != 0) && (unit_size > 1))
	   {
	      (void) fprintf(stderr,"lraw2viff: Warning!  Last point in the \
file was an incomplete.\n(%d out of %d bytes found)\n", (num_bytes % unit_size),
	      unit_size);
	   }

	   if (type == VFF_TYP_COMPLEX)
	      size *= 2;
	}
        *num_points  = size;

	 status    = cast_data((unsigned char **) &data,
                         (unsigned int) size,
                         (unsigned int) type,
                         (unsigned int) mach_type,
                         (unsigned int) current_machine);
        if (status == FALSE)
        {
             (void) fprintf(stderr, "error in casting data.\n");
             return(NULL);
        }

	/*
	 *  Finished reading the data points from the file.  Try to malloc
	 *  the final array with the exact number of points.  If we don't
	 *  have enough size then we return data, otherwise we copy data
	 *  to temp, free data, and return temp as the points in the file.
	 */

	if (complex_convert == TRUE) {
	    if (!(temp = (float *) malloc((unsigned int) size * sizeof(float))))
	    {
	       return(NULL);
	    }
	}
        else {       /*  complex_convert is FALSE */
	    return((float *) data);
	}

	switch (type)
	{
	   case VFF_TYP_BIT:
		bptr = (unsigned char *) data;
		for (i = 0; i < size; i++)
		{
		    c = (1 << (i % 8));
		    temp[i] = (float) (c & (*bptr));

		    if ((i % 8) == 7)
		       bptr++;
		}
		break;

	   case VFF_TYP_1_BYTE:
		cptr = (unsigned char *) data;
		for (i = 0; i < size; i++)
		    temp[i] = (float) cptr[i];
		break;

	   case VFF_TYP_2_BYTE:
		sptr = (short *) data;
		for (i = 0; i < size; i++)
		    temp[i] = (float) sptr[i];
		break;

	   case VFF_TYP_4_BYTE:
		iptr = (int *) data;
		for (i = 0; i < size; i++)
		    temp[i] = (float) iptr[i];
		break;

	   case VFF_TYP_FLOAT:
	   case VFF_TYP_COMPLEX:
		fptr = (float *) data;
		for (i = 0; i < size; i++)
		    temp[i] = (float) fptr[i];
		break;
	}
	return(temp);
}



/**************************************************************
*
* MODULE NAME: 	write_raw
*
*     PURPOSE:  This routine writes a raw data array to the
*		desired file, specified by fid.
*
*		Note:  This routine is really not necessary since
*		       all it does is write the data to the fid.
*		       But it is hoped that others will use this
*		       routine so that at a later time there will
*		       be only one routine to change.  For example,
*		       if data caching is to be added to khoros then
*		       this routine would be converted to write data
*		       to shared memory or sockets, not just file
*		       descriptors.
*
*
*       INPUT:
*
*	fid		file descriptor pointing to the stream in
*			which the raw floating point data is located
*
*	data		the raw data array to written to fid
*
*	num_bytes	number of bytes found in the raw data array
*
*      OUTPUT:	Outputs the raw data to the desired file.
*
* CALLED FROM: main
*
* ROUTINES CALLED:
*
**************************************************************/

int	write_raw(fid, data, num_bytes)

int	fid, num_bytes;
char	*data;
{
	int	num;

	num = kwrite(fid, data, num_bytes);
	if (num != num_bytes)
	{
	   (void) fprintf(stderr, "\nwrite_raw:\n");
	   (void) fprintf(stderr, "Write failed!  Only able to write %d out of\
 %d bytes to disk.\n");
	   return(0);
	}
	return(1);
}
