Rewritten util::stripIter(), which now returns pair of iterator.

pull/2/head
Tatsuhiro Tsujikawa 2011-11-03 16:19:21 +09:00
parent e8d4deecad
commit 6ef91d60b3
10 changed files with 108 additions and 84 deletions

View File

@ -198,24 +198,6 @@ void HttpHeader::setRequestPath(const std::string& requestPath)
requestPath_ = requestPath; requestPath_ = requestPath;
} }
namespace {
template<typename InputIterator>
std::pair<InputIterator, InputIterator> stripIter2
(InputIterator first, InputIterator last,
const std::string& chars = "\r\n \t")
{
for(; first != last &&
std::find(chars.begin(), chars.end(), *first) != chars.end(); ++first);
if(first == last) {
return std::make_pair(first, last);
}
InputIterator left = last-1;
for(; left != first &&
std::find(chars.begin(), chars.end(), *left) != chars.end(); --left);
return std::make_pair(first, left+1);
}
} // namespace
void HttpHeader::fill void HttpHeader::fill
(std::string::const_iterator first, (std::string::const_iterator first,
std::string::const_iterator last) std::string::const_iterator last)
@ -233,7 +215,7 @@ void HttpHeader::fill
// multiline header? // multiline header?
if(*first == ' ' || *first == '\t') { if(*first == ' ' || *first == '\t') {
std::pair<std::string::const_iterator, std::pair<std::string::const_iterator,
std::string::const_iterator> p = stripIter2(first, j); std::string::const_iterator> p = util::stripIter(first, j);
if(!name.empty() && p.first != p.second) { if(!name.empty() && p.first != p.second) {
if(!value.empty()) { if(!value.empty()) {
value += ' '; value += ' ';
@ -246,9 +228,9 @@ void HttpHeader::fill
put(name, value); put(name, value);
} }
std::pair<std::string::const_iterator, std::pair<std::string::const_iterator,
std::string::const_iterator> p = stripIter2(first, sep); std::string::const_iterator> p = util::stripIter(first, sep);
name.assign(p.first, p.second); name.assign(p.first, p.second);
p = stripIter2(sep+1, j); p = util::stripIter(sep+1, j);
value.assign(p.first, p.second); value.assign(p.first, p.second);
} }
} }

View File

@ -309,11 +309,12 @@ bool parseMetalinkHttpLink(MetalinkHttpEntry& result, const std::string& s)
if(last == s.end()) { if(last == s.end()) {
return false; return false;
} }
std::string uri = util::stripIter(first+1, last); std::pair<std::string::const_iterator,
if(uri.empty()) { std::string::const_iterator> p = util::stripIter(first+1, last);
if(p.first == p.second) {
return false; return false;
} else { } else {
result.uri = uri; result.uri.assign(p.first, p.second);
} }
last = std::find(last, s.end(), ';'); last = std::find(last, s.end(), ';');
if(last != s.end()) { if(last != s.end()) {

View File

@ -66,7 +66,8 @@ bool parseNsCookie
return false; return false;
} }
std::string cookieDomain = cookie::removePrecedingDots(vs[0]); std::string cookieDomain = cookie::removePrecedingDots(vs[0]);
if(vs[5].empty() || cookieDomain.empty() || !cookie::goodPath(vs[2])) { if(vs[5].empty() || cookieDomain.empty() ||
!cookie::goodPath(vs[2].begin(), vs[2].end())) {
return false; return false;
} }
int64_t expiryTime; int64_t expiryTime;

View File

@ -148,10 +148,13 @@ bool ServerStatMan::load(const std::string& filename)
return false; return false;
} }
} }
std::string line = util::stripIter(&buf[0], &buf[strlen(buf)]); std::pair<std::string::const_iterator,
if(line.empty()) { std::string::const_iterator> p =
util::stripIter(&buf[0], &buf[strlen(buf)]);
if(p.first == p.second) {
continue; continue;
} }
std::string line(p.first, p.second);
std::vector<std::string> items; std::vector<std::string> items;
util::split(line, std::back_inserter(items), ","); util::split(line, std::back_inserter(items), ",");
std::map<std::string, std::string> m; std::map<std::string, std::string> m;

View File

@ -108,7 +108,7 @@ int cookieRowMapper(void* data, int columns, char** values, char** names)
std::string cookieName = toString(values[4]); std::string cookieName = toString(values[4]);
std::string cookiePath = toString(values[1]); std::string cookiePath = toString(values[1]);
if(cookieName.empty() || cookieDomain.empty() || if(cookieName.empty() || cookieDomain.empty() ||
!cookie::goodPath(cookiePath)) { !cookie::goodPath(cookiePath.begin(), cookiePath.end())) {
return 0; return 0;
} }
int64_t expiryTime; int64_t expiryTime;

View File

@ -65,13 +65,16 @@ std::string::const_iterator getNextDigit
} }
} // namespace } // namespace
bool parseDate(time_t& time, const std::string& cookieDate) bool parseDate
(time_t& time,
std::string::const_iterator first,
std::string::const_iterator last)
{ {
// Following algorithm is described in // Following algorithm is described in
// http://tools.ietf.org/html/rfc6265#section-5.1.1 // http://tools.ietf.org/html/rfc6265#section-5.1.1
std::vector<std::string> dateTokens; std::vector<std::string> dateTokens;
for(std::string::const_iterator i = cookieDate.begin(), for(std::string::const_iterator i = first,
eoi = cookieDate.end(); i != eoi;) { eoi = last; i != eoi;) {
unsigned char c = *i; unsigned char c = *i;
if(isDelimiter(c)) { if(isDelimiter(c)) {
++i; ++i;
@ -210,12 +213,16 @@ bool parse
if(eq == nvEnd) { if(eq == nvEnd) {
return false; return false;
} }
std::string cookieName = util::stripIter(cookieStr.begin(), eq); std::pair<std::string::const_iterator,
if(cookieName.empty()) { std::string::const_iterator> p =
util::stripIter(cookieStr.begin(), eq);
if(p.first == p.second) {
return false; return false;
} }
std::string cookieValue = util::stripIter(eq+1, nvEnd); std::string cookieName(p.first, p.second);
cookieValue = util::strip(cookieValue, "\""); p = util::stripIter(eq+1, nvEnd);
p = util::stripIter(p.first, p.second, "\"");
std::string cookieValue(p.first, p.second);
time_t expiryTime = 0; time_t expiryTime = 0;
bool foundExpires = false; bool foundExpires = false;
bool persistent = false; bool persistent = false;
@ -233,36 +240,41 @@ bool parse
for(std::string::const_iterator i = nvEnd; i != end;) { for(std::string::const_iterator i = nvEnd; i != end;) {
std::string::const_iterator j = std::find(i, end, ';'); std::string::const_iterator j = std::find(i, end, ';');
std::string::const_iterator eq = std::find(i, j, '='); std::string::const_iterator eq = std::find(i, j, '=');
std::string attrName = util::stripIter(i, eq); p = util::stripIter(i, eq);
std::string attrName(p.first, p.second);
util::lowercase(attrName); util::lowercase(attrName);
std::string attrValue; std::pair<std::string::const_iterator,
if(eq != j) { std::string::const_iterator> attrp;
attrValue = util::stripIter(eq+1, j); if(eq == j) {
attrp.first = attrp.second = j;
} else {
attrp = util::stripIter(eq+1, j);
} }
i = j; i = j;
if(j != end) { if(j != end) {
++i; ++i;
} }
if(attrName == "expires") { if(attrName == "expires") {
if(parseDate(expiryTime, attrValue)) { if(parseDate(expiryTime, attrp.first, attrp.second)) {
foundExpires = true; foundExpires = true;
} else { } else {
return false; return false;
} }
} else if(attrName == "max-age") { } else if(attrName == "max-age") {
if(attrValue.empty() || if(attrp.first == attrp.second ||
(!in(static_cast<unsigned char>(attrValue[0]), 0x30u, 0x39u) && (!in(static_cast<unsigned char>(*attrp.first), 0x30u, 0x39u) &&
attrValue[0] != '-')) { *attrp.first != '-')) {
return false; return false;
} }
for(std::string::const_iterator s = attrValue.begin()+1, for(std::string::const_iterator s = attrp.first+1,
eos = attrValue.end(); s != eos; ++s) { eos = attrp.second; s != eos; ++s) {
if(!in(static_cast<unsigned char>(*s), 0x30u, 0x39u)) { if(!in(static_cast<unsigned char>(*s), 0x30u, 0x39u)) {
return false; return false;
} }
} }
int64_t delta; int64_t delta;
if(util::parseLLIntNoThrow(delta, attrValue)) { if(util::parseLLIntNoThrow(delta,
std::string(attrp.first, attrp.second))) {
foundMaxAge = true; foundMaxAge = true;
if(delta <= 0) { if(delta <= 0) {
maxAge = 0; maxAge = 0;
@ -279,19 +291,19 @@ bool parse
return false; return false;
} }
} else if(attrName == "domain") { } else if(attrName == "domain") {
if(attrValue.empty()) { if(attrp.first == attrp.second) {
return false; return false;
} }
std::string::const_iterator noDot = attrValue.begin(); std::string::const_iterator noDot = attrp.first;
std::string::const_iterator end = attrValue.end(); std::string::const_iterator end = attrp.second;
for(; noDot != end && *noDot == '.'; ++noDot); for(; noDot != end && *noDot == '.'; ++noDot);
if(noDot == end) { if(noDot == end) {
return false; return false;
} }
cookieDomain = std::string(noDot, end); cookieDomain = std::string(noDot, end);
} else if(attrName == "path") { } else if(attrName == "path") {
if(goodPath(attrValue)) { if(goodPath(attrp.first, attrp.second)) {
cookiePath = attrValue; cookiePath.assign(attrp.first, attrp.second);
} else { } else {
cookiePath = defaultPath; cookiePath = defaultPath;
} }
@ -349,9 +361,11 @@ std::string removePrecedingDots(const std::string& host)
return std::string(noDot, end); return std::string(noDot, end);
} }
bool goodPath(const std::string& cookiePath) bool goodPath
(std::string::const_iterator first,
std::string::const_iterator last)
{ {
return !cookiePath.empty() && cookiePath[0] == '/'; return first != last && *first == '/';
} }
std::string canonicalizeHost(const std::string& host) std::string canonicalizeHost(const std::string& host)

View File

@ -47,7 +47,10 @@ class Cookie;
namespace cookie { namespace cookie {
bool parseDate(time_t& time, const std::string& cookieDate); bool parseDate
(time_t& time,
std::string::const_iterator first,
std::string::const_iterator last);
bool parse bool parse
(Cookie& cookie, (Cookie& cookie,
@ -58,7 +61,9 @@ bool parse
std::string removePrecedingDots(const std::string& host); std::string removePrecedingDots(const std::string& host);
bool goodPath(const std::string& cookiePath); bool goodPath
(std::string::const_iterator first,
std::string::const_iterator last);
std::string canonicalizeHost(const std::string& host); std::string canonicalizeHost(const std::string& host);

View File

@ -190,7 +190,10 @@ const std::string DEFAULT_STRIP_CHARSET("\r\n\t ");
std::string strip(const std::string& str, const std::string& chars) std::string strip(const std::string& str, const std::string& chars)
{ {
return stripIter(str.begin(), str.end(), chars); std::pair<std::string::const_iterator,
std::string::const_iterator> p =
stripIter(str.begin(), str.end(), chars);
return std::string(p.first, p.second);
} }
void divide void divide
@ -203,8 +206,11 @@ void divide
hp.first = strip(src); hp.first = strip(src);
hp.second = A2STR::NIL; hp.second = A2STR::NIL;
} else { } else {
hp.first = stripIter(first, dpos); std::pair<std::string::const_iterator,
hp.second = stripIter(dpos+1, last); std::string::const_iterator> p = stripIter(first, dpos);
hp.first.assign(p.first, p.second);
p = stripIter(dpos+1, last);
hp.second.assign(p.first, p.second);
} }
} }

View File

@ -142,22 +142,19 @@ int32_t difftvsec(struct timeval tv1, struct timeval tv2);
extern const std::string DEFAULT_STRIP_CHARSET; extern const std::string DEFAULT_STRIP_CHARSET;
template<typename InputIterator> template<typename InputIterator>
std::string stripIter std::pair<InputIterator, InputIterator> stripIter
(InputIterator first, InputIterator last, (InputIterator first, InputIterator last,
const std::string& chars = DEFAULT_STRIP_CHARSET) const std::string& chars = DEFAULT_STRIP_CHARSET)
{ {
if(std::distance(first, last) == 0) {
return A2STR::NIL;
}
for(; first != last && for(; first != last &&
std::find(chars.begin(), chars.end(), *first) != chars.end(); ++first); std::find(chars.begin(), chars.end(), *first) != chars.end(); ++first);
if(first == last) { if(first == last) {
return A2STR::NIL; return std::make_pair(first, last);
} }
InputIterator left = last-1; InputIterator left = last-1;
for(; left != first && for(; left != first &&
std::find(chars.begin(), chars.end(), *left) != chars.end(); --left); std::find(chars.begin(), chars.end(), *left) != chars.end(); --left);
return std::string(first, left+1); return std::make_pair(first, left+1);
} }
std::string strip std::string strip
@ -367,9 +364,13 @@ OutputIterator split(const std::string& src, OutputIterator out,
std::string::const_iterator j = i; std::string::const_iterator j = i;
for(; j != last && for(; j != last &&
std::find(delims.begin(), delims.end(), *j) == delims.end(); ++j); std::find(delims.begin(), delims.end(), *j) == delims.end(); ++j);
std::string t = doStrip?util::stripIter(i, j):std::string(i, j); std::pair<std::string::const_iterator,
if(allowEmpty || !t.empty()) { std::string::const_iterator> p(i, j);
*out++ = t; if(doStrip) {
p = stripIter(i, j);
}
if(allowEmpty || p.first != p.second) {
*out++ = std::string(p.first, p.second);
} }
i = j; i = j;
if(j != last) { if(j != last) {
@ -489,24 +490,27 @@ nextParam
parmnameLast = last; parmnameLast = last;
} }
} }
std::string tname, tvalue; std::pair<std::string::const_iterator,
std::string::const_iterator> namep;
std::pair<std::string::const_iterator,
std::string::const_iterator> valuep;
if(parmnameFirst == parmnameLast) { if(parmnameFirst == parmnameLast) {
if(!eqFound) { if(!eqFound) {
parmnameFirst = first; parmnameFirst = first;
parmnameLast = last; parmnameLast = last;
tname = util::stripIter(parmnameFirst, parmnameLast); namep = stripIter(parmnameFirst, parmnameLast);
} }
} else { } else {
first = parmnameLast+1; first = parmnameLast+1;
tname = util::stripIter(parmnameFirst, parmnameLast); namep = stripIter(parmnameFirst, parmnameLast);
tvalue = util::stripIter(first, last); valuep = stripIter(first, last);
} }
if(last != end) { if(last != end) {
++last; ++last;
} }
if(!tname.empty()) { if(namep.first != namep.second) {
name.swap(tname); name.assign(namep.first, namep.second);
value.swap(tvalue); value.assign(valuep.first, valuep.second);
return std::make_pair(last, true); return std::make_pair(last, true);
} }
first = last; first = last;

View File

@ -34,25 +34,33 @@ void CookieHelperTest::testParseDate()
{ {
// RFC1123 // RFC1123
time_t time = 0; time_t time = 0;
CPPUNIT_ASSERT(cookie::parseDate(time, "Sat, 06 Sep 2008 15:26:33 GMT")); std::string s = "Sat, 06 Sep 2008 15:26:33 GMT";
CPPUNIT_ASSERT(cookie::parseDate(time, s.begin(), s.end()));
CPPUNIT_ASSERT_EQUAL((time_t)1220714793, time); CPPUNIT_ASSERT_EQUAL((time_t)1220714793, time);
// RFC850 // RFC850
CPPUNIT_ASSERT(cookie::parseDate(time, "Saturday, 06-Sep-08 15:26:33 GMT")); s = "Saturday, 06-Sep-08 15:26:33 GMT";
CPPUNIT_ASSERT(cookie::parseDate(time, s.begin(), s.end()));
CPPUNIT_ASSERT_EQUAL((time_t)1220714793, time); CPPUNIT_ASSERT_EQUAL((time_t)1220714793, time);
// ANSI C's asctime() // ANSI C's asctime()
CPPUNIT_ASSERT(cookie::parseDate(time, "Sun Sep 6 15:26:33 2008")); s = "Sun Sep 6 15:26:33 2008";
CPPUNIT_ASSERT(cookie::parseDate(time, s.begin(), s.end()));
CPPUNIT_ASSERT_EQUAL((time_t)1220714793, time); CPPUNIT_ASSERT_EQUAL((time_t)1220714793, time);
s = "Thu Jan 1 0:0:0 1970";
CPPUNIT_ASSERT(cookie::parseDate(time, "Thu Jan 1 0:0:0 1970")); CPPUNIT_ASSERT(cookie::parseDate(time, s.begin(), s.end()));
CPPUNIT_ASSERT_EQUAL((time_t)0, time); CPPUNIT_ASSERT_EQUAL((time_t)0, time);
CPPUNIT_ASSERT(!cookie::parseDate(time, "Thu Jan 1 1970 0:")); s = "Thu Jan 1 1970 0:";
CPPUNIT_ASSERT(!cookie::parseDate(time, "Thu Jan 1 1970 0:0")); CPPUNIT_ASSERT(!cookie::parseDate(time, s.begin(), s.end()));
CPPUNIT_ASSERT(!cookie::parseDate(time, "Thu Jan 1 1970 0:0:")); s = "Thu Jan 1 1970 0:0";
CPPUNIT_ASSERT(!cookie::parseDate(time, s.begin(), s.end()));
s = "Thu Jan 1 1970 0:0:";
CPPUNIT_ASSERT(!cookie::parseDate(time, s.begin(), s.end()));
// Leap year // Leap year
CPPUNIT_ASSERT(cookie::parseDate(time, "Tue, 29 Feb 2000 00:00:00 GMT")); s = "Tue, 29 Feb 2000 00:00:00 GMT";
CPPUNIT_ASSERT(!cookie::parseDate(time, "Thu, 29 Feb 2001 00:00:00 GMT")); CPPUNIT_ASSERT(cookie::parseDate(time, s.begin(), s.end()));
s = "Thu, 29 Feb 2001 00:00:00 GMT";
CPPUNIT_ASSERT(!cookie::parseDate(time, s.begin(), s.end()));
} }
void CookieHelperTest::testDomainMatch() void CookieHelperTest::testDomainMatch()