Skip to content

Commit

Permalink
Add Add url::get_part_pos function
Browse files Browse the repository at this point in the history
  • Loading branch information
rmisev committed Dec 31, 2024
1 parent 7360681 commit 337ae54
Show file tree
Hide file tree
Showing 3 changed files with 82 additions and 10 deletions.
35 changes: 27 additions & 8 deletions include/upa/url.h
Original file line number Diff line number Diff line change
Expand Up @@ -542,19 +542,38 @@ class url {
/// @return `true` if URL is valid, `false` otherwise
[[nodiscard]] bool is_valid() const noexcept;

/// @brief Gets the start and end position of the specified URL part
///
/// Returns the start and end position of the part (as defined in
/// https://url.spec.whatwg.org/#url-representation) in the string returned by the
/// `get_href()`, `href()` or `to_string()` functions.
///
/// * `get_part_pos(upa::url::SCHEME)` - get a URL's **scheme** position
/// * `get_part_pos(upa::url::USERNAME)` - get a URL's **username** position
/// * `get_part_pos(upa::url::PASSWORD)` - get a URL's **password** position
/// * `get_part_pos(upa::url::HOST)` - get a URL's **host** position
/// * `get_part_pos(upa::url::PORT)` - get a URL's **port** position
/// * `get_part_pos(upa::url::PATH)` - get a URL's **path** position
/// * `get_part_pos(upa::url::QUERY)` - get a URL's **query** position
/// * `get_part_pos(upa::url::FRAGMENT)` - get a URL's **fragment** position
///
/// @param[in] t URL's part
/// @return the start and end position of the specified URL part
[[nodiscard]] std::pair<std::size_t, std::size_t> get_part_pos(PartType t) const;

/// @brief Gets URL's part (URL record member) as string
///
/// Function to get ASCII string of any URL's part (URL record member) defined here:
/// https://url.spec.whatwg.org/#url-representation
///
/// * `get_part_view(upa::url::SCHEME)` - get a URLs **scheme** string
/// * `get_part_view(upa::url::USERNAME)` - get a URLs **username** string
/// * `get_part_view(upa::url::PASSWORD)` - get a URLs **password** string
/// * `get_part_view(upa::url::HOST)` - get a URLs **host** serialized to string
/// * `get_part_view(upa::url::PORT)` - get a URLs **port** serialized to string
/// * `get_part_view(upa::url::PATH)` - get a URLs **path** serialized to string
/// * `get_part_view(upa::url::QUERY)` - get a URLs **query** string
/// * `get_part_view(upa::url::FRAGMENT)` - get a URLs **fragment** string
/// * `get_part_view(upa::url::SCHEME)` - get a URL's **scheme** string
/// * `get_part_view(upa::url::USERNAME)` - get a URL's **username** string
/// * `get_part_view(upa::url::PASSWORD)` - get a URL's **password** string
/// * `get_part_view(upa::url::HOST)` - get a URL's **host** serialized to string
/// * `get_part_view(upa::url::PORT)` - get a URL's **port** serialized to string
/// * `get_part_view(upa::url::PATH)` - get a URL's **path** serialized to string
/// * `get_part_view(upa::url::QUERY)` - get a URL's **query** string
/// * `get_part_view(upa::url::FRAGMENT)` - get a URL's **fragment** string
///
/// @param[in] t URL's part
/// @return URL's part string; it is empty if part is empty or null
Expand Down
17 changes: 15 additions & 2 deletions src/url.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2016-2023 Rimas Misevičius
// Copyright 2016-2024 Rimas Misevičius
// Distributed under the BSD-style license that can be
// found in the LICENSE file.
//
Expand Down Expand Up @@ -27,8 +27,21 @@ const uint8_t kPartStart[url::PART_COUNT] = {

} // namespace detail

// Gets start and end position of the specified URL part

// URL's part flag masks
std::pair<std::size_t, std::size_t> url::get_part_pos(PartType t) const {
if (t == SCHEME)
return { 0, part_end_[SCHEME] };
const std::size_t e = part_end_[t];
if (e) {
std::size_t b = part_end_[t - 1];
if (b < e) b += detail::kPartStart[t];
return { b, e };
}
return { norm_url_.size(), norm_url_.size() };
}

// URL's part flag masks

const unsigned url::kPartFlagMask[url::PART_COUNT] = {
SCHEME_FLAG,
Expand Down
40 changes: 40 additions & 0 deletions test/test-url.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,20 @@
#include "test-utils.h"
#include <unordered_map>

// Conversion to doctest String
// https://github.com/doctest/doctest/blob/master/doc/markdown/stringification.md

namespace doctest {
template <class T1, class T2>
struct StringMaker<std::pair<T1, T2>> {
static String convert(const std::pair<T1, T2>& value) {
std::stringstream strs;
strs << "(" << value.first << ", " << value.second << ")";
const auto str = strs.str();
return { str.data(), static_cast<String::size_type>(str.length()) };
}
};
}

template<class T>
void discard(T&&) {}
Expand Down Expand Up @@ -462,6 +476,32 @@ TEST_CASE("url::has_opaque_path") {

// URL parts

TEST_CASE("url::get_part_pos") {
upa::url url{ "s://u:p@h:1/?q#f" };

CHECK(url.get_part_pos(upa::url::SCHEME) == std::make_pair(std::size_t(0), std::size_t(1)));
CHECK(url.get_part_pos(upa::url::USERNAME) == std::make_pair(std::size_t(4), std::size_t(5)));
CHECK(url.get_part_pos(upa::url::PASSWORD) == std::make_pair(std::size_t(6), std::size_t(7)));
CHECK(url.get_part_pos(upa::url::HOST) == std::make_pair(std::size_t(8), std::size_t(9)));
CHECK(url.get_part_pos(upa::url::PORT) == std::make_pair(std::size_t(10), std::size_t(11)));
CHECK(url.get_part_pos(upa::url::PATH) == std::make_pair(std::size_t(11), std::size_t(12)));
CHECK(url.get_part_pos(upa::url::QUERY) == std::make_pair(std::size_t(13), std::size_t(14)));
CHECK(url.get_part_pos(upa::url::FRAGMENT) == std::make_pair(std::size_t(15), std::size_t(16)));

url.hash("");
CHECK(url.get_part_pos(upa::url::FRAGMENT) == std::make_pair(std::size_t(14), std::size_t(14)));

url.search("");
CHECK(url.get_part_pos(upa::url::QUERY) == std::make_pair(std::size_t(12), std::size_t(12)));
CHECK(url.get_part_pos(upa::url::FRAGMENT) == std::make_pair(std::size_t(12), std::size_t(12)));

url.parse("s://u:p@h:1");
CHECK(url.href() == "s://u:p@h:1");
CHECK(url.get_part_pos(upa::url::PATH) == std::make_pair(std::size_t(11), std::size_t(11)));
CHECK(url.get_part_pos(upa::url::QUERY) == std::make_pair(std::size_t(11), std::size_t(11)));
CHECK(url.get_part_pos(upa::url::FRAGMENT) == std::make_pair(std::size_t(11), std::size_t(11)));
}

TEST_CASE("url::is_empty and url::is_null") {
upa::url url;

Expand Down

0 comments on commit 337ae54

Please sign in to comment.