mirror of
https://github.com/pocoproject/poco.git
synced 2025-01-18 00:15:27 +01:00
performance improvements to DateTimeParser and HTTP server
This commit is contained in:
parent
75ecce9cc4
commit
37dc590bdf
@ -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)
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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();
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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));
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user