📄 parsercategory.cxx
字号:
#if defined(HAVE_CONFIG_H)
#include "resip/stack/config.hxx"
#endif
#include "resip/stack/HeaderFieldValue.hxx"
#include "resip/stack/ParserCategory.hxx"
#include "rutil/ParseBuffer.hxx"
#include "resip/stack/SipMessage.hxx"
#include "rutil/DataStream.hxx"
#include "rutil/ParseBuffer.hxx"
#include "rutil/compat.hxx"
#include "resip/stack/UnknownParameter.hxx"
#include "resip/stack/ExtensionParameter.hxx"
#include <iostream>
#include <cassert>
#include "rutil/Logger.hxx"
#define RESIPROCATE_SUBSYSTEM Subsystem::SIP
#include "rutil/WinLeakCheck.hxx"
using namespace resip;
using namespace std;
const ParserCategory::ParameterTypeSet
ParserCategory::EmptyParameterTypeSet;
ParserCategory::ParserCategory(HeaderFieldValue* headerFieldValue,
Headers::Type headerType)
: LazyParser(headerFieldValue),
mParameters(),
mUnknownParameters(),
mHeaderType(headerType)
{
}
ParserCategory::ParserCategory()
: LazyParser(),
mHeaderType(Headers::NONE)
{
}
ParserCategory::ParserCategory(const ParserCategory& rhs)
: LazyParser(rhs),
mHeaderType(rhs.mHeaderType)
{
if (isParsed())
{
copyParametersFrom(rhs);
}
}
ParserCategory&
ParserCategory::operator=(const ParserCategory& rhs)
{
if (this != &rhs)
{
clear();
mHeaderType = rhs.mHeaderType;
LazyParser::operator=(rhs);
if (rhs.isParsed())
{
copyParametersFrom(rhs);
}
}
return *this;
}
void
ParserCategory::clear()
{
//DebugLog(<<"ParserCategory::clear");
LazyParser::clear();
for (ParameterList::iterator it = mParameters.begin();
it != mParameters.end(); it++)
{
delete *it;
}
mParameters.clear();
for (ParameterList::iterator it = mUnknownParameters.begin();
it != mUnknownParameters.end(); it++)
{
delete *it;
}
mUnknownParameters.clear();
}
void
ParserCategory::copyParametersFrom(const ParserCategory& other)
{
for (ParameterList::iterator it = other.mParameters.begin();
it != other.mParameters.end(); it++)
{
mParameters.push_back((*it)->clone());
}
for (ParameterList::iterator it = other.mUnknownParameters.begin();
it != other.mUnknownParameters.end(); it++)
{
mUnknownParameters.push_back((*it)->clone());
}
}
ParserCategory::~ParserCategory()
{
clear();
}
const Data&
ParserCategory::param(const ExtensionParameter& param) const
{
checkParsed();
Parameter* p = getParameterByData(param.getName());
if (!p)
{
InfoLog(<< "Referenced an unknown parameter " << param.getName());
throw Exception("Missing unknown parameter", __FILE__, __LINE__);
}
return static_cast<UnknownParameter*>(p)->value();
}
Data&
ParserCategory::param(const ExtensionParameter& param)
{
checkParsed();
Parameter* p = getParameterByData(param.getName());
if (!p)
{
p = new UnknownParameter(param.getName());
mUnknownParameters.push_back(p);
}
return static_cast<UnknownParameter*>(p)->value();
}
bool
ParserCategory::exists(const ParamBase& paramType) const
{
checkParsed();
bool ret = getParameterByEnum(paramType.getTypeNum()) != NULL;
return ret;
}
// removing non-present parameter is allowed
void
ParserCategory::remove(const ParamBase& paramType)
{
checkParsed();
removeParameterByEnum(paramType.getTypeNum());
}
void
ParserCategory::remove(const ExtensionParameter& param)
{
checkParsed();
removeParameterByData(param.getName());
}
bool
ParserCategory::exists(const ExtensionParameter& param) const
{
checkParsed();
return getParameterByData(param.getName()) != NULL;
}
void
ParserCategory::removeParametersExcept(const ParameterTypeSet& set)
{
checkParsed();
for (ParameterList::iterator it = mParameters.begin();
it != mParameters.end();)
{
if (set.find((*it)->getType()) == set.end())
{
delete *it;
it = mParameters.erase(it);
}
else
{
++it;
}
}
}
void
ParserCategory::parseParameters(ParseBuffer& pb)
{
while (!pb.eof() )
{
const char* start = pb.position();
pb.skipWhitespace();
if ( (!pb.eof() && *pb.position() == Symbols::SEMI_COLON[0]) )
{
// extract the key
pb.skipChar();
const char* keyStart = pb.skipWhitespace();
const char* keyEnd = pb.skipToOneOf(" \t\r\n;=?>"); //!dlb! @ here?
if((int)(keyEnd-keyStart) != 0)
{
ParameterTypes::Type type = ParameterTypes::getType(keyStart, (keyEnd - keyStart));
if (type == ParameterTypes::UNKNOWN)
{
mUnknownParameters.push_back(new UnknownParameter(keyStart,
int((keyEnd - keyStart)), pb, " \t\r\n;?>"));
}
else
{
// invoke the particular factory
mParameters.push_back(ParameterTypes::ParameterFactories[type](type, pb, " \t\r\n;?>"));
}
}
}
else
{
pb.reset(start);
return;
}
}
}
static Data up_Msgr("msgr");
ostream&
ParserCategory::encodeParameters(ostream& str) const
{
for (ParameterList::iterator it = mParameters.begin();
it != mParameters.end(); it++)
{
#if 0
// !cj! - may be wrong just hacking
// The goal of all this is not to add a tag if the tag is empty
ParameterTypes::Type type = (*it)->getType();
if ( type == ParameterTypes::tag )
{
Parameter* p = (*it);
DataParameter* d = dynamic_cast<DataParameter*>(p);
Data& data = d->value();
if ( !data.empty() )
{
str << Symbols::SEMI_COLON;
// !ah! this is a TOTAL hack to work around an MSN bug that
// !ah! requires a SPACE after the SEMI following the MIME type.
if (it == mParameters.begin() && getParameterByData(up_Msgr))
{
str << Symbols::SPACE;
}
(*it)->encode(str);
}
}
else
{
str << Symbols::SEMI_COLON;
// !ah! this is a TOTAL hack to work around an MSN bug that
// !ah! requires a SPACE after the SEMI following the MIME type.
if (it == mParameters.begin() && getParameterByData(up_Msgr))
{
str << Symbols::SPACE;
}
(*it)->encode(str);
}
#else
str << Symbols::SEMI_COLON;
// !ah! this is a TOTAL hack to work around an MSN bug that
// !ah! requires a SPACE after the SEMI following the MIME type.
if (it == mParameters.begin() && getParameterByData(up_Msgr))
{
str << Symbols::SPACE;
}
(*it)->encode(str);
#endif
}
for (ParameterList::iterator it = mUnknownParameters.begin();
it != mUnknownParameters.end(); it++)
{
str << Symbols::SEMI_COLON;
(*it)->encode(str);
}
return str;
}
ostream&
resip::operator<<(ostream& stream, const ParserCategory& category)
{
category.checkParsed();
return category.encode(stream);
}
Parameter*
ParserCategory::getParameterByEnum(ParameterTypes::Type type) const
{
for (ParameterList::iterator it = mParameters.begin();
it != mParameters.end(); it++)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -