/*
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 repeat compressor 'rep'

// We implemented the 'separate' repeat compressor:
// The count is stored in a different container separate from
// the data stored by the subcompressor

// Note that the subcompressor is *always* required to be a non-restricting -
// i.e. the subcompressor must always accept the strings.

#pragma once

#include "CompressMan.hpp"
#include "UnCompCont.hpp"

class RepeatSepCompressorFactory;
class Session;

// The structure for representing the the subcompressor. There is exactly
// one repeat subcompressor and one optional tail compressor.
struct RepeatSepCompressorInfo
{
	Session *session;
	void SetSession(Session *s);

   union{
      UserCompressor       *subcompressor;
      UserUncompressor     *subuncompressor;
   };
   union{
      UserCompressor       *subcompressor2;
      UserUncompressor     *subuncompressor2;
   };

   // The delimiter
   char                 *delimiter;
   unsigned long        delimiterlen;

   void ScanParamString(char *paramstr,int len);
      // Parses a parameter string
};

//********************************************************************************
// The repeat compressor compressor
class RepeatSepCompressor : public UserCompressor
{
   friend RepeatSepCompressorFactory;
protected:

   RepeatSepCompressorInfo info;
   unsigned long           curcount;   // The number strings already parsed

public:
	RepeatSepCompressor(Session *s);
   void ComputeProperties();
      // Determines the properties of the compressor
      // Also determines the number of containers and the size of the user data
   void InitCompress(CompressContainer *cont,char *dataptr);
      // Initializes the subcompressors
   char ParseString(char *str,unsigned len,char *dataptr);
      // Parses the string and returns 1, if accepted, otherwise 0.
      // ParseString is *only* called if there is a tail compressor!
      // Only in this case, the compressor is rejecting.

      // This function does not actually store/compress the string
      // But it can keep an internal state - in the next step,
      // CompressString is called.
   void CompressString(char *str,unsigned len,CompressContainer *cont,char *dataptr);
   void FinishCompress(CompressContainer *cont,char *dataptr);
   void PrintCompressInfo(char *dataptr,unsigned long *overalluncomprsize,unsigned long *overallcomprsize);
};

class RepeatSepUncompressor : public UserUncompressor
{
   friend RepeatSepCompressorFactory;

   RepeatSepCompressorInfo info;
public:
	RepeatSepUncompressor(Session *s);
   void ComputeProperties();
   void InitUncompress(UncompressContainer *cont,char *dataptr);
   void UncompressItem(UncompressContainer *cont,char *dataptr,XMLOutput *output);
};

class RepeatSepCompressorFactory : public UserCompressorFactory
{
public:
	RepeatSepCompressorFactory(Session *s): UserCompressorFactory(s) {};

   char *GetName();
   char *GetDescription();

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

