/***************************************************************************
 *                                                                         *
 *   PARMMLT.CPP                                                           *
 *                                                                         *
 *   Copyright (c) 1998 Galacticomm, Inc.         All rights reserved.     *
 *                                                                         *
 *   Active HTML multipart parameter container class implementation.       *
 *                                                                         *
 *                                           - J. Alvrus    06/19/1998     *
 *                                                                         *
 ***************************************************************************/

#pragma warn -par
#include "parmmlt.h"

#define FILREV "$Revision: 1 $"

MARKSOURCE(parmmlt)

acthParamMulti::acthParamMulti()   // default constructor (never to be used)
{                                  // (but STL wants it for some reason)
     ASSERTM(0,"acthParamMulti() default constructor called!");
}
acthParamMulti::acthParamMulti(    // constructor
CHAR const * _name,                //   name of parameter (decoded)
CharIStreamIt const * _valbeg,     //   beginning of value
CharIStreamIt const * _valend,     //   past end of value
CharIStreamIt const * _partbeg) :  //   beginning of part
     acthParam(_name,_valbeg,_valend,_partbeg)
{
     // form vector of headers
     CharIStreamIt itBeg=partbeg;
     CharIStreamIt itEnd=partbeg;
     CHAR strCRLF[]="\r\n";
     do {
          // find end of current header
          itEnd=search(itBeg,valbeg,strCRLF,strCRLF+CSTRLEN("\r\n"));
          if (itEnd == itBeg) {
               break;
          }

          // add positions to vector
          m_hdrVec.push_back(HDRPOS(itBeg,itEnd));

          // go to start of next header
          itBeg=itEnd+CSTRLEN("\r\n");
     } while (itBeg != valbeg);
}

INT                                //   returns EOF when done
acthParamMulti::getChar(           // get next (decoded) character from param
CharIStreamIt * pit) const         //   based on this iterator
{
     if ((*pit) == valend) {
          return(EOF);
     }
     INT c=*(*pit);
     ++(*pit);
     return(c);
}

INT
acthParamMulti::numHeaders() const // get number of parameter headers
{
     return(m_hdrVec.size());
}

size_t                             //   returns length of value (less term.)
acthParamMulti::getHeader(         // get a parameter header
INT index,                         //   by index
CHAR *namBuf,                      //   where to put name (eg "parm")
size_t namSiz,                     //   room for name (incl '\0')
CHAR * valBuf,                     //   buffer to receive result
size_t valSiz) const               //   size of buffer
{
     ASSERT(0 <= index && index < numHeaders());
     if (index < 0 || numHeaders() <= index) {
          return(0);
     }
     HDRPOS pos=m_hdrVec[index];
     CharIStreamIt valBeg=find(pos.beg,pos.end,':');
     ExtractHeader(pos.beg,valBeg,namBuf,namSiz);
     ++valBeg;
     return(ExtractHeader(valBeg,pos.end,valBuf,valSiz));
}

bool                               //   returns true if header exists
acthParamMulti::getHeader(         // get a parameter header
CHAR const * name,                 //   by name
CHAR * valBuf,                     //   buffer to receive result
size_t valSiz) const               //   size of buffer
{

     size_t nlen=::strlen(name);
     if (nlen > 0 && name[nlen-1] == ':') {
          nlen--;                  // allow name to end in ":"
     }
     for (INT i=0 ; i < numHeaders() ; ++i) {
          HDRPOS pos=m_hdrVec[i];
          if (itSameTo(name,name+nlen,pos.beg,pos.end)) {
               CharIStreamIt valBeg=pos.beg+nlen+1;
               ExtractHeader(valBeg,pos.end,valBuf,valSiz);
               return(true);
          }
     }
     return(false);
}

size_t                             //   returns length of value (less term.)
acthParamMulti::ExtractHeader(     // extract header contents into buffer
CharIStreamIt const & valBeg,      //   beginning of value
CharIStreamIt const & valEnd,      //   past end of value
CHAR * valBuf,                     //   buffer to receive value
size_t valSiz) const               //   size of buffer
{
     // skip any preceding white space
     CharIStreamIt itOut=valBeg;
     while (itOut != valEnd && isspace(*itOut)) {
          ++itOut;
     }

     // extract to buffer
     return(::StreamToBuffer(itOut,valEnd,valBuf,valSiz));
}
