// This may look like C code, but it is really -*- C++ -*-
// 
// <copyright> 
//  
//  Copyright (c) 1996
//  Institute for Information Processing and Computer Supported New Media (IICM), 
//  Graz University of Technology, Austria. 
//  
// </copyright> 
// 
// 
// <file> 
// 
// Name:        tag1valuen.C
// 
// Purpose:     
// 
// Created:     4 Dec 1996   Joerg Faschingbauer
// 
// Modified:    
// 
// Description: 
// 
// formerly called "Till Vollmer's HeaderFields" from libHgHttp.a
// 
// $Id: tag1valuen.C,v 1.1 1997/03/03 10:00:07 root Exp $
// 
// $Log: tag1valuen.C,v $
// Revision 1.1  1997/03/03 10:00:07  root
// Initial revision
//
// 
// </file> 
#include "tag1valuen.h"

#include "assert.h"
#include "buffer.h"

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


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


// --------------------------------------------------------------------
const RString OneTagNValues :: empty_ ;

void OneTagNValues :: insert (const RString& value) {
   values_.append (value) ;
}

void OneTagNValues :: insert (const RStringField& values) {
   values_ += values ;
}

bool OneTagNValues :: operator == (const OneTagNValues& it) const {
   return (::strcasecmp(it.key_,key_)==0) ? true:false;
}

bool OneTagNValues :: operator < (const OneTagNValues& it) const {
   return (::strcasecmp(key_,it.key_)<0) ? true:false;
}

// --------------------------------------------------------------------
int TagAndValues :: length (int tvsep, int linesep, int term) const {
   int lentores=0;
   for (int i=0;i<count();i++) {
      const OneTagNValues& x=operator[](i);
      const RString& key=x.key();
      const RStringField& ar=x.values();
      if (ar.count())
         for (int  j=0;j<ar.count();j++)
            lentores+=key.length()+ar[j].length()+tvsep+linesep;
      else {
         hgassert(0,"TagAndValues::length(): there is a key without value");
      }
   }
   return lentores+=term ;
}

void TagAndValues::insert (const OneTagNValues& x) {
   int pos;
   if(position(x,pos)) {
      // if already in there, simply add the values
      OneTagNValues find=operator[](pos);
      remove(find);
      find.insert(x.values());
      OneTagNValuesArray::insert(find);
   }
   else
      OneTagNValuesArray::insert(x);
}

void TagAndValues::override (const OneTagNValues& o) {
   int pos;
   if (position(o,pos)) {
      const OneTagNValues& find=operator[](pos);
      remove(find);
   }
   OneTagNValuesArray::insert (o) ;
}

bool TagAndValues :: element (const RString& key, OneTagNValues& o) const {
   OneTagNValues lookup (key) ;
   int pos ;
   if (! position (lookup, pos))
      return false ;
   else {
      o = operator[](pos) ;
      return true ;
   }
}

bool TagAndValues :: element (const RString& key) const {
   OneTagNValues lookup (key) ;
   int pos ;
   if (! position (lookup, pos))
      return false ;
   else
      return true ;
}

void TagAndValues :: write (OBuffer& buf, 
                            const RString& tvsep, 
                            const RString& linesep, 
                            const RString& term) const {
   for (int i=0 ; i<count() ; i++) {
      const OneTagNValues& o = operator[] (i) ;
      for (int j=0 ; j<o.values().count() ; j++)
         buf << o.key() << tvsep << o.values()[j] << linesep ;
   }
   buf << term ;
}

void TagAndValues :: write (RString& buf, 
                            const RString& tvsep, 
                            const RString& linesep, 
                            const RString& term) const {
   for (int i=0 ; i<count() ; i++) {
      const OneTagNValues& o = operator[] (i) ;
      for (int j=0 ; j<o.values().count() ; j++) {
         buf += o.key() ;
         buf += tvsep ;
         buf += o.values()[j] ;
         buf += linesep ;
      }
   }
   buf += term ;
}

void TagAndValues :: write (char* buf,
                            const RString& tvsep, 
                            const RString& linesep, 
                            const RString& term) const {
   char* ptr = buf ;
   for (int i=0 ; i<count() ; i++) {
      const OneTagNValues& o = operator[] (i) ;
      for (int j=0 ; j<o.values().count() ; j++) {
         if (o.key().length()) {
            ::memcpy (ptr, o.key().string(), o.key().length()) ;
            ptr += o.key().length() ;
         }
         if (tvsep.length()) {
            ::memcpy (ptr, tvsep.string(), tvsep.length()) ;
            ptr += tvsep.length() ;
         }
         if (o.values()[j].length()) {
            ::memcpy (ptr, o.values()[j].string(), o.values()[j].length()) ;
            ptr += o.values()[j].length() ;
         }
         if (linesep.length()) {
            ::memcpy (ptr, linesep.string(), linesep.length()) ;
            ptr += linesep.length() ;
         }
      }
   }
   if (term.length())
      ::memcpy (ptr, term.string(), term.length()) ;
}

