//-----------------------------------------------------------------------------
// Copyright (c) 1994,1995 Southeastern Universities Research Association,
//                         Continuous Electron Beam Accelerator Facility
//
// This software was developed under a United States Government license
// described in the NOTICE file included as part of this distribution.
//
//-----------------------------------------------------------------------------
//
// Description:
//     Linked list of blocks of void pointer
//     
//            Not safe C++ practice because of void*. 
//            Reason: It is very difficult to do instantiation inside
//                    a shared library.
//
// Author:  Jie Chen
//
// Revision History:
//   cdevBlockList.h,v
// Revision 1.1  1995/12/08  15:33:31  chen
// linked block list
//
// Revision 1.1.1.1  1995/06/16  17:14:07  epics
// initial import of cdev
//
//
#ifndef _CDEV_XOBJ_LIST_H
#define _CDEV_XOBJ_LIST_H

#include <stdio.h>
#include <cdevSpec.h>
#include <assert.h>

typedef void* blockListItem;

//===========================================================================
//    class tranObjBlockList
//          List of blocks each with size
//===========================================================================
const int DEFAULT_BLOCK_SIZE = 64;

class cdevBlockListIterator;

//===========================================================================
//     class cdevBlockLink
//           Node for the cdevBlockList class (private)
//=============================================================================
class CDEV_CLASS_SPEC cdevBlockLink
{
 private:
  //constructors
  // create a single block with all unset value in it
  cdevBlockLink (cdevBlockLink * nextPtr, cdevBlockLink *prevPtr, 
		    unsigned int size = DEFAULT_BLOCK_SIZE);
  // create a single block with default value in it
  cdevBlockLink (cdevBlockLink * nextPtr, cdevBlockLink *prevPtr, 
		    const blockListItem& defVal,
		    unsigned int size = DEFAULT_BLOCK_SIZE);
  // create a single block with some value in it
  cdevBlockLink (cdevBlockLink * nextPtr, cdevBlockLink *prevPtr,
		    blockListItem *date,
		    unsigned int size = DEFAULT_BLOCK_SIZE);
  // copy constructor, copy all lists
  cdevBlockLink (const cdevBlockLink& link);
  // assignment operator
  cdevBlockLink& operator = (const cdevBlockLink &link);
  // destructor
  virtual ~cdevBlockLink (void);

  // operations
  // duplicate whole list
  cdevBlockLink* duplicate (void);
  // duplicate list starting here to the right
  cdevBlockLink* duplicate (int type); // type 0. goes to right, 1 left
  // insert a new block after 
  cdevBlockLink* addNewBlock (void);
  cdevBlockLink* addNewBlock (const blockListItem & defValue);
  // free all memory associated with the list
  void freeAllMemory (void);
  
  // data area
  blockListItem        *value_;
  unsigned int         blockSize_;
  // default value stored in the block
  // keep track how many slots are occupied
  cdevBlockLink     *ptrToNextLink_;
  cdevBlockLink     *ptrToPrevLink_;

  // friends
  friend class cdevBlockList;
  friend class cdevBlockListIterator;
};

class CDEV_CLASS_SPEC cdevBlockList
{
 public:
  // constructors and destructor
  cdevBlockList (unsigned int blockSize = DEFAULT_BLOCK_SIZE);
  cdevBlockList (const blockListItem& defVal, 
		    unsigned int blockSize = DEFAULT_BLOCK_SIZE);
  cdevBlockList (const cdevBlockList &rsc);
  cdevBlockList& operator = (const cdevBlockList &rsc);
  virtual ~cdevBlockList (void);

  // operations
  // access elements via subscript
  virtual blockListItem &  operator [] (unsigned int ) const;
  // free all memory
  virtual void             deleteAll (void);
  // just clean out value
  virtual void             clearAll (void);
  virtual cdevBlockList * duplicate (void) const;
  virtual int              includes (blockListItem value) const;
  virtual int              length (void) const;

 protected:
  // data filed
  cdevBlockLink         firstBlock_;
  unsigned int             blockSize_;
  unsigned int             size_;
  blockListItem*           defValue_;

 private:
  // return how many steps a particular pointer away from
  // the beginning of the first block
  unsigned int           entryNumber (blockListItem *ptr);
  cdevBlockLink*      blockPointer (blockListItem *ptr);
  blockListItem*         entryPointer (unsigned int steps);
  friend class           cdevBlockListIterator;
};

//=========================================================================
//     class cdevBlockListIterator
//             Iterator class used to loop over all list elements
//=========================================================================
class CDEV_CLASS_SPEC cdevBlockListIterator
{
 public:
  // constructor
  cdevBlockListIterator (cdevBlockList &l);
  
  // iterator protocol
  virtual int            init (void);
  virtual blockListItem  operator () ();
  virtual int            operator !();
  // prefix
  virtual int            operator ++();
  virtual void           operator = (blockListItem newValue);

  // new method for blockList
  int                    forcePut (blockListItem value);
  blockListItem *        currentPosition();
  // prefix
  int                    operator --();
  // move cursor to the end of the list
  virtual int            end (void);

 protected:
  // data fields
  cdevBlockList         &data;
  blockListItem*        currEntry_;
  blockListItem*        blockEnd_;
  blockListItem*        blockStart_;
  blockListItem*        listEnd_;
  unsigned int          curPos_;
};
#endif

