/*
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 run-length encoder 'rl'

#pragma once

class Session;

#define RUNLENGTH_ITEM_MINSIZE 16

// The run length item is used to store the current run-length item.
// The run length item can be quite large - therefore, we store it
// in a single-chained list. The list grows bigger, if longer items
// need to be stored.

struct CurRunLengthItem
   // The string is stored in the current item
{
   CurRunLengthItem  *next;
   unsigned short    len;     // The current length of data within this item
   unsigned short    size;    // The size of the item

   char *GetStrPtr();
      // Returns the pointer to the data
};

struct CurRunLengthState
   // Represents the state of the run-length encoder
{
	Session *session;
   CurRunLengthItem  *items;        // The list of items
   unsigned short    totallen;      // The overall length of the string
   short             runlencount;   // If -1, if we just started

	void SetSession(Session *s);

   void KeepNewString(unsigned char *str,unsigned short len);
      // Keeps the current string in the memory
      // If the previous memory is not enough, we need to allocate more
      // CurRunLengthItem
};

class RunLengthCompressor : public UserCompressor
{
public:
   RunLengthCompressor(Session *s);

   void InitCompress(CompressContainer *cont,char *dataptr);

	// Note that we don't have function 'ParseString', since it compressor
   // is always accepting
   void CompressString(char *str,unsigned len,CompressContainer *cont,char *dataptr);
	void FinishCompress(CompressContainer *cont,char *dataptr);
      // The compression is finalized by storing the current
      // run length and the value.
};

//****************************************************************************************
// The decompressor for run length encoder

class RunLengthUncompressor : public UserUncompressor
{
public:
   RunLengthUncompressor(Session *s);
   RunLengthUncompressor();
	void Init();
   void InitUncompress(UncompressContainer *cont,char *dataptr);
      // The initialization for the state

   void UncompressItem(UncompressContainer *cont,char *dataptr,XMLOutput *output);
};

class RunLengthCompressorFactory : public UserCompressorFactory
{
   RunLengthUncompressor uncompressor;

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

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

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