/*
This product contains certain software code or other information
("AT&T Software") proprietary to AT&T Corp. ("AT&T").  The AT&T
Software is provided to you "AS IS".  YOU ASSUME TOTAL RESPONSIBILITY
AND RISK FOR USE OF THE AT&T SOFTWARE.  AT&T DOES NOT MAKE, AND
EXPRESSLY DISCLAIMS, ANY EXPRESS OR IMPLIED WARRANTIES OF ANY KIND
WHATSOEVER, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, WARRANTIES OF
TITLE OR NON-INFRINGEMENT OF ANY INTELLECTUAL PROPERTY RIGHTS, ANY
WARRANTIES ARISING BY USAGE OF TRADE, COURSE OF DEALING OR COURSE OF
PERFORMANCE, OR ANY WARRANTY THAT THE AT&T SOFTWARE IS "ERROR FREE" OR
WILL MEET YOUR REQUIREMENTS.

Unless you accept a license to use the AT&T Software, you shall not
reverse compile, disassemble or otherwise reverse engineer this
product to ascertain the source code for any AT&T Software.

(c) AT&T Corp. All rights reserved.  AT&T is a registered trademark of AT&T Corp.

***********************************************************************

History:

      24/11/99  - initial release by Hartmut Liefke, liefke@seas.upenn.edu
                                     Dan Suciu,      suciu@research.att.com
*/

//********************************************************************
//********************************************************************

// This module contains the standard user compressors, such as 'u', 'u8', 'di', ...

#include "stdafx.h"


// The delta compressor 'di'
DeltaCompressor::DeltaCompressor(Session *s, unsigned long mymindigits): UserCompressor(s)
{
   mindigits=mymindigits;
   datasize=sizeof(DeltaCompressorState);
   contnum=1;isrejecting=1;canoverlap=1;
}

void DeltaCompressor::InitCompress(CompressContainer *cont,char *dataptr)
{
   ((DeltaCompressorState *)dataptr)->prevvalue=0;
}

char DeltaCompressor::ParseString(char *str,unsigned len,char *dataptr)
{
   DeltaCompressorState *state=(DeltaCompressorState *)dataptr;

   if(ParseSignedInt(str,len,&val)==0)
      return 0;

   // We should check that (val-state->prevvalue) fits into a compressed integer !!
   return 1;
}

void DeltaCompressor::CompressString(char *str,unsigned len,CompressContainer *cont,char *dataptr)
{
   long                 dval;
   DeltaCompressorState *state=(DeltaCompressorState *)dataptr;

   dval=val-state->prevvalue;

   if(dval>=0)
      cont->StoreCompressedSInt(0,dval);
   else
      cont->StoreCompressedSInt(1,0xFFFFFFFFL-dval+1L);

   state->prevvalue=val;
}

DeltaUncompressor::DeltaUncompressor(unsigned long mymindigits): UserUncompressor()
{
	Init(mymindigits);
}

DeltaUncompressor::DeltaUncompressor(Session *s, unsigned long mymindigits): UserUncompressor(s)
{
	Init(mymindigits);
}

void DeltaUncompressor::Init(unsigned long mymindigits)
{
   mindigits=mymindigits;

   datasize=sizeof(DeltaCompressorState);
   contnum=1;
}

void DeltaUncompressor::InitUncompress(UncompressContainer *cont,char *dataptr)
{
   ((DeltaCompressorState *)dataptr)->prevvalue=0;
}

void DeltaUncompressor::UncompressItem(UncompressContainer *cont,char *dataptr,XMLOutput *xoutput)
{
   DeltaCompressorState *state=(DeltaCompressorState *)dataptr;

   state->prevvalue+=cont->LoadSInt32();

   if(state->prevvalue&0x80000000L)
      PrintInteger((unsigned long)-state->prevvalue,1,mindigits,xoutput);
   else
      PrintInteger((unsigned long) state->prevvalue,0,mindigits,xoutput);
}

DeltaCompressorFactory::DeltaCompressorFactory(Session *s): UserCompressorFactory(s)
{
	uncompressor.SetSession(s);
}

char *DeltaCompressorFactory::GetName()         
{  
	return "di"; 
}
char *DeltaCompressorFactory::GetDescription()  
{  
	return "Delta compressor for signed integers"; 
}

UserCompressor *DeltaCompressorFactory::InstantiateCompressor(char *paramstr,int len)
{
   unsigned long mindigits=0;
   if(paramstr!=NULL)
   {
      char savechar=paramstr[len];
      paramstr[len]=0;
      mindigits=atoi(paramstr);
      paramstr[len]=savechar;
      if(mindigits<=0)
      {
         XMillException *e = new XMillException(XMILL_ERR_ARGUMENTS, "Invalid parameter '");
         e->ErrorCont(paramstr,len);
         e->ErrorCont("' for compressor 'di'!");
         throw e;
      }
   }
   return new DeltaCompressor(session, mindigits);
}

UserUncompressor *DeltaCompressorFactory::InstantiateUncompressor(char *paramstr,int len)
{
   unsigned long mindigits=0;
   if(paramstr!=NULL)
   {
      char savechar=paramstr[len];
      paramstr[len]=0;
      mindigits=atoi(paramstr);
      paramstr[len]=savechar;
      return new DeltaUncompressor(session, mindigits);
   }
   else
      return &uncompressor;
}
