#ifndef HEPCOLUMN_H
#define HEPCOLUMN_H

// ----------------------------------------------------------------------
//
// Column.h - class declaration for a Column of an Ntuple
//

// To use:
//   create a HepTuple manager* M
//   create the HepNtuple*h by M->newHepNtuple(title, id=0)
//   define a column using the one of the methods h->ColumnAt()
//						  h->column()
//						  h->newColumn()
//						  h->columnVia()
//   or for a whole block at once, 		  h->block()
//
// Then refine the column definition by calls to h->pack(), h->dimensions(),
// etc.  By returning a pointer to the HepNtuple, and remembering the previous
// column defined, we support syntax like
//     h->ColumnAt(whatever)->pack(whichever)->dimensions(whosis)->index(whom);
//


#ifdef COMMENT
Codeguard name is HEPCOLUMN_H:  Rule is file name starts without the name guard
HEP, so we prepend HEP to the class name.

Mods in development:

7/14/97   	Started this header; including material already known to
		be needed from doing the capture code, and attriutes known
		to be needed from when Gao did the transform code.

#endif // COMMENT


#ifdef COMMENT

In this preliminary version of the header for HepNtuple we
don''t know yet how we will want to handle colums of characters (in
HBOOK they have 8 types, CHAR4 thru CHAR32).  This decision won''t seriously
affect the rest of the interface.

#endif /* COMMENT */

#ifndef ZMENVIRONMENT_H
  #include "ZMutility/ZMenvironment.h"
#endif

#include <string>

#include <stddef.h>

// #include "HepTuple/dummyZMexception.h"
#include "HepTuple/Exceptions.h"

#ifndef FIXEDTYPES_H
  #include "ZMutility/FixedTypes.h"
#endif
ZM_USING_NAMESPACE( zmfxt )

#include "HepTuple/ColumnAttribs.h"
#include "HepTuple/useMethod.h"


ZM_BEGIN_NAMESPACE( zmht )	/*  namespace zmht  {  */

class Block;

class ColInternals {
public:
  // Parent Class for Manager Specific information
  inline ColInternals() {};
  inline virtual ~ColInternals() {};
};

class Column {

public:

  // Create a new Column, its attributes are all set to 0 expect for the type
  // and tag.

  // ************************ //
  // ***** Constructors ***** //
  // ************************ //

  static Column* newColumn( Block* block, ColumnAttribs attrib);
  // Create a ColumnT<T> with the type T implied by attrib

  virtual ~Column();

  virtual Column* duplicate(Block* newBlock) = 0;
  // return an exact duplicate of this without any value,

  // ********************* //
  // ***** Accessors ***** //
  // ********************* //

  bool isCaptured() const;      // is filled for this row
  bool hasBeenStored() const;   // has once been stored, and is thus frozen
                                // in definition and properties
  void setHasBeenStored();      // tell the column that it has been store.
  bool captureCheck() const;    // return true is a we can do a capture
  Block* block() const;         // return the block where the column is.
  bool hasDestination() const;  // return true if a destination has been set.

  ColumnAttribs attributes() const;

  std::string name() const;

  virtual bool checkType(Int1 val); // this is repeated for all simple types
  // check if the column is of the right type (same as argument).

  virtual std::string::size_type sizeofElem() const = 0;
  // return the size of the content of the column
  virtual std::string::size_type sizeofSingleElem() const = 0;
  // return the size of a single element of the column (same as above
  // except in the case of array)

  virtual void* copyToMem(void* addr) = 0;
  // this copy the content of the column at the location indicated by
  // addr and return (addr + sizeofElem())

  virtual bool copyToMem(void* addr, const std::string& indices) = 0;
  // this copy the content of the cell of a column array
  // to the location indicated by addr and true unless the column
  // was not an array or the indices are not understood (and the exception
  // thrown is ignored).

  virtual void* getValueAddr() = 0;
  // return the address of the value of the column.

  // ********************* //
  // ***** Modifiers ***** //
  // ********************* //

  bool setPacking(int nbits, float low, float high);
  bool setSpan(int low, int high);
  bool setDimension ( int dim1, int dim2 = 0,
                      int dim3=0, int dim4=0, int dim5=0, int dim6=0,
                      int dim7=0, int dim8=0, int dim9=0, int dim10=0);
  bool   setIndex(const std::string& indextag);
  bool   getPacking(int* nbits, float* low, float* high);
  bool   getSpan(int* min, int* max);
  std::string getIndex();
  int    getDimension(int* dims);

  bool   isIndex() const;
  void   isIndex(bool newStatus);
  // get (or set) whether the column is used as an index by another column.

  bool setDesignatedVariable (void * variable);
  // Warning this has NO check that the variable has the proper type for the
  // column!
  bool setDestinationVariable(void * variable);
  // Warning this has NO check that the variable has the proper type for the
  // column!
  bool setDesignatedFunction (genericFunction func);
  // Warning this has NO check that the funtion has the proper type for the
  // column!
  bool setDestinationFunction(genericFunction func);
  // Warning this has NO check that the function has the proper type for the
  // column!
  bool setDesignatedMethod (void * method);
  // Warning this has NO check that the method has the proper type for the
  // column!
  bool setDestinationMethod(void * method);
  // Warning this has NO check that the method has the proper type for the
  // column!

  // ****************************** //
  // ***** Capture functions  ***** //
  // ****************************** //

  virtual bool captureDesignatedValues() = 0;
  virtual void clear();
  virtual void setToDefault() = 0;

  // ************************** //
  // ***** Read Functions ***** //
  // ************************** //

  virtual bool read(const void * addr) = 0;
  // copy the value pointed to by addr to the designated variable/
  // function/method.  WARNING This CAN NOT check if the value is of
  // the proper type.  The addr MUST point to an array of the proper size
  // if the column is an array.

  virtual bool read() = 0;
  // copy the value of the column addr to the designated variable/
  // function/method.

  virtual void* copyFromMem(const void* addr) = 0;
  // this copy the content of addr into the Column value
  // and return (addr + sizeofElem())

  // ********************************** //
  // ***** Repeat for other types ***** //
  // ********************************** //

  virtual bool checkType(Int2 val);
  virtual bool checkType(Int4 val);
#ifdef Int8
  virtual bool checkType(Int8 val);
#endif
  virtual bool checkType(UInt1 val);
  virtual bool checkType(UInt2 val);
  virtual bool checkType(UInt4 val);
#ifdef Uint8
  virtual bool checkType(UInt8 val);
#endif
  virtual bool checkType(Float4 val);
  virtual bool checkType(Float8 val);
#ifdef Float16
  virtual bool checkType(Float16 val);
#endif
  virtual bool checkType(bool val);
  // check if the column is of the right type (same as argument).
  virtual bool checkType(void* val);

  // ********************* //
  // ***** Internals ***** //
  // ********************* //
  
  ColInternals* internals(ColInternals* rep = NULL);
  // return the internals pointer.  If rep is not NULL, delete
  // any previous one and replace it by rep

protected:

  // ************************ //
  // ***** Constructors ***** //
  // ************************ //

  Column( Block* block, ColumnAttribs attrib);

  Column( Block* block, const std::string& name);
  // Create a new Column in the block *block, the type is extracted from
  // name using fortran conventions.

  Column( Block* block, const std::string& tag, ColumnData_t type);

  void setIsCaptured(bool val);
  ColumnAttribs _attributes;
  // This data member is only protected to allow for the templated
  // lower class to be able to modify it directly.

private:

  Block* _block; // . . . . . Name of block this column is in
  bool _isCaptured;     // is filled for this row
  bool _hasBeenStored;  // has once been stored, and is thus frozen
			// in definition and properties

  ColInternals *internals_; // for use by the individual managers.

}; /* Column */


ZM_END_NAMESPACE( zmht )	/*  }  // namespace zmht  */

#include "HepTuple/Column.icc"

#endif // Code Guard HEPCOLUMN_H
