1 #pragma once 2 3 #include <phosphor-logging/lg2/concepts.hpp> 4 5 #include <algorithm> 6 #include <array> 7 #include <string_view> 8 9 namespace lg2::details 10 { 11 12 /** A type to handle compile-time validation of header strings. */ 13 struct header_str 14 { 15 // Hold the header string value. 16 std::string_view value; 17 18 /** Constructor which performs validation. */ 19 template <typename T> header_strlg2::details::header_str20 consteval header_str(const T& s) : value(s) 21 { 22 if (value.size() == 0) 23 { 24 report_error( 25 "journald requires headers must have non-zero length."); 26 } 27 if (value[0] == '_') 28 { 29 report_error("journald requires header do not start with " 30 "underscore (_)"); 31 } 32 33 if (value.find_first_not_of("ABCDEFGHIJKLMNOPQRSTUVWXYZ_0123456789") != 34 std::string_view::npos) 35 { 36 report_error( 37 "journald requires header may only contain underscore, " 38 "uppercase letters, or numbers ([_A-Z0-9])."); 39 } 40 41 constexpr std::array reserved{ 42 "CODE_FILE", "CODE_FUNC", "CODE_LINE", 43 "LOG2_FMTMSG", "MESSAGE", "PRIORITY", 44 }; 45 if (std::ranges::find(reserved, value) != std::end(reserved)) 46 { 47 report_error("Header name is reserved."); 48 } 49 } 50 51 /** Cast conversion back to (const char*). */ operator const char*lg2::details::header_str52 operator const char*() const 53 { 54 return value.data(); 55 } 56 datalg2::details::header_str57 const char* data() const 58 { 59 return value.data(); 60 } 61 62 private: 63 // This does nothing, but is useful for creating nice compile errors in 64 // a constexpr context. 65 static void report_error(const char*); 66 }; 67 68 /** A helper type for constexpr conversion into header_str, if 69 * 'maybe_constexpr_string'. For non-constexpr string, this does nothing. 70 */ 71 template <typename T> 72 struct header_str_conversion 73 { 74 using type = T; 75 }; 76 77 /** Specialization for maybe_constexpr_string. */ 78 template <maybe_constexpr_string T> 79 struct header_str_conversion<T> 80 { 81 using type = const header_str&; 82 }; 83 84 /** std-style _t alias for header_str_conversion. */ 85 template <typename T> 86 using header_str_conversion_t = typename header_str_conversion<T>::type; 87 88 } // namespace lg2::details 89