performance improvements to DateTimeParser and HTTP server

This commit is contained in:
Guenter Obiltschnig 2009-02-01 20:27:19 +00:00
parent 75ecce9cc4
commit 37dc590bdf
12 changed files with 78 additions and 31 deletions

View File

@ -51,7 +51,7 @@ class ScopedUnlock
/// A class that simplifies thread synchronization
/// with a mutex.
/// The constructor accepts a Mutex and unlocks it.
/// The destructor unlocks the mutex.
/// The destructor locks the mutex.
{
public:
inline ScopedUnlock(M& mutex, bool unlockNow = true): _mutex(mutex)

View File

@ -220,8 +220,27 @@ int icompare(
template <class S>
int icompare(const S& str1, const S& str2)
// A special optimization for an often used case.
{
return icompare(str1, 0, str1.size(), str2.begin(), str2.end());
typename S::const_iterator it1(str1.begin());
typename S::const_iterator end1(str1.end());
typename S::const_iterator it2(str2.begin());
typename S::const_iterator end2(str2.end());
while (it1 != end1 && it2 != end2)
{
typename S::value_type c1(std::tolower(*it1));
typename S::value_type c2(std::tolower(*it2));
if (c1 < c2)
return -1;
else if (c1 > c2)
return 1;
++it1; ++it2;
}
if (it1 == end1)
return it2 == end2 ? 0 : -1;
else
return 1;
}

View File

@ -55,6 +55,7 @@ std::string DateTimeFormatter::format(const Timestamp& timestamp, const std::str
std::string DateTimeFormatter::format(const DateTime& dateTime, const std::string& fmt, int timeZoneDifferential)
{
std::string result;
result.reserve(64);
std::string::const_iterator it = fmt.begin();
std::string::const_iterator end = fmt.end();
while (it != end)
@ -107,6 +108,7 @@ std::string DateTimeFormatter::format(const LocalDateTime& dateTime, const std::
std::string DateTimeFormatter::format(const Timespan& timespan, const std::string& fmt)
{
std::string result;
result.reserve(32);
std::string::const_iterator it = fmt.begin();
std::string::const_iterator end = fmt.end();
while (it != end)
@ -140,6 +142,7 @@ std::string DateTimeFormatter::format(const Timespan& timespan, const std::strin
std::string DateTimeFormatter::tzdISO(int timeZoneDifferential)
{
std::string tzd;
tzd.reserve(8);
if (timeZoneDifferential != UTC)
{
if (timeZoneDifferential >= 0)
@ -165,6 +168,7 @@ std::string DateTimeFormatter::tzdISO(int timeZoneDifferential)
std::string DateTimeFormatter::tzdRFC(int timeZoneDifferential)
{
std::string tzd;
tzd.reserve(8);
if (timeZoneDifferential != UTC)
{
if (timeZoneDifferential >= 0)

View File

@ -1,7 +1,7 @@
//
// UUID.cpp
//
// $Id: //poco/svn/Foundation/src/UUID.cpp#2 $
// $Id: //poco/1.3/Foundation/src/UUID.cpp#4 $
//
// Library: Foundation
// Package: UUID
@ -143,30 +143,32 @@ void UUID::swap(UUID& uuid)
void UUID::parse(const std::string& uuid)
{
if(uuid.size() < 36)
{
if (uuid.size() < 36)
throw SyntaxException(uuid);
}
if(uuid[8] != '-' || uuid[13] != '-' || uuid[18] != '-' || uuid[23] != '-')
{
if (uuid[8] != '-'|| uuid[13] != '-' || uuid[18] != '-' || uuid[23] != '-')
throw SyntaxException(uuid);
}
std::string::const_iterator it = uuid.begin();
_timeLow = 0;
for (int i = 0; i < 8; ++i)
{
_timeLow = (_timeLow << 4) | nibble(*it++);
}
}
++it;
_timeMid = 0;
for (int i = 0; i < 4; ++i)
{
_timeMid = (_timeMid << 4) | nibble(*it++);
}
++it;
_timeHiAndVersion = 0;
for (int i = 0; i < 4; ++i)
{
_timeHiAndVersion = (_timeHiAndVersion << 4) | nibble(*it++);
}
++it;
_clockSeq = 0;
for (int i = 0; i < 4; ++i)
{
_clockSeq = (_clockSeq << 4) | nibble(*it++);
@ -176,7 +178,7 @@ void UUID::parse(const std::string& uuid)
{
_node[i] = (nibble(*it++) << 4) | nibble(*it++) ;
}
}
}
std::string UUID::toString() const

View File

@ -143,6 +143,8 @@ public:
static const std::string CONNECTION_KEEP_ALIVE;
static const std::string CONNECTION_CLOSE;
static const std::string EMPTY;
protected:
HTTPMessage();
/// Creates the HTTPMessage with version HTTP/1.0.

View File

@ -92,6 +92,9 @@ public:
HTTPServerResponse& response() const;
/// Returns a reference to the associated response.
protected:
static const std::string EXPECT;
private:
HTTPServerResponse& _response;
std::istream* _pStream;

View File

@ -237,7 +237,9 @@ void HTTPCookie::setHttpOnly(bool flag)
std::string HTTPCookie::toString() const
{
std::string result(_name);
std::string result;
result.reserve(256);
result.append(_name);
result.append("=");
if (_version == 0)
{

View File

@ -62,6 +62,7 @@ const std::string HTTPMessage::TRANSFER_ENCODING = "Transfer-Encoding";
const std::string HTTPMessage::CONNECTION = "Connection";
const std::string HTTPMessage::CONNECTION_KEEP_ALIVE = "Keep-Alive";
const std::string HTTPMessage::CONNECTION_CLOSE = "Close";
const std::string HTTPMessage::EMPTY;
HTTPMessage::HTTPMessage():
@ -98,8 +99,9 @@ void HTTPMessage::setContentLength(int length)
int HTTPMessage::getContentLength() const
{
if (has(CONTENT_LENGTH))
return NumberParser::parse(get(CONTENT_LENGTH));
const std::string& contentLength = get(CONTENT_LENGTH, EMPTY);
if (!contentLength.empty())
return NumberParser::parse(contentLength);
else
return UNKNOWN_CONTENT_LENGTH;
}
@ -116,10 +118,7 @@ void HTTPMessage::setTransferEncoding(const std::string& transferEncoding)
const std::string& HTTPMessage::getTransferEncoding() const
{
if (has(TRANSFER_ENCODING))
return get(TRANSFER_ENCODING);
else
return IDENTITY_TRANSFER_ENCODING;
return get(TRANSFER_ENCODING, IDENTITY_TRANSFER_ENCODING);
}
@ -155,10 +154,7 @@ void HTTPMessage::setContentType(const MediaType& mediaType)
const std::string& HTTPMessage::getContentType() const
{
if (has(CONTENT_TYPE))
return get(CONTENT_TYPE);
else
return UNKNOWN_CONTENT_TYPE;
return get(CONTENT_TYPE, UNKNOWN_CONTENT_TYPE);
}
@ -173,8 +169,9 @@ void HTTPMessage::setKeepAlive(bool keepAlive)
bool HTTPMessage::getKeepAlive() const
{
if (has(CONNECTION))
return icompare(get(CONNECTION), CONNECTION_KEEP_ALIVE) == 0;
const std::string& connection = get(CONNECTION, EMPTY);
if (!connection.empty())
return icompare(connection, CONNECTION_KEEP_ALIVE) == 0;
else
return getVersion() == HTTP_1_1;
}

View File

@ -136,6 +136,7 @@ const std::string& HTTPRequest::getHost() const
void HTTPRequest::setCookies(const NameValueCollection& cookies)
{
std::string cookie;
cookie.reserve(64);
for (NameValueCollection::ConstIterator it = cookies.begin(); it != cookies.end(); ++it)
{
if (it != cookies.begin())
@ -207,6 +208,9 @@ void HTTPRequest::read(std::istream& istr)
std::string method;
std::string uri;
std::string version;
method.reserve(16);
uri.reserve(64);
version.reserve(16);
int ch = istr.get();
if (ch == eof) throw NoMessageException();
while (std::isspace(ch)) ch = istr.get();

View File

@ -51,6 +51,9 @@ namespace Poco {
namespace Net {
const std::string HTTPServerRequestImpl::EXPECT("Expect");
HTTPServerRequestImpl::HTTPServerRequestImpl(HTTPServerResponse& response, HTTPServerSession& session, HTTPServerParams* pParams):
_response(response),
_pStream(0),
@ -87,7 +90,8 @@ HTTPServerRequestImpl::~HTTPServerRequestImpl()
bool HTTPServerRequestImpl::expectContinue() const
{
return has("Expect") && icompare(get("Expect"), "100-continue") == 0;
const std::string& expect = get(EXPECT, EMPTY);
return !expect.empty() && icompare(expect, "100-continue") == 0;
}

View File

@ -81,11 +81,15 @@ void MessageHeader::write(std::ostream& ostr) const
void MessageHeader::read(std::istream& istr)
{
static const int eof = std::char_traits<char>::eof();
std::string name;
std::string value;
name.reserve(32);
value.reserve(64);
int ch = istr.get();
while (ch != eof && ch != '\r' && ch != '\n')
{
std::string name;
std::string value;
name.clear();
value.clear();
while (ch != eof && ch != ':' && ch != '\n' && name.length() < MAX_NAME_LENGTH) { name += ch; ch = istr.get(); }
if (ch == '\n') { ch = istr.get(); continue; } // ignore invalid header lines
if (ch != ':') throw MessageException("Field name too long/no colon found");
@ -118,6 +122,7 @@ void MessageHeader::splitElements(const std::string& s, std::vector<std::string>
std::string::const_iterator it = s.begin();
std::string::const_iterator end = s.end();
std::string elem;
elem.reserve(64);
while (it != end)
{
if (*it == '"')
@ -174,11 +179,15 @@ void MessageHeader::splitParameters(const std::string& s, std::string& value, Na
void MessageHeader::splitParameters(const std::string::const_iterator& begin, const std::string::const_iterator& end, NameValueCollection& parameters)
{
std::string pname;
std::string pvalue;
pname.reserve(32);
pvalue.reserve(64);
std::string::const_iterator it = begin;
while (it != end)
{
std::string pname;
std::string pvalue;
pname.clear();
pvalue.clear();
while (it != end && std::isspace(*it)) ++it;
while (it != end && *it != '=' && *it != ';') pname += *it++;
Poco::trimRightInPlace(pname);

View File

@ -92,8 +92,9 @@ void NameValueCollection::set(const std::string& name, const std::string& value)
{
Iterator it = _map.find(name);
if (it != _map.end())
_map.erase(it);
_map.insert(HeaderMap::value_type(name, value));
it->second = value;
else
_map.insert(HeaderMap::value_type(name, value));
}