FE 0.13.1
Header-only C++ frontend library
Loading...
Searching...
No Matches
algo.h
Go to the documentation of this file.
1#pragma once
2
3#include <cassert>
4#include <cstddef>
5#include <cstdint>
6
7#include <algorithm>
8#include <array>
9#include <bit>
10#include <functional>
11#include <iterator>
12#include <ranges>
13#include <string>
14#include <string_view>
15#include <type_traits>
16
17namespace fe {
18
19/// @name Utility Functions
20///@{
21
22/// A bitcast from @p src of type @p S to @p D, supporting different sizes.
23/// Keeps the *low-order* bytes on either endianness:
24/// a wider @p D zero-fills the rest, a narrower one truncates.
25template<class D, class S>
26constexpr D bitcast_resize(const S& src) noexcept
27 requires(std::is_trivially_copyable_v<S> && std::is_trivially_copyable_v<D>) {
28 if constexpr (sizeof(D) == sizeof(S)) {
29 return std::bit_cast<D>(src);
30 } else {
31 constexpr auto n = std::min(sizeof(D), sizeof(S));
32 constexpr auto be = std::endian::native == std::endian::big;
33 auto s = std::bit_cast<std::array<std::byte, sizeof(S)>>(src);
34 auto d = std::array<std::byte, sizeof(D)>{};
35 for (size_t i = 0; i != n; ++i)
36 d[be ? sizeof(D) - n + i : i] = s[be ? sizeof(S) - n + i : i];
37 return std::bit_cast<D>(d);
38 }
39}
40
41/// Rounds @p offset up to the next multiple of @p align.
42[[nodiscard]] constexpr std::uint64_t pad(std::uint64_t offset, std::uint64_t align) noexcept {
43 assert(align != 0);
44
45 auto mod = offset % align;
46 if (mod) offset += align - mod;
47 return offset;
48}
49
50[[nodiscard]] constexpr bool is_aligned(std::uint64_t offset, std::uint64_t align) noexcept {
51 assert(align != 0);
52 return offset % align == 0;
53}
54///@}
55
56/// @name Algorithms
57///@{
58template<std::random_access_iterator I, class T, class L = std::less<>>
59[[nodiscard]] constexpr I binary_find(I begin, I end, const T& val, L lt = {}) noexcept {
60 I i;
61 if (std::distance(begin, end) < 16)
62 for (i = begin; i != end && lt(*i, val); ++i) {}
63 else
64 i = std::lower_bound(begin, end, val, lt);
65 return (i != end && !lt(val, *i)) ? i : end;
66}
67
68template<std::ranges::random_access_range R, class T, class L = std::less<>>
69[[nodiscard]] constexpr auto binary_find(R&& r, const T& val, L lt = {}) noexcept requires std::ranges::common_range<R>
70{
71 return binary_find(std::ranges::begin(r), std::ranges::end(r), val, lt);
72}
73
74/// Like `std::string::substr`, but works on `std::string_view` and clamps @p i instead of throwing.
75[[nodiscard]] constexpr std::string_view
76subview(std::string_view s, size_t i, size_t n = std::string_view::npos) noexcept {
77 return s.substr(std::min(i, s.size()), n);
78}
79
80/// Replaces all occurrences of @p what with @p repl.
81inline void find_and_replace(std::string& str, std::string_view what, std::string_view repl) {
82 assert(!what.empty() && "would never terminate");
83
84 for (size_t pos = str.find(what); pos != std::string::npos; pos = str.find(what, pos + repl.size()))
85 str.replace(pos, what.size(), repl);
86}
87///@}
88
89} // namespace fe
Definition algo.h:17
void find_and_replace(std::string &str, std::string_view what, std::string_view repl)
Replaces all occurrences of what with repl.
Definition algo.h:81
constexpr D bitcast_resize(const S &src) noexcept
A bitcast from src of type S to D, supporting different sizes.
Definition algo.h:26
constexpr I binary_find(I begin, I end, const T &val, L lt={}) noexcept
Definition algo.h:59
constexpr bool is_aligned(std::uint64_t offset, std::uint64_t align) noexcept
Definition algo.h:50
constexpr std::string_view subview(std::string_view s, size_t i, size_t n=std::string_view::npos) noexcept
Like std::string::substr, but works on std::string_view and clamps i instead of throwing.
Definition algo.h:76
constexpr std::uint64_t pad(std::uint64_t offset, std::uint64_t align) noexcept
Rounds offset up to the next multiple of align.
Definition algo.h:42