//<copyright>
//
// Copyright (c) 1996
// Institute for Information Processing and Computer Supported New Media (IICM),
// Graz University of Technology, Austria.
//
//</copyright>

//<file>
//
// Name:    hdrfields.h
//
// Purpose: attributes
//
// Created: 22 Jan 1996 Till Vollmer
//
// $Id: hdrfields.h,v 1.7 1997/02/03 14:26:16 jfasch Exp $
//
// Description:
//   
//</file>
//
// $Log: hdrfields.h,v $
// Revision 1.7  1997/02/03 14:26:16  jfasch
// shortcut for finished entry
//
// Revision 1.6  1996/10/24 09:18:19  jfasch
// verbose.h and assert.h and new.h, ERROR was a macro under NT
//
// Revision 1.5  1996/05/23 14:54:23  tvollmer
// removed the old tmpfield
//
// Revision 1.4  1996/03/07 11:21:48  jfasch
// due to a compile run on our IBM, which is always fatal
//
// Revision 1.3  1996/03/04 09:23:10  jfasch
// some undeclared functions on *very* OS's --> extern
//
// Revision 1.2  1996/03/04 08:41:33  tvollmer
// *** empty log message ***
//
// Revision 1.1  1996/02/27 10:27:50  jfasch
// Initial revision
//
#ifndef http_hdrfields_h
#define http_hdrfields_h

#include <hyperg/utils/str.h>
#include <hyperg/utils/fields.h>
#include <hyperg/utils/arrays.h>
#include <string.h>

#ifdef WIN32
#include <strings.h>
#endif

#include "libhttp.h"

#include <hyperg/utils/strarr.h>

#if (defined SUN) && (HG_OSMaj == 4) || (defined ULTRIX) || (defined AIX)
extern "C" int strcasecmp (const char*, const char*) ;
#endif

class HeaderField
{
public:
    HeaderField(){};
    HeaderField(const RString& it):key_(it){}
    HeaderField(const RString& key,const RString& value):key_(key){insert(value);}
    HeaderField(const RString& key,const RStringArray& values):key_(key),values_(values){}


    void insert(const RString& value);
    void insert(const RStringArray& values);
    int operator ==(const HeaderField& it) const  {return (strcasecmp(it.key_,key_)==0) ? true:false;}
    int operator !=(const HeaderField& it) const {return !(it.key_==key_);} // :->
    int operator <(const HeaderField& it) const {return (strcasecmp(key_,it.key_)<0) ? true:false;}
//    static friend ostream& operator <<(ostream&,const HeaderField&);
    const RString& value() const {if (values_.count()) return values_[0]; else return empty_;}
    const RStringArray& values() const {return values_;}
    const RString& key()const {return key_;}
private:
    RString key_;
    RStringArray values_;
    static RString empty_;
};

inline ostream& operator <<(ostream& os,const HeaderField& at)
{
    return os << at.key() << endl << at.values();
} 

Arraysdeclare(HeaderFieldArray,HeaderField)

class HeaderFields: public HeaderFieldArray
{
public:
    //    HeaderFields(const RString & it){init_(it);}
    //    HeaderFields(const char* it){init_(RString(it));}
    HeaderFields(){}

    int length(const RString& =": ",const RString& ="\r\n",const RString& ="\r\n" ) const;  // length of header without \0 byte !! 
    
    void insert(const HeaderField& x);
    void insert(const RString&, const RString&);
    void override(const RString&, const RString&);

    const RString& value(const RString&)const ;
    const RString& shortestValue(const RString&) const;

    const RStringArray& values(const RString&) const;

    boolean exists(const RString&) const;

    const HeaderField& headerField(const RString&) const ;

    RString all(const RString& =": ",const RString& ="\r\n",const RString& ="\r\n") const;

    int write(char*,const RString& =": ",const RString& ="\r\n",const RString& ="\r\n") const;

private:
    //    void init_(const RString&);
    static HeaderField emptyheaderfield_;
    static RString empty_;
    static RStringArray emptyarray_;
};


Fieldsdeclare(TmpFieldBase,char)

class TmpField
{
public:
   TmpField():buf_((int)SIZE){}
   TmpField& operator << (char c) { buf_.append(c); return *this; }

   // eat the current content of buf_ as name
   bool name() ;
   // eat the current content of buf_ as value
   bool value() ;

   bool end (HeaderField&) ;
   bool end (RString&) ;

private:    
   enum { SIZE = 256 } ;
   HeaderField hf_ ;
   TmpFieldBase buf_;
};

inline bool TmpField :: name() {
    
    hf_ = HeaderField (RString(buf_.data(),buf_.count())) ;
    buf_=TmpFieldBase((int)SIZE);  // reinit
    return true ;
}

inline bool TmpField :: value() {
    hf_.insert (RString(buf_.data(),buf_.count())) ;
    buf_=TmpFieldBase((int)SIZE);  // reinit
    return true ;
}

inline bool TmpField :: end (HeaderField& hf) {
   hf = hf_ ;
   return true ;
}

inline bool TmpField :: end (RString& s) {
    s=RString(buf_.data(),buf_.count());
    buf_=TmpFieldBase((int)SIZE);  // reinit
    return true ;
}
#endif







