/*
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 Or-Compressor.
// The Or-compressor has name 'or' and a list of other compressors as parameters

#pragma once

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

struct OrCompressorItem
   // Each parameter of the or-compressor is stored in this structur
{
   OrCompressorItem  *next;   // Next parameter
   UserCompressor    *usercompressor;
   UserUncompressor  *useruncompressor;

#ifdef NOTHREAD
   void *operator new(size_t size);
   void operator delete(void *ptr);
#endif
};

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

// Until now, we only implemented the separate Or-compressor
// - i.e. each sub-compressor gets own containers and there
// is no overlapping between containers

class OrSepCompressorFactory;

struct OrSepCompressorInfo
{
	Session *session;
   OrCompressorItem  *subcompressors;

	void SetSession(Session *s) {session = s;}
   void CreateSubCompressors(char *paramstr,int len);
      // Parses a given parameter string and creates the structure of
      // sub-compressor parameters
};

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

class OrSepCompressor : public UserCompressor
   // The compressor part of the Or-compressor,
{
   friend OrSepCompressorFactory;
protected:

   OrSepCompressorInfo  info; // The parameters

   long                 curidx;           // This is used
   OrCompressorItem     *curcompressor;

   unsigned short       curdataoffset;
   unsigned short       curcontoffset;

public:
	OrSepCompressor(Session *s);

   void ComputeProperties();
      // We determine whether the or-compressor is rejecting or can be overlapping
      // Furthermore, we determine the number of containers and the user data size needed

   void InitCompress(CompressContainer *cont,char *dataptr);
      // Before we start any compression, we initialize the compressor.
      // 'dataptr' denotes the state

	char ParseString(char *str,unsigned len,char *dataptr);
      // Parses the string and returns 1, if accepted, otherwise 0.
      // This function does not actually store/compreess 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);
      // Compresses the given input string
      // 'dataptr' denotes the state
      // If the compressor is 'rejecting', then the function can expect
      // that 'ParseString' has been called before.

   void FinishCompress(CompressContainer *cont,char *dataptr);
      // Finishes the compression - the compressor should write any
      // remaining data to the containers

   void PrintCompressInfo(char *dataptr,unsigned long *overalluncomprsize,unsigned long *overallcomprsize);
      // Prints statistical information about how well the compressor compressed
      // the data
};

//**********************************************************************************
//**********************************************************************************
// The decompressor for the separated Or-compressor

class OrSepUncompressor : public UserUncompressor
{
   friend OrSepCompressorFactory;
   OrSepCompressorInfo  info;

	OrSepUncompressor(Session *s);
   void ComputeProperties();
      // Computes the properties. Determines the number of containers
      // and the size of the user data

   void InitUncompress(UncompressContainer *cont,char *dataptr);
      // Initialized the decompressor
      // Each subcompressor is called with the corresponding containers and state

   void UncompressItem(UncompressContainer *cont,char *dataptr,XMLOutput *output);
      // Does the actual decompression of a single text item
      // and prints the text to 'output'
};

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

// The Compressor Factory for the separate Or-compressor
class OrSepCompressorFactory : public UserCompressorFactory
{
public:
   char *GetName();
   char *GetDescription();

	OrSepCompressorFactory(Session *s): UserCompressorFactory(s) {};

   UserCompressor *InstantiateCompressor(char *paramstr,int len);
      // Instantiates the Or-compressor for specific parameters

	UserUncompressor *InstantiateUncompressor(char *paramstr,int len);
      // Instantiates the Or-decompressor for specific parameters
};
