#ident "$Id: lzsmem.c,v 1.1 1995/03/16 17:08:29 garyp Exp $"
/*****************************************************************************
 * Copyright (c) 1988-95 Digi International Inc., All Rights Reserved
 * 
 * This  software  contains  proprietary  and  confidential   information   of
 * Digi International  Inc.   By  accepting  transfer  of this copy, Recipient
 * agrees to retain this software in  confidence,  to  prevent  disclosure  to
 * others,  and  to make no  use of this software other than that for which it
 * was delivered.  This is an unpublished copyright work  Digi   International
 * Inc.    Except   as   permitted   by  federal  law,  17 USC 117, copying is
 * strictly prohibited.
 * 
 * Digi  International  Inc.  CONFIDENTIAL  -   (Digi    International    Inc.
 * Confidential  when   combined   with   the   aggregated  modules  for  this
 * product) OBJECT CODE ONLY SOURCE MATERIALS
 * 
 * (C) COPYRIGHT Digi International Inc. 1995
 * 
 * All Rights Reserved
 * 
 * US   Government   Users   Restricted   Rights   -   Use,   duplication   or
 * disclosure  restricted by GSA ADP Schedule Contract with Digi International
 * Inc.
 * 
 *****************************************************************************/

/*----------------------------------------------------------------------*/
/* LZS221-C Version 4.0							*/
/*----------------------------------------------------------------------*/
/* LZSMEM.C - Buffer copy functions					*/
/*									*/
/*  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!	*/
/*  !!                                                              !!	*/
/*  !!  NOTE:                                                       !!	*/
/*  !!  The contents of this document constitute                    !!	*/
/*  !!           CONFIDENTIAL INFORMATION                           !!	*/
/*  !!  		(C) Stac Electronics 1994.                  !!	*/
/*  !!					                            !!	*/
/*  !!      Including one or more U.S. Patents:			    !!	*/
/*  !!		No. 4701745, 5016009, 5126739 and 5146221 and       !!	*/
/*  !!                  other pending patents.               	    !!	*/
/*  !!                                                              !!	*/
/*  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!	*/
/*									*/
/*----------------------------------------------------------------------*/
/*									*/
/* Copyright 1994 Stac Electronics, Carlsbad, California.		*/
/* All rights reserved.  This code is Stac confidential property, and	*/
/* the algorithms and methods used herein may not be disclosed to any	*/
/* party without express written consent from Stac Electronics.		*/
/*								      	*/
/*----------------------------------------------------------------------*/
#include "lzs.h"      
#include "types.h"
#define MAX_BLOCK_SIZE_TYPE long
#define SIZEOF_tOrigByteIndex 4
#define MAX_BUFFR_SIZE_TYPE long
#if defined (LZS_FAST)
#define _FAST_
#define _Small_Blocks_
#define MAX_ORIG_INDEX OrigCnt
#undef LZS_SMALL_BUFFERS
#define LZS_SMALL_BUFFERS
#endif
#if defined (_BIG_CMPRS_BFR_)
#define MAX_ORIG_CNT_FAST 57343U
#else
#define _EARLY_OUT_ 1
#define MAX_ORIG_CNT_FAST 63487U
#endif
#define MAX_INDEX	~((tOrigByteIndex) 0)
#if !defined MAX_ORIG_INDEX
#define MAX_ORIG_INDEX \
		((flags & LZS_SOURCE_FLUSH) ? OrigCnt : MAX_INDEX)
#endif
#if defined (_Small_Blocks_)
#undef MAX_BLOCK_SIZE_TYPE
#undef SIZEOF_tOrigByteIndex
#define MAX_BLOCK_SIZE_TYPE 	short
#define SIZEOF_tOrigByteIndex 	2
#endif
#if defined (LZS_SMALL_BUFFERS)
#undef MAX_BUFFR_SIZE_TYPE
#define MAX_BUFFR_SIZE_TYPE 	short
#define MAX_BUFFER_SIZE 	0xFFFFU
#endif
typedef unsigned MAX_BUFFR_SIZE_TYPE tMaxBfrSz;
typedef unsigned MAX_BLOCK_SIZE_TYPE tOrigByteIndex;
#define FP_Off(fp) fp
#define dREG
#define pREG register
unsigned char LZS_FAR *LZS_FAR mem_copy_r (
	void LZS_FAR   *pDestn,		
	void LZS_FAR   *pSource,        
	unsigned short  Nbytes          
)
{
	register unsigned char LZS_FAR * pEnd =
		(unsigned char LZS_FAR *) pDestn
																  + Nbytes;
#if !defined (LZS_ALIGNED)
	register unsigned long	dwReg;
#endif
	
	
	if (Nbytes > 7) {
		
		if (((uint3264)pSource) & 1) {
			*(unsigned char LZS_FAR *) pDestn =
				 *(unsigned char LZS_FAR *) pSource;
			pDestn = ((unsigned char LZS_FAR *) pDestn + 1);
			pSource = ((unsigned char LZS_FAR *) pSource + 1);
		}
		if (((uint3264)pSource) & 2) {
			*(unsigned char LZS_FAR *) pDestn =
				*(unsigned char LZS_FAR *) pSource;
			*((unsigned char LZS_FAR *) pDestn + 1) =
				*((unsigned char LZS_FAR *) pSource+1);
			pDestn = ((unsigned char LZS_FAR *) pDestn + 2);
			pSource = ((unsigned char LZS_FAR *) pSource + 2);
		}
		pEnd -= 3;	
#if !defined (LZS_ALIGNED)
		if (((uint3264)pDestn) & 1) {
			while ((unsigned char LZS_FAR *)pDestn < pEnd) {
				dwReg = *(unsigned long LZS_FAR *) pSource;
#if (LZS_BYTE_ORDER == LZS_LITTLE_END)
					
					
					*(unsigned char LZS_FAR *) pDestn =
						(unsigned char) dwReg;
					pDestn = ((unsigned char LZS_FAR *)
						pDestn + 1);
					dwReg >>= 8;
					*(unsigned short LZS_FAR *) pDestn =
						(unsigned short)dwReg;
					dwReg >>= 16;
					*((unsigned char LZS_FAR *) pDestn+2) =
						(unsigned char) dwReg;
#else
					
					
					*((unsigned char LZS_FAR *) pDestn+3) =
						(unsigned char) dwReg;
					pDestn = ((unsigned char LZS_FAR *)
						pDestn + 1);
					dwReg >>= 8;
					*(unsigned short LZS_FAR *) pDestn =
						(unsigned short)dwReg;
					dwReg >>= 16;
					*((unsigned char LZS_FAR *) pDestn-1) =
						(unsigned char) dwReg;
#endif
				pDestn = ((unsigned char LZS_FAR *)
					pDestn + 3);
				pSource = ((unsigned char LZS_FAR *)
					pSource + 4);
			}	
		}
		else if (((uint3264)pDestn) & 2) {
			
			while ((unsigned char LZS_FAR *)pDestn < pEnd) {
				*(unsigned short LZS_FAR *) pDestn =
					*(unsigned short LZS_FAR *) pSource;
				*((unsigned short LZS_FAR *) pDestn + 1) =
					*((unsigned short LZS_FAR *)pSource+1);
				pDestn = ((unsigned short LZS_FAR *)pDestn+2);
				pSource= ((unsigned short LZS_FAR *)pSource+2);
			}	
		}
		else {	
			
			while ((unsigned char LZS_FAR *)pDestn < pEnd) {
				*(unsigned long LZS_FAR *) pDestn =
					*(unsigned long LZS_FAR *)  pSource;
				pDestn = ((unsigned long LZS_FAR *) pDestn+1);
				pSource = ((unsigned long LZS_FAR *)pSource+1);
			}
		}
#else
		while ((unsigned char LZS_FAR *)pDestn < pEnd) {
			*(unsigned long LZS_FAR *) pDestn =
				*(unsigned long LZS_FAR *) pSource;
			pDestn = ((unsigned long LZS_FAR *) pDestn + 1);
			pSource = ((unsigned long LZS_FAR *) pSource + 1);
		}
#endif
		pEnd += 3;	
	}
	
	while ((unsigned char LZS_FAR *)pDestn < pEnd) {
		*(unsigned char LZS_FAR *) pDestn =
			*(unsigned char LZS_FAR *) pSource;
		pDestn = ((unsigned char LZS_FAR *) pDestn + 1);
		pSource = ((unsigned char LZS_FAR *) pSource + 1);
	}
	return ((unsigned char LZS_FAR *)pDestn);
}
unsigned char LZS_FAR * LZS_FAR copy_prev_string_r (
	unsigned char LZS_FAR *pDestn,	
	unsigned short	       Offset,	
	tMaxBfrSz 	       Nbytes	
					
)
{
	unsigned char LZS_FAR *pEnd;
	unsigned char LZS_FAR *pSi;	
	unsigned long  	       E_A_X;
	unsigned short	       i;
	pSi = pDestn - Offset;
	pEnd = pDestn + Nbytes;		
	if (Offset >= 4) {
Off4Plus:
		
		if (Nbytes & 1) {
			*pDestn++ = *pSi++;	
		}
		if (Nbytes & 2) {
#if !defined (LZS_ALIGNED)
			*pDestn = *pSi;
			*(pDestn+1) = *(pSi+1);
#else
			*(unsigned short LZS_FAR *) pDestn =
				*(unsigned short LZS_FAR *) pSi;
#endif
			pDestn += 2;
			pSi += 2;
		}
		while (pDestn < pEnd)   {
#if !defined (LZS_ALIGNED)
			*pDestn = *pSi;
			*(pDestn+1) = *(pSi+1);
			*(pDestn+2) = *(pSi+2);
			*(pDestn+3) = *(pSi+3);
#else
			*(unsigned long LZS_FAR *) pDestn =
				*(unsigned long LZS_FAR *) pSi;
#endif
			pDestn += 4;
			pSi += 4;
		}
		return (pDestn);	
	}
	if (Offset > 1) {
		if (Nbytes < 3) {
			while ( pDestn < pEnd )
				*pDestn++ = *pSi++;
				return (pDestn);
				
		}
		Nbytes -= Offset;	
		for (i = Offset; i; i--)
			 *pDestn++ = *pSi++;
		pSi -= Offset;
		goto Off4Plus;
	}
	
	E_A_X  = (((unsigned long) *pSi) << 8) | *pSi;
	E_A_X |= E_A_X << 16;
#if !defined (LZS_ALIGNED)
	
	if (Nbytes > 7) {
		
		if (((uint3264)pDestn) & 1) {
			*pDestn++ = (unsigned char) E_A_X;
		}
		if (((uint3264)pDestn) & 2) {
			*(unsigned char LZS_FAR *) pDestn =
				(unsigned char) E_A_X;
			*((unsigned char LZS_FAR *) pDestn + 1) =
				(unsigned char) E_A_X;
			pDestn += 2;
		}
		pEnd -= 3;	
				
		while (pDestn < pEnd) {
			*(unsigned long LZS_FAR *) pDestn = E_A_X;
			pDestn += 4;
		}
		pEnd += 3;	
	}
	
	while (pDestn < pEnd) {
		*pDestn++ = (unsigned char)E_A_X;
	}
#else
	if (Nbytes & 1) *pDestn++ = (unsigned char)E_A_X;
		
	if (Nbytes & 2) {
		*(unsigned short LZS_FAR *) pDestn = (unsigned short) E_A_X;
		pDestn += 2;
	}
	while (pDestn < pEnd)   {
		*(unsigned long LZS_FAR *) pDestn = E_A_X;
		pDestn += 4;
	}
#endif
	return (pDestn); 	
}
void LZS_FAR init_hash_tbl_r (
	void 	LZS_FAR *pDestn,    
	void 	LZS_FAR *pPattern,  
	unsigned short 	 wNbytes    
)
{
	register unsigned long E_A_X;
	register unsigned char LZS_FAR *pEnd;
	E_A_X = *(unsigned long LZS_FAR *)pPattern;	
	pEnd  = (unsigned char LZS_FAR *) pDestn + (wNbytes & 0xFFF8);
	while ( (unsigned char LZS_FAR *)pDestn < pEnd ) {
		*(unsigned long LZS_FAR *) pDestn = E_A_X;
		*((unsigned long LZS_FAR *) pDestn + 1) = E_A_X;
		pDestn = ((unsigned long LZS_FAR *) pDestn + 2);
	}
	if (wNbytes & 4) {	
		*(unsigned long LZS_FAR *) pDestn = E_A_X;
		pDestn = ((unsigned long LZS_FAR *) pDestn + 1);
	}
	if (wNbytes & 2) {	
		*(unsigned short LZS_FAR *)pDestn = (unsigned short)E_A_X;
	}
}
