/*
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 container manager for the compressor XMill

#pragma once

#include "XMillData.h"
#include "MemStreamer.hpp"
#include "ZLib.hpp"
#include "Load.hpp"

// Some class definitions
class Output;
class CompressContainerBlock;
class CompressContainerMan;
class PathDictNode;
class SmallBlockUncompressor;
class CompVPathExpr;
class DecompVPathExpr;

class CompressContainer: public MemStreamer
   // The main structure for representing a container
   // A CompressContainer is simply a MemStreamer-Object
   // Containers are grouped together in CompressContainerBlocks
{
public:
#ifdef NOTHREAD
   void *operator new(size_t size);
   void operator delete(void *ptr);
#endif
};

class CompressContainerBlock
   // Used for grouping a sequence of CompressContainers together.
   // The sequence of CompressContainers follow *directly* the container block object
   // in memory.
{
   friend CompressContainerMan;
	Session *session;
	Settings *settings;
   CompressContainerBlock  *nextblock;       // The next container block in the list
   unsigned short          contnum;          // Number of containers
   unsigned short          userdatasize;     // The compressor associated with the container
                                             // can store user data with the container block
                                             // The user data is physically stored after
                                             // the container objects.
   PathDictNode            *pathdictnode;    // The path dictionary node corresponding to the
                                             // container block
   CompVPathExpr           *cpathexpr;       // The corresponding path expression
   unsigned long           blockid;          // The identifier of the block

   unsigned long ComputeSmallContainerSize();
      // Determines how the accumulated size of all small containers.

   void StoreMainInfo(MemStreamer *output);
      // Stores the structural information about the container block
      // i.e. the number+size of the containers.

   unsigned long GetDataSize();
      // Computes the overall size of the container block

   void CompressSmallContainers(Compressor *compress);
      // Compresses all small containers 
   void CompressLargeContainers(Output *output);
      // Compresses all large containers 

   void FinishCompress();
      // Is called after all small/large containers have been compressed

   void ReleaseMemory();
      // Releases all the memory after compression

public:
#ifdef NOTHREAD
   void *operator new(size_t size,unsigned contnum,unsigned userdatasize);
   void operator delete(void *ptr);
#ifdef SPECIAL_DELETE
   void operator delete(void *ptr,unsigned contnum,unsigned userdatasize);
#endif
#endif
   CompressContainerBlock(Session *s,Settings *se,unsigned long id);
   void Init(Session *s,Settings *se,unsigned long id);
   unsigned long GetID();
      // Returns block ID

   CompressContainer *GetContainer(int idx);
      // Returns the container with index 'idx' (0<=idx<=contnum)
   CompVPathExpr *GetPathExpr();
      // return the path expression of the container block

   unsigned short GetContNum();
      // Returns container number

   char *GetUserDataPtr();
      // Returns a pointer to the actual user data after the container objects

   unsigned long     GetUserDataSize();
      // Returns the size of the container data
};

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

class CompressContainerMan
   // Manages the sequence of container blocks
   // (and each container block has a list of containers)
{
	Session *session;
   unsigned long           containernum;           // The number of containers
   unsigned long           blocknum;               // The number of blocks
   CompressContainerBlock  *blocklist,*lastblock;  // The list of blocks

public:

   CompressContainerMan(Session *s);

   CompressContainerBlock *CreateNewContainerBlock(unsigned contnum,unsigned userdatasize,PathDictNode *mypathdictnode,CompVPathExpr *pathexpr);
      // Creates a new container block with 'contnum' containers , with user data size
      // given by 'userdatasize', with the path dictionary node given by 'mypathdictnode'
      // and the path expression given by 'pathexpr'
      // If there is not enough memory, the function returns NULL.

   void FinishCompress();  // Is called after the compression of all containers has finished

   unsigned long GetDataSize();  // Returns the overall size of all containers

   void StoreMainInfo(MemStreamer *memstream);
      // Compresses the structural information of the container blocks

   unsigned long ComputeSmallContainerSize();
      // Determines the overall size of the small containers

   void CompressSmallContainers(Compressor *compress);
      // Compresses the small containers

   void CompressLargeContainers(Output *output);
      // Compresses the large containers

   void ReleaseMemory();
      // Releases all the memory of the containers
};
