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

//<file>
//
// Name:    hdrfields.C
//
// Purpose: attributes
//
// Created: 21 Jan 1996 Till Vollmer
//
// $Id: hdrfields.C,v 1.8 1996/10/24 09:18:19 jfasch Exp $
//
// Description:
//   
//</file>
//
// $Log: hdrfields.C,v $
// Revision 1.8  1996/10/24 09:18:19  jfasch
// verbose.h and assert.h and new.h, ERROR was a macro under NT
//
// Revision 1.7  1996/07/12 12:44:42  jfasch
// ooops
//
// Revision 1.6  1996/07/12 12:10:30  jfasch
// GNU feature of putting non-fixed arrays on the stack (or so) won't
// work everywhere.
//
// Revision 1.5  1996/07/08 12:49:59  tvollmer
// bug fix in void HeaderFields::insert(const HeaderField& x)
//
// Revision 1.4  1996/05/23 14:54:23  tvollmer
// removed old tmpfield
//
// Revision 1.3  1996/03/26 12:34:30  tvollmer
// found some bug in length() removed
//
// 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
//

#include "hdrfields.h"
#define VERBOSE
#include <hyperg/utils/verbose.h>
#include <hyperg/utils/assert.h>
// later to insert
//Arraysimplement(RStringArray,RString)

Arraysimplement(HeaderFieldArray,HeaderField)
Fieldsimplement(TmpFieldBase,char)
RString HeaderField::empty_;     // should be enough to realy empty it

void HeaderField::insert(const RString& value)
{
    values_.insert(value);  
// may fail but who cares, cauze its then already in it
}    

void HeaderField::insert(const RStringArray& values)
{
    values_+=values; // merge it
}



// void HeaderFields::init_(const RString& o)
// {
//     RString line;
//     RString name;
//     RString value;
//     int ndx=0;
//     do
//     {
//         if (!o.gWordChar(ndx, '\n', line)) 
//         {
//            line=o.gRight(ndx);
//            ndx=o.length();  // all out
//         }
//         int i;
//         if ((i = line.index(':')) != -1) 
//         {
//             name = line.gSubstrIndex(0, i-1);
//             value = line.gRight(i+1);
// //            cerr << name <<" "<< value << endl;
//             insert(name,value);

           
//             // insert name and value
//             // here
//         }
        
//     }
//     while(ndx<o.length());

// }



// HeaderFields 

HeaderField HeaderFields::emptyheaderfield_;
RString     HeaderFields::empty_;
RStringArray HeaderFields::emptyarray_;   


void HeaderFields::insert(const HeaderField& x)
{
    int pos;
    if(position(x,pos))
    {
        HeaderField find=operator[](pos);
        remove(find);
        find.insert(x.values());
        HeaderFieldArray::insert(find);
    }
    else
        HeaderFieldArray::insert(x);
}



void HeaderFields::insert(const RString& key, const RString& value)
{
    int pos;
    if(position(HeaderField(key),pos))
    {
        HeaderField find=operator[](pos);
        remove(find);
        find.insert(value);
        HeaderFieldArray::insert(find);
    }
    else
    {
        HeaderFieldArray::insert(HeaderField(key,value));
    }

}




const HeaderField& HeaderFields::headerField(const RString& key) const 
{
    int pos;
    if (position(HeaderField(key),pos))
        return operator[](pos);
    
    else
        return emptyheaderfield_;
    
}

const RString& HeaderFields::shortestValue(const RString& key) const
{
    int pos;
    if(position(HeaderField(key),pos))
    {
        const HeaderField& it=operator[](pos);
        const RStringArray& ar=it.values();
        if (ar.count())
        {
            int min=ar[0].length();
            int ind=0;
            for (int y=0;y<ar.count();y++)
            {
                if (ar[y].length()<min)
                {
                    min=ar[y].length();
                    ind=y;
                } 
            }

            return ar[ind];
        }
        else
            return empty_;
    }
    else
    {
//        cerr << "HeaderFields::value() is not here !" << flush << endl;
        return empty_;
    }

}


const RString& HeaderFields::value(const RString& key) const
{
    int pos;
    if(position(HeaderField(key),pos))
    {
        const HeaderField& it=operator[](pos);
        const RStringArray& ar=it.values();
//        cerr <<"HeaderFields::value() got the values" << flush << endl;
        
        if (ar.count())
        {
//            cerr <<"HeaderFields::value() there is at least one" << flush << endl;
            
            return ar[0];
        }
        else
            return empty_;
    }
    else
    {
//        cerr << "HeaderFields::value() is not here !" << flush << endl;
        return empty_;
    }
}
const RStringArray& HeaderFields::values(const RString& key) const
{
    int pos;
    if (position(HeaderField(key),pos))
    {
        const HeaderField& it=operator[](pos);
        return it.values();

    }
    else
    {
//        cerr << "HeaderFields::value() is not here !" << flush << endl;
        return emptyarray_;
    }
}

int HeaderFields::length(const RString& del,const RString& ret,const RString& end) const
{
    int lentores=0;
    for (int i=0;i<count();i++)
    {
        const HeaderField& x=operator[](i);
        const RString& key=x.key();
        const RStringArray& ar=x.values();
        if (ar.count())
        {
            for (int  j=0;j<ar.count();j++)
            {
                lentores+=key.length()+ar[j].length()+del.length()+ret.length();
            }

        }        
        else
        {
            hgassert(0,"HeaderFields::All(): there is a key without value");

        }
        
    }
    lentores+=end.length();
    return lentores;
}

int HeaderFields::write(char* p,const RString& del,const RString& ret,const RString& end) const
{
    const char* x=p; 
    for (int i=0;i<count();i++)
    {
        HeaderField x=operator[](i);
        RString key=x.key();
        RStringArray ar=x.values();
        if (ar.count())
        {
            for (int  j=0;j<ar.count();j++)
            {
                // fast but ugly  :->
                int len=key.length();
                memcpy(p,key.string(),len);
                p+=len;
                len=del.length();
                memcpy(p,del.string(),len);
                p+=len;
                len=ar[j].length();
                memcpy(p,ar[j].string(),len);
                p+=len;
                len=ret.length();
                memcpy(p,ret.string(),len);
                p+=len;
            }
        }        
    }
    memcpy(p,end.string(),end.length());
    p+=end.length();
    return p-x;
}

RString HeaderFields::all(const RString& del,const RString& ret,const RString& end) const
{
    int len=length(del,ret,end);
    char* tmp = new char[len] ;
    int x=write(tmp,del,ret,end);
    hgassert(x==len,"HeaderFields::all() something strange happened");
    RString rv (tmp, len) ;
    delete tmp ;
    return rv ;
}

void HeaderFields::override(const RString& key, const RString& value)
{

    int pos;
    if (position(HeaderField(key),pos))
    {
        const HeaderField& find=operator[](pos);
        remove(find);
    }

    HeaderFieldArray::insert(HeaderField(key,value));
}

boolean HeaderFields::exists(const RString& key) const
{
    return element(HeaderField(key));
}


