userver: userver/utils/impl/source_location.hpp Source File
Loading...
Searching...
No Matches
source_location.hpp
1#pragma once
2
3#include <cstdint>
4#include <string_view>
5#include <type_traits>
6
7#include <userver/logging/log_filepath.hpp>
8
9USERVER_NAMESPACE_BEGIN
10
11namespace utils::impl {
12
13class SourceLocation final {
14 struct EmplaceEnabler final {
15 constexpr explicit EmplaceEnabler() noexcept = default;
16 };
17
18 public:
19 static constexpr SourceLocation Current(
20 EmplaceEnabler /*unused*/ = EmplaceEnabler{},
21 std::string_view file_name = USERVER_FILEPATH,
22 std::string_view function_name = __builtin_FUNCTION(),
23 std::uint_least32_t line = __builtin_LINE()) noexcept {
24 return SourceLocation{line, file_name, function_name};
25 }
26
27 // Mainly intended for interfacing with external libraries.
28 static constexpr SourceLocation Custom(
29 std::uint_least32_t line, std::string_view file_name,
30 std::string_view function_name) noexcept {
31 return SourceLocation{line, file_name, function_name};
32 }
33
34 constexpr std::uint_least32_t GetLine() const noexcept { return line_; }
35
36 constexpr std::string_view GetLineString() const noexcept {
37 return std::string_view(&line_string_[kMaxLineDigits - line_digits_],
38 line_digits_);
39 }
40
41 constexpr std::string_view GetFileName() const noexcept { return file_name_; }
42
43 constexpr std::string_view GetFunctionName() const noexcept {
44 return function_name_;
45 }
46
47 private:
48 static_assert(sizeof(std::uint_least32_t) == sizeof(std::uint32_t));
49
50 static constexpr std::size_t kMaxLineDigits = 8;
51
52 constexpr SourceLocation(std::uint_least32_t line, std::string_view file_name,
53 std::string_view function_name) noexcept
54 : line_(line),
55 line_digits_(DigitsBase10(line)),
56 file_name_(file_name),
57 function_name_(function_name) {
58 FillLineString();
59 }
60
61 static constexpr std::size_t DigitsBase10(std::uint32_t line) noexcept {
62 static_assert(sizeof(line) == 4);
63 return 1 //
64 + (line >= 10) //
65 + (line >= 100) //
66 + (line >= 1000) //
67 + (line >= 10000) //
68 + (line >= 100000) //
69 + (line >= 1000000) //
70 + (line >= 10000000) //
71 + (line >= 100000000) //
72 + (line >= 1000000000); //
73 }
74
75 constexpr void FillLineString() noexcept {
76 constexpr std::size_t kMaxSupportedLine = 99999999;
77 if (line_ > kMaxSupportedLine) {
78 // Line string greater than 8 digits won't fit. Use fake line numbers
79 // for 100M+ lines source files.
80 line_ = kMaxSupportedLine;
81 line_digits_ = kMaxLineDigits;
82 }
83 auto line = line_;
84 line_string_[kMaxLineDigits - 1] = '0';
85 for (std::size_t index = kMaxLineDigits - 1; line > 0;
86 line /= 10, --index) {
87 line_string_[index] = '0' + (line % 10);
88 }
89 }
90
91 std::uint32_t line_;
92 std::uint32_t line_digits_;
93 char line_string_[kMaxLineDigits]{};
94 std::string_view file_name_;
95 std::string_view function_name_;
96};
97
98} // namespace utils::impl
99
100USERVER_NAMESPACE_END