// This may look like C code, but it is really -*- C++ -*-
// 
// <copyright> 
//  
//  Copyright (c) 1993 
//  Institute for Information Processing and Computer Supported New Media (IICM), 
//  Graz University of Technology, Austria. 
//  
// </copyright> 
// 
// 
// <file> 
// 
// Name:        hgheader.h
// 
// Purpose:     header sent with documents from/to the document server
// 
// Created:     27 Oct 93   Joerg Faschingbauer
// 
// Modified:    
// 
// Description: 
// 
// 
// </file> 
#ifndef hg_hyperg_hgheader_h
#define hg_hyperg_hgheader_h

#include <hyperg/utils/types.h>
#include <hyperg/utils/str.h>


// <class> 
//  
// Name:             HgHeader
// 
// Purpose:          
// 
// Public Interface: 
// 
// - HgHeader()
//   default constructor 
// 
// - HgHeader (const HgHeader&)
//   copy constructor
// 
// - int read (const char*, int length)
// - int read (const RString&)
// 
//   fills this with the contents of a char array of size length or RString, resp..
//   returns the actual size of the header contained in the array, else -1.
// 
// - void write (RString&) const
// 
//   formats this into an RString in the same way it is read by the above method.
// 
// - boolean ok() const
//   boolean operator !() const
//   operator void*() const
// 
//   check the state of this
// 
// - HgHdrType type() const
//   long size() const
//   long refno() const
//   boolean compressed() const
//   int version() const
// 
//   blah
// 
// - HgHeader& type (HgHdrType)
//   HgHeader& size (long)
//   HgHeader& refno (long)
//   HgHeader& compressed (boolean c)
// 
//   set the members. 
//   as they return *this, you may say "h.size(100).type(HgHeader::HTF)"
// 
// - static const int maxsize
//   static const int minsize
// 
//   (max|min)imal size of a formatted HgHeader. 
// 
// - static const char terminator
// 
//   terminating char of a formatted HgHeader (currently a '\0', but may be changed)
// 
// 
// Description:      
// 
// Writing a HgHeader:
// 
// Make an instance with the non-default constructor and format it into an RString, 
// which you may then write onto anything you want (socket?).
// 
// Reading a HgHeader:
// 
// Make an instance with the default constructor. Then read minsize<=x<=maxsize 
// bytes from the medium you want to read the header from (but only maxsize is 
// guaranteed to work!). Finally use the read() method to fill (parse) the contents of the 
// header from that char array.
// 
// </class> 
class HgHeader {
public:
   enum HgHdrType {
      HTF,
         PLAINTEXT,
         HTML,
         IMAGE,
         MOVIE,
         SCENE,
         AUDIO,
         UNKNOWN,
         POSTSCRIPT,
         NTYPES
         } ;
   enum Def { Default } ;

public:
   HgHeader() ;
   HgHeader (Def) ;
   HgHeader (const HgHeader&) ;

   HgHeader& operator = (const HgHeader&) ;

   int read (const char*, int length) ;
   int read (const RString&) ;
   // size will include the terminating 0-char:
   void write (char*, int& size) const ;
   void write (RString&) const ;

   boolean ok() const { return !is_nil_(); }
   boolean operator !() const { return !ok(); }
   operator void*() const { return (void*)ok(); }

   HgHdrType type() const { return type_; }
   long size() const { return size_; }
   long refno() const { return refno_; }
   boolean compressed() const { return compressed_; }
   int version() const { return usedversion_; }

   HgHeader& type (HgHdrType t) { type_ = t; return *this; }
   HgHeader& size (long s) { size_ = s; return *this; }
   HgHeader& refno (long r) { refno_ = r; return *this; }
   HgHeader& compressed (boolean c) { compressed_ = c; return *this; }

   // can't send out 'notinit' values since old versions (probably 
   // inside old servers and clients) will report an error on reading 
   // such values.
   // one doesn't have to call it explicitly before writing out the header, 
   // HgHeader::write() does it by itself.
   void setDefaults() ;

   static boolean possiblePrefix (const RString&) ;

   static const int maxsize ;
   static const int minsize ;
   static const char terminator ;
   static const RString tag ;
   static const int notinit ;

private:
   // THE contents
   HgHdrType type_ ;
   long size_ ; // size of the data that follow
   long refno_ ; // reference number 
   int compressed_ ;
   int usedversion_ ;
   // 

   static const int version_ ;
   static const char* format_ ;

private:
   void nil_out_() ;
   boolean is_nil_() const ;
   static int get_line_(const char* begin, const char* end) ;
} ;

inline int HgHeader :: read (const RString& s) {
   return read (s.string(), s.length()) ;
}


#endif
