C++ Essence Library 0.1.0
A Utility Library for Modern C++ Programming
Loading...
Searching...
No Matches
parse_qualified_function_name.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#if defined(_MSC_VER) && defined(_WIN32)
26#include "../../char8_t_remediation.hpp"
27#endif
28
29#include "../literal_string.hpp"
30#include "find_at_depth.hpp"
31#include "language_tokens.hpp"
32#include "parse_raw_identifier_name.hpp"
33
34#include <algorithm>
35#include <array>
36#include <cstddef>
37#include <string_view>
38
39namespace essence::meta::detail {
40#if defined(_MSC_VER) && defined(_WIN64)
41 inline constexpr std::array calling_conventions{U8("__cdecl"), U8("__vectorcall")};
42#elif defined(_MSC_VER) && defined(_WIN32)
43 inline constexpr std::array calling_conventions{
44 U8("__cdecl"), U8("__stdcall"), U8("__fastcall"), U8("__vectorcall"), U8("__thiscall")};
45#elif defined(__clang__) || defined(__GNUC__)
46 inline constexpr std::array<const char*, 0> calling_conventions{};
47#else
48#error "Unsupported compiler."
49#endif
50
56 consteval std::string_view parse_qualified_function_name(std::string_view signature) noexcept {
57 // When using MSVC, finds the start index of the function name past the
58 // top-level calling convention token (e.g. __cdecl/__vectorcall for x64,
59 // __stdcall/__cdecl/__fastcall/__vectorcall/__thiscall for x86).
60 // When using GCC or Clang, returns zero immediately.
61 const auto start_index = [&]() -> std::size_t {
62 // Workaround for failing compilation on x86-64 Clang assertions trunk.
63 // std::array<T, 0>::begin() and std::array<T, 0>::end() are not
64 // odr-usable.
65 if constexpr (!calling_conventions.empty()) {
66 for (auto&& item : calling_conventions) {
67 if (const auto index = find_at_depth<find_mode_type::full_match>(signature, item);
68 index != std::string_view::npos) {
69 return index + 1;
70 }
71 }
72 }
73
74 return 0;
75 }();
76
77 // Finds the end index of the function name before the top-level left
78 // "<" or "(" indicating the start of the template or function arguments.
79 const auto function_name_start_index =
80 std::max(start_index, find_at_depth<find_mode_type::full_match_reverse>(signature, language_tokens::scope));
81
82 const auto end_index = find_at_depth<find_mode_type::any_of>(signature,
83 literal_string{language_tokens::left_parentheses, language_tokens::left_angle_bracket}, 1,
84 function_name_start_index != std::string_view::npos ? function_name_start_index : start_index);
85
86 const auto final_size =
87 end_index != std::string_view::npos ? (end_index - 1 - start_index) : (signature.size() - start_index);
88
89 return signature.substr(start_index, final_size);
90 }
91} // namespace essence::meta::detail