C++ Essence Library 0.1.0
A Utility Library for Modern C++ Programming
Loading...
Searching...
No Matches
find_at_depth.hpp
1/*
2 * Copyright (c) 2024 The RefValue Project
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a copy
5 * of this software and associated documentation files (the "Software"), to deal
6 * in the Software without restriction, including without limitation the rights
7 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 * copies of the Software, and to permit persons to whom the Software is
9 * furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 * THE SOFTWARE.
21 */
22
23#pragma once
24
25#include "../../uniform_string_finder.hpp"
26#include "../literal_string.hpp"
27#include "language_tokens.hpp"
28
29#include <algorithm>
30#include <cstddef>
31#include <string_view>
32#include <utility>
33
34namespace essence::meta::detail {
35 template <find_mode_type = find_mode_type::reserved>
37 template <bool Reverse, bool AnyOf, typename Iter, typename End>
38 static constexpr std::size_t find_impl(
39 Iter first, End last, std::string_view keyword, std::size_t index, std::size_t depth = 0) noexcept {
40 char last_char{};
41 std::size_t current_depth{};
42
43 constexpr auto next_iter = [](auto& iter) {
44 if constexpr (Reverse) {
45 --iter;
46 } else {
47 ++iter;
48 }
49 };
50
51 // Matches the keyword at the current depth.
52 auto match_string = [&](auto& iter) {
53 if constexpr (AnyOf) {
54 return current_depth == depth && keyword.find_first_of(*iter) != std::string_view::npos;
55 } else {
56 return current_depth == depth
57 && std::equal(iter,
58 iter + std::min(std::distance(iter, last), static_cast<std::ptrdiff_t>(keyword.size())),
59 keyword.begin());
60 }
61 };
62
63 // Acquires the actual boundary iterators.
64 auto&& [real_first, real_last] = [&] {
65 if constexpr (Reverse) {
66 return std::pair{std::prev(last),
67 std::prev(std::next(
68 first, index == std::string_view::npos ? 0 : static_cast<std::ptrdiff_t>(index)))};
69 } else {
70 return std::pair{std::next(first, static_cast<std::ptrdiff_t>(index)), last};
71 }
72 }();
73
74 for (auto iter = real_first; iter != real_last; next_iter(iter)) {
75 if (language_tokens::left_enclosing_tokens.contains(*iter)) {
76 ++current_depth;
77 }
78
79 // Except the pointer operator ->.
80 if (current_depth != 0 && language_tokens::right_enclosing_tokens.contains(*iter)
81 && last_char != language_tokens::arrow.front()) {
82 --current_depth;
83 }
84
85 last_char = *iter;
86
87 // Matches the keyword at this depth.
88 if (match_string(iter)) {
89 // Calculates the distance to the user-input first iterator.
90 return std::distance(first, iter) + (AnyOf ? 1 : keyword.size());
91 }
92 }
93
94 return std::string_view::npos;
95 }
96 };
97
98 template <>
99 struct depth_level_finder_traits<find_mode_type::any_of> {
100 static constexpr std::size_t find(std::string_view str, std::string_view keyword, std::size_t depth = 0,
102 return depth_level_finder_traits<>::find_impl<false, true>(str.begin(), str.end(), keyword, index, depth);
103 }
104 };
105
106 template <>
107 struct depth_level_finder_traits<find_mode_type::full_match> {
108 static constexpr std::size_t find(std::string_view str, std::string_view keyword, std::size_t depth = 0,
110 return depth_level_finder_traits<>::find_impl<false, false>(str.begin(), str.end(), keyword, index, depth);
111 }
112 };
113
114 template <>
115 struct depth_level_finder_traits<find_mode_type::any_of_reverse> {
116 static constexpr std::size_t find(std::string_view str, std::string_view keyword, std::size_t depth = 0,
118 return depth_level_finder_traits<>::find_impl<true, true>(str.begin(), str.end(), keyword, index, depth);
119 }
120 };
121
122 template <>
123 struct depth_level_finder_traits<find_mode_type::full_match_reverse> {
124 static constexpr std::size_t find(std::string_view str, std::string_view keyword, std::size_t depth = 0,
126 return depth_level_finder_traits<>::find_impl<true, false>(str.begin(), str.end(), keyword, index, depth);
127 }
128 };
129
130 template <find_mode_type Mode>
131 constexpr std::size_t find_at_depth(std::string_view str, std::string_view keyword, std::size_t depth = 0,
132 std::size_t index = string_finder_traits<Mode>::default_index) noexcept {
133 return depth_level_finder_traits<Mode>::find(str, keyword, depth, index);
134 }
135} // namespace essence::meta::detail
Definition uniform_string_finder.hpp:38