/*
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:

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

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

#pragma once

#include "XMill.h"

#define XMILL_ZEROS_STR			"0000000000"

#define XMILL_HEX_0x_STR		"0x"
#define XMILL_HEX_0X_STR		"0X"

#define XMILL_HEX_PREFIX_LEN	2

/* prefix flag bits 0-1 for hex(case)compressor */
#define XMILL_HEX_NONE			0
#define XMILL_HEX_0X				1
#define XMILL_HEX_0x				2
#define XMILL_HEX_RSVD			3
#define XMILL_HEX_BITS			3
#define XMILL_HEX_NUM_BITS		2

#define XMILL_BASEX_MAXDIGITS 32

#define XMILL_BASEX_DEFAULT	10

/* global (un)compressor */
class BaseXNumCompressor : public UserCompressor
{
protected:
   unsigned char base;
   unsigned char preflag;	// bits 6-2 == number of digits in last sequence
									// bits 1-0 == hex prefix
	unsigned long numdigits;
   unsigned long mindigits;
	unsigned char ishexcase;
	unsigned char preskip;
   unsigned char maxdigits;

	virtual long char2num(unsigned char c);
public:
   BaseXNumCompressor(Session *s, unsigned long mymindigits,
							unsigned char base, unsigned char ishexcase);
   void Init(unsigned long mymindigits,
				 unsigned char base, unsigned char ishexcase);
   virtual char ParseString(char *str,unsigned len,char *dataptr);
   virtual void CompressString(char *str,unsigned len,CompressContainer *cont,char *dataptr);
};

class BaseXNumUncompressor : public UserUncompressor
{
protected:
   unsigned char base;
   unsigned char preflag;
	unsigned long numdigits;
	unsigned long restdigits;
   unsigned long mindigits;
	unsigned char ishexcase;
	unsigned char buffer[XMILL_BASEX_MAXDIGITS];
   unsigned char maxdigits;
	unsigned int startdiv;

	virtual unsigned char num2char(unsigned int n);
	virtual void decodeNum(UncompressContainer *cont, XMLOutput *xoutput);
public:
   BaseXNumUncompressor();
   BaseXNumUncompressor(unsigned char base, 
							unsigned char ishexcase, 
							unsigned long mymindigits=0);
   BaseXNumUncompressor(Session *s, 
							unsigned char base, 
							unsigned char ishexcase, 
							unsigned long mymindigits=0);
   void Init(unsigned char base, 
				 unsigned char ishexcase, 
				 unsigned long mymindigits=0);
   virtual void UncompressItem(UncompressContainer *cont,char *dataptr,XMLOutput *xoutput);
};

/* (un)compressors */
class BinCompressor : public BaseXNumCompressor
{
public:
   BinCompressor(Session *s, unsigned long mymindigits);
   //char ParseString(char *str,unsigned len,char *dataptr);
   //void CompressString(char *str,unsigned len,CompressContainer *cont,char *dataptr);
};

class BinUncompressor : public BaseXNumUncompressor
{
public:
   BinUncompressor(unsigned long mymindigits=0);
   BinUncompressor(Session *s, unsigned long mymindigits=0);
   //void Init(unsigned long mymindigits);
   //void UncompressItem(UncompressContainer *cont,char *dataptr,XMLOutput *xoutput);
};

class HexCompressor : public BaseXNumCompressor
{
public:
   HexCompressor(Session *s, unsigned long mymindigits);
   //char ParseString(char *str,unsigned len,char *dataptr);
   //void CompressString(char *str,unsigned len,CompressContainer *cont,char *dataptr);
};

class HexUncompressor : public BaseXNumUncompressor
{
public:
   HexUncompressor(unsigned long mymindigits=0);
   HexUncompressor(Session *s, unsigned long mymindigits=0);
   //void Init(unsigned long mymindigits);
   //void UncompressItem(UncompressContainer *cont,char *dataptr,XMLOutput *xoutput);
};

class HexCaseCompressor : public BaseXNumCompressor
{
public:
   HexCaseCompressor(Session *s, unsigned long mymindigits);
   //char ParseString(char *str,unsigned len,char *dataptr);
   //void CompressString(char *str,unsigned len,CompressContainer *cont,char *dataptr);
};

class HexCaseUncompressor : public BaseXNumUncompressor
{
public:
   HexCaseUncompressor(unsigned long mymindigits=0);
   HexCaseUncompressor(Session *s, unsigned long mymindigits=0);
   //void Init(unsigned long mymindigits);
   //void UncompressItem(UncompressContainer *cont,char *dataptr,XMLOutput *xoutput);
};

class Base64Compressor : public BaseXNumCompressor
{
	long char2num(unsigned char c);
public:
   Base64Compressor(Session *s, unsigned long mymindigits);
   //char ParseString(char *str,unsigned len,char *dataptr);
   void CompressString(char *str,unsigned len,CompressContainer *cont,char *dataptr);
};

class Base64Uncompressor : public BaseXNumUncompressor
{
	unsigned char num2char(unsigned int n);
	void decodeNum(UncompressContainer *cont, XMLOutput *xoutput);
public:
   Base64Uncompressor(unsigned long mymindigits=0);
   Base64Uncompressor(Session *s, unsigned long mymindigits=0);
   //void Init(unsigned long mymindigits);
   //void UncompressItem(UncompressContainer *cont,char *dataptr,XMLOutput *xoutput);
};

/* factories */
class BaseXNumCompressorFactory : public UserCompressorFactory
{
   BaseXNumUncompressor   uncompressor;

public:
   char *GetName();
   char *GetDescription();

	BaseXNumCompressorFactory(Session *s): UserCompressorFactory(s) 
	{
		uncompressor.SetSession(s);
		uncompressor.Init(XMILL_BASEX_DEFAULT, FALSE);
	}

	UserCompressor *InstantiateCompressor(char *paramstr,int len);
	UserUncompressor *InstantiateUncompressor(char *paramstr,int len);
};

class HexCompressorFactory : public UserCompressorFactory
{
   HexUncompressor   uncompressor;

public:
   char *GetName();
   char *GetDescription();

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

	UserCompressor *InstantiateCompressor(char *paramstr,int len);
	UserUncompressor *InstantiateUncompressor(char *paramstr,int len);
};

class HexCaseCompressorFactory : public UserCompressorFactory
{
   HexCaseUncompressor   uncompressor;

public:
   char *GetName();
   char *GetDescription();

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

	UserCompressor *InstantiateCompressor(char *paramstr,int len);
	UserUncompressor *InstantiateUncompressor(char *paramstr,int len);
};

class BinCompressorFactory : public UserCompressorFactory
{
   BinUncompressor   uncompressor;

public:
   char *GetName();
   char *GetDescription();

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

	UserCompressor *InstantiateCompressor(char *paramstr,int len);
	UserUncompressor *InstantiateUncompressor(char *paramstr,int len);
};

class Base64CompressorFactory : public UserCompressorFactory
{
   Base64Uncompressor   uncompressor;

public:
   char *GetName();
   char *GetDescription();

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

	UserCompressor *InstantiateCompressor(char *paramstr,int len);
	UserUncompressor *InstantiateUncompressor(char *paramstr,int len);
};

