GCC Code Coverage Report


Directory: src/
File: header/text_conversion_constexpr.h
Date: 2024-12-30 15:39:09
Exec Total Coverage
Lines: 41 42 97.6%
Functions: 18 18 100.0%
Branches: 55 66 83.3%

Line Branch Exec Source
1 #pragma once
2
3 #ifdef __cpp_lib_ranges
4 #ifdef __cpp_lib_concepts
5 #include <concepts>
6 #include <ranges>
7 #define USE_RANGES
8 #endif
9 #endif
10
11 #include <array>
12 #include <string>
13
14 namespace text_conversion_constexpr
15 {
16 2 inline const char* version()
17 {
18 2 return "0.1.3";
19 }
20
21 namespace intern
22 {
23 549 constexpr auto is_alpha(auto c)
24 {
25
7/8
✓ Branch 0 taken 459 times.
✓ Branch 1 taken 90 times.
✓ Branch 2 taken 428 times.
✓ Branch 3 taken 31 times.
✓ Branch 4 taken 428 times.
✓ Branch 5 taken 90 times.
✓ Branch 6 taken 428 times.
✗ Branch 7 not taken.
549 return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z');
26 }
27
28 119 constexpr auto is_lower(auto c)
29 {
30
3/4
✓ Branch 0 taken 90 times.
✓ Branch 1 taken 29 times.
✓ Branch 2 taken 90 times.
✗ Branch 3 not taken.
119 return (c >= 'a' && c <= 'z');
31 }
32
33 constexpr static auto uppercase = 'a' - 'A';
34
35 } // namespace intern
36
37 /*
38 * Converts the given text to title case style.
39 *
40 * https://apastyle.apa.org/style-grammar-guidelines/capitalization/title-case
41 *
42 * @param[in,out] data The text to convert, modified in place.
43 * Must support character indexing and `size()`.
44 */
45 template <typename DATA>
46 #ifdef USE_RANGES
47 requires std::ranges::sized_range<DATA>
48 #endif
49 27 constexpr void convert_to_title_case(DATA& data)
50 {
51
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 23 times.
27 if (data.empty())
52 return;
53
54 549 auto is_letter = [&](const auto& letter)
55 {
56
7/8
✓ Branch 1 taken 84 times.
✓ Branch 2 taken 423 times.
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 82 times.
✓ Branch 6 taken 6 times.
✓ Branch 7 taken 36 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 6 times.
549 return intern::is_alpha(letter) || letter == '\'';
57 };
58
59 479 auto make_upper_case = [&](auto offset)
60 {
61 119 auto& letter = data[offset];
62 // check if lower case letter
63
6/8
✓ Branch 1 taken 59 times.
✓ Branch 2 taken 26 times.
✓ Branch 4 taken 24 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 4 times.
✓ Branch 8 taken 3 times.
✓ Branch 10 taken 3 times.
✗ Branch 11 not taken.
119 if (intern::is_lower(letter))
64 90 letter -= intern::uppercase;
65 };
66
67 109 auto check_if_short_word = [&](const auto& word, const auto& short_words)
68 {
69
4/4
✓ Branch 1 taken 63 times.
✓ Branch 2 taken 37 times.
✓ Branch 4 taken 5 times.
✓ Branch 5 taken 4 times.
109 if (word.size() >= 4)
70 68 return false;
71
72
4/4
✓ Branch 2 taken 564 times.
✓ Branch 3 taken 22 times.
✓ Branch 6 taken 48 times.
✓ Branch 7 taken 2 times.
636 for (const auto& short_word : short_words)
73
4/4
✓ Branch 1 taken 15 times.
✓ Branch 2 taken 549 times.
✓ Branch 4 taken 2 times.
✓ Branch 5 taken 46 times.
612 if (short_word == word)
74 17 return true;
75
76 24 return false;
77 };
78
79 27 const std::array<std::string_view, 22> short_words{
80 "a", "an", "the", "and", "as", "but", "for", "if",
81 "nor", "or", "so", "yet", "at", "by", "in", "of",
82 "off", "on", "per", "to", "up", "via"};
83
84 27 auto word_length = 0u;
85 27 auto start_index = 0u;
86
87 // first letter
88
1/2
✓ Branch 1 taken 18 times.
✗ Branch 2 not taken.
27 make_upper_case(0);
89
90 27 const auto size = data.size();
91 27 const auto last_letter_idx = size - 1u;
92
93 27 auto first_word = true;
94
95
2/2
✓ Branch 0 taken 503 times.
✓ Branch 1 taken 23 times.
576 for (auto i = 0u; i < size; ++i)
96 {
97
1/2
✓ Branch 1 taken 404 times.
✗ Branch 2 not taken.
549 const auto letter = is_letter(data[i]);
98
2/2
✓ Branch 0 taken 421 times.
✓ Branch 1 taken 82 times.
549 if (letter)
99 {
100
2/2
✓ Branch 0 taken 98 times.
✓ Branch 1 taken 323 times.
461 if (word_length == 0u)
101 108 start_index = i;
102
103 461 word_length++;
104 }
105
106
6/6
✓ Branch 0 taken 82 times.
✓ Branch 1 taken 421 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 81 times.
✓ Branch 4 taken 18 times.
✓ Branch 5 taken 404 times.
549 if ((!letter && word_length > 0u) || i == last_letter_idx)
107 {
108
1/2
✓ Branch 1 taken 77 times.
✗ Branch 2 not taken.
109 const std::string_view word(&data[start_index], word_length);
109
110 109 const auto to_upper = !check_if_short_word(word, short_words);
111
112
3/4
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 84 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 15 times.
109 if (to_upper || first_word)
113
1/2
✓ Branch 1 taken 67 times.
✗ Branch 2 not taken.
92 make_upper_case(start_index);
114
115 109 word_length = 0u;
116 109 first_word = false;
117 }
118 }
119 }
120
121 } // namespace text_conversion_constexpr
122