1 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
2 // See https://llvm.org/LICENSE.txt for license information.
3 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
4 //
5 //===----------------------------------------------------------------------===//
6 
7 #ifndef _LIBCPP_HAS_NO_UNICODE
8 
9 #include <array>
10 #include <format>
11 
12 #include "benchmark/benchmark.h"
13 
14 #include "test_macros.h"
15 
16 template <class CharT, size_t N>
17 class tester {
18   static constexpr size_t size_ = N - 1;
19   std::array<CharT, 100 * size_> data_;
20 
21 public:
22   explicit constexpr tester(const CharT (&input)[N]) {
23     auto it = data_.begin();
24     for (int i = 0; i < 100; ++i)
25       it = std::copy_n(input, size_, it);
26   }
27 
28   constexpr size_t size() const noexcept { return data_.size(); }
29   constexpr const CharT* begin() const noexcept { return data_.begin(); }
30   constexpr const CharT* end() const noexcept { return data_.end(); }
31 
32   void test(benchmark::State& state) const {
33     for (auto _ : state)
34       benchmark::DoNotOptimize(std::__format_spec::__get_string_alignment(
35           begin(), end(), 1'000'000, 1'000'000));
36     state.SetItemsProcessed(state.iterations() * size());
37   }
38 };
39 
40 #define TEST(u8)                                                               \
41   if constexpr (std::same_as<CharT, char>) {                                   \
42     constexpr auto p = tester{u8};                                             \
43     p.test(state);                                                             \
44   } else if constexpr (std::same_as<CharT, char16_t>) {                        \
45     constexpr auto p = tester{TEST_CONCAT(u, u8)};                             \
46     p.test(state);                                                             \
47   } else {                                                                     \
48     constexpr auto p = tester{TEST_CONCAT(U, u8)};                             \
49     p.test(state);                                                             \
50   }
51 
52 template <class CharT>
53 static void BM_EstimateLengthNoMultiByte(benchmark::State& state) {
54   TEST("The quick brown fox jumps over the lazy dog");
55 }
56 
57 template <class CharT>
58 static void BM_EstimateLengthTwoByteDE(benchmark::State& state) {
59   static_assert(sizeof("Victor jagt zwölf Boxkämpfer quer über den großen Sylter Deich") == 67);
60 
61   // https://en.wikipedia.org/wiki/Pangram
62   TEST("Victor jagt zwölf Boxkämpfer quer über den großen Sylter Deich");
63 }
64 
65 template <class CharT>
66 static void BM_EstimateLengthTwoBytePL(benchmark::State& state) {
67   static_assert(sizeof("Stróż pchnął kość w quiz gędźb vel fax myjń") == 53);
68 
69   // https://en.wikipedia.org/wiki/Pangram
70   TEST("Stróż pchnął kość w quiz gędźb vel fax myjń");
71 }
72 
73 // All values below are 1100, which is is the first multi column sequence.
74 template <class CharT>
75 static void BM_EstimateLengthThreeByteSingleColumnLow(benchmark::State& state) {
76   static_assert(sizeof("\u0800\u0801\u0802\u0803\u0804\u0805\u0806\u0807"
77                        "\u0808\u0809\u080a\u080b\u080c\u080d\u080e\u080f") ==
78                 49);
79 
80   TEST("\u0800\u0801\u0802\u0803\u0804\u0805\u0806\u0807"
81        "\u0808\u0809\u080a\u080b\u080c\u080d\u080e\u080f");
82 }
83 
84 template <class CharT>
85 static void
86 BM_EstimateLengthThreeByteSingleColumnHigh(benchmark::State& state) {
87   static_assert(sizeof("\u1800\u1801\u1802\u1803\u1804\u1805\u1806\u1807"
88                        "\u1808\u1809\u180a\u180b\u180c\u180d\u180e\u180f") ==
89                 49);
90 
91   TEST("\u1800\u1801\u1802\u1803\u1804\u1805\u1806\u1807"
92        "\u1808\u1809\u180a\u180b\u180c\u180d\u180e\u180f");
93 }
94 
95 template <class CharT>
96 static void BM_EstimateLengthThreeByteDoubleColumn(benchmark::State& state) {
97   static_assert(sizeof("\u1100\u0801\u0802\u0803\u0804\u0805\u0806\u0807"
98                        "\u1108\u0809\u080a\u080b\u080c\u080d\u080e\u080f") ==
99                 49);
100 
101   TEST("\u1100\u0801\u0802\u0803\u0804\u0805\u0806\u0807"
102        "\u1108\u0809\u080a\u080b\u080c\u080d\u080e\u080f");
103 }
104 
105 template <class CharT>
106 static void BM_EstimateLengthThreeByte(benchmark::State& state) {
107   static_assert(sizeof("\u1400\u1501\ubbbb\uff00\u0800\u4099\uabcd\u4000"
108                        "\u8ead\ubeef\u1111\u4987\u4321\uffff\u357a\ud50e") ==
109                 49);
110 
111   TEST("\u1400\u1501\ubbbb\uff00\u0800\u4099\uabcd\u4000"
112        "\u8ead\ubeef\u1111\u4987\u4321\uffff\u357a\ud50e");
113 }
114 
115 template <class CharT>
116 static void BM_EstimateLengthFourByteSingleColumn(benchmark::State& state) {
117   static_assert(sizeof("\U00010000\U00010001\U00010002\U00010003"
118                        "\U00010004\U00010005\U00010006\U00010007"
119                        "\U00010008\U00010009\U0001000a\U0001000b"
120                        "\U0001000c\U0001000d\U0001000e\U0001000f") == 65);
121 
122   TEST("\U00010000\U00010001\U00010002\U00010003"
123        "\U00010004\U00010005\U00010006\U00010007"
124        "\U00010008\U00010009\U0001000a\U0001000b"
125        "\U0001000c\U0001000d\U0001000e\U0001000f");
126 }
127 
128 template <class CharT>
129 static void BM_EstimateLengthFourByteDoubleColumn(benchmark::State& state) {
130   static_assert(sizeof("\U00020000\U00020002\U00020002\U00020003"
131                        "\U00020004\U00020005\U00020006\U00020007"
132                        "\U00020008\U00020009\U0002000a\U0002000b"
133                        "\U0002000c\U0002000d\U0002000e\U0002000f") == 65);
134 
135   TEST("\U00020000\U00020002\U00020002\U00020003"
136        "\U00020004\U00020005\U00020006\U00020007"
137        "\U00020008\U00020009\U0002000a\U0002000b"
138        "\U0002000c\U0002000d\U0002000e\U0002000f");
139 }
140 
141 template <class CharT>
142 static void BM_EstimateLengthFourByte(benchmark::State& state) {
143   static_assert(sizeof("\U00010000\U00010001\U00010002\U00010003"
144                        "\U00020004\U00020005\U00020006\U00020007"
145                        "\U00010008\U00010009\U0001000a\U0001000b"
146                        "\U0002000c\U0002000d\U0002000e\U0002000f") == 65);
147 
148   TEST("\U00010000\U00010001\U00010002\U00010003"
149        "\U00020004\U00020005\U00020006\U00020007"
150        "\U00010008\U00010009\U0001000a\U0001000b"
151        "\U0002000c\U0002000d\U0002000e\U0002000f");
152 }
153 
154 BENCHMARK_TEMPLATE(BM_EstimateLengthNoMultiByte, char);
155 BENCHMARK_TEMPLATE(BM_EstimateLengthTwoByteDE, char);
156 BENCHMARK_TEMPLATE(BM_EstimateLengthTwoBytePL, char);
157 BENCHMARK_TEMPLATE(BM_EstimateLengthThreeByteSingleColumnLow, char);
158 BENCHMARK_TEMPLATE(BM_EstimateLengthThreeByteSingleColumnHigh, char);
159 BENCHMARK_TEMPLATE(BM_EstimateLengthThreeByteDoubleColumn, char);
160 BENCHMARK_TEMPLATE(BM_EstimateLengthThreeByte, char);
161 BENCHMARK_TEMPLATE(BM_EstimateLengthFourByteSingleColumn, char);
162 BENCHMARK_TEMPLATE(BM_EstimateLengthFourByteDoubleColumn, char);
163 BENCHMARK_TEMPLATE(BM_EstimateLengthFourByte, char);
164 
165 BENCHMARK_TEMPLATE(BM_EstimateLengthNoMultiByte, char16_t);
166 BENCHMARK_TEMPLATE(BM_EstimateLengthTwoByteDE, char16_t);
167 BENCHMARK_TEMPLATE(BM_EstimateLengthTwoBytePL, char16_t);
168 BENCHMARK_TEMPLATE(BM_EstimateLengthThreeByteSingleColumnLow, char16_t);
169 BENCHMARK_TEMPLATE(BM_EstimateLengthThreeByteSingleColumnHigh, char16_t);
170 BENCHMARK_TEMPLATE(BM_EstimateLengthThreeByteDoubleColumn, char16_t);
171 BENCHMARK_TEMPLATE(BM_EstimateLengthThreeByte, char16_t);
172 BENCHMARK_TEMPLATE(BM_EstimateLengthFourByteSingleColumn, char16_t);
173 BENCHMARK_TEMPLATE(BM_EstimateLengthFourByteDoubleColumn, char16_t);
174 BENCHMARK_TEMPLATE(BM_EstimateLengthFourByte, char16_t);
175 
176 BENCHMARK_TEMPLATE(BM_EstimateLengthNoMultiByte, char32_t);
177 BENCHMARK_TEMPLATE(BM_EstimateLengthTwoByteDE, char32_t);
178 BENCHMARK_TEMPLATE(BM_EstimateLengthTwoBytePL, char32_t);
179 BENCHMARK_TEMPLATE(BM_EstimateLengthThreeByteSingleColumnLow, char32_t);
180 BENCHMARK_TEMPLATE(BM_EstimateLengthThreeByteSingleColumnHigh, char32_t);
181 BENCHMARK_TEMPLATE(BM_EstimateLengthThreeByteDoubleColumn, char32_t);
182 BENCHMARK_TEMPLATE(BM_EstimateLengthThreeByte, char32_t);
183 BENCHMARK_TEMPLATE(BM_EstimateLengthFourByteSingleColumn, char32_t);
184 BENCHMARK_TEMPLATE(BM_EstimateLengthFourByteDoubleColumn, char32_t);
185 BENCHMARK_TEMPLATE(BM_EstimateLengthFourByte, char32_t);
186 
187 int main(int argc, char** argv) {
188   benchmark::Initialize(&argc, argv);
189   if (benchmark::ReportUnrecognizedArguments(argc, argv))
190     return 1;
191 
192   benchmark::RunSpecifiedBenchmarks();
193 }
194 #else
195 int main(int, char**) { return 0; }
196 #endif
197