diff --git a/coding/coding_tests/uri_test.cpp b/coding/coding_tests/uri_test.cpp index 73b2073460..86eb69db56 100644 --- a/coding/coding_tests/uri_test.cpp +++ b/coding/coding_tests/uri_test.cpp @@ -24,7 +24,7 @@ public: ~TestUri() { - Uri uri(&m_uri[0], m_uri.size()); + Uri uri(m_uri); TEST_EQUAL(uri.GetScheme(), m_scheme, ()); TEST_EQUAL(uri.GetPath(), m_path, ()); TEST(!m_scheme.empty() || !uri.IsValid(), ("Scheme is empty if and only if uri is invalid!")); @@ -35,7 +35,7 @@ private: void AddTestValue(string const & key, string const & value) { - TEST(!m_keyValuePairs.empty(), ("Check that key/value pair is expected")); + TEST(!m_keyValuePairs.empty(), ("Failed for uri = ", m_uri, "Passed KV = ", key, value)); TEST_EQUAL(m_keyValuePairs.front().first, key, ()); TEST_EQUAL(m_keyValuePairs.front().second, value, ()); m_keyValuePairs.pop(); diff --git a/coding/uri.cpp b/coding/uri.cpp index 9244219045..e37b86413f 100644 --- a/coding/uri.cpp +++ b/coding/uri.cpp @@ -1,16 +1,18 @@ #include "uri.hpp" #include "url_encode.hpp" -#include "../base/logging.hpp" -#include "../std/algorithm.hpp" -using namespace url_scheme; +#include "../base/assert.hpp" + + +namespace url_scheme +{ void Uri::Init() { if (!Parse()) { - m_scheme.clear(); - m_path.clear(); + ASSERT(m_scheme.empty() && m_path.empty() && !IsValid(), ()); + m_queryStart = m_url.size(); } } @@ -23,17 +25,24 @@ bool Uri::Parse() m_scheme.assign(m_url, 0, pathStart); // skip slashes - while (++pathStart < m_url.size() && m_url[pathStart] == '/') {}; + while (++pathStart < m_url.size() && m_url[pathStart] == '/') {} - // get path + // Find query starting point for (key, value) parsing. m_queryStart = m_url.find('?', pathStart); - m_path.assign(m_url, pathStart, m_queryStart - pathStart); - - // url without query + size_t pathLength; if (m_queryStart == string::npos) + { m_queryStart = m_url.size(); + pathLength = m_queryStart - pathStart; + } else + { + pathLength = m_queryStart - pathStart; ++m_queryStart; + } + + // Get path (url without query). + m_path.assign(m_url, pathStart, pathLength); return true; } @@ -41,29 +50,32 @@ bool Uri::Parse() void Uri::ForEachKeyValue(CallbackT const & callback) const { // parse query for keys and values - for (size_t start = m_queryStart; start < m_url.size(); ) + size_t const count = m_url.size(); + for (size_t start = m_queryStart; start < count; ) { - // TODO: Unoptimal search here, since it goes until the end of the string. - size_t const end = min(m_url.size(), m_url.find('&', start)); + size_t end = m_url.find('&', start); + if (end == string::npos) + end = count; // Skip empty keys. - if (end - start > 0) + if (end != start) { size_t const eq = m_url.find('=', start); string key, value; - if (eq < end) + if (eq != string::npos && eq < end) { key = UrlDecode(m_url.substr(start, eq - start)); value = UrlDecode(m_url.substr(eq + 1, end - eq - 1)); } else - { key = UrlDecode(m_url.substr(start, end - start)); - } + callback(key, value); } start = end + 1; } } + +} diff --git a/coding/uri.hpp b/coding/uri.hpp index bc98660e95..25ff1b6bab 100644 --- a/coding/uri.hpp +++ b/coding/uri.hpp @@ -1,9 +1,11 @@ #pragma once #include "../base/base.hpp" + #include "../std/function.hpp" #include "../std/string.hpp" + namespace url_scheme {