wuxing0105 commited on
Commit
5300be7
·
verified ·
1 Parent(s): 00e39c3

Add files using upload-large-folder tool

Browse files
This view is limited to 50 files because it contains too many changes.   See raw diff
Files changed (50) hide show
  1. weight/_dep/abseil-cpp/absl/cleanup/BUILD.bazel +73 -0
  2. weight/_dep/abseil-cpp/absl/cleanup/cleanup.h +140 -0
  3. weight/_dep/abseil-cpp/absl/cleanup/cleanup_test.cc +311 -0
  4. weight/_dep/abseil-cpp/absl/cleanup/internal/cleanup.h +100 -0
  5. weight/_dep/abseil-cpp/absl/copts/GENERATED_copts.bzl +230 -0
  6. weight/_dep/abseil-cpp/absl/copts/configure_copts.bzl +82 -0
  7. weight/_dep/abseil-cpp/absl/copts/copts.py +191 -0
  8. weight/_dep/abseil-cpp/absl/copts/generate_copts.py +109 -0
  9. weight/_dep/abseil-cpp/absl/flags/BUILD.bazel +601 -0
  10. weight/_dep/abseil-cpp/absl/flags/CMakeLists.txt +471 -0
  11. weight/_dep/abseil-cpp/absl/flags/commandlineflag.cc +34 -0
  12. weight/_dep/abseil-cpp/absl/flags/commandlineflag.h +200 -0
  13. weight/_dep/abseil-cpp/absl/flags/commandlineflag_test.cc +231 -0
  14. weight/_dep/abseil-cpp/absl/flags/config.h +68 -0
  15. weight/_dep/abseil-cpp/absl/flags/config_test.cc +61 -0
  16. weight/_dep/abseil-cpp/absl/flags/declare.h +68 -0
  17. weight/_dep/abseil-cpp/absl/flags/flag.h +301 -0
  18. weight/_dep/abseil-cpp/absl/flags/flag_benchmark.cc +251 -0
  19. weight/_dep/abseil-cpp/absl/flags/flag_benchmark.lds +13 -0
  20. weight/_dep/abseil-cpp/absl/flags/flag_test.cc +1217 -0
  21. weight/_dep/abseil-cpp/absl/flags/flag_test_defs.cc +24 -0
  22. weight/_dep/abseil-cpp/absl/flags/internal/commandlineflag.h +68 -0
  23. weight/_dep/abseil-cpp/absl/flags/internal/flag.h +796 -0
  24. weight/_dep/abseil-cpp/absl/flags/marshalling.cc +291 -0
  25. weight/_dep/abseil-cpp/absl/flags/parse.cc +943 -0
  26. weight/_dep/abseil-cpp/absl/flags/parse.h +130 -0
  27. weight/_dep/abseil-cpp/absl/flags/parse_test.cc +1087 -0
  28. weight/_dep/abseil-cpp/absl/flags/reflection.h +90 -0
  29. weight/_dep/abseil-cpp/absl/flags/reflection_test.cc +265 -0
  30. weight/_dep/abseil-cpp/absl/flags/usage.cc +66 -0
  31. weight/_dep/abseil-cpp/absl/flags/usage_config.cc +165 -0
  32. weight/_dep/abseil-cpp/absl/flags/usage_config.h +135 -0
  33. weight/_dep/abseil-cpp/absl/flags/usage_config_test.cc +205 -0
  34. weight/_dep/abseil-cpp/absl/strings/cord_test.cc +0 -0
  35. weight/_dep/abseil-cpp/absl/strings/escaping.cc +957 -0
  36. weight/_dep/abseil-cpp/absl/strings/escaping_test.cc +714 -0
  37. weight/_dep/abseil-cpp/absl/strings/has_ostream_operator_test.cc +41 -0
  38. weight/_dep/abseil-cpp/absl/strings/internal/charconv_bigint.h +423 -0
  39. weight/_dep/abseil-cpp/absl/strings/internal/charconv_bigint_test.cc +260 -0
  40. weight/_dep/abseil-cpp/absl/strings/internal/charconv_parse_test.cc +357 -0
  41. weight/_dep/abseil-cpp/absl/strings/internal/cord_data_edge_test.cc +130 -0
  42. weight/_dep/abseil-cpp/absl/strings/internal/cord_rep_btree.cc +1241 -0
  43. weight/_dep/abseil-cpp/absl/strings/internal/cord_rep_btree_navigator.cc +187 -0
  44. weight/_dep/abseil-cpp/absl/strings/internal/cord_rep_btree_navigator.h +267 -0
  45. weight/_dep/abseil-cpp/absl/strings/internal/cord_rep_btree_reader.cc +69 -0
  46. weight/_dep/abseil-cpp/absl/strings/internal/cord_rep_btree_reader.h +212 -0
  47. weight/_dep/abseil-cpp/absl/strings/internal/cord_rep_btree_reader_test.cc +293 -0
  48. weight/_dep/abseil-cpp/absl/strings/internal/cord_rep_btree_test.cc +1568 -0
  49. weight/_dep/abseil-cpp/absl/strings/internal/cord_rep_consume.h +47 -0
  50. weight/_dep/abseil-cpp/absl/strings/internal/cord_rep_crc.cc +56 -0
weight/_dep/abseil-cpp/absl/cleanup/BUILD.bazel ADDED
@@ -0,0 +1,73 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright 2021 The Abseil Authors.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # https://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ load(
16
+ "//absl:copts/configure_copts.bzl",
17
+ "ABSL_DEFAULT_COPTS",
18
+ "ABSL_DEFAULT_LINKOPTS",
19
+ "ABSL_TEST_COPTS",
20
+ )
21
+
22
+ package(
23
+ default_visibility = ["//visibility:public"],
24
+ features = [
25
+ "header_modules",
26
+ "layering_check",
27
+ "parse_headers",
28
+ ],
29
+ )
30
+
31
+ licenses(["notice"])
32
+
33
+ cc_library(
34
+ name = "cleanup_internal",
35
+ hdrs = ["internal/cleanup.h"],
36
+ copts = ABSL_DEFAULT_COPTS,
37
+ linkopts = ABSL_DEFAULT_LINKOPTS,
38
+ deps = [
39
+ "//absl/base:base_internal",
40
+ "//absl/base:core_headers",
41
+ "//absl/utility",
42
+ ],
43
+ )
44
+
45
+ cc_library(
46
+ name = "cleanup",
47
+ hdrs = [
48
+ "cleanup.h",
49
+ ],
50
+ copts = ABSL_DEFAULT_COPTS,
51
+ linkopts = ABSL_DEFAULT_LINKOPTS,
52
+ deps = [
53
+ ":cleanup_internal",
54
+ "//absl/base:config",
55
+ "//absl/base:core_headers",
56
+ ],
57
+ )
58
+
59
+ cc_test(
60
+ name = "cleanup_test",
61
+ size = "small",
62
+ srcs = [
63
+ "cleanup_test.cc",
64
+ ],
65
+ copts = ABSL_TEST_COPTS,
66
+ deps = [
67
+ ":cleanup",
68
+ "//absl/base:config",
69
+ "//absl/utility",
70
+ "@com_google_googletest//:gtest",
71
+ "@com_google_googletest//:gtest_main",
72
+ ],
73
+ )
weight/_dep/abseil-cpp/absl/cleanup/cleanup.h ADDED
@@ -0,0 +1,140 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Copyright 2021 The Abseil Authors.
2
+ //
3
+ // Licensed under the Apache License, Version 2.0 (the "License");
4
+ // you may not use this file except in compliance with the License.
5
+ // You may obtain a copy of the License at
6
+ //
7
+ // https://www.apache.org/licenses/LICENSE-2.0
8
+ //
9
+ // Unless required by applicable law or agreed to in writing, software
10
+ // distributed under the License is distributed on an "AS IS" BASIS,
11
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ // See the License for the specific language governing permissions and
13
+ // limitations under the License.
14
+ //
15
+ // -----------------------------------------------------------------------------
16
+ // File: cleanup.h
17
+ // -----------------------------------------------------------------------------
18
+ //
19
+ // `absl::Cleanup` implements the scope guard idiom, invoking the contained
20
+ // callback's `operator()() &&` on scope exit.
21
+ //
22
+ // Example:
23
+ //
24
+ // ```
25
+ // absl::Status CopyGoodData(const char* source_path, const char* sink_path) {
26
+ // FILE* source_file = fopen(source_path, "r");
27
+ // if (source_file == nullptr) {
28
+ // return absl::NotFoundError("No source file"); // No cleanups execute
29
+ // }
30
+ //
31
+ // // C++17 style cleanup using class template argument deduction
32
+ // absl::Cleanup source_closer = [source_file] { fclose(source_file); };
33
+ //
34
+ // FILE* sink_file = fopen(sink_path, "w");
35
+ // if (sink_file == nullptr) {
36
+ // return absl::NotFoundError("No sink file"); // First cleanup executes
37
+ // }
38
+ //
39
+ // // C++11 style cleanup using the factory function
40
+ // auto sink_closer = absl::MakeCleanup([sink_file] { fclose(sink_file); });
41
+ //
42
+ // Data data;
43
+ // while (ReadData(source_file, &data)) {
44
+ // if (!data.IsGood()) {
45
+ // absl::Status result = absl::FailedPreconditionError("Read bad data");
46
+ // return result; // Both cleanups execute
47
+ // }
48
+ // SaveData(sink_file, &data);
49
+ // }
50
+ //
51
+ // return absl::OkStatus(); // Both cleanups execute
52
+ // }
53
+ // ```
54
+ //
55
+ // Methods:
56
+ //
57
+ // `std::move(cleanup).Cancel()` will prevent the callback from executing.
58
+ //
59
+ // `std::move(cleanup).Invoke()` will execute the callback early, before
60
+ // destruction, and prevent the callback from executing in the destructor.
61
+ //
62
+ // Usage:
63
+ //
64
+ // `absl::Cleanup` is not an interface type. It is only intended to be used
65
+ // within the body of a function. It is not a value type and instead models a
66
+ // control flow construct. Check out `defer` in Golang for something similar.
67
+
68
+ #ifndef ABSL_CLEANUP_CLEANUP_H_
69
+ #define ABSL_CLEANUP_CLEANUP_H_
70
+
71
+ #include <utility>
72
+
73
+ #include "absl/base/config.h"
74
+ #include "absl/base/macros.h"
75
+ #include "absl/cleanup/internal/cleanup.h"
76
+
77
+ namespace absl {
78
+ ABSL_NAMESPACE_BEGIN
79
+
80
+ template <typename Arg, typename Callback = void()>
81
+ class ABSL_MUST_USE_RESULT Cleanup final {
82
+ static_assert(cleanup_internal::WasDeduced<Arg>(),
83
+ "Explicit template parameters are not supported.");
84
+
85
+ static_assert(cleanup_internal::ReturnsVoid<Callback>(),
86
+ "Callbacks that return values are not supported.");
87
+
88
+ public:
89
+ Cleanup(Callback callback) : storage_(std::move(callback)) {} // NOLINT
90
+
91
+ Cleanup(Cleanup&& other) = default;
92
+
93
+ void Cancel() && {
94
+ ABSL_HARDENING_ASSERT(storage_.IsCallbackEngaged());
95
+ storage_.DestroyCallback();
96
+ }
97
+
98
+ void Invoke() && {
99
+ ABSL_HARDENING_ASSERT(storage_.IsCallbackEngaged());
100
+ storage_.InvokeCallback();
101
+ storage_.DestroyCallback();
102
+ }
103
+
104
+ ~Cleanup() {
105
+ if (storage_.IsCallbackEngaged()) {
106
+ storage_.InvokeCallback();
107
+ storage_.DestroyCallback();
108
+ }
109
+ }
110
+
111
+ private:
112
+ cleanup_internal::Storage<Callback> storage_;
113
+ };
114
+
115
+ // `absl::Cleanup c = /* callback */;`
116
+ //
117
+ // C++17 type deduction API for creating an instance of `absl::Cleanup`
118
+ #if defined(ABSL_HAVE_CLASS_TEMPLATE_ARGUMENT_DEDUCTION)
119
+ template <typename Callback>
120
+ Cleanup(Callback callback) -> Cleanup<cleanup_internal::Tag, Callback>;
121
+ #endif // defined(ABSL_HAVE_CLASS_TEMPLATE_ARGUMENT_DEDUCTION)
122
+
123
+ // `auto c = absl::MakeCleanup(/* callback */);`
124
+ //
125
+ // C++11 type deduction API for creating an instance of `absl::Cleanup`
126
+ template <typename... Args, typename Callback>
127
+ absl::Cleanup<cleanup_internal::Tag, Callback> MakeCleanup(Callback callback) {
128
+ static_assert(cleanup_internal::WasDeduced<cleanup_internal::Tag, Args...>(),
129
+ "Explicit template parameters are not supported.");
130
+
131
+ static_assert(cleanup_internal::ReturnsVoid<Callback>(),
132
+ "Callbacks that return values are not supported.");
133
+
134
+ return {std::move(callback)};
135
+ }
136
+
137
+ ABSL_NAMESPACE_END
138
+ } // namespace absl
139
+
140
+ #endif // ABSL_CLEANUP_CLEANUP_H_
weight/_dep/abseil-cpp/absl/cleanup/cleanup_test.cc ADDED
@@ -0,0 +1,311 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Copyright 2021 The Abseil Authors.
2
+ //
3
+ // Licensed under the Apache License, Version 2.0 (the "License");
4
+ // you may not use this file except in compliance with the License.
5
+ // You may obtain a copy of the License at
6
+ //
7
+ // https://www.apache.org/licenses/LICENSE-2.0
8
+ //
9
+ // Unless required by applicable law or agreed to in writing, software
10
+ // distributed under the License is distributed on an "AS IS" BASIS,
11
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ // See the License for the specific language governing permissions and
13
+ // limitations under the License.
14
+
15
+ #include "absl/cleanup/cleanup.h"
16
+
17
+ #include <functional>
18
+ #include <type_traits>
19
+ #include <utility>
20
+
21
+ #include "gtest/gtest.h"
22
+ #include "absl/base/config.h"
23
+ #include "absl/utility/utility.h"
24
+
25
+ namespace {
26
+
27
+ using Tag = absl::cleanup_internal::Tag;
28
+
29
+ template <typename Type1, typename Type2>
30
+ constexpr bool IsSame() {
31
+ return (std::is_same<Type1, Type2>::value);
32
+ }
33
+
34
+ struct IdentityFactory {
35
+ template <typename Callback>
36
+ static Callback AsCallback(Callback callback) {
37
+ return Callback(std::move(callback));
38
+ }
39
+ };
40
+
41
+ // `FunctorClass` is a type used for testing `absl::Cleanup`. It is intended to
42
+ // represent users that make their own move-only callback types outside of
43
+ // `std::function` and lambda literals.
44
+ class FunctorClass {
45
+ using Callback = std::function<void()>;
46
+
47
+ public:
48
+ explicit FunctorClass(Callback callback) : callback_(std::move(callback)) {}
49
+
50
+ FunctorClass(FunctorClass&& other)
51
+ : callback_(absl::exchange(other.callback_, Callback())) {}
52
+
53
+ FunctorClass(const FunctorClass&) = delete;
54
+
55
+ FunctorClass& operator=(const FunctorClass&) = delete;
56
+
57
+ FunctorClass& operator=(FunctorClass&&) = delete;
58
+
59
+ void operator()() const& = delete;
60
+
61
+ void operator()() && {
62
+ ASSERT_TRUE(callback_);
63
+ callback_();
64
+ callback_ = nullptr;
65
+ }
66
+
67
+ private:
68
+ Callback callback_;
69
+ };
70
+
71
+ struct FunctorClassFactory {
72
+ template <typename Callback>
73
+ static FunctorClass AsCallback(Callback callback) {
74
+ return FunctorClass(std::move(callback));
75
+ }
76
+ };
77
+
78
+ struct StdFunctionFactory {
79
+ template <typename Callback>
80
+ static std::function<void()> AsCallback(Callback callback) {
81
+ return std::function<void()>(std::move(callback));
82
+ }
83
+ };
84
+
85
+ using CleanupTestParams =
86
+ ::testing::Types<IdentityFactory, FunctorClassFactory, StdFunctionFactory>;
87
+ template <typename>
88
+ struct CleanupTest : public ::testing::Test {};
89
+ TYPED_TEST_SUITE(CleanupTest, CleanupTestParams);
90
+
91
+ bool fn_ptr_called = false;
92
+ void FnPtrFunction() { fn_ptr_called = true; }
93
+
94
+ TYPED_TEST(CleanupTest, FactoryProducesCorrectType) {
95
+ {
96
+ auto callback = TypeParam::AsCallback([] {});
97
+ auto cleanup = absl::MakeCleanup(std::move(callback));
98
+
99
+ static_assert(
100
+ IsSame<absl::Cleanup<Tag, decltype(callback)>, decltype(cleanup)>(),
101
+ "");
102
+ }
103
+
104
+ {
105
+ auto cleanup = absl::MakeCleanup(&FnPtrFunction);
106
+
107
+ static_assert(IsSame<absl::Cleanup<Tag, void (*)()>, decltype(cleanup)>(),
108
+ "");
109
+ }
110
+
111
+ {
112
+ auto cleanup = absl::MakeCleanup(FnPtrFunction);
113
+
114
+ static_assert(IsSame<absl::Cleanup<Tag, void (*)()>, decltype(cleanup)>(),
115
+ "");
116
+ }
117
+ }
118
+
119
+ #if defined(ABSL_HAVE_CLASS_TEMPLATE_ARGUMENT_DEDUCTION)
120
+ TYPED_TEST(CleanupTest, CTADProducesCorrectType) {
121
+ {
122
+ auto callback = TypeParam::AsCallback([] {});
123
+ absl::Cleanup cleanup = std::move(callback);
124
+
125
+ static_assert(
126
+ IsSame<absl::Cleanup<Tag, decltype(callback)>, decltype(cleanup)>(),
127
+ "");
128
+ }
129
+
130
+ {
131
+ absl::Cleanup cleanup = &FnPtrFunction;
132
+
133
+ static_assert(IsSame<absl::Cleanup<Tag, void (*)()>, decltype(cleanup)>(),
134
+ "");
135
+ }
136
+
137
+ {
138
+ absl::Cleanup cleanup = FnPtrFunction;
139
+
140
+ static_assert(IsSame<absl::Cleanup<Tag, void (*)()>, decltype(cleanup)>(),
141
+ "");
142
+ }
143
+ }
144
+
145
+ TYPED_TEST(CleanupTest, FactoryAndCTADProduceSameType) {
146
+ {
147
+ auto callback = IdentityFactory::AsCallback([] {});
148
+ auto factory_cleanup = absl::MakeCleanup(callback);
149
+ absl::Cleanup deduction_cleanup = callback;
150
+
151
+ static_assert(
152
+ IsSame<decltype(factory_cleanup), decltype(deduction_cleanup)>(), "");
153
+ }
154
+
155
+ {
156
+ auto factory_cleanup =
157
+ absl::MakeCleanup(FunctorClassFactory::AsCallback([] {}));
158
+ absl::Cleanup deduction_cleanup = FunctorClassFactory::AsCallback([] {});
159
+
160
+ static_assert(
161
+ IsSame<decltype(factory_cleanup), decltype(deduction_cleanup)>(), "");
162
+ }
163
+
164
+ {
165
+ auto factory_cleanup =
166
+ absl::MakeCleanup(StdFunctionFactory::AsCallback([] {}));
167
+ absl::Cleanup deduction_cleanup = StdFunctionFactory::AsCallback([] {});
168
+
169
+ static_assert(
170
+ IsSame<decltype(factory_cleanup), decltype(deduction_cleanup)>(), "");
171
+ }
172
+
173
+ {
174
+ auto factory_cleanup = absl::MakeCleanup(&FnPtrFunction);
175
+ absl::Cleanup deduction_cleanup = &FnPtrFunction;
176
+
177
+ static_assert(
178
+ IsSame<decltype(factory_cleanup), decltype(deduction_cleanup)>(), "");
179
+ }
180
+
181
+ {
182
+ auto factory_cleanup = absl::MakeCleanup(FnPtrFunction);
183
+ absl::Cleanup deduction_cleanup = FnPtrFunction;
184
+
185
+ static_assert(
186
+ IsSame<decltype(factory_cleanup), decltype(deduction_cleanup)>(), "");
187
+ }
188
+ }
189
+ #endif // defined(ABSL_HAVE_CLASS_TEMPLATE_ARGUMENT_DEDUCTION)
190
+
191
+ TYPED_TEST(CleanupTest, BasicUsage) {
192
+ bool called = false;
193
+
194
+ {
195
+ auto cleanup =
196
+ absl::MakeCleanup(TypeParam::AsCallback([&called] { called = true; }));
197
+ EXPECT_FALSE(called); // Constructor shouldn't invoke the callback
198
+ }
199
+
200
+ EXPECT_TRUE(called); // Destructor should invoke the callback
201
+ }
202
+
203
+ TYPED_TEST(CleanupTest, BasicUsageWithFunctionPointer) {
204
+ fn_ptr_called = false;
205
+
206
+ {
207
+ auto cleanup = absl::MakeCleanup(TypeParam::AsCallback(&FnPtrFunction));
208
+ EXPECT_FALSE(fn_ptr_called); // Constructor shouldn't invoke the callback
209
+ }
210
+
211
+ EXPECT_TRUE(fn_ptr_called); // Destructor should invoke the callback
212
+ }
213
+
214
+ TYPED_TEST(CleanupTest, Cancel) {
215
+ bool called = false;
216
+
217
+ {
218
+ auto cleanup =
219
+ absl::MakeCleanup(TypeParam::AsCallback([&called] { called = true; }));
220
+ EXPECT_FALSE(called); // Constructor shouldn't invoke the callback
221
+
222
+ std::move(cleanup).Cancel();
223
+ EXPECT_FALSE(called); // Cancel shouldn't invoke the callback
224
+ }
225
+
226
+ EXPECT_FALSE(called); // Destructor shouldn't invoke the callback
227
+ }
228
+
229
+ TYPED_TEST(CleanupTest, Invoke) {
230
+ bool called = false;
231
+
232
+ {
233
+ auto cleanup =
234
+ absl::MakeCleanup(TypeParam::AsCallback([&called] { called = true; }));
235
+ EXPECT_FALSE(called); // Constructor shouldn't invoke the callback
236
+
237
+ std::move(cleanup).Invoke();
238
+ EXPECT_TRUE(called); // Invoke should invoke the callback
239
+
240
+ called = false; // Reset tracker before destructor runs
241
+ }
242
+
243
+ EXPECT_FALSE(called); // Destructor shouldn't invoke the callback
244
+ }
245
+
246
+ TYPED_TEST(CleanupTest, Move) {
247
+ bool called = false;
248
+
249
+ {
250
+ auto moved_from_cleanup =
251
+ absl::MakeCleanup(TypeParam::AsCallback([&called] { called = true; }));
252
+ EXPECT_FALSE(called); // Constructor shouldn't invoke the callback
253
+
254
+ {
255
+ auto moved_to_cleanup = std::move(moved_from_cleanup);
256
+ EXPECT_FALSE(called); // Move shouldn't invoke the callback
257
+ }
258
+
259
+ EXPECT_TRUE(called); // Destructor should invoke the callback
260
+
261
+ called = false; // Reset tracker before destructor runs
262
+ }
263
+
264
+ EXPECT_FALSE(called); // Destructor shouldn't invoke the callback
265
+ }
266
+
267
+ int DestructionCount = 0;
268
+
269
+ struct DestructionCounter {
270
+ void operator()() {}
271
+
272
+ ~DestructionCounter() { ++DestructionCount; }
273
+ };
274
+
275
+ TYPED_TEST(CleanupTest, DestructorDestroys) {
276
+ {
277
+ auto cleanup =
278
+ absl::MakeCleanup(TypeParam::AsCallback(DestructionCounter()));
279
+ DestructionCount = 0;
280
+ }
281
+
282
+ EXPECT_EQ(DestructionCount, 1); // Engaged cleanup destroys
283
+ }
284
+
285
+ TYPED_TEST(CleanupTest, CancelDestroys) {
286
+ {
287
+ auto cleanup =
288
+ absl::MakeCleanup(TypeParam::AsCallback(DestructionCounter()));
289
+ DestructionCount = 0;
290
+
291
+ std::move(cleanup).Cancel();
292
+ EXPECT_EQ(DestructionCount, 1); // Cancel destroys
293
+ }
294
+
295
+ EXPECT_EQ(DestructionCount, 1); // Canceled cleanup does not double destroy
296
+ }
297
+
298
+ TYPED_TEST(CleanupTest, InvokeDestroys) {
299
+ {
300
+ auto cleanup =
301
+ absl::MakeCleanup(TypeParam::AsCallback(DestructionCounter()));
302
+ DestructionCount = 0;
303
+
304
+ std::move(cleanup).Invoke();
305
+ EXPECT_EQ(DestructionCount, 1); // Invoke destroys
306
+ }
307
+
308
+ EXPECT_EQ(DestructionCount, 1); // Invoked cleanup does not double destroy
309
+ }
310
+
311
+ } // namespace
weight/_dep/abseil-cpp/absl/cleanup/internal/cleanup.h ADDED
@@ -0,0 +1,100 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Copyright 2021 The Abseil Authors.
2
+ //
3
+ // Licensed under the Apache License, Version 2.0 (the "License");
4
+ // you may not use this file except in compliance with the License.
5
+ // You may obtain a copy of the License at
6
+ //
7
+ // https://www.apache.org/licenses/LICENSE-2.0
8
+ //
9
+ // Unless required by applicable law or agreed to in writing, software
10
+ // distributed under the License is distributed on an "AS IS" BASIS,
11
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ // See the License for the specific language governing permissions and
13
+ // limitations under the License.
14
+
15
+ #ifndef ABSL_CLEANUP_INTERNAL_CLEANUP_H_
16
+ #define ABSL_CLEANUP_INTERNAL_CLEANUP_H_
17
+
18
+ #include <new>
19
+ #include <type_traits>
20
+ #include <utility>
21
+
22
+ #include "absl/base/internal/invoke.h"
23
+ #include "absl/base/macros.h"
24
+ #include "absl/base/thread_annotations.h"
25
+ #include "absl/utility/utility.h"
26
+
27
+ namespace absl {
28
+ ABSL_NAMESPACE_BEGIN
29
+
30
+ namespace cleanup_internal {
31
+
32
+ struct Tag {};
33
+
34
+ template <typename Arg, typename... Args>
35
+ constexpr bool WasDeduced() {
36
+ return (std::is_same<cleanup_internal::Tag, Arg>::value) &&
37
+ (sizeof...(Args) == 0);
38
+ }
39
+
40
+ template <typename Callback>
41
+ constexpr bool ReturnsVoid() {
42
+ return (std::is_same<base_internal::invoke_result_t<Callback>, void>::value);
43
+ }
44
+
45
+ template <typename Callback>
46
+ class Storage {
47
+ public:
48
+ Storage() = delete;
49
+
50
+ explicit Storage(Callback callback) {
51
+ // Placement-new into a character buffer is used for eager destruction when
52
+ // the cleanup is invoked or cancelled. To ensure this optimizes well, the
53
+ // behavior is implemented locally instead of using an absl::optional.
54
+ ::new (GetCallbackBuffer()) Callback(std::move(callback));
55
+ is_callback_engaged_ = true;
56
+ }
57
+
58
+ Storage(Storage&& other) {
59
+ ABSL_HARDENING_ASSERT(other.IsCallbackEngaged());
60
+
61
+ ::new (GetCallbackBuffer()) Callback(std::move(other.GetCallback()));
62
+ is_callback_engaged_ = true;
63
+
64
+ other.DestroyCallback();
65
+ }
66
+
67
+ Storage(const Storage& other) = delete;
68
+
69
+ Storage& operator=(Storage&& other) = delete;
70
+
71
+ Storage& operator=(const Storage& other) = delete;
72
+
73
+ void* GetCallbackBuffer() { return static_cast<void*>(+callback_buffer_); }
74
+
75
+ Callback& GetCallback() {
76
+ return *reinterpret_cast<Callback*>(GetCallbackBuffer());
77
+ }
78
+
79
+ bool IsCallbackEngaged() const { return is_callback_engaged_; }
80
+
81
+ void DestroyCallback() {
82
+ is_callback_engaged_ = false;
83
+ GetCallback().~Callback();
84
+ }
85
+
86
+ void InvokeCallback() ABSL_NO_THREAD_SAFETY_ANALYSIS {
87
+ std::move(GetCallback())();
88
+ }
89
+
90
+ private:
91
+ bool is_callback_engaged_;
92
+ alignas(Callback) char callback_buffer_[sizeof(Callback)];
93
+ };
94
+
95
+ } // namespace cleanup_internal
96
+
97
+ ABSL_NAMESPACE_END
98
+ } // namespace absl
99
+
100
+ #endif // ABSL_CLEANUP_INTERNAL_CLEANUP_H_
weight/_dep/abseil-cpp/absl/copts/GENERATED_copts.bzl ADDED
@@ -0,0 +1,230 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """GENERATED! DO NOT MANUALLY EDIT THIS FILE.
2
+
3
+ (1) Edit absl/copts/copts.py.
4
+ (2) Run `python <path_to_absl>/copts/generate_copts.py`.
5
+ """
6
+
7
+ ABSL_CLANG_CL_FLAGS = [
8
+ "/W3",
9
+ "/DNOMINMAX",
10
+ "/DWIN32_LEAN_AND_MEAN",
11
+ "/D_CRT_SECURE_NO_WARNINGS",
12
+ "/D_SCL_SECURE_NO_WARNINGS",
13
+ "/D_ENABLE_EXTENDED_ALIGNED_STORAGE",
14
+ ]
15
+
16
+ ABSL_CLANG_CL_TEST_FLAGS = [
17
+ "/W3",
18
+ "/DNOMINMAX",
19
+ "/DWIN32_LEAN_AND_MEAN",
20
+ "/D_CRT_SECURE_NO_WARNINGS",
21
+ "/D_SCL_SECURE_NO_WARNINGS",
22
+ "/D_ENABLE_EXTENDED_ALIGNED_STORAGE",
23
+ "-Wno-deprecated-declarations",
24
+ "-Wno-implicit-int-conversion",
25
+ "-Wno-missing-prototypes",
26
+ "-Wno-missing-variable-declarations",
27
+ "-Wno-shadow",
28
+ "-Wno-shorten-64-to-32",
29
+ "-Wno-sign-compare",
30
+ "-Wno-sign-conversion",
31
+ "-Wno-unreachable-code-loop-increment",
32
+ "-Wno-unused-function",
33
+ "-Wno-unused-member-function",
34
+ "-Wno-unused-parameter",
35
+ "-Wno-unused-private-field",
36
+ "-Wno-unused-template",
37
+ "-Wno-used-but-marked-unused",
38
+ "-Wno-gnu-zero-variadic-macro-arguments",
39
+ ]
40
+
41
+ ABSL_GCC_FLAGS = [
42
+ "-Wall",
43
+ "-Wextra",
44
+ "-Wcast-qual",
45
+ "-Wconversion-null",
46
+ "-Wformat-security",
47
+ "-Wmissing-declarations",
48
+ "-Woverlength-strings",
49
+ "-Wpointer-arith",
50
+ "-Wundef",
51
+ "-Wunused-local-typedefs",
52
+ "-Wunused-result",
53
+ "-Wvarargs",
54
+ "-Wvla",
55
+ "-Wwrite-strings",
56
+ "-DNOMINMAX",
57
+ ]
58
+
59
+ ABSL_GCC_TEST_FLAGS = [
60
+ "-Wall",
61
+ "-Wextra",
62
+ "-Wcast-qual",
63
+ "-Wconversion-null",
64
+ "-Wformat-security",
65
+ "-Woverlength-strings",
66
+ "-Wpointer-arith",
67
+ "-Wundef",
68
+ "-Wunused-local-typedefs",
69
+ "-Wunused-result",
70
+ "-Wvarargs",
71
+ "-Wvla",
72
+ "-Wwrite-strings",
73
+ "-DNOMINMAX",
74
+ "-Wno-deprecated-declarations",
75
+ "-Wno-missing-declarations",
76
+ "-Wno-self-move",
77
+ "-Wno-sign-compare",
78
+ "-Wno-unused-function",
79
+ "-Wno-unused-parameter",
80
+ "-Wno-unused-private-field",
81
+ ]
82
+
83
+ ABSL_LLVM_FLAGS = [
84
+ "-Wall",
85
+ "-Wextra",
86
+ "-Wcast-qual",
87
+ "-Wconversion",
88
+ "-Wfloat-overflow-conversion",
89
+ "-Wfloat-zero-conversion",
90
+ "-Wfor-loop-analysis",
91
+ "-Wformat-security",
92
+ "-Wgnu-redeclared-enum",
93
+ "-Winfinite-recursion",
94
+ "-Winvalid-constexpr",
95
+ "-Wliteral-conversion",
96
+ "-Wmissing-declarations",
97
+ "-Woverlength-strings",
98
+ "-Wpointer-arith",
99
+ "-Wself-assign",
100
+ "-Wshadow-all",
101
+ "-Wshorten-64-to-32",
102
+ "-Wsign-conversion",
103
+ "-Wstring-conversion",
104
+ "-Wtautological-overlap-compare",
105
+ "-Wtautological-unsigned-zero-compare",
106
+ "-Wundef",
107
+ "-Wuninitialized",
108
+ "-Wunreachable-code",
109
+ "-Wunused-comparison",
110
+ "-Wunused-local-typedefs",
111
+ "-Wunused-result",
112
+ "-Wvla",
113
+ "-Wwrite-strings",
114
+ "-Wno-float-conversion",
115
+ "-Wno-implicit-float-conversion",
116
+ "-Wno-implicit-int-float-conversion",
117
+ "-Wno-unknown-warning-option",
118
+ "-DNOMINMAX",
119
+ ]
120
+
121
+ ABSL_LLVM_TEST_FLAGS = [
122
+ "-Wall",
123
+ "-Wextra",
124
+ "-Wcast-qual",
125
+ "-Wconversion",
126
+ "-Wfloat-overflow-conversion",
127
+ "-Wfloat-zero-conversion",
128
+ "-Wfor-loop-analysis",
129
+ "-Wformat-security",
130
+ "-Wgnu-redeclared-enum",
131
+ "-Winfinite-recursion",
132
+ "-Winvalid-constexpr",
133
+ "-Wliteral-conversion",
134
+ "-Wmissing-declarations",
135
+ "-Woverlength-strings",
136
+ "-Wpointer-arith",
137
+ "-Wself-assign",
138
+ "-Wshadow-all",
139
+ "-Wstring-conversion",
140
+ "-Wtautological-overlap-compare",
141
+ "-Wtautological-unsigned-zero-compare",
142
+ "-Wundef",
143
+ "-Wuninitialized",
144
+ "-Wunreachable-code",
145
+ "-Wunused-comparison",
146
+ "-Wunused-local-typedefs",
147
+ "-Wunused-result",
148
+ "-Wvla",
149
+ "-Wwrite-strings",
150
+ "-Wno-float-conversion",
151
+ "-Wno-implicit-float-conversion",
152
+ "-Wno-implicit-int-float-conversion",
153
+ "-Wno-unknown-warning-option",
154
+ "-DNOMINMAX",
155
+ "-Wno-deprecated-declarations",
156
+ "-Wno-implicit-int-conversion",
157
+ "-Wno-missing-prototypes",
158
+ "-Wno-missing-variable-declarations",
159
+ "-Wno-shadow",
160
+ "-Wno-shorten-64-to-32",
161
+ "-Wno-sign-compare",
162
+ "-Wno-sign-conversion",
163
+ "-Wno-unreachable-code-loop-increment",
164
+ "-Wno-unused-function",
165
+ "-Wno-unused-member-function",
166
+ "-Wno-unused-parameter",
167
+ "-Wno-unused-private-field",
168
+ "-Wno-unused-template",
169
+ "-Wno-used-but-marked-unused",
170
+ "-Wno-gnu-zero-variadic-macro-arguments",
171
+ ]
172
+
173
+ ABSL_MSVC_FLAGS = [
174
+ "/W3",
175
+ "/bigobj",
176
+ "/wd4005",
177
+ "/wd4068",
178
+ "/wd4180",
179
+ "/wd4244",
180
+ "/wd4267",
181
+ "/wd4503",
182
+ "/wd4800",
183
+ "/DNOMINMAX",
184
+ "/DWIN32_LEAN_AND_MEAN",
185
+ "/D_CRT_SECURE_NO_WARNINGS",
186
+ "/D_SCL_SECURE_NO_WARNINGS",
187
+ "/D_ENABLE_EXTENDED_ALIGNED_STORAGE",
188
+ ]
189
+
190
+ ABSL_MSVC_LINKOPTS = [
191
+ "-ignore:4221",
192
+ ]
193
+
194
+ ABSL_MSVC_TEST_FLAGS = [
195
+ "/W3",
196
+ "/bigobj",
197
+ "/wd4005",
198
+ "/wd4068",
199
+ "/wd4180",
200
+ "/wd4244",
201
+ "/wd4267",
202
+ "/wd4503",
203
+ "/wd4800",
204
+ "/DNOMINMAX",
205
+ "/DWIN32_LEAN_AND_MEAN",
206
+ "/D_CRT_SECURE_NO_WARNINGS",
207
+ "/D_SCL_SECURE_NO_WARNINGS",
208
+ "/D_ENABLE_EXTENDED_ALIGNED_STORAGE",
209
+ "/wd4018",
210
+ "/wd4101",
211
+ "/wd4503",
212
+ "/wd4996",
213
+ "/DNOMINMAX",
214
+ ]
215
+
216
+ ABSL_RANDOM_HWAES_ARM32_FLAGS = [
217
+ "-mfpu=neon",
218
+ ]
219
+
220
+ ABSL_RANDOM_HWAES_ARM64_FLAGS = [
221
+ "-march=armv8-a+crypto",
222
+ ]
223
+
224
+ ABSL_RANDOM_HWAES_MSVC_X64_FLAGS = [
225
+ ]
226
+
227
+ ABSL_RANDOM_HWAES_X64_FLAGS = [
228
+ "-maes",
229
+ "-msse4.1",
230
+ ]
weight/_dep/abseil-cpp/absl/copts/configure_copts.bzl ADDED
@@ -0,0 +1,82 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """absl specific copts.
2
+
3
+ This file simply selects the correct options from the generated files. To
4
+ change Abseil copts, edit absl/copts/copts.py
5
+ """
6
+
7
+ load(
8
+ "//absl:copts/GENERATED_copts.bzl",
9
+ "ABSL_CLANG_CL_FLAGS",
10
+ "ABSL_CLANG_CL_TEST_FLAGS",
11
+ "ABSL_GCC_FLAGS",
12
+ "ABSL_GCC_TEST_FLAGS",
13
+ "ABSL_LLVM_FLAGS",
14
+ "ABSL_LLVM_TEST_FLAGS",
15
+ "ABSL_MSVC_FLAGS",
16
+ "ABSL_MSVC_LINKOPTS",
17
+ "ABSL_MSVC_TEST_FLAGS",
18
+ "ABSL_RANDOM_HWAES_ARM32_FLAGS",
19
+ "ABSL_RANDOM_HWAES_ARM64_FLAGS",
20
+ "ABSL_RANDOM_HWAES_MSVC_X64_FLAGS",
21
+ "ABSL_RANDOM_HWAES_X64_FLAGS",
22
+ )
23
+
24
+ ABSL_DEFAULT_COPTS = select({
25
+ "//absl:msvc_compiler": ABSL_MSVC_FLAGS,
26
+ "//absl:clang-cl_compiler": ABSL_CLANG_CL_FLAGS,
27
+ "//absl:clang_compiler": ABSL_LLVM_FLAGS,
28
+ "//absl:gcc_compiler": ABSL_GCC_FLAGS,
29
+ "//conditions:default": ABSL_GCC_FLAGS,
30
+ })
31
+
32
+ ABSL_TEST_COPTS = select({
33
+ "//absl:msvc_compiler": ABSL_MSVC_TEST_FLAGS,
34
+ "//absl:clang-cl_compiler": ABSL_CLANG_CL_TEST_FLAGS,
35
+ "//absl:clang_compiler": ABSL_LLVM_TEST_FLAGS,
36
+ "//absl:gcc_compiler": ABSL_GCC_TEST_FLAGS,
37
+ "//conditions:default": ABSL_GCC_TEST_FLAGS,
38
+ })
39
+
40
+ ABSL_DEFAULT_LINKOPTS = select({
41
+ "//absl:msvc_compiler": ABSL_MSVC_LINKOPTS,
42
+ "//conditions:default": [],
43
+ })
44
+
45
+ # ABSL_RANDOM_RANDEN_COPTS blaze copts flags which are required by each
46
+ # environment to build an accelerated RandenHwAes library.
47
+ ABSL_RANDOM_RANDEN_COPTS = select({
48
+ # APPLE
49
+ ":cpu_darwin_x86_64": ABSL_RANDOM_HWAES_X64_FLAGS,
50
+ ":cpu_darwin": ABSL_RANDOM_HWAES_X64_FLAGS,
51
+ ":cpu_x64_windows_msvc": ABSL_RANDOM_HWAES_MSVC_X64_FLAGS,
52
+ ":cpu_x64_windows": ABSL_RANDOM_HWAES_MSVC_X64_FLAGS,
53
+ ":cpu_k8": ABSL_RANDOM_HWAES_X64_FLAGS,
54
+ ":cpu_ppc": ["-mcrypto"],
55
+ ":cpu_aarch64": ABSL_RANDOM_HWAES_ARM64_FLAGS,
56
+
57
+ # Supported by default or unsupported.
58
+ "//conditions:default": [],
59
+ })
60
+
61
+ # absl_random_randen_copts_init:
62
+ # Initialize the config targets based on cpu, os, etc. used to select
63
+ # the required values for ABSL_RANDOM_RANDEN_COPTS
64
+ def absl_random_randen_copts_init():
65
+ """Initialize the config_settings used by ABSL_RANDOM_RANDEN_COPTS."""
66
+
67
+ # CPU configs.
68
+ # These configs have consistent flags to enable HWAES intsructions.
69
+ cpu_configs = [
70
+ "ppc",
71
+ "k8",
72
+ "darwin_x86_64",
73
+ "darwin",
74
+ "x64_windows_msvc",
75
+ "x64_windows",
76
+ "aarch64",
77
+ ]
78
+ for cpu in cpu_configs:
79
+ native.config_setting(
80
+ name = "cpu_%s" % cpu,
81
+ values = {"cpu": cpu},
82
+ )
weight/_dep/abseil-cpp/absl/copts/copts.py ADDED
@@ -0,0 +1,191 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Abseil compiler options.
2
+
3
+ This is the source of truth for Abseil compiler options. To modify Abseil
4
+ compilation options:
5
+
6
+ (1) Edit the appropriate list in this file based on the platform the flag is
7
+ needed on.
8
+ (2) Run `<path_to_absl>/copts/generate_copts.py`.
9
+
10
+ The generated copts are consumed by configure_copts.bzl and
11
+ AbseilConfigureCopts.cmake.
12
+ """
13
+
14
+ ABSL_GCC_FLAGS = [
15
+ "-Wall",
16
+ "-Wextra",
17
+ "-Wcast-qual",
18
+ "-Wconversion-null",
19
+ "-Wformat-security",
20
+ "-Wmissing-declarations",
21
+ "-Woverlength-strings",
22
+ "-Wpointer-arith",
23
+ "-Wundef",
24
+ "-Wunused-local-typedefs",
25
+ "-Wunused-result",
26
+ "-Wvarargs",
27
+ "-Wvla", # variable-length array
28
+ "-Wwrite-strings",
29
+ # Don't define min and max macros (Build on Windows using gcc)
30
+ "-DNOMINMAX",
31
+ ]
32
+
33
+ ABSL_GCC_TEST_ADDITIONAL_FLAGS = [
34
+ "-Wno-deprecated-declarations",
35
+ "-Wno-missing-declarations",
36
+ "-Wno-self-move",
37
+ "-Wno-sign-compare",
38
+ "-Wno-unused-function",
39
+ "-Wno-unused-parameter",
40
+ "-Wno-unused-private-field",
41
+ ]
42
+
43
+ ABSL_LLVM_FLAGS = [
44
+ "-Wall",
45
+ "-Wextra",
46
+ "-Wcast-qual",
47
+ "-Wconversion",
48
+ "-Wfloat-overflow-conversion",
49
+ "-Wfloat-zero-conversion",
50
+ "-Wfor-loop-analysis",
51
+ "-Wformat-security",
52
+ "-Wgnu-redeclared-enum",
53
+ "-Winfinite-recursion",
54
+ "-Winvalid-constexpr",
55
+ "-Wliteral-conversion",
56
+ "-Wmissing-declarations",
57
+ "-Woverlength-strings",
58
+ "-Wpointer-arith",
59
+ "-Wself-assign",
60
+ "-Wshadow-all",
61
+ "-Wshorten-64-to-32",
62
+ "-Wsign-conversion",
63
+ "-Wstring-conversion",
64
+ "-Wtautological-overlap-compare",
65
+ "-Wtautological-unsigned-zero-compare",
66
+ "-Wundef",
67
+ "-Wuninitialized",
68
+ "-Wunreachable-code",
69
+ "-Wunused-comparison",
70
+ "-Wunused-local-typedefs",
71
+ "-Wunused-result",
72
+ "-Wvla",
73
+ "-Wwrite-strings",
74
+ # Warnings that are enabled by group warning flags like -Wall that we
75
+ # explicitly disable.
76
+ "-Wno-float-conversion",
77
+ "-Wno-implicit-float-conversion",
78
+ "-Wno-implicit-int-float-conversion",
79
+ # Disable warnings on unknown warning flags (when warning flags are
80
+ # unknown on older compiler versions)
81
+ "-Wno-unknown-warning-option",
82
+ # Don't define min and max macros (Build on Windows using clang)
83
+ "-DNOMINMAX",
84
+ ]
85
+
86
+ ABSL_LLVM_TEST_ADDITIONAL_FLAGS = [
87
+ "-Wno-deprecated-declarations",
88
+ "-Wno-implicit-int-conversion",
89
+ "-Wno-missing-prototypes",
90
+ "-Wno-missing-variable-declarations",
91
+ "-Wno-shadow",
92
+ "-Wno-shorten-64-to-32",
93
+ "-Wno-sign-compare",
94
+ "-Wno-sign-conversion",
95
+ "-Wno-unreachable-code-loop-increment",
96
+ "-Wno-unused-function",
97
+ "-Wno-unused-member-function",
98
+ "-Wno-unused-parameter",
99
+ "-Wno-unused-private-field",
100
+ "-Wno-unused-template",
101
+ "-Wno-used-but-marked-unused",
102
+ # gtest depends on this GNU extension being offered.
103
+ "-Wno-gnu-zero-variadic-macro-arguments",
104
+ ]
105
+
106
+ # /Wall with msvc includes unhelpful warnings such as C4711, C4710, ...
107
+ MSVC_BIG_WARNING_FLAGS = [
108
+ "/W3",
109
+ ]
110
+
111
+ MSVC_WARNING_FLAGS = [
112
+ # Increase the number of sections available in object files
113
+ "/bigobj",
114
+ "/wd4005", # macro-redefinition
115
+ "/wd4068", # unknown pragma
116
+ # qualifier applied to function type has no meaning; ignored
117
+ "/wd4180",
118
+ # conversion from 'type1' to 'type2', possible loss of data
119
+ "/wd4244",
120
+ # conversion from 'size_t' to 'type', possible loss of data
121
+ "/wd4267",
122
+ # The decorated name was longer than the compiler limit
123
+ "/wd4503",
124
+ # forcing value to bool 'true' or 'false' (performance warning)
125
+ "/wd4800",
126
+ ]
127
+
128
+ MSVC_DEFINES = [
129
+ "/DNOMINMAX", # Don't define min and max macros (windows.h)
130
+ # Don't bloat namespace with incompatible winsock versions.
131
+ "/DWIN32_LEAN_AND_MEAN",
132
+ # Don't warn about usage of insecure C functions.
133
+ "/D_CRT_SECURE_NO_WARNINGS",
134
+ "/D_SCL_SECURE_NO_WARNINGS",
135
+ # Introduced in VS 2017 15.8, allow overaligned types in aligned_storage
136
+ "/D_ENABLE_EXTENDED_ALIGNED_STORAGE",
137
+ ]
138
+
139
+
140
+ def GccStyleFilterAndCombine(default_flags, test_flags):
141
+ """Merges default_flags and test_flags for GCC and LLVM.
142
+
143
+ Args:
144
+ default_flags: A list of default compiler flags
145
+ test_flags: A list of flags that are only used in tests
146
+
147
+ Returns:
148
+ A combined list of default_flags and test_flags, but with all flags of the
149
+ form '-Wwarning' removed if test_flags contains a flag of the form
150
+ '-Wno-warning'
151
+ """
152
+ remove = set(["-W" + f[5:] for f in test_flags if f[:5] == "-Wno-"])
153
+ return [f for f in default_flags if f not in remove] + test_flags
154
+
155
+ COPT_VARS = {
156
+ "ABSL_GCC_FLAGS": ABSL_GCC_FLAGS,
157
+ "ABSL_GCC_TEST_FLAGS": GccStyleFilterAndCombine(
158
+ ABSL_GCC_FLAGS, ABSL_GCC_TEST_ADDITIONAL_FLAGS),
159
+ "ABSL_LLVM_FLAGS": ABSL_LLVM_FLAGS,
160
+ "ABSL_LLVM_TEST_FLAGS": GccStyleFilterAndCombine(
161
+ ABSL_LLVM_FLAGS, ABSL_LLVM_TEST_ADDITIONAL_FLAGS),
162
+ "ABSL_CLANG_CL_FLAGS":
163
+ MSVC_BIG_WARNING_FLAGS + MSVC_DEFINES,
164
+ "ABSL_CLANG_CL_TEST_FLAGS":
165
+ MSVC_BIG_WARNING_FLAGS + MSVC_DEFINES + ABSL_LLVM_TEST_ADDITIONAL_FLAGS,
166
+ "ABSL_MSVC_FLAGS":
167
+ MSVC_BIG_WARNING_FLAGS + MSVC_WARNING_FLAGS + MSVC_DEFINES,
168
+ "ABSL_MSVC_TEST_FLAGS":
169
+ MSVC_BIG_WARNING_FLAGS + MSVC_WARNING_FLAGS + MSVC_DEFINES + [
170
+ "/wd4018", # signed/unsigned mismatch
171
+ "/wd4101", # unreferenced local variable
172
+ "/wd4503", # decorated name length exceeded, name was truncated
173
+ "/wd4996", # use of deprecated symbol
174
+ "/DNOMINMAX", # disable the min() and max() macros from <windows.h>
175
+ ],
176
+ "ABSL_MSVC_LINKOPTS": [
177
+ # Object file doesn't export any previously undefined symbols
178
+ "-ignore:4221",
179
+ ],
180
+ # "HWAES" is an abbreviation for "hardware AES" (AES - Advanced Encryption
181
+ # Standard). These flags are used for detecting whether or not the target
182
+ # architecture has hardware support for AES instructions which can be used
183
+ # to improve performance of some random bit generators.
184
+ "ABSL_RANDOM_HWAES_ARM64_FLAGS": ["-march=armv8-a+crypto"],
185
+ "ABSL_RANDOM_HWAES_ARM32_FLAGS": ["-mfpu=neon"],
186
+ "ABSL_RANDOM_HWAES_X64_FLAGS": [
187
+ "-maes",
188
+ "-msse4.1",
189
+ ],
190
+ "ABSL_RANDOM_HWAES_MSVC_X64_FLAGS": [],
191
+ }
weight/_dep/abseil-cpp/absl/copts/generate_copts.py ADDED
@@ -0,0 +1,109 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """Generate Abseil compile compile option configs.
3
+
4
+ Usage: <path_to_absl>/copts/generate_copts.py
5
+
6
+ The configs are generated from copts.py.
7
+ """
8
+
9
+ from os import path
10
+ import sys
11
+ from copts import COPT_VARS
12
+
13
+
14
+ # Helper functions
15
+ def file_header_lines():
16
+ return [
17
+ "GENERATED! DO NOT MANUALLY EDIT THIS FILE.", "",
18
+ "(1) Edit absl/copts/copts.py.",
19
+ "(2) Run `python <path_to_absl>/copts/generate_copts.py`."
20
+ ]
21
+
22
+
23
+ def flatten(*lists):
24
+ return [item for sublist in lists for item in sublist]
25
+
26
+
27
+ def relative_filename(filename):
28
+ return path.join(path.dirname(__file__), filename)
29
+
30
+
31
+ # Style classes. These contain all the syntactic styling needed to generate a
32
+ # copt file for different build tools.
33
+ class CMakeStyle(object):
34
+ """Style object for CMake copts file."""
35
+
36
+ def separator(self):
37
+ return ""
38
+
39
+ def list_introducer(self, name):
40
+ return "list(APPEND " + name
41
+
42
+ def list_closer(self):
43
+ return ")\n"
44
+
45
+ def docstring(self):
46
+ return "\n".join((("# " + line).strip() for line in file_header_lines()))
47
+
48
+ def filename(self):
49
+ return "GENERATED_AbseilCopts.cmake"
50
+
51
+
52
+ class StarlarkStyle(object):
53
+ """Style object for Starlark copts file."""
54
+
55
+ def separator(self):
56
+ return ","
57
+
58
+ def list_introducer(self, name):
59
+ return name + " = ["
60
+
61
+ def list_closer(self):
62
+ return "]\n"
63
+
64
+ def docstring(self):
65
+ docstring_quotes = "\"\"\""
66
+ return docstring_quotes + "\n".join(
67
+ flatten(file_header_lines(), [docstring_quotes]))
68
+
69
+ def filename(self):
70
+ return "GENERATED_copts.bzl"
71
+
72
+
73
+ def copt_list(name, arg_list, style):
74
+ """Copt file generation."""
75
+
76
+ make_line = lambda s: " \"" + s + "\"" + style.separator()
77
+ external_str_list = [make_line(s) for s in arg_list]
78
+
79
+ return "\n".join(
80
+ flatten(
81
+ [style.list_introducer(name)],
82
+ external_str_list,
83
+ [style.list_closer()]))
84
+
85
+
86
+ def generate_copt_file(style):
87
+ """Creates a generated copt file using the given style object.
88
+
89
+ Args:
90
+ style: either StarlarkStyle() or CMakeStyle()
91
+ """
92
+ with open(relative_filename(style.filename()), "w") as f:
93
+ f.write(style.docstring())
94
+ f.write("\n")
95
+ for var_name, arg_list in sorted(COPT_VARS.items()):
96
+ f.write("\n")
97
+ f.write(copt_list(var_name, arg_list, style))
98
+
99
+
100
+ def main(argv):
101
+ if len(argv) > 1:
102
+ raise RuntimeError("generate_copts needs no command line args")
103
+
104
+ generate_copt_file(StarlarkStyle())
105
+ generate_copt_file(CMakeStyle())
106
+
107
+
108
+ if __name__ == "__main__":
109
+ main(sys.argv)
weight/_dep/abseil-cpp/absl/flags/BUILD.bazel ADDED
@@ -0,0 +1,601 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #
2
+ # Copyright 2019 The Abseil Authors.
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # https://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+ #
16
+
17
+ load(
18
+ "//absl:copts/configure_copts.bzl",
19
+ "ABSL_DEFAULT_COPTS",
20
+ "ABSL_DEFAULT_LINKOPTS",
21
+ "ABSL_TEST_COPTS",
22
+ )
23
+
24
+ package(
25
+ default_visibility = ["//visibility:public"],
26
+ features = [
27
+ "header_modules",
28
+ "layering_check",
29
+ "parse_headers",
30
+ ],
31
+ )
32
+
33
+ licenses(["notice"])
34
+
35
+ cc_library(
36
+ name = "path_util",
37
+ hdrs = [
38
+ "internal/path_util.h",
39
+ ],
40
+ copts = ABSL_DEFAULT_COPTS,
41
+ linkopts = ABSL_DEFAULT_LINKOPTS,
42
+ visibility = [
43
+ "//absl/flags:__pkg__",
44
+ ],
45
+ deps = [
46
+ "//absl/base:config",
47
+ "//absl/strings",
48
+ ],
49
+ )
50
+
51
+ cc_library(
52
+ name = "program_name",
53
+ srcs = [
54
+ "internal/program_name.cc",
55
+ ],
56
+ hdrs = [
57
+ "internal/program_name.h",
58
+ ],
59
+ copts = ABSL_DEFAULT_COPTS,
60
+ linkopts = ABSL_DEFAULT_LINKOPTS,
61
+ visibility = [
62
+ "//absl/flags:__pkg__",
63
+ "//absl/log:__pkg__",
64
+ ],
65
+ deps = [
66
+ ":path_util",
67
+ "//absl/base:config",
68
+ "//absl/base:core_headers",
69
+ "//absl/strings",
70
+ "//absl/synchronization",
71
+ ],
72
+ )
73
+
74
+ cc_library(
75
+ name = "config",
76
+ srcs = [
77
+ "usage_config.cc",
78
+ ],
79
+ hdrs = [
80
+ "config.h",
81
+ "usage_config.h",
82
+ ],
83
+ copts = ABSL_DEFAULT_COPTS,
84
+ linkopts = ABSL_DEFAULT_LINKOPTS,
85
+ deps = [
86
+ ":path_util",
87
+ ":program_name",
88
+ "//absl/base:config",
89
+ "//absl/base:core_headers",
90
+ "//absl/strings",
91
+ "//absl/synchronization",
92
+ ],
93
+ )
94
+
95
+ cc_library(
96
+ name = "marshalling",
97
+ srcs = [
98
+ "marshalling.cc",
99
+ ],
100
+ hdrs = [
101
+ "marshalling.h",
102
+ ],
103
+ copts = ABSL_DEFAULT_COPTS,
104
+ linkopts = ABSL_DEFAULT_LINKOPTS,
105
+ deps = [
106
+ "//absl/base:config",
107
+ "//absl/base:core_headers",
108
+ "//absl/base:log_severity",
109
+ "//absl/numeric:int128",
110
+ "//absl/strings",
111
+ "//absl/strings:str_format",
112
+ "//absl/types:optional",
113
+ ],
114
+ )
115
+
116
+ cc_library(
117
+ name = "commandlineflag_internal",
118
+ srcs = [
119
+ "internal/commandlineflag.cc",
120
+ ],
121
+ hdrs = [
122
+ "internal/commandlineflag.h",
123
+ ],
124
+ copts = ABSL_DEFAULT_COPTS,
125
+ linkopts = ABSL_DEFAULT_LINKOPTS,
126
+ visibility = [
127
+ "//visibility:private",
128
+ ],
129
+ deps = [
130
+ "//absl/base:config",
131
+ "//absl/base:fast_type_id",
132
+ ],
133
+ )
134
+
135
+ cc_library(
136
+ name = "commandlineflag",
137
+ srcs = [
138
+ "commandlineflag.cc",
139
+ ],
140
+ hdrs = [
141
+ "commandlineflag.h",
142
+ ],
143
+ copts = ABSL_DEFAULT_COPTS,
144
+ linkopts = ABSL_DEFAULT_LINKOPTS,
145
+ deps = [
146
+ ":commandlineflag_internal",
147
+ "//absl/base:config",
148
+ "//absl/base:fast_type_id",
149
+ "//absl/strings",
150
+ "//absl/types:optional",
151
+ ],
152
+ )
153
+
154
+ cc_library(
155
+ name = "private_handle_accessor",
156
+ srcs = [
157
+ "internal/private_handle_accessor.cc",
158
+ ],
159
+ hdrs = [
160
+ "internal/private_handle_accessor.h",
161
+ ],
162
+ copts = ABSL_DEFAULT_COPTS,
163
+ linkopts = ABSL_DEFAULT_LINKOPTS,
164
+ visibility = [
165
+ "//absl/flags:__pkg__",
166
+ ],
167
+ deps = [
168
+ ":commandlineflag",
169
+ ":commandlineflag_internal",
170
+ "//absl/base:config",
171
+ "//absl/strings",
172
+ ],
173
+ )
174
+
175
+ cc_library(
176
+ name = "reflection",
177
+ srcs = [
178
+ "reflection.cc",
179
+ ],
180
+ hdrs = [
181
+ "internal/registry.h",
182
+ "reflection.h",
183
+ ],
184
+ copts = ABSL_DEFAULT_COPTS,
185
+ linkopts = ABSL_DEFAULT_LINKOPTS,
186
+ deps = [
187
+ ":commandlineflag",
188
+ ":commandlineflag_internal",
189
+ ":config",
190
+ ":private_handle_accessor",
191
+ "//absl/base:config",
192
+ "//absl/base:core_headers",
193
+ "//absl/base:no_destructor",
194
+ "//absl/container:flat_hash_map",
195
+ "//absl/strings",
196
+ "//absl/synchronization",
197
+ ],
198
+ )
199
+
200
+ cc_library(
201
+ name = "flag_internal",
202
+ srcs = [
203
+ "internal/flag.cc",
204
+ ],
205
+ hdrs = [
206
+ "internal/flag.h",
207
+ "internal/sequence_lock.h",
208
+ ],
209
+ copts = ABSL_DEFAULT_COPTS,
210
+ linkopts = ABSL_DEFAULT_LINKOPTS,
211
+ visibility = ["//absl/base:__subpackages__"],
212
+ deps = [
213
+ ":commandlineflag",
214
+ ":commandlineflag_internal",
215
+ ":config",
216
+ ":marshalling",
217
+ ":reflection",
218
+ "//absl/base",
219
+ "//absl/base:config",
220
+ "//absl/base:core_headers",
221
+ "//absl/base:dynamic_annotations",
222
+ "//absl/memory",
223
+ "//absl/meta:type_traits",
224
+ "//absl/strings",
225
+ "//absl/synchronization",
226
+ "//absl/utility",
227
+ ],
228
+ )
229
+
230
+ cc_library(
231
+ name = "flag",
232
+ hdrs = [
233
+ "declare.h",
234
+ "flag.h",
235
+ ],
236
+ copts = ABSL_DEFAULT_COPTS,
237
+ linkopts = ABSL_DEFAULT_LINKOPTS,
238
+ deps = [
239
+ ":config",
240
+ ":flag_internal",
241
+ ":reflection",
242
+ "//absl/base",
243
+ "//absl/base:config",
244
+ "//absl/base:core_headers",
245
+ "//absl/strings",
246
+ ],
247
+ )
248
+
249
+ cc_library(
250
+ name = "usage_internal",
251
+ srcs = [
252
+ "internal/usage.cc",
253
+ ],
254
+ hdrs = [
255
+ "internal/usage.h",
256
+ ],
257
+ copts = ABSL_DEFAULT_COPTS,
258
+ linkopts = ABSL_DEFAULT_LINKOPTS,
259
+ visibility = [
260
+ "//absl/flags:__pkg__",
261
+ ],
262
+ deps = [
263
+ ":commandlineflag",
264
+ ":config",
265
+ ":flag",
266
+ ":flag_internal",
267
+ ":path_util",
268
+ ":private_handle_accessor",
269
+ ":program_name",
270
+ ":reflection",
271
+ "//absl/base:config",
272
+ "//absl/base:core_headers",
273
+ "//absl/strings",
274
+ "//absl/synchronization",
275
+ ],
276
+ )
277
+
278
+ cc_library(
279
+ name = "usage",
280
+ srcs = [
281
+ "usage.cc",
282
+ ],
283
+ hdrs = [
284
+ "usage.h",
285
+ ],
286
+ copts = ABSL_DEFAULT_COPTS,
287
+ linkopts = ABSL_DEFAULT_LINKOPTS,
288
+ deps = [
289
+ ":usage_internal",
290
+ "//absl/base:config",
291
+ "//absl/base:core_headers",
292
+ "//absl/base:raw_logging_internal",
293
+ "//absl/strings",
294
+ "//absl/synchronization",
295
+ ],
296
+ )
297
+
298
+ cc_library(
299
+ name = "parse",
300
+ srcs = ["parse.cc"],
301
+ hdrs = [
302
+ "internal/parse.h",
303
+ "parse.h",
304
+ ],
305
+ copts = ABSL_DEFAULT_COPTS,
306
+ linkopts = ABSL_DEFAULT_LINKOPTS,
307
+ deps = [
308
+ ":commandlineflag",
309
+ ":commandlineflag_internal",
310
+ ":config",
311
+ ":flag",
312
+ ":flag_internal",
313
+ ":private_handle_accessor",
314
+ ":program_name",
315
+ ":reflection",
316
+ ":usage",
317
+ ":usage_internal",
318
+ "//absl/algorithm:container",
319
+ "//absl/base:config",
320
+ "//absl/base:core_headers",
321
+ "//absl/strings",
322
+ "//absl/synchronization",
323
+ ],
324
+ )
325
+
326
+ ############################################################################
327
+ # Unit tests in alphabetical order.
328
+
329
+ cc_test(
330
+ name = "commandlineflag_test",
331
+ size = "small",
332
+ srcs = [
333
+ "commandlineflag_test.cc",
334
+ ],
335
+ copts = ABSL_TEST_COPTS,
336
+ linkopts = ABSL_DEFAULT_LINKOPTS,
337
+ tags = [
338
+ "no_test:os:android",
339
+ "no_test:os:ios",
340
+ "no_test_android",
341
+ "no_test_ios",
342
+ "no_test_wasm",
343
+ ],
344
+ deps = [
345
+ ":commandlineflag",
346
+ ":commandlineflag_internal",
347
+ ":config",
348
+ ":flag",
349
+ ":private_handle_accessor",
350
+ ":reflection",
351
+ "//absl/memory",
352
+ "//absl/strings",
353
+ "@com_google_googletest//:gtest",
354
+ "@com_google_googletest//:gtest_main",
355
+ ],
356
+ )
357
+
358
+ cc_test(
359
+ name = "config_test",
360
+ size = "small",
361
+ srcs = [
362
+ "config_test.cc",
363
+ ],
364
+ copts = ABSL_TEST_COPTS,
365
+ linkopts = ABSL_DEFAULT_LINKOPTS,
366
+ deps = [
367
+ ":config",
368
+ "@com_google_googletest//:gtest",
369
+ "@com_google_googletest//:gtest_main",
370
+ ],
371
+ )
372
+
373
+ cc_test(
374
+ name = "flag_test",
375
+ size = "small",
376
+ srcs = [
377
+ "flag_test.cc",
378
+ "flag_test_defs.cc",
379
+ ],
380
+ copts = ABSL_TEST_COPTS,
381
+ linkopts = ABSL_DEFAULT_LINKOPTS,
382
+ tags = [
383
+ "no_test:os:android",
384
+ "no_test:os:ios",
385
+ "no_test_android",
386
+ "no_test_ios",
387
+ "no_test_wasm",
388
+ ],
389
+ deps = [
390
+ ":config",
391
+ ":flag",
392
+ ":flag_internal",
393
+ ":marshalling",
394
+ ":reflection",
395
+ "//absl/base:core_headers",
396
+ "//absl/base:malloc_internal",
397
+ "//absl/numeric:int128",
398
+ "//absl/strings",
399
+ "//absl/time",
400
+ "@com_google_googletest//:gtest",
401
+ "@com_google_googletest//:gtest_main",
402
+ ],
403
+ )
404
+
405
+ cc_binary(
406
+ name = "flag_benchmark",
407
+ testonly = 1,
408
+ srcs = [
409
+ "flag_benchmark.cc",
410
+ ],
411
+ copts = ABSL_TEST_COPTS,
412
+ linkopts = select({
413
+ "//conditions:default": [],
414
+ }) + ABSL_DEFAULT_LINKOPTS,
415
+ tags = ["benchmark"],
416
+ visibility = ["//visibility:private"],
417
+ deps = [
418
+ "flag_benchmark.lds",
419
+ ":flag",
420
+ ":marshalling",
421
+ ":parse",
422
+ ":reflection",
423
+ "//absl/strings",
424
+ "//absl/time",
425
+ "//absl/types:optional",
426
+ "@com_github_google_benchmark//:benchmark_main",
427
+ ],
428
+ )
429
+
430
+ cc_test(
431
+ name = "marshalling_test",
432
+ size = "small",
433
+ srcs = [
434
+ "marshalling_test.cc",
435
+ ],
436
+ copts = ABSL_TEST_COPTS,
437
+ linkopts = ABSL_DEFAULT_LINKOPTS,
438
+ deps = [
439
+ ":marshalling",
440
+ "@com_google_googletest//:gtest",
441
+ "@com_google_googletest//:gtest_main",
442
+ ],
443
+ )
444
+
445
+ cc_test(
446
+ name = "parse_test",
447
+ size = "small",
448
+ timeout = "moderate",
449
+ srcs = [
450
+ "parse_test.cc",
451
+ ],
452
+ copts = ABSL_TEST_COPTS,
453
+ linkopts = ABSL_DEFAULT_LINKOPTS,
454
+ tags = [
455
+ "no_test:os:android",
456
+ "no_test:os:ios",
457
+ "no_test_android",
458
+ "no_test_ios",
459
+ "no_test_wasm",
460
+ ],
461
+ deps = [
462
+ ":flag",
463
+ ":parse",
464
+ ":reflection",
465
+ ":usage_internal",
466
+ "//absl/base:scoped_set_env",
467
+ "//absl/log",
468
+ "//absl/strings",
469
+ "//absl/types:span",
470
+ "@com_google_googletest//:gtest",
471
+ "@com_google_googletest//:gtest_main",
472
+ ],
473
+ )
474
+
475
+ cc_test(
476
+ name = "path_util_test",
477
+ size = "small",
478
+ srcs = [
479
+ "internal/path_util_test.cc",
480
+ ],
481
+ copts = ABSL_TEST_COPTS,
482
+ linkopts = ABSL_DEFAULT_LINKOPTS,
483
+ deps = [
484
+ ":path_util",
485
+ "@com_google_googletest//:gtest",
486
+ "@com_google_googletest//:gtest_main",
487
+ ],
488
+ )
489
+
490
+ cc_test(
491
+ name = "program_name_test",
492
+ size = "small",
493
+ srcs = [
494
+ "internal/program_name_test.cc",
495
+ ],
496
+ copts = ABSL_TEST_COPTS,
497
+ linkopts = ABSL_DEFAULT_LINKOPTS,
498
+ tags = ["no_test_wasm"],
499
+ deps = [
500
+ ":program_name",
501
+ "//absl/strings",
502
+ "@com_google_googletest//:gtest",
503
+ "@com_google_googletest//:gtest_main",
504
+ ],
505
+ )
506
+
507
+ cc_test(
508
+ name = "reflection_test",
509
+ size = "small",
510
+ srcs = [
511
+ "reflection_test.cc",
512
+ ],
513
+ copts = ABSL_TEST_COPTS,
514
+ linkopts = ABSL_DEFAULT_LINKOPTS,
515
+ tags = [
516
+ "no_test:os:android",
517
+ "no_test:os:ios",
518
+ "no_test_android",
519
+ "no_test_ios",
520
+ "no_test_wasm",
521
+ ],
522
+ deps = [
523
+ ":commandlineflag_internal",
524
+ ":flag",
525
+ ":marshalling",
526
+ ":reflection",
527
+ ":usage_internal",
528
+ "//absl/memory",
529
+ "//absl/strings",
530
+ "@com_google_googletest//:gtest",
531
+ "@com_google_googletest//:gtest_main",
532
+ ],
533
+ )
534
+
535
+ cc_test(
536
+ name = "sequence_lock_test",
537
+ size = "small",
538
+ timeout = "moderate",
539
+ srcs = [
540
+ "internal/sequence_lock_test.cc",
541
+ ],
542
+ copts = ABSL_TEST_COPTS,
543
+ linkopts = ABSL_DEFAULT_LINKOPTS,
544
+ shard_count = 31,
545
+ tags = ["no_test_wasm"],
546
+ deps = [
547
+ ":flag_internal",
548
+ "//absl/base",
549
+ "//absl/container:fixed_array",
550
+ "//absl/time",
551
+ "@com_google_googletest//:gtest",
552
+ "@com_google_googletest//:gtest_main",
553
+ ],
554
+ )
555
+
556
+ cc_test(
557
+ name = "usage_config_test",
558
+ size = "small",
559
+ srcs = [
560
+ "usage_config_test.cc",
561
+ ],
562
+ copts = ABSL_TEST_COPTS,
563
+ linkopts = ABSL_DEFAULT_LINKOPTS,
564
+ deps = [
565
+ ":config",
566
+ ":path_util",
567
+ ":program_name",
568
+ "//absl/strings",
569
+ "@com_google_googletest//:gtest",
570
+ "@com_google_googletest//:gtest_main",
571
+ ],
572
+ )
573
+
574
+ cc_test(
575
+ name = "usage_test",
576
+ size = "small",
577
+ srcs = [
578
+ "internal/usage_test.cc",
579
+ ],
580
+ copts = ABSL_TEST_COPTS,
581
+ linkopts = ABSL_DEFAULT_LINKOPTS,
582
+ tags = [
583
+ "no_test:os:android",
584
+ "no_test:os:ios",
585
+ "no_test_android",
586
+ "no_test_ios",
587
+ "no_test_wasm",
588
+ ],
589
+ deps = [
590
+ ":config",
591
+ ":flag",
592
+ ":parse",
593
+ ":path_util",
594
+ ":program_name",
595
+ ":reflection",
596
+ ":usage",
597
+ ":usage_internal",
598
+ "//absl/strings",
599
+ "@com_google_googletest//:gtest",
600
+ ],
601
+ )
weight/_dep/abseil-cpp/absl/flags/CMakeLists.txt ADDED
@@ -0,0 +1,471 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #
2
+ # Copyright 2019 The Abseil Authors.
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # https://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+ #
16
+
17
+ # Internal-only target, do not depend on directly.
18
+ absl_cc_library(
19
+ NAME
20
+ flags_path_util
21
+ HDRS
22
+ "internal/path_util.h"
23
+ COPTS
24
+ ${ABSL_DEFAULT_COPTS}
25
+ LINKOPTS
26
+ ${ABSL_DEFAULT_LINKOPTS}
27
+ DEPS
28
+ absl::config
29
+ absl::strings
30
+ PUBLIC
31
+ )
32
+
33
+ # Internal-only target, do not depend on directly.
34
+ absl_cc_library(
35
+ NAME
36
+ flags_program_name
37
+ SRCS
38
+ "internal/program_name.cc"
39
+ HDRS
40
+ "internal/program_name.h"
41
+ COPTS
42
+ ${ABSL_DEFAULT_COPTS}
43
+ LINKOPTS
44
+ ${ABSL_DEFAULT_LINKOPTS}
45
+ DEPS
46
+ absl::config
47
+ absl::core_headers
48
+ absl::flags_path_util
49
+ absl::strings
50
+ absl::synchronization
51
+ PUBLIC
52
+ )
53
+
54
+ absl_cc_library(
55
+ NAME
56
+ flags_config
57
+ SRCS
58
+ "usage_config.cc"
59
+ HDRS
60
+ "config.h"
61
+ "usage_config.h"
62
+ COPTS
63
+ ${ABSL_DEFAULT_COPTS}
64
+ LINKOPTS
65
+ ${ABSL_DEFAULT_LINKOPTS}
66
+ DEPS
67
+ absl::config
68
+ absl::flags_path_util
69
+ absl::flags_program_name
70
+ absl::core_headers
71
+ absl::strings
72
+ absl::synchronization
73
+ )
74
+
75
+ absl_cc_library(
76
+ NAME
77
+ flags_marshalling
78
+ SRCS
79
+ "marshalling.cc"
80
+ HDRS
81
+ "marshalling.h"
82
+ COPTS
83
+ ${ABSL_DEFAULT_COPTS}
84
+ LINKOPTS
85
+ ${ABSL_DEFAULT_LINKOPTS}
86
+ DEPS
87
+ absl::config
88
+ absl::core_headers
89
+ absl::log_severity
90
+ absl::int128
91
+ absl::optional
92
+ absl::strings
93
+ absl::str_format
94
+ )
95
+
96
+ # Internal-only target, do not depend on directly.
97
+ absl_cc_library(
98
+ NAME
99
+ flags_commandlineflag_internal
100
+ SRCS
101
+ "internal/commandlineflag.cc"
102
+ HDRS
103
+ "internal/commandlineflag.h"
104
+ COPTS
105
+ ${ABSL_DEFAULT_COPTS}
106
+ LINKOPTS
107
+ ${ABSL_DEFAULT_LINKOPTS}
108
+ DEPS
109
+ absl::config
110
+ absl::dynamic_annotations
111
+ absl::fast_type_id
112
+ )
113
+
114
+ absl_cc_library(
115
+ NAME
116
+ flags_commandlineflag
117
+ SRCS
118
+ "commandlineflag.cc"
119
+ HDRS
120
+ "commandlineflag.h"
121
+ COPTS
122
+ ${ABSL_DEFAULT_COPTS}
123
+ LINKOPTS
124
+ ${ABSL_DEFAULT_LINKOPTS}
125
+ DEPS
126
+ absl::config
127
+ absl::fast_type_id
128
+ absl::flags_commandlineflag_internal
129
+ absl::optional
130
+ absl::strings
131
+ )
132
+
133
+ # Internal-only target, do not depend on directly.
134
+ absl_cc_library(
135
+ NAME
136
+ flags_private_handle_accessor
137
+ SRCS
138
+ "internal/private_handle_accessor.cc"
139
+ HDRS
140
+ "internal/private_handle_accessor.h"
141
+ COPTS
142
+ ${ABSL_DEFAULT_COPTS}
143
+ LINKOPTS
144
+ ${ABSL_DEFAULT_LINKOPTS}
145
+ DEPS
146
+ absl::config
147
+ absl::flags_commandlineflag
148
+ absl::flags_commandlineflag_internal
149
+ absl::strings
150
+ )
151
+
152
+ absl_cc_library(
153
+ NAME
154
+ flags_reflection
155
+ SRCS
156
+ "reflection.cc"
157
+ HDRS
158
+ "reflection.h"
159
+ "internal/registry.h"
160
+ COPTS
161
+ ${ABSL_DEFAULT_COPTS}
162
+ LINKOPTS
163
+ ${ABSL_DEFAULT_LINKOPTS}
164
+ DEPS
165
+ absl::config
166
+ absl::flags_commandlineflag
167
+ absl::flags_private_handle_accessor
168
+ absl::flags_config
169
+ absl::strings
170
+ absl::synchronization
171
+ absl::flat_hash_map
172
+ absl::no_destructor
173
+ )
174
+
175
+ # Internal-only target, do not depend on directly.
176
+ absl_cc_library(
177
+ NAME
178
+ flags_internal
179
+ SRCS
180
+ "internal/flag.cc"
181
+ HDRS
182
+ "internal/flag.h"
183
+ "internal/sequence_lock.h"
184
+ COPTS
185
+ ${ABSL_DEFAULT_COPTS}
186
+ LINKOPTS
187
+ ${ABSL_DEFAULT_LINKOPTS}
188
+ DEPS
189
+ absl::base
190
+ absl::config
191
+ absl::flags_commandlineflag
192
+ absl::flags_commandlineflag_internal
193
+ absl::flags_config
194
+ absl::flags_marshalling
195
+ absl::synchronization
196
+ absl::meta
197
+ absl::utility
198
+ PUBLIC
199
+ )
200
+
201
+ absl_cc_library(
202
+ NAME
203
+ flags
204
+ HDRS
205
+ "declare.h"
206
+ "flag.h"
207
+ COPTS
208
+ ${ABSL_DEFAULT_COPTS}
209
+ LINKOPTS
210
+ ${ABSL_DEFAULT_LINKOPTS}
211
+ DEPS
212
+ absl::config
213
+ absl::flags_commandlineflag
214
+ absl::flags_config
215
+ absl::flags_internal
216
+ absl::flags_reflection
217
+ absl::base
218
+ absl::core_headers
219
+ absl::strings
220
+ )
221
+
222
+ # Internal-only target, do not depend on directly.
223
+ absl_cc_library(
224
+ NAME
225
+ flags_usage_internal
226
+ SRCS
227
+ "internal/usage.cc"
228
+ HDRS
229
+ "internal/usage.h"
230
+ COPTS
231
+ ${ABSL_DEFAULT_COPTS}
232
+ LINKOPTS
233
+ ${ABSL_DEFAULT_LINKOPTS}
234
+ DEPS
235
+ absl::config
236
+ absl::flags_config
237
+ absl::flags
238
+ absl::flags_commandlineflag
239
+ absl::flags_internal
240
+ absl::flags_path_util
241
+ absl::flags_private_handle_accessor
242
+ absl::flags_program_name
243
+ absl::flags_reflection
244
+ absl::strings
245
+ absl::synchronization
246
+ )
247
+
248
+ absl_cc_library(
249
+ NAME
250
+ flags_usage
251
+ SRCS
252
+ "usage.cc"
253
+ HDRS
254
+ "usage.h"
255
+ COPTS
256
+ ${ABSL_DEFAULT_COPTS}
257
+ LINKOPTS
258
+ ${ABSL_DEFAULT_LINKOPTS}
259
+ DEPS
260
+ absl::config
261
+ absl::core_headers
262
+ absl::flags_usage_internal
263
+ absl::raw_logging_internal
264
+ absl::strings
265
+ absl::synchronization
266
+ )
267
+
268
+ absl_cc_library(
269
+ NAME
270
+ flags_parse
271
+ SRCS
272
+ "parse.cc"
273
+ HDRS
274
+ "internal/parse.h"
275
+ "parse.h"
276
+ COPTS
277
+ ${ABSL_DEFAULT_COPTS}
278
+ LINKOPTS
279
+ ${ABSL_DEFAULT_LINKOPTS}
280
+ DEPS
281
+ absl::algorithm_container
282
+ absl::config
283
+ absl::core_headers
284
+ absl::flags_config
285
+ absl::flags
286
+ absl::flags_commandlineflag
287
+ absl::flags_commandlineflag_internal
288
+ absl::flags_internal
289
+ absl::flags_private_handle_accessor
290
+ absl::flags_program_name
291
+ absl::flags_reflection
292
+ absl::flags_usage
293
+ absl::strings
294
+ absl::synchronization
295
+ )
296
+
297
+ ############################################################################
298
+ # Unit tests in alphabetical order.
299
+
300
+ absl_cc_test(
301
+ NAME
302
+ flags_commandlineflag_test
303
+ SRCS
304
+ "commandlineflag_test.cc"
305
+ COPTS
306
+ ${ABSL_TEST_COPTS}
307
+ DEPS
308
+ absl::flags
309
+ absl::flags_commandlineflag
310
+ absl::flags_commandlineflag_internal
311
+ absl::flags_config
312
+ absl::flags_private_handle_accessor
313
+ absl::flags_reflection
314
+ absl::memory
315
+ absl::strings
316
+ GTest::gtest_main
317
+ )
318
+
319
+ absl_cc_test(
320
+ NAME
321
+ flags_config_test
322
+ SRCS
323
+ "config_test.cc"
324
+ COPTS
325
+ ${ABSL_TEST_COPTS}
326
+ DEPS
327
+ absl::flags_config
328
+ GTest::gtest_main
329
+ )
330
+
331
+ absl_cc_test(
332
+ NAME
333
+ flags_flag_test
334
+ SRCS
335
+ "flag_test.cc"
336
+ "flag_test_defs.cc"
337
+ COPTS
338
+ ${ABSL_TEST_COPTS}
339
+ DEPS
340
+ absl::core_headers
341
+ absl::flags
342
+ absl::flags_config
343
+ absl::flags_internal
344
+ absl::flags_marshalling
345
+ absl::flags_reflection
346
+ absl::int128
347
+ absl::strings
348
+ absl::time
349
+ GTest::gtest_main
350
+ )
351
+
352
+ absl_cc_test(
353
+ NAME
354
+ flags_marshalling_test
355
+ SRCS
356
+ "marshalling_test.cc"
357
+ COPTS
358
+ ${ABSL_TEST_COPTS}
359
+ DEPS
360
+ absl::flags_marshalling
361
+ GTest::gtest_main
362
+ )
363
+
364
+ absl_cc_test(
365
+ NAME
366
+ flags_parse_test
367
+ SRCS
368
+ "parse_test.cc"
369
+ COPTS
370
+ ${ABSL_TEST_COPTS}
371
+ DEPS
372
+ absl::flags
373
+ absl::flags_parse
374
+ absl::flags_reflection
375
+ absl::flags_usage_internal
376
+ absl::log
377
+ absl::scoped_set_env
378
+ absl::span
379
+ absl::strings
380
+ GTest::gmock_main
381
+ )
382
+
383
+ absl_cc_test(
384
+ NAME
385
+ flags_path_util_test
386
+ SRCS
387
+ "internal/path_util_test.cc"
388
+ COPTS
389
+ ${ABSL_TEST_COPTS}
390
+ DEPS
391
+ absl::flags_path_util
392
+ GTest::gtest_main
393
+ )
394
+
395
+ absl_cc_test(
396
+ NAME
397
+ flags_program_name_test
398
+ SRCS
399
+ "internal/program_name_test.cc"
400
+ COPTS
401
+ ${ABSL_TEST_COPTS}
402
+ DEPS
403
+ absl::flags_program_name
404
+ absl::strings
405
+ GTest::gtest_main
406
+ )
407
+
408
+ absl_cc_test(
409
+ NAME
410
+ flags_reflection_test
411
+ SRCS
412
+ "reflection_test.cc"
413
+ COPTS
414
+ ${ABSL_TEST_COPTS}
415
+ DEPS
416
+ absl::flags_commandlineflag_internal
417
+ absl::flags
418
+ absl::flags_reflection
419
+ absl::flags_usage
420
+ absl::memory
421
+ absl::strings
422
+ GTest::gmock_main
423
+ )
424
+
425
+ absl_cc_test(
426
+ NAME
427
+ flags_sequence_lock_test
428
+ SRCS
429
+ "internal/sequence_lock_test.cc"
430
+ COPTS
431
+ ${ABSL_TEST_COPTS}
432
+ DEPS
433
+ absl::base
434
+ absl::flags_internal
435
+ absl::time
436
+ GTest::gmock_main
437
+ )
438
+
439
+ absl_cc_test(
440
+ NAME
441
+ flags_usage_config_test
442
+ SRCS
443
+ "usage_config_test.cc"
444
+ COPTS
445
+ ${ABSL_TEST_COPTS}
446
+ DEPS
447
+ absl::flags_config
448
+ absl::flags_path_util
449
+ absl::flags_program_name
450
+ absl::strings
451
+ GTest::gtest_main
452
+ )
453
+
454
+ absl_cc_test(
455
+ NAME
456
+ flags_usage_test
457
+ SRCS
458
+ "internal/usage_test.cc"
459
+ COPTS
460
+ ${ABSL_TEST_COPTS}
461
+ DEPS
462
+ absl::flags_config
463
+ absl::flags
464
+ absl::flags_path_util
465
+ absl::flags_program_name
466
+ absl::flags_parse
467
+ absl::flags_reflection
468
+ absl::flags_usage
469
+ absl::strings
470
+ GTest::gmock
471
+ )
weight/_dep/abseil-cpp/absl/flags/commandlineflag.cc ADDED
@@ -0,0 +1,34 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ //
2
+ // Copyright 2020 The Abseil Authors.
3
+ //
4
+ // Licensed under the Apache License, Version 2.0 (the "License");
5
+ // you may not use this file except in compliance with the License.
6
+ // You may obtain a copy of the License at
7
+ //
8
+ // https://www.apache.org/licenses/LICENSE-2.0
9
+ //
10
+ // Unless required by applicable law or agreed to in writing, software
11
+ // distributed under the License is distributed on an "AS IS" BASIS,
12
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ // See the License for the specific language governing permissions and
14
+ // limitations under the License.
15
+
16
+ #include "absl/flags/commandlineflag.h"
17
+
18
+ #include <string>
19
+
20
+ #include "absl/base/config.h"
21
+ #include "absl/flags/internal/commandlineflag.h"
22
+ #include "absl/strings/string_view.h"
23
+
24
+ namespace absl {
25
+ ABSL_NAMESPACE_BEGIN
26
+
27
+ bool CommandLineFlag::IsRetired() const { return false; }
28
+ bool CommandLineFlag::ParseFrom(absl::string_view value, std::string* error) {
29
+ return ParseFrom(value, flags_internal::SET_FLAGS_VALUE,
30
+ flags_internal::kProgrammaticChange, *error);
31
+ }
32
+
33
+ ABSL_NAMESPACE_END
34
+ } // namespace absl
weight/_dep/abseil-cpp/absl/flags/commandlineflag.h ADDED
@@ -0,0 +1,200 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ //
2
+ // Copyright 2020 The Abseil Authors.
3
+ //
4
+ // Licensed under the Apache License, Version 2.0 (the "License");
5
+ // you may not use this file except in compliance with the License.
6
+ // You may obtain a copy of the License at
7
+ //
8
+ // https://www.apache.org/licenses/LICENSE-2.0
9
+ //
10
+ // Unless required by applicable law or agreed to in writing, software
11
+ // distributed under the License is distributed on an "AS IS" BASIS,
12
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ // See the License for the specific language governing permissions and
14
+ // limitations under the License.
15
+ //
16
+ // -----------------------------------------------------------------------------
17
+ // File: commandlineflag.h
18
+ // -----------------------------------------------------------------------------
19
+ //
20
+ // This header file defines the `CommandLineFlag`, which acts as a type-erased
21
+ // handle for accessing metadata about the Abseil Flag in question.
22
+ //
23
+ // Because an actual Abseil flag is of an unspecified type, you should not
24
+ // manipulate or interact directly with objects of that type. Instead, use the
25
+ // CommandLineFlag type as an intermediary.
26
+ #ifndef ABSL_FLAGS_COMMANDLINEFLAG_H_
27
+ #define ABSL_FLAGS_COMMANDLINEFLAG_H_
28
+
29
+ #include <memory>
30
+ #include <string>
31
+
32
+ #include "absl/base/config.h"
33
+ #include "absl/base/internal/fast_type_id.h"
34
+ #include "absl/flags/internal/commandlineflag.h"
35
+ #include "absl/strings/string_view.h"
36
+ #include "absl/types/optional.h"
37
+
38
+ namespace absl {
39
+ ABSL_NAMESPACE_BEGIN
40
+ namespace flags_internal {
41
+ class PrivateHandleAccessor;
42
+ } // namespace flags_internal
43
+
44
+ // CommandLineFlag
45
+ //
46
+ // This type acts as a type-erased handle for an instance of an Abseil Flag and
47
+ // holds reflection information pertaining to that flag. Use CommandLineFlag to
48
+ // access a flag's name, location, help string etc.
49
+ //
50
+ // To obtain an absl::CommandLineFlag, invoke `absl::FindCommandLineFlag()`
51
+ // passing it the flag name string.
52
+ //
53
+ // Example:
54
+ //
55
+ // // Obtain reflection handle for a flag named "flagname".
56
+ // const absl::CommandLineFlag* my_flag_data =
57
+ // absl::FindCommandLineFlag("flagname");
58
+ //
59
+ // // Now you can get flag info from that reflection handle.
60
+ // std::string flag_location = my_flag_data->Filename();
61
+ // ...
62
+ class CommandLineFlag {
63
+ public:
64
+ constexpr CommandLineFlag() = default;
65
+
66
+ // Not copyable/assignable.
67
+ CommandLineFlag(const CommandLineFlag&) = delete;
68
+ CommandLineFlag& operator=(const CommandLineFlag&) = delete;
69
+
70
+ // absl::CommandLineFlag::IsOfType()
71
+ //
72
+ // Return true iff flag has type T.
73
+ template <typename T>
74
+ inline bool IsOfType() const {
75
+ return TypeId() == base_internal::FastTypeId<T>();
76
+ }
77
+
78
+ // absl::CommandLineFlag::TryGet()
79
+ //
80
+ // Attempts to retrieve the flag value. Returns value on success,
81
+ // absl::nullopt otherwise.
82
+ template <typename T>
83
+ absl::optional<T> TryGet() const {
84
+ if (IsRetired() || !IsOfType<T>()) {
85
+ return absl::nullopt;
86
+ }
87
+
88
+ // Implementation notes:
89
+ //
90
+ // We are wrapping a union around the value of `T` to serve three purposes:
91
+ //
92
+ // 1. `U.value` has correct size and alignment for a value of type `T`
93
+ // 2. The `U.value` constructor is not invoked since U's constructor does
94
+ // not do it explicitly.
95
+ // 3. The `U.value` destructor is invoked since U's destructor does it
96
+ // explicitly. This makes `U` a kind of RAII wrapper around non default
97
+ // constructible value of T, which is destructed when we leave the
98
+ // scope. We do need to destroy U.value, which is constructed by
99
+ // CommandLineFlag::Read even though we left it in a moved-from state
100
+ // after std::move.
101
+ //
102
+ // All of this serves to avoid requiring `T` being default constructible.
103
+ union U {
104
+ T value;
105
+ U() {}
106
+ ~U() { value.~T(); }
107
+ };
108
+ U u;
109
+
110
+ Read(&u.value);
111
+ // allow retired flags to be "read", so we can report invalid access.
112
+ if (IsRetired()) {
113
+ return absl::nullopt;
114
+ }
115
+ return std::move(u.value);
116
+ }
117
+
118
+ // absl::CommandLineFlag::Name()
119
+ //
120
+ // Returns name of this flag.
121
+ virtual absl::string_view Name() const = 0;
122
+
123
+ // absl::CommandLineFlag::Filename()
124
+ //
125
+ // Returns name of the file where this flag is defined.
126
+ virtual std::string Filename() const = 0;
127
+
128
+ // absl::CommandLineFlag::Help()
129
+ //
130
+ // Returns help message associated with this flag.
131
+ virtual std::string Help() const = 0;
132
+
133
+ // absl::CommandLineFlag::IsRetired()
134
+ //
135
+ // Returns true iff this object corresponds to retired flag.
136
+ virtual bool IsRetired() const;
137
+
138
+ // absl::CommandLineFlag::DefaultValue()
139
+ //
140
+ // Returns the default value for this flag.
141
+ virtual std::string DefaultValue() const = 0;
142
+
143
+ // absl::CommandLineFlag::CurrentValue()
144
+ //
145
+ // Returns the current value for this flag.
146
+ virtual std::string CurrentValue() const = 0;
147
+
148
+ // absl::CommandLineFlag::ParseFrom()
149
+ //
150
+ // Sets the value of the flag based on specified string `value`. If the flag
151
+ // was successfully set to new value, it returns true. Otherwise, sets `error`
152
+ // to indicate the error, leaves the flag unchanged, and returns false.
153
+ bool ParseFrom(absl::string_view value, std::string* error);
154
+
155
+ protected:
156
+ ~CommandLineFlag() = default;
157
+
158
+ private:
159
+ friend class flags_internal::PrivateHandleAccessor;
160
+
161
+ // Sets the value of the flag based on specified string `value`. If the flag
162
+ // was successfully set to new value, it returns true. Otherwise, sets `error`
163
+ // to indicate the error, leaves the flag unchanged, and returns false. There
164
+ // are three ways to set the flag's value:
165
+ // * Update the current flag value
166
+ // * Update the flag's default value
167
+ // * Update the current flag value if it was never set before
168
+ // The mode is selected based on `set_mode` parameter.
169
+ virtual bool ParseFrom(absl::string_view value,
170
+ flags_internal::FlagSettingMode set_mode,
171
+ flags_internal::ValueSource source,
172
+ std::string& error) = 0;
173
+
174
+ // Returns id of the flag's value type.
175
+ virtual flags_internal::FlagFastTypeId TypeId() const = 0;
176
+
177
+ // Interface to save flag to some persistent state. Returns current flag state
178
+ // or nullptr if flag does not support saving and restoring a state.
179
+ virtual std::unique_ptr<flags_internal::FlagStateInterface> SaveState() = 0;
180
+
181
+ // Copy-construct a new value of the flag's type in a memory referenced by
182
+ // the dst based on the current flag's value.
183
+ virtual void Read(void* dst) const = 0;
184
+
185
+ // To be deleted. Used to return true if flag's current value originated from
186
+ // command line.
187
+ virtual bool IsSpecifiedOnCommandLine() const = 0;
188
+
189
+ // Validates supplied value using validator or parseflag routine
190
+ virtual bool ValidateInputValue(absl::string_view value) const = 0;
191
+
192
+ // Checks that flags default value can be converted to string and back to the
193
+ // flag's value type.
194
+ virtual void CheckDefaultValueParsingRoundtrip() const = 0;
195
+ };
196
+
197
+ ABSL_NAMESPACE_END
198
+ } // namespace absl
199
+
200
+ #endif // ABSL_FLAGS_COMMANDLINEFLAG_H_
weight/_dep/abseil-cpp/absl/flags/commandlineflag_test.cc ADDED
@@ -0,0 +1,231 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ //
2
+ // Copyright 2019 The Abseil Authors.
3
+ //
4
+ // Licensed under the Apache License, Version 2.0 (the "License");
5
+ // you may not use this file except in compliance with the License.
6
+ // You may obtain a copy of the License at
7
+ //
8
+ // https://www.apache.org/licenses/LICENSE-2.0
9
+ //
10
+ // Unless required by applicable law or agreed to in writing, software
11
+ // distributed under the License is distributed on an "AS IS" BASIS,
12
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ // See the License for the specific language governing permissions and
14
+ // limitations under the License.
15
+
16
+ #include "absl/flags/commandlineflag.h"
17
+
18
+ #include <memory>
19
+ #include <string>
20
+
21
+ #include "gtest/gtest.h"
22
+ #include "absl/flags/flag.h"
23
+ #include "absl/flags/internal/commandlineflag.h"
24
+ #include "absl/flags/internal/private_handle_accessor.h"
25
+ #include "absl/flags/reflection.h"
26
+ #include "absl/flags/usage_config.h"
27
+ #include "absl/memory/memory.h"
28
+ #include "absl/strings/match.h"
29
+ #include "absl/strings/str_cat.h"
30
+ #include "absl/strings/string_view.h"
31
+
32
+ ABSL_FLAG(int, int_flag, 201, "int_flag help");
33
+ ABSL_FLAG(std::string, string_flag, "dflt",
34
+ absl::StrCat("string_flag", " help"));
35
+ ABSL_RETIRED_FLAG(bool, bool_retired_flag, false, "bool_retired_flag help");
36
+
37
+ // These are only used to test default values.
38
+ ABSL_FLAG(int, int_flag2, 201, "");
39
+ ABSL_FLAG(std::string, string_flag2, "dflt", "");
40
+
41
+ namespace {
42
+
43
+ namespace flags = absl::flags_internal;
44
+
45
+ class CommandLineFlagTest : public testing::Test {
46
+ protected:
47
+ static void SetUpTestSuite() {
48
+ // Install a function to normalize filenames before this test is run.
49
+ absl::FlagsUsageConfig default_config;
50
+ default_config.normalize_filename = &CommandLineFlagTest::NormalizeFileName;
51
+ absl::SetFlagsUsageConfig(default_config);
52
+ }
53
+
54
+ void SetUp() override { flag_saver_ = absl::make_unique<absl::FlagSaver>(); }
55
+ void TearDown() override { flag_saver_.reset(); }
56
+
57
+ private:
58
+ static std::string NormalizeFileName(absl::string_view fname) {
59
+ #ifdef _WIN32
60
+ std::string normalized(fname);
61
+ std::replace(normalized.begin(), normalized.end(), '\\', '/');
62
+ fname = normalized;
63
+ #endif
64
+ return std::string(fname);
65
+ }
66
+
67
+ std::unique_ptr<absl::FlagSaver> flag_saver_;
68
+ };
69
+
70
+ TEST_F(CommandLineFlagTest, TestAttributesAccessMethods) {
71
+ auto* flag_01 = absl::FindCommandLineFlag("int_flag");
72
+
73
+ ASSERT_TRUE(flag_01);
74
+ EXPECT_EQ(flag_01->Name(), "int_flag");
75
+ EXPECT_EQ(flag_01->Help(), "int_flag help");
76
+ EXPECT_TRUE(!flag_01->IsRetired());
77
+ EXPECT_TRUE(flag_01->IsOfType<int>());
78
+ EXPECT_TRUE(!flag_01->IsOfType<bool>());
79
+ EXPECT_TRUE(!flag_01->IsOfType<std::string>());
80
+ EXPECT_TRUE(absl::EndsWith(flag_01->Filename(),
81
+ "absl/flags/commandlineflag_test.cc"))
82
+ << flag_01->Filename();
83
+
84
+ auto* flag_02 = absl::FindCommandLineFlag("string_flag");
85
+
86
+ ASSERT_TRUE(flag_02);
87
+ EXPECT_EQ(flag_02->Name(), "string_flag");
88
+ EXPECT_EQ(flag_02->Help(), "string_flag help");
89
+ EXPECT_TRUE(!flag_02->IsRetired());
90
+ EXPECT_TRUE(flag_02->IsOfType<std::string>());
91
+ EXPECT_TRUE(!flag_02->IsOfType<bool>());
92
+ EXPECT_TRUE(!flag_02->IsOfType<int>());
93
+ EXPECT_TRUE(absl::EndsWith(flag_02->Filename(),
94
+ "absl/flags/commandlineflag_test.cc"))
95
+ << flag_02->Filename();
96
+ }
97
+
98
+ // --------------------------------------------------------------------
99
+
100
+ TEST_F(CommandLineFlagTest, TestValueAccessMethods) {
101
+ absl::SetFlag(&FLAGS_int_flag2, 301);
102
+ auto* flag_01 = absl::FindCommandLineFlag("int_flag2");
103
+
104
+ ASSERT_TRUE(flag_01);
105
+ EXPECT_EQ(flag_01->CurrentValue(), "301");
106
+ EXPECT_EQ(flag_01->DefaultValue(), "201");
107
+
108
+ absl::SetFlag(&FLAGS_string_flag2, "new_str_value");
109
+ auto* flag_02 = absl::FindCommandLineFlag("string_flag2");
110
+
111
+ ASSERT_TRUE(flag_02);
112
+ EXPECT_EQ(flag_02->CurrentValue(), "new_str_value");
113
+ EXPECT_EQ(flag_02->DefaultValue(), "dflt");
114
+ }
115
+
116
+ // --------------------------------------------------------------------
117
+
118
+ TEST_F(CommandLineFlagTest, TestParseFromCurrentValue) {
119
+ std::string err;
120
+
121
+ auto* flag_01 = absl::FindCommandLineFlag("int_flag");
122
+ EXPECT_FALSE(
123
+ flags::PrivateHandleAccessor::IsSpecifiedOnCommandLine(*flag_01));
124
+
125
+ EXPECT_TRUE(flags::PrivateHandleAccessor::ParseFrom(
126
+ *flag_01, "11", flags::SET_FLAGS_VALUE, flags::kProgrammaticChange, err));
127
+ EXPECT_EQ(absl::GetFlag(FLAGS_int_flag), 11);
128
+ EXPECT_FALSE(
129
+ flags::PrivateHandleAccessor::IsSpecifiedOnCommandLine(*flag_01));
130
+
131
+ EXPECT_TRUE(flags::PrivateHandleAccessor::ParseFrom(
132
+ *flag_01, "-123", flags::SET_FLAGS_VALUE, flags::kProgrammaticChange,
133
+ err));
134
+ EXPECT_EQ(absl::GetFlag(FLAGS_int_flag), -123);
135
+ EXPECT_FALSE(
136
+ flags::PrivateHandleAccessor::IsSpecifiedOnCommandLine(*flag_01));
137
+
138
+ EXPECT_TRUE(!flags::PrivateHandleAccessor::ParseFrom(
139
+ *flag_01, "xyz", flags::SET_FLAGS_VALUE, flags::kProgrammaticChange,
140
+ err));
141
+ EXPECT_EQ(absl::GetFlag(FLAGS_int_flag), -123);
142
+ EXPECT_EQ(err, "Illegal value 'xyz' specified for flag 'int_flag'");
143
+ EXPECT_FALSE(
144
+ flags::PrivateHandleAccessor::IsSpecifiedOnCommandLine(*flag_01));
145
+
146
+ EXPECT_TRUE(!flags::PrivateHandleAccessor::ParseFrom(
147
+ *flag_01, "A1", flags::SET_FLAGS_VALUE, flags::kProgrammaticChange, err));
148
+ EXPECT_EQ(absl::GetFlag(FLAGS_int_flag), -123);
149
+ EXPECT_EQ(err, "Illegal value 'A1' specified for flag 'int_flag'");
150
+ EXPECT_FALSE(
151
+ flags::PrivateHandleAccessor::IsSpecifiedOnCommandLine(*flag_01));
152
+
153
+ EXPECT_TRUE(flags::PrivateHandleAccessor::ParseFrom(
154
+ *flag_01, "0x10", flags::SET_FLAGS_VALUE, flags::kProgrammaticChange,
155
+ err));
156
+ EXPECT_EQ(absl::GetFlag(FLAGS_int_flag), 16);
157
+ EXPECT_FALSE(
158
+ flags::PrivateHandleAccessor::IsSpecifiedOnCommandLine(*flag_01));
159
+
160
+ EXPECT_TRUE(flags::PrivateHandleAccessor::ParseFrom(
161
+ *flag_01, "011", flags::SET_FLAGS_VALUE, flags::kCommandLine, err));
162
+ EXPECT_EQ(absl::GetFlag(FLAGS_int_flag), 11);
163
+ EXPECT_TRUE(flags::PrivateHandleAccessor::IsSpecifiedOnCommandLine(*flag_01));
164
+
165
+ EXPECT_TRUE(!flags::PrivateHandleAccessor::ParseFrom(
166
+ *flag_01, "", flags::SET_FLAGS_VALUE, flags::kProgrammaticChange, err));
167
+ EXPECT_EQ(err, "Illegal value '' specified for flag 'int_flag'");
168
+
169
+ auto* flag_02 = absl::FindCommandLineFlag("string_flag");
170
+ EXPECT_TRUE(flags::PrivateHandleAccessor::ParseFrom(
171
+ *flag_02, "xyz", flags::SET_FLAGS_VALUE, flags::kProgrammaticChange,
172
+ err));
173
+ EXPECT_EQ(absl::GetFlag(FLAGS_string_flag), "xyz");
174
+
175
+ EXPECT_TRUE(flags::PrivateHandleAccessor::ParseFrom(
176
+ *flag_02, "", flags::SET_FLAGS_VALUE, flags::kProgrammaticChange, err));
177
+ EXPECT_EQ(absl::GetFlag(FLAGS_string_flag), "");
178
+ }
179
+
180
+ // --------------------------------------------------------------------
181
+
182
+ TEST_F(CommandLineFlagTest, TestParseFromDefaultValue) {
183
+ std::string err;
184
+
185
+ auto* flag_01 = absl::FindCommandLineFlag("int_flag");
186
+
187
+ EXPECT_TRUE(flags::PrivateHandleAccessor::ParseFrom(
188
+ *flag_01, "111", flags::SET_FLAGS_DEFAULT, flags::kProgrammaticChange,
189
+ err));
190
+ EXPECT_EQ(flag_01->DefaultValue(), "111");
191
+
192
+ auto* flag_02 = absl::FindCommandLineFlag("string_flag");
193
+
194
+ EXPECT_TRUE(flags::PrivateHandleAccessor::ParseFrom(
195
+ *flag_02, "abc", flags::SET_FLAGS_DEFAULT, flags::kProgrammaticChange,
196
+ err));
197
+ EXPECT_EQ(flag_02->DefaultValue(), "abc");
198
+ }
199
+
200
+ // --------------------------------------------------------------------
201
+
202
+ TEST_F(CommandLineFlagTest, TestParseFromIfDefault) {
203
+ std::string err;
204
+
205
+ auto* flag_01 = absl::FindCommandLineFlag("int_flag");
206
+
207
+ EXPECT_TRUE(flags::PrivateHandleAccessor::ParseFrom(
208
+ *flag_01, "22", flags::SET_FLAG_IF_DEFAULT, flags::kProgrammaticChange,
209
+ err))
210
+ << err;
211
+ EXPECT_EQ(absl::GetFlag(FLAGS_int_flag), 22);
212
+
213
+ EXPECT_TRUE(flags::PrivateHandleAccessor::ParseFrom(
214
+ *flag_01, "33", flags::SET_FLAG_IF_DEFAULT, flags::kProgrammaticChange,
215
+ err));
216
+ EXPECT_EQ(absl::GetFlag(FLAGS_int_flag), 22);
217
+ // EXPECT_EQ(err, "ERROR: int_flag is already set to 22");
218
+
219
+ // Reset back to default value
220
+ EXPECT_TRUE(flags::PrivateHandleAccessor::ParseFrom(
221
+ *flag_01, "201", flags::SET_FLAGS_VALUE, flags::kProgrammaticChange,
222
+ err));
223
+
224
+ EXPECT_TRUE(flags::PrivateHandleAccessor::ParseFrom(
225
+ *flag_01, "33", flags::SET_FLAG_IF_DEFAULT, flags::kProgrammaticChange,
226
+ err));
227
+ EXPECT_EQ(absl::GetFlag(FLAGS_int_flag), 201);
228
+ // EXPECT_EQ(err, "ERROR: int_flag is already set to 201");
229
+ }
230
+
231
+ } // namespace
weight/_dep/abseil-cpp/absl/flags/config.h ADDED
@@ -0,0 +1,68 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ //
2
+ // Copyright 2019 The Abseil Authors.
3
+ //
4
+ // Licensed under the Apache License, Version 2.0 (the "License");
5
+ // you may not use this file except in compliance with the License.
6
+ // You may obtain a copy of the License at
7
+ //
8
+ // https://www.apache.org/licenses/LICENSE-2.0
9
+ //
10
+ // Unless required by applicable law or agreed to in writing, software
11
+ // distributed under the License is distributed on an "AS IS" BASIS,
12
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ // See the License for the specific language governing permissions and
14
+ // limitations under the License.
15
+
16
+ #ifndef ABSL_FLAGS_CONFIG_H_
17
+ #define ABSL_FLAGS_CONFIG_H_
18
+
19
+ // Determine if we should strip string literals from the Flag objects.
20
+ // By default we strip string literals on mobile platforms.
21
+ #if !defined(ABSL_FLAGS_STRIP_NAMES)
22
+
23
+ #if defined(__ANDROID__)
24
+ #define ABSL_FLAGS_STRIP_NAMES 1
25
+
26
+ #elif defined(__APPLE__)
27
+ #include <TargetConditionals.h>
28
+ #if defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE
29
+ #define ABSL_FLAGS_STRIP_NAMES 1
30
+ #elif defined(TARGET_OS_EMBEDDED) && TARGET_OS_EMBEDDED
31
+ #define ABSL_FLAGS_STRIP_NAMES 1
32
+ #endif // TARGET_OS_*
33
+ #endif
34
+
35
+ #endif // !defined(ABSL_FLAGS_STRIP_NAMES)
36
+
37
+ #if !defined(ABSL_FLAGS_STRIP_NAMES)
38
+ // If ABSL_FLAGS_STRIP_NAMES wasn't set on the command line or above,
39
+ // the default is not to strip.
40
+ #define ABSL_FLAGS_STRIP_NAMES 0
41
+ #endif
42
+
43
+ #if !defined(ABSL_FLAGS_STRIP_HELP)
44
+ // By default, if we strip names, we also strip help.
45
+ #define ABSL_FLAGS_STRIP_HELP ABSL_FLAGS_STRIP_NAMES
46
+ #endif
47
+
48
+ // These macros represent the "source of truth" for the list of supported
49
+ // built-in types.
50
+ #define ABSL_FLAGS_INTERNAL_BUILTIN_TYPES(A) \
51
+ A(bool, bool) \
52
+ A(short, short) \
53
+ A(unsigned short, unsigned_short) \
54
+ A(int, int) \
55
+ A(unsigned int, unsigned_int) \
56
+ A(long, long) \
57
+ A(unsigned long, unsigned_long) \
58
+ A(long long, long_long) \
59
+ A(unsigned long long, unsigned_long_long) \
60
+ A(double, double) \
61
+ A(float, float)
62
+
63
+ #define ABSL_FLAGS_INTERNAL_SUPPORTED_TYPES(A) \
64
+ ABSL_FLAGS_INTERNAL_BUILTIN_TYPES(A) \
65
+ A(std::string, std_string) \
66
+ A(std::vector<std::string>, std_vector_of_string)
67
+
68
+ #endif // ABSL_FLAGS_CONFIG_H_
weight/_dep/abseil-cpp/absl/flags/config_test.cc ADDED
@@ -0,0 +1,61 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Copyright 2019 The Abseil Authors.
2
+ //
3
+ // Licensed under the Apache License, Version 2.0 (the "License");
4
+ // you may not use this file except in compliance with the License.
5
+ // You may obtain a copy of the License at
6
+ //
7
+ // https://www.apache.org/licenses/LICENSE-2.0
8
+ //
9
+ // Unless required by applicable law or agreed to in writing, software
10
+ // distributed under the License is distributed on an "AS IS" BASIS,
11
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ // See the License for the specific language governing permissions and
13
+ // limitations under the License.
14
+
15
+ #include "absl/flags/config.h"
16
+
17
+ #ifdef __APPLE__
18
+ #include <TargetConditionals.h>
19
+ #endif
20
+
21
+ #include "gtest/gtest.h"
22
+
23
+ #ifndef ABSL_FLAGS_STRIP_NAMES
24
+ #error ABSL_FLAGS_STRIP_NAMES is not defined
25
+ #endif
26
+
27
+ #ifndef ABSL_FLAGS_STRIP_HELP
28
+ #error ABSL_FLAGS_STRIP_HELP is not defined
29
+ #endif
30
+
31
+ namespace {
32
+
33
+ // Test that ABSL_FLAGS_STRIP_NAMES and ABSL_FLAGS_STRIP_HELP are configured how
34
+ // we expect them to be configured by default. If you override this
35
+ // configuration, this test will fail, but the code should still be safe to use.
36
+ TEST(FlagsConfigTest, Test) {
37
+ #if defined(__ANDROID__)
38
+ EXPECT_EQ(ABSL_FLAGS_STRIP_NAMES, 1);
39
+ EXPECT_EQ(ABSL_FLAGS_STRIP_HELP, 1);
40
+ #elif defined(__myriad2__)
41
+ EXPECT_EQ(ABSL_FLAGS_STRIP_NAMES, 0);
42
+ EXPECT_EQ(ABSL_FLAGS_STRIP_HELP, 0);
43
+ #elif defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE
44
+ EXPECT_EQ(ABSL_FLAGS_STRIP_NAMES, 1);
45
+ EXPECT_EQ(ABSL_FLAGS_STRIP_HELP, 1);
46
+ #elif defined(TARGET_OS_EMBEDDED) && TARGET_OS_EMBEDDED
47
+ EXPECT_EQ(ABSL_FLAGS_STRIP_NAMES, 1);
48
+ EXPECT_EQ(ABSL_FLAGS_STRIP_HELP, 1);
49
+ #elif defined(__APPLE__)
50
+ EXPECT_EQ(ABSL_FLAGS_STRIP_NAMES, 0);
51
+ EXPECT_EQ(ABSL_FLAGS_STRIP_HELP, 0);
52
+ #elif defined(_WIN32)
53
+ EXPECT_EQ(ABSL_FLAGS_STRIP_NAMES, 0);
54
+ EXPECT_EQ(ABSL_FLAGS_STRIP_HELP, 0);
55
+ #elif defined(__linux__)
56
+ EXPECT_EQ(ABSL_FLAGS_STRIP_NAMES, 0);
57
+ EXPECT_EQ(ABSL_FLAGS_STRIP_HELP, 0);
58
+ #endif
59
+ }
60
+
61
+ } // namespace
weight/_dep/abseil-cpp/absl/flags/declare.h ADDED
@@ -0,0 +1,68 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ //
2
+ // Copyright 2019 The Abseil Authors.
3
+ //
4
+ // Licensed under the Apache License, Version 2.0 (the "License");
5
+ // you may not use this file except in compliance with the License.
6
+ // You may obtain a copy of the License at
7
+ //
8
+ // https://www.apache.org/licenses/LICENSE-2.0
9
+ //
10
+ // Unless required by applicable law or agreed to in writing, software
11
+ // distributed under the License is distributed on an "AS IS" BASIS,
12
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ // See the License for the specific language governing permissions and
14
+ // limitations under the License.
15
+ //
16
+ // -----------------------------------------------------------------------------
17
+ // File: declare.h
18
+ // -----------------------------------------------------------------------------
19
+ //
20
+ // This file defines the ABSL_DECLARE_FLAG macro, allowing you to declare an
21
+ // `absl::Flag` for use within a translation unit. You should place this
22
+ // declaration within the header file associated with the .cc file that defines
23
+ // and owns the `Flag`.
24
+
25
+ #ifndef ABSL_FLAGS_DECLARE_H_
26
+ #define ABSL_FLAGS_DECLARE_H_
27
+
28
+ #include "absl/base/config.h"
29
+
30
+ namespace absl {
31
+ ABSL_NAMESPACE_BEGIN
32
+ namespace flags_internal {
33
+
34
+ // absl::Flag<T> represents a flag of type 'T' created by ABSL_FLAG.
35
+ template <typename T>
36
+ class Flag;
37
+
38
+ } // namespace flags_internal
39
+
40
+ // Flag
41
+ //
42
+ // Forward declaration of the `absl::Flag` type for use in defining the macro.
43
+ template <typename T>
44
+ using Flag = flags_internal::Flag<T>;
45
+
46
+ ABSL_NAMESPACE_END
47
+ } // namespace absl
48
+
49
+ // ABSL_DECLARE_FLAG()
50
+ //
51
+ // This macro is a convenience for declaring use of an `absl::Flag` within a
52
+ // translation unit. This macro should be used within a header file to
53
+ // declare usage of the flag within any .cc file including that header file.
54
+ //
55
+ // The ABSL_DECLARE_FLAG(type, name) macro expands to:
56
+ //
57
+ // extern absl::Flag<type> FLAGS_name;
58
+ #define ABSL_DECLARE_FLAG(type, name) ABSL_DECLARE_FLAG_INTERNAL(type, name)
59
+
60
+ // Internal implementation of ABSL_DECLARE_FLAG to allow macro expansion of its
61
+ // arguments. Clients must use ABSL_DECLARE_FLAG instead.
62
+ #define ABSL_DECLARE_FLAG_INTERNAL(type, name) \
63
+ extern absl::Flag<type> FLAGS_##name; \
64
+ namespace absl /* block flags in namespaces */ {} \
65
+ /* second redeclaration is to allow applying attributes */ \
66
+ extern absl::Flag<type> FLAGS_##name
67
+
68
+ #endif // ABSL_FLAGS_DECLARE_H_
weight/_dep/abseil-cpp/absl/flags/flag.h ADDED
@@ -0,0 +1,301 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ //
2
+ // Copyright 2019 The Abseil Authors.
3
+ //
4
+ // Licensed under the Apache License, Version 2.0 (the "License");
5
+ // you may not use this file except in compliance with the License.
6
+ // You may obtain a copy of the License at
7
+ //
8
+ // https://www.apache.org/licenses/LICENSE-2.0
9
+ //
10
+ // Unless required by applicable law or agreed to in writing, software
11
+ // distributed under the License is distributed on an "AS IS" BASIS,
12
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ // See the License for the specific language governing permissions and
14
+ // limitations under the License.
15
+ //
16
+ // -----------------------------------------------------------------------------
17
+ // File: flag.h
18
+ // -----------------------------------------------------------------------------
19
+ //
20
+ // This header file defines the `absl::Flag<T>` type for holding command-line
21
+ // flag data, and abstractions to create, get and set such flag data.
22
+ //
23
+ // It is important to note that this type is **unspecified** (an implementation
24
+ // detail) and you do not construct or manipulate actual `absl::Flag<T>`
25
+ // instances. Instead, you define and declare flags using the
26
+ // `ABSL_FLAG()` and `ABSL_DECLARE_FLAG()` macros, and get and set flag values
27
+ // using the `absl::GetFlag()` and `absl::SetFlag()` functions.
28
+
29
+ #ifndef ABSL_FLAGS_FLAG_H_
30
+ #define ABSL_FLAGS_FLAG_H_
31
+
32
+ #include <string>
33
+ #include <type_traits>
34
+
35
+ #include "absl/base/attributes.h"
36
+ #include "absl/base/config.h"
37
+ #include "absl/base/optimization.h"
38
+ #include "absl/flags/config.h"
39
+ #include "absl/flags/internal/flag.h"
40
+ #include "absl/flags/internal/registry.h"
41
+ #include "absl/strings/string_view.h"
42
+
43
+ namespace absl {
44
+ ABSL_NAMESPACE_BEGIN
45
+
46
+ // Flag
47
+ //
48
+ // An `absl::Flag` holds a command-line flag value, providing a runtime
49
+ // parameter to a binary. Such flags should be defined in the global namespace
50
+ // and (preferably) in the module containing the binary's `main()` function.
51
+ //
52
+ // You should not construct and cannot use the `absl::Flag` type directly;
53
+ // instead, you should declare flags using the `ABSL_DECLARE_FLAG()` macro
54
+ // within a header file, and define your flag using `ABSL_FLAG()` within your
55
+ // header's associated `.cc` file. Such flags will be named `FLAGS_name`.
56
+ //
57
+ // Example:
58
+ //
59
+ // .h file
60
+ //
61
+ // // Declares usage of a flag named "FLAGS_count"
62
+ // ABSL_DECLARE_FLAG(int, count);
63
+ //
64
+ // .cc file
65
+ //
66
+ // // Defines a flag named "FLAGS_count" with a default `int` value of 0.
67
+ // ABSL_FLAG(int, count, 0, "Count of items to process");
68
+ //
69
+ // No public methods of `absl::Flag<T>` are part of the Abseil Flags API.
70
+ //
71
+ // For type support of Abseil Flags, see the marshalling.h header file, which
72
+ // discusses supported standard types, optional flags, and additional Abseil
73
+ // type support.
74
+
75
+ template <typename T>
76
+ using Flag = flags_internal::Flag<T>;
77
+
78
+ // GetFlag()
79
+ //
80
+ // Returns the value (of type `T`) of an `absl::Flag<T>` instance, by value. Do
81
+ // not construct an `absl::Flag<T>` directly and call `absl::GetFlag()`;
82
+ // instead, refer to flag's constructed variable name (e.g. `FLAGS_name`).
83
+ // Because this function returns by value and not by reference, it is
84
+ // thread-safe, but note that the operation may be expensive; as a result, avoid
85
+ // `absl::GetFlag()` within any tight loops.
86
+ //
87
+ // Example:
88
+ //
89
+ // // FLAGS_count is a Flag of type `int`
90
+ // int my_count = absl::GetFlag(FLAGS_count);
91
+ //
92
+ // // FLAGS_firstname is a Flag of type `std::string`
93
+ // std::string first_name = absl::GetFlag(FLAGS_firstname);
94
+ template <typename T>
95
+ ABSL_MUST_USE_RESULT T GetFlag(const absl::Flag<T>& flag) {
96
+ return flags_internal::FlagImplPeer::InvokeGet<T>(flag);
97
+ }
98
+
99
+ // SetFlag()
100
+ //
101
+ // Sets the value of an `absl::Flag` to the value `v`. Do not construct an
102
+ // `absl::Flag<T>` directly and call `absl::SetFlag()`; instead, use the
103
+ // flag's variable name (e.g. `FLAGS_name`). This function is
104
+ // thread-safe, but is potentially expensive. Avoid setting flags in general,
105
+ // but especially within performance-critical code.
106
+ template <typename T>
107
+ void SetFlag(absl::Flag<T>* flag, const T& v) {
108
+ flags_internal::FlagImplPeer::InvokeSet(*flag, v);
109
+ }
110
+
111
+ // Overload of `SetFlag()` to allow callers to pass in a value that is
112
+ // convertible to `T`. E.g., use this overload to pass a "const char*" when `T`
113
+ // is `std::string`.
114
+ template <typename T, typename V>
115
+ void SetFlag(absl::Flag<T>* flag, const V& v) {
116
+ T value(v);
117
+ flags_internal::FlagImplPeer::InvokeSet(*flag, value);
118
+ }
119
+
120
+ // GetFlagReflectionHandle()
121
+ //
122
+ // Returns the reflection handle corresponding to specified Abseil Flag
123
+ // instance. Use this handle to access flag's reflection information, like name,
124
+ // location, default value etc.
125
+ //
126
+ // Example:
127
+ //
128
+ // std::string = absl::GetFlagReflectionHandle(FLAGS_count).DefaultValue();
129
+
130
+ template <typename T>
131
+ const CommandLineFlag& GetFlagReflectionHandle(const absl::Flag<T>& f) {
132
+ return flags_internal::FlagImplPeer::InvokeReflect(f);
133
+ }
134
+
135
+ ABSL_NAMESPACE_END
136
+ } // namespace absl
137
+
138
+
139
+ // ABSL_FLAG()
140
+ //
141
+ // This macro defines an `absl::Flag<T>` instance of a specified type `T`:
142
+ //
143
+ // ABSL_FLAG(T, name, default_value, help);
144
+ //
145
+ // where:
146
+ //
147
+ // * `T` is a supported flag type (see the list of types in `marshalling.h`),
148
+ // * `name` designates the name of the flag (as a global variable
149
+ // `FLAGS_name`),
150
+ // * `default_value` is an expression holding the default value for this flag
151
+ // (which must be implicitly convertible to `T`),
152
+ // * `help` is the help text, which can also be an expression.
153
+ //
154
+ // This macro expands to a flag named 'FLAGS_name' of type 'T':
155
+ //
156
+ // absl::Flag<T> FLAGS_name = ...;
157
+ //
158
+ // Note that all such instances are created as global variables.
159
+ //
160
+ // For `ABSL_FLAG()` values that you wish to expose to other translation units,
161
+ // it is recommended to define those flags within the `.cc` file associated with
162
+ // the header where the flag is declared.
163
+ //
164
+ // Note: do not construct objects of type `absl::Flag<T>` directly. Only use the
165
+ // `ABSL_FLAG()` macro for such construction.
166
+ #define ABSL_FLAG(Type, name, default_value, help) \
167
+ ABSL_FLAG_IMPL(Type, name, default_value, help)
168
+
169
+ // ABSL_FLAG().OnUpdate()
170
+ //
171
+ // Defines a flag of type `T` with a callback attached:
172
+ //
173
+ // ABSL_FLAG(T, name, default_value, help).OnUpdate(callback);
174
+ //
175
+ // `callback` should be convertible to `void (*)()`.
176
+ //
177
+ // After any setting of the flag value, the callback will be called at least
178
+ // once. A rapid sequence of changes may be merged together into the same
179
+ // callback. No concurrent calls to the callback will be made for the same
180
+ // flag. Callbacks are allowed to read the current value of the flag but must
181
+ // not mutate that flag.
182
+ //
183
+ // The update mechanism guarantees "eventual consistency"; if the callback
184
+ // derives an auxiliary data structure from the flag value, it is guaranteed
185
+ // that eventually the flag value and the derived data structure will be
186
+ // consistent.
187
+ //
188
+ // Note: ABSL_FLAG.OnUpdate() does not have a public definition. Hence, this
189
+ // comment serves as its API documentation.
190
+
191
+ // -----------------------------------------------------------------------------
192
+ // Implementation details below this section
193
+ // -----------------------------------------------------------------------------
194
+
195
+ // ABSL_FLAG_IMPL macro definition conditional on ABSL_FLAGS_STRIP_NAMES
196
+ #define ABSL_FLAG_IMPL_FLAG_PTR(flag) flag
197
+ #define ABSL_FLAG_IMPL_HELP_ARG(name) \
198
+ absl::flags_internal::HelpArg<AbslFlagHelpGenFor##name>( \
199
+ FLAGS_help_storage_##name)
200
+ #define ABSL_FLAG_IMPL_DEFAULT_ARG(Type, name) \
201
+ absl::flags_internal::DefaultArg<Type, AbslFlagDefaultGenFor##name>(0)
202
+
203
+ #if ABSL_FLAGS_STRIP_NAMES
204
+ #define ABSL_FLAG_IMPL_FLAGNAME(txt) ""
205
+ #define ABSL_FLAG_IMPL_FILENAME() ""
206
+ #define ABSL_FLAG_IMPL_REGISTRAR(T, flag) \
207
+ absl::flags_internal::FlagRegistrar<T, false>(ABSL_FLAG_IMPL_FLAG_PTR(flag), \
208
+ nullptr)
209
+ #else
210
+ #define ABSL_FLAG_IMPL_FLAGNAME(txt) txt
211
+ #define ABSL_FLAG_IMPL_FILENAME() __FILE__
212
+ #define ABSL_FLAG_IMPL_REGISTRAR(T, flag) \
213
+ absl::flags_internal::FlagRegistrar<T, true>(ABSL_FLAG_IMPL_FLAG_PTR(flag), \
214
+ __FILE__)
215
+ #endif
216
+
217
+ // ABSL_FLAG_IMPL macro definition conditional on ABSL_FLAGS_STRIP_HELP
218
+
219
+ #if ABSL_FLAGS_STRIP_HELP
220
+ #define ABSL_FLAG_IMPL_FLAGHELP(txt) absl::flags_internal::kStrippedFlagHelp
221
+ #else
222
+ #define ABSL_FLAG_IMPL_FLAGHELP(txt) txt
223
+ #endif
224
+
225
+ // AbslFlagHelpGenFor##name is used to encapsulate both immediate (method Const)
226
+ // and lazy (method NonConst) evaluation of help message expression. We choose
227
+ // between the two via the call to HelpArg in absl::Flag instantiation below.
228
+ // If help message expression is constexpr evaluable compiler will optimize
229
+ // away this whole struct.
230
+ // TODO(rogeeff): place these generated structs into local namespace and apply
231
+ // ABSL_INTERNAL_UNIQUE_SHORT_NAME.
232
+ // TODO(rogeeff): Apply __attribute__((nodebug)) to FLAGS_help_storage_##name
233
+ #define ABSL_FLAG_IMPL_DECLARE_HELP_WRAPPER(name, txt) \
234
+ struct AbslFlagHelpGenFor##name { \
235
+ /* The expression is run in the caller as part of the */ \
236
+ /* default value argument. That keeps temporaries alive */ \
237
+ /* long enough for NonConst to work correctly. */ \
238
+ static constexpr absl::string_view Value( \
239
+ absl::string_view absl_flag_help = ABSL_FLAG_IMPL_FLAGHELP(txt)) { \
240
+ return absl_flag_help; \
241
+ } \
242
+ static std::string NonConst() { return std::string(Value()); } \
243
+ }; \
244
+ constexpr auto FLAGS_help_storage_##name ABSL_INTERNAL_UNIQUE_SMALL_NAME() \
245
+ ABSL_ATTRIBUTE_SECTION_VARIABLE(flags_help_cold) = \
246
+ absl::flags_internal::HelpStringAsArray<AbslFlagHelpGenFor##name>( \
247
+ 0);
248
+
249
+ #define ABSL_FLAG_IMPL_DECLARE_DEF_VAL_WRAPPER(name, Type, default_value) \
250
+ struct AbslFlagDefaultGenFor##name { \
251
+ Type value = absl::flags_internal::InitDefaultValue<Type>(default_value); \
252
+ static void Gen(void* absl_flag_default_loc) { \
253
+ new (absl_flag_default_loc) Type(AbslFlagDefaultGenFor##name{}.value); \
254
+ } \
255
+ };
256
+
257
+ // ABSL_FLAG_IMPL
258
+ //
259
+ // Note: Name of registrar object is not arbitrary. It is used to "grab"
260
+ // global name for FLAGS_no<flag_name> symbol, thus preventing the possibility
261
+ // of defining two flags with names foo and nofoo.
262
+ #define ABSL_FLAG_IMPL(Type, name, default_value, help) \
263
+ extern ::absl::Flag<Type> FLAGS_##name; \
264
+ namespace absl /* block flags in namespaces */ {} \
265
+ ABSL_FLAG_IMPL_DECLARE_DEF_VAL_WRAPPER(name, Type, default_value) \
266
+ ABSL_FLAG_IMPL_DECLARE_HELP_WRAPPER(name, help) \
267
+ ABSL_CONST_INIT absl::Flag<Type> FLAGS_##name{ \
268
+ ABSL_FLAG_IMPL_FLAGNAME(#name), ABSL_FLAG_IMPL_FILENAME(), \
269
+ ABSL_FLAG_IMPL_HELP_ARG(name), ABSL_FLAG_IMPL_DEFAULT_ARG(Type, name)}; \
270
+ extern absl::flags_internal::FlagRegistrarEmpty FLAGS_no##name; \
271
+ absl::flags_internal::FlagRegistrarEmpty FLAGS_no##name = \
272
+ ABSL_FLAG_IMPL_REGISTRAR(Type, FLAGS_##name)
273
+
274
+ // ABSL_RETIRED_FLAG
275
+ //
276
+ // Designates the flag (which is usually pre-existing) as "retired." A retired
277
+ // flag is a flag that is now unused by the program, but may still be passed on
278
+ // the command line, usually by production scripts. A retired flag is ignored
279
+ // and code can't access it at runtime.
280
+ //
281
+ // This macro registers a retired flag with given name and type, with a name
282
+ // identical to the name of the original flag you are retiring. The retired
283
+ // flag's type can change over time, so that you can retire code to support a
284
+ // custom flag type.
285
+ //
286
+ // This macro has the same signature as `ABSL_FLAG`. To retire a flag, simply
287
+ // replace an `ABSL_FLAG` definition with `ABSL_RETIRED_FLAG`, leaving the
288
+ // arguments unchanged (unless of course you actually want to retire the flag
289
+ // type at this time as well).
290
+ //
291
+ // `default_value` is only used as a double check on the type. `explanation` is
292
+ // unused.
293
+ // TODO(rogeeff): replace RETIRED_FLAGS with FLAGS once forward declarations of
294
+ // retired flags are cleaned up.
295
+ #define ABSL_RETIRED_FLAG(type, name, default_value, explanation) \
296
+ static absl::flags_internal::RetiredFlag<type> RETIRED_FLAGS_##name; \
297
+ ABSL_ATTRIBUTE_UNUSED static const auto RETIRED_FLAGS_REG_##name = \
298
+ (RETIRED_FLAGS_##name.Retire(#name), \
299
+ ::absl::flags_internal::FlagRegistrarEmpty{})
300
+
301
+ #endif // ABSL_FLAGS_FLAG_H_
weight/_dep/abseil-cpp/absl/flags/flag_benchmark.cc ADDED
@@ -0,0 +1,251 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ //
2
+ // Copyright 2020 The Abseil Authors.
3
+ //
4
+ // Licensed under the Apache License, Version 2.0 (the "License");
5
+ // you may not use this file except in compliance with the License.
6
+ // You may obtain a copy of the License at
7
+ //
8
+ // https://www.apache.org/licenses/LICENSE-2.0
9
+ //
10
+ // Unless required by applicable law or agreed to in writing, software
11
+ // distributed under the License is distributed on an "AS IS" BASIS,
12
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ // See the License for the specific language governing permissions and
14
+ // limitations under the License.
15
+
16
+ #include <stdint.h>
17
+
18
+ #include <string>
19
+ #include <vector>
20
+
21
+ #include "absl/flags/flag.h"
22
+ #include "absl/flags/marshalling.h"
23
+ #include "absl/flags/parse.h"
24
+ #include "absl/flags/reflection.h"
25
+ #include "absl/strings/string_view.h"
26
+ #include "absl/time/time.h"
27
+ #include "absl/types/optional.h"
28
+ #include "benchmark/benchmark.h"
29
+
30
+ namespace {
31
+ using String = std::string;
32
+ using VectorOfStrings = std::vector<std::string>;
33
+ using AbslDuration = absl::Duration;
34
+
35
+ // We do not want to take over marshalling for the types absl::optional<int>,
36
+ // absl::optional<std::string> which we do not own. Instead we introduce unique
37
+ // "aliases" to these types, which we do.
38
+ using AbslOptionalInt = absl::optional<int>;
39
+ struct OptionalInt : AbslOptionalInt {
40
+ using AbslOptionalInt::AbslOptionalInt;
41
+ };
42
+ // Next two functions represent Abseil Flags marshalling for OptionalInt.
43
+ bool AbslParseFlag(absl::string_view src, OptionalInt* flag,
44
+ std::string* error) {
45
+ int val;
46
+ if (src.empty())
47
+ flag->reset();
48
+ else if (!absl::ParseFlag(src, &val, error))
49
+ return false;
50
+ *flag = val;
51
+ return true;
52
+ }
53
+ std::string AbslUnparseFlag(const OptionalInt& flag) {
54
+ return !flag ? "" : absl::UnparseFlag(*flag);
55
+ }
56
+
57
+ using AbslOptionalString = absl::optional<std::string>;
58
+ struct OptionalString : AbslOptionalString {
59
+ using AbslOptionalString::AbslOptionalString;
60
+ };
61
+ // Next two functions represent Abseil Flags marshalling for OptionalString.
62
+ bool AbslParseFlag(absl::string_view src, OptionalString* flag,
63
+ std::string* error) {
64
+ std::string val;
65
+ if (src.empty())
66
+ flag->reset();
67
+ else if (!absl::ParseFlag(src, &val, error))
68
+ return false;
69
+ *flag = val;
70
+ return true;
71
+ }
72
+ std::string AbslUnparseFlag(const OptionalString& flag) {
73
+ return !flag ? "" : absl::UnparseFlag(*flag);
74
+ }
75
+
76
+ struct UDT {
77
+ UDT() = default;
78
+ UDT(const UDT&) {}
79
+ UDT& operator=(const UDT&) { return *this; }
80
+ };
81
+ // Next two functions represent Abseil Flags marshalling for UDT.
82
+ bool AbslParseFlag(absl::string_view, UDT*, std::string*) { return true; }
83
+ std::string AbslUnparseFlag(const UDT&) { return ""; }
84
+
85
+ } // namespace
86
+
87
+ #define BENCHMARKED_TYPES(A) \
88
+ A(bool) \
89
+ A(int16_t) \
90
+ A(uint16_t) \
91
+ A(int32_t) \
92
+ A(uint32_t) \
93
+ A(int64_t) \
94
+ A(uint64_t) \
95
+ A(double) \
96
+ A(float) \
97
+ A(String) \
98
+ A(VectorOfStrings) \
99
+ A(OptionalInt) \
100
+ A(OptionalString) \
101
+ A(AbslDuration) \
102
+ A(UDT)
103
+
104
+ #define REPLICATE_0(A, T, name, index) A(T, name, index)
105
+ #define REPLICATE_1(A, T, name, index) \
106
+ REPLICATE_0(A, T, name, index##0) REPLICATE_0(A, T, name, index##1)
107
+ #define REPLICATE_2(A, T, name, index) \
108
+ REPLICATE_1(A, T, name, index##0) REPLICATE_1(A, T, name, index##1)
109
+ #define REPLICATE_3(A, T, name, index) \
110
+ REPLICATE_2(A, T, name, index##0) REPLICATE_2(A, T, name, index##1)
111
+ #define REPLICATE_4(A, T, name, index) \
112
+ REPLICATE_3(A, T, name, index##0) REPLICATE_3(A, T, name, index##1)
113
+ #define REPLICATE_5(A, T, name, index) \
114
+ REPLICATE_4(A, T, name, index##0) REPLICATE_4(A, T, name, index##1)
115
+ #define REPLICATE_6(A, T, name, index) \
116
+ REPLICATE_5(A, T, name, index##0) REPLICATE_5(A, T, name, index##1)
117
+ #define REPLICATE_7(A, T, name, index) \
118
+ REPLICATE_6(A, T, name, index##0) REPLICATE_6(A, T, name, index##1)
119
+ #define REPLICATE_8(A, T, name, index) \
120
+ REPLICATE_7(A, T, name, index##0) REPLICATE_7(A, T, name, index##1)
121
+ #define REPLICATE_9(A, T, name, index) \
122
+ REPLICATE_8(A, T, name, index##0) REPLICATE_8(A, T, name, index##1)
123
+ #if defined(_MSC_VER)
124
+ #define REPLICATE(A, T, name) \
125
+ REPLICATE_7(A, T, name, 0) REPLICATE_7(A, T, name, 1)
126
+ #define SINGLE_FLAG(T) FLAGS_##T##_flag_00000000
127
+ #else
128
+ #define REPLICATE(A, T, name) \
129
+ REPLICATE_9(A, T, name, 0) REPLICATE_9(A, T, name, 1)
130
+ #define SINGLE_FLAG(T) FLAGS_##T##_flag_0000000000
131
+ #endif
132
+ #define REPLICATE_ALL(A, T, name) \
133
+ REPLICATE_9(A, T, name, 0) REPLICATE_9(A, T, name, 1)
134
+
135
+ #define COUNT(T, name, index) +1
136
+ constexpr size_t kNumFlags = 0 REPLICATE(COUNT, _, _);
137
+
138
+ #if defined(__clang__) && defined(__linux__)
139
+ // Force the flags used for benchmarks into a separate ELF section.
140
+ // This ensures that, even when other parts of the code might change size,
141
+ // the layout of the flags across cachelines is kept constant. This makes
142
+ // benchmark results more reproducible across unrelated code changes.
143
+ #pragma clang section data = ".benchmark_flags"
144
+ #endif
145
+ #define DEFINE_FLAG(T, name, index) ABSL_FLAG(T, name##_##index, {}, "");
146
+ #define FLAG_DEF(T) REPLICATE(DEFINE_FLAG, T, T##_flag);
147
+ BENCHMARKED_TYPES(FLAG_DEF)
148
+ #if defined(__clang__) && defined(__linux__)
149
+ #pragma clang section data = ""
150
+ #endif
151
+ // Register thousands of flags to bloat up the size of the registry.
152
+ // This mimics real life production binaries.
153
+ #define BLOAT_FLAG(_unused1, _unused2, index) \
154
+ ABSL_FLAG(int, bloat_flag_##index, 0, "");
155
+ REPLICATE_ALL(BLOAT_FLAG, _, _)
156
+
157
+ namespace {
158
+
159
+ #define FLAG_PTR(T, name, index) &FLAGS_##name##_##index,
160
+ #define FLAG_PTR_ARR(T) \
161
+ static constexpr absl::Flag<T>* FlagPtrs_##T[] = { \
162
+ REPLICATE(FLAG_PTR, T, T##_flag)};
163
+ BENCHMARKED_TYPES(FLAG_PTR_ARR)
164
+
165
+ #define BM_SingleGetFlag(T) \
166
+ void BM_SingleGetFlag_##T(benchmark::State& state) { \
167
+ for (auto _ : state) { \
168
+ benchmark::DoNotOptimize(absl::GetFlag(SINGLE_FLAG(T))); \
169
+ } \
170
+ } \
171
+ BENCHMARK(BM_SingleGetFlag_##T)->ThreadRange(1, 16);
172
+
173
+ BENCHMARKED_TYPES(BM_SingleGetFlag)
174
+
175
+ template <typename T>
176
+ struct Accumulator {
177
+ using type = T;
178
+ };
179
+ template <>
180
+ struct Accumulator<String> {
181
+ using type = size_t;
182
+ };
183
+ template <>
184
+ struct Accumulator<VectorOfStrings> {
185
+ using type = size_t;
186
+ };
187
+ template <>
188
+ struct Accumulator<OptionalInt> {
189
+ using type = bool;
190
+ };
191
+ template <>
192
+ struct Accumulator<OptionalString> {
193
+ using type = bool;
194
+ };
195
+ template <>
196
+ struct Accumulator<UDT> {
197
+ using type = bool;
198
+ };
199
+
200
+ template <typename T>
201
+ void Accumulate(typename Accumulator<T>::type& a, const T& f) {
202
+ a += f;
203
+ }
204
+ void Accumulate(bool& a, bool f) { a = a || f; }
205
+ void Accumulate(size_t& a, const std::string& f) { a += f.size(); }
206
+ void Accumulate(size_t& a, const std::vector<std::string>& f) { a += f.size(); }
207
+ void Accumulate(bool& a, const OptionalInt& f) { a |= f.has_value(); }
208
+ void Accumulate(bool& a, const OptionalString& f) { a |= f.has_value(); }
209
+ void Accumulate(bool& a, const UDT& f) {
210
+ a |= reinterpret_cast<int64_t>(&f) & 0x1;
211
+ }
212
+
213
+ #define BM_ManyGetFlag(T) \
214
+ void BM_ManyGetFlag_##T(benchmark::State& state) { \
215
+ Accumulator<T>::type res = {}; \
216
+ while (state.KeepRunningBatch(kNumFlags)) { \
217
+ for (auto* flag_ptr : FlagPtrs_##T) { \
218
+ Accumulate(res, absl::GetFlag(*flag_ptr)); \
219
+ } \
220
+ } \
221
+ benchmark::DoNotOptimize(res); \
222
+ } \
223
+ BENCHMARK(BM_ManyGetFlag_##T)->ThreadRange(1, 8);
224
+
225
+ BENCHMARKED_TYPES(BM_ManyGetFlag)
226
+
227
+ void BM_ThreadedFindCommandLineFlag(benchmark::State& state) {
228
+ char dummy[] = "dummy";
229
+ char* argv[] = {dummy};
230
+ // We need to ensure that flags have been parsed. That is where the registry
231
+ // is finalized.
232
+ absl::ParseCommandLine(1, argv);
233
+
234
+ while (state.KeepRunningBatch(kNumFlags)) {
235
+ for (auto* flag_ptr : FlagPtrs_bool) {
236
+ benchmark::DoNotOptimize(absl::FindCommandLineFlag(flag_ptr->Name()));
237
+ }
238
+ }
239
+ }
240
+ BENCHMARK(BM_ThreadedFindCommandLineFlag)->ThreadRange(1, 16);
241
+
242
+ } // namespace
243
+
244
+ #ifdef __llvm__
245
+ // To view disassembly use: gdb ${BINARY} -batch -ex "disassemble /s $FUNC"
246
+ #define InvokeGetFlag(T) \
247
+ T AbslInvokeGetFlag##T() { return absl::GetFlag(SINGLE_FLAG(T)); } \
248
+ int odr##T = (benchmark::DoNotOptimize(AbslInvokeGetFlag##T), 1);
249
+
250
+ BENCHMARKED_TYPES(InvokeGetFlag)
251
+ #endif // __llvm__
weight/_dep/abseil-cpp/absl/flags/flag_benchmark.lds ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* This linker script forces the flags used by flags_benchmark
2
+ * into a separate page-aligned section. This isn't necessary for
3
+ * correctness but ensures that the benchmark results are more
4
+ * reproducible across unrelated code changes.
5
+ */
6
+ SECTIONS {
7
+ .benchmark_flags : {
8
+ . = ALIGN(0x1000);
9
+ * (.benchmark_flags);
10
+ }
11
+ }
12
+
13
+ INSERT AFTER .data
weight/_dep/abseil-cpp/absl/flags/flag_test.cc ADDED
@@ -0,0 +1,1217 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ //
2
+ // Copyright 2019 The Abseil Authors.
3
+ //
4
+ // Licensed under the Apache License, Version 2.0 (the "License");
5
+ // you may not use this file except in compliance with the License.
6
+ // You may obtain a copy of the License at
7
+ //
8
+ // https://www.apache.org/licenses/LICENSE-2.0
9
+ //
10
+ // Unless required by applicable law or agreed to in writing, software
11
+ // distributed under the License is distributed on an "AS IS" BASIS,
12
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ // See the License for the specific language governing permissions and
14
+ // limitations under the License.
15
+
16
+ #include "absl/flags/flag.h"
17
+
18
+ #include <stddef.h>
19
+ #include <stdint.h>
20
+
21
+ #include <atomic>
22
+ #include <cmath>
23
+ #include <new>
24
+ #include <string>
25
+ #include <thread> // NOLINT
26
+ #include <vector>
27
+
28
+ #include "gtest/gtest.h"
29
+ #include "absl/base/attributes.h"
30
+ #include "absl/base/macros.h"
31
+ #include "absl/flags/config.h"
32
+ #include "absl/flags/declare.h"
33
+ #include "absl/flags/internal/flag.h"
34
+ #include "absl/flags/marshalling.h"
35
+ #include "absl/flags/reflection.h"
36
+ #include "absl/flags/usage_config.h"
37
+ #include "absl/numeric/int128.h"
38
+ #include "absl/strings/match.h"
39
+ #include "absl/strings/numbers.h"
40
+ #include "absl/strings/str_cat.h"
41
+ #include "absl/strings/str_split.h"
42
+ #include "absl/strings/string_view.h"
43
+ #include "absl/time/time.h"
44
+
45
+ ABSL_DECLARE_FLAG(int64_t, mistyped_int_flag);
46
+ ABSL_DECLARE_FLAG(std::vector<std::string>, mistyped_string_flag);
47
+
48
+ namespace {
49
+
50
+ namespace flags = absl::flags_internal;
51
+
52
+ std::string TestHelpMsg() { return "dynamic help"; }
53
+ #if defined(_MSC_VER) && !defined(__clang__)
54
+ std::string TestLiteralHelpMsg() { return "literal help"; }
55
+ #endif
56
+ template <typename T>
57
+ void TestMakeDflt(void* dst) {
58
+ new (dst) T{};
59
+ }
60
+ void TestCallback() {}
61
+
62
+ struct UDT {
63
+ UDT() = default;
64
+ UDT(const UDT&) = default;
65
+ UDT& operator=(const UDT&) = default;
66
+ };
67
+ bool AbslParseFlag(absl::string_view, UDT*, std::string*) { return true; }
68
+ std::string AbslUnparseFlag(const UDT&) { return ""; }
69
+
70
+ class FlagTest : public testing::Test {
71
+ protected:
72
+ static void SetUpTestSuite() {
73
+ // Install a function to normalize filenames before this test is run.
74
+ absl::FlagsUsageConfig default_config;
75
+ default_config.normalize_filename = &FlagTest::NormalizeFileName;
76
+ absl::SetFlagsUsageConfig(default_config);
77
+ }
78
+
79
+ private:
80
+ static std::string NormalizeFileName(absl::string_view fname) {
81
+ #ifdef _WIN32
82
+ std::string normalized(fname);
83
+ std::replace(normalized.begin(), normalized.end(), '\\', '/');
84
+ fname = normalized;
85
+ #endif
86
+ return std::string(fname);
87
+ }
88
+ absl::FlagSaver flag_saver_;
89
+ };
90
+
91
+ struct S1 {
92
+ S1() = default;
93
+ S1(const S1&) = default;
94
+ int32_t f1;
95
+ int64_t f2;
96
+ };
97
+
98
+ struct S2 {
99
+ S2() = default;
100
+ S2(const S2&) = default;
101
+ int64_t f1;
102
+ double f2;
103
+ };
104
+
105
+ TEST_F(FlagTest, Traits) {
106
+ EXPECT_EQ(flags::StorageKind<int>(),
107
+ flags::FlagValueStorageKind::kValueAndInitBit);
108
+ EXPECT_EQ(flags::StorageKind<bool>(),
109
+ flags::FlagValueStorageKind::kValueAndInitBit);
110
+ EXPECT_EQ(flags::StorageKind<double>(),
111
+ flags::FlagValueStorageKind::kOneWordAtomic);
112
+ EXPECT_EQ(flags::StorageKind<int64_t>(),
113
+ flags::FlagValueStorageKind::kOneWordAtomic);
114
+
115
+ EXPECT_EQ(flags::StorageKind<S1>(),
116
+ flags::FlagValueStorageKind::kSequenceLocked);
117
+ EXPECT_EQ(flags::StorageKind<S2>(),
118
+ flags::FlagValueStorageKind::kSequenceLocked);
119
+ // Make sure absl::Duration uses the sequence-locked code path. MSVC 2015
120
+ // doesn't consider absl::Duration to be trivially-copyable so we just
121
+ // restrict this to clang as it seems to be a well-behaved compiler.
122
+ #ifdef __clang__
123
+ EXPECT_EQ(flags::StorageKind<absl::Duration>(),
124
+ flags::FlagValueStorageKind::kSequenceLocked);
125
+ #endif
126
+
127
+ EXPECT_EQ(flags::StorageKind<std::string>(),
128
+ flags::FlagValueStorageKind::kAlignedBuffer);
129
+ EXPECT_EQ(flags::StorageKind<std::vector<std::string>>(),
130
+ flags::FlagValueStorageKind::kAlignedBuffer);
131
+
132
+ EXPECT_EQ(flags::StorageKind<absl::int128>(),
133
+ flags::FlagValueStorageKind::kSequenceLocked);
134
+ EXPECT_EQ(flags::StorageKind<absl::uint128>(),
135
+ flags::FlagValueStorageKind::kSequenceLocked);
136
+ }
137
+
138
+ // --------------------------------------------------------------------
139
+
140
+ constexpr flags::FlagHelpArg help_arg{flags::FlagHelpMsg("literal help"),
141
+ flags::FlagHelpKind::kLiteral};
142
+
143
+ using String = std::string;
144
+ using int128 = absl::int128;
145
+ using uint128 = absl::uint128;
146
+
147
+ #define DEFINE_CONSTRUCTED_FLAG(T, dflt, dflt_kind) \
148
+ constexpr flags::FlagDefaultArg f1default##T{ \
149
+ flags::FlagDefaultSrc{dflt}, flags::FlagDefaultKind::dflt_kind}; \
150
+ constexpr absl::Flag<T> f1##T{"f1", "file", help_arg, f1default##T}; \
151
+ ABSL_CONST_INIT absl::Flag<T> f2##T { \
152
+ "f2", "file", \
153
+ {flags::FlagHelpMsg(&TestHelpMsg), flags::FlagHelpKind::kGenFunc}, \
154
+ flags::FlagDefaultArg { \
155
+ flags::FlagDefaultSrc(&TestMakeDflt<T>), \
156
+ flags::FlagDefaultKind::kGenFunc \
157
+ } \
158
+ }
159
+
160
+ DEFINE_CONSTRUCTED_FLAG(bool, true, kOneWord);
161
+ DEFINE_CONSTRUCTED_FLAG(int16_t, 1, kOneWord);
162
+ DEFINE_CONSTRUCTED_FLAG(uint16_t, 2, kOneWord);
163
+ DEFINE_CONSTRUCTED_FLAG(int32_t, 3, kOneWord);
164
+ DEFINE_CONSTRUCTED_FLAG(uint32_t, 4, kOneWord);
165
+ DEFINE_CONSTRUCTED_FLAG(int64_t, 5, kOneWord);
166
+ DEFINE_CONSTRUCTED_FLAG(uint64_t, 6, kOneWord);
167
+ DEFINE_CONSTRUCTED_FLAG(float, 7.8, kOneWord);
168
+ DEFINE_CONSTRUCTED_FLAG(double, 9.10, kOneWord);
169
+ DEFINE_CONSTRUCTED_FLAG(String, &TestMakeDflt<String>, kGenFunc);
170
+ DEFINE_CONSTRUCTED_FLAG(UDT, &TestMakeDflt<UDT>, kGenFunc);
171
+ DEFINE_CONSTRUCTED_FLAG(int128, 13, kGenFunc);
172
+ DEFINE_CONSTRUCTED_FLAG(uint128, 14, kGenFunc);
173
+
174
+ template <typename T>
175
+ bool TestConstructionFor(const absl::Flag<T>& f1, absl::Flag<T>& f2) {
176
+ EXPECT_EQ(absl::GetFlagReflectionHandle(f1).Name(), "f1");
177
+ EXPECT_EQ(absl::GetFlagReflectionHandle(f1).Help(), "literal help");
178
+ EXPECT_EQ(absl::GetFlagReflectionHandle(f1).Filename(), "file");
179
+
180
+ flags::FlagRegistrar<T, false>(ABSL_FLAG_IMPL_FLAG_PTR(f2), nullptr)
181
+ .OnUpdate(TestCallback);
182
+
183
+ EXPECT_EQ(absl::GetFlagReflectionHandle(f2).Name(), "f2");
184
+ EXPECT_EQ(absl::GetFlagReflectionHandle(f2).Help(), "dynamic help");
185
+ EXPECT_EQ(absl::GetFlagReflectionHandle(f2).Filename(), "file");
186
+
187
+ return true;
188
+ }
189
+
190
+ #define TEST_CONSTRUCTED_FLAG(T) TestConstructionFor(f1##T, f2##T);
191
+
192
+ TEST_F(FlagTest, TestConstruction) {
193
+ TEST_CONSTRUCTED_FLAG(bool);
194
+ TEST_CONSTRUCTED_FLAG(int16_t);
195
+ TEST_CONSTRUCTED_FLAG(uint16_t);
196
+ TEST_CONSTRUCTED_FLAG(int32_t);
197
+ TEST_CONSTRUCTED_FLAG(uint32_t);
198
+ TEST_CONSTRUCTED_FLAG(int64_t);
199
+ TEST_CONSTRUCTED_FLAG(uint64_t);
200
+ TEST_CONSTRUCTED_FLAG(float);
201
+ TEST_CONSTRUCTED_FLAG(double);
202
+ TEST_CONSTRUCTED_FLAG(String);
203
+ TEST_CONSTRUCTED_FLAG(UDT);
204
+ TEST_CONSTRUCTED_FLAG(int128);
205
+ TEST_CONSTRUCTED_FLAG(uint128);
206
+ }
207
+
208
+ // --------------------------------------------------------------------
209
+
210
+ } // namespace
211
+
212
+ ABSL_DECLARE_FLAG(bool, test_flag_01);
213
+ ABSL_DECLARE_FLAG(int, test_flag_02);
214
+ ABSL_DECLARE_FLAG(int16_t, test_flag_03);
215
+ ABSL_DECLARE_FLAG(uint16_t, test_flag_04);
216
+ ABSL_DECLARE_FLAG(int32_t, test_flag_05);
217
+ ABSL_DECLARE_FLAG(uint32_t, test_flag_06);
218
+ ABSL_DECLARE_FLAG(int64_t, test_flag_07);
219
+ ABSL_DECLARE_FLAG(uint64_t, test_flag_08);
220
+ ABSL_DECLARE_FLAG(double, test_flag_09);
221
+ ABSL_DECLARE_FLAG(float, test_flag_10);
222
+ ABSL_DECLARE_FLAG(std::string, test_flag_11);
223
+ ABSL_DECLARE_FLAG(absl::Duration, test_flag_12);
224
+ ABSL_DECLARE_FLAG(absl::int128, test_flag_13);
225
+ ABSL_DECLARE_FLAG(absl::uint128, test_flag_14);
226
+
227
+ namespace {
228
+
229
+ #if !ABSL_FLAGS_STRIP_NAMES
230
+
231
+ TEST_F(FlagTest, TestFlagDeclaration) {
232
+ // test that we can access flag objects.
233
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_01).Name(),
234
+ "test_flag_01");
235
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_02).Name(),
236
+ "test_flag_02");
237
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_03).Name(),
238
+ "test_flag_03");
239
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_04).Name(),
240
+ "test_flag_04");
241
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_05).Name(),
242
+ "test_flag_05");
243
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_06).Name(),
244
+ "test_flag_06");
245
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_07).Name(),
246
+ "test_flag_07");
247
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_08).Name(),
248
+ "test_flag_08");
249
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_09).Name(),
250
+ "test_flag_09");
251
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_10).Name(),
252
+ "test_flag_10");
253
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_11).Name(),
254
+ "test_flag_11");
255
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_12).Name(),
256
+ "test_flag_12");
257
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_13).Name(),
258
+ "test_flag_13");
259
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_14).Name(),
260
+ "test_flag_14");
261
+ }
262
+ #endif // !ABSL_FLAGS_STRIP_NAMES
263
+
264
+ // --------------------------------------------------------------------
265
+
266
+ } // namespace
267
+
268
+ ABSL_FLAG(bool, test_flag_01, true, "test flag 01");
269
+ ABSL_FLAG(int, test_flag_02, 1234, "test flag 02");
270
+ ABSL_FLAG(int16_t, test_flag_03, -34, "test flag 03");
271
+ ABSL_FLAG(uint16_t, test_flag_04, 189, "test flag 04");
272
+ ABSL_FLAG(int32_t, test_flag_05, 10765, "test flag 05");
273
+ ABSL_FLAG(uint32_t, test_flag_06, 40000, "test flag 06");
274
+ ABSL_FLAG(int64_t, test_flag_07, -1234567, "test flag 07");
275
+ ABSL_FLAG(uint64_t, test_flag_08, 9876543, "test flag 08");
276
+ ABSL_FLAG(double, test_flag_09, -9.876e-50, "test flag 09");
277
+ ABSL_FLAG(float, test_flag_10, 1.234e12f, "test flag 10");
278
+ ABSL_FLAG(std::string, test_flag_11, "", "test flag 11");
279
+ ABSL_FLAG(absl::Duration, test_flag_12, absl::Minutes(10), "test flag 12");
280
+ ABSL_FLAG(absl::int128, test_flag_13, absl::MakeInt128(-1, 0), "test flag 13");
281
+ ABSL_FLAG(absl::uint128, test_flag_14, absl::MakeUint128(0, 0xFFFAAABBBCCCDDD),
282
+ "test flag 14");
283
+
284
+ namespace {
285
+
286
+ #if !ABSL_FLAGS_STRIP_NAMES
287
+ TEST_F(FlagTest, TestFlagDefinition) {
288
+ absl::string_view expected_file_name = "absl/flags/flag_test.cc";
289
+
290
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_01).Name(),
291
+ "test_flag_01");
292
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_01).Help(),
293
+ "test flag 01");
294
+ EXPECT_TRUE(absl::EndsWith(
295
+ absl::GetFlagReflectionHandle(FLAGS_test_flag_01).Filename(),
296
+ expected_file_name))
297
+ << absl::GetFlagReflectionHandle(FLAGS_test_flag_01).Filename();
298
+
299
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_02).Name(),
300
+ "test_flag_02");
301
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_02).Help(),
302
+ "test flag 02");
303
+ EXPECT_TRUE(absl::EndsWith(
304
+ absl::GetFlagReflectionHandle(FLAGS_test_flag_02).Filename(),
305
+ expected_file_name))
306
+ << absl::GetFlagReflectionHandle(FLAGS_test_flag_02).Filename();
307
+
308
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_03).Name(),
309
+ "test_flag_03");
310
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_03).Help(),
311
+ "test flag 03");
312
+ EXPECT_TRUE(absl::EndsWith(
313
+ absl::GetFlagReflectionHandle(FLAGS_test_flag_03).Filename(),
314
+ expected_file_name))
315
+ << absl::GetFlagReflectionHandle(FLAGS_test_flag_03).Filename();
316
+
317
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_04).Name(),
318
+ "test_flag_04");
319
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_04).Help(),
320
+ "test flag 04");
321
+ EXPECT_TRUE(absl::EndsWith(
322
+ absl::GetFlagReflectionHandle(FLAGS_test_flag_04).Filename(),
323
+ expected_file_name))
324
+ << absl::GetFlagReflectionHandle(FLAGS_test_flag_04).Filename();
325
+
326
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_05).Name(),
327
+ "test_flag_05");
328
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_05).Help(),
329
+ "test flag 05");
330
+ EXPECT_TRUE(absl::EndsWith(
331
+ absl::GetFlagReflectionHandle(FLAGS_test_flag_05).Filename(),
332
+ expected_file_name))
333
+ << absl::GetFlagReflectionHandle(FLAGS_test_flag_05).Filename();
334
+
335
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_06).Name(),
336
+ "test_flag_06");
337
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_06).Help(),
338
+ "test flag 06");
339
+ EXPECT_TRUE(absl::EndsWith(
340
+ absl::GetFlagReflectionHandle(FLAGS_test_flag_06).Filename(),
341
+ expected_file_name))
342
+ << absl::GetFlagReflectionHandle(FLAGS_test_flag_06).Filename();
343
+
344
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_07).Name(),
345
+ "test_flag_07");
346
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_07).Help(),
347
+ "test flag 07");
348
+ EXPECT_TRUE(absl::EndsWith(
349
+ absl::GetFlagReflectionHandle(FLAGS_test_flag_07).Filename(),
350
+ expected_file_name))
351
+ << absl::GetFlagReflectionHandle(FLAGS_test_flag_07).Filename();
352
+
353
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_08).Name(),
354
+ "test_flag_08");
355
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_08).Help(),
356
+ "test flag 08");
357
+ EXPECT_TRUE(absl::EndsWith(
358
+ absl::GetFlagReflectionHandle(FLAGS_test_flag_08).Filename(),
359
+ expected_file_name))
360
+ << absl::GetFlagReflectionHandle(FLAGS_test_flag_08).Filename();
361
+
362
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_09).Name(),
363
+ "test_flag_09");
364
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_09).Help(),
365
+ "test flag 09");
366
+ EXPECT_TRUE(absl::EndsWith(
367
+ absl::GetFlagReflectionHandle(FLAGS_test_flag_09).Filename(),
368
+ expected_file_name))
369
+ << absl::GetFlagReflectionHandle(FLAGS_test_flag_09).Filename();
370
+
371
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_10).Name(),
372
+ "test_flag_10");
373
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_10).Help(),
374
+ "test flag 10");
375
+ EXPECT_TRUE(absl::EndsWith(
376
+ absl::GetFlagReflectionHandle(FLAGS_test_flag_10).Filename(),
377
+ expected_file_name))
378
+ << absl::GetFlagReflectionHandle(FLAGS_test_flag_10).Filename();
379
+
380
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_11).Name(),
381
+ "test_flag_11");
382
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_11).Help(),
383
+ "test flag 11");
384
+ EXPECT_TRUE(absl::EndsWith(
385
+ absl::GetFlagReflectionHandle(FLAGS_test_flag_11).Filename(),
386
+ expected_file_name))
387
+ << absl::GetFlagReflectionHandle(FLAGS_test_flag_11).Filename();
388
+
389
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_12).Name(),
390
+ "test_flag_12");
391
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_12).Help(),
392
+ "test flag 12");
393
+ EXPECT_TRUE(absl::EndsWith(
394
+ absl::GetFlagReflectionHandle(FLAGS_test_flag_12).Filename(),
395
+ expected_file_name))
396
+ << absl::GetFlagReflectionHandle(FLAGS_test_flag_12).Filename();
397
+
398
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_13).Name(),
399
+ "test_flag_13");
400
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_13).Help(),
401
+ "test flag 13");
402
+ EXPECT_TRUE(absl::EndsWith(
403
+ absl::GetFlagReflectionHandle(FLAGS_test_flag_13).Filename(),
404
+ expected_file_name))
405
+ << absl::GetFlagReflectionHandle(FLAGS_test_flag_13).Filename();
406
+
407
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_14).Name(),
408
+ "test_flag_14");
409
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_14).Help(),
410
+ "test flag 14");
411
+ EXPECT_TRUE(absl::EndsWith(
412
+ absl::GetFlagReflectionHandle(FLAGS_test_flag_14).Filename(),
413
+ expected_file_name))
414
+ << absl::GetFlagReflectionHandle(FLAGS_test_flag_14).Filename();
415
+ }
416
+ #endif // !ABSL_FLAGS_STRIP_NAMES
417
+
418
+ // --------------------------------------------------------------------
419
+
420
+ TEST_F(FlagTest, TestDefault) {
421
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_01).DefaultValue(),
422
+ "true");
423
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_02).DefaultValue(),
424
+ "1234");
425
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_03).DefaultValue(),
426
+ "-34");
427
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_04).DefaultValue(),
428
+ "189");
429
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_05).DefaultValue(),
430
+ "10765");
431
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_06).DefaultValue(),
432
+ "40000");
433
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_07).DefaultValue(),
434
+ "-1234567");
435
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_08).DefaultValue(),
436
+ "9876543");
437
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_09).DefaultValue(),
438
+ "-9.876e-50");
439
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_10).DefaultValue(),
440
+ "1.234e+12");
441
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_11).DefaultValue(),
442
+ "");
443
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_12).DefaultValue(),
444
+ "10m");
445
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_13).DefaultValue(),
446
+ "-18446744073709551616");
447
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_14).DefaultValue(),
448
+ "1152827684197027293");
449
+
450
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_01).CurrentValue(),
451
+ "true");
452
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_02).CurrentValue(),
453
+ "1234");
454
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_03).CurrentValue(),
455
+ "-34");
456
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_04).CurrentValue(),
457
+ "189");
458
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_05).CurrentValue(),
459
+ "10765");
460
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_06).CurrentValue(),
461
+ "40000");
462
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_07).CurrentValue(),
463
+ "-1234567");
464
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_08).CurrentValue(),
465
+ "9876543");
466
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_09).CurrentValue(),
467
+ "-9.876e-50");
468
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_10).CurrentValue(),
469
+ "1.234e+12");
470
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_11).CurrentValue(),
471
+ "");
472
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_12).CurrentValue(),
473
+ "10m");
474
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_13).CurrentValue(),
475
+ "-18446744073709551616");
476
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_14).CurrentValue(),
477
+ "1152827684197027293");
478
+
479
+ EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_01), true);
480
+ EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_02), 1234);
481
+ EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_03), -34);
482
+ EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_04), 189);
483
+ EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_05), 10765);
484
+ EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_06), 40000);
485
+ EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_07), -1234567);
486
+ EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_08), 9876543);
487
+ EXPECT_NEAR(absl::GetFlag(FLAGS_test_flag_09), -9.876e-50, 1e-55);
488
+ EXPECT_NEAR(absl::GetFlag(FLAGS_test_flag_10), 1.234e12f, 1e5f);
489
+ EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_11), "");
490
+ EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_12), absl::Minutes(10));
491
+ EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_13), absl::MakeInt128(-1, 0));
492
+ EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_14),
493
+ absl::MakeUint128(0, 0xFFFAAABBBCCCDDD));
494
+ }
495
+
496
+ // --------------------------------------------------------------------
497
+
498
+ struct NonTriviallyCopyableAggregate {
499
+ NonTriviallyCopyableAggregate() = default;
500
+ NonTriviallyCopyableAggregate(const NonTriviallyCopyableAggregate& rhs)
501
+ : value(rhs.value) {}
502
+ NonTriviallyCopyableAggregate& operator=(
503
+ const NonTriviallyCopyableAggregate& rhs) {
504
+ value = rhs.value;
505
+ return *this;
506
+ }
507
+
508
+ int value;
509
+ };
510
+ bool AbslParseFlag(absl::string_view src, NonTriviallyCopyableAggregate* f,
511
+ std::string* e) {
512
+ return absl::ParseFlag(src, &f->value, e);
513
+ }
514
+ std::string AbslUnparseFlag(const NonTriviallyCopyableAggregate& ntc) {
515
+ return absl::StrCat(ntc.value);
516
+ }
517
+
518
+ bool operator==(const NonTriviallyCopyableAggregate& ntc1,
519
+ const NonTriviallyCopyableAggregate& ntc2) {
520
+ return ntc1.value == ntc2.value;
521
+ }
522
+
523
+ } // namespace
524
+
525
+ ABSL_FLAG(bool, test_flag_eb_01, {}, "");
526
+ ABSL_FLAG(int32_t, test_flag_eb_02, {}, "");
527
+ ABSL_FLAG(int64_t, test_flag_eb_03, {}, "");
528
+ ABSL_FLAG(double, test_flag_eb_04, {}, "");
529
+ ABSL_FLAG(std::string, test_flag_eb_05, {}, "");
530
+ ABSL_FLAG(NonTriviallyCopyableAggregate, test_flag_eb_06, {}, "");
531
+
532
+ namespace {
533
+
534
+ TEST_F(FlagTest, TestEmptyBracesDefault) {
535
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_eb_01).DefaultValue(),
536
+ "false");
537
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_eb_02).DefaultValue(),
538
+ "0");
539
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_eb_03).DefaultValue(),
540
+ "0");
541
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_eb_04).DefaultValue(),
542
+ "0");
543
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_eb_05).DefaultValue(),
544
+ "");
545
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_eb_06).DefaultValue(),
546
+ "0");
547
+
548
+ EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_eb_01), false);
549
+ EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_eb_02), 0);
550
+ EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_eb_03), 0);
551
+ EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_eb_04), 0.0);
552
+ EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_eb_05), "");
553
+ EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_eb_06),
554
+ NonTriviallyCopyableAggregate{});
555
+ }
556
+
557
+ // --------------------------------------------------------------------
558
+
559
+ TEST_F(FlagTest, TestGetSet) {
560
+ absl::SetFlag(&FLAGS_test_flag_01, false);
561
+ EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_01), false);
562
+
563
+ absl::SetFlag(&FLAGS_test_flag_02, 321);
564
+ EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_02), 321);
565
+
566
+ absl::SetFlag(&FLAGS_test_flag_03, 67);
567
+ EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_03), 67);
568
+
569
+ absl::SetFlag(&FLAGS_test_flag_04, 1);
570
+ EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_04), 1);
571
+
572
+ absl::SetFlag(&FLAGS_test_flag_05, -908);
573
+ EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_05), -908);
574
+
575
+ absl::SetFlag(&FLAGS_test_flag_06, 4001);
576
+ EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_06), 4001);
577
+
578
+ absl::SetFlag(&FLAGS_test_flag_07, -23456);
579
+ EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_07), -23456);
580
+
581
+ absl::SetFlag(&FLAGS_test_flag_08, 975310);
582
+ EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_08), 975310);
583
+
584
+ absl::SetFlag(&FLAGS_test_flag_09, 1.00001);
585
+ EXPECT_NEAR(absl::GetFlag(FLAGS_test_flag_09), 1.00001, 1e-10);
586
+
587
+ absl::SetFlag(&FLAGS_test_flag_10, -3.54f);
588
+ EXPECT_NEAR(absl::GetFlag(FLAGS_test_flag_10), -3.54f, 1e-6f);
589
+
590
+ absl::SetFlag(&FLAGS_test_flag_11, "asdf");
591
+ EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_11), "asdf");
592
+
593
+ absl::SetFlag(&FLAGS_test_flag_12, absl::Seconds(110));
594
+ EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_12), absl::Seconds(110));
595
+
596
+ absl::SetFlag(&FLAGS_test_flag_13, absl::MakeInt128(-1, 0));
597
+ EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_13), absl::MakeInt128(-1, 0));
598
+
599
+ absl::SetFlag(&FLAGS_test_flag_14, absl::MakeUint128(0, 0xFFFAAABBBCCCDDD));
600
+ EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_14),
601
+ absl::MakeUint128(0, 0xFFFAAABBBCCCDDD));
602
+ }
603
+
604
+ // --------------------------------------------------------------------
605
+
606
+ TEST_F(FlagTest, TestGetViaReflection) {
607
+ auto* handle = absl::FindCommandLineFlag("test_flag_01");
608
+ EXPECT_EQ(*handle->TryGet<bool>(), true);
609
+ handle = absl::FindCommandLineFlag("test_flag_02");
610
+ EXPECT_EQ(*handle->TryGet<int>(), 1234);
611
+ handle = absl::FindCommandLineFlag("test_flag_03");
612
+ EXPECT_EQ(*handle->TryGet<int16_t>(), -34);
613
+ handle = absl::FindCommandLineFlag("test_flag_04");
614
+ EXPECT_EQ(*handle->TryGet<uint16_t>(), 189);
615
+ handle = absl::FindCommandLineFlag("test_flag_05");
616
+ EXPECT_EQ(*handle->TryGet<int32_t>(), 10765);
617
+ handle = absl::FindCommandLineFlag("test_flag_06");
618
+ EXPECT_EQ(*handle->TryGet<uint32_t>(), 40000);
619
+ handle = absl::FindCommandLineFlag("test_flag_07");
620
+ EXPECT_EQ(*handle->TryGet<int64_t>(), -1234567);
621
+ handle = absl::FindCommandLineFlag("test_flag_08");
622
+ EXPECT_EQ(*handle->TryGet<uint64_t>(), 9876543);
623
+ handle = absl::FindCommandLineFlag("test_flag_09");
624
+ EXPECT_NEAR(*handle->TryGet<double>(), -9.876e-50, 1e-55);
625
+ handle = absl::FindCommandLineFlag("test_flag_10");
626
+ EXPECT_NEAR(*handle->TryGet<float>(), 1.234e12f, 1e5f);
627
+ handle = absl::FindCommandLineFlag("test_flag_11");
628
+ EXPECT_EQ(*handle->TryGet<std::string>(), "");
629
+ handle = absl::FindCommandLineFlag("test_flag_12");
630
+ EXPECT_EQ(*handle->TryGet<absl::Duration>(), absl::Minutes(10));
631
+ handle = absl::FindCommandLineFlag("test_flag_13");
632
+ EXPECT_EQ(*handle->TryGet<absl::int128>(), absl::MakeInt128(-1, 0));
633
+ handle = absl::FindCommandLineFlag("test_flag_14");
634
+ EXPECT_EQ(*handle->TryGet<absl::uint128>(),
635
+ absl::MakeUint128(0, 0xFFFAAABBBCCCDDD));
636
+ }
637
+
638
+ // --------------------------------------------------------------------
639
+
640
+ TEST_F(FlagTest, ConcurrentSetAndGet) {
641
+ static constexpr int kNumThreads = 8;
642
+ // Two arbitrary durations. One thread will concurrently flip the flag
643
+ // between these two values, while the other threads read it and verify
644
+ // that no other value is seen.
645
+ static const absl::Duration kValidDurations[] = {
646
+ absl::Seconds(int64_t{0x6cebf47a9b68c802}) + absl::Nanoseconds(229702057),
647
+ absl::Seconds(int64_t{0x23fec0307e4e9d3}) + absl::Nanoseconds(44555374)};
648
+ absl::SetFlag(&FLAGS_test_flag_12, kValidDurations[0]);
649
+
650
+ std::atomic<bool> stop{false};
651
+ std::vector<std::thread> threads;
652
+ auto* handle = absl::FindCommandLineFlag("test_flag_12");
653
+ for (int i = 0; i < kNumThreads; i++) {
654
+ threads.emplace_back([&]() {
655
+ while (!stop.load(std::memory_order_relaxed)) {
656
+ // Try loading the flag both directly and via a reflection
657
+ // handle.
658
+ absl::Duration v = absl::GetFlag(FLAGS_test_flag_12);
659
+ EXPECT_TRUE(v == kValidDurations[0] || v == kValidDurations[1]);
660
+ v = *handle->TryGet<absl::Duration>();
661
+ EXPECT_TRUE(v == kValidDurations[0] || v == kValidDurations[1]);
662
+ }
663
+ });
664
+ }
665
+ absl::Time end_time = absl::Now() + absl::Seconds(1);
666
+ int i = 0;
667
+ while (absl::Now() < end_time) {
668
+ absl::SetFlag(&FLAGS_test_flag_12,
669
+ kValidDurations[i++ % ABSL_ARRAYSIZE(kValidDurations)]);
670
+ }
671
+ stop.store(true, std::memory_order_relaxed);
672
+ for (auto& t : threads) t.join();
673
+ }
674
+
675
+ // --------------------------------------------------------------------
676
+
677
+ int GetDflt1() { return 1; }
678
+
679
+ } // namespace
680
+
681
+ ABSL_FLAG(int, test_int_flag_with_non_const_default, GetDflt1(),
682
+ "test int flag non const default");
683
+ ABSL_FLAG(std::string, test_string_flag_with_non_const_default,
684
+ absl::StrCat("AAA", "BBB"), "test string flag non const default");
685
+
686
+ namespace {
687
+
688
+ TEST_F(FlagTest, TestNonConstexprDefault) {
689
+ EXPECT_EQ(absl::GetFlag(FLAGS_test_int_flag_with_non_const_default), 1);
690
+ EXPECT_EQ(absl::GetFlag(FLAGS_test_string_flag_with_non_const_default),
691
+ "AAABBB");
692
+ }
693
+
694
+ // --------------------------------------------------------------------
695
+
696
+ } // namespace
697
+
698
+ ABSL_FLAG(bool, test_flag_with_non_const_help, true,
699
+ absl::StrCat("test ", "flag ", "non const help"));
700
+
701
+ namespace {
702
+
703
+ #if !ABSL_FLAGS_STRIP_HELP
704
+ TEST_F(FlagTest, TestNonConstexprHelp) {
705
+ EXPECT_EQ(
706
+ absl::GetFlagReflectionHandle(FLAGS_test_flag_with_non_const_help).Help(),
707
+ "test flag non const help");
708
+ }
709
+ #endif //! ABSL_FLAGS_STRIP_HELP
710
+
711
+ // --------------------------------------------------------------------
712
+
713
+ int cb_test_value = -1;
714
+ void TestFlagCB();
715
+
716
+ } // namespace
717
+
718
+ ABSL_FLAG(int, test_flag_with_cb, 100, "").OnUpdate(TestFlagCB);
719
+
720
+ ABSL_FLAG(int, test_flag_with_lambda_cb, 200, "").OnUpdate([]() {
721
+ cb_test_value = absl::GetFlag(FLAGS_test_flag_with_lambda_cb) +
722
+ absl::GetFlag(FLAGS_test_flag_with_cb);
723
+ });
724
+
725
+ namespace {
726
+
727
+ void TestFlagCB() { cb_test_value = absl::GetFlag(FLAGS_test_flag_with_cb); }
728
+
729
+ // Tests side-effects of callback invocation.
730
+ TEST_F(FlagTest, CallbackInvocation) {
731
+ EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_with_cb), 100);
732
+ EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_with_lambda_cb), 200);
733
+ EXPECT_EQ(cb_test_value, 300);
734
+
735
+ absl::SetFlag(&FLAGS_test_flag_with_cb, 1);
736
+ EXPECT_EQ(cb_test_value, 1);
737
+
738
+ absl::SetFlag(&FLAGS_test_flag_with_lambda_cb, 3);
739
+ EXPECT_EQ(cb_test_value, 4);
740
+ }
741
+
742
+ // --------------------------------------------------------------------
743
+
744
+ struct CustomUDT {
745
+ CustomUDT() : a(1), b(1) {}
746
+ CustomUDT(int a_, int b_) : a(a_), b(b_) {}
747
+
748
+ friend bool operator==(const CustomUDT& f1, const CustomUDT& f2) {
749
+ return f1.a == f2.a && f1.b == f2.b;
750
+ }
751
+
752
+ int a;
753
+ int b;
754
+ };
755
+ bool AbslParseFlag(absl::string_view in, CustomUDT* f, std::string*) {
756
+ std::vector<absl::string_view> parts =
757
+ absl::StrSplit(in, ':', absl::SkipWhitespace());
758
+
759
+ if (parts.size() != 2) return false;
760
+
761
+ if (!absl::SimpleAtoi(parts[0], &f->a)) return false;
762
+
763
+ if (!absl::SimpleAtoi(parts[1], &f->b)) return false;
764
+
765
+ return true;
766
+ }
767
+ std::string AbslUnparseFlag(const CustomUDT& f) {
768
+ return absl::StrCat(f.a, ":", f.b);
769
+ }
770
+
771
+ } // namespace
772
+
773
+ ABSL_FLAG(CustomUDT, test_flag_custom_udt, CustomUDT(), "test flag custom UDT");
774
+
775
+ namespace {
776
+
777
+ TEST_F(FlagTest, TestCustomUDT) {
778
+ EXPECT_EQ(flags::StorageKind<CustomUDT>(),
779
+ flags::FlagValueStorageKind::kOneWordAtomic);
780
+ EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_custom_udt), CustomUDT(1, 1));
781
+ absl::SetFlag(&FLAGS_test_flag_custom_udt, CustomUDT(2, 3));
782
+ EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_custom_udt), CustomUDT(2, 3));
783
+ }
784
+
785
+ // MSVC produces link error on the type mismatch.
786
+ // Linux does not have build errors and validations work as expected.
787
+ #if !defined(_WIN32) && GTEST_HAS_DEATH_TEST
788
+
789
+ using FlagDeathTest = FlagTest;
790
+
791
+ TEST_F(FlagDeathTest, TestTypeMismatchValidations) {
792
+ #if !defined(NDEBUG)
793
+ EXPECT_DEATH_IF_SUPPORTED(
794
+ static_cast<void>(absl::GetFlag(FLAGS_mistyped_int_flag)),
795
+ "Flag 'mistyped_int_flag' is defined as one type and declared "
796
+ "as another");
797
+ EXPECT_DEATH_IF_SUPPORTED(
798
+ static_cast<void>(absl::GetFlag(FLAGS_mistyped_string_flag)),
799
+ "Flag 'mistyped_string_flag' is defined as one type and "
800
+ "declared as another");
801
+ #endif
802
+
803
+ EXPECT_DEATH_IF_SUPPORTED(
804
+ absl::SetFlag(&FLAGS_mistyped_int_flag, 1),
805
+ "Flag 'mistyped_int_flag' is defined as one type and declared "
806
+ "as another");
807
+ EXPECT_DEATH_IF_SUPPORTED(
808
+ absl::SetFlag(&FLAGS_mistyped_string_flag, std::vector<std::string>{}),
809
+ "Flag 'mistyped_string_flag' is defined as one type and declared as "
810
+ "another");
811
+ }
812
+
813
+ #endif
814
+
815
+ // --------------------------------------------------------------------
816
+
817
+ // A contrived type that offers implicit and explicit conversion from specific
818
+ // source types.
819
+ struct ConversionTestVal {
820
+ ConversionTestVal() = default;
821
+ explicit ConversionTestVal(int a_in) : a(a_in) {}
822
+
823
+ enum class ViaImplicitConv { kTen = 10, kEleven };
824
+ // NOLINTNEXTLINE
825
+ ConversionTestVal(ViaImplicitConv from) : a(static_cast<int>(from)) {}
826
+
827
+ int a;
828
+ };
829
+
830
+ bool AbslParseFlag(absl::string_view in, ConversionTestVal* val_out,
831
+ std::string*) {
832
+ if (!absl::SimpleAtoi(in, &val_out->a)) {
833
+ return false;
834
+ }
835
+ return true;
836
+ }
837
+ std::string AbslUnparseFlag(const ConversionTestVal& val) {
838
+ return absl::StrCat(val.a);
839
+ }
840
+
841
+ } // namespace
842
+
843
+ // Flag default values can be specified with a value that converts to the flag
844
+ // value type implicitly.
845
+ ABSL_FLAG(ConversionTestVal, test_flag_implicit_conv,
846
+ ConversionTestVal::ViaImplicitConv::kTen,
847
+ "test flag init via implicit conversion");
848
+
849
+ namespace {
850
+
851
+ TEST_F(FlagTest, CanSetViaImplicitConversion) {
852
+ EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_implicit_conv).a, 10);
853
+ absl::SetFlag(&FLAGS_test_flag_implicit_conv,
854
+ ConversionTestVal::ViaImplicitConv::kEleven);
855
+ EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_implicit_conv).a, 11);
856
+ }
857
+
858
+ // --------------------------------------------------------------------
859
+
860
+ struct NonDfltConstructible {
861
+ public:
862
+ // This constructor tests that we can initialize the flag with int value
863
+ NonDfltConstructible(int i) : value(i) {} // NOLINT
864
+
865
+ // This constructor tests that we can't initialize the flag with char value
866
+ // but can with explicitly constructed NonDfltConstructible.
867
+ explicit NonDfltConstructible(char c) : value(100 + static_cast<int>(c)) {}
868
+
869
+ int value;
870
+ };
871
+
872
+ bool AbslParseFlag(absl::string_view in, NonDfltConstructible* ndc_out,
873
+ std::string*) {
874
+ return absl::SimpleAtoi(in, &ndc_out->value);
875
+ }
876
+ std::string AbslUnparseFlag(const NonDfltConstructible& ndc) {
877
+ return absl::StrCat(ndc.value);
878
+ }
879
+
880
+ } // namespace
881
+
882
+ ABSL_FLAG(NonDfltConstructible, ndc_flag1, NonDfltConstructible('1'),
883
+ "Flag with non default constructible type");
884
+ ABSL_FLAG(NonDfltConstructible, ndc_flag2, 0,
885
+ "Flag with non default constructible type");
886
+
887
+ namespace {
888
+
889
+ TEST_F(FlagTest, TestNonDefaultConstructibleType) {
890
+ EXPECT_EQ(absl::GetFlag(FLAGS_ndc_flag1).value, '1' + 100);
891
+ EXPECT_EQ(absl::GetFlag(FLAGS_ndc_flag2).value, 0);
892
+
893
+ absl::SetFlag(&FLAGS_ndc_flag1, NonDfltConstructible('A'));
894
+ absl::SetFlag(&FLAGS_ndc_flag2, 25);
895
+
896
+ EXPECT_EQ(absl::GetFlag(FLAGS_ndc_flag1).value, 'A' + 100);
897
+ EXPECT_EQ(absl::GetFlag(FLAGS_ndc_flag2).value, 25);
898
+ }
899
+
900
+ } // namespace
901
+
902
+ // --------------------------------------------------------------------
903
+
904
+ ABSL_RETIRED_FLAG(bool, old_bool_flag, true, "old descr");
905
+ ABSL_RETIRED_FLAG(int, old_int_flag, (int)std::sqrt(10), "old descr");
906
+ ABSL_RETIRED_FLAG(std::string, old_str_flag, "", absl::StrCat("old ", "descr"));
907
+
908
+ namespace {
909
+
910
+ bool initialization_order_fiasco_test ABSL_ATTRIBUTE_UNUSED = [] {
911
+ // Iterate over all the flags during static initialization.
912
+ // This should not trigger ASan's initialization-order-fiasco.
913
+ auto* handle1 = absl::FindCommandLineFlag("flag_on_separate_file");
914
+ auto* handle2 = absl::FindCommandLineFlag("retired_flag_on_separate_file");
915
+ if (handle1 != nullptr && handle2 != nullptr) {
916
+ return handle1->Name() == handle2->Name();
917
+ }
918
+ return true;
919
+ }();
920
+
921
+ TEST_F(FlagTest, TestRetiredFlagRegistration) {
922
+ auto* handle = absl::FindCommandLineFlag("old_bool_flag");
923
+ EXPECT_TRUE(handle->IsOfType<bool>());
924
+ EXPECT_TRUE(handle->IsRetired());
925
+ handle = absl::FindCommandLineFlag("old_int_flag");
926
+ EXPECT_TRUE(handle->IsOfType<int>());
927
+ EXPECT_TRUE(handle->IsRetired());
928
+ handle = absl::FindCommandLineFlag("old_str_flag");
929
+ EXPECT_TRUE(handle->IsOfType<std::string>());
930
+ EXPECT_TRUE(handle->IsRetired());
931
+ }
932
+
933
+ } // namespace
934
+
935
+ // --------------------------------------------------------------------
936
+
937
+ namespace {
938
+
939
+ // User-defined type with small alignment, but size exceeding 16.
940
+ struct SmallAlignUDT {
941
+ SmallAlignUDT() : c('A'), s(12) {}
942
+ char c;
943
+ int16_t s;
944
+ char bytes[14];
945
+ };
946
+
947
+ bool AbslParseFlag(absl::string_view, SmallAlignUDT*, std::string*) {
948
+ return true;
949
+ }
950
+ std::string AbslUnparseFlag(const SmallAlignUDT&) { return ""; }
951
+
952
+ // User-defined type with small size, but not trivially copyable.
953
+ struct NonTriviallyCopyableUDT {
954
+ NonTriviallyCopyableUDT() : c('A') {}
955
+ NonTriviallyCopyableUDT(const NonTriviallyCopyableUDT& rhs) : c(rhs.c) {}
956
+ NonTriviallyCopyableUDT& operator=(const NonTriviallyCopyableUDT& rhs) {
957
+ c = rhs.c;
958
+ return *this;
959
+ }
960
+
961
+ char c;
962
+ };
963
+
964
+ bool AbslParseFlag(absl::string_view, NonTriviallyCopyableUDT*, std::string*) {
965
+ return true;
966
+ }
967
+ std::string AbslUnparseFlag(const NonTriviallyCopyableUDT&) { return ""; }
968
+
969
+ } // namespace
970
+
971
+ ABSL_FLAG(SmallAlignUDT, test_flag_sa_udt, {}, "help");
972
+ ABSL_FLAG(NonTriviallyCopyableUDT, test_flag_ntc_udt, {}, "help");
973
+
974
+ namespace {
975
+
976
+ TEST_F(FlagTest, TestSmallAlignUDT) {
977
+ SmallAlignUDT value = absl::GetFlag(FLAGS_test_flag_sa_udt);
978
+ EXPECT_EQ(value.c, 'A');
979
+ EXPECT_EQ(value.s, 12);
980
+
981
+ value.c = 'B';
982
+ value.s = 45;
983
+ absl::SetFlag(&FLAGS_test_flag_sa_udt, value);
984
+ value = absl::GetFlag(FLAGS_test_flag_sa_udt);
985
+ EXPECT_EQ(value.c, 'B');
986
+ EXPECT_EQ(value.s, 45);
987
+ }
988
+
989
+ TEST_F(FlagTest, TestNonTriviallyCopyableUDT) {
990
+ NonTriviallyCopyableUDT value = absl::GetFlag(FLAGS_test_flag_ntc_udt);
991
+ EXPECT_EQ(value.c, 'A');
992
+
993
+ value.c = 'B';
994
+ absl::SetFlag(&FLAGS_test_flag_ntc_udt, value);
995
+ value = absl::GetFlag(FLAGS_test_flag_ntc_udt);
996
+ EXPECT_EQ(value.c, 'B');
997
+ }
998
+
999
+ } // namespace
1000
+
1001
+ // --------------------------------------------------------------------
1002
+
1003
+ namespace {
1004
+
1005
+ enum TestE { A = 1, B = 2, C = 3 };
1006
+
1007
+ struct EnumWrapper {
1008
+ EnumWrapper() : e(A) {}
1009
+
1010
+ TestE e;
1011
+ };
1012
+
1013
+ bool AbslParseFlag(absl::string_view, EnumWrapper*, std::string*) {
1014
+ return true;
1015
+ }
1016
+ std::string AbslUnparseFlag(const EnumWrapper&) { return ""; }
1017
+
1018
+ } // namespace
1019
+
1020
+ ABSL_FLAG(EnumWrapper, test_enum_wrapper_flag, {}, "help");
1021
+
1022
+ TEST_F(FlagTest, TesTypeWrappingEnum) {
1023
+ EnumWrapper value = absl::GetFlag(FLAGS_test_enum_wrapper_flag);
1024
+ EXPECT_EQ(value.e, A);
1025
+
1026
+ value.e = B;
1027
+ absl::SetFlag(&FLAGS_test_enum_wrapper_flag, value);
1028
+ value = absl::GetFlag(FLAGS_test_enum_wrapper_flag);
1029
+ EXPECT_EQ(value.e, B);
1030
+ }
1031
+
1032
+ // This is a compile test to ensure macros are expanded within ABSL_FLAG and
1033
+ // ABSL_DECLARE_FLAG.
1034
+ #define FLAG_NAME_MACRO(name) prefix_##name
1035
+ ABSL_DECLARE_FLAG(int, FLAG_NAME_MACRO(test_macro_named_flag));
1036
+ ABSL_FLAG(int, FLAG_NAME_MACRO(test_macro_named_flag), 0,
1037
+ "Testing macro expansion within ABSL_FLAG");
1038
+
1039
+ TEST_F(FlagTest, MacroWithinAbslFlag) {
1040
+ EXPECT_EQ(absl::GetFlag(FLAGS_prefix_test_macro_named_flag), 0);
1041
+ absl::SetFlag(&FLAGS_prefix_test_macro_named_flag, 1);
1042
+ EXPECT_EQ(absl::GetFlag(FLAGS_prefix_test_macro_named_flag), 1);
1043
+ }
1044
+
1045
+ // --------------------------------------------------------------------
1046
+
1047
+ #if defined(__GNUC__) && !defined(__clang__) && __GNUC__ <= 5
1048
+ #define ABSL_SKIP_OPTIONAL_BOOL_TEST_DUE_TO_GCC_BUG
1049
+ #endif
1050
+
1051
+ #ifndef ABSL_SKIP_OPTIONAL_BOOL_TEST_DUE_TO_GCC_BUG
1052
+ ABSL_FLAG(absl::optional<bool>, optional_bool, absl::nullopt, "help");
1053
+ #endif
1054
+ ABSL_FLAG(absl::optional<int>, optional_int, {}, "help");
1055
+ ABSL_FLAG(absl::optional<double>, optional_double, 9.3, "help");
1056
+ ABSL_FLAG(absl::optional<std::string>, optional_string, absl::nullopt, "help");
1057
+ ABSL_FLAG(absl::optional<absl::Duration>, optional_duration, absl::nullopt,
1058
+ "help");
1059
+ ABSL_FLAG(absl::optional<absl::optional<int>>, optional_optional_int,
1060
+ absl::nullopt, "help");
1061
+ #if defined(ABSL_HAVE_STD_OPTIONAL) && !defined(ABSL_USES_STD_OPTIONAL)
1062
+ ABSL_FLAG(std::optional<int64_t>, std_optional_int64, std::nullopt, "help");
1063
+ #endif
1064
+
1065
+ namespace {
1066
+
1067
+ #ifndef ABSL_SKIP_OPTIONAL_BOOL_TEST_DUE_TO_GCC_BUG
1068
+ TEST_F(FlagTest, TestOptionalBool) {
1069
+ EXPECT_FALSE(absl::GetFlag(FLAGS_optional_bool).has_value());
1070
+ EXPECT_EQ(absl::GetFlag(FLAGS_optional_bool), absl::nullopt);
1071
+
1072
+ absl::SetFlag(&FLAGS_optional_bool, false);
1073
+ EXPECT_TRUE(absl::GetFlag(FLAGS_optional_bool).has_value());
1074
+ EXPECT_EQ(absl::GetFlag(FLAGS_optional_bool), false);
1075
+
1076
+ absl::SetFlag(&FLAGS_optional_bool, true);
1077
+ EXPECT_TRUE(absl::GetFlag(FLAGS_optional_bool).has_value());
1078
+ EXPECT_EQ(absl::GetFlag(FLAGS_optional_bool), true);
1079
+
1080
+ absl::SetFlag(&FLAGS_optional_bool, absl::nullopt);
1081
+ EXPECT_FALSE(absl::GetFlag(FLAGS_optional_bool).has_value());
1082
+ EXPECT_EQ(absl::GetFlag(FLAGS_optional_bool), absl::nullopt);
1083
+ }
1084
+
1085
+ // --------------------------------------------------------------------
1086
+ #endif
1087
+
1088
+ TEST_F(FlagTest, TestOptionalInt) {
1089
+ EXPECT_FALSE(absl::GetFlag(FLAGS_optional_int).has_value());
1090
+ EXPECT_EQ(absl::GetFlag(FLAGS_optional_int), absl::nullopt);
1091
+
1092
+ absl::SetFlag(&FLAGS_optional_int, 0);
1093
+ EXPECT_TRUE(absl::GetFlag(FLAGS_optional_int).has_value());
1094
+ EXPECT_EQ(absl::GetFlag(FLAGS_optional_int), 0);
1095
+
1096
+ absl::SetFlag(&FLAGS_optional_int, 10);
1097
+ EXPECT_TRUE(absl::GetFlag(FLAGS_optional_int).has_value());
1098
+ EXPECT_EQ(absl::GetFlag(FLAGS_optional_int), 10);
1099
+
1100
+ absl::SetFlag(&FLAGS_optional_int, absl::nullopt);
1101
+ EXPECT_FALSE(absl::GetFlag(FLAGS_optional_int).has_value());
1102
+ EXPECT_EQ(absl::GetFlag(FLAGS_optional_int), absl::nullopt);
1103
+ }
1104
+
1105
+ // --------------------------------------------------------------------
1106
+
1107
+ TEST_F(FlagTest, TestOptionalDouble) {
1108
+ EXPECT_TRUE(absl::GetFlag(FLAGS_optional_double).has_value());
1109
+ EXPECT_DOUBLE_EQ(*absl::GetFlag(FLAGS_optional_double), 9.3);
1110
+
1111
+ absl::SetFlag(&FLAGS_optional_double, 0.0);
1112
+ EXPECT_TRUE(absl::GetFlag(FLAGS_optional_double).has_value());
1113
+ EXPECT_EQ(absl::GetFlag(FLAGS_optional_double), 0.0);
1114
+
1115
+ absl::SetFlag(&FLAGS_optional_double, 1.234);
1116
+ EXPECT_TRUE(absl::GetFlag(FLAGS_optional_double).has_value());
1117
+ EXPECT_DOUBLE_EQ(*absl::GetFlag(FLAGS_optional_double), 1.234);
1118
+
1119
+ absl::SetFlag(&FLAGS_optional_double, absl::nullopt);
1120
+ EXPECT_FALSE(absl::GetFlag(FLAGS_optional_double).has_value());
1121
+ EXPECT_EQ(absl::GetFlag(FLAGS_optional_double), absl::nullopt);
1122
+ }
1123
+
1124
+ // --------------------------------------------------------------------
1125
+
1126
+ TEST_F(FlagTest, TestOptionalString) {
1127
+ EXPECT_FALSE(absl::GetFlag(FLAGS_optional_string).has_value());
1128
+ EXPECT_EQ(absl::GetFlag(FLAGS_optional_string), absl::nullopt);
1129
+
1130
+ // Setting optional string to "" leads to undefined behavior.
1131
+
1132
+ absl::SetFlag(&FLAGS_optional_string, " ");
1133
+ EXPECT_TRUE(absl::GetFlag(FLAGS_optional_string).has_value());
1134
+ EXPECT_EQ(absl::GetFlag(FLAGS_optional_string), " ");
1135
+
1136
+ absl::SetFlag(&FLAGS_optional_string, "QWERTY");
1137
+ EXPECT_TRUE(absl::GetFlag(FLAGS_optional_string).has_value());
1138
+ EXPECT_EQ(absl::GetFlag(FLAGS_optional_string), "QWERTY");
1139
+
1140
+ absl::SetFlag(&FLAGS_optional_string, absl::nullopt);
1141
+ EXPECT_FALSE(absl::GetFlag(FLAGS_optional_string).has_value());
1142
+ EXPECT_EQ(absl::GetFlag(FLAGS_optional_string), absl::nullopt);
1143
+ }
1144
+
1145
+ // --------------------------------------------------------------------
1146
+
1147
+ TEST_F(FlagTest, TestOptionalDuration) {
1148
+ EXPECT_FALSE(absl::GetFlag(FLAGS_optional_duration).has_value());
1149
+ EXPECT_EQ(absl::GetFlag(FLAGS_optional_duration), absl::nullopt);
1150
+
1151
+ absl::SetFlag(&FLAGS_optional_duration, absl::ZeroDuration());
1152
+ EXPECT_TRUE(absl::GetFlag(FLAGS_optional_duration).has_value());
1153
+ EXPECT_EQ(absl::GetFlag(FLAGS_optional_duration), absl::Seconds(0));
1154
+
1155
+ absl::SetFlag(&FLAGS_optional_duration, absl::Hours(3));
1156
+ EXPECT_TRUE(absl::GetFlag(FLAGS_optional_duration).has_value());
1157
+ EXPECT_EQ(absl::GetFlag(FLAGS_optional_duration), absl::Hours(3));
1158
+
1159
+ absl::SetFlag(&FLAGS_optional_duration, absl::nullopt);
1160
+ EXPECT_FALSE(absl::GetFlag(FLAGS_optional_duration).has_value());
1161
+ EXPECT_EQ(absl::GetFlag(FLAGS_optional_duration), absl::nullopt);
1162
+ }
1163
+
1164
+ // --------------------------------------------------------------------
1165
+
1166
+ TEST_F(FlagTest, TestOptionalOptional) {
1167
+ EXPECT_FALSE(absl::GetFlag(FLAGS_optional_optional_int).has_value());
1168
+ EXPECT_EQ(absl::GetFlag(FLAGS_optional_optional_int), absl::nullopt);
1169
+
1170
+ absl::optional<int> nullint{absl::nullopt};
1171
+
1172
+ absl::SetFlag(&FLAGS_optional_optional_int, nullint);
1173
+ EXPECT_TRUE(absl::GetFlag(FLAGS_optional_optional_int).has_value());
1174
+ EXPECT_NE(absl::GetFlag(FLAGS_optional_optional_int), nullint);
1175
+ EXPECT_EQ(absl::GetFlag(FLAGS_optional_optional_int),
1176
+ absl::optional<absl::optional<int>>{nullint});
1177
+
1178
+ absl::SetFlag(&FLAGS_optional_optional_int, 0);
1179
+ EXPECT_TRUE(absl::GetFlag(FLAGS_optional_optional_int).has_value());
1180
+ EXPECT_EQ(absl::GetFlag(FLAGS_optional_optional_int), 0);
1181
+
1182
+ absl::SetFlag(&FLAGS_optional_optional_int, absl::optional<int>{0});
1183
+ EXPECT_TRUE(absl::GetFlag(FLAGS_optional_optional_int).has_value());
1184
+ EXPECT_EQ(absl::GetFlag(FLAGS_optional_optional_int), 0);
1185
+ EXPECT_EQ(absl::GetFlag(FLAGS_optional_optional_int), absl::optional<int>{0});
1186
+
1187
+ absl::SetFlag(&FLAGS_optional_optional_int, absl::nullopt);
1188
+ EXPECT_FALSE(absl::GetFlag(FLAGS_optional_optional_int).has_value());
1189
+ EXPECT_EQ(absl::GetFlag(FLAGS_optional_optional_int), absl::nullopt);
1190
+ }
1191
+
1192
+ // --------------------------------------------------------------------
1193
+
1194
+ #if defined(ABSL_HAVE_STD_OPTIONAL) && !defined(ABSL_USES_STD_OPTIONAL)
1195
+
1196
+ TEST_F(FlagTest, TestStdOptional) {
1197
+ EXPECT_FALSE(absl::GetFlag(FLAGS_std_optional_int64).has_value());
1198
+ EXPECT_EQ(absl::GetFlag(FLAGS_std_optional_int64), std::nullopt);
1199
+
1200
+ absl::SetFlag(&FLAGS_std_optional_int64, 0);
1201
+ EXPECT_TRUE(absl::GetFlag(FLAGS_std_optional_int64).has_value());
1202
+ EXPECT_EQ(absl::GetFlag(FLAGS_std_optional_int64), 0);
1203
+
1204
+ absl::SetFlag(&FLAGS_std_optional_int64, 0xFFFFFFFFFF16);
1205
+ EXPECT_TRUE(absl::GetFlag(FLAGS_std_optional_int64).has_value());
1206
+ EXPECT_EQ(absl::GetFlag(FLAGS_std_optional_int64), 0xFFFFFFFFFF16);
1207
+
1208
+ absl::SetFlag(&FLAGS_std_optional_int64, std::nullopt);
1209
+ EXPECT_FALSE(absl::GetFlag(FLAGS_std_optional_int64).has_value());
1210
+ EXPECT_EQ(absl::GetFlag(FLAGS_std_optional_int64), std::nullopt);
1211
+ }
1212
+
1213
+ // --------------------------------------------------------------------
1214
+
1215
+ #endif
1216
+
1217
+ } // namespace
weight/_dep/abseil-cpp/absl/flags/flag_test_defs.cc ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ //
2
+ // Copyright 2019 The Abseil Authors.
3
+ //
4
+ // Licensed under the Apache License, Version 2.0 (the "License");
5
+ // you may not use this file except in compliance with the License.
6
+ // You may obtain a copy of the License at
7
+ //
8
+ // https://www.apache.org/licenses/LICENSE-2.0
9
+ //
10
+ // Unless required by applicable law or agreed to in writing, software
11
+ // distributed under the License is distributed on an "AS IS" BASIS,
12
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ // See the License for the specific language governing permissions and
14
+ // limitations under the License.
15
+
16
+ // This file is used to test the mismatch of the flag type between definition
17
+ // and declaration. These are definitions. flag_test.cc contains declarations.
18
+ #include <string>
19
+ #include "absl/flags/flag.h"
20
+
21
+ ABSL_FLAG(int, mistyped_int_flag, 0, "");
22
+ ABSL_FLAG(std::string, mistyped_string_flag, "", "");
23
+ ABSL_FLAG(bool, flag_on_separate_file, false, "");
24
+ ABSL_RETIRED_FLAG(bool, retired_flag_on_separate_file, false, "");
weight/_dep/abseil-cpp/absl/flags/internal/commandlineflag.h ADDED
@@ -0,0 +1,68 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ //
2
+ // Copyright 2019 The Abseil Authors.
3
+ //
4
+ // Licensed under the Apache License, Version 2.0 (the "License");
5
+ // you may not use this file except in compliance with the License.
6
+ // You may obtain a copy of the License at
7
+ //
8
+ // https://www.apache.org/licenses/LICENSE-2.0
9
+ //
10
+ // Unless required by applicable law or agreed to in writing, software
11
+ // distributed under the License is distributed on an "AS IS" BASIS,
12
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ // See the License for the specific language governing permissions and
14
+ // limitations under the License.
15
+
16
+ #ifndef ABSL_FLAGS_INTERNAL_COMMANDLINEFLAG_H_
17
+ #define ABSL_FLAGS_INTERNAL_COMMANDLINEFLAG_H_
18
+
19
+ #include "absl/base/config.h"
20
+ #include "absl/base/internal/fast_type_id.h"
21
+
22
+ namespace absl {
23
+ ABSL_NAMESPACE_BEGIN
24
+ namespace flags_internal {
25
+
26
+ // An alias for flag fast type id. This value identifies the flag value type
27
+ // similarly to typeid(T), without relying on RTTI being available. In most
28
+ // cases this id is enough to uniquely identify the flag's value type. In a few
29
+ // cases we'll have to resort to using actual RTTI implementation if it is
30
+ // available.
31
+ using FlagFastTypeId = absl::base_internal::FastTypeIdType;
32
+
33
+ // Options that control SetCommandLineOptionWithMode.
34
+ enum FlagSettingMode {
35
+ // update the flag's value unconditionally (can call this multiple times).
36
+ SET_FLAGS_VALUE,
37
+ // update the flag's value, but *only if* it has not yet been updated
38
+ // with SET_FLAGS_VALUE, SET_FLAG_IF_DEFAULT, or "FLAGS_xxx = nondef".
39
+ SET_FLAG_IF_DEFAULT,
40
+ // set the flag's default value to this. If the flag has not been updated
41
+ // yet (via SET_FLAGS_VALUE, SET_FLAG_IF_DEFAULT, or "FLAGS_xxx = nondef")
42
+ // change the flag's current value to the new default value as well.
43
+ SET_FLAGS_DEFAULT
44
+ };
45
+
46
+ // Options that control ParseFrom: Source of a value.
47
+ enum ValueSource {
48
+ // Flag is being set by value specified on a command line.
49
+ kCommandLine,
50
+ // Flag is being set by value specified in the code.
51
+ kProgrammaticChange,
52
+ };
53
+
54
+ // Handle to FlagState objects. Specific flag state objects will restore state
55
+ // of a flag produced this flag state from method CommandLineFlag::SaveState().
56
+ class FlagStateInterface {
57
+ public:
58
+ virtual ~FlagStateInterface();
59
+
60
+ // Restores the flag originated this object to the saved state.
61
+ virtual void Restore() const = 0;
62
+ };
63
+
64
+ } // namespace flags_internal
65
+ ABSL_NAMESPACE_END
66
+ } // namespace absl
67
+
68
+ #endif // ABSL_FLAGS_INTERNAL_COMMANDLINEFLAG_H_
weight/_dep/abseil-cpp/absl/flags/internal/flag.h ADDED
@@ -0,0 +1,796 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ //
2
+ // Copyright 2019 The Abseil Authors.
3
+ //
4
+ // Licensed under the Apache License, Version 2.0 (the "License");
5
+ // you may not use this file except in compliance with the License.
6
+ // You may obtain a copy of the License at
7
+ //
8
+ // https://www.apache.org/licenses/LICENSE-2.0
9
+ //
10
+ // Unless required by applicable law or agreed to in writing, software
11
+ // distributed under the License is distributed on an "AS IS" BASIS,
12
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ // See the License for the specific language governing permissions and
14
+ // limitations under the License.
15
+
16
+ #ifndef ABSL_FLAGS_INTERNAL_FLAG_H_
17
+ #define ABSL_FLAGS_INTERNAL_FLAG_H_
18
+
19
+ #include <stddef.h>
20
+ #include <stdint.h>
21
+
22
+ #include <atomic>
23
+ #include <cstring>
24
+ #include <memory>
25
+ #include <new>
26
+ #include <string>
27
+ #include <type_traits>
28
+ #include <typeinfo>
29
+
30
+ #include "absl/base/attributes.h"
31
+ #include "absl/base/call_once.h"
32
+ #include "absl/base/casts.h"
33
+ #include "absl/base/config.h"
34
+ #include "absl/base/optimization.h"
35
+ #include "absl/base/thread_annotations.h"
36
+ #include "absl/flags/commandlineflag.h"
37
+ #include "absl/flags/config.h"
38
+ #include "absl/flags/internal/commandlineflag.h"
39
+ #include "absl/flags/internal/registry.h"
40
+ #include "absl/flags/internal/sequence_lock.h"
41
+ #include "absl/flags/marshalling.h"
42
+ #include "absl/meta/type_traits.h"
43
+ #include "absl/strings/string_view.h"
44
+ #include "absl/synchronization/mutex.h"
45
+ #include "absl/utility/utility.h"
46
+
47
+ namespace absl {
48
+ ABSL_NAMESPACE_BEGIN
49
+
50
+ ///////////////////////////////////////////////////////////////////////////////
51
+ // Forward declaration of absl::Flag<T> public API.
52
+ namespace flags_internal {
53
+ template <typename T>
54
+ class Flag;
55
+ } // namespace flags_internal
56
+
57
+ template <typename T>
58
+ using Flag = flags_internal::Flag<T>;
59
+
60
+ template <typename T>
61
+ ABSL_MUST_USE_RESULT T GetFlag(const absl::Flag<T>& flag);
62
+
63
+ template <typename T>
64
+ void SetFlag(absl::Flag<T>* flag, const T& v);
65
+
66
+ template <typename T, typename V>
67
+ void SetFlag(absl::Flag<T>* flag, const V& v);
68
+
69
+ template <typename U>
70
+ const CommandLineFlag& GetFlagReflectionHandle(const absl::Flag<U>& f);
71
+
72
+ ///////////////////////////////////////////////////////////////////////////////
73
+ // Flag value type operations, eg., parsing, copying, etc. are provided
74
+ // by function specific to that type with a signature matching FlagOpFn.
75
+
76
+ namespace flags_internal {
77
+
78
+ enum class FlagOp {
79
+ kAlloc,
80
+ kDelete,
81
+ kCopy,
82
+ kCopyConstruct,
83
+ kSizeof,
84
+ kFastTypeId,
85
+ kRuntimeTypeId,
86
+ kParse,
87
+ kUnparse,
88
+ kValueOffset,
89
+ };
90
+ using FlagOpFn = void* (*)(FlagOp, const void*, void*, void*);
91
+
92
+ // Forward declaration for Flag value specific operations.
93
+ template <typename T>
94
+ void* FlagOps(FlagOp op, const void* v1, void* v2, void* v3);
95
+
96
+ // Allocate aligned memory for a flag value.
97
+ inline void* Alloc(FlagOpFn op) {
98
+ return op(FlagOp::kAlloc, nullptr, nullptr, nullptr);
99
+ }
100
+ // Deletes memory interpreting obj as flag value type pointer.
101
+ inline void Delete(FlagOpFn op, void* obj) {
102
+ op(FlagOp::kDelete, nullptr, obj, nullptr);
103
+ }
104
+ // Copies src to dst interpreting as flag value type pointers.
105
+ inline void Copy(FlagOpFn op, const void* src, void* dst) {
106
+ op(FlagOp::kCopy, src, dst, nullptr);
107
+ }
108
+ // Construct a copy of flag value in a location pointed by dst
109
+ // based on src - pointer to the flag's value.
110
+ inline void CopyConstruct(FlagOpFn op, const void* src, void* dst) {
111
+ op(FlagOp::kCopyConstruct, src, dst, nullptr);
112
+ }
113
+ // Makes a copy of flag value pointed by obj.
114
+ inline void* Clone(FlagOpFn op, const void* obj) {
115
+ void* res = flags_internal::Alloc(op);
116
+ flags_internal::CopyConstruct(op, obj, res);
117
+ return res;
118
+ }
119
+ // Returns true if parsing of input text is successful.
120
+ inline bool Parse(FlagOpFn op, absl::string_view text, void* dst,
121
+ std::string* error) {
122
+ return op(FlagOp::kParse, &text, dst, error) != nullptr;
123
+ }
124
+ // Returns string representing supplied value.
125
+ inline std::string Unparse(FlagOpFn op, const void* val) {
126
+ std::string result;
127
+ op(FlagOp::kUnparse, val, &result, nullptr);
128
+ return result;
129
+ }
130
+ // Returns size of flag value type.
131
+ inline size_t Sizeof(FlagOpFn op) {
132
+ // This sequence of casts reverses the sequence from
133
+ // `flags_internal::FlagOps()`
134
+ return static_cast<size_t>(reinterpret_cast<intptr_t>(
135
+ op(FlagOp::kSizeof, nullptr, nullptr, nullptr)));
136
+ }
137
+ // Returns fast type id corresponding to the value type.
138
+ inline FlagFastTypeId FastTypeId(FlagOpFn op) {
139
+ return reinterpret_cast<FlagFastTypeId>(
140
+ op(FlagOp::kFastTypeId, nullptr, nullptr, nullptr));
141
+ }
142
+ // Returns fast type id corresponding to the value type.
143
+ inline const std::type_info* RuntimeTypeId(FlagOpFn op) {
144
+ return reinterpret_cast<const std::type_info*>(
145
+ op(FlagOp::kRuntimeTypeId, nullptr, nullptr, nullptr));
146
+ }
147
+ // Returns offset of the field value_ from the field impl_ inside of
148
+ // absl::Flag<T> data. Given FlagImpl pointer p you can get the
149
+ // location of the corresponding value as:
150
+ // reinterpret_cast<char*>(p) + ValueOffset().
151
+ inline ptrdiff_t ValueOffset(FlagOpFn op) {
152
+ // This sequence of casts reverses the sequence from
153
+ // `flags_internal::FlagOps()`
154
+ return static_cast<ptrdiff_t>(reinterpret_cast<intptr_t>(
155
+ op(FlagOp::kValueOffset, nullptr, nullptr, nullptr)));
156
+ }
157
+
158
+ // Returns an address of RTTI's typeid(T).
159
+ template <typename T>
160
+ inline const std::type_info* GenRuntimeTypeId() {
161
+ #ifdef ABSL_INTERNAL_HAS_RTTI
162
+ return &typeid(T);
163
+ #else
164
+ return nullptr;
165
+ #endif
166
+ }
167
+
168
+ ///////////////////////////////////////////////////////////////////////////////
169
+ // Flag help auxiliary structs.
170
+
171
+ // This is help argument for absl::Flag encapsulating the string literal pointer
172
+ // or pointer to function generating it as well as enum descriminating two
173
+ // cases.
174
+ using HelpGenFunc = std::string (*)();
175
+
176
+ template <size_t N>
177
+ struct FixedCharArray {
178
+ char value[N];
179
+
180
+ template <size_t... I>
181
+ static constexpr FixedCharArray<N> FromLiteralString(
182
+ absl::string_view str, absl::index_sequence<I...>) {
183
+ return (void)str, FixedCharArray<N>({{str[I]..., '\0'}});
184
+ }
185
+ };
186
+
187
+ template <typename Gen, size_t N = Gen::Value().size()>
188
+ constexpr FixedCharArray<N + 1> HelpStringAsArray(int) {
189
+ return FixedCharArray<N + 1>::FromLiteralString(
190
+ Gen::Value(), absl::make_index_sequence<N>{});
191
+ }
192
+
193
+ template <typename Gen>
194
+ constexpr std::false_type HelpStringAsArray(char) {
195
+ return std::false_type{};
196
+ }
197
+
198
+ union FlagHelpMsg {
199
+ constexpr explicit FlagHelpMsg(const char* help_msg) : literal(help_msg) {}
200
+ constexpr explicit FlagHelpMsg(HelpGenFunc help_gen) : gen_func(help_gen) {}
201
+
202
+ const char* literal;
203
+ HelpGenFunc gen_func;
204
+ };
205
+
206
+ enum class FlagHelpKind : uint8_t { kLiteral = 0, kGenFunc = 1 };
207
+
208
+ struct FlagHelpArg {
209
+ FlagHelpMsg source;
210
+ FlagHelpKind kind;
211
+ };
212
+
213
+ extern const char kStrippedFlagHelp[];
214
+
215
+ // These two HelpArg overloads allows us to select at compile time one of two
216
+ // way to pass Help argument to absl::Flag. We'll be passing
217
+ // AbslFlagHelpGenFor##name as Gen and integer 0 as a single argument to prefer
218
+ // first overload if possible. If help message is evaluatable on constexpr
219
+ // context We'll be able to make FixedCharArray out of it and we'll choose first
220
+ // overload. In this case the help message expression is immediately evaluated
221
+ // and is used to construct the absl::Flag. No additional code is generated by
222
+ // ABSL_FLAG Otherwise SFINAE kicks in and first overload is dropped from the
223
+ // consideration, in which case the second overload will be used. The second
224
+ // overload does not attempt to evaluate the help message expression
225
+ // immediately and instead delays the evaluation by returning the function
226
+ // pointer (&T::NonConst) generating the help message when necessary. This is
227
+ // evaluatable in constexpr context, but the cost is an extra function being
228
+ // generated in the ABSL_FLAG code.
229
+ template <typename Gen, size_t N>
230
+ constexpr FlagHelpArg HelpArg(const FixedCharArray<N>& value) {
231
+ return {FlagHelpMsg(value.value), FlagHelpKind::kLiteral};
232
+ }
233
+
234
+ template <typename Gen>
235
+ constexpr FlagHelpArg HelpArg(std::false_type) {
236
+ return {FlagHelpMsg(&Gen::NonConst), FlagHelpKind::kGenFunc};
237
+ }
238
+
239
+ ///////////////////////////////////////////////////////////////////////////////
240
+ // Flag default value auxiliary structs.
241
+
242
+ // Signature for the function generating the initial flag value (usually
243
+ // based on default value supplied in flag's definition)
244
+ using FlagDfltGenFunc = void (*)(void*);
245
+
246
+ union FlagDefaultSrc {
247
+ constexpr explicit FlagDefaultSrc(FlagDfltGenFunc gen_func_arg)
248
+ : gen_func(gen_func_arg) {}
249
+
250
+ #define ABSL_FLAGS_INTERNAL_DFLT_FOR_TYPE(T, name) \
251
+ T name##_value; \
252
+ constexpr explicit FlagDefaultSrc(T value) : name##_value(value) {} // NOLINT
253
+ ABSL_FLAGS_INTERNAL_BUILTIN_TYPES(ABSL_FLAGS_INTERNAL_DFLT_FOR_TYPE)
254
+ #undef ABSL_FLAGS_INTERNAL_DFLT_FOR_TYPE
255
+
256
+ void* dynamic_value;
257
+ FlagDfltGenFunc gen_func;
258
+ };
259
+
260
+ enum class FlagDefaultKind : uint8_t {
261
+ kDynamicValue = 0,
262
+ kGenFunc = 1,
263
+ kOneWord = 2 // for default values UP to one word in size
264
+ };
265
+
266
+ struct FlagDefaultArg {
267
+ FlagDefaultSrc source;
268
+ FlagDefaultKind kind;
269
+ };
270
+
271
+ // This struct and corresponding overload to InitDefaultValue are used to
272
+ // facilitate usage of {} as default value in ABSL_FLAG macro.
273
+ // TODO(rogeeff): Fix handling types with explicit constructors.
274
+ struct EmptyBraces {};
275
+
276
+ template <typename T>
277
+ constexpr T InitDefaultValue(T t) {
278
+ return t;
279
+ }
280
+
281
+ template <typename T>
282
+ constexpr T InitDefaultValue(EmptyBraces) {
283
+ return T{};
284
+ }
285
+
286
+ template <typename ValueT, typename GenT,
287
+ typename std::enable_if<std::is_integral<ValueT>::value, int>::type =
288
+ ((void)GenT{}, 0)>
289
+ constexpr FlagDefaultArg DefaultArg(int) {
290
+ return {FlagDefaultSrc(GenT{}.value), FlagDefaultKind::kOneWord};
291
+ }
292
+
293
+ template <typename ValueT, typename GenT>
294
+ constexpr FlagDefaultArg DefaultArg(char) {
295
+ return {FlagDefaultSrc(&GenT::Gen), FlagDefaultKind::kGenFunc};
296
+ }
297
+
298
+ ///////////////////////////////////////////////////////////////////////////////
299
+ // Flag current value auxiliary structs.
300
+
301
+ constexpr int64_t UninitializedFlagValue() {
302
+ return static_cast<int64_t>(0xababababababababll);
303
+ }
304
+
305
+ template <typename T>
306
+ using FlagUseValueAndInitBitStorage =
307
+ std::integral_constant<bool, std::is_trivially_copyable<T>::value &&
308
+ std::is_default_constructible<T>::value &&
309
+ (sizeof(T) < 8)>;
310
+
311
+ template <typename T>
312
+ using FlagUseOneWordStorage =
313
+ std::integral_constant<bool, std::is_trivially_copyable<T>::value &&
314
+ (sizeof(T) <= 8)>;
315
+
316
+ template <class T>
317
+ using FlagUseSequenceLockStorage =
318
+ std::integral_constant<bool, std::is_trivially_copyable<T>::value &&
319
+ (sizeof(T) > 8)>;
320
+
321
+ enum class FlagValueStorageKind : uint8_t {
322
+ kValueAndInitBit = 0,
323
+ kOneWordAtomic = 1,
324
+ kSequenceLocked = 2,
325
+ kAlignedBuffer = 3,
326
+ };
327
+
328
+ template <typename T>
329
+ static constexpr FlagValueStorageKind StorageKind() {
330
+ return FlagUseValueAndInitBitStorage<T>::value
331
+ ? FlagValueStorageKind::kValueAndInitBit
332
+ : FlagUseOneWordStorage<T>::value
333
+ ? FlagValueStorageKind::kOneWordAtomic
334
+ : FlagUseSequenceLockStorage<T>::value
335
+ ? FlagValueStorageKind::kSequenceLocked
336
+ : FlagValueStorageKind::kAlignedBuffer;
337
+ }
338
+
339
+ struct FlagOneWordValue {
340
+ constexpr explicit FlagOneWordValue(int64_t v) : value(v) {}
341
+ std::atomic<int64_t> value;
342
+ };
343
+
344
+ template <typename T>
345
+ struct alignas(8) FlagValueAndInitBit {
346
+ T value;
347
+ // Use an int instead of a bool to guarantee that a non-zero value has
348
+ // a bit set.
349
+ uint8_t init;
350
+ };
351
+
352
+ template <typename T,
353
+ FlagValueStorageKind Kind = flags_internal::StorageKind<T>()>
354
+ struct FlagValue;
355
+
356
+ template <typename T>
357
+ struct FlagValue<T, FlagValueStorageKind::kValueAndInitBit> : FlagOneWordValue {
358
+ constexpr FlagValue() : FlagOneWordValue(0) {}
359
+ bool Get(const SequenceLock&, T& dst) const {
360
+ int64_t storage = value.load(std::memory_order_acquire);
361
+ if (ABSL_PREDICT_FALSE(storage == 0)) {
362
+ return false;
363
+ }
364
+ dst = absl::bit_cast<FlagValueAndInitBit<T>>(storage).value;
365
+ return true;
366
+ }
367
+ };
368
+
369
+ template <typename T>
370
+ struct FlagValue<T, FlagValueStorageKind::kOneWordAtomic> : FlagOneWordValue {
371
+ constexpr FlagValue() : FlagOneWordValue(UninitializedFlagValue()) {}
372
+ bool Get(const SequenceLock&, T& dst) const {
373
+ int64_t one_word_val = value.load(std::memory_order_acquire);
374
+ if (ABSL_PREDICT_FALSE(one_word_val == UninitializedFlagValue())) {
375
+ return false;
376
+ }
377
+ std::memcpy(&dst, static_cast<const void*>(&one_word_val), sizeof(T));
378
+ return true;
379
+ }
380
+ };
381
+
382
+ template <typename T>
383
+ struct FlagValue<T, FlagValueStorageKind::kSequenceLocked> {
384
+ bool Get(const SequenceLock& lock, T& dst) const {
385
+ return lock.TryRead(&dst, value_words, sizeof(T));
386
+ }
387
+
388
+ static constexpr int kNumWords =
389
+ flags_internal::AlignUp(sizeof(T), sizeof(uint64_t)) / sizeof(uint64_t);
390
+
391
+ alignas(T) alignas(
392
+ std::atomic<uint64_t>) std::atomic<uint64_t> value_words[kNumWords];
393
+ };
394
+
395
+ template <typename T>
396
+ struct FlagValue<T, FlagValueStorageKind::kAlignedBuffer> {
397
+ bool Get(const SequenceLock&, T&) const { return false; }
398
+
399
+ alignas(T) char value[sizeof(T)];
400
+ };
401
+
402
+ ///////////////////////////////////////////////////////////////////////////////
403
+ // Flag callback auxiliary structs.
404
+
405
+ // Signature for the mutation callback used by watched Flags
406
+ // The callback is noexcept.
407
+ // TODO(rogeeff): add noexcept after C++17 support is added.
408
+ using FlagCallbackFunc = void (*)();
409
+
410
+ struct FlagCallback {
411
+ FlagCallbackFunc func;
412
+ absl::Mutex guard; // Guard for concurrent callback invocations.
413
+ };
414
+
415
+ ///////////////////////////////////////////////////////////////////////////////
416
+ // Flag implementation, which does not depend on flag value type.
417
+ // The class encapsulates the Flag's data and access to it.
418
+
419
+ struct DynValueDeleter {
420
+ explicit DynValueDeleter(FlagOpFn op_arg = nullptr);
421
+ void operator()(void* ptr) const;
422
+
423
+ FlagOpFn op;
424
+ };
425
+
426
+ class FlagState;
427
+
428
+ class FlagImpl final : public CommandLineFlag {
429
+ public:
430
+ constexpr FlagImpl(const char* name, const char* filename, FlagOpFn op,
431
+ FlagHelpArg help, FlagValueStorageKind value_kind,
432
+ FlagDefaultArg default_arg)
433
+ : name_(name),
434
+ filename_(filename),
435
+ op_(op),
436
+ help_(help.source),
437
+ help_source_kind_(static_cast<uint8_t>(help.kind)),
438
+ value_storage_kind_(static_cast<uint8_t>(value_kind)),
439
+ def_kind_(static_cast<uint8_t>(default_arg.kind)),
440
+ modified_(false),
441
+ on_command_line_(false),
442
+ callback_(nullptr),
443
+ default_value_(default_arg.source),
444
+ data_guard_{} {}
445
+
446
+ // Constant access methods
447
+ int64_t ReadOneWord() const ABSL_LOCKS_EXCLUDED(*DataGuard());
448
+ bool ReadOneBool() const ABSL_LOCKS_EXCLUDED(*DataGuard());
449
+ void Read(void* dst) const override ABSL_LOCKS_EXCLUDED(*DataGuard());
450
+ void Read(bool* value) const ABSL_LOCKS_EXCLUDED(*DataGuard()) {
451
+ *value = ReadOneBool();
452
+ }
453
+ template <typename T,
454
+ absl::enable_if_t<flags_internal::StorageKind<T>() ==
455
+ FlagValueStorageKind::kOneWordAtomic,
456
+ int> = 0>
457
+ void Read(T* value) const ABSL_LOCKS_EXCLUDED(*DataGuard()) {
458
+ int64_t v = ReadOneWord();
459
+ std::memcpy(value, static_cast<const void*>(&v), sizeof(T));
460
+ }
461
+ template <typename T,
462
+ typename std::enable_if<flags_internal::StorageKind<T>() ==
463
+ FlagValueStorageKind::kValueAndInitBit,
464
+ int>::type = 0>
465
+ void Read(T* value) const ABSL_LOCKS_EXCLUDED(*DataGuard()) {
466
+ *value = absl::bit_cast<FlagValueAndInitBit<T>>(ReadOneWord()).value;
467
+ }
468
+
469
+ // Mutating access methods
470
+ void Write(const void* src) ABSL_LOCKS_EXCLUDED(*DataGuard());
471
+
472
+ // Interfaces to operate on callbacks.
473
+ void SetCallback(const FlagCallbackFunc mutation_callback)
474
+ ABSL_LOCKS_EXCLUDED(*DataGuard());
475
+ void InvokeCallback() const ABSL_EXCLUSIVE_LOCKS_REQUIRED(*DataGuard());
476
+
477
+ // Used in read/write operations to validate source/target has correct type.
478
+ // For example if flag is declared as absl::Flag<int> FLAGS_foo, a call to
479
+ // absl::GetFlag(FLAGS_foo) validates that the type of FLAGS_foo is indeed
480
+ // int. To do that we pass the "assumed" type id (which is deduced from type
481
+ // int) as an argument `type_id`, which is in turn is validated against the
482
+ // type id stored in flag object by flag definition statement.
483
+ void AssertValidType(FlagFastTypeId type_id,
484
+ const std::type_info* (*gen_rtti)()) const;
485
+
486
+ private:
487
+ template <typename T>
488
+ friend class Flag;
489
+ friend class FlagState;
490
+
491
+ // Ensures that `data_guard_` is initialized and returns it.
492
+ absl::Mutex* DataGuard() const
493
+ ABSL_LOCK_RETURNED(reinterpret_cast<absl::Mutex*>(data_guard_));
494
+ // Returns heap allocated value of type T initialized with default value.
495
+ std::unique_ptr<void, DynValueDeleter> MakeInitValue() const
496
+ ABSL_EXCLUSIVE_LOCKS_REQUIRED(*DataGuard());
497
+ // Flag initialization called via absl::call_once.
498
+ void Init();
499
+
500
+ // Offset value access methods. One per storage kind. These methods to not
501
+ // respect const correctness, so be very carefull using them.
502
+
503
+ // This is a shared helper routine which encapsulates most of the magic. Since
504
+ // it is only used inside the three routines below, which are defined in
505
+ // flag.cc, we can define it in that file as well.
506
+ template <typename StorageT>
507
+ StorageT* OffsetValue() const;
508
+ // This is an accessor for a value stored in an aligned buffer storage
509
+ // used for non-trivially-copyable data types.
510
+ // Returns a mutable pointer to the start of a buffer.
511
+ void* AlignedBufferValue() const;
512
+
513
+ // The same as above, but used for sequencelock-protected storage.
514
+ std::atomic<uint64_t>* AtomicBufferValue() const;
515
+
516
+ // This is an accessor for a value stored as one word atomic. Returns a
517
+ // mutable reference to an atomic value.
518
+ std::atomic<int64_t>& OneWordValue() const;
519
+
520
+ // Attempts to parse supplied `value` string. If parsing is successful,
521
+ // returns new value. Otherwise returns nullptr.
522
+ std::unique_ptr<void, DynValueDeleter> TryParse(absl::string_view value,
523
+ std::string& err) const
524
+ ABSL_EXCLUSIVE_LOCKS_REQUIRED(*DataGuard());
525
+ // Stores the flag value based on the pointer to the source.
526
+ void StoreValue(const void* src) ABSL_EXCLUSIVE_LOCKS_REQUIRED(*DataGuard());
527
+
528
+ // Copy the flag data, protected by `seq_lock_` into `dst`.
529
+ //
530
+ // REQUIRES: ValueStorageKind() == kSequenceLocked.
531
+ void ReadSequenceLockedData(void* dst) const
532
+ ABSL_LOCKS_EXCLUDED(*DataGuard());
533
+
534
+ FlagHelpKind HelpSourceKind() const {
535
+ return static_cast<FlagHelpKind>(help_source_kind_);
536
+ }
537
+ FlagValueStorageKind ValueStorageKind() const {
538
+ return static_cast<FlagValueStorageKind>(value_storage_kind_);
539
+ }
540
+ FlagDefaultKind DefaultKind() const
541
+ ABSL_EXCLUSIVE_LOCKS_REQUIRED(*DataGuard()) {
542
+ return static_cast<FlagDefaultKind>(def_kind_);
543
+ }
544
+
545
+ // CommandLineFlag interface implementation
546
+ absl::string_view Name() const override;
547
+ std::string Filename() const override;
548
+ std::string Help() const override;
549
+ FlagFastTypeId TypeId() const override;
550
+ bool IsSpecifiedOnCommandLine() const override
551
+ ABSL_LOCKS_EXCLUDED(*DataGuard());
552
+ std::string DefaultValue() const override ABSL_LOCKS_EXCLUDED(*DataGuard());
553
+ std::string CurrentValue() const override ABSL_LOCKS_EXCLUDED(*DataGuard());
554
+ bool ValidateInputValue(absl::string_view value) const override
555
+ ABSL_LOCKS_EXCLUDED(*DataGuard());
556
+ void CheckDefaultValueParsingRoundtrip() const override
557
+ ABSL_LOCKS_EXCLUDED(*DataGuard());
558
+
559
+ int64_t ModificationCount() const ABSL_EXCLUSIVE_LOCKS_REQUIRED(*DataGuard());
560
+
561
+ // Interfaces to save and restore flags to/from persistent state.
562
+ // Returns current flag state or nullptr if flag does not support
563
+ // saving and restoring a state.
564
+ std::unique_ptr<FlagStateInterface> SaveState() override
565
+ ABSL_LOCKS_EXCLUDED(*DataGuard());
566
+
567
+ // Restores the flag state to the supplied state object. If there is
568
+ // nothing to restore returns false. Otherwise returns true.
569
+ bool RestoreState(const FlagState& flag_state)
570
+ ABSL_LOCKS_EXCLUDED(*DataGuard());
571
+
572
+ bool ParseFrom(absl::string_view value, FlagSettingMode set_mode,
573
+ ValueSource source, std::string& error) override
574
+ ABSL_LOCKS_EXCLUDED(*DataGuard());
575
+
576
+ // Immutable flag's state.
577
+
578
+ // Flags name passed to ABSL_FLAG as second arg.
579
+ const char* const name_;
580
+ // The file name where ABSL_FLAG resides.
581
+ const char* const filename_;
582
+ // Type-specific operations "vtable".
583
+ const FlagOpFn op_;
584
+ // Help message literal or function to generate it.
585
+ const FlagHelpMsg help_;
586
+ // Indicates if help message was supplied as literal or generator func.
587
+ const uint8_t help_source_kind_ : 1;
588
+ // Kind of storage this flag is using for the flag's value.
589
+ const uint8_t value_storage_kind_ : 2;
590
+
591
+ uint8_t : 0; // The bytes containing the const bitfields must not be
592
+ // shared with bytes containing the mutable bitfields.
593
+
594
+ // Mutable flag's state (guarded by `data_guard_`).
595
+
596
+ // def_kind_ is not guard by DataGuard() since it is accessed in Init without
597
+ // locks.
598
+ uint8_t def_kind_ : 2;
599
+ // Has this flag's value been modified?
600
+ bool modified_ : 1 ABSL_GUARDED_BY(*DataGuard());
601
+ // Has this flag been specified on command line.
602
+ bool on_command_line_ : 1 ABSL_GUARDED_BY(*DataGuard());
603
+
604
+ // Unique tag for absl::call_once call to initialize this flag.
605
+ absl::once_flag init_control_;
606
+
607
+ // Sequence lock / mutation counter.
608
+ flags_internal::SequenceLock seq_lock_;
609
+
610
+ // Optional flag's callback and absl::Mutex to guard the invocations.
611
+ FlagCallback* callback_ ABSL_GUARDED_BY(*DataGuard());
612
+ // Either a pointer to the function generating the default value based on the
613
+ // value specified in ABSL_FLAG or pointer to the dynamically set default
614
+ // value via SetCommandLineOptionWithMode. def_kind_ is used to distinguish
615
+ // these two cases.
616
+ FlagDefaultSrc default_value_;
617
+
618
+ // This is reserved space for an absl::Mutex to guard flag data. It will be
619
+ // initialized in FlagImpl::Init via placement new.
620
+ // We can't use "absl::Mutex data_guard_", since this class is not literal.
621
+ // We do not want to use "absl::Mutex* data_guard_", since this would require
622
+ // heap allocation during initialization, which is both slows program startup
623
+ // and can fail. Using reserved space + placement new allows us to avoid both
624
+ // problems.
625
+ alignas(absl::Mutex) mutable char data_guard_[sizeof(absl::Mutex)];
626
+ };
627
+
628
+ ///////////////////////////////////////////////////////////////////////////////
629
+ // The Flag object parameterized by the flag's value type. This class implements
630
+ // flag reflection handle interface.
631
+
632
+ template <typename T>
633
+ class Flag {
634
+ public:
635
+ constexpr Flag(const char* name, const char* filename, FlagHelpArg help,
636
+ const FlagDefaultArg default_arg)
637
+ : impl_(name, filename, &FlagOps<T>, help,
638
+ flags_internal::StorageKind<T>(), default_arg),
639
+ value_() {}
640
+
641
+ // CommandLineFlag interface
642
+ absl::string_view Name() const { return impl_.Name(); }
643
+ std::string Filename() const { return impl_.Filename(); }
644
+ std::string Help() const { return impl_.Help(); }
645
+ // Do not use. To be removed.
646
+ bool IsSpecifiedOnCommandLine() const {
647
+ return impl_.IsSpecifiedOnCommandLine();
648
+ }
649
+ std::string DefaultValue() const { return impl_.DefaultValue(); }
650
+ std::string CurrentValue() const { return impl_.CurrentValue(); }
651
+
652
+ private:
653
+ template <typename, bool>
654
+ friend class FlagRegistrar;
655
+ friend class FlagImplPeer;
656
+
657
+ T Get() const {
658
+ // See implementation notes in CommandLineFlag::Get().
659
+ union U {
660
+ T value;
661
+ U() {}
662
+ ~U() { value.~T(); }
663
+ };
664
+ U u;
665
+
666
+ #if !defined(NDEBUG)
667
+ impl_.AssertValidType(base_internal::FastTypeId<T>(), &GenRuntimeTypeId<T>);
668
+ #endif
669
+
670
+ if (ABSL_PREDICT_FALSE(!value_.Get(impl_.seq_lock_, u.value))) {
671
+ impl_.Read(&u.value);
672
+ }
673
+ return std::move(u.value);
674
+ }
675
+ void Set(const T& v) {
676
+ impl_.AssertValidType(base_internal::FastTypeId<T>(), &GenRuntimeTypeId<T>);
677
+ impl_.Write(&v);
678
+ }
679
+
680
+ // Access to the reflection.
681
+ const CommandLineFlag& Reflect() const { return impl_; }
682
+
683
+ // Flag's data
684
+ // The implementation depends on value_ field to be placed exactly after the
685
+ // impl_ field, so that impl_ can figure out the offset to the value and
686
+ // access it.
687
+ FlagImpl impl_;
688
+ FlagValue<T> value_;
689
+ };
690
+
691
+ ///////////////////////////////////////////////////////////////////////////////
692
+ // Trampoline for friend access
693
+
694
+ class FlagImplPeer {
695
+ public:
696
+ template <typename T, typename FlagType>
697
+ static T InvokeGet(const FlagType& flag) {
698
+ return flag.Get();
699
+ }
700
+ template <typename FlagType, typename T>
701
+ static void InvokeSet(FlagType& flag, const T& v) {
702
+ flag.Set(v);
703
+ }
704
+ template <typename FlagType>
705
+ static const CommandLineFlag& InvokeReflect(const FlagType& f) {
706
+ return f.Reflect();
707
+ }
708
+ };
709
+
710
+ ///////////////////////////////////////////////////////////////////////////////
711
+ // Implementation of Flag value specific operations routine.
712
+ template <typename T>
713
+ void* FlagOps(FlagOp op, const void* v1, void* v2, void* v3) {
714
+ switch (op) {
715
+ case FlagOp::kAlloc: {
716
+ std::allocator<T> alloc;
717
+ return std::allocator_traits<std::allocator<T>>::allocate(alloc, 1);
718
+ }
719
+ case FlagOp::kDelete: {
720
+ T* p = static_cast<T*>(v2);
721
+ p->~T();
722
+ std::allocator<T> alloc;
723
+ std::allocator_traits<std::allocator<T>>::deallocate(alloc, p, 1);
724
+ return nullptr;
725
+ }
726
+ case FlagOp::kCopy:
727
+ *static_cast<T*>(v2) = *static_cast<const T*>(v1);
728
+ return nullptr;
729
+ case FlagOp::kCopyConstruct:
730
+ new (v2) T(*static_cast<const T*>(v1));
731
+ return nullptr;
732
+ case FlagOp::kSizeof:
733
+ return reinterpret_cast<void*>(static_cast<uintptr_t>(sizeof(T)));
734
+ case FlagOp::kFastTypeId:
735
+ return const_cast<void*>(base_internal::FastTypeId<T>());
736
+ case FlagOp::kRuntimeTypeId:
737
+ return const_cast<std::type_info*>(GenRuntimeTypeId<T>());
738
+ case FlagOp::kParse: {
739
+ // Initialize the temporary instance of type T based on current value in
740
+ // destination (which is going to be flag's default value).
741
+ T temp(*static_cast<T*>(v2));
742
+ if (!absl::ParseFlag<T>(*static_cast<const absl::string_view*>(v1), &temp,
743
+ static_cast<std::string*>(v3))) {
744
+ return nullptr;
745
+ }
746
+ *static_cast<T*>(v2) = std::move(temp);
747
+ return v2;
748
+ }
749
+ case FlagOp::kUnparse:
750
+ *static_cast<std::string*>(v2) =
751
+ absl::UnparseFlag<T>(*static_cast<const T*>(v1));
752
+ return nullptr;
753
+ case FlagOp::kValueOffset: {
754
+ // Round sizeof(FlagImp) to a multiple of alignof(FlagValue<T>) to get the
755
+ // offset of the data.
756
+ size_t round_to = alignof(FlagValue<T>);
757
+ size_t offset =
758
+ (sizeof(FlagImpl) + round_to - 1) / round_to * round_to;
759
+ return reinterpret_cast<void*>(offset);
760
+ }
761
+ }
762
+ return nullptr;
763
+ }
764
+
765
+ ///////////////////////////////////////////////////////////////////////////////
766
+ // This class facilitates Flag object registration and tail expression-based
767
+ // flag definition, for example:
768
+ // ABSL_FLAG(int, foo, 42, "Foo help").OnUpdate(NotifyFooWatcher);
769
+ struct FlagRegistrarEmpty {};
770
+ template <typename T, bool do_register>
771
+ class FlagRegistrar {
772
+ public:
773
+ explicit FlagRegistrar(Flag<T>& flag, const char* filename) : flag_(flag) {
774
+ if (do_register)
775
+ flags_internal::RegisterCommandLineFlag(flag_.impl_, filename);
776
+ }
777
+
778
+ FlagRegistrar OnUpdate(FlagCallbackFunc cb) && {
779
+ flag_.impl_.SetCallback(cb);
780
+ return *this;
781
+ }
782
+
783
+ // Make the registrar "die" gracefully as an empty struct on a line where
784
+ // registration happens. Registrar objects are intended to live only as
785
+ // temporary.
786
+ operator FlagRegistrarEmpty() const { return {}; } // NOLINT
787
+
788
+ private:
789
+ Flag<T>& flag_; // Flag being registered (not owned).
790
+ };
791
+
792
+ } // namespace flags_internal
793
+ ABSL_NAMESPACE_END
794
+ } // namespace absl
795
+
796
+ #endif // ABSL_FLAGS_INTERNAL_FLAG_H_
weight/_dep/abseil-cpp/absl/flags/marshalling.cc ADDED
@@ -0,0 +1,291 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ //
2
+ // Copyright 2019 The Abseil Authors.
3
+ //
4
+ // Licensed under the Apache License, Version 2.0 (the "License");
5
+ // you may not use this file except in compliance with the License.
6
+ // You may obtain a copy of the License at
7
+ //
8
+ // https://www.apache.org/licenses/LICENSE-2.0
9
+ //
10
+ // Unless required by applicable law or agreed to in writing, software
11
+ // distributed under the License is distributed on an "AS IS" BASIS,
12
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ // See the License for the specific language governing permissions and
14
+ // limitations under the License.
15
+
16
+ #include "absl/flags/marshalling.h"
17
+
18
+ #include <stddef.h>
19
+
20
+ #include <cmath>
21
+ #include <limits>
22
+ #include <sstream>
23
+ #include <string>
24
+ #include <type_traits>
25
+ #include <vector>
26
+
27
+ #include "absl/base/config.h"
28
+ #include "absl/base/log_severity.h"
29
+ #include "absl/base/macros.h"
30
+ #include "absl/numeric/int128.h"
31
+ #include "absl/strings/ascii.h"
32
+ #include "absl/strings/match.h"
33
+ #include "absl/strings/numbers.h"
34
+ #include "absl/strings/str_cat.h"
35
+ #include "absl/strings/str_format.h"
36
+ #include "absl/strings/str_join.h"
37
+ #include "absl/strings/str_split.h"
38
+ #include "absl/strings/string_view.h"
39
+
40
+ namespace absl {
41
+ ABSL_NAMESPACE_BEGIN
42
+ namespace flags_internal {
43
+
44
+ // --------------------------------------------------------------------
45
+ // AbslParseFlag specializations for boolean type.
46
+
47
+ bool AbslParseFlag(absl::string_view text, bool* dst, std::string*) {
48
+ const char* kTrue[] = {"1", "t", "true", "y", "yes"};
49
+ const char* kFalse[] = {"0", "f", "false", "n", "no"};
50
+ static_assert(sizeof(kTrue) == sizeof(kFalse), "true_false_equal");
51
+
52
+ text = absl::StripAsciiWhitespace(text);
53
+
54
+ for (size_t i = 0; i < ABSL_ARRAYSIZE(kTrue); ++i) {
55
+ if (absl::EqualsIgnoreCase(text, kTrue[i])) {
56
+ *dst = true;
57
+ return true;
58
+ } else if (absl::EqualsIgnoreCase(text, kFalse[i])) {
59
+ *dst = false;
60
+ return true;
61
+ }
62
+ }
63
+ return false; // didn't match a legal input
64
+ }
65
+
66
+ // --------------------------------------------------------------------
67
+ // AbslParseFlag for integral types.
68
+
69
+ // Return the base to use for parsing text as an integer. Leading 0x
70
+ // puts us in base 16. But leading 0 does not put us in base 8. It
71
+ // caused too many bugs when we had that behavior.
72
+ static int NumericBase(absl::string_view text) {
73
+ if (text.empty()) return 0;
74
+ size_t num_start = (text[0] == '-' || text[0] == '+') ? 1 : 0;
75
+ const bool hex = (text.size() >= num_start + 2 && text[num_start] == '0' &&
76
+ (text[num_start + 1] == 'x' || text[num_start + 1] == 'X'));
77
+ return hex ? 16 : 10;
78
+ }
79
+
80
+ template <typename IntType>
81
+ inline bool ParseFlagImpl(absl::string_view text, IntType& dst) {
82
+ text = absl::StripAsciiWhitespace(text);
83
+
84
+ return absl::numbers_internal::safe_strtoi_base(text, &dst,
85
+ NumericBase(text));
86
+ }
87
+
88
+ bool AbslParseFlag(absl::string_view text, short* dst, std::string*) {
89
+ int val;
90
+ if (!ParseFlagImpl(text, val)) return false;
91
+ if (static_cast<short>(val) != val) // worked, but number out of range
92
+ return false;
93
+ *dst = static_cast<short>(val);
94
+ return true;
95
+ }
96
+
97
+ bool AbslParseFlag(absl::string_view text, unsigned short* dst, std::string*) {
98
+ unsigned int val;
99
+ if (!ParseFlagImpl(text, val)) return false;
100
+ if (static_cast<unsigned short>(val) !=
101
+ val) // worked, but number out of range
102
+ return false;
103
+ *dst = static_cast<unsigned short>(val);
104
+ return true;
105
+ }
106
+
107
+ bool AbslParseFlag(absl::string_view text, int* dst, std::string*) {
108
+ return ParseFlagImpl(text, *dst);
109
+ }
110
+
111
+ bool AbslParseFlag(absl::string_view text, unsigned int* dst, std::string*) {
112
+ return ParseFlagImpl(text, *dst);
113
+ }
114
+
115
+ bool AbslParseFlag(absl::string_view text, long* dst, std::string*) {
116
+ return ParseFlagImpl(text, *dst);
117
+ }
118
+
119
+ bool AbslParseFlag(absl::string_view text, unsigned long* dst, std::string*) {
120
+ return ParseFlagImpl(text, *dst);
121
+ }
122
+
123
+ bool AbslParseFlag(absl::string_view text, long long* dst, std::string*) {
124
+ return ParseFlagImpl(text, *dst);
125
+ }
126
+
127
+ bool AbslParseFlag(absl::string_view text, unsigned long long* dst,
128
+ std::string*) {
129
+ return ParseFlagImpl(text, *dst);
130
+ }
131
+
132
+ bool AbslParseFlag(absl::string_view text, absl::int128* dst, std::string*) {
133
+ text = absl::StripAsciiWhitespace(text);
134
+
135
+ // check hex
136
+ int base = NumericBase(text);
137
+ if (!absl::numbers_internal::safe_strto128_base(text, dst, base)) {
138
+ return false;
139
+ }
140
+
141
+ return base == 16 ? absl::SimpleHexAtoi(text, dst)
142
+ : absl::SimpleAtoi(text, dst);
143
+ }
144
+
145
+ bool AbslParseFlag(absl::string_view text, absl::uint128* dst, std::string*) {
146
+ text = absl::StripAsciiWhitespace(text);
147
+
148
+ // check hex
149
+ int base = NumericBase(text);
150
+ if (!absl::numbers_internal::safe_strtou128_base(text, dst, base)) {
151
+ return false;
152
+ }
153
+
154
+ return base == 16 ? absl::SimpleHexAtoi(text, dst)
155
+ : absl::SimpleAtoi(text, dst);
156
+ }
157
+
158
+ // --------------------------------------------------------------------
159
+ // AbslParseFlag for floating point types.
160
+
161
+ bool AbslParseFlag(absl::string_view text, float* dst, std::string*) {
162
+ return absl::SimpleAtof(text, dst);
163
+ }
164
+
165
+ bool AbslParseFlag(absl::string_view text, double* dst, std::string*) {
166
+ return absl::SimpleAtod(text, dst);
167
+ }
168
+
169
+ // --------------------------------------------------------------------
170
+ // AbslParseFlag for strings.
171
+
172
+ bool AbslParseFlag(absl::string_view text, std::string* dst, std::string*) {
173
+ dst->assign(text.data(), text.size());
174
+ return true;
175
+ }
176
+
177
+ // --------------------------------------------------------------------
178
+ // AbslParseFlag for vector of strings.
179
+
180
+ bool AbslParseFlag(absl::string_view text, std::vector<std::string>* dst,
181
+ std::string*) {
182
+ // An empty flag value corresponds to an empty vector, not a vector
183
+ // with a single, empty std::string.
184
+ if (text.empty()) {
185
+ dst->clear();
186
+ return true;
187
+ }
188
+ *dst = absl::StrSplit(text, ',', absl::AllowEmpty());
189
+ return true;
190
+ }
191
+
192
+ // --------------------------------------------------------------------
193
+ // AbslUnparseFlag specializations for various builtin flag types.
194
+
195
+ std::string Unparse(bool v) { return v ? "true" : "false"; }
196
+ std::string Unparse(short v) { return absl::StrCat(v); }
197
+ std::string Unparse(unsigned short v) { return absl::StrCat(v); }
198
+ std::string Unparse(int v) { return absl::StrCat(v); }
199
+ std::string Unparse(unsigned int v) { return absl::StrCat(v); }
200
+ std::string Unparse(long v) { return absl::StrCat(v); }
201
+ std::string Unparse(unsigned long v) { return absl::StrCat(v); }
202
+ std::string Unparse(long long v) { return absl::StrCat(v); }
203
+ std::string Unparse(unsigned long long v) { return absl::StrCat(v); }
204
+ std::string Unparse(absl::int128 v) {
205
+ std::stringstream ss;
206
+ ss << v;
207
+ return ss.str();
208
+ }
209
+ std::string Unparse(absl::uint128 v) {
210
+ std::stringstream ss;
211
+ ss << v;
212
+ return ss.str();
213
+ }
214
+
215
+ template <typename T>
216
+ std::string UnparseFloatingPointVal(T v) {
217
+ // digits10 is guaranteed to roundtrip correctly in string -> value -> string
218
+ // conversions, but may not be enough to represent all the values correctly.
219
+ std::string digit10_str =
220
+ absl::StrFormat("%.*g", std::numeric_limits<T>::digits10, v);
221
+ if (std::isnan(v) || std::isinf(v)) return digit10_str;
222
+
223
+ T roundtrip_val = 0;
224
+ std::string err;
225
+ if (absl::ParseFlag(digit10_str, &roundtrip_val, &err) &&
226
+ roundtrip_val == v) {
227
+ return digit10_str;
228
+ }
229
+
230
+ // max_digits10 is the number of base-10 digits that are necessary to uniquely
231
+ // represent all distinct values.
232
+ return absl::StrFormat("%.*g", std::numeric_limits<T>::max_digits10, v);
233
+ }
234
+ std::string Unparse(float v) { return UnparseFloatingPointVal(v); }
235
+ std::string Unparse(double v) { return UnparseFloatingPointVal(v); }
236
+ std::string AbslUnparseFlag(absl::string_view v) { return std::string(v); }
237
+ std::string AbslUnparseFlag(const std::vector<std::string>& v) {
238
+ return absl::StrJoin(v, ",");
239
+ }
240
+
241
+ } // namespace flags_internal
242
+
243
+ bool AbslParseFlag(absl::string_view text, absl::LogSeverity* dst,
244
+ std::string* err) {
245
+ text = absl::StripAsciiWhitespace(text);
246
+ if (text.empty()) {
247
+ *err = "no value provided";
248
+ return false;
249
+ }
250
+ if (absl::EqualsIgnoreCase(text, "dfatal")) {
251
+ *dst = absl::kLogDebugFatal;
252
+ return true;
253
+ }
254
+ if (absl::EqualsIgnoreCase(text, "klogdebugfatal")) {
255
+ *dst = absl::kLogDebugFatal;
256
+ return true;
257
+ }
258
+ if (text.front() == 'k' || text.front() == 'K') text.remove_prefix(1);
259
+ if (absl::EqualsIgnoreCase(text, "info")) {
260
+ *dst = absl::LogSeverity::kInfo;
261
+ return true;
262
+ }
263
+ if (absl::EqualsIgnoreCase(text, "warning")) {
264
+ *dst = absl::LogSeverity::kWarning;
265
+ return true;
266
+ }
267
+ if (absl::EqualsIgnoreCase(text, "error")) {
268
+ *dst = absl::LogSeverity::kError;
269
+ return true;
270
+ }
271
+ if (absl::EqualsIgnoreCase(text, "fatal")) {
272
+ *dst = absl::LogSeverity::kFatal;
273
+ return true;
274
+ }
275
+ std::underlying_type<absl::LogSeverity>::type numeric_value;
276
+ if (absl::ParseFlag(text, &numeric_value, err)) {
277
+ *dst = static_cast<absl::LogSeverity>(numeric_value);
278
+ return true;
279
+ }
280
+ *err =
281
+ "only integers, absl::LogSeverity enumerators, and DFATAL are accepted";
282
+ return false;
283
+ }
284
+
285
+ std::string AbslUnparseFlag(absl::LogSeverity v) {
286
+ if (v == absl::NormalizeLogSeverity(v)) return absl::LogSeverityName(v);
287
+ return absl::UnparseFlag(static_cast<int>(v));
288
+ }
289
+
290
+ ABSL_NAMESPACE_END
291
+ } // namespace absl
weight/_dep/abseil-cpp/absl/flags/parse.cc ADDED
@@ -0,0 +1,943 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ //
2
+ // Copyright 2019 The Abseil Authors.
3
+ //
4
+ // Licensed under the Apache License, Version 2.0 (the "License");
5
+ // you may not use this file except in compliance with the License.
6
+ // You may obtain a copy of the License at
7
+ //
8
+ // https://www.apache.org/licenses/LICENSE-2.0
9
+ //
10
+ // Unless required by applicable law or agreed to in writing, software
11
+ // distributed under the License is distributed on an "AS IS" BASIS,
12
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ // See the License for the specific language governing permissions and
14
+ // limitations under the License.
15
+
16
+ #include "absl/flags/parse.h"
17
+
18
+ #include <stdlib.h>
19
+
20
+ #include <algorithm>
21
+ #include <cstdint>
22
+ #include <cstdlib>
23
+ #include <fstream>
24
+ #include <iostream>
25
+ #include <ostream>
26
+ #include <string>
27
+ #include <tuple>
28
+ #include <utility>
29
+ #include <vector>
30
+
31
+ #ifdef _WIN32
32
+ #include <windows.h>
33
+ #endif
34
+
35
+ #include "absl/algorithm/container.h"
36
+ #include "absl/base/attributes.h"
37
+ #include "absl/base/config.h"
38
+ #include "absl/base/const_init.h"
39
+ #include "absl/base/thread_annotations.h"
40
+ #include "absl/flags/commandlineflag.h"
41
+ #include "absl/flags/config.h"
42
+ #include "absl/flags/flag.h"
43
+ #include "absl/flags/internal/commandlineflag.h"
44
+ #include "absl/flags/internal/flag.h"
45
+ #include "absl/flags/internal/parse.h"
46
+ #include "absl/flags/internal/private_handle_accessor.h"
47
+ #include "absl/flags/internal/program_name.h"
48
+ #include "absl/flags/internal/usage.h"
49
+ #include "absl/flags/reflection.h"
50
+ #include "absl/flags/usage.h"
51
+ #include "absl/flags/usage_config.h"
52
+ #include "absl/strings/ascii.h"
53
+ #include "absl/strings/internal/damerau_levenshtein_distance.h"
54
+ #include "absl/strings/str_cat.h"
55
+ #include "absl/strings/str_join.h"
56
+ #include "absl/strings/string_view.h"
57
+ #include "absl/strings/strip.h"
58
+ #include "absl/synchronization/mutex.h"
59
+
60
+ // --------------------------------------------------------------------
61
+
62
+ namespace absl {
63
+ ABSL_NAMESPACE_BEGIN
64
+ namespace flags_internal {
65
+ namespace {
66
+
67
+ ABSL_CONST_INIT absl::Mutex processing_checks_guard(absl::kConstInit);
68
+
69
+ ABSL_CONST_INIT bool flagfile_needs_processing
70
+ ABSL_GUARDED_BY(processing_checks_guard) = false;
71
+ ABSL_CONST_INIT bool fromenv_needs_processing
72
+ ABSL_GUARDED_BY(processing_checks_guard) = false;
73
+ ABSL_CONST_INIT bool tryfromenv_needs_processing
74
+ ABSL_GUARDED_BY(processing_checks_guard) = false;
75
+
76
+ ABSL_CONST_INIT absl::Mutex specified_flags_guard(absl::kConstInit);
77
+ ABSL_CONST_INIT std::vector<const CommandLineFlag*>* specified_flags
78
+ ABSL_GUARDED_BY(specified_flags_guard) = nullptr;
79
+
80
+ // Suggesting at most kMaxHints flags in case of misspellings.
81
+ ABSL_CONST_INIT const size_t kMaxHints = 100;
82
+ // Suggesting only flags which have a smaller distance than kMaxDistance.
83
+ ABSL_CONST_INIT const size_t kMaxDistance = 3;
84
+
85
+ struct SpecifiedFlagsCompare {
86
+ bool operator()(const CommandLineFlag* a, const CommandLineFlag* b) const {
87
+ return a->Name() < b->Name();
88
+ }
89
+ bool operator()(const CommandLineFlag* a, absl::string_view b) const {
90
+ return a->Name() < b;
91
+ }
92
+ bool operator()(absl::string_view a, const CommandLineFlag* b) const {
93
+ return a < b->Name();
94
+ }
95
+ };
96
+
97
+ } // namespace
98
+ } // namespace flags_internal
99
+ ABSL_NAMESPACE_END
100
+ } // namespace absl
101
+
102
+ // These flags influence how command line flags are parsed and are only intended
103
+ // to be set on the command line. Avoid reading or setting them from C++ code.
104
+ ABSL_FLAG(std::vector<std::string>, flagfile, {},
105
+ "comma-separated list of files to load flags from")
106
+ .OnUpdate([]() {
107
+ if (absl::GetFlag(FLAGS_flagfile).empty()) return;
108
+
109
+ absl::MutexLock l(&absl::flags_internal::processing_checks_guard);
110
+
111
+ // Setting this flag twice before it is handled most likely an internal
112
+ // error and should be reviewed by developers.
113
+ if (absl::flags_internal::flagfile_needs_processing) {
114
+ ABSL_INTERNAL_LOG(WARNING, "flagfile set twice before it is handled");
115
+ }
116
+
117
+ absl::flags_internal::flagfile_needs_processing = true;
118
+ });
119
+ ABSL_FLAG(std::vector<std::string>, fromenv, {},
120
+ "comma-separated list of flags to set from the environment"
121
+ " [use 'export FLAGS_flag1=value']")
122
+ .OnUpdate([]() {
123
+ if (absl::GetFlag(FLAGS_fromenv).empty()) return;
124
+
125
+ absl::MutexLock l(&absl::flags_internal::processing_checks_guard);
126
+
127
+ // Setting this flag twice before it is handled most likely an internal
128
+ // error and should be reviewed by developers.
129
+ if (absl::flags_internal::fromenv_needs_processing) {
130
+ ABSL_INTERNAL_LOG(WARNING, "fromenv set twice before it is handled.");
131
+ }
132
+
133
+ absl::flags_internal::fromenv_needs_processing = true;
134
+ });
135
+ ABSL_FLAG(std::vector<std::string>, tryfromenv, {},
136
+ "comma-separated list of flags to try to set from the environment if "
137
+ "present")
138
+ .OnUpdate([]() {
139
+ if (absl::GetFlag(FLAGS_tryfromenv).empty()) return;
140
+
141
+ absl::MutexLock l(&absl::flags_internal::processing_checks_guard);
142
+
143
+ // Setting this flag twice before it is handled most likely an internal
144
+ // error and should be reviewed by developers.
145
+ if (absl::flags_internal::tryfromenv_needs_processing) {
146
+ ABSL_INTERNAL_LOG(WARNING,
147
+ "tryfromenv set twice before it is handled.");
148
+ }
149
+
150
+ absl::flags_internal::tryfromenv_needs_processing = true;
151
+ });
152
+
153
+ // Rather than reading or setting --undefok from C++ code, please consider using
154
+ // ABSL_RETIRED_FLAG instead.
155
+ ABSL_FLAG(std::vector<std::string>, undefok, {},
156
+ "comma-separated list of flag names that it is okay to specify "
157
+ "on the command line even if the program does not define a flag "
158
+ "with that name");
159
+
160
+ namespace absl {
161
+ ABSL_NAMESPACE_BEGIN
162
+ namespace flags_internal {
163
+
164
+ namespace {
165
+
166
+ class ArgsList {
167
+ public:
168
+ ArgsList() : next_arg_(0) {}
169
+ ArgsList(int argc, char* argv[]) : args_(argv, argv + argc), next_arg_(0) {}
170
+ explicit ArgsList(const std::vector<std::string>& args)
171
+ : args_(args), next_arg_(0) {}
172
+
173
+ // Returns success status: true if parsing successful, false otherwise.
174
+ bool ReadFromFlagfile(const std::string& flag_file_name);
175
+
176
+ size_t Size() const { return args_.size() - next_arg_; }
177
+ size_t FrontIndex() const { return next_arg_; }
178
+ absl::string_view Front() const { return args_[next_arg_]; }
179
+ void PopFront() { next_arg_++; }
180
+
181
+ private:
182
+ std::vector<std::string> args_;
183
+ size_t next_arg_;
184
+ };
185
+
186
+ bool ArgsList::ReadFromFlagfile(const std::string& flag_file_name) {
187
+ std::ifstream flag_file(flag_file_name);
188
+
189
+ if (!flag_file) {
190
+ flags_internal::ReportUsageError(
191
+ absl::StrCat("Can't open flagfile ", flag_file_name), true);
192
+
193
+ return false;
194
+ }
195
+
196
+ // This argument represents fake argv[0], which should be present in all arg
197
+ // lists.
198
+ args_.emplace_back("");
199
+
200
+ std::string line;
201
+ bool success = true;
202
+
203
+ while (std::getline(flag_file, line)) {
204
+ absl::string_view stripped = absl::StripLeadingAsciiWhitespace(line);
205
+
206
+ if (stripped.empty() || stripped[0] == '#') {
207
+ // Comment or empty line; just ignore.
208
+ continue;
209
+ }
210
+
211
+ if (stripped[0] == '-') {
212
+ if (stripped == "--") {
213
+ flags_internal::ReportUsageError(
214
+ "Flagfile can't contain position arguments or --", true);
215
+
216
+ success = false;
217
+ break;
218
+ }
219
+
220
+ args_.emplace_back(stripped);
221
+ continue;
222
+ }
223
+
224
+ flags_internal::ReportUsageError(
225
+ absl::StrCat("Unexpected line in the flagfile ", flag_file_name, ": ",
226
+ line),
227
+ true);
228
+
229
+ success = false;
230
+ }
231
+
232
+ return success;
233
+ }
234
+
235
+ // --------------------------------------------------------------------
236
+
237
+ // Reads the environment variable with name `name` and stores results in
238
+ // `value`. If variable is not present in environment returns false, otherwise
239
+ // returns true.
240
+ bool GetEnvVar(const char* var_name, std::string& var_value) {
241
+ #ifdef _WIN32
242
+ char buf[1024];
243
+ auto get_res = GetEnvironmentVariableA(var_name, buf, sizeof(buf));
244
+ if (get_res >= sizeof(buf)) {
245
+ return false;
246
+ }
247
+
248
+ if (get_res == 0) {
249
+ return false;
250
+ }
251
+
252
+ var_value = std::string(buf, get_res);
253
+ #else
254
+ const char* val = ::getenv(var_name);
255
+ if (val == nullptr) {
256
+ return false;
257
+ }
258
+
259
+ var_value = val;
260
+ #endif
261
+
262
+ return true;
263
+ }
264
+
265
+ // --------------------------------------------------------------------
266
+
267
+ // Returns:
268
+ // Flag name or empty if arg= --
269
+ // Flag value after = in --flag=value (empty if --foo)
270
+ // "Is empty value" status. True if arg= --foo=, false otherwise. This is
271
+ // required to separate --foo from --foo=.
272
+ // For example:
273
+ // arg return values
274
+ // "--foo=bar" -> {"foo", "bar", false}.
275
+ // "--foo" -> {"foo", "", false}.
276
+ // "--foo=" -> {"foo", "", true}.
277
+ std::tuple<absl::string_view, absl::string_view, bool> SplitNameAndValue(
278
+ absl::string_view arg) {
279
+ // Allow -foo and --foo
280
+ absl::ConsumePrefix(&arg, "-");
281
+
282
+ if (arg.empty()) {
283
+ return std::make_tuple("", "", false);
284
+ }
285
+
286
+ auto equal_sign_pos = arg.find('=');
287
+
288
+ absl::string_view flag_name = arg.substr(0, equal_sign_pos);
289
+
290
+ absl::string_view value;
291
+ bool is_empty_value = false;
292
+
293
+ if (equal_sign_pos != absl::string_view::npos) {
294
+ value = arg.substr(equal_sign_pos + 1);
295
+ is_empty_value = value.empty();
296
+ }
297
+
298
+ return std::make_tuple(flag_name, value, is_empty_value);
299
+ }
300
+
301
+ // --------------------------------------------------------------------
302
+
303
+ // Returns:
304
+ // found flag or nullptr
305
+ // is negative in case of --nofoo
306
+ std::tuple<CommandLineFlag*, bool> LocateFlag(absl::string_view flag_name) {
307
+ CommandLineFlag* flag = absl::FindCommandLineFlag(flag_name);
308
+ bool is_negative = false;
309
+
310
+ if (!flag && absl::ConsumePrefix(&flag_name, "no")) {
311
+ flag = absl::FindCommandLineFlag(flag_name);
312
+ is_negative = true;
313
+ }
314
+
315
+ return std::make_tuple(flag, is_negative);
316
+ }
317
+
318
+ // --------------------------------------------------------------------
319
+
320
+ // Verify that default values of typed flags must be convertible to string and
321
+ // back.
322
+ void CheckDefaultValuesParsingRoundtrip() {
323
+ #ifndef NDEBUG
324
+ flags_internal::ForEachFlag([&](CommandLineFlag& flag) {
325
+ if (flag.IsRetired()) return;
326
+
327
+ #define ABSL_FLAGS_INTERNAL_IGNORE_TYPE(T, _) \
328
+ if (flag.IsOfType<T>()) return;
329
+
330
+ ABSL_FLAGS_INTERNAL_SUPPORTED_TYPES(ABSL_FLAGS_INTERNAL_IGNORE_TYPE)
331
+ #undef ABSL_FLAGS_INTERNAL_IGNORE_TYPE
332
+
333
+ flags_internal::PrivateHandleAccessor::CheckDefaultValueParsingRoundtrip(
334
+ flag);
335
+ });
336
+ #endif
337
+ }
338
+
339
+ // --------------------------------------------------------------------
340
+
341
+ // Returns success status, which is true if we successfully read all flag files,
342
+ // in which case new ArgLists are appended to the input_args in a reverse order
343
+ // of file names in the input flagfiles list. This order ensures that flags from
344
+ // the first flagfile in the input list are processed before the second flagfile
345
+ // etc.
346
+ bool ReadFlagfiles(const std::vector<std::string>& flagfiles,
347
+ std::vector<ArgsList>& input_args) {
348
+ bool success = true;
349
+ for (auto it = flagfiles.rbegin(); it != flagfiles.rend(); ++it) {
350
+ ArgsList al;
351
+
352
+ if (al.ReadFromFlagfile(*it)) {
353
+ input_args.push_back(al);
354
+ } else {
355
+ success = false;
356
+ }
357
+ }
358
+
359
+ return success;
360
+ }
361
+
362
+ // Returns success status, which is true if were able to locate all environment
363
+ // variables correctly or if fail_on_absent_in_env is false. The environment
364
+ // variable names are expected to be of the form `FLAGS_<flag_name>`, where
365
+ // `flag_name` is a string from the input flag_names list. If successful we
366
+ // append a single ArgList at the end of the input_args.
367
+ bool ReadFlagsFromEnv(const std::vector<std::string>& flag_names,
368
+ std::vector<ArgsList>& input_args,
369
+ bool fail_on_absent_in_env) {
370
+ bool success = true;
371
+ std::vector<std::string> args;
372
+
373
+ // This argument represents fake argv[0], which should be present in all arg
374
+ // lists.
375
+ args.emplace_back("");
376
+
377
+ for (const auto& flag_name : flag_names) {
378
+ // Avoid infinite recursion.
379
+ if (flag_name == "fromenv" || flag_name == "tryfromenv") {
380
+ flags_internal::ReportUsageError(
381
+ absl::StrCat("Infinite recursion on flag ", flag_name), true);
382
+
383
+ success = false;
384
+ continue;
385
+ }
386
+
387
+ const std::string envname = absl::StrCat("FLAGS_", flag_name);
388
+ std::string envval;
389
+ if (!GetEnvVar(envname.c_str(), envval)) {
390
+ if (fail_on_absent_in_env) {
391
+ flags_internal::ReportUsageError(
392
+ absl::StrCat(envname, " not found in environment"), true);
393
+
394
+ success = false;
395
+ }
396
+
397
+ continue;
398
+ }
399
+
400
+ args.push_back(absl::StrCat("--", flag_name, "=", envval));
401
+ }
402
+
403
+ if (success) {
404
+ input_args.emplace_back(args);
405
+ }
406
+
407
+ return success;
408
+ }
409
+
410
+ // --------------------------------------------------------------------
411
+
412
+ // Returns success status, which is true if were able to handle all generator
413
+ // flags (flagfile, fromenv, tryfromemv) successfully.
414
+ bool HandleGeneratorFlags(std::vector<ArgsList>& input_args,
415
+ std::vector<std::string>& flagfile_value) {
416
+ bool success = true;
417
+
418
+ absl::MutexLock l(&flags_internal::processing_checks_guard);
419
+
420
+ // flagfile could have been set either on a command line or
421
+ // programmatically before invoking ParseCommandLine. Note that we do not
422
+ // actually process arguments specified in the flagfile, but instead
423
+ // create a secondary arguments list to be processed along with the rest
424
+ // of the command line arguments. Since we always the process most recently
425
+ // created list of arguments first, this will result in flagfile argument
426
+ // being processed before any other argument in the command line. If
427
+ // FLAGS_flagfile contains more than one file name we create multiple new
428
+ // levels of arguments in a reverse order of file names. Thus we always
429
+ // process arguments from first file before arguments containing in a
430
+ // second file, etc. If flagfile contains another
431
+ // --flagfile inside of it, it will produce new level of arguments and
432
+ // processed before the rest of the flagfile. We are also collecting all
433
+ // flagfiles set on original command line. Unlike the rest of the flags,
434
+ // this flag can be set multiple times and is expected to be handled
435
+ // multiple times. We are collecting them all into a single list and set
436
+ // the value of FLAGS_flagfile to that value at the end of the parsing.
437
+ if (flags_internal::flagfile_needs_processing) {
438
+ auto flagfiles = absl::GetFlag(FLAGS_flagfile);
439
+
440
+ if (input_args.size() == 1) {
441
+ flagfile_value.insert(flagfile_value.end(), flagfiles.begin(),
442
+ flagfiles.end());
443
+ }
444
+
445
+ success &= ReadFlagfiles(flagfiles, input_args);
446
+
447
+ flags_internal::flagfile_needs_processing = false;
448
+ }
449
+
450
+ // Similar to flagfile fromenv/tryfromemv can be set both
451
+ // programmatically and at runtime on a command line. Unlike flagfile these
452
+ // can't be recursive.
453
+ if (flags_internal::fromenv_needs_processing) {
454
+ auto flags_list = absl::GetFlag(FLAGS_fromenv);
455
+
456
+ success &= ReadFlagsFromEnv(flags_list, input_args, true);
457
+
458
+ flags_internal::fromenv_needs_processing = false;
459
+ }
460
+
461
+ if (flags_internal::tryfromenv_needs_processing) {
462
+ auto flags_list = absl::GetFlag(FLAGS_tryfromenv);
463
+
464
+ success &= ReadFlagsFromEnv(flags_list, input_args, false);
465
+
466
+ flags_internal::tryfromenv_needs_processing = false;
467
+ }
468
+
469
+ return success;
470
+ }
471
+
472
+ // --------------------------------------------------------------------
473
+
474
+ void ResetGeneratorFlags(const std::vector<std::string>& flagfile_value) {
475
+ // Setting flagfile to the value which collates all the values set on a
476
+ // command line and programmatically. So if command line looked like
477
+ // --flagfile=f1 --flagfile=f2 the final value of the FLAGS_flagfile flag is
478
+ // going to be {"f1", "f2"}
479
+ if (!flagfile_value.empty()) {
480
+ absl::SetFlag(&FLAGS_flagfile, flagfile_value);
481
+ absl::MutexLock l(&flags_internal::processing_checks_guard);
482
+ flags_internal::flagfile_needs_processing = false;
483
+ }
484
+
485
+ // fromenv/tryfromenv are set to <undefined> value.
486
+ if (!absl::GetFlag(FLAGS_fromenv).empty()) {
487
+ absl::SetFlag(&FLAGS_fromenv, {});
488
+ }
489
+ if (!absl::GetFlag(FLAGS_tryfromenv).empty()) {
490
+ absl::SetFlag(&FLAGS_tryfromenv, {});
491
+ }
492
+
493
+ absl::MutexLock l(&flags_internal::processing_checks_guard);
494
+ flags_internal::fromenv_needs_processing = false;
495
+ flags_internal::tryfromenv_needs_processing = false;
496
+ }
497
+
498
+ // --------------------------------------------------------------------
499
+
500
+ // Returns:
501
+ // success status
502
+ // deduced value
503
+ // We are also mutating curr_list in case if we need to get a hold of next
504
+ // argument in the input.
505
+ std::tuple<bool, absl::string_view> DeduceFlagValue(const CommandLineFlag& flag,
506
+ absl::string_view value,
507
+ bool is_negative,
508
+ bool is_empty_value,
509
+ ArgsList* curr_list) {
510
+ // Value is either an argument suffix after `=` in "--foo=<value>"
511
+ // or separate argument in case of "--foo" "<value>".
512
+
513
+ // boolean flags have these forms:
514
+ // --foo
515
+ // --nofoo
516
+ // --foo=true
517
+ // --foo=false
518
+ // --nofoo=<value> is not supported
519
+ // --foo <value> is not supported
520
+
521
+ // non boolean flags have these forms:
522
+ // --foo=<value>
523
+ // --foo <value>
524
+ // --nofoo is not supported
525
+
526
+ if (flag.IsOfType<bool>()) {
527
+ if (value.empty()) {
528
+ if (is_empty_value) {
529
+ // "--bool_flag=" case
530
+ flags_internal::ReportUsageError(
531
+ absl::StrCat(
532
+ "Missing the value after assignment for the boolean flag '",
533
+ flag.Name(), "'"),
534
+ true);
535
+ return std::make_tuple(false, "");
536
+ }
537
+
538
+ // "--bool_flag" case
539
+ value = is_negative ? "0" : "1";
540
+ } else if (is_negative) {
541
+ // "--nobool_flag=Y" case
542
+ flags_internal::ReportUsageError(
543
+ absl::StrCat("Negative form with assignment is not valid for the "
544
+ "boolean flag '",
545
+ flag.Name(), "'"),
546
+ true);
547
+ return std::make_tuple(false, "");
548
+ }
549
+ } else if (is_negative) {
550
+ // "--noint_flag=1" case
551
+ flags_internal::ReportUsageError(
552
+ absl::StrCat("Negative form is not valid for the flag '", flag.Name(),
553
+ "'"),
554
+ true);
555
+ return std::make_tuple(false, "");
556
+ } else if (value.empty() && (!is_empty_value)) {
557
+ if (curr_list->Size() == 1) {
558
+ // "--int_flag" case
559
+ flags_internal::ReportUsageError(
560
+ absl::StrCat("Missing the value for the flag '", flag.Name(), "'"),
561
+ true);
562
+ return std::make_tuple(false, "");
563
+ }
564
+
565
+ // "--int_flag" "10" case
566
+ curr_list->PopFront();
567
+ value = curr_list->Front();
568
+
569
+ // Heuristic to detect the case where someone treats a string arg
570
+ // like a bool or just forgets to pass a value:
571
+ // --my_string_var --foo=bar
572
+ // We look for a flag of string type, whose value begins with a
573
+ // dash and corresponds to known flag or standalone --.
574
+ if (!value.empty() && value[0] == '-' && flag.IsOfType<std::string>()) {
575
+ auto maybe_flag_name = std::get<0>(SplitNameAndValue(value.substr(1)));
576
+
577
+ if (maybe_flag_name.empty() ||
578
+ std::get<0>(LocateFlag(maybe_flag_name)) != nullptr) {
579
+ // "--string_flag" "--known_flag" case
580
+ ABSL_INTERNAL_LOG(
581
+ WARNING,
582
+ absl::StrCat("Did you really mean to set flag '", flag.Name(),
583
+ "' to the value '", value, "'?"));
584
+ }
585
+ }
586
+ }
587
+
588
+ return std::make_tuple(true, value);
589
+ }
590
+
591
+ // --------------------------------------------------------------------
592
+
593
+ bool CanIgnoreUndefinedFlag(absl::string_view flag_name) {
594
+ auto undefok = absl::GetFlag(FLAGS_undefok);
595
+ if (std::find(undefok.begin(), undefok.end(), flag_name) != undefok.end()) {
596
+ return true;
597
+ }
598
+
599
+ if (absl::ConsumePrefix(&flag_name, "no") &&
600
+ std::find(undefok.begin(), undefok.end(), flag_name) != undefok.end()) {
601
+ return true;
602
+ }
603
+
604
+ return false;
605
+ }
606
+
607
+ // --------------------------------------------------------------------
608
+
609
+ void ReportUnrecognizedFlags(
610
+ const std::vector<UnrecognizedFlag>& unrecognized_flags,
611
+ bool report_as_fatal_error) {
612
+ for (const auto& unrecognized : unrecognized_flags) {
613
+ // Verify if flag_name has the "no" already removed
614
+ std::vector<std::string> misspelling_hints;
615
+ if (unrecognized.source == UnrecognizedFlag::kFromArgv) {
616
+ misspelling_hints =
617
+ flags_internal::GetMisspellingHints(unrecognized.flag_name);
618
+ }
619
+
620
+ if (misspelling_hints.empty()) {
621
+ flags_internal::ReportUsageError(
622
+ absl::StrCat("Unknown command line flag '", unrecognized.flag_name,
623
+ "'"),
624
+ report_as_fatal_error);
625
+ } else {
626
+ flags_internal::ReportUsageError(
627
+ absl::StrCat("Unknown command line flag '", unrecognized.flag_name,
628
+ "'. Did you mean: ",
629
+ absl::StrJoin(misspelling_hints, ", "), " ?"),
630
+ report_as_fatal_error);
631
+ }
632
+ }
633
+ }
634
+
635
+ } // namespace
636
+
637
+ // --------------------------------------------------------------------
638
+
639
+ bool WasPresentOnCommandLine(absl::string_view flag_name) {
640
+ absl::ReaderMutexLock l(&specified_flags_guard);
641
+ ABSL_INTERNAL_CHECK(specified_flags != nullptr,
642
+ "ParseCommandLine is not invoked yet");
643
+
644
+ return std::binary_search(specified_flags->begin(), specified_flags->end(),
645
+ flag_name, SpecifiedFlagsCompare{});
646
+ }
647
+
648
+ // --------------------------------------------------------------------
649
+
650
+ struct BestHints {
651
+ explicit BestHints(uint8_t _max) : best_distance(_max + 1) {}
652
+ bool AddHint(absl::string_view hint, uint8_t distance) {
653
+ if (hints.size() >= kMaxHints) return false;
654
+ if (distance == best_distance) {
655
+ hints.emplace_back(hint);
656
+ }
657
+ if (distance < best_distance) {
658
+ best_distance = distance;
659
+ hints = std::vector<std::string>{std::string(hint)};
660
+ }
661
+ return true;
662
+ }
663
+
664
+ uint8_t best_distance;
665
+ std::vector<std::string> hints;
666
+ };
667
+
668
+ // Return the list of flags with the smallest Damerau-Levenshtein distance to
669
+ // the given flag.
670
+ std::vector<std::string> GetMisspellingHints(const absl::string_view flag) {
671
+ const size_t maxCutoff = std::min(flag.size() / 2 + 1, kMaxDistance);
672
+ auto undefok = absl::GetFlag(FLAGS_undefok);
673
+ BestHints best_hints(static_cast<uint8_t>(maxCutoff));
674
+ flags_internal::ForEachFlag([&](const CommandLineFlag& f) {
675
+ if (best_hints.hints.size() >= kMaxHints) return;
676
+ uint8_t distance = strings_internal::CappedDamerauLevenshteinDistance(
677
+ flag, f.Name(), best_hints.best_distance);
678
+ best_hints.AddHint(f.Name(), distance);
679
+ // For boolean flags, also calculate distance to the negated form.
680
+ if (f.IsOfType<bool>()) {
681
+ const std::string negated_flag = absl::StrCat("no", f.Name());
682
+ distance = strings_internal::CappedDamerauLevenshteinDistance(
683
+ flag, negated_flag, best_hints.best_distance);
684
+ best_hints.AddHint(negated_flag, distance);
685
+ }
686
+ });
687
+ // Finally calculate distance to flags in "undefok".
688
+ absl::c_for_each(undefok, [&](const absl::string_view f) {
689
+ if (best_hints.hints.size() >= kMaxHints) return;
690
+ uint8_t distance = strings_internal::CappedDamerauLevenshteinDistance(
691
+ flag, f, best_hints.best_distance);
692
+ best_hints.AddHint(absl::StrCat(f, " (undefok)"), distance);
693
+ });
694
+ return best_hints.hints;
695
+ }
696
+
697
+ // --------------------------------------------------------------------
698
+
699
+ std::vector<char*> ParseCommandLineImpl(int argc, char* argv[],
700
+ UsageFlagsAction usage_flag_action,
701
+ OnUndefinedFlag undef_flag_action,
702
+ std::ostream& error_help_output) {
703
+ std::vector<char*> positional_args;
704
+ std::vector<UnrecognizedFlag> unrecognized_flags;
705
+
706
+ auto help_mode = flags_internal::ParseAbseilFlagsOnlyImpl(
707
+ argc, argv, positional_args, unrecognized_flags, usage_flag_action);
708
+
709
+ if (undef_flag_action != OnUndefinedFlag::kIgnoreUndefined) {
710
+ flags_internal::ReportUnrecognizedFlags(
711
+ unrecognized_flags,
712
+ (undef_flag_action == OnUndefinedFlag::kAbortIfUndefined));
713
+
714
+ if (undef_flag_action == OnUndefinedFlag::kAbortIfUndefined) {
715
+ if (!unrecognized_flags.empty()) {
716
+ flags_internal::HandleUsageFlags(error_help_output,
717
+ ProgramUsageMessage()); std::exit(1);
718
+ }
719
+ }
720
+ }
721
+
722
+ flags_internal::MaybeExit(help_mode);
723
+
724
+ return positional_args;
725
+ }
726
+
727
+ // --------------------------------------------------------------------
728
+
729
+ // This function handles all Abseil Flags and built-in usage flags and, if any
730
+ // help mode was handled, it returns that help mode. The caller of this function
731
+ // can decide to exit based on the returned help mode.
732
+ // The caller may decide to handle unrecognized positional arguments and
733
+ // unrecognized flags first before exiting.
734
+ //
735
+ // Returns:
736
+ // * HelpMode::kFull if parsing errors were detected in recognized arguments
737
+ // * The HelpMode that was handled in case when `usage_flag_action` is
738
+ // UsageFlagsAction::kHandleUsage and a usage flag was specified on the
739
+ // commandline
740
+ // * Otherwise it returns HelpMode::kNone
741
+ HelpMode ParseAbseilFlagsOnlyImpl(
742
+ int argc, char* argv[], std::vector<char*>& positional_args,
743
+ std::vector<UnrecognizedFlag>& unrecognized_flags,
744
+ UsageFlagsAction usage_flag_action) {
745
+ ABSL_INTERNAL_CHECK(argc > 0, "Missing argv[0]");
746
+
747
+ using flags_internal::ArgsList;
748
+ using flags_internal::specified_flags;
749
+
750
+ std::vector<std::string> flagfile_value;
751
+ std::vector<ArgsList> input_args;
752
+
753
+ // Once parsing has started we will not allow more flag registrations.
754
+ flags_internal::FinalizeRegistry();
755
+
756
+ // This routine does not return anything since we abort on failure.
757
+ flags_internal::CheckDefaultValuesParsingRoundtrip();
758
+
759
+ input_args.push_back(ArgsList(argc, argv));
760
+
761
+ // Set program invocation name if it is not set before.
762
+ if (flags_internal::ProgramInvocationName() == "UNKNOWN") {
763
+ flags_internal::SetProgramInvocationName(argv[0]);
764
+ }
765
+ positional_args.push_back(argv[0]);
766
+
767
+ absl::MutexLock l(&flags_internal::specified_flags_guard);
768
+ if (specified_flags == nullptr) {
769
+ specified_flags = new std::vector<const CommandLineFlag*>;
770
+ } else {
771
+ specified_flags->clear();
772
+ }
773
+
774
+ // Iterate through the list of the input arguments. First level are
775
+ // arguments originated from argc/argv. Following levels are arguments
776
+ // originated from recursive parsing of flagfile(s).
777
+ bool success = true;
778
+ while (!input_args.empty()) {
779
+ // First we process the built-in generator flags.
780
+ success &= flags_internal::HandleGeneratorFlags(input_args, flagfile_value);
781
+
782
+ // Select top-most (most recent) arguments list. If it is empty drop it
783
+ // and re-try.
784
+ ArgsList& curr_list = input_args.back();
785
+
786
+ // Every ArgsList starts with real or fake program name, so we can always
787
+ // start by skipping it.
788
+ curr_list.PopFront();
789
+
790
+ if (curr_list.Size() == 0) {
791
+ input_args.pop_back();
792
+ continue;
793
+ }
794
+
795
+ // Handle the next argument in the current list. If the stack of argument
796
+ // lists contains only one element - we are processing an argument from
797
+ // the original argv.
798
+ absl::string_view arg(curr_list.Front());
799
+ bool arg_from_argv = input_args.size() == 1;
800
+
801
+ // If argument does not start with '-' or is just "-" - this is
802
+ // positional argument.
803
+ if (!absl::ConsumePrefix(&arg, "-") || arg.empty()) {
804
+ ABSL_INTERNAL_CHECK(arg_from_argv,
805
+ "Flagfile cannot contain positional argument");
806
+
807
+ positional_args.push_back(argv[curr_list.FrontIndex()]);
808
+ continue;
809
+ }
810
+
811
+ // Split the current argument on '=' to deduce the argument flag name and
812
+ // value. If flag name is empty it means we've got an "--" argument. Value
813
+ // can be empty either if there were no '=' in argument string at all or
814
+ // an argument looked like "--foo=". In a latter case is_empty_value is
815
+ // true.
816
+ absl::string_view flag_name;
817
+ absl::string_view value;
818
+ bool is_empty_value = false;
819
+
820
+ std::tie(flag_name, value, is_empty_value) =
821
+ flags_internal::SplitNameAndValue(arg);
822
+
823
+ // Standalone "--" argument indicates that the rest of the arguments are
824
+ // positional. We do not support positional arguments in flagfiles.
825
+ if (flag_name.empty()) {
826
+ ABSL_INTERNAL_CHECK(arg_from_argv,
827
+ "Flagfile cannot contain positional argument");
828
+
829
+ curr_list.PopFront();
830
+ break;
831
+ }
832
+
833
+ // Locate the flag based on flag name. Handle both --foo and --nofoo.
834
+ CommandLineFlag* flag = nullptr;
835
+ bool is_negative = false;
836
+ std::tie(flag, is_negative) = flags_internal::LocateFlag(flag_name);
837
+
838
+ if (flag == nullptr) {
839
+ // Usage flags are not modeled as Abseil flags. Locate them separately.
840
+ if (flags_internal::DeduceUsageFlags(flag_name, value)) {
841
+ continue;
842
+ }
843
+ unrecognized_flags.emplace_back(arg_from_argv
844
+ ? UnrecognizedFlag::kFromArgv
845
+ : UnrecognizedFlag::kFromFlagfile,
846
+ flag_name);
847
+ continue;
848
+ }
849
+
850
+ // Deduce flag's value (from this or next argument).
851
+ bool value_success = true;
852
+ std::tie(value_success, value) = flags_internal::DeduceFlagValue(
853
+ *flag, value, is_negative, is_empty_value, &curr_list);
854
+ success &= value_success;
855
+
856
+ // Set the located flag to a new value, unless it is retired. Setting
857
+ // retired flag fails, but we ignoring it here while also reporting access
858
+ // to retired flag.
859
+ std::string error;
860
+ if (!flags_internal::PrivateHandleAccessor::ParseFrom(
861
+ *flag, value, flags_internal::SET_FLAGS_VALUE,
862
+ flags_internal::kCommandLine, error)) {
863
+ if (flag->IsRetired()) continue;
864
+
865
+ flags_internal::ReportUsageError(error, true);
866
+ success = false;
867
+ } else {
868
+ specified_flags->push_back(flag);
869
+ }
870
+ }
871
+
872
+ flags_internal::ResetGeneratorFlags(flagfile_value);
873
+
874
+ // All the remaining arguments are positional.
875
+ if (!input_args.empty()) {
876
+ for (size_t arg_index = input_args.back().FrontIndex();
877
+ arg_index < static_cast<size_t>(argc); ++arg_index) {
878
+ positional_args.push_back(argv[arg_index]);
879
+ }
880
+ }
881
+
882
+ // Trim and sort the vector.
883
+ specified_flags->shrink_to_fit();
884
+ std::sort(specified_flags->begin(), specified_flags->end(),
885
+ flags_internal::SpecifiedFlagsCompare{});
886
+
887
+ // Filter out unrecognized flags, which are ok to ignore.
888
+ std::vector<UnrecognizedFlag> filtered;
889
+ filtered.reserve(unrecognized_flags.size());
890
+ for (const auto& unrecognized : unrecognized_flags) {
891
+ if (flags_internal::CanIgnoreUndefinedFlag(unrecognized.flag_name))
892
+ continue;
893
+ filtered.push_back(unrecognized);
894
+ }
895
+
896
+ std::swap(unrecognized_flags, filtered);
897
+
898
+ if (!success) {
899
+ #if ABSL_FLAGS_STRIP_NAMES
900
+ flags_internal::ReportUsageError(
901
+ "NOTE: command line flags are disabled in this build", true);
902
+ #else
903
+ flags_internal::HandleUsageFlags(std::cerr, ProgramUsageMessage());
904
+ #endif
905
+ return HelpMode::kFull; // We just need to make sure the exit with
906
+ // code 1.
907
+ }
908
+
909
+ return usage_flag_action == UsageFlagsAction::kHandleUsage
910
+ ? flags_internal::HandleUsageFlags(std::cout,
911
+ ProgramUsageMessage())
912
+ : HelpMode::kNone;
913
+ }
914
+
915
+ } // namespace flags_internal
916
+
917
+ void ParseAbseilFlagsOnly(int argc, char* argv[],
918
+ std::vector<char*>& positional_args,
919
+ std::vector<UnrecognizedFlag>& unrecognized_flags) {
920
+ auto help_mode = flags_internal::ParseAbseilFlagsOnlyImpl(
921
+ argc, argv, positional_args, unrecognized_flags,
922
+ flags_internal::UsageFlagsAction::kHandleUsage);
923
+
924
+ flags_internal::MaybeExit(help_mode);
925
+ }
926
+
927
+ // --------------------------------------------------------------------
928
+
929
+ void ReportUnrecognizedFlags(
930
+ const std::vector<UnrecognizedFlag>& unrecognized_flags) {
931
+ flags_internal::ReportUnrecognizedFlags(unrecognized_flags, true);
932
+ }
933
+
934
+ // --------------------------------------------------------------------
935
+
936
+ std::vector<char*> ParseCommandLine(int argc, char* argv[]) {
937
+ return flags_internal::ParseCommandLineImpl(
938
+ argc, argv, flags_internal::UsageFlagsAction::kHandleUsage,
939
+ flags_internal::OnUndefinedFlag::kAbortIfUndefined);
940
+ }
941
+
942
+ ABSL_NAMESPACE_END
943
+ } // namespace absl
weight/_dep/abseil-cpp/absl/flags/parse.h ADDED
@@ -0,0 +1,130 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ //
2
+ // Copyright 2019 The Abseil Authors.
3
+ //
4
+ // Licensed under the Apache License, Version 2.0 (the "License");
5
+ // you may not use this file except in compliance with the License.
6
+ // You may obtain a copy of the License at
7
+ //
8
+ // https://www.apache.org/licenses/LICENSE-2.0
9
+ //
10
+ // Unless required by applicable law or agreed to in writing, software
11
+ // distributed under the License is distributed on an "AS IS" BASIS,
12
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ // See the License for the specific language governing permissions and
14
+ // limitations under the License.
15
+ //
16
+ // -----------------------------------------------------------------------------
17
+ // File: parse.h
18
+ // -----------------------------------------------------------------------------
19
+ //
20
+ // This file defines the main parsing function for Abseil flags:
21
+ // `absl::ParseCommandLine()`.
22
+
23
+ #ifndef ABSL_FLAGS_PARSE_H_
24
+ #define ABSL_FLAGS_PARSE_H_
25
+
26
+ #include <string>
27
+ #include <vector>
28
+
29
+ #include "absl/base/config.h"
30
+ #include "absl/flags/internal/parse.h"
31
+
32
+ namespace absl {
33
+ ABSL_NAMESPACE_BEGIN
34
+
35
+ // This type represent information about an unrecognized flag in the command
36
+ // line.
37
+ struct UnrecognizedFlag {
38
+ enum Source { kFromArgv, kFromFlagfile };
39
+
40
+ explicit UnrecognizedFlag(Source s, absl::string_view f)
41
+ : source(s), flag_name(f) {}
42
+ // This field indicates where we found this flag: on the original command line
43
+ // or read in some flag file.
44
+ Source source;
45
+ // Name of the flag we did not recognize in --flag_name=value or --flag_name.
46
+ std::string flag_name;
47
+ };
48
+
49
+ inline bool operator==(const UnrecognizedFlag& lhs,
50
+ const UnrecognizedFlag& rhs) {
51
+ return lhs.source == rhs.source && lhs.flag_name == rhs.flag_name;
52
+ }
53
+
54
+ namespace flags_internal {
55
+
56
+ HelpMode ParseAbseilFlagsOnlyImpl(
57
+ int argc, char* argv[], std::vector<char*>& positional_args,
58
+ std::vector<UnrecognizedFlag>& unrecognized_flags,
59
+ UsageFlagsAction usage_flag_action);
60
+
61
+ } // namespace flags_internal
62
+
63
+ // ParseAbseilFlagsOnly()
64
+ //
65
+ // Parses a list of command-line arguments, passed in the `argc` and `argv[]`
66
+ // parameters, into a set of Abseil Flag values, returning any unparsed
67
+ // arguments in `positional_args` and `unrecognized_flags` output parameters.
68
+ //
69
+ // This function classifies all the arguments (including content of the
70
+ // flagfiles, if any) into one of the following groups:
71
+ //
72
+ // * arguments specified as "--flag=value" or "--flag value" that match
73
+ // registered or built-in Abseil Flags. These are "Abseil Flag arguments."
74
+ // * arguments specified as "--flag" that are unrecognized as Abseil Flags
75
+ // * arguments that are not specified as "--flag" are positional arguments
76
+ // * arguments that follow the flag-terminating delimiter (`--`) are also
77
+ // treated as positional arguments regardless of their syntax.
78
+ //
79
+ // All of the deduced Abseil Flag arguments are then parsed into their
80
+ // corresponding flag values. If any syntax errors are found in these arguments,
81
+ // the binary exits with code 1.
82
+ //
83
+ // This function also handles Abseil Flags built-in usage flags (e.g. --help)
84
+ // if any were present on the command line.
85
+ //
86
+ // All the remaining positional arguments including original program name
87
+ // (argv[0]) are are returned in the `positional_args` output parameter.
88
+ //
89
+ // All unrecognized flags that are not otherwise ignored are returned in the
90
+ // `unrecognized_flags` output parameter. Note that the special `undefok`
91
+ // flag allows you to specify flags which can be safely ignored; `undefok`
92
+ // specifies these flags as a comma-separated list. Any unrecognized flags
93
+ // that appear within `undefok` will therefore be ignored and not included in
94
+ // the `unrecognized_flag` output parameter.
95
+ //
96
+ void ParseAbseilFlagsOnly(int argc, char* argv[],
97
+ std::vector<char*>& positional_args,
98
+ std::vector<UnrecognizedFlag>& unrecognized_flags);
99
+
100
+ // ReportUnrecognizedFlags()
101
+ //
102
+ // Reports an error to `stderr` for all non-ignored unrecognized flags in
103
+ // the provided `unrecognized_flags` list.
104
+ void ReportUnrecognizedFlags(
105
+ const std::vector<UnrecognizedFlag>& unrecognized_flags);
106
+
107
+ // ParseCommandLine()
108
+ //
109
+ // First parses Abseil Flags only from the command line according to the
110
+ // description in `ParseAbseilFlagsOnly`. In addition this function handles
111
+ // unrecognized and usage flags.
112
+ //
113
+ // If any unrecognized flags are located they are reported using
114
+ // `ReportUnrecognizedFlags`.
115
+ //
116
+ // If any errors detected during command line parsing, this routine reports a
117
+ // usage message and aborts the program.
118
+ //
119
+ // If any built-in usage flags were specified on the command line (e.g.
120
+ // `--help`), this function reports help messages and then gracefully exits the
121
+ // program.
122
+ //
123
+ // This function returns all the remaining positional arguments collected by
124
+ // `ParseAbseilFlagsOnly`.
125
+ std::vector<char*> ParseCommandLine(int argc, char* argv[]);
126
+
127
+ ABSL_NAMESPACE_END
128
+ } // namespace absl
129
+
130
+ #endif // ABSL_FLAGS_PARSE_H_
weight/_dep/abseil-cpp/absl/flags/parse_test.cc ADDED
@@ -0,0 +1,1087 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ //
2
+ // Copyright 2019 The Abseil Authors.
3
+ //
4
+ // Licensed under the Apache License, Version 2.0 (the "License");
5
+ // you may not use this file except in compliance with the License.
6
+ // You may obtain a copy of the License at
7
+ //
8
+ // https://www.apache.org/licenses/LICENSE-2.0
9
+ //
10
+ // Unless required by applicable law or agreed to in writing, software
11
+ // distributed under the License is distributed on an "AS IS" BASIS,
12
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ // See the License for the specific language governing permissions and
14
+ // limitations under the License.
15
+
16
+ #include "absl/flags/parse.h"
17
+
18
+ #include <stdlib.h>
19
+
20
+ #include <fstream>
21
+ #include <iostream>
22
+ #include <string>
23
+ #include <vector>
24
+
25
+ #include "gmock/gmock.h"
26
+ #include "gtest/gtest.h"
27
+ #include "absl/base/internal/scoped_set_env.h"
28
+ #include "absl/flags/flag.h"
29
+ #include "absl/flags/internal/parse.h"
30
+ #include "absl/flags/internal/usage.h"
31
+ #include "absl/flags/reflection.h"
32
+ #include "absl/log/log.h"
33
+ #include "absl/strings/str_cat.h"
34
+ #include "absl/strings/string_view.h"
35
+ #include "absl/strings/substitute.h"
36
+ #include "absl/types/span.h"
37
+
38
+ #ifdef _WIN32
39
+ #include <windows.h>
40
+ #endif
41
+
42
+ // Define 125 similar flags to test kMaxHints for flag suggestions.
43
+ #define FLAG_MULT(x) F3(x)
44
+ #define TEST_FLAG_HEADER FLAG_HEADER_
45
+
46
+ #define F(name) ABSL_FLAG(int, name, 0, "");
47
+
48
+ #define F1(name) \
49
+ F(name##1); \
50
+ F(name##2); \
51
+ F(name##3); \
52
+ F(name##4); \
53
+ F(name##5);
54
+ /**/
55
+ #define F2(name) \
56
+ F1(name##1); \
57
+ F1(name##2); \
58
+ F1(name##3); \
59
+ F1(name##4); \
60
+ F1(name##5);
61
+ /**/
62
+ #define F3(name) \
63
+ F2(name##1); \
64
+ F2(name##2); \
65
+ F2(name##3); \
66
+ F2(name##4); \
67
+ F2(name##5);
68
+ /**/
69
+
70
+ FLAG_MULT(TEST_FLAG_HEADER)
71
+
72
+ namespace {
73
+
74
+ using absl::base_internal::ScopedSetEnv;
75
+
76
+ struct UDT {
77
+ UDT() = default;
78
+ UDT(const UDT&) = default;
79
+ UDT& operator=(const UDT&) = default;
80
+ UDT(int v) : value(v) {} // NOLINT
81
+
82
+ int value;
83
+ };
84
+
85
+ bool AbslParseFlag(absl::string_view in, UDT* udt, std::string* err) {
86
+ if (in == "A") {
87
+ udt->value = 1;
88
+ return true;
89
+ }
90
+ if (in == "AAA") {
91
+ udt->value = 10;
92
+ return true;
93
+ }
94
+
95
+ *err = "Use values A, AAA instead";
96
+ return false;
97
+ }
98
+ std::string AbslUnparseFlag(const UDT& udt) {
99
+ return udt.value == 1 ? "A" : "AAA";
100
+ }
101
+
102
+ std::string GetTestTmpDirEnvVar(const char* const env_var_name) {
103
+ #ifdef _WIN32
104
+ char buf[MAX_PATH];
105
+ auto get_res = GetEnvironmentVariableA(env_var_name, buf, sizeof(buf));
106
+ if (get_res >= sizeof(buf) || get_res == 0) {
107
+ return "";
108
+ }
109
+
110
+ return std::string(buf, get_res);
111
+ #else
112
+ const char* val = ::getenv(env_var_name);
113
+ if (val == nullptr) {
114
+ return "";
115
+ }
116
+
117
+ return val;
118
+ #endif
119
+ }
120
+
121
+ const std::string& GetTestTempDir() {
122
+ static std::string* temp_dir_name = []() -> std::string* {
123
+ std::string* res = new std::string(GetTestTmpDirEnvVar("TEST_TMPDIR"));
124
+
125
+ if (res->empty()) {
126
+ *res = GetTestTmpDirEnvVar("TMPDIR");
127
+ }
128
+
129
+ if (res->empty()) {
130
+ #ifdef _WIN32
131
+ char temp_path_buffer[MAX_PATH];
132
+
133
+ auto len = GetTempPathA(MAX_PATH, temp_path_buffer);
134
+ if (len < MAX_PATH && len != 0) {
135
+ std::string temp_dir_name = temp_path_buffer;
136
+ if (!absl::EndsWith(temp_dir_name, "\\")) {
137
+ temp_dir_name.push_back('\\');
138
+ }
139
+ absl::StrAppend(&temp_dir_name, "parse_test.", GetCurrentProcessId());
140
+ if (CreateDirectoryA(temp_dir_name.c_str(), nullptr)) {
141
+ *res = temp_dir_name;
142
+ }
143
+ }
144
+ #else
145
+ char temp_dir_template[] = "/tmp/parse_test.XXXXXX";
146
+ if (auto* unique_name = ::mkdtemp(temp_dir_template)) {
147
+ *res = unique_name;
148
+ }
149
+ #endif
150
+ }
151
+
152
+ if (res->empty()) {
153
+ LOG(FATAL) << "Failed to make temporary directory for data files";
154
+ }
155
+
156
+ #ifdef _WIN32
157
+ *res += "\\";
158
+ #else
159
+ *res += "/";
160
+ #endif
161
+
162
+ return res;
163
+ }();
164
+
165
+ return *temp_dir_name;
166
+ }
167
+
168
+ struct FlagfileData {
169
+ const absl::string_view file_name;
170
+ const absl::Span<const char* const> file_lines;
171
+ };
172
+
173
+ // clang-format off
174
+ constexpr const char* const ff1_data[] = {
175
+ "# comment ",
176
+ " # comment ",
177
+ "",
178
+ " ",
179
+ "--int_flag=-1",
180
+ " --string_flag=q2w2 ",
181
+ " ## ",
182
+ " --double_flag=0.1",
183
+ "--bool_flag=Y "
184
+ };
185
+
186
+ constexpr const char* const ff2_data[] = {
187
+ "# Setting legacy flag",
188
+ "--legacy_int=1111",
189
+ "--legacy_bool",
190
+ "--nobool_flag",
191
+ "--legacy_str=aqsw",
192
+ "--int_flag=100",
193
+ " ## ============="
194
+ };
195
+ // clang-format on
196
+
197
+ // Builds flagfile flag in the flagfile_flag buffer and returns it. This
198
+ // function also creates a temporary flagfile based on FlagfileData input.
199
+ // We create a flagfile in a temporary directory with the name specified in
200
+ // FlagfileData and populate it with lines specified in FlagfileData. If $0 is
201
+ // referenced in any of the lines in FlagfileData they are replaced with
202
+ // temporary directory location. This way we can test inclusion of one flagfile
203
+ // from another flagfile.
204
+ const char* GetFlagfileFlag(const std::vector<FlagfileData>& ffd,
205
+ std::string& flagfile_flag) {
206
+ flagfile_flag = "--flagfile=";
207
+ absl::string_view separator;
208
+ for (const auto& flagfile_data : ffd) {
209
+ std::string flagfile_name =
210
+ absl::StrCat(GetTestTempDir(), flagfile_data.file_name);
211
+
212
+ std::ofstream flagfile_out(flagfile_name);
213
+ for (auto line : flagfile_data.file_lines) {
214
+ flagfile_out << absl::Substitute(line, GetTestTempDir()) << "\n";
215
+ }
216
+
217
+ absl::StrAppend(&flagfile_flag, separator, flagfile_name);
218
+ separator = ",";
219
+ }
220
+
221
+ return flagfile_flag.c_str();
222
+ }
223
+
224
+ } // namespace
225
+
226
+ ABSL_FLAG(int, int_flag, 1, "");
227
+ ABSL_FLAG(double, double_flag, 1.1, "");
228
+ ABSL_FLAG(std::string, string_flag, "a", "");
229
+ ABSL_FLAG(bool, bool_flag, false, "");
230
+ ABSL_FLAG(UDT, udt_flag, -1, "");
231
+ ABSL_RETIRED_FLAG(int, legacy_int, 1, "");
232
+ ABSL_RETIRED_FLAG(bool, legacy_bool, false, "");
233
+ ABSL_RETIRED_FLAG(std::string, legacy_str, "l", "");
234
+
235
+ namespace {
236
+
237
+ namespace flags = absl::flags_internal;
238
+ using testing::AllOf;
239
+ using testing::ElementsAreArray;
240
+ using testing::HasSubstr;
241
+
242
+ class ParseTest : public testing::Test {
243
+ public:
244
+ ~ParseTest() override { flags::SetFlagsHelpMode(flags::HelpMode::kNone); }
245
+
246
+ private:
247
+ absl::FlagSaver flag_saver_;
248
+ };
249
+
250
+ // --------------------------------------------------------------------
251
+
252
+ template <int N>
253
+ flags::HelpMode InvokeParseAbslOnlyImpl(const char* (&in_argv)[N]) {
254
+ std::vector<char*> positional_args;
255
+ std::vector<absl::UnrecognizedFlag> unrecognized_flags;
256
+
257
+ return flags::ParseAbseilFlagsOnlyImpl(N, const_cast<char**>(in_argv),
258
+ positional_args, unrecognized_flags,
259
+ flags::UsageFlagsAction::kHandleUsage);
260
+ }
261
+
262
+ // --------------------------------------------------------------------
263
+
264
+ template <int N>
265
+ void InvokeParseAbslOnly(const char* (&in_argv)[N]) {
266
+ std::vector<char*> positional_args;
267
+ std::vector<absl::UnrecognizedFlag> unrecognized_flags;
268
+
269
+ absl::ParseAbseilFlagsOnly(2, const_cast<char**>(in_argv), positional_args,
270
+ unrecognized_flags);
271
+ }
272
+
273
+ // --------------------------------------------------------------------
274
+
275
+ template <int N>
276
+ std::vector<char*> InvokeParseCommandLineImpl(const char* (&in_argv)[N]) {
277
+ return flags::ParseCommandLineImpl(
278
+ N, const_cast<char**>(in_argv), flags::UsageFlagsAction::kHandleUsage,
279
+ flags::OnUndefinedFlag::kAbortIfUndefined, std::cerr);
280
+ }
281
+
282
+ // --------------------------------------------------------------------
283
+
284
+ template <int N>
285
+ std::vector<char*> InvokeParse(const char* (&in_argv)[N]) {
286
+ return absl::ParseCommandLine(N, const_cast<char**>(in_argv));
287
+ }
288
+
289
+ // --------------------------------------------------------------------
290
+
291
+ template <int N>
292
+ void TestParse(const char* (&in_argv)[N], int int_flag_value,
293
+ double double_flag_val, absl::string_view string_flag_val,
294
+ bool bool_flag_val, int exp_position_args = 0) {
295
+ auto out_args = InvokeParse(in_argv);
296
+
297
+ EXPECT_EQ(out_args.size(), 1 + exp_position_args);
298
+ EXPECT_STREQ(out_args[0], "testbin");
299
+
300
+ EXPECT_EQ(absl::GetFlag(FLAGS_int_flag), int_flag_value);
301
+ EXPECT_NEAR(absl::GetFlag(FLAGS_double_flag), double_flag_val, 0.0001);
302
+ EXPECT_EQ(absl::GetFlag(FLAGS_string_flag), string_flag_val);
303
+ EXPECT_EQ(absl::GetFlag(FLAGS_bool_flag), bool_flag_val);
304
+ }
305
+
306
+ // --------------------------------------------------------------------
307
+
308
+ TEST_F(ParseTest, TestEmptyArgv) {
309
+ const char* in_argv[] = {"testbin"};
310
+
311
+ auto out_args = InvokeParse(in_argv);
312
+
313
+ EXPECT_EQ(out_args.size(), 1);
314
+ EXPECT_STREQ(out_args[0], "testbin");
315
+ }
316
+
317
+ // --------------------------------------------------------------------
318
+
319
+ TEST_F(ParseTest, TestValidIntArg) {
320
+ const char* in_args1[] = {
321
+ "testbin",
322
+ "--int_flag=10",
323
+ };
324
+ TestParse(in_args1, 10, 1.1, "a", false);
325
+
326
+ const char* in_args2[] = {
327
+ "testbin",
328
+ "-int_flag=020",
329
+ };
330
+ TestParse(in_args2, 20, 1.1, "a", false);
331
+
332
+ const char* in_args3[] = {
333
+ "testbin",
334
+ "--int_flag",
335
+ "-30",
336
+ };
337
+ TestParse(in_args3, -30, 1.1, "a", false);
338
+
339
+ const char* in_args4[] = {
340
+ "testbin",
341
+ "-int_flag",
342
+ "0x21",
343
+ };
344
+ TestParse(in_args4, 33, 1.1, "a", false);
345
+ }
346
+
347
+ // --------------------------------------------------------------------
348
+
349
+ TEST_F(ParseTest, TestValidDoubleArg) {
350
+ const char* in_args1[] = {
351
+ "testbin",
352
+ "--double_flag=2.3",
353
+ };
354
+ TestParse(in_args1, 1, 2.3, "a", false);
355
+
356
+ const char* in_args2[] = {
357
+ "testbin",
358
+ "--double_flag=0x1.2",
359
+ };
360
+ TestParse(in_args2, 1, 1.125, "a", false);
361
+
362
+ const char* in_args3[] = {
363
+ "testbin",
364
+ "--double_flag",
365
+ "99.7",
366
+ };
367
+ TestParse(in_args3, 1, 99.7, "a", false);
368
+
369
+ const char* in_args4[] = {
370
+ "testbin",
371
+ "--double_flag",
372
+ "0x20.1",
373
+ };
374
+ TestParse(in_args4, 1, 32.0625, "a", false);
375
+ }
376
+
377
+ // --------------------------------------------------------------------
378
+
379
+ TEST_F(ParseTest, TestValidStringArg) {
380
+ const char* in_args1[] = {
381
+ "testbin",
382
+ "--string_flag=aqswde",
383
+ };
384
+ TestParse(in_args1, 1, 1.1, "aqswde", false);
385
+
386
+ const char* in_args2[] = {
387
+ "testbin",
388
+ "-string_flag=a=b=c",
389
+ };
390
+ TestParse(in_args2, 1, 1.1, "a=b=c", false);
391
+
392
+ const char* in_args3[] = {
393
+ "testbin",
394
+ "--string_flag",
395
+ "zaxscd",
396
+ };
397
+ TestParse(in_args3, 1, 1.1, "zaxscd", false);
398
+
399
+ const char* in_args4[] = {
400
+ "testbin",
401
+ "-string_flag",
402
+ "--int_flag",
403
+ };
404
+ TestParse(in_args4, 1, 1.1, "--int_flag", false);
405
+
406
+ const char* in_args5[] = {
407
+ "testbin",
408
+ "--string_flag",
409
+ "--no_a_flag=11",
410
+ };
411
+ TestParse(in_args5, 1, 1.1, "--no_a_flag=11", false);
412
+ }
413
+
414
+ // --------------------------------------------------------------------
415
+
416
+ TEST_F(ParseTest, TestValidBoolArg) {
417
+ const char* in_args1[] = {
418
+ "testbin",
419
+ "--bool_flag",
420
+ };
421
+ TestParse(in_args1, 1, 1.1, "a", true);
422
+
423
+ const char* in_args2[] = {
424
+ "testbin",
425
+ "--nobool_flag",
426
+ };
427
+ TestParse(in_args2, 1, 1.1, "a", false);
428
+
429
+ const char* in_args3[] = {
430
+ "testbin",
431
+ "--bool_flag=true",
432
+ };
433
+ TestParse(in_args3, 1, 1.1, "a", true);
434
+
435
+ const char* in_args4[] = {
436
+ "testbin",
437
+ "-bool_flag=false",
438
+ };
439
+ TestParse(in_args4, 1, 1.1, "a", false);
440
+ }
441
+
442
+ // --------------------------------------------------------------------
443
+
444
+ TEST_F(ParseTest, TestValidUDTArg) {
445
+ const char* in_args1[] = {
446
+ "testbin",
447
+ "--udt_flag=A",
448
+ };
449
+ InvokeParse(in_args1);
450
+
451
+ EXPECT_EQ(absl::GetFlag(FLAGS_udt_flag).value, 1);
452
+
453
+ const char* in_args2[] = {"testbin", "--udt_flag", "AAA"};
454
+ InvokeParse(in_args2);
455
+
456
+ EXPECT_EQ(absl::GetFlag(FLAGS_udt_flag).value, 10);
457
+ }
458
+
459
+ // --------------------------------------------------------------------
460
+
461
+ TEST_F(ParseTest, TestValidMultipleArg) {
462
+ const char* in_args1[] = {
463
+ "testbin", "--bool_flag", "--int_flag=2",
464
+ "--double_flag=0.1", "--string_flag=asd",
465
+ };
466
+ TestParse(in_args1, 2, 0.1, "asd", true);
467
+
468
+ const char* in_args2[] = {
469
+ "testbin", "--string_flag=", "--nobool_flag", "--int_flag",
470
+ "-011", "--double_flag", "-1e-2",
471
+ };
472
+ TestParse(in_args2, -11, -0.01, "", false);
473
+
474
+ const char* in_args3[] = {
475
+ "testbin", "--int_flag", "-0", "--string_flag", "\"\"",
476
+ "--bool_flag=true", "--double_flag=1e18",
477
+ };
478
+ TestParse(in_args3, 0, 1e18, "\"\"", true);
479
+ }
480
+
481
+ // --------------------------------------------------------------------
482
+
483
+ TEST_F(ParseTest, TestPositionalArgs) {
484
+ const char* in_args1[] = {
485
+ "testbin",
486
+ "p1",
487
+ "p2",
488
+ };
489
+ TestParse(in_args1, 1, 1.1, "a", false, 2);
490
+
491
+ auto out_args1 = InvokeParse(in_args1);
492
+
493
+ EXPECT_STREQ(out_args1[1], "p1");
494
+ EXPECT_STREQ(out_args1[2], "p2");
495
+
496
+ const char* in_args2[] = {
497
+ "testbin",
498
+ "--int_flag=2",
499
+ "p1",
500
+ };
501
+ TestParse(in_args2, 2, 1.1, "a", false, 1);
502
+
503
+ auto out_args2 = InvokeParse(in_args2);
504
+
505
+ EXPECT_STREQ(out_args2[1], "p1");
506
+
507
+ const char* in_args3[] = {"testbin", "p1", "--int_flag=3",
508
+ "p2", "--bool_flag", "true"};
509
+ TestParse(in_args3, 3, 1.1, "a", true, 3);
510
+
511
+ auto out_args3 = InvokeParse(in_args3);
512
+
513
+ EXPECT_STREQ(out_args3[1], "p1");
514
+ EXPECT_STREQ(out_args3[2], "p2");
515
+ EXPECT_STREQ(out_args3[3], "true");
516
+
517
+ const char* in_args4[] = {
518
+ "testbin",
519
+ "--",
520
+ "p1",
521
+ "p2",
522
+ };
523
+ TestParse(in_args4, 3, 1.1, "a", true, 2);
524
+
525
+ auto out_args4 = InvokeParse(in_args4);
526
+
527
+ EXPECT_STREQ(out_args4[1], "p1");
528
+ EXPECT_STREQ(out_args4[2], "p2");
529
+
530
+ const char* in_args5[] = {
531
+ "testbin", "p1", "--int_flag=4", "--", "--bool_flag", "false", "p2",
532
+ };
533
+ TestParse(in_args5, 4, 1.1, "a", true, 4);
534
+
535
+ auto out_args5 = InvokeParse(in_args5);
536
+
537
+ EXPECT_STREQ(out_args5[1], "p1");
538
+ EXPECT_STREQ(out_args5[2], "--bool_flag");
539
+ EXPECT_STREQ(out_args5[3], "false");
540
+ EXPECT_STREQ(out_args5[4], "p2");
541
+ }
542
+
543
+ // --------------------------------------------------------------------
544
+
545
+ using ParseDeathTest = ParseTest;
546
+
547
+ TEST_F(ParseDeathTest, TestUndefinedArg) {
548
+ const char* in_args1[] = {
549
+ "testbin",
550
+ "--undefined_flag",
551
+ };
552
+ EXPECT_DEATH_IF_SUPPORTED(InvokeParse(in_args1),
553
+ "Unknown command line flag 'undefined_flag'");
554
+
555
+ const char* in_args2[] = {
556
+ "testbin",
557
+ "--noprefixed_flag",
558
+ };
559
+ EXPECT_DEATH_IF_SUPPORTED(InvokeParse(in_args2),
560
+ "Unknown command line flag 'noprefixed_flag'");
561
+
562
+ const char* in_args3[] = {
563
+ "testbin",
564
+ "--Int_flag=1",
565
+ };
566
+ EXPECT_DEATH_IF_SUPPORTED(InvokeParse(in_args3),
567
+ "Unknown command line flag 'Int_flag'");
568
+ }
569
+
570
+ // --------------------------------------------------------------------
571
+
572
+ TEST_F(ParseDeathTest, TestInvalidBoolFlagFormat) {
573
+ const char* in_args1[] = {
574
+ "testbin",
575
+ "--bool_flag=",
576
+ };
577
+ EXPECT_DEATH_IF_SUPPORTED(
578
+ InvokeParse(in_args1),
579
+ "Missing the value after assignment for the boolean flag 'bool_flag'");
580
+
581
+ const char* in_args2[] = {
582
+ "testbin",
583
+ "--nobool_flag=true",
584
+ };
585
+ EXPECT_DEATH_IF_SUPPORTED(InvokeParse(in_args2),
586
+ "Negative form with assignment is not valid for the boolean "
587
+ "flag 'bool_flag'");
588
+ }
589
+
590
+ // --------------------------------------------------------------------
591
+
592
+ TEST_F(ParseDeathTest, TestInvalidNonBoolFlagFormat) {
593
+ const char* in_args1[] = {
594
+ "testbin",
595
+ "--nostring_flag",
596
+ };
597
+ EXPECT_DEATH_IF_SUPPORTED(InvokeParse(in_args1),
598
+ "Negative form is not valid for the flag 'string_flag'");
599
+
600
+ const char* in_args2[] = {
601
+ "testbin",
602
+ "--int_flag",
603
+ };
604
+ EXPECT_DEATH_IF_SUPPORTED(InvokeParse(in_args2),
605
+ "Missing the value for the flag 'int_flag'");
606
+ }
607
+
608
+ // --------------------------------------------------------------------
609
+
610
+ TEST_F(ParseDeathTest, TestInvalidUDTFlagFormat) {
611
+ const char* in_args1[] = {
612
+ "testbin",
613
+ "--udt_flag=1",
614
+ };
615
+ EXPECT_DEATH_IF_SUPPORTED(InvokeParse(in_args1),
616
+ "Illegal value '1' specified for flag 'udt_flag'; Use values A, "
617
+ "AAA instead");
618
+
619
+ const char* in_args2[] = {
620
+ "testbin",
621
+ "--udt_flag",
622
+ "AA",
623
+ };
624
+ EXPECT_DEATH_IF_SUPPORTED(InvokeParse(in_args2),
625
+ "Illegal value 'AA' specified for flag 'udt_flag'; Use values "
626
+ "A, AAA instead");
627
+ }
628
+
629
+ // --------------------------------------------------------------------
630
+
631
+ TEST_F(ParseDeathTest, TestFlagSuggestions) {
632
+ const char* in_args1[] = {
633
+ "testbin",
634
+ "--legacy_boo",
635
+ };
636
+ EXPECT_DEATH_IF_SUPPORTED(
637
+ InvokeParse(in_args1),
638
+ "Unknown command line flag 'legacy_boo'. Did you mean: legacy_bool ?");
639
+
640
+ const char* in_args2[] = {"testbin", "--foo", "--undefok=foo1"};
641
+ EXPECT_DEATH_IF_SUPPORTED(
642
+ InvokeParse(in_args2),
643
+ "Unknown command line flag 'foo'. Did you mean: foo1 \\(undefok\\)?");
644
+
645
+ const char* in_args3[] = {
646
+ "testbin",
647
+ "--nolegacy_ino",
648
+ };
649
+ EXPECT_DEATH_IF_SUPPORTED(InvokeParse(in_args3),
650
+ "Unknown command line flag 'nolegacy_ino'. Did "
651
+ "you mean: nolegacy_bool, legacy_int ?");
652
+ }
653
+
654
+ // --------------------------------------------------------------------
655
+
656
+ TEST_F(ParseTest, GetHints) {
657
+ EXPECT_THAT(absl::flags_internal::GetMisspellingHints("legacy_boo"),
658
+ testing::ContainerEq(std::vector<std::string>{"legacy_bool"}));
659
+ EXPECT_THAT(absl::flags_internal::GetMisspellingHints("nolegacy_itn"),
660
+ testing::ContainerEq(std::vector<std::string>{"legacy_int"}));
661
+ EXPECT_THAT(absl::flags_internal::GetMisspellingHints("nolegacy_int1"),
662
+ testing::ContainerEq(std::vector<std::string>{"legacy_int"}));
663
+ EXPECT_THAT(absl::flags_internal::GetMisspellingHints("nolegacy_int"),
664
+ testing::ContainerEq(std::vector<std::string>{"legacy_int"}));
665
+ EXPECT_THAT(absl::flags_internal::GetMisspellingHints("nolegacy_ino"),
666
+ testing::ContainerEq(
667
+ std::vector<std::string>{"nolegacy_bool", "legacy_int"}));
668
+ EXPECT_THAT(
669
+ absl::flags_internal::GetMisspellingHints("FLAG_HEADER_000").size(), 100);
670
+ }
671
+
672
+ // --------------------------------------------------------------------
673
+
674
+ TEST_F(ParseTest, TestLegacyFlags) {
675
+ const char* in_args1[] = {
676
+ "testbin",
677
+ "--legacy_int=11",
678
+ };
679
+ TestParse(in_args1, 1, 1.1, "a", false);
680
+
681
+ const char* in_args2[] = {
682
+ "testbin",
683
+ "--legacy_bool",
684
+ };
685
+ TestParse(in_args2, 1, 1.1, "a", false);
686
+
687
+ const char* in_args3[] = {
688
+ "testbin", "--legacy_int", "22", "--int_flag=2",
689
+ "--legacy_bool", "true", "--legacy_str", "--string_flag=qwe",
690
+ };
691
+ TestParse(in_args3, 2, 1.1, "a", false, 1);
692
+ }
693
+
694
+ // --------------------------------------------------------------------
695
+
696
+ TEST_F(ParseTest, TestSimpleValidFlagfile) {
697
+ std::string flagfile_flag;
698
+
699
+ const char* in_args1[] = {
700
+ "testbin",
701
+ GetFlagfileFlag({{"parse_test.ff1", absl::MakeConstSpan(ff1_data)}},
702
+ flagfile_flag),
703
+ };
704
+ TestParse(in_args1, -1, 0.1, "q2w2 ", true);
705
+
706
+ const char* in_args2[] = {
707
+ "testbin",
708
+ GetFlagfileFlag({{"parse_test.ff2", absl::MakeConstSpan(ff2_data)}},
709
+ flagfile_flag),
710
+ };
711
+ TestParse(in_args2, 100, 0.1, "q2w2 ", false);
712
+ }
713
+
714
+ // --------------------------------------------------------------------
715
+
716
+ TEST_F(ParseTest, TestValidMultiFlagfile) {
717
+ std::string flagfile_flag;
718
+
719
+ const char* in_args1[] = {
720
+ "testbin",
721
+ GetFlagfileFlag({{"parse_test.ff2", absl::MakeConstSpan(ff2_data)},
722
+ {"parse_test.ff1", absl::MakeConstSpan(ff1_data)}},
723
+ flagfile_flag),
724
+ };
725
+ TestParse(in_args1, -1, 0.1, "q2w2 ", true);
726
+ }
727
+
728
+ // --------------------------------------------------------------------
729
+
730
+ TEST_F(ParseTest, TestFlagfileMixedWithRegularFlags) {
731
+ std::string flagfile_flag;
732
+
733
+ const char* in_args1[] = {
734
+ "testbin", "--int_flag=3",
735
+ GetFlagfileFlag({{"parse_test.ff1", absl::MakeConstSpan(ff1_data)}},
736
+ flagfile_flag),
737
+ "-double_flag=0.2"};
738
+ TestParse(in_args1, -1, 0.2, "q2w2 ", true);
739
+ }
740
+
741
+ // --------------------------------------------------------------------
742
+
743
+ TEST_F(ParseTest, TestFlagfileInFlagfile) {
744
+ std::string flagfile_flag;
745
+
746
+ constexpr const char* const ff3_data[] = {
747
+ "--flagfile=$0/parse_test.ff1",
748
+ "--flagfile=$0/parse_test.ff2",
749
+ };
750
+
751
+ GetFlagfileFlag({{"parse_test.ff2", absl::MakeConstSpan(ff2_data)},
752
+ {"parse_test.ff1", absl::MakeConstSpan(ff1_data)}},
753
+ flagfile_flag);
754
+
755
+ const char* in_args1[] = {
756
+ "testbin",
757
+ GetFlagfileFlag({{"parse_test.ff3", absl::MakeConstSpan(ff3_data)}},
758
+ flagfile_flag),
759
+ };
760
+ TestParse(in_args1, 100, 0.1, "q2w2 ", false);
761
+ }
762
+
763
+ // --------------------------------------------------------------------
764
+
765
+ TEST_F(ParseDeathTest, TestInvalidFlagfiles) {
766
+ std::string flagfile_flag;
767
+
768
+ constexpr const char* const ff4_data[] = {
769
+ "--unknown_flag=10"
770
+ };
771
+
772
+ const char* in_args1[] = {
773
+ "testbin",
774
+ GetFlagfileFlag({{"parse_test.ff4",
775
+ absl::MakeConstSpan(ff4_data)}}, flagfile_flag),
776
+ };
777
+ EXPECT_DEATH_IF_SUPPORTED(InvokeParse(in_args1),
778
+ "Unknown command line flag 'unknown_flag'");
779
+
780
+ constexpr const char* const ff5_data[] = {
781
+ "--int_flag 10",
782
+ };
783
+
784
+ const char* in_args2[] = {
785
+ "testbin",
786
+ GetFlagfileFlag({{"parse_test.ff5",
787
+ absl::MakeConstSpan(ff5_data)}}, flagfile_flag),
788
+ };
789
+ EXPECT_DEATH_IF_SUPPORTED(InvokeParse(in_args2),
790
+ "Unknown command line flag 'int_flag 10'");
791
+
792
+ constexpr const char* const ff6_data[] = {
793
+ "--int_flag=10", "--", "arg1", "arg2", "arg3",
794
+ };
795
+
796
+ const char* in_args3[] = {
797
+ "testbin",
798
+ GetFlagfileFlag({{"parse_test.ff6", absl::MakeConstSpan(ff6_data)}},
799
+ flagfile_flag),
800
+ };
801
+ EXPECT_DEATH_IF_SUPPORTED(InvokeParse(in_args3),
802
+ "Flagfile can't contain position arguments or --");
803
+
804
+ const char* in_args4[] = {
805
+ "testbin",
806
+ "--flagfile=invalid_flag_file",
807
+ };
808
+ EXPECT_DEATH_IF_SUPPORTED(InvokeParse(in_args4),
809
+ "Can't open flagfile invalid_flag_file");
810
+
811
+ constexpr const char* const ff7_data[] = {
812
+ "--int_flag=10",
813
+ "*bin*",
814
+ "--str_flag=aqsw",
815
+ };
816
+
817
+ const char* in_args5[] = {
818
+ "testbin",
819
+ GetFlagfileFlag({{"parse_test.ff7", absl::MakeConstSpan(ff7_data)}},
820
+ flagfile_flag),
821
+ };
822
+ EXPECT_DEATH_IF_SUPPORTED(InvokeParse(in_args5),
823
+ "Unexpected line in the flagfile .*: \\*bin\\*");
824
+ }
825
+
826
+ // --------------------------------------------------------------------
827
+
828
+ TEST_F(ParseTest, TestReadingRequiredFlagsFromEnv) {
829
+ const char* in_args1[] = {"testbin",
830
+ "--fromenv=int_flag,bool_flag,string_flag"};
831
+
832
+ ScopedSetEnv set_int_flag("FLAGS_int_flag", "33");
833
+ ScopedSetEnv set_bool_flag("FLAGS_bool_flag", "True");
834
+ ScopedSetEnv set_string_flag("FLAGS_string_flag", "AQ12");
835
+
836
+ TestParse(in_args1, 33, 1.1, "AQ12", true);
837
+ }
838
+
839
+ // --------------------------------------------------------------------
840
+
841
+ TEST_F(ParseDeathTest, TestReadingUnsetRequiredFlagsFromEnv) {
842
+ const char* in_args1[] = {"testbin", "--fromenv=int_flag"};
843
+
844
+ EXPECT_DEATH_IF_SUPPORTED(InvokeParse(in_args1),
845
+ "FLAGS_int_flag not found in environment");
846
+ }
847
+
848
+ // --------------------------------------------------------------------
849
+
850
+ TEST_F(ParseDeathTest, TestRecursiveFlagsFromEnv) {
851
+ const char* in_args1[] = {"testbin", "--fromenv=tryfromenv"};
852
+
853
+ ScopedSetEnv set_tryfromenv("FLAGS_tryfromenv", "int_flag");
854
+
855
+ EXPECT_DEATH_IF_SUPPORTED(InvokeParse(in_args1),
856
+ "Infinite recursion on flag tryfromenv");
857
+ }
858
+
859
+ // --------------------------------------------------------------------
860
+
861
+ TEST_F(ParseTest, TestReadingOptionalFlagsFromEnv) {
862
+ const char* in_args1[] = {
863
+ "testbin", "--tryfromenv=int_flag,bool_flag,string_flag,other_flag"};
864
+
865
+ ScopedSetEnv set_int_flag("FLAGS_int_flag", "17");
866
+ ScopedSetEnv set_bool_flag("FLAGS_bool_flag", "Y");
867
+
868
+ TestParse(in_args1, 17, 1.1, "a", true);
869
+ }
870
+
871
+ // --------------------------------------------------------------------
872
+
873
+ TEST_F(ParseTest, TestReadingFlagsFromEnvMoxedWithRegularFlags) {
874
+ const char* in_args1[] = {
875
+ "testbin",
876
+ "--bool_flag=T",
877
+ "--tryfromenv=int_flag,bool_flag",
878
+ "--int_flag=-21",
879
+ };
880
+
881
+ ScopedSetEnv set_int_flag("FLAGS_int_flag", "-15");
882
+ ScopedSetEnv set_bool_flag("FLAGS_bool_flag", "F");
883
+
884
+ TestParse(in_args1, -21, 1.1, "a", false);
885
+ }
886
+
887
+ // --------------------------------------------------------------------
888
+
889
+ TEST_F(ParseDeathTest, TestSimpleHelpFlagHandling) {
890
+ const char* in_args1[] = {
891
+ "testbin",
892
+ "--help",
893
+ };
894
+
895
+ EXPECT_EQ(InvokeParseAbslOnlyImpl(in_args1), flags::HelpMode::kImportant);
896
+ EXPECT_EXIT(InvokeParse(in_args1), testing::ExitedWithCode(1), "");
897
+
898
+ const char* in_args2[] = {
899
+ "testbin",
900
+ "--help",
901
+ "--int_flag=3",
902
+ };
903
+
904
+ EXPECT_EQ(InvokeParseAbslOnlyImpl(in_args2), flags::HelpMode::kImportant);
905
+ EXPECT_EQ(absl::GetFlag(FLAGS_int_flag), 3);
906
+
907
+ const char* in_args3[] = {"testbin", "--help", "some_positional_arg"};
908
+
909
+ EXPECT_EQ(InvokeParseAbslOnlyImpl(in_args3), flags::HelpMode::kImportant);
910
+ }
911
+
912
+ // --------------------------------------------------------------------
913
+
914
+ TEST_F(ParseTest, TestSubstringHelpFlagHandling) {
915
+ const char* in_args1[] = {
916
+ "testbin",
917
+ "--help=abcd",
918
+ };
919
+
920
+ EXPECT_EQ(InvokeParseAbslOnlyImpl(in_args1), flags::HelpMode::kMatch);
921
+ EXPECT_EQ(flags::GetFlagsHelpMatchSubstr(), "abcd");
922
+ }
923
+
924
+ // --------------------------------------------------------------------
925
+
926
+ TEST_F(ParseDeathTest, TestVersionHandling) {
927
+ const char* in_args1[] = {
928
+ "testbin",
929
+ "--version",
930
+ };
931
+
932
+ EXPECT_EQ(InvokeParseAbslOnlyImpl(in_args1), flags::HelpMode::kVersion);
933
+ }
934
+
935
+ // --------------------------------------------------------------------
936
+
937
+ TEST_F(ParseTest, TestCheckArgsHandling) {
938
+ const char* in_args1[] = {"testbin", "--only_check_args", "--int_flag=211"};
939
+
940
+ EXPECT_EQ(InvokeParseAbslOnlyImpl(in_args1), flags::HelpMode::kOnlyCheckArgs);
941
+ EXPECT_EXIT(InvokeParseAbslOnly(in_args1), testing::ExitedWithCode(0), "");
942
+ EXPECT_EXIT(InvokeParse(in_args1), testing::ExitedWithCode(0), "");
943
+
944
+ const char* in_args2[] = {"testbin", "--only_check_args", "--unknown_flag=a"};
945
+
946
+ EXPECT_EQ(InvokeParseAbslOnlyImpl(in_args2), flags::HelpMode::kOnlyCheckArgs);
947
+ EXPECT_EXIT(InvokeParseAbslOnly(in_args2), testing::ExitedWithCode(0), "");
948
+ EXPECT_EXIT(InvokeParse(in_args2), testing::ExitedWithCode(1), "");
949
+ }
950
+
951
+ // --------------------------------------------------------------------
952
+
953
+ TEST_F(ParseTest, WasPresentOnCommandLine) {
954
+ const char* in_args1[] = {
955
+ "testbin", "arg1", "--bool_flag",
956
+ "--int_flag=211", "arg2", "--double_flag=1.1",
957
+ "--string_flag", "asd", "--",
958
+ "--some_flag", "arg4",
959
+ };
960
+
961
+ InvokeParse(in_args1);
962
+
963
+ EXPECT_TRUE(flags::WasPresentOnCommandLine("bool_flag"));
964
+ EXPECT_TRUE(flags::WasPresentOnCommandLine("int_flag"));
965
+ EXPECT_TRUE(flags::WasPresentOnCommandLine("double_flag"));
966
+ EXPECT_TRUE(flags::WasPresentOnCommandLine("string_flag"));
967
+ EXPECT_FALSE(flags::WasPresentOnCommandLine("some_flag"));
968
+ EXPECT_FALSE(flags::WasPresentOnCommandLine("another_flag"));
969
+ }
970
+
971
+ // --------------------------------------------------------------------
972
+
973
+ TEST_F(ParseTest, ParseAbseilFlagsOnlySuccess) {
974
+ const char* in_args[] = {
975
+ "testbin",
976
+ "arg1",
977
+ "--bool_flag",
978
+ "--int_flag=211",
979
+ "arg2",
980
+ "--double_flag=1.1",
981
+ "--undef_flag1",
982
+ "--undef_flag2=123",
983
+ "--string_flag",
984
+ "asd",
985
+ "--",
986
+ "--some_flag",
987
+ "arg4",
988
+ };
989
+
990
+ std::vector<char*> positional_args;
991
+ std::vector<absl::UnrecognizedFlag> unrecognized_flags;
992
+
993
+ absl::ParseAbseilFlagsOnly(13, const_cast<char**>(in_args), positional_args,
994
+ unrecognized_flags);
995
+ EXPECT_THAT(positional_args,
996
+ ElementsAreArray(
997
+ {absl::string_view("testbin"), absl::string_view("arg1"),
998
+ absl::string_view("arg2"), absl::string_view("--some_flag"),
999
+ absl::string_view("arg4")}));
1000
+ EXPECT_THAT(unrecognized_flags,
1001
+ ElementsAreArray(
1002
+ {absl::UnrecognizedFlag(absl::UnrecognizedFlag::kFromArgv,
1003
+ "undef_flag1"),
1004
+ absl::UnrecognizedFlag(absl::UnrecognizedFlag::kFromArgv,
1005
+ "undef_flag2")}));
1006
+ }
1007
+
1008
+ // --------------------------------------------------------------------
1009
+
1010
+ TEST_F(ParseDeathTest, ParseAbseilFlagsOnlyFailure) {
1011
+ const char* in_args[] = {
1012
+ "testbin",
1013
+ "--int_flag=21.1",
1014
+ };
1015
+
1016
+ EXPECT_DEATH_IF_SUPPORTED(
1017
+ InvokeParseAbslOnly(in_args),
1018
+ "Illegal value '21.1' specified for flag 'int_flag'");
1019
+ }
1020
+
1021
+ // --------------------------------------------------------------------
1022
+
1023
+ TEST_F(ParseTest, UndefOkFlagsAreIgnored) {
1024
+ const char* in_args[] = {
1025
+ "testbin", "--undef_flag1",
1026
+ "--undef_flag2=123", "--undefok=undef_flag2",
1027
+ "--undef_flag3", "value",
1028
+ };
1029
+
1030
+ std::vector<char*> positional_args;
1031
+ std::vector<absl::UnrecognizedFlag> unrecognized_flags;
1032
+
1033
+ absl::ParseAbseilFlagsOnly(6, const_cast<char**>(in_args), positional_args,
1034
+ unrecognized_flags);
1035
+ EXPECT_THAT(positional_args, ElementsAreArray({absl::string_view("testbin"),
1036
+ absl::string_view("value")}));
1037
+ EXPECT_THAT(unrecognized_flags,
1038
+ ElementsAreArray(
1039
+ {absl::UnrecognizedFlag(absl::UnrecognizedFlag::kFromArgv,
1040
+ "undef_flag1"),
1041
+ absl::UnrecognizedFlag(absl::UnrecognizedFlag::kFromArgv,
1042
+ "undef_flag3")}));
1043
+ }
1044
+
1045
+ // --------------------------------------------------------------------
1046
+
1047
+ TEST_F(ParseTest, AllUndefOkFlagsAreIgnored) {
1048
+ const char* in_args[] = {
1049
+ "testbin",
1050
+ "--undef_flag1",
1051
+ "--undef_flag2=123",
1052
+ "--undefok=undef_flag2,undef_flag1,undef_flag3",
1053
+ "--undef_flag3",
1054
+ "value",
1055
+ "--",
1056
+ "--undef_flag4",
1057
+ };
1058
+
1059
+ std::vector<char*> positional_args;
1060
+ std::vector<absl::UnrecognizedFlag> unrecognized_flags;
1061
+
1062
+ absl::ParseAbseilFlagsOnly(8, const_cast<char**>(in_args), positional_args,
1063
+ unrecognized_flags);
1064
+ EXPECT_THAT(positional_args,
1065
+ ElementsAreArray({absl::string_view("testbin"),
1066
+ absl::string_view("value"),
1067
+ absl::string_view("--undef_flag4")}));
1068
+ EXPECT_THAT(unrecognized_flags, testing::IsEmpty());
1069
+ }
1070
+
1071
+ // --------------------------------------------------------------------
1072
+
1073
+ TEST_F(ParseDeathTest, ExitOnUnrecognizedFlagPrintsHelp) {
1074
+ const char* in_args[] = {
1075
+ "testbin",
1076
+ "--undef_flag1",
1077
+ "--help=int_flag",
1078
+ };
1079
+
1080
+ EXPECT_EXIT(InvokeParseCommandLineImpl(in_args), testing::ExitedWithCode(1),
1081
+ AllOf(HasSubstr("Unknown command line flag 'undef_flag1'"),
1082
+ HasSubstr("Try --helpfull to get a list of all flags")));
1083
+ }
1084
+
1085
+ // --------------------------------------------------------------------
1086
+
1087
+ } // namespace
weight/_dep/abseil-cpp/absl/flags/reflection.h ADDED
@@ -0,0 +1,90 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ //
2
+ // Copyright 2020 The Abseil Authors.
3
+ //
4
+ // Licensed under the Apache License, Version 2.0 (the "License");
5
+ // you may not use this file except in compliance with the License.
6
+ // You may obtain a copy of the License at
7
+ //
8
+ // https://www.apache.org/licenses/LICENSE-2.0
9
+ //
10
+ // Unless required by applicable law or agreed to in writing, software
11
+ // distributed under the License is distributed on an "AS IS" BASIS,
12
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ // See the License for the specific language governing permissions and
14
+ // limitations under the License.
15
+ //
16
+ // -----------------------------------------------------------------------------
17
+ // File: reflection.h
18
+ // -----------------------------------------------------------------------------
19
+ //
20
+ // This file defines the routines to access and operate on an Abseil Flag's
21
+ // reflection handle.
22
+
23
+ #ifndef ABSL_FLAGS_REFLECTION_H_
24
+ #define ABSL_FLAGS_REFLECTION_H_
25
+
26
+ #include <string>
27
+
28
+ #include "absl/base/config.h"
29
+ #include "absl/container/flat_hash_map.h"
30
+ #include "absl/flags/commandlineflag.h"
31
+ #include "absl/flags/internal/commandlineflag.h"
32
+
33
+ namespace absl {
34
+ ABSL_NAMESPACE_BEGIN
35
+ namespace flags_internal {
36
+ class FlagSaverImpl;
37
+ } // namespace flags_internal
38
+
39
+ // FindCommandLineFlag()
40
+ //
41
+ // Returns the reflection handle of an Abseil flag of the specified name, or
42
+ // `nullptr` if not found. This function will emit a warning if the name of a
43
+ // 'retired' flag is specified.
44
+ absl::CommandLineFlag* FindCommandLineFlag(absl::string_view name);
45
+
46
+ // Returns current state of the Flags registry in a form of mapping from flag
47
+ // name to a flag reflection handle.
48
+ absl::flat_hash_map<absl::string_view, absl::CommandLineFlag*> GetAllFlags();
49
+
50
+ //------------------------------------------------------------------------------
51
+ // FlagSaver
52
+ //------------------------------------------------------------------------------
53
+ //
54
+ // A FlagSaver object stores the state of flags in the scope where the FlagSaver
55
+ // is defined, allowing modification of those flags within that scope and
56
+ // automatic restoration of the flags to their previous state upon leaving the
57
+ // scope.
58
+ //
59
+ // A FlagSaver can be used within tests to temporarily change the test
60
+ // environment and restore the test case to its previous state.
61
+ //
62
+ // Example:
63
+ //
64
+ // void MyFunc() {
65
+ // absl::FlagSaver fs;
66
+ // ...
67
+ // absl::SetFlag(&FLAGS_myFlag, otherValue);
68
+ // ...
69
+ // } // scope of FlagSaver left, flags return to previous state
70
+ //
71
+ // This class is thread-safe.
72
+
73
+ class FlagSaver {
74
+ public:
75
+ FlagSaver();
76
+ ~FlagSaver();
77
+
78
+ FlagSaver(const FlagSaver&) = delete;
79
+ void operator=(const FlagSaver&) = delete;
80
+
81
+ private:
82
+ flags_internal::FlagSaverImpl* impl_;
83
+ };
84
+
85
+ //-----------------------------------------------------------------------------
86
+
87
+ ABSL_NAMESPACE_END
88
+ } // namespace absl
89
+
90
+ #endif // ABSL_FLAGS_REFLECTION_H_
weight/_dep/abseil-cpp/absl/flags/reflection_test.cc ADDED
@@ -0,0 +1,265 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ //
2
+ // Copyright 2019 The Abseil Authors.
3
+ //
4
+ // Licensed under the Apache License, Version 2.0 (the "License");
5
+ // you may not use this file except in compliance with the License.
6
+ // You may obtain a copy of the License at
7
+ //
8
+ // https://www.apache.org/licenses/LICENSE-2.0
9
+ //
10
+ // Unless required by applicable law or agreed to in writing, software
11
+ // distributed under the License is distributed on an "AS IS" BASIS,
12
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ // See the License for the specific language governing permissions and
14
+ // limitations under the License.
15
+
16
+ #include "absl/flags/reflection.h"
17
+
18
+ #include <memory>
19
+ #include <string>
20
+
21
+ #include "gmock/gmock.h"
22
+ #include "gtest/gtest.h"
23
+ #include "absl/flags/declare.h"
24
+ #include "absl/flags/flag.h"
25
+ #include "absl/flags/internal/commandlineflag.h"
26
+ #include "absl/flags/marshalling.h"
27
+ #include "absl/memory/memory.h"
28
+ #include "absl/strings/str_cat.h"
29
+ #include "absl/strings/str_split.h"
30
+
31
+ ABSL_FLAG(int, int_flag, 1, "int_flag help");
32
+ ABSL_FLAG(std::string, string_flag, "dflt", "string_flag help");
33
+ ABSL_RETIRED_FLAG(bool, bool_retired_flag, false, "bool_retired_flag help");
34
+
35
+ namespace {
36
+
37
+ class ReflectionTest : public testing::Test {
38
+ protected:
39
+ void SetUp() override { flag_saver_ = absl::make_unique<absl::FlagSaver>(); }
40
+ void TearDown() override { flag_saver_.reset(); }
41
+
42
+ private:
43
+ std::unique_ptr<absl::FlagSaver> flag_saver_;
44
+ };
45
+
46
+ // --------------------------------------------------------------------
47
+
48
+ TEST_F(ReflectionTest, TestFindCommandLineFlag) {
49
+ auto* handle = absl::FindCommandLineFlag("some_flag");
50
+ EXPECT_EQ(handle, nullptr);
51
+
52
+ handle = absl::FindCommandLineFlag("int_flag");
53
+ EXPECT_NE(handle, nullptr);
54
+
55
+ handle = absl::FindCommandLineFlag("string_flag");
56
+ EXPECT_NE(handle, nullptr);
57
+
58
+ handle = absl::FindCommandLineFlag("bool_retired_flag");
59
+ EXPECT_NE(handle, nullptr);
60
+ }
61
+
62
+ // --------------------------------------------------------------------
63
+
64
+ TEST_F(ReflectionTest, TestGetAllFlags) {
65
+ auto all_flags = absl::GetAllFlags();
66
+ EXPECT_NE(all_flags.find("int_flag"), all_flags.end());
67
+ EXPECT_EQ(all_flags.find("bool_retired_flag"), all_flags.end());
68
+ EXPECT_EQ(all_flags.find("some_undefined_flag"), all_flags.end());
69
+
70
+ std::vector<absl::string_view> flag_names_first_attempt;
71
+ auto all_flags_1 = absl::GetAllFlags();
72
+ for (auto f : all_flags_1) {
73
+ flag_names_first_attempt.push_back(f.first);
74
+ }
75
+
76
+ std::vector<absl::string_view> flag_names_second_attempt;
77
+ auto all_flags_2 = absl::GetAllFlags();
78
+ for (auto f : all_flags_2) {
79
+ flag_names_second_attempt.push_back(f.first);
80
+ }
81
+
82
+ EXPECT_THAT(flag_names_first_attempt,
83
+ ::testing::UnorderedElementsAreArray(flag_names_second_attempt));
84
+ }
85
+
86
+ // --------------------------------------------------------------------
87
+
88
+ struct CustomUDT {
89
+ CustomUDT() : a(1), b(1) {}
90
+ CustomUDT(int a_, int b_) : a(a_), b(b_) {}
91
+
92
+ friend bool operator==(const CustomUDT& f1, const CustomUDT& f2) {
93
+ return f1.a == f2.a && f1.b == f2.b;
94
+ }
95
+
96
+ int a;
97
+ int b;
98
+ };
99
+ bool AbslParseFlag(absl::string_view in, CustomUDT* f, std::string*) {
100
+ std::vector<absl::string_view> parts =
101
+ absl::StrSplit(in, ':', absl::SkipWhitespace());
102
+
103
+ if (parts.size() != 2) return false;
104
+
105
+ if (!absl::SimpleAtoi(parts[0], &f->a)) return false;
106
+
107
+ if (!absl::SimpleAtoi(parts[1], &f->b)) return false;
108
+
109
+ return true;
110
+ }
111
+ std::string AbslUnparseFlag(const CustomUDT& f) {
112
+ return absl::StrCat(f.a, ":", f.b);
113
+ }
114
+
115
+ } // namespace
116
+
117
+ // --------------------------------------------------------------------
118
+
119
+ ABSL_FLAG(bool, test_flag_01, true, "");
120
+ ABSL_FLAG(int, test_flag_02, 1234, "");
121
+ ABSL_FLAG(int16_t, test_flag_03, -34, "");
122
+ ABSL_FLAG(uint16_t, test_flag_04, 189, "");
123
+ ABSL_FLAG(int32_t, test_flag_05, 10765, "");
124
+ ABSL_FLAG(uint32_t, test_flag_06, 40000, "");
125
+ ABSL_FLAG(int64_t, test_flag_07, -1234567, "");
126
+ ABSL_FLAG(uint64_t, test_flag_08, 9876543, "");
127
+ ABSL_FLAG(double, test_flag_09, -9.876e-50, "");
128
+ ABSL_FLAG(float, test_flag_10, 1.234e12f, "");
129
+ ABSL_FLAG(std::string, test_flag_11, "", "");
130
+ ABSL_FLAG(absl::Duration, test_flag_12, absl::Minutes(10), "");
131
+ static int counter = 0;
132
+ ABSL_FLAG(int, test_flag_13, 200, "").OnUpdate([]() { counter++; });
133
+ ABSL_FLAG(CustomUDT, test_flag_14, {}, "");
134
+
135
+ namespace {
136
+
137
+ TEST_F(ReflectionTest, TestFlagSaverInScope) {
138
+ {
139
+ absl::FlagSaver s;
140
+ counter = 0;
141
+ absl::SetFlag(&FLAGS_test_flag_01, false);
142
+ absl::SetFlag(&FLAGS_test_flag_02, -1021);
143
+ absl::SetFlag(&FLAGS_test_flag_03, 6009);
144
+ absl::SetFlag(&FLAGS_test_flag_04, 44);
145
+ absl::SetFlag(&FLAGS_test_flag_05, +800);
146
+ absl::SetFlag(&FLAGS_test_flag_06, -40978756);
147
+ absl::SetFlag(&FLAGS_test_flag_07, 23405);
148
+ absl::SetFlag(&FLAGS_test_flag_08, 975310);
149
+ absl::SetFlag(&FLAGS_test_flag_09, 1.00001);
150
+ absl::SetFlag(&FLAGS_test_flag_10, -3.54f);
151
+ absl::SetFlag(&FLAGS_test_flag_11, "asdf");
152
+ absl::SetFlag(&FLAGS_test_flag_12, absl::Hours(20));
153
+ absl::SetFlag(&FLAGS_test_flag_13, 4);
154
+ absl::SetFlag(&FLAGS_test_flag_14, CustomUDT{-1, -2});
155
+ }
156
+
157
+ EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_01), true);
158
+ EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_02), 1234);
159
+ EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_03), -34);
160
+ EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_04), 189);
161
+ EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_05), 10765);
162
+ EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_06), 40000);
163
+ EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_07), -1234567);
164
+ EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_08), 9876543);
165
+ EXPECT_NEAR(absl::GetFlag(FLAGS_test_flag_09), -9.876e-50, 1e-55);
166
+ EXPECT_NEAR(absl::GetFlag(FLAGS_test_flag_10), 1.234e12f, 1e5f);
167
+ EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_11), "");
168
+ EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_12), absl::Minutes(10));
169
+ EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_13), 200);
170
+ EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_14), CustomUDT{});
171
+ EXPECT_EQ(counter, 2);
172
+ }
173
+
174
+ // --------------------------------------------------------------------
175
+
176
+ TEST_F(ReflectionTest, TestFlagSaverVsUpdateViaReflection) {
177
+ {
178
+ absl::FlagSaver s;
179
+ counter = 0;
180
+ std::string error;
181
+ EXPECT_TRUE(
182
+ absl::FindCommandLineFlag("test_flag_01")->ParseFrom("false", &error))
183
+ << error;
184
+ EXPECT_TRUE(
185
+ absl::FindCommandLineFlag("test_flag_02")->ParseFrom("-4536", &error))
186
+ << error;
187
+ EXPECT_TRUE(
188
+ absl::FindCommandLineFlag("test_flag_03")->ParseFrom("111", &error))
189
+ << error;
190
+ EXPECT_TRUE(
191
+ absl::FindCommandLineFlag("test_flag_04")->ParseFrom("909", &error))
192
+ << error;
193
+ EXPECT_TRUE(
194
+ absl::FindCommandLineFlag("test_flag_05")->ParseFrom("-2004", &error))
195
+ << error;
196
+ EXPECT_TRUE(
197
+ absl::FindCommandLineFlag("test_flag_06")->ParseFrom("1000023", &error))
198
+ << error;
199
+ EXPECT_TRUE(
200
+ absl::FindCommandLineFlag("test_flag_07")->ParseFrom("69305", &error))
201
+ << error;
202
+ EXPECT_TRUE(absl::FindCommandLineFlag("test_flag_08")
203
+ ->ParseFrom("1000000001", &error))
204
+ << error;
205
+ EXPECT_TRUE(
206
+ absl::FindCommandLineFlag("test_flag_09")->ParseFrom("2.09021", &error))
207
+ << error;
208
+ EXPECT_TRUE(
209
+ absl::FindCommandLineFlag("test_flag_10")->ParseFrom("-33.1", &error))
210
+ << error;
211
+ EXPECT_TRUE(
212
+ absl::FindCommandLineFlag("test_flag_11")->ParseFrom("ADD_FOO", &error))
213
+ << error;
214
+ EXPECT_TRUE(absl::FindCommandLineFlag("test_flag_12")
215
+ ->ParseFrom("3h11m16s", &error))
216
+ << error;
217
+ EXPECT_TRUE(
218
+ absl::FindCommandLineFlag("test_flag_13")->ParseFrom("0", &error))
219
+ << error;
220
+ EXPECT_TRUE(
221
+ absl::FindCommandLineFlag("test_flag_14")->ParseFrom("10:1", &error))
222
+ << error;
223
+ }
224
+
225
+ EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_01), true);
226
+ EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_02), 1234);
227
+ EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_03), -34);
228
+ EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_04), 189);
229
+ EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_05), 10765);
230
+ EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_06), 40000);
231
+ EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_07), -1234567);
232
+ EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_08), 9876543);
233
+ EXPECT_NEAR(absl::GetFlag(FLAGS_test_flag_09), -9.876e-50, 1e-55);
234
+ EXPECT_NEAR(absl::GetFlag(FLAGS_test_flag_10), 1.234e12f, 1e5f);
235
+ EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_11), "");
236
+ EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_12), absl::Minutes(10));
237
+ EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_13), 200);
238
+ EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_14), CustomUDT{});
239
+ EXPECT_EQ(counter, 2);
240
+ }
241
+
242
+ // --------------------------------------------------------------------
243
+
244
+ TEST_F(ReflectionTest, TestMultipleFlagSaversInEnclosedScopes) {
245
+ {
246
+ absl::FlagSaver s;
247
+ absl::SetFlag(&FLAGS_test_flag_08, 10);
248
+ EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_08), 10);
249
+ {
250
+ absl::FlagSaver s;
251
+ absl::SetFlag(&FLAGS_test_flag_08, 20);
252
+ EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_08), 20);
253
+ {
254
+ absl::FlagSaver s;
255
+ absl::SetFlag(&FLAGS_test_flag_08, -200);
256
+ EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_08), -200);
257
+ }
258
+ EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_08), 20);
259
+ }
260
+ EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_08), 10);
261
+ }
262
+ EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_08), 9876543);
263
+ }
264
+
265
+ } // namespace
weight/_dep/abseil-cpp/absl/flags/usage.cc ADDED
@@ -0,0 +1,66 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ //
2
+ // Copyright 2019 The Abseil Authors.
3
+ //
4
+ // Licensed under the Apache License, Version 2.0 (the "License");
5
+ // you may not use this file except in compliance with the License.
6
+ // You may obtain a copy of the License at
7
+ //
8
+ // https://www.apache.org/licenses/LICENSE-2.0
9
+ //
10
+ // Unless required by applicable law or agreed to in writing, software
11
+ // distributed under the License is distributed on an "AS IS" BASIS,
12
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ // See the License for the specific language governing permissions and
14
+ // limitations under the License.
15
+ #include "absl/flags/usage.h"
16
+
17
+ #include <stdlib.h>
18
+
19
+ #include <string>
20
+
21
+ #include "absl/base/attributes.h"
22
+ #include "absl/base/config.h"
23
+ #include "absl/base/const_init.h"
24
+ #include "absl/base/internal/raw_logging.h"
25
+ #include "absl/base/thread_annotations.h"
26
+ #include "absl/flags/internal/usage.h"
27
+ #include "absl/strings/string_view.h"
28
+ #include "absl/synchronization/mutex.h"
29
+
30
+ namespace absl {
31
+ ABSL_NAMESPACE_BEGIN
32
+ namespace flags_internal {
33
+ namespace {
34
+ ABSL_CONST_INIT absl::Mutex usage_message_guard(absl::kConstInit);
35
+ ABSL_CONST_INIT std::string* program_usage_message
36
+ ABSL_GUARDED_BY(usage_message_guard) = nullptr;
37
+ } // namespace
38
+ } // namespace flags_internal
39
+
40
+ // --------------------------------------------------------------------
41
+ // Sets the "usage" message to be used by help reporting routines.
42
+ void SetProgramUsageMessage(absl::string_view new_usage_message) {
43
+ absl::MutexLock l(&flags_internal::usage_message_guard);
44
+
45
+ if (flags_internal::program_usage_message != nullptr) {
46
+ ABSL_INTERNAL_LOG(FATAL, "SetProgramUsageMessage() called twice.");
47
+ std::exit(1);
48
+ }
49
+
50
+ flags_internal::program_usage_message = new std::string(new_usage_message);
51
+ }
52
+
53
+ // --------------------------------------------------------------------
54
+ // Returns the usage message set by SetProgramUsageMessage().
55
+ // Note: We able to return string_view here only because calling
56
+ // SetProgramUsageMessage twice is prohibited.
57
+ absl::string_view ProgramUsageMessage() {
58
+ absl::MutexLock l(&flags_internal::usage_message_guard);
59
+
60
+ return flags_internal::program_usage_message != nullptr
61
+ ? absl::string_view(*flags_internal::program_usage_message)
62
+ : "Warning: SetProgramUsageMessage() never called";
63
+ }
64
+
65
+ ABSL_NAMESPACE_END
66
+ } // namespace absl
weight/_dep/abseil-cpp/absl/flags/usage_config.cc ADDED
@@ -0,0 +1,165 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ //
2
+ // Copyright 2019 The Abseil Authors.
3
+ //
4
+ // Licensed under the Apache License, Version 2.0 (the "License");
5
+ // you may not use this file except in compliance with the License.
6
+ // You may obtain a copy of the License at
7
+ //
8
+ // https://www.apache.org/licenses/LICENSE-2.0
9
+ //
10
+ // Unless required by applicable law or agreed to in writing, software
11
+ // distributed under the License is distributed on an "AS IS" BASIS,
12
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ // See the License for the specific language governing permissions and
14
+ // limitations under the License.
15
+
16
+ #include "absl/flags/usage_config.h"
17
+
18
+ #include <functional>
19
+ #include <iostream>
20
+ #include <string>
21
+
22
+ #include "absl/base/attributes.h"
23
+ #include "absl/base/config.h"
24
+ #include "absl/base/const_init.h"
25
+ #include "absl/base/thread_annotations.h"
26
+ #include "absl/flags/internal/path_util.h"
27
+ #include "absl/flags/internal/program_name.h"
28
+ #include "absl/strings/match.h"
29
+ #include "absl/strings/string_view.h"
30
+ #include "absl/strings/strip.h"
31
+ #include "absl/synchronization/mutex.h"
32
+
33
+ extern "C" {
34
+
35
+ // Additional report of fatal usage error message before we std::exit. Error is
36
+ // fatal if is_fatal argument to ReportUsageError is true.
37
+ ABSL_ATTRIBUTE_WEAK void ABSL_INTERNAL_C_SYMBOL(
38
+ AbslInternalReportFatalUsageError)(absl::string_view) {}
39
+
40
+ } // extern "C"
41
+
42
+ namespace absl {
43
+ ABSL_NAMESPACE_BEGIN
44
+ namespace flags_internal {
45
+
46
+ namespace {
47
+
48
+ // --------------------------------------------------------------------
49
+ // Returns true if flags defined in the filename should be reported with
50
+ // -helpshort flag.
51
+
52
+ bool ContainsHelpshortFlags(absl::string_view filename) {
53
+ // By default we only want flags in binary's main. We expect the main
54
+ // routine to reside in <program>.cc or <program>-main.cc or
55
+ // <program>_main.cc, where the <program> is the name of the binary
56
+ // (without .exe on Windows).
57
+ auto suffix = flags_internal::Basename(filename);
58
+ auto program_name = flags_internal::ShortProgramInvocationName();
59
+ absl::string_view program_name_ref = program_name;
60
+ #if defined(_WIN32)
61
+ absl::ConsumeSuffix(&program_name_ref, ".exe");
62
+ #endif
63
+ if (!absl::ConsumePrefix(&suffix, program_name_ref))
64
+ return false;
65
+ return absl::StartsWith(suffix, ".") || absl::StartsWith(suffix, "-main.") ||
66
+ absl::StartsWith(suffix, "_main.");
67
+ }
68
+
69
+ // --------------------------------------------------------------------
70
+ // Returns true if flags defined in the filename should be reported with
71
+ // -helppackage flag.
72
+
73
+ bool ContainsHelppackageFlags(absl::string_view filename) {
74
+ // TODO(rogeeff): implement properly when registry is available.
75
+ return ContainsHelpshortFlags(filename);
76
+ }
77
+
78
+ // --------------------------------------------------------------------
79
+ // Generates program version information into supplied output.
80
+
81
+ std::string VersionString() {
82
+ std::string version_str(flags_internal::ShortProgramInvocationName());
83
+
84
+ version_str += "\n";
85
+
86
+ #if !defined(NDEBUG)
87
+ version_str += "Debug build (NDEBUG not #defined)\n";
88
+ #endif
89
+
90
+ return version_str;
91
+ }
92
+
93
+ // --------------------------------------------------------------------
94
+ // Normalizes the filename specific to the build system/filesystem used.
95
+
96
+ std::string NormalizeFilename(absl::string_view filename) {
97
+ // Skip any leading slashes
98
+ auto pos = filename.find_first_not_of("\\/");
99
+ if (pos == absl::string_view::npos) return "";
100
+
101
+ filename.remove_prefix(pos);
102
+ return std::string(filename);
103
+ }
104
+
105
+ // --------------------------------------------------------------------
106
+
107
+ ABSL_CONST_INIT absl::Mutex custom_usage_config_guard(absl::kConstInit);
108
+ ABSL_CONST_INIT FlagsUsageConfig* custom_usage_config
109
+ ABSL_GUARDED_BY(custom_usage_config_guard) = nullptr;
110
+
111
+ } // namespace
112
+
113
+ FlagsUsageConfig GetUsageConfig() {
114
+ absl::MutexLock l(&custom_usage_config_guard);
115
+
116
+ if (custom_usage_config) return *custom_usage_config;
117
+
118
+ FlagsUsageConfig default_config;
119
+ default_config.contains_helpshort_flags = &ContainsHelpshortFlags;
120
+ default_config.contains_help_flags = &ContainsHelppackageFlags;
121
+ default_config.contains_helppackage_flags = &ContainsHelppackageFlags;
122
+ default_config.version_string = &VersionString;
123
+ default_config.normalize_filename = &NormalizeFilename;
124
+
125
+ return default_config;
126
+ }
127
+
128
+ void ReportUsageError(absl::string_view msg, bool is_fatal) {
129
+ std::cerr << "ERROR: " << msg << std::endl;
130
+
131
+ if (is_fatal) {
132
+ ABSL_INTERNAL_C_SYMBOL(AbslInternalReportFatalUsageError)(msg);
133
+ }
134
+ }
135
+
136
+ } // namespace flags_internal
137
+
138
+ void SetFlagsUsageConfig(FlagsUsageConfig usage_config) {
139
+ absl::MutexLock l(&flags_internal::custom_usage_config_guard);
140
+
141
+ if (!usage_config.contains_helpshort_flags)
142
+ usage_config.contains_helpshort_flags =
143
+ flags_internal::ContainsHelpshortFlags;
144
+
145
+ if (!usage_config.contains_help_flags)
146
+ usage_config.contains_help_flags = flags_internal::ContainsHelppackageFlags;
147
+
148
+ if (!usage_config.contains_helppackage_flags)
149
+ usage_config.contains_helppackage_flags =
150
+ flags_internal::ContainsHelppackageFlags;
151
+
152
+ if (!usage_config.version_string)
153
+ usage_config.version_string = flags_internal::VersionString;
154
+
155
+ if (!usage_config.normalize_filename)
156
+ usage_config.normalize_filename = flags_internal::NormalizeFilename;
157
+
158
+ if (flags_internal::custom_usage_config)
159
+ *flags_internal::custom_usage_config = usage_config;
160
+ else
161
+ flags_internal::custom_usage_config = new FlagsUsageConfig(usage_config);
162
+ }
163
+
164
+ ABSL_NAMESPACE_END
165
+ } // namespace absl
weight/_dep/abseil-cpp/absl/flags/usage_config.h ADDED
@@ -0,0 +1,135 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ //
2
+ // Copyright 2019 The Abseil Authors.
3
+ //
4
+ // Licensed under the Apache License, Version 2.0 (the "License");
5
+ // you may not use this file except in compliance with the License.
6
+ // You may obtain a copy of the License at
7
+ //
8
+ // https://www.apache.org/licenses/LICENSE-2.0
9
+ //
10
+ // Unless required by applicable law or agreed to in writing, software
11
+ // distributed under the License is distributed on an "AS IS" BASIS,
12
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ // See the License for the specific language governing permissions and
14
+ // limitations under the License.
15
+ //
16
+ // -----------------------------------------------------------------------------
17
+ // File: usage_config.h
18
+ // -----------------------------------------------------------------------------
19
+ //
20
+ // This file defines the main usage reporting configuration interfaces and
21
+ // documents Abseil's supported built-in usage flags. If these flags are found
22
+ // when parsing a command-line, Abseil will exit the program and display
23
+ // appropriate help messages.
24
+ #ifndef ABSL_FLAGS_USAGE_CONFIG_H_
25
+ #define ABSL_FLAGS_USAGE_CONFIG_H_
26
+
27
+ #include <functional>
28
+ #include <string>
29
+
30
+ #include "absl/base/config.h"
31
+ #include "absl/strings/string_view.h"
32
+
33
+ // -----------------------------------------------------------------------------
34
+ // Built-in Usage Flags
35
+ // -----------------------------------------------------------------------------
36
+ //
37
+ // Abseil supports the following built-in usage flags. When passed, these flags
38
+ // exit the program and :
39
+ //
40
+ // * --help
41
+ // Shows help on important flags for this binary
42
+ // * --helpfull
43
+ // Shows help on all flags
44
+ // * --helpshort
45
+ // Shows help on only the main module for this program
46
+ // * --helppackage
47
+ // Shows help on all modules in the main package
48
+ // * --version
49
+ // Shows the version and build info for this binary and exits
50
+ // * --only_check_args
51
+ // Exits after checking all flags
52
+ // * --helpon
53
+ // Shows help on the modules named by this flag value
54
+ // * --helpmatch
55
+ // Shows help on modules whose name contains the specified substring
56
+
57
+ namespace absl {
58
+ ABSL_NAMESPACE_BEGIN
59
+
60
+ namespace flags_internal {
61
+ using FlagKindFilter = std::function<bool (absl::string_view)>;
62
+ } // namespace flags_internal
63
+
64
+ // FlagsUsageConfig
65
+ //
66
+ // This structure contains the collection of callbacks for changing the behavior
67
+ // of the usage reporting routines in Abseil Flags.
68
+ struct FlagsUsageConfig {
69
+ // Returns true if flags defined in the given source code file should be
70
+ // reported with --helpshort flag. For example, if the file
71
+ // "path/to/my/code.cc" defines the flag "--my_flag", and
72
+ // contains_helpshort_flags("path/to/my/code.cc") returns true, invoking the
73
+ // program with --helpshort will include information about --my_flag in the
74
+ // program output.
75
+ flags_internal::FlagKindFilter contains_helpshort_flags;
76
+
77
+ // Returns true if flags defined in the filename should be reported with
78
+ // --help flag. For example, if the file
79
+ // "path/to/my/code.cc" defines the flag "--my_flag", and
80
+ // contains_help_flags("path/to/my/code.cc") returns true, invoking the
81
+ // program with --help will include information about --my_flag in the
82
+ // program output.
83
+ flags_internal::FlagKindFilter contains_help_flags;
84
+
85
+ // Returns true if flags defined in the filename should be reported with
86
+ // --helppackage flag. For example, if the file
87
+ // "path/to/my/code.cc" defines the flag "--my_flag", and
88
+ // contains_helppackage_flags("path/to/my/code.cc") returns true, invoking the
89
+ // program with --helppackage will include information about --my_flag in the
90
+ // program output.
91
+ flags_internal::FlagKindFilter contains_helppackage_flags;
92
+
93
+ // Generates string containing program version. This is the string reported
94
+ // when user specifies --version in a command line.
95
+ std::function<std::string()> version_string;
96
+
97
+ // Normalizes the filename specific to the build system/filesystem used. This
98
+ // routine is used when we report the information about the flag definition
99
+ // location. For instance, if your build resides at some location you do not
100
+ // want to expose in the usage output, you can trim it to show only relevant
101
+ // part.
102
+ // For example:
103
+ // normalize_filename("/my_company/some_long_path/src/project/file.cc")
104
+ // might produce
105
+ // "project/file.cc".
106
+ std::function<std::string(absl::string_view)> normalize_filename;
107
+ };
108
+
109
+ // SetFlagsUsageConfig()
110
+ //
111
+ // Sets the usage reporting configuration callbacks. If any of the callbacks are
112
+ // not set in usage_config instance, then the default value of the callback is
113
+ // used.
114
+ void SetFlagsUsageConfig(FlagsUsageConfig usage_config);
115
+
116
+ namespace flags_internal {
117
+
118
+ FlagsUsageConfig GetUsageConfig();
119
+
120
+ void ReportUsageError(absl::string_view msg, bool is_fatal);
121
+
122
+ } // namespace flags_internal
123
+ ABSL_NAMESPACE_END
124
+ } // namespace absl
125
+
126
+ extern "C" {
127
+
128
+ // Additional report of fatal usage error message before we std::exit. Error is
129
+ // fatal if is_fatal argument to ReportUsageError is true.
130
+ void ABSL_INTERNAL_C_SYMBOL(AbslInternalReportFatalUsageError)(
131
+ absl::string_view);
132
+
133
+ } // extern "C"
134
+
135
+ #endif // ABSL_FLAGS_USAGE_CONFIG_H_
weight/_dep/abseil-cpp/absl/flags/usage_config_test.cc ADDED
@@ -0,0 +1,205 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ //
2
+ // Copyright 2019 The Abseil Authors.
3
+ //
4
+ // Licensed under the Apache License, Version 2.0 (the "License");
5
+ // you may not use this file except in compliance with the License.
6
+ // You may obtain a copy of the License at
7
+ //
8
+ // https://www.apache.org/licenses/LICENSE-2.0
9
+ //
10
+ // Unless required by applicable law or agreed to in writing, software
11
+ // distributed under the License is distributed on an "AS IS" BASIS,
12
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ // See the License for the specific language governing permissions and
14
+ // limitations under the License.
15
+
16
+ #include "absl/flags/usage_config.h"
17
+
18
+ #include <string>
19
+
20
+ #include "gtest/gtest.h"
21
+ #include "absl/flags/internal/path_util.h"
22
+ #include "absl/flags/internal/program_name.h"
23
+ #include "absl/strings/match.h"
24
+ #include "absl/strings/string_view.h"
25
+
26
+ namespace {
27
+
28
+ class FlagsUsageConfigTest : public testing::Test {
29
+ protected:
30
+ void SetUp() override {
31
+ // Install Default config for the use on this unit test.
32
+ // Binary may install a custom config before tests are run.
33
+ absl::FlagsUsageConfig default_config;
34
+ absl::SetFlagsUsageConfig(default_config);
35
+ }
36
+ };
37
+
38
+ namespace flags = absl::flags_internal;
39
+
40
+ bool TstContainsHelpshortFlags(absl::string_view f) {
41
+ return absl::StartsWith(flags::Basename(f), "progname.");
42
+ }
43
+
44
+ bool TstContainsHelppackageFlags(absl::string_view f) {
45
+ return absl::EndsWith(flags::Package(f), "aaa/");
46
+ }
47
+
48
+ bool TstContainsHelpFlags(absl::string_view f) {
49
+ return absl::EndsWith(flags::Package(f), "zzz/");
50
+ }
51
+
52
+ std::string TstVersionString() { return "program 1.0.0"; }
53
+
54
+ std::string TstNormalizeFilename(absl::string_view filename) {
55
+ return std::string(filename.substr(2));
56
+ }
57
+
58
+ void TstReportUsageMessage(absl::string_view msg) {}
59
+
60
+ // --------------------------------------------------------------------
61
+
62
+ TEST_F(FlagsUsageConfigTest, TestGetSetFlagsUsageConfig) {
63
+ EXPECT_TRUE(flags::GetUsageConfig().contains_helpshort_flags);
64
+ EXPECT_TRUE(flags::GetUsageConfig().contains_help_flags);
65
+ EXPECT_TRUE(flags::GetUsageConfig().contains_helppackage_flags);
66
+ EXPECT_TRUE(flags::GetUsageConfig().version_string);
67
+ EXPECT_TRUE(flags::GetUsageConfig().normalize_filename);
68
+
69
+ absl::FlagsUsageConfig empty_config;
70
+ empty_config.contains_helpshort_flags = &TstContainsHelpshortFlags;
71
+ empty_config.contains_help_flags = &TstContainsHelpFlags;
72
+ empty_config.contains_helppackage_flags = &TstContainsHelppackageFlags;
73
+ empty_config.version_string = &TstVersionString;
74
+ empty_config.normalize_filename = &TstNormalizeFilename;
75
+ absl::SetFlagsUsageConfig(empty_config);
76
+
77
+ EXPECT_TRUE(flags::GetUsageConfig().contains_helpshort_flags);
78
+ EXPECT_TRUE(flags::GetUsageConfig().contains_help_flags);
79
+ EXPECT_TRUE(flags::GetUsageConfig().contains_helppackage_flags);
80
+ EXPECT_TRUE(flags::GetUsageConfig().version_string);
81
+ EXPECT_TRUE(flags::GetUsageConfig().normalize_filename);
82
+ }
83
+
84
+ // --------------------------------------------------------------------
85
+
86
+ TEST_F(FlagsUsageConfigTest, TestContainsHelpshortFlags) {
87
+ #if defined(_WIN32)
88
+ flags::SetProgramInvocationName("usage_config_test.exe");
89
+ #else
90
+ flags::SetProgramInvocationName("usage_config_test");
91
+ #endif
92
+
93
+ auto config = flags::GetUsageConfig();
94
+ EXPECT_TRUE(config.contains_helpshort_flags("adir/cd/usage_config_test.cc"));
95
+ EXPECT_TRUE(
96
+ config.contains_helpshort_flags("aaaa/usage_config_test-main.cc"));
97
+ EXPECT_TRUE(config.contains_helpshort_flags("abc/usage_config_test_main.cc"));
98
+ EXPECT_FALSE(config.contains_helpshort_flags("usage_config_main.cc"));
99
+
100
+ absl::FlagsUsageConfig empty_config;
101
+ empty_config.contains_helpshort_flags = &TstContainsHelpshortFlags;
102
+ absl::SetFlagsUsageConfig(empty_config);
103
+
104
+ EXPECT_TRUE(
105
+ flags::GetUsageConfig().contains_helpshort_flags("aaa/progname.cpp"));
106
+ EXPECT_FALSE(
107
+ flags::GetUsageConfig().contains_helpshort_flags("aaa/progmane.cpp"));
108
+ }
109
+
110
+ // --------------------------------------------------------------------
111
+
112
+ TEST_F(FlagsUsageConfigTest, TestContainsHelpFlags) {
113
+ flags::SetProgramInvocationName("usage_config_test");
114
+
115
+ auto config = flags::GetUsageConfig();
116
+ EXPECT_TRUE(config.contains_help_flags("zzz/usage_config_test.cc"));
117
+ EXPECT_TRUE(
118
+ config.contains_help_flags("bdir/a/zzz/usage_config_test-main.cc"));
119
+ EXPECT_TRUE(
120
+ config.contains_help_flags("//aqse/zzz/usage_config_test_main.cc"));
121
+ EXPECT_FALSE(config.contains_help_flags("zzz/aa/usage_config_main.cc"));
122
+
123
+ absl::FlagsUsageConfig empty_config;
124
+ empty_config.contains_help_flags = &TstContainsHelpFlags;
125
+ absl::SetFlagsUsageConfig(empty_config);
126
+
127
+ EXPECT_TRUE(flags::GetUsageConfig().contains_help_flags("zzz/main-body.c"));
128
+ EXPECT_FALSE(
129
+ flags::GetUsageConfig().contains_help_flags("zzz/dir/main-body.c"));
130
+ }
131
+
132
+ // --------------------------------------------------------------------
133
+
134
+ TEST_F(FlagsUsageConfigTest, TestContainsHelppackageFlags) {
135
+ flags::SetProgramInvocationName("usage_config_test");
136
+
137
+ auto config = flags::GetUsageConfig();
138
+ EXPECT_TRUE(config.contains_helppackage_flags("aaa/usage_config_test.cc"));
139
+ EXPECT_TRUE(
140
+ config.contains_helppackage_flags("bbdir/aaa/usage_config_test-main.cc"));
141
+ EXPECT_TRUE(config.contains_helppackage_flags(
142
+ "//aqswde/aaa/usage_config_test_main.cc"));
143
+ EXPECT_FALSE(config.contains_helppackage_flags("aadir/usage_config_main.cc"));
144
+
145
+ absl::FlagsUsageConfig empty_config;
146
+ empty_config.contains_helppackage_flags = &TstContainsHelppackageFlags;
147
+ absl::SetFlagsUsageConfig(empty_config);
148
+
149
+ EXPECT_TRUE(
150
+ flags::GetUsageConfig().contains_helppackage_flags("aaa/main-body.c"));
151
+ EXPECT_FALSE(
152
+ flags::GetUsageConfig().contains_helppackage_flags("aadir/main-body.c"));
153
+ }
154
+
155
+ // --------------------------------------------------------------------
156
+
157
+ TEST_F(FlagsUsageConfigTest, TestVersionString) {
158
+ flags::SetProgramInvocationName("usage_config_test");
159
+
160
+ #ifdef NDEBUG
161
+ std::string expected_output = "usage_config_test\n";
162
+ #else
163
+ std::string expected_output =
164
+ "usage_config_test\nDebug build (NDEBUG not #defined)\n";
165
+ #endif
166
+
167
+ EXPECT_EQ(flags::GetUsageConfig().version_string(), expected_output);
168
+
169
+ absl::FlagsUsageConfig empty_config;
170
+ empty_config.version_string = &TstVersionString;
171
+ absl::SetFlagsUsageConfig(empty_config);
172
+
173
+ EXPECT_EQ(flags::GetUsageConfig().version_string(), "program 1.0.0");
174
+ }
175
+
176
+ // --------------------------------------------------------------------
177
+
178
+ TEST_F(FlagsUsageConfigTest, TestNormalizeFilename) {
179
+ // This tests the default implementation.
180
+ EXPECT_EQ(flags::GetUsageConfig().normalize_filename("a/a.cc"), "a/a.cc");
181
+ EXPECT_EQ(flags::GetUsageConfig().normalize_filename("/a/a.cc"), "a/a.cc");
182
+ EXPECT_EQ(flags::GetUsageConfig().normalize_filename("///a/a.cc"), "a/a.cc");
183
+ EXPECT_EQ(flags::GetUsageConfig().normalize_filename("/"), "");
184
+
185
+ // This tests that the custom implementation is called.
186
+ absl::FlagsUsageConfig empty_config;
187
+ empty_config.normalize_filename = &TstNormalizeFilename;
188
+ absl::SetFlagsUsageConfig(empty_config);
189
+
190
+ EXPECT_EQ(flags::GetUsageConfig().normalize_filename("a/a.cc"), "a.cc");
191
+ EXPECT_EQ(flags::GetUsageConfig().normalize_filename("aaa/a.cc"), "a/a.cc");
192
+
193
+ // This tests that the default implementation is called.
194
+ empty_config.normalize_filename = nullptr;
195
+ absl::SetFlagsUsageConfig(empty_config);
196
+
197
+ EXPECT_EQ(flags::GetUsageConfig().normalize_filename("a/a.cc"), "a/a.cc");
198
+ EXPECT_EQ(flags::GetUsageConfig().normalize_filename("/a/a.cc"), "a/a.cc");
199
+ EXPECT_EQ(flags::GetUsageConfig().normalize_filename("///a/a.cc"), "a/a.cc");
200
+ EXPECT_EQ(flags::GetUsageConfig().normalize_filename("\\a\\a.cc"), "a\\a.cc");
201
+ EXPECT_EQ(flags::GetUsageConfig().normalize_filename("//"), "");
202
+ EXPECT_EQ(flags::GetUsageConfig().normalize_filename("\\\\"), "");
203
+ }
204
+
205
+ } // namespace
weight/_dep/abseil-cpp/absl/strings/cord_test.cc ADDED
The diff for this file is too large to render. See raw diff
 
weight/_dep/abseil-cpp/absl/strings/escaping.cc ADDED
@@ -0,0 +1,957 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Copyright 2017 The Abseil Authors.
2
+ //
3
+ // Licensed under the Apache License, Version 2.0 (the "License");
4
+ // you may not use this file except in compliance with the License.
5
+ // You may obtain a copy of the License at
6
+ //
7
+ // https://www.apache.org/licenses/LICENSE-2.0
8
+ //
9
+ // Unless required by applicable law or agreed to in writing, software
10
+ // distributed under the License is distributed on an "AS IS" BASIS,
11
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ // See the License for the specific language governing permissions and
13
+ // limitations under the License.
14
+
15
+ #include "absl/strings/escaping.h"
16
+
17
+ #include <algorithm>
18
+ #include <cassert>
19
+ #include <cstddef>
20
+ #include <cstdint>
21
+ #include <cstring>
22
+ #include <limits>
23
+ #include <string>
24
+
25
+ #include "absl/base/config.h"
26
+ #include "absl/base/internal/raw_logging.h"
27
+ #include "absl/base/internal/unaligned_access.h"
28
+ #include "absl/strings/ascii.h"
29
+ #include "absl/strings/charset.h"
30
+ #include "absl/strings/internal/escaping.h"
31
+ #include "absl/strings/internal/resize_uninitialized.h"
32
+ #include "absl/strings/internal/utf8.h"
33
+ #include "absl/strings/numbers.h"
34
+ #include "absl/strings/str_cat.h"
35
+ #include "absl/strings/string_view.h"
36
+
37
+ namespace absl {
38
+ ABSL_NAMESPACE_BEGIN
39
+ namespace {
40
+
41
+ // These are used for the leave_nulls_escaped argument to CUnescapeInternal().
42
+ constexpr bool kUnescapeNulls = false;
43
+
44
+ inline bool is_octal_digit(char c) { return ('0' <= c) && (c <= '7'); }
45
+
46
+ inline unsigned int hex_digit_to_int(char c) {
47
+ static_assert('0' == 0x30 && 'A' == 0x41 && 'a' == 0x61,
48
+ "Character set must be ASCII.");
49
+ assert(absl::ascii_isxdigit(static_cast<unsigned char>(c)));
50
+ unsigned int x = static_cast<unsigned char>(c);
51
+ if (x > '9') {
52
+ x += 9;
53
+ }
54
+ return x & 0xf;
55
+ }
56
+
57
+ inline bool IsSurrogate(char32_t c, absl::string_view src, std::string* error) {
58
+ if (c >= 0xD800 && c <= 0xDFFF) {
59
+ if (error) {
60
+ *error = absl::StrCat("invalid surrogate character (0xD800-DFFF): \\",
61
+ src);
62
+ }
63
+ return true;
64
+ }
65
+ return false;
66
+ }
67
+
68
+ // ----------------------------------------------------------------------
69
+ // CUnescapeInternal()
70
+ // Implements both CUnescape() and CUnescapeForNullTerminatedString().
71
+ //
72
+ // Unescapes C escape sequences and is the reverse of CEscape().
73
+ //
74
+ // If 'source' is valid, stores the unescaped string and its size in
75
+ // 'dest' and 'dest_len' respectively, and returns true. Otherwise
76
+ // returns false and optionally stores the error description in
77
+ // 'error'. Set 'error' to nullptr to disable error reporting.
78
+ //
79
+ // 'dest' should point to a buffer that is at least as big as 'source'.
80
+ // 'source' and 'dest' may be the same.
81
+ //
82
+ // NOTE: any changes to this function must also be reflected in the older
83
+ // UnescapeCEscapeSequences().
84
+ // ----------------------------------------------------------------------
85
+ bool CUnescapeInternal(absl::string_view source, bool leave_nulls_escaped,
86
+ char* dest, ptrdiff_t* dest_len, std::string* error) {
87
+ char* d = dest;
88
+ const char* p = source.data();
89
+ const char* end = p + source.size();
90
+ const char* last_byte = end - 1;
91
+
92
+ // Small optimization for case where source = dest and there's no escaping
93
+ while (p == d && p < end && *p != '\\') p++, d++;
94
+
95
+ while (p < end) {
96
+ if (*p != '\\') {
97
+ *d++ = *p++;
98
+ } else {
99
+ if (++p > last_byte) { // skip past the '\\'
100
+ if (error) *error = "String cannot end with \\";
101
+ return false;
102
+ }
103
+ switch (*p) {
104
+ case 'a': *d++ = '\a'; break;
105
+ case 'b': *d++ = '\b'; break;
106
+ case 'f': *d++ = '\f'; break;
107
+ case 'n': *d++ = '\n'; break;
108
+ case 'r': *d++ = '\r'; break;
109
+ case 't': *d++ = '\t'; break;
110
+ case 'v': *d++ = '\v'; break;
111
+ case '\\': *d++ = '\\'; break;
112
+ case '?': *d++ = '\?'; break; // \? Who knew?
113
+ case '\'': *d++ = '\''; break;
114
+ case '"': *d++ = '\"'; break;
115
+ case '0':
116
+ case '1':
117
+ case '2':
118
+ case '3':
119
+ case '4':
120
+ case '5':
121
+ case '6':
122
+ case '7': {
123
+ // octal digit: 1 to 3 digits
124
+ const char* octal_start = p;
125
+ unsigned int ch = static_cast<unsigned int>(*p - '0'); // digit 1
126
+ if (p < last_byte && is_octal_digit(p[1]))
127
+ ch = ch * 8 + static_cast<unsigned int>(*++p - '0'); // digit 2
128
+ if (p < last_byte && is_octal_digit(p[1]))
129
+ ch = ch * 8 + static_cast<unsigned int>(*++p - '0'); // digit 3
130
+ if (ch > 0xff) {
131
+ if (error) {
132
+ *error = "Value of \\" +
133
+ std::string(octal_start,
134
+ static_cast<size_t>(p + 1 - octal_start)) +
135
+ " exceeds 0xff";
136
+ }
137
+ return false;
138
+ }
139
+ if ((ch == 0) && leave_nulls_escaped) {
140
+ // Copy the escape sequence for the null character
141
+ const size_t octal_size = static_cast<size_t>(p + 1 - octal_start);
142
+ *d++ = '\\';
143
+ memmove(d, octal_start, octal_size);
144
+ d += octal_size;
145
+ break;
146
+ }
147
+ *d++ = static_cast<char>(ch);
148
+ break;
149
+ }
150
+ case 'x':
151
+ case 'X': {
152
+ if (p >= last_byte) {
153
+ if (error) *error = "String cannot end with \\x";
154
+ return false;
155
+ } else if (!absl::ascii_isxdigit(static_cast<unsigned char>(p[1]))) {
156
+ if (error) *error = "\\x cannot be followed by a non-hex digit";
157
+ return false;
158
+ }
159
+ unsigned int ch = 0;
160
+ const char* hex_start = p;
161
+ while (p < last_byte &&
162
+ absl::ascii_isxdigit(static_cast<unsigned char>(p[1])))
163
+ // Arbitrarily many hex digits
164
+ ch = (ch << 4) + hex_digit_to_int(*++p);
165
+ if (ch > 0xFF) {
166
+ if (error) {
167
+ *error = "Value of \\" +
168
+ std::string(hex_start,
169
+ static_cast<size_t>(p + 1 - hex_start)) +
170
+ " exceeds 0xff";
171
+ }
172
+ return false;
173
+ }
174
+ if ((ch == 0) && leave_nulls_escaped) {
175
+ // Copy the escape sequence for the null character
176
+ const size_t hex_size = static_cast<size_t>(p + 1 - hex_start);
177
+ *d++ = '\\';
178
+ memmove(d, hex_start, hex_size);
179
+ d += hex_size;
180
+ break;
181
+ }
182
+ *d++ = static_cast<char>(ch);
183
+ break;
184
+ }
185
+ case 'u': {
186
+ // \uhhhh => convert 4 hex digits to UTF-8
187
+ char32_t rune = 0;
188
+ const char* hex_start = p;
189
+ if (p + 4 >= end) {
190
+ if (error) {
191
+ *error = "\\u must be followed by 4 hex digits: \\" +
192
+ std::string(hex_start,
193
+ static_cast<size_t>(p + 1 - hex_start));
194
+ }
195
+ return false;
196
+ }
197
+ for (int i = 0; i < 4; ++i) {
198
+ // Look one char ahead.
199
+ if (absl::ascii_isxdigit(static_cast<unsigned char>(p[1]))) {
200
+ rune = (rune << 4) + hex_digit_to_int(*++p); // Advance p.
201
+ } else {
202
+ if (error) {
203
+ *error = "\\u must be followed by 4 hex digits: \\" +
204
+ std::string(hex_start,
205
+ static_cast<size_t>(p + 1 - hex_start));
206
+ }
207
+ return false;
208
+ }
209
+ }
210
+ if ((rune == 0) && leave_nulls_escaped) {
211
+ // Copy the escape sequence for the null character
212
+ *d++ = '\\';
213
+ memmove(d, hex_start, 5); // u0000
214
+ d += 5;
215
+ break;
216
+ }
217
+ if (IsSurrogate(rune, absl::string_view(hex_start, 5), error)) {
218
+ return false;
219
+ }
220
+ d += strings_internal::EncodeUTF8Char(d, rune);
221
+ break;
222
+ }
223
+ case 'U': {
224
+ // \Uhhhhhhhh => convert 8 hex digits to UTF-8
225
+ char32_t rune = 0;
226
+ const char* hex_start = p;
227
+ if (p + 8 >= end) {
228
+ if (error) {
229
+ *error = "\\U must be followed by 8 hex digits: \\" +
230
+ std::string(hex_start,
231
+ static_cast<size_t>(p + 1 - hex_start));
232
+ }
233
+ return false;
234
+ }
235
+ for (int i = 0; i < 8; ++i) {
236
+ // Look one char ahead.
237
+ if (absl::ascii_isxdigit(static_cast<unsigned char>(p[1]))) {
238
+ // Don't change rune until we're sure this
239
+ // is within the Unicode limit, but do advance p.
240
+ uint32_t newrune = (rune << 4) + hex_digit_to_int(*++p);
241
+ if (newrune > 0x10FFFF) {
242
+ if (error) {
243
+ *error = "Value of \\" +
244
+ std::string(hex_start,
245
+ static_cast<size_t>(p + 1 - hex_start)) +
246
+ " exceeds Unicode limit (0x10FFFF)";
247
+ }
248
+ return false;
249
+ } else {
250
+ rune = newrune;
251
+ }
252
+ } else {
253
+ if (error) {
254
+ *error = "\\U must be followed by 8 hex digits: \\" +
255
+ std::string(hex_start,
256
+ static_cast<size_t>(p + 1 - hex_start));
257
+ }
258
+ return false;
259
+ }
260
+ }
261
+ if ((rune == 0) && leave_nulls_escaped) {
262
+ // Copy the escape sequence for the null character
263
+ *d++ = '\\';
264
+ memmove(d, hex_start, 9); // U00000000
265
+ d += 9;
266
+ break;
267
+ }
268
+ if (IsSurrogate(rune, absl::string_view(hex_start, 9), error)) {
269
+ return false;
270
+ }
271
+ d += strings_internal::EncodeUTF8Char(d, rune);
272
+ break;
273
+ }
274
+ default: {
275
+ if (error) *error = std::string("Unknown escape sequence: \\") + *p;
276
+ return false;
277
+ }
278
+ }
279
+ p++; // read past letter we escaped
280
+ }
281
+ }
282
+ *dest_len = d - dest;
283
+ return true;
284
+ }
285
+
286
+ // ----------------------------------------------------------------------
287
+ // CUnescapeInternal()
288
+ //
289
+ // Same as above but uses a std::string for output. 'source' and 'dest'
290
+ // may be the same.
291
+ // ----------------------------------------------------------------------
292
+ bool CUnescapeInternal(absl::string_view source, bool leave_nulls_escaped,
293
+ std::string* dest, std::string* error) {
294
+ strings_internal::STLStringResizeUninitialized(dest, source.size());
295
+
296
+ ptrdiff_t dest_size;
297
+ if (!CUnescapeInternal(source,
298
+ leave_nulls_escaped,
299
+ &(*dest)[0],
300
+ &dest_size,
301
+ error)) {
302
+ return false;
303
+ }
304
+ dest->erase(static_cast<size_t>(dest_size));
305
+ return true;
306
+ }
307
+
308
+ // ----------------------------------------------------------------------
309
+ // CEscape()
310
+ // CHexEscape()
311
+ // Utf8SafeCEscape()
312
+ // Utf8SafeCHexEscape()
313
+ // Escapes 'src' using C-style escape sequences. This is useful for
314
+ // preparing query flags. The 'Hex' version uses hexadecimal rather than
315
+ // octal sequences. The 'Utf8Safe' version does not touch UTF-8 bytes.
316
+ //
317
+ // Escaped chars: \n, \r, \t, ", ', \, and !absl::ascii_isprint().
318
+ // ----------------------------------------------------------------------
319
+ std::string CEscapeInternal(absl::string_view src, bool use_hex,
320
+ bool utf8_safe) {
321
+ std::string dest;
322
+ bool last_hex_escape = false; // true if last output char was \xNN.
323
+
324
+ for (char c : src) {
325
+ bool is_hex_escape = false;
326
+ switch (c) {
327
+ case '\n': dest.append("\\" "n"); break;
328
+ case '\r': dest.append("\\" "r"); break;
329
+ case '\t': dest.append("\\" "t"); break;
330
+ case '\"': dest.append("\\" "\""); break;
331
+ case '\'': dest.append("\\" "'"); break;
332
+ case '\\': dest.append("\\" "\\"); break;
333
+ default: {
334
+ // Note that if we emit \xNN and the src character after that is a hex
335
+ // digit then that digit must be escaped too to prevent it being
336
+ // interpreted as part of the character code by C.
337
+ const unsigned char uc = static_cast<unsigned char>(c);
338
+ if ((!utf8_safe || uc < 0x80) &&
339
+ (!absl::ascii_isprint(uc) ||
340
+ (last_hex_escape && absl::ascii_isxdigit(uc)))) {
341
+ if (use_hex) {
342
+ dest.append("\\" "x");
343
+ dest.push_back(numbers_internal::kHexChar[uc / 16]);
344
+ dest.push_back(numbers_internal::kHexChar[uc % 16]);
345
+ is_hex_escape = true;
346
+ } else {
347
+ dest.append("\\");
348
+ dest.push_back(numbers_internal::kHexChar[uc / 64]);
349
+ dest.push_back(numbers_internal::kHexChar[(uc % 64) / 8]);
350
+ dest.push_back(numbers_internal::kHexChar[uc % 8]);
351
+ }
352
+ } else {
353
+ dest.push_back(c);
354
+ break;
355
+ }
356
+ }
357
+ }
358
+ last_hex_escape = is_hex_escape;
359
+ }
360
+
361
+ return dest;
362
+ }
363
+
364
+ /* clang-format off */
365
+ constexpr unsigned char kCEscapedLen[256] = {
366
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 4, 4, 2, 4, 4, // \t, \n, \r
367
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
368
+ 1, 1, 2, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, // ", '
369
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // '0'..'9'
370
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 'A'..'O'
371
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, // 'P'..'Z', '\'
372
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 'a'..'o'
373
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 4, // 'p'..'z', DEL
374
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
375
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
376
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
377
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
378
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
379
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
380
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
381
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
382
+ };
383
+ /* clang-format on */
384
+
385
+ // Calculates the length of the C-style escaped version of 'src'.
386
+ // Assumes that non-printable characters are escaped using octal sequences, and
387
+ // that UTF-8 bytes are not handled specially.
388
+ inline size_t CEscapedLength(absl::string_view src) {
389
+ size_t escaped_len = 0;
390
+ // The maximum value of kCEscapedLen[x] is 4, so we can escape any string of
391
+ // length size_t_max/4 without checking for overflow.
392
+ size_t unchecked_limit =
393
+ std::min<size_t>(src.size(), std::numeric_limits<size_t>::max() / 4);
394
+ size_t i = 0;
395
+ while (i < unchecked_limit) {
396
+ // Common case: No need to check for overflow.
397
+ escaped_len += kCEscapedLen[static_cast<unsigned char>(src[i++])];
398
+ }
399
+ while (i < src.size()) {
400
+ // Beyond unchecked_limit we need to check for overflow before adding.
401
+ size_t char_len = kCEscapedLen[static_cast<unsigned char>(src[i++])];
402
+ ABSL_INTERNAL_CHECK(
403
+ escaped_len <= std::numeric_limits<size_t>::max() - char_len,
404
+ "escaped_len overflow");
405
+ escaped_len += char_len;
406
+ }
407
+ return escaped_len;
408
+ }
409
+
410
+ void CEscapeAndAppendInternal(absl::string_view src, std::string* dest) {
411
+ size_t escaped_len = CEscapedLength(src);
412
+ if (escaped_len == src.size()) {
413
+ dest->append(src.data(), src.size());
414
+ return;
415
+ }
416
+
417
+ size_t cur_dest_len = dest->size();
418
+ ABSL_INTERNAL_CHECK(
419
+ cur_dest_len <= std::numeric_limits<size_t>::max() - escaped_len,
420
+ "std::string size overflow");
421
+ strings_internal::STLStringResizeUninitialized(dest,
422
+ cur_dest_len + escaped_len);
423
+ char* append_ptr = &(*dest)[cur_dest_len];
424
+
425
+ for (char c : src) {
426
+ size_t char_len = kCEscapedLen[static_cast<unsigned char>(c)];
427
+ if (char_len == 1) {
428
+ *append_ptr++ = c;
429
+ } else if (char_len == 2) {
430
+ switch (c) {
431
+ case '\n':
432
+ *append_ptr++ = '\\';
433
+ *append_ptr++ = 'n';
434
+ break;
435
+ case '\r':
436
+ *append_ptr++ = '\\';
437
+ *append_ptr++ = 'r';
438
+ break;
439
+ case '\t':
440
+ *append_ptr++ = '\\';
441
+ *append_ptr++ = 't';
442
+ break;
443
+ case '\"':
444
+ *append_ptr++ = '\\';
445
+ *append_ptr++ = '\"';
446
+ break;
447
+ case '\'':
448
+ *append_ptr++ = '\\';
449
+ *append_ptr++ = '\'';
450
+ break;
451
+ case '\\':
452
+ *append_ptr++ = '\\';
453
+ *append_ptr++ = '\\';
454
+ break;
455
+ }
456
+ } else {
457
+ *append_ptr++ = '\\';
458
+ *append_ptr++ = '0' + static_cast<unsigned char>(c) / 64;
459
+ *append_ptr++ = '0' + (static_cast<unsigned char>(c) % 64) / 8;
460
+ *append_ptr++ = '0' + static_cast<unsigned char>(c) % 8;
461
+ }
462
+ }
463
+ }
464
+
465
+ // Reverses the mapping in Base64EscapeInternal; see that method's
466
+ // documentation for details of the mapping.
467
+ bool Base64UnescapeInternal(const char* src_param, size_t szsrc, char* dest,
468
+ size_t szdest, const signed char* unbase64,
469
+ size_t* len) {
470
+ static const char kPad64Equals = '=';
471
+ static const char kPad64Dot = '.';
472
+
473
+ size_t destidx = 0;
474
+ int decode = 0;
475
+ int state = 0;
476
+ unsigned char ch = 0;
477
+ unsigned int temp = 0;
478
+
479
+ // If "char" is signed by default, using *src as an array index results in
480
+ // accessing negative array elements. Treat the input as a pointer to
481
+ // unsigned char to avoid this.
482
+ const unsigned char* src = reinterpret_cast<const unsigned char*>(src_param);
483
+
484
+ // The GET_INPUT macro gets the next input character, skipping
485
+ // over any whitespace, and stopping when we reach the end of the
486
+ // string or when we read any non-data character. The arguments are
487
+ // an arbitrary identifier (used as a label for goto) and the number
488
+ // of data bytes that must remain in the input to avoid aborting the
489
+ // loop.
490
+ #define GET_INPUT(label, remain) \
491
+ label: \
492
+ --szsrc; \
493
+ ch = *src++; \
494
+ decode = unbase64[ch]; \
495
+ if (decode < 0) { \
496
+ if (absl::ascii_isspace(ch) && szsrc >= remain) goto label; \
497
+ state = 4 - remain; \
498
+ break; \
499
+ }
500
+
501
+ // if dest is null, we're just checking to see if it's legal input
502
+ // rather than producing output. (I suspect this could just be done
503
+ // with a regexp...). We duplicate the loop so this test can be
504
+ // outside it instead of in every iteration.
505
+
506
+ if (dest) {
507
+ // This loop consumes 4 input bytes and produces 3 output bytes
508
+ // per iteration. We can't know at the start that there is enough
509
+ // data left in the string for a full iteration, so the loop may
510
+ // break out in the middle; if so 'state' will be set to the
511
+ // number of input bytes read.
512
+
513
+ while (szsrc >= 4) {
514
+ // We'll start by optimistically assuming that the next four
515
+ // bytes of the string (src[0..3]) are four good data bytes
516
+ // (that is, no nulls, whitespace, padding chars, or illegal
517
+ // chars). We need to test src[0..2] for nulls individually
518
+ // before constructing temp to preserve the property that we
519
+ // never read past a null in the string (no matter how long
520
+ // szsrc claims the string is).
521
+
522
+ if (!src[0] || !src[1] || !src[2] ||
523
+ ((temp = ((unsigned(unbase64[src[0]]) << 18) |
524
+ (unsigned(unbase64[src[1]]) << 12) |
525
+ (unsigned(unbase64[src[2]]) << 6) |
526
+ (unsigned(unbase64[src[3]])))) &
527
+ 0x80000000)) {
528
+ // Iff any of those four characters was bad (null, illegal,
529
+ // whitespace, padding), then temp's high bit will be set
530
+ // (because unbase64[] is -1 for all bad characters).
531
+ //
532
+ // We'll back up and resort to the slower decoder, which knows
533
+ // how to handle those cases.
534
+
535
+ GET_INPUT(first, 4);
536
+ temp = static_cast<unsigned char>(decode);
537
+ GET_INPUT(second, 3);
538
+ temp = (temp << 6) | static_cast<unsigned char>(decode);
539
+ GET_INPUT(third, 2);
540
+ temp = (temp << 6) | static_cast<unsigned char>(decode);
541
+ GET_INPUT(fourth, 1);
542
+ temp = (temp << 6) | static_cast<unsigned char>(decode);
543
+ } else {
544
+ // We really did have four good data bytes, so advance four
545
+ // characters in the string.
546
+
547
+ szsrc -= 4;
548
+ src += 4;
549
+ }
550
+
551
+ // temp has 24 bits of input, so write that out as three bytes.
552
+
553
+ if (destidx + 3 > szdest) return false;
554
+ dest[destidx + 2] = static_cast<char>(temp);
555
+ temp >>= 8;
556
+ dest[destidx + 1] = static_cast<char>(temp);
557
+ temp >>= 8;
558
+ dest[destidx] = static_cast<char>(temp);
559
+ destidx += 3;
560
+ }
561
+ } else {
562
+ while (szsrc >= 4) {
563
+ if (!src[0] || !src[1] || !src[2] ||
564
+ ((temp = ((unsigned(unbase64[src[0]]) << 18) |
565
+ (unsigned(unbase64[src[1]]) << 12) |
566
+ (unsigned(unbase64[src[2]]) << 6) |
567
+ (unsigned(unbase64[src[3]])))) &
568
+ 0x80000000)) {
569
+ GET_INPUT(first_no_dest, 4);
570
+ GET_INPUT(second_no_dest, 3);
571
+ GET_INPUT(third_no_dest, 2);
572
+ GET_INPUT(fourth_no_dest, 1);
573
+ } else {
574
+ szsrc -= 4;
575
+ src += 4;
576
+ }
577
+ destidx += 3;
578
+ }
579
+ }
580
+
581
+ #undef GET_INPUT
582
+
583
+ // if the loop terminated because we read a bad character, return
584
+ // now.
585
+ if (decode < 0 && ch != kPad64Equals && ch != kPad64Dot &&
586
+ !absl::ascii_isspace(ch))
587
+ return false;
588
+
589
+ if (ch == kPad64Equals || ch == kPad64Dot) {
590
+ // if we stopped by hitting an '=' or '.', un-read that character -- we'll
591
+ // look at it again when we count to check for the proper number of
592
+ // equals signs at the end.
593
+ ++szsrc;
594
+ --src;
595
+ } else {
596
+ // This loop consumes 1 input byte per iteration. It's used to
597
+ // clean up the 0-3 input bytes remaining when the first, faster
598
+ // loop finishes. 'temp' contains the data from 'state' input
599
+ // characters read by the first loop.
600
+ while (szsrc > 0) {
601
+ --szsrc;
602
+ ch = *src++;
603
+ decode = unbase64[ch];
604
+ if (decode < 0) {
605
+ if (absl::ascii_isspace(ch)) {
606
+ continue;
607
+ } else if (ch == kPad64Equals || ch == kPad64Dot) {
608
+ // back up one character; we'll read it again when we check
609
+ // for the correct number of pad characters at the end.
610
+ ++szsrc;
611
+ --src;
612
+ break;
613
+ } else {
614
+ return false;
615
+ }
616
+ }
617
+
618
+ // Each input character gives us six bits of output.
619
+ temp = (temp << 6) | static_cast<unsigned char>(decode);
620
+ ++state;
621
+ if (state == 4) {
622
+ // If we've accumulated 24 bits of output, write that out as
623
+ // three bytes.
624
+ if (dest) {
625
+ if (destidx + 3 > szdest) return false;
626
+ dest[destidx + 2] = static_cast<char>(temp);
627
+ temp >>= 8;
628
+ dest[destidx + 1] = static_cast<char>(temp);
629
+ temp >>= 8;
630
+ dest[destidx] = static_cast<char>(temp);
631
+ }
632
+ destidx += 3;
633
+ state = 0;
634
+ temp = 0;
635
+ }
636
+ }
637
+ }
638
+
639
+ // Process the leftover data contained in 'temp' at the end of the input.
640
+ int expected_equals = 0;
641
+ switch (state) {
642
+ case 0:
643
+ // Nothing left over; output is a multiple of 3 bytes.
644
+ break;
645
+
646
+ case 1:
647
+ // Bad input; we have 6 bits left over.
648
+ return false;
649
+
650
+ case 2:
651
+ // Produce one more output byte from the 12 input bits we have left.
652
+ if (dest) {
653
+ if (destidx + 1 > szdest) return false;
654
+ temp >>= 4;
655
+ dest[destidx] = static_cast<char>(temp);
656
+ }
657
+ ++destidx;
658
+ expected_equals = 2;
659
+ break;
660
+
661
+ case 3:
662
+ // Produce two more output bytes from the 18 input bits we have left.
663
+ if (dest) {
664
+ if (destidx + 2 > szdest) return false;
665
+ temp >>= 2;
666
+ dest[destidx + 1] = static_cast<char>(temp);
667
+ temp >>= 8;
668
+ dest[destidx] = static_cast<char>(temp);
669
+ }
670
+ destidx += 2;
671
+ expected_equals = 1;
672
+ break;
673
+
674
+ default:
675
+ // state should have no other values at this point.
676
+ ABSL_RAW_LOG(FATAL, "This can't happen; base64 decoder state = %d",
677
+ state);
678
+ }
679
+
680
+ // The remainder of the string should be all whitespace, mixed with
681
+ // exactly 0 equals signs, or exactly 'expected_equals' equals
682
+ // signs. (Always accepting 0 equals signs is an Abseil extension
683
+ // not covered in the RFC, as is accepting dot as the pad character.)
684
+
685
+ int equals = 0;
686
+ while (szsrc > 0) {
687
+ if (*src == kPad64Equals || *src == kPad64Dot)
688
+ ++equals;
689
+ else if (!absl::ascii_isspace(*src))
690
+ return false;
691
+ --szsrc;
692
+ ++src;
693
+ }
694
+
695
+ const bool ok = (equals == 0 || equals == expected_equals);
696
+ if (ok) *len = destidx;
697
+ return ok;
698
+ }
699
+
700
+ // The arrays below map base64-escaped characters back to their original values.
701
+ // For the inverse case, see k(WebSafe)Base64Chars in the internal
702
+ // escaping.cc.
703
+ // These arrays were generated by the following inversion code:
704
+ // #include <sys/time.h>
705
+ // #include <stdlib.h>
706
+ // #include <string.h>
707
+ // main()
708
+ // {
709
+ // static const char Base64[] =
710
+ // "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
711
+ // char* pos;
712
+ // int idx, i, j;
713
+ // printf(" ");
714
+ // for (i = 0; i < 255; i += 8) {
715
+ // for (j = i; j < i + 8; j++) {
716
+ // pos = strchr(Base64, j);
717
+ // if ((pos == nullptr) || (j == 0))
718
+ // idx = -1;
719
+ // else
720
+ // idx = pos - Base64;
721
+ // if (idx == -1)
722
+ // printf(" %2d, ", idx);
723
+ // else
724
+ // printf(" %2d/*%c*/,", idx, j);
725
+ // }
726
+ // printf("\n ");
727
+ // }
728
+ // }
729
+ //
730
+ // where the value of "Base64[]" was replaced by one of k(WebSafe)Base64Chars
731
+ // in the internal escaping.cc.
732
+ /* clang-format off */
733
+ constexpr signed char kUnBase64[] = {
734
+ -1, -1, -1, -1, -1, -1, -1, -1,
735
+ -1, -1, -1, -1, -1, -1, -1, -1,
736
+ -1, -1, -1, -1, -1, -1, -1, -1,
737
+ -1, -1, -1, -1, -1, -1, -1, -1,
738
+ -1, -1, -1, -1, -1, -1, -1, -1,
739
+ -1, -1, -1, 62/*+*/, -1, -1, -1, 63/*/ */,
740
+ 52/*0*/, 53/*1*/, 54/*2*/, 55/*3*/, 56/*4*/, 57/*5*/, 58/*6*/, 59/*7*/,
741
+ 60/*8*/, 61/*9*/, -1, -1, -1, -1, -1, -1,
742
+ -1, 0/*A*/, 1/*B*/, 2/*C*/, 3/*D*/, 4/*E*/, 5/*F*/, 6/*G*/,
743
+ 07/*H*/, 8/*I*/, 9/*J*/, 10/*K*/, 11/*L*/, 12/*M*/, 13/*N*/, 14/*O*/,
744
+ 15/*P*/, 16/*Q*/, 17/*R*/, 18/*S*/, 19/*T*/, 20/*U*/, 21/*V*/, 22/*W*/,
745
+ 23/*X*/, 24/*Y*/, 25/*Z*/, -1, -1, -1, -1, -1,
746
+ -1, 26/*a*/, 27/*b*/, 28/*c*/, 29/*d*/, 30/*e*/, 31/*f*/, 32/*g*/,
747
+ 33/*h*/, 34/*i*/, 35/*j*/, 36/*k*/, 37/*l*/, 38/*m*/, 39/*n*/, 40/*o*/,
748
+ 41/*p*/, 42/*q*/, 43/*r*/, 44/*s*/, 45/*t*/, 46/*u*/, 47/*v*/, 48/*w*/,
749
+ 49/*x*/, 50/*y*/, 51/*z*/, -1, -1, -1, -1, -1,
750
+ -1, -1, -1, -1, -1, -1, -1, -1,
751
+ -1, -1, -1, -1, -1, -1, -1, -1,
752
+ -1, -1, -1, -1, -1, -1, -1, -1,
753
+ -1, -1, -1, -1, -1, -1, -1, -1,
754
+ -1, -1, -1, -1, -1, -1, -1, -1,
755
+ -1, -1, -1, -1, -1, -1, -1, -1,
756
+ -1, -1, -1, -1, -1, -1, -1, -1,
757
+ -1, -1, -1, -1, -1, -1, -1, -1,
758
+ -1, -1, -1, -1, -1, -1, -1, -1,
759
+ -1, -1, -1, -1, -1, -1, -1, -1,
760
+ -1, -1, -1, -1, -1, -1, -1, -1,
761
+ -1, -1, -1, -1, -1, -1, -1, -1,
762
+ -1, -1, -1, -1, -1, -1, -1, -1,
763
+ -1, -1, -1, -1, -1, -1, -1, -1,
764
+ -1, -1, -1, -1, -1, -1, -1, -1,
765
+ -1, -1, -1, -1, -1, -1, -1, -1
766
+ };
767
+
768
+ constexpr signed char kUnWebSafeBase64[] = {
769
+ -1, -1, -1, -1, -1, -1, -1, -1,
770
+ -1, -1, -1, -1, -1, -1, -1, -1,
771
+ -1, -1, -1, -1, -1, -1, -1, -1,
772
+ -1, -1, -1, -1, -1, -1, -1, -1,
773
+ -1, -1, -1, -1, -1, -1, -1, -1,
774
+ -1, -1, -1, -1, -1, 62/*-*/, -1, -1,
775
+ 52/*0*/, 53/*1*/, 54/*2*/, 55/*3*/, 56/*4*/, 57/*5*/, 58/*6*/, 59/*7*/,
776
+ 60/*8*/, 61/*9*/, -1, -1, -1, -1, -1, -1,
777
+ -1, 0/*A*/, 1/*B*/, 2/*C*/, 3/*D*/, 4/*E*/, 5/*F*/, 6/*G*/,
778
+ 07/*H*/, 8/*I*/, 9/*J*/, 10/*K*/, 11/*L*/, 12/*M*/, 13/*N*/, 14/*O*/,
779
+ 15/*P*/, 16/*Q*/, 17/*R*/, 18/*S*/, 19/*T*/, 20/*U*/, 21/*V*/, 22/*W*/,
780
+ 23/*X*/, 24/*Y*/, 25/*Z*/, -1, -1, -1, -1, 63/*_*/,
781
+ -1, 26/*a*/, 27/*b*/, 28/*c*/, 29/*d*/, 30/*e*/, 31/*f*/, 32/*g*/,
782
+ 33/*h*/, 34/*i*/, 35/*j*/, 36/*k*/, 37/*l*/, 38/*m*/, 39/*n*/, 40/*o*/,
783
+ 41/*p*/, 42/*q*/, 43/*r*/, 44/*s*/, 45/*t*/, 46/*u*/, 47/*v*/, 48/*w*/,
784
+ 49/*x*/, 50/*y*/, 51/*z*/, -1, -1, -1, -1, -1,
785
+ -1, -1, -1, -1, -1, -1, -1, -1,
786
+ -1, -1, -1, -1, -1, -1, -1, -1,
787
+ -1, -1, -1, -1, -1, -1, -1, -1,
788
+ -1, -1, -1, -1, -1, -1, -1, -1,
789
+ -1, -1, -1, -1, -1, -1, -1, -1,
790
+ -1, -1, -1, -1, -1, -1, -1, -1,
791
+ -1, -1, -1, -1, -1, -1, -1, -1,
792
+ -1, -1, -1, -1, -1, -1, -1, -1,
793
+ -1, -1, -1, -1, -1, -1, -1, -1,
794
+ -1, -1, -1, -1, -1, -1, -1, -1,
795
+ -1, -1, -1, -1, -1, -1, -1, -1,
796
+ -1, -1, -1, -1, -1, -1, -1, -1,
797
+ -1, -1, -1, -1, -1, -1, -1, -1,
798
+ -1, -1, -1, -1, -1, -1, -1, -1,
799
+ -1, -1, -1, -1, -1, -1, -1, -1,
800
+ -1, -1, -1, -1, -1, -1, -1, -1
801
+ };
802
+ /* clang-format on */
803
+
804
+ template <typename String>
805
+ bool Base64UnescapeInternal(const char* src, size_t slen, String* dest,
806
+ const signed char* unbase64) {
807
+ // Determine the size of the output string. Base64 encodes every 3 bytes into
808
+ // 4 characters. Any leftover chars are added directly for good measure.
809
+ const size_t dest_len = 3 * (slen / 4) + (slen % 4);
810
+
811
+ strings_internal::STLStringResizeUninitialized(dest, dest_len);
812
+
813
+ // We are getting the destination buffer by getting the beginning of the
814
+ // string and converting it into a char *.
815
+ size_t len;
816
+ const bool ok =
817
+ Base64UnescapeInternal(src, slen, &(*dest)[0], dest_len, unbase64, &len);
818
+ if (!ok) {
819
+ dest->clear();
820
+ return false;
821
+ }
822
+
823
+ // could be shorter if there was padding
824
+ assert(len <= dest_len);
825
+ dest->erase(len);
826
+
827
+ return true;
828
+ }
829
+
830
+ /* clang-format off */
831
+ constexpr char kHexValueLenient[256] = {
832
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
833
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
834
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
835
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 0, // '0'..'9'
836
+ 0, 10, 11, 12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 'A'..'F'
837
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
838
+ 0, 10, 11, 12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 'a'..'f'
839
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
840
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
841
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
842
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
843
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
844
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
845
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
846
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
847
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
848
+ };
849
+
850
+ /* clang-format on */
851
+
852
+ // This is a templated function so that T can be either a char*
853
+ // or a string. This works because we use the [] operator to access
854
+ // individual characters at a time.
855
+ template <typename T>
856
+ void HexStringToBytesInternal(const char* from, T to, size_t num) {
857
+ for (size_t i = 0; i < num; i++) {
858
+ to[i] = static_cast<char>(kHexValueLenient[from[i * 2] & 0xFF] << 4) +
859
+ (kHexValueLenient[from[i * 2 + 1] & 0xFF]);
860
+ }
861
+ }
862
+
863
+ // This is a templated function so that T can be either a char* or a
864
+ // std::string.
865
+ template <typename T>
866
+ void BytesToHexStringInternal(const unsigned char* src, T dest, size_t num) {
867
+ auto dest_ptr = &dest[0];
868
+ for (auto src_ptr = src; src_ptr != (src + num); ++src_ptr, dest_ptr += 2) {
869
+ const char* hex_p = &numbers_internal::kHexTable[*src_ptr * 2];
870
+ std::copy(hex_p, hex_p + 2, dest_ptr);
871
+ }
872
+ }
873
+
874
+ } // namespace
875
+
876
+ // ----------------------------------------------------------------------
877
+ // CUnescape()
878
+ //
879
+ // See CUnescapeInternal() for implementation details.
880
+ // ----------------------------------------------------------------------
881
+ bool CUnescape(absl::string_view source, std::string* dest,
882
+ std::string* error) {
883
+ return CUnescapeInternal(source, kUnescapeNulls, dest, error);
884
+ }
885
+
886
+ std::string CEscape(absl::string_view src) {
887
+ std::string dest;
888
+ CEscapeAndAppendInternal(src, &dest);
889
+ return dest;
890
+ }
891
+
892
+ std::string CHexEscape(absl::string_view src) {
893
+ return CEscapeInternal(src, true, false);
894
+ }
895
+
896
+ std::string Utf8SafeCEscape(absl::string_view src) {
897
+ return CEscapeInternal(src, false, true);
898
+ }
899
+
900
+ std::string Utf8SafeCHexEscape(absl::string_view src) {
901
+ return CEscapeInternal(src, true, true);
902
+ }
903
+
904
+ bool Base64Unescape(absl::string_view src, std::string* dest) {
905
+ return Base64UnescapeInternal(src.data(), src.size(), dest, kUnBase64);
906
+ }
907
+
908
+ bool WebSafeBase64Unescape(absl::string_view src, std::string* dest) {
909
+ return Base64UnescapeInternal(src.data(), src.size(), dest, kUnWebSafeBase64);
910
+ }
911
+
912
+ void Base64Escape(absl::string_view src, std::string* dest) {
913
+ strings_internal::Base64EscapeInternal(
914
+ reinterpret_cast<const unsigned char*>(src.data()), src.size(), dest,
915
+ true, strings_internal::kBase64Chars);
916
+ }
917
+
918
+ void WebSafeBase64Escape(absl::string_view src, std::string* dest) {
919
+ strings_internal::Base64EscapeInternal(
920
+ reinterpret_cast<const unsigned char*>(src.data()), src.size(), dest,
921
+ false, strings_internal::kWebSafeBase64Chars);
922
+ }
923
+
924
+ std::string Base64Escape(absl::string_view src) {
925
+ std::string dest;
926
+ strings_internal::Base64EscapeInternal(
927
+ reinterpret_cast<const unsigned char*>(src.data()), src.size(), &dest,
928
+ true, strings_internal::kBase64Chars);
929
+ return dest;
930
+ }
931
+
932
+ std::string WebSafeBase64Escape(absl::string_view src) {
933
+ std::string dest;
934
+ strings_internal::Base64EscapeInternal(
935
+ reinterpret_cast<const unsigned char*>(src.data()), src.size(), &dest,
936
+ false, strings_internal::kWebSafeBase64Chars);
937
+ return dest;
938
+ }
939
+
940
+ std::string HexStringToBytes(absl::string_view from) {
941
+ std::string result;
942
+ const auto num = from.size() / 2;
943
+ strings_internal::STLStringResizeUninitialized(&result, num);
944
+ absl::HexStringToBytesInternal<std::string&>(from.data(), result, num);
945
+ return result;
946
+ }
947
+
948
+ std::string BytesToHexString(absl::string_view from) {
949
+ std::string result;
950
+ strings_internal::STLStringResizeUninitialized(&result, 2 * from.size());
951
+ absl::BytesToHexStringInternal<std::string&>(
952
+ reinterpret_cast<const unsigned char*>(from.data()), result, from.size());
953
+ return result;
954
+ }
955
+
956
+ ABSL_NAMESPACE_END
957
+ } // namespace absl
weight/_dep/abseil-cpp/absl/strings/escaping_test.cc ADDED
@@ -0,0 +1,714 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Copyright 2017 The Abseil Authors.
2
+ //
3
+ // Licensed under the Apache License, Version 2.0 (the "License");
4
+ // you may not use this file except in compliance with the License.
5
+ // You may obtain a copy of the License at
6
+ //
7
+ // https://www.apache.org/licenses/LICENSE-2.0
8
+ //
9
+ // Unless required by applicable law or agreed to in writing, software
10
+ // distributed under the License is distributed on an "AS IS" BASIS,
11
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ // See the License for the specific language governing permissions and
13
+ // limitations under the License.
14
+
15
+ #include "absl/strings/escaping.h"
16
+
17
+ #include <array>
18
+ #include <cstddef>
19
+ #include <cstdio>
20
+ #include <cstring>
21
+ #include <initializer_list>
22
+ #include <memory>
23
+ #include <string>
24
+ #include <vector>
25
+
26
+ #include "gtest/gtest.h"
27
+ #include "absl/log/check.h"
28
+ #include "absl/strings/str_cat.h"
29
+
30
+ #include "absl/strings/internal/escaping_test_common.h"
31
+ #include "absl/strings/string_view.h"
32
+
33
+ namespace {
34
+
35
+ struct epair {
36
+ std::string escaped;
37
+ std::string unescaped;
38
+ };
39
+
40
+ TEST(CEscape, EscapeAndUnescape) {
41
+ const std::string inputs[] = {
42
+ std::string("foo\nxx\r\b\0023"),
43
+ std::string(""),
44
+ std::string("abc"),
45
+ std::string("\1chad_rules"),
46
+ std::string("\1arnar_drools"),
47
+ std::string("xxxx\r\t'\"\\"),
48
+ std::string("\0xx\0", 4),
49
+ std::string("\x01\x31"),
50
+ std::string("abc\xb\x42\141bc"),
51
+ std::string("123\1\x31\x32\x33"),
52
+ std::string("\xc1\xca\x1b\x62\x19o\xcc\x04"),
53
+ std::string(
54
+ "\\\"\xe8\xb0\xb7\xe6\xad\x8c\\\" is Google\\\'s Chinese name"),
55
+ };
56
+ // Do this twice, once for octal escapes and once for hex escapes.
57
+ for (int kind = 0; kind < 4; kind++) {
58
+ for (const std::string& original : inputs) {
59
+ std::string escaped;
60
+ switch (kind) {
61
+ case 0:
62
+ escaped = absl::CEscape(original);
63
+ break;
64
+ case 1:
65
+ escaped = absl::CHexEscape(original);
66
+ break;
67
+ case 2:
68
+ escaped = absl::Utf8SafeCEscape(original);
69
+ break;
70
+ case 3:
71
+ escaped = absl::Utf8SafeCHexEscape(original);
72
+ break;
73
+ }
74
+ std::string unescaped_str;
75
+ EXPECT_TRUE(absl::CUnescape(escaped, &unescaped_str));
76
+ EXPECT_EQ(unescaped_str, original);
77
+
78
+ unescaped_str.erase();
79
+ std::string error;
80
+ EXPECT_TRUE(absl::CUnescape(escaped, &unescaped_str, &error));
81
+ EXPECT_EQ(error, "");
82
+
83
+ // Check in-place unescaping
84
+ std::string s = escaped;
85
+ EXPECT_TRUE(absl::CUnescape(s, &s));
86
+ ASSERT_EQ(s, original);
87
+ }
88
+ }
89
+ // Check that all possible two character strings can be escaped then
90
+ // unescaped successfully.
91
+ for (int char0 = 0; char0 < 256; char0++) {
92
+ for (int char1 = 0; char1 < 256; char1++) {
93
+ char chars[2];
94
+ chars[0] = char0;
95
+ chars[1] = char1;
96
+ std::string s(chars, 2);
97
+ std::string escaped = absl::CHexEscape(s);
98
+ std::string unescaped;
99
+ EXPECT_TRUE(absl::CUnescape(escaped, &unescaped));
100
+ EXPECT_EQ(s, unescaped);
101
+ }
102
+ }
103
+ }
104
+
105
+ TEST(CEscape, BasicEscaping) {
106
+ epair oct_values[] = {
107
+ {"foo\\rbar\\nbaz\\t", "foo\rbar\nbaz\t"},
108
+ {"\\'full of \\\"sound\\\" and \\\"fury\\\"\\'",
109
+ "'full of \"sound\" and \"fury\"'"},
110
+ {"signi\\\\fying\\\\ nothing\\\\", "signi\\fying\\ nothing\\"},
111
+ {"\\010\\t\\n\\013\\014\\r", "\010\011\012\013\014\015"}
112
+ };
113
+ epair hex_values[] = {
114
+ {"ubik\\rubik\\nubik\\t", "ubik\rubik\nubik\t"},
115
+ {"I\\\'ve just seen a \\\"face\\\"",
116
+ "I've just seen a \"face\""},
117
+ {"hel\\\\ter\\\\skel\\\\ter\\\\", "hel\\ter\\skel\\ter\\"},
118
+ {"\\x08\\t\\n\\x0b\\x0c\\r", "\010\011\012\013\014\015"}
119
+ };
120
+ epair utf8_oct_values[] = {
121
+ {"\xe8\xb0\xb7\xe6\xad\x8c\\r\xe8\xb0\xb7\xe6\xad\x8c\\nbaz\\t",
122
+ "\xe8\xb0\xb7\xe6\xad\x8c\r\xe8\xb0\xb7\xe6\xad\x8c\nbaz\t"},
123
+ {"\\\"\xe8\xb0\xb7\xe6\xad\x8c\\\" is Google\\\'s Chinese name",
124
+ "\"\xe8\xb0\xb7\xe6\xad\x8c\" is Google\'s Chinese name"},
125
+ {"\xe3\x83\xa1\xe3\x83\xbc\xe3\x83\xab\\\\are\\\\Japanese\\\\chars\\\\",
126
+ "\xe3\x83\xa1\xe3\x83\xbc\xe3\x83\xab\\are\\Japanese\\chars\\"},
127
+ {"\xed\x81\xac\xeb\xa1\xac\\010\\t\\n\\013\\014\\r",
128
+ "\xed\x81\xac\xeb\xa1\xac\010\011\012\013\014\015"}
129
+ };
130
+ epair utf8_hex_values[] = {
131
+ {"\x20\xe4\xbd\xa0\\t\xe5\xa5\xbd,\\r!\\n",
132
+ "\x20\xe4\xbd\xa0\t\xe5\xa5\xbd,\r!\n"},
133
+ {"\xe8\xa9\xa6\xe9\xa8\x93\\\' means \\\"test\\\"",
134
+ "\xe8\xa9\xa6\xe9\xa8\x93\' means \"test\""},
135
+ {"\\\\\xe6\x88\x91\\\\:\\\\\xe6\x9d\xa8\xe6\xac\xa2\\\\",
136
+ "\\\xe6\x88\x91\\:\\\xe6\x9d\xa8\xe6\xac\xa2\\"},
137
+ {"\xed\x81\xac\xeb\xa1\xac\\x08\\t\\n\\x0b\\x0c\\r",
138
+ "\xed\x81\xac\xeb\xa1\xac\010\011\012\013\014\015"}
139
+ };
140
+
141
+ for (const epair& val : oct_values) {
142
+ std::string escaped = absl::CEscape(val.unescaped);
143
+ EXPECT_EQ(escaped, val.escaped);
144
+ }
145
+ for (const epair& val : hex_values) {
146
+ std::string escaped = absl::CHexEscape(val.unescaped);
147
+ EXPECT_EQ(escaped, val.escaped);
148
+ }
149
+ for (const epair& val : utf8_oct_values) {
150
+ std::string escaped = absl::Utf8SafeCEscape(val.unescaped);
151
+ EXPECT_EQ(escaped, val.escaped);
152
+ }
153
+ for (const epair& val : utf8_hex_values) {
154
+ std::string escaped = absl::Utf8SafeCHexEscape(val.unescaped);
155
+ EXPECT_EQ(escaped, val.escaped);
156
+ }
157
+ }
158
+
159
+ TEST(Unescape, BasicFunction) {
160
+ epair tests[] =
161
+ {{"", ""},
162
+ {"\\u0030", "0"},
163
+ {"\\u00A3", "\xC2\xA3"},
164
+ {"\\u22FD", "\xE2\x8B\xBD"},
165
+ {"\\U00010000", "\xF0\x90\x80\x80"},
166
+ {"\\U0010FFFD", "\xF4\x8F\xBF\xBD"}};
167
+ for (const epair& val : tests) {
168
+ std::string out;
169
+ EXPECT_TRUE(absl::CUnescape(val.escaped, &out));
170
+ EXPECT_EQ(out, val.unescaped);
171
+ }
172
+ std::string bad[] = {"\\u1", // too short
173
+ "\\U1", // too short
174
+ "\\Uffffff", // exceeds 0x10ffff (largest Unicode)
175
+ "\\U00110000", // exceeds 0x10ffff (largest Unicode)
176
+ "\\uD835", // surrogate character (D800-DFFF)
177
+ "\\U0000DD04", // surrogate character (D800-DFFF)
178
+ "\\777", // exceeds 0xff
179
+ "\\xABCD"}; // exceeds 0xff
180
+ for (const std::string& e : bad) {
181
+ std::string error;
182
+ std::string out;
183
+ EXPECT_FALSE(absl::CUnescape(e, &out, &error));
184
+ EXPECT_FALSE(error.empty());
185
+
186
+ out.erase();
187
+ EXPECT_FALSE(absl::CUnescape(e, &out));
188
+ }
189
+ }
190
+
191
+ class CUnescapeTest : public testing::Test {
192
+ protected:
193
+ static const char kStringWithMultipleOctalNulls[];
194
+ static const char kStringWithMultipleHexNulls[];
195
+ static const char kStringWithMultipleUnicodeNulls[];
196
+
197
+ std::string result_string_;
198
+ };
199
+
200
+ const char CUnescapeTest::kStringWithMultipleOctalNulls[] =
201
+ "\\0\\n" // null escape \0 plus newline
202
+ "0\\n" // just a number 0 (not a null escape) plus newline
203
+ "\\00\\12" // null escape \00 plus octal newline code
204
+ "\\000"; // null escape \000
205
+
206
+ // This has the same ingredients as kStringWithMultipleOctalNulls
207
+ // but with \x hex escapes instead of octal escapes.
208
+ const char CUnescapeTest::kStringWithMultipleHexNulls[] =
209
+ "\\x0\\n"
210
+ "0\\n"
211
+ "\\x00\\xa"
212
+ "\\x000";
213
+
214
+ const char CUnescapeTest::kStringWithMultipleUnicodeNulls[] =
215
+ "\\u0000\\n" // short-form (4-digit) null escape plus newline
216
+ "0\\n" // just a number 0 (not a null escape) plus newline
217
+ "\\U00000000"; // long-form (8-digit) null escape
218
+
219
+ TEST_F(CUnescapeTest, Unescapes1CharOctalNull) {
220
+ std::string original_string = "\\0";
221
+ EXPECT_TRUE(absl::CUnescape(original_string, &result_string_));
222
+ EXPECT_EQ(std::string("\0", 1), result_string_);
223
+ }
224
+
225
+ TEST_F(CUnescapeTest, Unescapes2CharOctalNull) {
226
+ std::string original_string = "\\00";
227
+ EXPECT_TRUE(absl::CUnescape(original_string, &result_string_));
228
+ EXPECT_EQ(std::string("\0", 1), result_string_);
229
+ }
230
+
231
+ TEST_F(CUnescapeTest, Unescapes3CharOctalNull) {
232
+ std::string original_string = "\\000";
233
+ EXPECT_TRUE(absl::CUnescape(original_string, &result_string_));
234
+ EXPECT_EQ(std::string("\0", 1), result_string_);
235
+ }
236
+
237
+ TEST_F(CUnescapeTest, Unescapes1CharHexNull) {
238
+ std::string original_string = "\\x0";
239
+ EXPECT_TRUE(absl::CUnescape(original_string, &result_string_));
240
+ EXPECT_EQ(std::string("\0", 1), result_string_);
241
+ }
242
+
243
+ TEST_F(CUnescapeTest, Unescapes2CharHexNull) {
244
+ std::string original_string = "\\x00";
245
+ EXPECT_TRUE(absl::CUnescape(original_string, &result_string_));
246
+ EXPECT_EQ(std::string("\0", 1), result_string_);
247
+ }
248
+
249
+ TEST_F(CUnescapeTest, Unescapes3CharHexNull) {
250
+ std::string original_string = "\\x000";
251
+ EXPECT_TRUE(absl::CUnescape(original_string, &result_string_));
252
+ EXPECT_EQ(std::string("\0", 1), result_string_);
253
+ }
254
+
255
+ TEST_F(CUnescapeTest, Unescapes4CharUnicodeNull) {
256
+ std::string original_string = "\\u0000";
257
+ EXPECT_TRUE(absl::CUnescape(original_string, &result_string_));
258
+ EXPECT_EQ(std::string("\0", 1), result_string_);
259
+ }
260
+
261
+ TEST_F(CUnescapeTest, Unescapes8CharUnicodeNull) {
262
+ std::string original_string = "\\U00000000";
263
+ EXPECT_TRUE(absl::CUnescape(original_string, &result_string_));
264
+ EXPECT_EQ(std::string("\0", 1), result_string_);
265
+ }
266
+
267
+ TEST_F(CUnescapeTest, UnescapesMultipleOctalNulls) {
268
+ std::string original_string(kStringWithMultipleOctalNulls);
269
+ EXPECT_TRUE(absl::CUnescape(original_string, &result_string_));
270
+ // All escapes, including newlines and null escapes, should have been
271
+ // converted to the equivalent characters.
272
+ EXPECT_EQ(std::string("\0\n"
273
+ "0\n"
274
+ "\0\n"
275
+ "\0",
276
+ 7),
277
+ result_string_);
278
+ }
279
+
280
+
281
+ TEST_F(CUnescapeTest, UnescapesMultipleHexNulls) {
282
+ std::string original_string(kStringWithMultipleHexNulls);
283
+ EXPECT_TRUE(absl::CUnescape(original_string, &result_string_));
284
+ EXPECT_EQ(std::string("\0\n"
285
+ "0\n"
286
+ "\0\n"
287
+ "\0",
288
+ 7),
289
+ result_string_);
290
+ }
291
+
292
+ TEST_F(CUnescapeTest, UnescapesMultipleUnicodeNulls) {
293
+ std::string original_string(kStringWithMultipleUnicodeNulls);
294
+ EXPECT_TRUE(absl::CUnescape(original_string, &result_string_));
295
+ EXPECT_EQ(std::string("\0\n"
296
+ "0\n"
297
+ "\0",
298
+ 5),
299
+ result_string_);
300
+ }
301
+
302
+ static struct {
303
+ absl::string_view plaintext;
304
+ absl::string_view cyphertext;
305
+ } const base64_tests[] = {
306
+ // Empty string.
307
+ {{"", 0}, {"", 0}},
308
+ {{nullptr, 0},
309
+ {"", 0}}, // if length is zero, plaintext ptr must be ignored!
310
+
311
+ // Basic bit patterns;
312
+ // values obtained with "echo -n '...' | uuencode -m test"
313
+
314
+ {{"\000", 1}, "AA=="},
315
+ {{"\001", 1}, "AQ=="},
316
+ {{"\002", 1}, "Ag=="},
317
+ {{"\004", 1}, "BA=="},
318
+ {{"\010", 1}, "CA=="},
319
+ {{"\020", 1}, "EA=="},
320
+ {{"\040", 1}, "IA=="},
321
+ {{"\100", 1}, "QA=="},
322
+ {{"\200", 1}, "gA=="},
323
+
324
+ {{"\377", 1}, "/w=="},
325
+ {{"\376", 1}, "/g=="},
326
+ {{"\375", 1}, "/Q=="},
327
+ {{"\373", 1}, "+w=="},
328
+ {{"\367", 1}, "9w=="},
329
+ {{"\357", 1}, "7w=="},
330
+ {{"\337", 1}, "3w=="},
331
+ {{"\277", 1}, "vw=="},
332
+ {{"\177", 1}, "fw=="},
333
+ {{"\000\000", 2}, "AAA="},
334
+ {{"\000\001", 2}, "AAE="},
335
+ {{"\000\002", 2}, "AAI="},
336
+ {{"\000\004", 2}, "AAQ="},
337
+ {{"\000\010", 2}, "AAg="},
338
+ {{"\000\020", 2}, "ABA="},
339
+ {{"\000\040", 2}, "ACA="},
340
+ {{"\000\100", 2}, "AEA="},
341
+ {{"\000\200", 2}, "AIA="},
342
+ {{"\001\000", 2}, "AQA="},
343
+ {{"\002\000", 2}, "AgA="},
344
+ {{"\004\000", 2}, "BAA="},
345
+ {{"\010\000", 2}, "CAA="},
346
+ {{"\020\000", 2}, "EAA="},
347
+ {{"\040\000", 2}, "IAA="},
348
+ {{"\100\000", 2}, "QAA="},
349
+ {{"\200\000", 2}, "gAA="},
350
+
351
+ {{"\377\377", 2}, "//8="},
352
+ {{"\377\376", 2}, "//4="},
353
+ {{"\377\375", 2}, "//0="},
354
+ {{"\377\373", 2}, "//s="},
355
+ {{"\377\367", 2}, "//c="},
356
+ {{"\377\357", 2}, "/+8="},
357
+ {{"\377\337", 2}, "/98="},
358
+ {{"\377\277", 2}, "/78="},
359
+ {{"\377\177", 2}, "/38="},
360
+ {{"\376\377", 2}, "/v8="},
361
+ {{"\375\377", 2}, "/f8="},
362
+ {{"\373\377", 2}, "+/8="},
363
+ {{"\367\377", 2}, "9/8="},
364
+ {{"\357\377", 2}, "7/8="},
365
+ {{"\337\377", 2}, "3/8="},
366
+ {{"\277\377", 2}, "v/8="},
367
+ {{"\177\377", 2}, "f/8="},
368
+
369
+ {{"\000\000\000", 3}, "AAAA"},
370
+ {{"\000\000\001", 3}, "AAAB"},
371
+ {{"\000\000\002", 3}, "AAAC"},
372
+ {{"\000\000\004", 3}, "AAAE"},
373
+ {{"\000\000\010", 3}, "AAAI"},
374
+ {{"\000\000\020", 3}, "AAAQ"},
375
+ {{"\000\000\040", 3}, "AAAg"},
376
+ {{"\000\000\100", 3}, "AABA"},
377
+ {{"\000\000\200", 3}, "AACA"},
378
+ {{"\000\001\000", 3}, "AAEA"},
379
+ {{"\000\002\000", 3}, "AAIA"},
380
+ {{"\000\004\000", 3}, "AAQA"},
381
+ {{"\000\010\000", 3}, "AAgA"},
382
+ {{"\000\020\000", 3}, "ABAA"},
383
+ {{"\000\040\000", 3}, "ACAA"},
384
+ {{"\000\100\000", 3}, "AEAA"},
385
+ {{"\000\200\000", 3}, "AIAA"},
386
+ {{"\001\000\000", 3}, "AQAA"},
387
+ {{"\002\000\000", 3}, "AgAA"},
388
+ {{"\004\000\000", 3}, "BAAA"},
389
+ {{"\010\000\000", 3}, "CAAA"},
390
+ {{"\020\000\000", 3}, "EAAA"},
391
+ {{"\040\000\000", 3}, "IAAA"},
392
+ {{"\100\000\000", 3}, "QAAA"},
393
+ {{"\200\000\000", 3}, "gAAA"},
394
+
395
+ {{"\377\377\377", 3}, "////"},
396
+ {{"\377\377\376", 3}, "///+"},
397
+ {{"\377\377\375", 3}, "///9"},
398
+ {{"\377\377\373", 3}, "///7"},
399
+ {{"\377\377\367", 3}, "///3"},
400
+ {{"\377\377\357", 3}, "///v"},
401
+ {{"\377\377\337", 3}, "///f"},
402
+ {{"\377\377\277", 3}, "//+/"},
403
+ {{"\377\377\177", 3}, "//9/"},
404
+ {{"\377\376\377", 3}, "//7/"},
405
+ {{"\377\375\377", 3}, "//3/"},
406
+ {{"\377\373\377", 3}, "//v/"},
407
+ {{"\377\367\377", 3}, "//f/"},
408
+ {{"\377\357\377", 3}, "/+//"},
409
+ {{"\377\337\377", 3}, "/9//"},
410
+ {{"\377\277\377", 3}, "/7//"},
411
+ {{"\377\177\377", 3}, "/3//"},
412
+ {{"\376\377\377", 3}, "/v//"},
413
+ {{"\375\377\377", 3}, "/f//"},
414
+ {{"\373\377\377", 3}, "+///"},
415
+ {{"\367\377\377", 3}, "9///"},
416
+ {{"\357\377\377", 3}, "7///"},
417
+ {{"\337\377\377", 3}, "3///"},
418
+ {{"\277\377\377", 3}, "v///"},
419
+ {{"\177\377\377", 3}, "f///"},
420
+
421
+ // Random numbers: values obtained with
422
+ //
423
+ // #! /bin/bash
424
+ // dd bs=$1 count=1 if=/dev/random of=/tmp/bar.random
425
+ // od -N $1 -t o1 /tmp/bar.random
426
+ // uuencode -m test < /tmp/bar.random
427
+ //
428
+ // where $1 is the number of bytes (2, 3)
429
+
430
+ {{"\243\361", 2}, "o/E="},
431
+ {{"\024\167", 2}, "FHc="},
432
+ {{"\313\252", 2}, "y6o="},
433
+ {{"\046\041", 2}, "JiE="},
434
+ {{"\145\236", 2}, "ZZ4="},
435
+ {{"\254\325", 2}, "rNU="},
436
+ {{"\061\330", 2}, "Mdg="},
437
+ {{"\245\032", 2}, "pRo="},
438
+ {{"\006\000", 2}, "BgA="},
439
+ {{"\375\131", 2}, "/Vk="},
440
+ {{"\303\210", 2}, "w4g="},
441
+ {{"\040\037", 2}, "IB8="},
442
+ {{"\261\372", 2}, "sfo="},
443
+ {{"\335\014", 2}, "3Qw="},
444
+ {{"\233\217", 2}, "m48="},
445
+ {{"\373\056", 2}, "+y4="},
446
+ {{"\247\232", 2}, "p5o="},
447
+ {{"\107\053", 2}, "Rys="},
448
+ {{"\204\077", 2}, "hD8="},
449
+ {{"\276\211", 2}, "vok="},
450
+ {{"\313\110", 2}, "y0g="},
451
+ {{"\363\376", 2}, "8/4="},
452
+ {{"\251\234", 2}, "qZw="},
453
+ {{"\103\262", 2}, "Q7I="},
454
+ {{"\142\312", 2}, "Yso="},
455
+ {{"\067\211", 2}, "N4k="},
456
+ {{"\220\001", 2}, "kAE="},
457
+ {{"\152\240", 2}, "aqA="},
458
+ {{"\367\061", 2}, "9zE="},
459
+ {{"\133\255", 2}, "W60="},
460
+ {{"\176\035", 2}, "fh0="},
461
+ {{"\032\231", 2}, "Gpk="},
462
+
463
+ {{"\013\007\144", 3}, "Cwdk"},
464
+ {{"\030\112\106", 3}, "GEpG"},
465
+ {{"\047\325\046", 3}, "J9Um"},
466
+ {{"\310\160\022", 3}, "yHAS"},
467
+ {{"\131\100\237", 3}, "WUCf"},
468
+ {{"\064\342\134", 3}, "NOJc"},
469
+ {{"\010\177\004", 3}, "CH8E"},
470
+ {{"\345\147\205", 3}, "5WeF"},
471
+ {{"\300\343\360", 3}, "wOPw"},
472
+ {{"\061\240\201", 3}, "MaCB"},
473
+ {{"\225\333\044", 3}, "ldsk"},
474
+ {{"\215\137\352", 3}, "jV/q"},
475
+ {{"\371\147\160", 3}, "+Wdw"},
476
+ {{"\030\320\051", 3}, "GNAp"},
477
+ {{"\044\174\241", 3}, "JHyh"},
478
+ {{"\260\127\037", 3}, "sFcf"},
479
+ {{"\111\045\033", 3}, "SSUb"},
480
+ {{"\202\114\107", 3}, "gkxH"},
481
+ {{"\057\371\042", 3}, "L/ki"},
482
+ {{"\223\247\244", 3}, "k6ek"},
483
+ {{"\047\216\144", 3}, "J45k"},
484
+ {{"\203\070\327", 3}, "gzjX"},
485
+ {{"\247\140\072", 3}, "p2A6"},
486
+ {{"\124\115\116", 3}, "VE1O"},
487
+ {{"\157\162\050", 3}, "b3Io"},
488
+ {{"\357\223\004", 3}, "75ME"},
489
+ {{"\052\117\156", 3}, "Kk9u"},
490
+ {{"\347\154\000", 3}, "52wA"},
491
+ {{"\303\012\142", 3}, "wwpi"},
492
+ {{"\060\035\362", 3}, "MB3y"},
493
+ {{"\130\226\361", 3}, "WJbx"},
494
+ {{"\173\013\071", 3}, "ews5"},
495
+ {{"\336\004\027", 3}, "3gQX"},
496
+ {{"\357\366\234", 3}, "7/ac"},
497
+ {{"\353\304\111", 3}, "68RJ"},
498
+ {{"\024\264\131", 3}, "FLRZ"},
499
+ {{"\075\114\251", 3}, "PUyp"},
500
+ {{"\315\031\225", 3}, "zRmV"},
501
+ {{"\154\201\276", 3}, "bIG+"},
502
+ {{"\200\066\072", 3}, "gDY6"},
503
+ {{"\142\350\267", 3}, "Yui3"},
504
+ {{"\033\000\166", 3}, "GwB2"},
505
+ {{"\210\055\077", 3}, "iC0/"},
506
+ {{"\341\037\124", 3}, "4R9U"},
507
+ {{"\161\103\152", 3}, "cUNq"},
508
+ {{"\270\142\131", 3}, "uGJZ"},
509
+ {{"\337\076\074", 3}, "3z48"},
510
+ {{"\375\106\362", 3}, "/Uby"},
511
+ {{"\227\301\127", 3}, "l8FX"},
512
+ {{"\340\002\234", 3}, "4AKc"},
513
+ {{"\121\064\033", 3}, "UTQb"},
514
+ {{"\157\134\143", 3}, "b1xj"},
515
+ {{"\247\055\327", 3}, "py3X"},
516
+ {{"\340\142\005", 3}, "4GIF"},
517
+ {{"\060\260\143", 3}, "MLBj"},
518
+ {{"\075\203\170", 3}, "PYN4"},
519
+ {{"\143\160\016", 3}, "Y3AO"},
520
+ {{"\313\013\063", 3}, "ywsz"},
521
+ {{"\174\236\135", 3}, "fJ5d"},
522
+ {{"\103\047\026", 3}, "QycW"},
523
+ {{"\365\005\343", 3}, "9QXj"},
524
+ {{"\271\160\223", 3}, "uXCT"},
525
+ {{"\362\255\172", 3}, "8q16"},
526
+ {{"\113\012\015", 3}, "SwoN"},
527
+
528
+ // various lengths, generated by this python script:
529
+ //
530
+ // from std::string import lowercase as lc
531
+ // for i in range(27):
532
+ // print '{ %2d, "%s",%s "%s" },' % (i, lc[:i], ' ' * (26-i),
533
+ // lc[:i].encode('base64').strip())
534
+
535
+ {{"", 0}, {"", 0}},
536
+ {"a", "YQ=="},
537
+ {"ab", "YWI="},
538
+ {"abc", "YWJj"},
539
+ {"abcd", "YWJjZA=="},
540
+ {"abcde", "YWJjZGU="},
541
+ {"abcdef", "YWJjZGVm"},
542
+ {"abcdefg", "YWJjZGVmZw=="},
543
+ {"abcdefgh", "YWJjZGVmZ2g="},
544
+ {"abcdefghi", "YWJjZGVmZ2hp"},
545
+ {"abcdefghij", "YWJjZGVmZ2hpag=="},
546
+ {"abcdefghijk", "YWJjZGVmZ2hpams="},
547
+ {"abcdefghijkl", "YWJjZGVmZ2hpamts"},
548
+ {"abcdefghijklm", "YWJjZGVmZ2hpamtsbQ=="},
549
+ {"abcdefghijklmn", "YWJjZGVmZ2hpamtsbW4="},
550
+ {"abcdefghijklmno", "YWJjZGVmZ2hpamtsbW5v"},
551
+ {"abcdefghijklmnop", "YWJjZGVmZ2hpamtsbW5vcA=="},
552
+ {"abcdefghijklmnopq", "YWJjZGVmZ2hpamtsbW5vcHE="},
553
+ {"abcdefghijklmnopqr", "YWJjZGVmZ2hpamtsbW5vcHFy"},
554
+ {"abcdefghijklmnopqrs", "YWJjZGVmZ2hpamtsbW5vcHFycw=="},
555
+ {"abcdefghijklmnopqrst", "YWJjZGVmZ2hpamtsbW5vcHFyc3Q="},
556
+ {"abcdefghijklmnopqrstu", "YWJjZGVmZ2hpamtsbW5vcHFyc3R1"},
557
+ {"abcdefghijklmnopqrstuv", "YWJjZGVmZ2hpamtsbW5vcHFyc3R1dg=="},
558
+ {"abcdefghijklmnopqrstuvw", "YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnc="},
559
+ {"abcdefghijklmnopqrstuvwx", "YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4"},
560
+ {"abcdefghijklmnopqrstuvwxy", "YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eQ=="},
561
+ {"abcdefghijklmnopqrstuvwxyz", "YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXo="},
562
+ };
563
+
564
+ template <typename StringType>
565
+ void TestEscapeAndUnescape() {
566
+ // Check the short strings; this tests the math (and boundaries)
567
+ for (const auto& tc : base64_tests) {
568
+ // Test plain base64.
569
+ StringType encoded("this junk should be ignored");
570
+ absl::Base64Escape(tc.plaintext, &encoded);
571
+ EXPECT_EQ(encoded, tc.cyphertext);
572
+ EXPECT_EQ(absl::Base64Escape(tc.plaintext), tc.cyphertext);
573
+
574
+ StringType decoded("this junk should be ignored");
575
+ EXPECT_TRUE(absl::Base64Unescape(encoded, &decoded));
576
+ EXPECT_EQ(decoded, tc.plaintext);
577
+
578
+ StringType websafe_with_padding(tc.cyphertext);
579
+ for (unsigned int c = 0; c < websafe_with_padding.size(); ++c) {
580
+ if ('+' == websafe_with_padding[c]) websafe_with_padding[c] = '-';
581
+ if ('/' == websafe_with_padding[c]) websafe_with_padding[c] = '_';
582
+ // Intentionally keeping padding aka '='.
583
+ }
584
+
585
+ // Test plain websafe (aka without padding).
586
+ StringType websafe(websafe_with_padding);
587
+ for (unsigned int c = 0; c < websafe.size(); ++c) {
588
+ if ('=' == websafe[c]) {
589
+ websafe.resize(c);
590
+ break;
591
+ }
592
+ }
593
+ encoded = "this junk should be ignored";
594
+ absl::WebSafeBase64Escape(tc.plaintext, &encoded);
595
+ EXPECT_EQ(encoded, websafe);
596
+ EXPECT_EQ(absl::WebSafeBase64Escape(tc.plaintext), websafe);
597
+
598
+ decoded = "this junk should be ignored";
599
+ EXPECT_TRUE(absl::WebSafeBase64Unescape(websafe, &decoded));
600
+ EXPECT_EQ(decoded, tc.plaintext);
601
+ }
602
+
603
+ // Now try the long strings, this tests the streaming
604
+ for (const auto& tc : absl::strings_internal::base64_strings()) {
605
+ StringType buffer;
606
+ absl::WebSafeBase64Escape(tc.plaintext, &buffer);
607
+ EXPECT_EQ(tc.cyphertext, buffer);
608
+ EXPECT_EQ(absl::WebSafeBase64Escape(tc.plaintext), tc.cyphertext);
609
+ }
610
+
611
+ // Verify the behavior when decoding bad data
612
+ {
613
+ absl::string_view data_set[] = {"ab-/", absl::string_view("\0bcd", 4),
614
+ absl::string_view("abc.\0", 5)};
615
+ for (absl::string_view bad_data : data_set) {
616
+ StringType buf;
617
+ EXPECT_FALSE(absl::Base64Unescape(bad_data, &buf));
618
+ EXPECT_FALSE(absl::WebSafeBase64Unescape(bad_data, &buf));
619
+ EXPECT_TRUE(buf.empty());
620
+ }
621
+ }
622
+ }
623
+
624
+ TEST(Base64, EscapeAndUnescape) {
625
+ TestEscapeAndUnescape<std::string>();
626
+ }
627
+
628
+ TEST(Base64, Padding) {
629
+ // Padding is optional.
630
+ // '.' is an acceptable padding character, just like '='.
631
+ std::initializer_list<absl::string_view> good_padding = {
632
+ "YQ",
633
+ "YQ==",
634
+ "YQ=.",
635
+ "YQ.=",
636
+ "YQ..",
637
+ };
638
+ for (absl::string_view b64 : good_padding) {
639
+ std::string decoded;
640
+ EXPECT_TRUE(absl::Base64Unescape(b64, &decoded));
641
+ EXPECT_EQ(decoded, "a");
642
+ std::string websafe_decoded;
643
+ EXPECT_TRUE(absl::WebSafeBase64Unescape(b64, &websafe_decoded));
644
+ EXPECT_EQ(websafe_decoded, "a");
645
+ }
646
+ std::initializer_list<absl::string_view> bad_padding = {
647
+ "YQ=",
648
+ "YQ.",
649
+ "YQ===",
650
+ "YQ==.",
651
+ "YQ=.=",
652
+ "YQ=..",
653
+ "YQ.==",
654
+ "YQ.=.",
655
+ "YQ..=",
656
+ "YQ...",
657
+ "YQ====",
658
+ "YQ....",
659
+ "YQ=====",
660
+ "YQ.....",
661
+ };
662
+ for (absl::string_view b64 : bad_padding) {
663
+ std::string decoded;
664
+ EXPECT_FALSE(absl::Base64Unescape(b64, &decoded));
665
+ std::string websafe_decoded;
666
+ EXPECT_FALSE(absl::WebSafeBase64Unescape(b64, &websafe_decoded));
667
+ }
668
+ }
669
+
670
+ TEST(Base64, DISABLED_HugeData) {
671
+ const size_t kSize = size_t(3) * 1000 * 1000 * 1000;
672
+ static_assert(kSize % 3 == 0, "kSize must be divisible by 3");
673
+ const std::string huge(kSize, 'x');
674
+
675
+ std::string escaped;
676
+ absl::Base64Escape(huge, &escaped);
677
+
678
+ // Generates the string that should match a base64 encoded "xxx..." string.
679
+ // "xxx" in base64 is "eHh4".
680
+ std::string expected_encoding;
681
+ expected_encoding.reserve(kSize / 3 * 4);
682
+ for (size_t i = 0; i < kSize / 3; ++i) {
683
+ expected_encoding.append("eHh4");
684
+ }
685
+ EXPECT_EQ(expected_encoding, escaped);
686
+
687
+ std::string unescaped;
688
+ EXPECT_TRUE(absl::Base64Unescape(escaped, &unescaped));
689
+ EXPECT_EQ(huge, unescaped);
690
+ }
691
+
692
+ TEST(HexAndBack, HexStringToBytes_and_BytesToHexString) {
693
+ std::string hex_mixed = "0123456789abcdefABCDEF";
694
+ std::string bytes_expected = "\x01\x23\x45\x67\x89\xab\xcd\xef\xAB\xCD\xEF";
695
+ std::string hex_only_lower = "0123456789abcdefabcdef";
696
+
697
+ std::string bytes_result = absl::HexStringToBytes(hex_mixed);
698
+ EXPECT_EQ(bytes_expected, bytes_result);
699
+
700
+ std::string prefix_valid = hex_mixed + "?";
701
+ std::string prefix_valid_result = absl::HexStringToBytes(
702
+ absl::string_view(prefix_valid.data(), prefix_valid.size() - 1));
703
+ EXPECT_EQ(bytes_expected, prefix_valid_result);
704
+
705
+ std::string infix_valid = "?" + hex_mixed + "???";
706
+ std::string infix_valid_result = absl::HexStringToBytes(
707
+ absl::string_view(infix_valid.data() + 1, hex_mixed.size()));
708
+ EXPECT_EQ(bytes_expected, infix_valid_result);
709
+
710
+ std::string hex_result = absl::BytesToHexString(bytes_expected);
711
+ EXPECT_EQ(hex_only_lower, hex_result);
712
+ }
713
+
714
+ } // namespace
weight/_dep/abseil-cpp/absl/strings/has_ostream_operator_test.cc ADDED
@@ -0,0 +1,41 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Copyright 2023 The Abseil Authors
2
+ //
3
+ // Licensed under the Apache License, Version 2.0 (the "License");
4
+ // you may not use this file except in compliance with the License.
5
+ // You may obtain a copy of the License at
6
+ //
7
+ // https://www.apache.org/licenses/LICENSE-2.0
8
+ //
9
+ // Unless required by applicable law or agreed to in writing, software
10
+ // distributed under the License is distributed on an "AS IS" BASIS,
11
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ // See the License for the specific language governing permissions and
13
+ // limitations under the License.
14
+
15
+ #include "absl/strings/has_ostream_operator.h"
16
+
17
+ #include <ostream>
18
+ #include <string>
19
+
20
+ #include "gtest/gtest.h"
21
+ #include "absl/types/optional.h"
22
+
23
+ namespace {
24
+
25
+ struct TypeWithoutOstreamOp {};
26
+
27
+ struct TypeWithOstreamOp {
28
+ friend std::ostream& operator<<(std::ostream& os, const TypeWithOstreamOp&) {
29
+ return os;
30
+ }
31
+ };
32
+
33
+ TEST(HasOstreamOperatorTest, Works) {
34
+ EXPECT_TRUE(absl::HasOstreamOperator<int>::value);
35
+ EXPECT_TRUE(absl::HasOstreamOperator<std::string>::value);
36
+ EXPECT_FALSE(absl::HasOstreamOperator<absl::optional<int>>::value);
37
+ EXPECT_FALSE(absl::HasOstreamOperator<TypeWithoutOstreamOp>::value);
38
+ EXPECT_TRUE(absl::HasOstreamOperator<TypeWithOstreamOp>::value);
39
+ }
40
+
41
+ } // namespace
weight/_dep/abseil-cpp/absl/strings/internal/charconv_bigint.h ADDED
@@ -0,0 +1,423 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Copyright 2018 The Abseil Authors.
2
+ //
3
+ // Licensed under the Apache License, Version 2.0 (the "License");
4
+ // you may not use this file except in compliance with the License.
5
+ // You may obtain a copy of the License at
6
+ //
7
+ // https://www.apache.org/licenses/LICENSE-2.0
8
+ //
9
+ // Unless required by applicable law or agreed to in writing, software
10
+ // distributed under the License is distributed on an "AS IS" BASIS,
11
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ // See the License for the specific language governing permissions and
13
+ // limitations under the License.
14
+
15
+ #ifndef ABSL_STRINGS_INTERNAL_CHARCONV_BIGINT_H_
16
+ #define ABSL_STRINGS_INTERNAL_CHARCONV_BIGINT_H_
17
+
18
+ #include <algorithm>
19
+ #include <cstdint>
20
+ #include <iostream>
21
+ #include <string>
22
+
23
+ #include "absl/base/config.h"
24
+ #include "absl/strings/ascii.h"
25
+ #include "absl/strings/internal/charconv_parse.h"
26
+ #include "absl/strings/string_view.h"
27
+
28
+ namespace absl {
29
+ ABSL_NAMESPACE_BEGIN
30
+ namespace strings_internal {
31
+
32
+ // The largest power that 5 that can be raised to, and still fit in a uint32_t.
33
+ constexpr int kMaxSmallPowerOfFive = 13;
34
+ // The largest power that 10 that can be raised to, and still fit in a uint32_t.
35
+ constexpr int kMaxSmallPowerOfTen = 9;
36
+
37
+ ABSL_DLL extern const uint32_t
38
+ kFiveToNth[kMaxSmallPowerOfFive + 1];
39
+ ABSL_DLL extern const uint32_t kTenToNth[kMaxSmallPowerOfTen + 1];
40
+
41
+ // Large, fixed-width unsigned integer.
42
+ //
43
+ // Exact rounding for decimal-to-binary floating point conversion requires very
44
+ // large integer math, but a design goal of absl::from_chars is to avoid
45
+ // allocating memory. The integer precision needed for decimal-to-binary
46
+ // conversions is large but bounded, so a huge fixed-width integer class
47
+ // suffices.
48
+ //
49
+ // This is an intentionally limited big integer class. Only needed operations
50
+ // are implemented. All storage lives in an array data member, and all
51
+ // arithmetic is done in-place, to avoid requiring separate storage for operand
52
+ // and result.
53
+ //
54
+ // This is an internal class. Some methods live in the .cc file, and are
55
+ // instantiated only for the values of max_words we need.
56
+ template <int max_words>
57
+ class BigUnsigned {
58
+ public:
59
+ static_assert(max_words == 4 || max_words == 84,
60
+ "unsupported max_words value");
61
+
62
+ BigUnsigned() : size_(0), words_{} {}
63
+ explicit constexpr BigUnsigned(uint64_t v)
64
+ : size_((v >> 32) ? 2 : v ? 1 : 0),
65
+ words_{static_cast<uint32_t>(v & 0xffffffffu),
66
+ static_cast<uint32_t>(v >> 32)} {}
67
+
68
+ // Constructs a BigUnsigned from the given string_view containing a decimal
69
+ // value. If the input string is not a decimal integer, constructs a 0
70
+ // instead.
71
+ explicit BigUnsigned(absl::string_view sv) : size_(0), words_{} {
72
+ // Check for valid input, returning a 0 otherwise. This is reasonable
73
+ // behavior only because this constructor is for unit tests.
74
+ if (std::find_if_not(sv.begin(), sv.end(), ascii_isdigit) != sv.end() ||
75
+ sv.empty()) {
76
+ return;
77
+ }
78
+ int exponent_adjust =
79
+ ReadDigits(sv.data(), sv.data() + sv.size(), Digits10() + 1);
80
+ if (exponent_adjust > 0) {
81
+ MultiplyByTenToTheNth(exponent_adjust);
82
+ }
83
+ }
84
+
85
+ // Loads the mantissa value of a previously-parsed float.
86
+ //
87
+ // Returns the associated decimal exponent. The value of the parsed float is
88
+ // exactly *this * 10**exponent.
89
+ int ReadFloatMantissa(const ParsedFloat& fp, int significant_digits);
90
+
91
+ // Returns the number of decimal digits of precision this type provides. All
92
+ // numbers with this many decimal digits or fewer are representable by this
93
+ // type.
94
+ //
95
+ // Analogous to std::numeric_limits<BigUnsigned>::digits10.
96
+ static constexpr int Digits10() {
97
+ // 9975007/1035508 is very slightly less than log10(2**32).
98
+ return static_cast<uint64_t>(max_words) * 9975007 / 1035508;
99
+ }
100
+
101
+ // Shifts left by the given number of bits.
102
+ void ShiftLeft(int count) {
103
+ if (count > 0) {
104
+ const int word_shift = count / 32;
105
+ if (word_shift >= max_words) {
106
+ SetToZero();
107
+ return;
108
+ }
109
+ size_ = (std::min)(size_ + word_shift, max_words);
110
+ count %= 32;
111
+ if (count == 0) {
112
+ std::copy_backward(words_, words_ + size_ - word_shift, words_ + size_);
113
+ } else {
114
+ for (int i = (std::min)(size_, max_words - 1); i > word_shift; --i) {
115
+ words_[i] = (words_[i - word_shift] << count) |
116
+ (words_[i - word_shift - 1] >> (32 - count));
117
+ }
118
+ words_[word_shift] = words_[0] << count;
119
+ // Grow size_ if necessary.
120
+ if (size_ < max_words && words_[size_]) {
121
+ ++size_;
122
+ }
123
+ }
124
+ std::fill_n(words_, word_shift, 0u);
125
+ }
126
+ }
127
+
128
+
129
+ // Multiplies by v in-place.
130
+ void MultiplyBy(uint32_t v) {
131
+ if (size_ == 0 || v == 1) {
132
+ return;
133
+ }
134
+ if (v == 0) {
135
+ SetToZero();
136
+ return;
137
+ }
138
+ const uint64_t factor = v;
139
+ uint64_t window = 0;
140
+ for (int i = 0; i < size_; ++i) {
141
+ window += factor * words_[i];
142
+ words_[i] = window & 0xffffffff;
143
+ window >>= 32;
144
+ }
145
+ // If carry bits remain and there's space for them, grow size_.
146
+ if (window && size_ < max_words) {
147
+ words_[size_] = window & 0xffffffff;
148
+ ++size_;
149
+ }
150
+ }
151
+
152
+ void MultiplyBy(uint64_t v) {
153
+ uint32_t words[2];
154
+ words[0] = static_cast<uint32_t>(v);
155
+ words[1] = static_cast<uint32_t>(v >> 32);
156
+ if (words[1] == 0) {
157
+ MultiplyBy(words[0]);
158
+ } else {
159
+ MultiplyBy(2, words);
160
+ }
161
+ }
162
+
163
+ // Multiplies in place by 5 to the power of n. n must be non-negative.
164
+ void MultiplyByFiveToTheNth(int n) {
165
+ while (n >= kMaxSmallPowerOfFive) {
166
+ MultiplyBy(kFiveToNth[kMaxSmallPowerOfFive]);
167
+ n -= kMaxSmallPowerOfFive;
168
+ }
169
+ if (n > 0) {
170
+ MultiplyBy(kFiveToNth[n]);
171
+ }
172
+ }
173
+
174
+ // Multiplies in place by 10 to the power of n. n must be non-negative.
175
+ void MultiplyByTenToTheNth(int n) {
176
+ if (n > kMaxSmallPowerOfTen) {
177
+ // For large n, raise to a power of 5, then shift left by the same amount.
178
+ // (10**n == 5**n * 2**n.) This requires fewer multiplications overall.
179
+ MultiplyByFiveToTheNth(n);
180
+ ShiftLeft(n);
181
+ } else if (n > 0) {
182
+ // We can do this more quickly for very small N by using a single
183
+ // multiplication.
184
+ MultiplyBy(kTenToNth[n]);
185
+ }
186
+ }
187
+
188
+ // Returns the value of 5**n, for non-negative n. This implementation uses
189
+ // a lookup table, and is faster then seeding a BigUnsigned with 1 and calling
190
+ // MultiplyByFiveToTheNth().
191
+ static BigUnsigned FiveToTheNth(int n);
192
+
193
+ // Multiplies by another BigUnsigned, in-place.
194
+ template <int M>
195
+ void MultiplyBy(const BigUnsigned<M>& other) {
196
+ MultiplyBy(other.size(), other.words());
197
+ }
198
+
199
+ void SetToZero() {
200
+ std::fill_n(words_, size_, 0u);
201
+ size_ = 0;
202
+ }
203
+
204
+ // Returns the value of the nth word of this BigUnsigned. This is
205
+ // range-checked, and returns 0 on out-of-bounds accesses.
206
+ uint32_t GetWord(int index) const {
207
+ if (index < 0 || index >= size_) {
208
+ return 0;
209
+ }
210
+ return words_[index];
211
+ }
212
+
213
+ // Returns this integer as a decimal string. This is not used in the decimal-
214
+ // to-binary conversion; it is intended to aid in testing.
215
+ std::string ToString() const;
216
+
217
+ int size() const { return size_; }
218
+ const uint32_t* words() const { return words_; }
219
+
220
+ private:
221
+ // Reads the number between [begin, end), possibly containing a decimal point,
222
+ // into this BigUnsigned.
223
+ //
224
+ // Callers are required to ensure [begin, end) contains a valid number, with
225
+ // one or more decimal digits and at most one decimal point. This routine
226
+ // will behave unpredictably if these preconditions are not met.
227
+ //
228
+ // Only the first `significant_digits` digits are read. Digits beyond this
229
+ // limit are "sticky": If the final significant digit is 0 or 5, and if any
230
+ // dropped digit is nonzero, then that final significant digit is adjusted up
231
+ // to 1 or 6. This adjustment allows for precise rounding.
232
+ //
233
+ // Returns `exponent_adjustment`, a power-of-ten exponent adjustment to
234
+ // account for the decimal point and for dropped significant digits. After
235
+ // this function returns,
236
+ // actual_value_of_parsed_string ~= *this * 10**exponent_adjustment.
237
+ int ReadDigits(const char* begin, const char* end, int significant_digits);
238
+
239
+ // Performs a step of big integer multiplication. This computes the full
240
+ // (64-bit-wide) values that should be added at the given index (step), and
241
+ // adds to that location in-place.
242
+ //
243
+ // Because our math all occurs in place, we must multiply starting from the
244
+ // highest word working downward. (This is a bit more expensive due to the
245
+ // extra carries involved.)
246
+ //
247
+ // This must be called in steps, for each word to be calculated, starting from
248
+ // the high end and working down to 0. The first value of `step` should be
249
+ // `std::min(original_size + other.size_ - 2, max_words - 1)`.
250
+ // The reason for this expression is that multiplying the i'th word from one
251
+ // multiplicand and the j'th word of another multiplicand creates a
252
+ // two-word-wide value to be stored at the (i+j)'th element. The highest
253
+ // word indices we will access are `original_size - 1` from this object, and
254
+ // `other.size_ - 1` from our operand. Therefore,
255
+ // `original_size + other.size_ - 2` is the first step we should calculate,
256
+ // but limited on an upper bound by max_words.
257
+
258
+ // Working from high-to-low ensures that we do not overwrite the portions of
259
+ // the initial value of *this which are still needed for later steps.
260
+ //
261
+ // Once called with step == 0, *this contains the result of the
262
+ // multiplication.
263
+ //
264
+ // `original_size` is the size_ of *this before the first call to
265
+ // MultiplyStep(). `other_words` and `other_size` are the contents of our
266
+ // operand. `step` is the step to perform, as described above.
267
+ void MultiplyStep(int original_size, const uint32_t* other_words,
268
+ int other_size, int step);
269
+
270
+ void MultiplyBy(int other_size, const uint32_t* other_words) {
271
+ const int original_size = size_;
272
+ const int first_step =
273
+ (std::min)(original_size + other_size - 2, max_words - 1);
274
+ for (int step = first_step; step >= 0; --step) {
275
+ MultiplyStep(original_size, other_words, other_size, step);
276
+ }
277
+ }
278
+
279
+ // Adds a 32-bit value to the index'th word, with carry.
280
+ void AddWithCarry(int index, uint32_t value) {
281
+ if (value) {
282
+ while (index < max_words && value > 0) {
283
+ words_[index] += value;
284
+ // carry if we overflowed in this word:
285
+ if (value > words_[index]) {
286
+ value = 1;
287
+ ++index;
288
+ } else {
289
+ value = 0;
290
+ }
291
+ }
292
+ size_ = (std::min)(max_words, (std::max)(index + 1, size_));
293
+ }
294
+ }
295
+
296
+ void AddWithCarry(int index, uint64_t value) {
297
+ if (value && index < max_words) {
298
+ uint32_t high = value >> 32;
299
+ uint32_t low = value & 0xffffffff;
300
+ words_[index] += low;
301
+ if (words_[index] < low) {
302
+ ++high;
303
+ if (high == 0) {
304
+ // Carry from the low word caused our high word to overflow.
305
+ // Short circuit here to do the right thing.
306
+ AddWithCarry(index + 2, static_cast<uint32_t>(1));
307
+ return;
308
+ }
309
+ }
310
+ if (high > 0) {
311
+ AddWithCarry(index + 1, high);
312
+ } else {
313
+ // Normally 32-bit AddWithCarry() sets size_, but since we don't call
314
+ // it when `high` is 0, do it ourselves here.
315
+ size_ = (std::min)(max_words, (std::max)(index + 1, size_));
316
+ }
317
+ }
318
+ }
319
+
320
+ // Divide this in place by a constant divisor. Returns the remainder of the
321
+ // division.
322
+ template <uint32_t divisor>
323
+ uint32_t DivMod() {
324
+ uint64_t accumulator = 0;
325
+ for (int i = size_ - 1; i >= 0; --i) {
326
+ accumulator <<= 32;
327
+ accumulator += words_[i];
328
+ // accumulator / divisor will never overflow an int32_t in this loop
329
+ words_[i] = static_cast<uint32_t>(accumulator / divisor);
330
+ accumulator = accumulator % divisor;
331
+ }
332
+ while (size_ > 0 && words_[size_ - 1] == 0) {
333
+ --size_;
334
+ }
335
+ return static_cast<uint32_t>(accumulator);
336
+ }
337
+
338
+ // The number of elements in words_ that may carry significant values.
339
+ // All elements beyond this point are 0.
340
+ //
341
+ // When size_ is 0, this BigUnsigned stores the value 0.
342
+ // When size_ is nonzero, is *not* guaranteed that words_[size_ - 1] is
343
+ // nonzero. This can occur due to overflow truncation.
344
+ // In particular, x.size_ != y.size_ does *not* imply x != y.
345
+ int size_;
346
+ uint32_t words_[max_words];
347
+ };
348
+
349
+ // Compares two big integer instances.
350
+ //
351
+ // Returns -1 if lhs < rhs, 0 if lhs == rhs, and 1 if lhs > rhs.
352
+ template <int N, int M>
353
+ int Compare(const BigUnsigned<N>& lhs, const BigUnsigned<M>& rhs) {
354
+ int limit = (std::max)(lhs.size(), rhs.size());
355
+ for (int i = limit - 1; i >= 0; --i) {
356
+ const uint32_t lhs_word = lhs.GetWord(i);
357
+ const uint32_t rhs_word = rhs.GetWord(i);
358
+ if (lhs_word < rhs_word) {
359
+ return -1;
360
+ } else if (lhs_word > rhs_word) {
361
+ return 1;
362
+ }
363
+ }
364
+ return 0;
365
+ }
366
+
367
+ template <int N, int M>
368
+ bool operator==(const BigUnsigned<N>& lhs, const BigUnsigned<M>& rhs) {
369
+ int limit = (std::max)(lhs.size(), rhs.size());
370
+ for (int i = 0; i < limit; ++i) {
371
+ if (lhs.GetWord(i) != rhs.GetWord(i)) {
372
+ return false;
373
+ }
374
+ }
375
+ return true;
376
+ }
377
+
378
+ template <int N, int M>
379
+ bool operator!=(const BigUnsigned<N>& lhs, const BigUnsigned<M>& rhs) {
380
+ return !(lhs == rhs);
381
+ }
382
+
383
+ template <int N, int M>
384
+ bool operator<(const BigUnsigned<N>& lhs, const BigUnsigned<M>& rhs) {
385
+ return Compare(lhs, rhs) == -1;
386
+ }
387
+
388
+ template <int N, int M>
389
+ bool operator>(const BigUnsigned<N>& lhs, const BigUnsigned<M>& rhs) {
390
+ return rhs < lhs;
391
+ }
392
+ template <int N, int M>
393
+ bool operator<=(const BigUnsigned<N>& lhs, const BigUnsigned<M>& rhs) {
394
+ return !(rhs < lhs);
395
+ }
396
+ template <int N, int M>
397
+ bool operator>=(const BigUnsigned<N>& lhs, const BigUnsigned<M>& rhs) {
398
+ return !(lhs < rhs);
399
+ }
400
+
401
+ // Output operator for BigUnsigned, for testing purposes only.
402
+ template <int N>
403
+ std::ostream& operator<<(std::ostream& os, const BigUnsigned<N>& num) {
404
+ return os << num.ToString();
405
+ }
406
+
407
+ // Explicit instantiation declarations for the sizes of BigUnsigned that we
408
+ // are using.
409
+ //
410
+ // For now, the choices of 4 and 84 are arbitrary; 4 is a small value that is
411
+ // still bigger than an int128, and 84 is a large value we will want to use
412
+ // in the from_chars implementation.
413
+ //
414
+ // Comments justifying the use of 84 belong in the from_chars implementation,
415
+ // and will be added in a follow-up CL.
416
+ extern template class BigUnsigned<4>;
417
+ extern template class BigUnsigned<84>;
418
+
419
+ } // namespace strings_internal
420
+ ABSL_NAMESPACE_END
421
+ } // namespace absl
422
+
423
+ #endif // ABSL_STRINGS_INTERNAL_CHARCONV_BIGINT_H_
weight/_dep/abseil-cpp/absl/strings/internal/charconv_bigint_test.cc ADDED
@@ -0,0 +1,260 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Copyright 2018 The Abseil Authors.
2
+ //
3
+ // Licensed under the Apache License, Version 2.0 (the "License");
4
+ // you may not use this file except in compliance with the License.
5
+ // You may obtain a copy of the License at
6
+ //
7
+ // https://www.apache.org/licenses/LICENSE-2.0
8
+ //
9
+ // Unless required by applicable law or agreed to in writing, software
10
+ // distributed under the License is distributed on an "AS IS" BASIS,
11
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ // See the License for the specific language governing permissions and
13
+ // limitations under the License.
14
+
15
+ #include "absl/strings/internal/charconv_bigint.h"
16
+
17
+ #include <string>
18
+
19
+ #include "gtest/gtest.h"
20
+
21
+ namespace absl {
22
+ ABSL_NAMESPACE_BEGIN
23
+ namespace strings_internal {
24
+
25
+ TEST(BigUnsigned, ShiftLeft) {
26
+ {
27
+ // Check that 3 * 2**100 is calculated correctly
28
+ BigUnsigned<4> num(3u);
29
+ num.ShiftLeft(100);
30
+ EXPECT_EQ(num, BigUnsigned<4>("3802951800684688204490109616128"));
31
+ }
32
+ {
33
+ // Test that overflow is truncated properly.
34
+ // 15 is 4 bits long, and BigUnsigned<4> is a 128-bit bigint.
35
+ // Shifting left by 125 bits should truncate off the high bit, so that
36
+ // 15 << 125 == 7 << 125
37
+ // after truncation.
38
+ BigUnsigned<4> a(15u);
39
+ BigUnsigned<4> b(7u);
40
+ BigUnsigned<4> c(3u);
41
+ a.ShiftLeft(125);
42
+ b.ShiftLeft(125);
43
+ c.ShiftLeft(125);
44
+ EXPECT_EQ(a, b);
45
+ EXPECT_NE(a, c);
46
+ }
47
+ {
48
+ // Same test, larger bigint:
49
+ BigUnsigned<84> a(15u);
50
+ BigUnsigned<84> b(7u);
51
+ BigUnsigned<84> c(3u);
52
+ a.ShiftLeft(84 * 32 - 3);
53
+ b.ShiftLeft(84 * 32 - 3);
54
+ c.ShiftLeft(84 * 32 - 3);
55
+ EXPECT_EQ(a, b);
56
+ EXPECT_NE(a, c);
57
+ }
58
+ {
59
+ // Check that incrementally shifting has the same result as doing it all at
60
+ // once (attempting to capture corner cases.)
61
+ const std::string seed = "1234567890123456789012345678901234567890";
62
+ BigUnsigned<84> a(seed);
63
+ for (int i = 1; i <= 84 * 32; ++i) {
64
+ a.ShiftLeft(1);
65
+ BigUnsigned<84> b(seed);
66
+ b.ShiftLeft(i);
67
+ EXPECT_EQ(a, b);
68
+ }
69
+ // And we should have fully rotated all bits off by now:
70
+ EXPECT_EQ(a, BigUnsigned<84>(0u));
71
+ }
72
+ {
73
+ // Bit shifting large and small numbers by large and small offsets.
74
+ // Intended to exercise bounds-checking corner on ShiftLeft() (directly
75
+ // and under asan).
76
+
77
+ // 2**(32*84)-1
78
+ const BigUnsigned<84> all_bits_one(
79
+ "1474444211396924248063325089479706787923460402125687709454567433186613"
80
+ "6228083464060749874845919674257665016359189106695900028098437021384227"
81
+ "3285029708032466536084583113729486015826557532750465299832071590813090"
82
+ "2011853039837649252477307070509704043541368002938784757296893793903797"
83
+ "8180292336310543540677175225040919704702800559606097685920595947397024"
84
+ "8303316808753252115729411497720357971050627997031988036134171378490368"
85
+ "6008000778741115399296162550786288457245180872759047016734959330367829"
86
+ "5235612397427686310674725251378116268607113017720538636924549612987647"
87
+ "5767411074510311386444547332882472126067840027882117834454260409440463"
88
+ "9345147252664893456053258463203120637089916304618696601333953616715125"
89
+ "2115882482473279040772264257431663818610405673876655957323083702713344"
90
+ "4201105427930770976052393421467136557055");
91
+ const BigUnsigned<84> zero(0u);
92
+ const BigUnsigned<84> one(1u);
93
+ // in bounds shifts
94
+ for (int i = 1; i < 84*32; ++i) {
95
+ // shifting all_bits_one to the left should result in a smaller number,
96
+ // since the high bits rotate off and the low bits are replaced with
97
+ // zeroes.
98
+ BigUnsigned<84> big_shifted = all_bits_one;
99
+ big_shifted.ShiftLeft(i);
100
+ EXPECT_GT(all_bits_one, big_shifted);
101
+ // Shifting 1 to the left should instead result in a larger number.
102
+ BigUnsigned<84> small_shifted = one;
103
+ small_shifted.ShiftLeft(i);
104
+ EXPECT_LT(one, small_shifted);
105
+ }
106
+ // Shifting by zero or a negative number has no effect
107
+ for (int no_op_shift : {0, -1, -84 * 32, std::numeric_limits<int>::min()}) {
108
+ BigUnsigned<84> big_shifted = all_bits_one;
109
+ big_shifted.ShiftLeft(no_op_shift);
110
+ EXPECT_EQ(all_bits_one, big_shifted);
111
+ BigUnsigned<84> small_shifted = one;
112
+ big_shifted.ShiftLeft(no_op_shift);
113
+ EXPECT_EQ(one, small_shifted);
114
+ }
115
+ // Shifting by an amount greater than the number of bits should result in
116
+ // zero.
117
+ for (int out_of_bounds_shift :
118
+ {84 * 32, 84 * 32 + 1, std::numeric_limits<int>::max()}) {
119
+ BigUnsigned<84> big_shifted = all_bits_one;
120
+ big_shifted.ShiftLeft(out_of_bounds_shift);
121
+ EXPECT_EQ(zero, big_shifted);
122
+ BigUnsigned<84> small_shifted = one;
123
+ small_shifted.ShiftLeft(out_of_bounds_shift);
124
+ EXPECT_EQ(zero, small_shifted);
125
+ }
126
+ }
127
+ }
128
+
129
+ TEST(BigUnsigned, MultiplyByUint32) {
130
+ const BigUnsigned<84> factorial_100(
131
+ "933262154439441526816992388562667004907159682643816214685929638952175999"
132
+ "932299156089414639761565182862536979208272237582511852109168640000000000"
133
+ "00000000000000");
134
+ BigUnsigned<84> a(1u);
135
+ for (uint32_t i = 1; i <= 100; ++i) {
136
+ a.MultiplyBy(i);
137
+ }
138
+ EXPECT_EQ(a, BigUnsigned<84>(factorial_100));
139
+ }
140
+
141
+ TEST(BigUnsigned, MultiplyByBigUnsigned) {
142
+ {
143
+ // Put the terms of factorial_200 into two bigints, and multiply them
144
+ // together.
145
+ const BigUnsigned<84> factorial_200(
146
+ "7886578673647905035523632139321850622951359776871732632947425332443594"
147
+ "4996340334292030428401198462390417721213891963883025764279024263710506"
148
+ "1926624952829931113462857270763317237396988943922445621451664240254033"
149
+ "2918641312274282948532775242424075739032403212574055795686602260319041"
150
+ "7032406235170085879617892222278962370389737472000000000000000000000000"
151
+ "0000000000000000000000000");
152
+ BigUnsigned<84> evens(1u);
153
+ BigUnsigned<84> odds(1u);
154
+ for (uint32_t i = 1; i < 200; i += 2) {
155
+ odds.MultiplyBy(i);
156
+ evens.MultiplyBy(i + 1);
157
+ }
158
+ evens.MultiplyBy(odds);
159
+ EXPECT_EQ(evens, factorial_200);
160
+ }
161
+ {
162
+ // Multiply various powers of 10 together.
163
+ for (int a = 0 ; a < 700; a += 25) {
164
+ SCOPED_TRACE(a);
165
+ BigUnsigned<84> a_value("3" + std::string(a, '0'));
166
+ for (int b = 0; b < (700 - a); b += 25) {
167
+ SCOPED_TRACE(b);
168
+ BigUnsigned<84> b_value("2" + std::string(b, '0'));
169
+ BigUnsigned<84> expected_product("6" + std::string(a + b, '0'));
170
+ b_value.MultiplyBy(a_value);
171
+ EXPECT_EQ(b_value, expected_product);
172
+ }
173
+ }
174
+ }
175
+ }
176
+
177
+ TEST(BigUnsigned, MultiplyByOverflow) {
178
+ {
179
+ // Check that multiplcation overflow predictably truncates.
180
+
181
+ // A big int with all bits on.
182
+ BigUnsigned<4> all_bits_on("340282366920938463463374607431768211455");
183
+ // Modulo 2**128, this is equal to -1. Therefore the square of this,
184
+ // modulo 2**128, should be 1.
185
+ all_bits_on.MultiplyBy(all_bits_on);
186
+ EXPECT_EQ(all_bits_on, BigUnsigned<4>(1u));
187
+ }
188
+ {
189
+ // Try multiplying a large bigint by 2**50, and compare the result to
190
+ // shifting.
191
+ BigUnsigned<4> value_1("12345678901234567890123456789012345678");
192
+ BigUnsigned<4> value_2("12345678901234567890123456789012345678");
193
+ BigUnsigned<4> two_to_fiftieth(1u);
194
+ two_to_fiftieth.ShiftLeft(50);
195
+
196
+ value_1.ShiftLeft(50);
197
+ value_2.MultiplyBy(two_to_fiftieth);
198
+ EXPECT_EQ(value_1, value_2);
199
+ }
200
+ }
201
+
202
+ TEST(BigUnsigned, FiveToTheNth) {
203
+ {
204
+ // Sanity check that MultiplyByFiveToTheNth gives consistent answers, up to
205
+ // and including overflow.
206
+ for (int i = 0; i < 1160; ++i) {
207
+ SCOPED_TRACE(i);
208
+ BigUnsigned<84> value_1(123u);
209
+ BigUnsigned<84> value_2(123u);
210
+ value_1.MultiplyByFiveToTheNth(i);
211
+ for (int j = 0; j < i; j++) {
212
+ value_2.MultiplyBy(5u);
213
+ }
214
+ EXPECT_EQ(value_1, value_2);
215
+ }
216
+ }
217
+ {
218
+ // Check that the faster, table-lookup-based static method returns the same
219
+ // result that multiplying in-place would return, up to and including
220
+ // overflow.
221
+ for (int i = 0; i < 1160; ++i) {
222
+ SCOPED_TRACE(i);
223
+ BigUnsigned<84> value_1(1u);
224
+ value_1.MultiplyByFiveToTheNth(i);
225
+ BigUnsigned<84> value_2 = BigUnsigned<84>::FiveToTheNth(i);
226
+ EXPECT_EQ(value_1, value_2);
227
+ }
228
+ }
229
+ }
230
+
231
+ TEST(BigUnsigned, TenToTheNth) {
232
+ {
233
+ // Sanity check MultiplyByTenToTheNth.
234
+ for (int i = 0; i < 800; ++i) {
235
+ SCOPED_TRACE(i);
236
+ BigUnsigned<84> value_1(123u);
237
+ BigUnsigned<84> value_2(123u);
238
+ value_1.MultiplyByTenToTheNth(i);
239
+ for (int j = 0; j < i; j++) {
240
+ value_2.MultiplyBy(10u);
241
+ }
242
+ EXPECT_EQ(value_1, value_2);
243
+ }
244
+ }
245
+ {
246
+ // Alternate testing approach, taking advantage of the decimal parser.
247
+ for (int i = 0; i < 200; ++i) {
248
+ SCOPED_TRACE(i);
249
+ BigUnsigned<84> value_1(135u);
250
+ value_1.MultiplyByTenToTheNth(i);
251
+ BigUnsigned<84> value_2("135" + std::string(i, '0'));
252
+ EXPECT_EQ(value_1, value_2);
253
+ }
254
+ }
255
+ }
256
+
257
+
258
+ } // namespace strings_internal
259
+ ABSL_NAMESPACE_END
260
+ } // namespace absl
weight/_dep/abseil-cpp/absl/strings/internal/charconv_parse_test.cc ADDED
@@ -0,0 +1,357 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Copyright 2018 The Abseil Authors.
2
+ //
3
+ // Licensed under the Apache License, Version 2.0 (the "License");
4
+ // you may not use this file except in compliance with the License.
5
+ // You may obtain a copy of the License at
6
+ //
7
+ // https://www.apache.org/licenses/LICENSE-2.0
8
+ //
9
+ // Unless required by applicable law or agreed to in writing, software
10
+ // distributed under the License is distributed on an "AS IS" BASIS,
11
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ // See the License for the specific language governing permissions and
13
+ // limitations under the License.
14
+
15
+ #include "absl/strings/internal/charconv_parse.h"
16
+
17
+ #include <string>
18
+ #include <utility>
19
+
20
+ #include "gmock/gmock.h"
21
+ #include "gtest/gtest.h"
22
+ #include "absl/log/check.h"
23
+ #include "absl/strings/str_cat.h"
24
+
25
+ using absl::chars_format;
26
+ using absl::strings_internal::FloatType;
27
+ using absl::strings_internal::ParsedFloat;
28
+ using absl::strings_internal::ParseFloat;
29
+
30
+ namespace {
31
+
32
+ // Check that a given string input is parsed to the expected mantissa and
33
+ // exponent.
34
+ //
35
+ // Input string `s` must contain a '$' character. It marks the end of the
36
+ // characters that should be consumed by the match. It is stripped from the
37
+ // input to ParseFloat.
38
+ //
39
+ // If input string `s` contains '[' and ']' characters, these mark the region
40
+ // of characters that should be marked as the "subrange". For NaNs, this is
41
+ // the location of the extended NaN string. For numbers, this is the location
42
+ // of the full, over-large mantissa.
43
+ template <int base>
44
+ void ExpectParsedFloat(std::string s, absl::chars_format format_flags,
45
+ FloatType expected_type, uint64_t expected_mantissa,
46
+ int expected_exponent,
47
+ int expected_literal_exponent = -999) {
48
+ SCOPED_TRACE(s);
49
+
50
+ int begin_subrange = -1;
51
+ int end_subrange = -1;
52
+ // If s contains '[' and ']', then strip these characters and set the subrange
53
+ // indices appropriately.
54
+ std::string::size_type open_bracket_pos = s.find('[');
55
+ if (open_bracket_pos != std::string::npos) {
56
+ begin_subrange = static_cast<int>(open_bracket_pos);
57
+ s.replace(open_bracket_pos, 1, "");
58
+ std::string::size_type close_bracket_pos = s.find(']');
59
+ CHECK_NE(close_bracket_pos, absl::string_view::npos)
60
+ << "Test input contains [ without matching ]";
61
+ end_subrange = static_cast<int>(close_bracket_pos);
62
+ s.replace(close_bracket_pos, 1, "");
63
+ }
64
+ const std::string::size_type expected_characters_matched = s.find('$');
65
+ CHECK_NE(expected_characters_matched, std::string::npos)
66
+ << "Input string must contain $";
67
+ s.replace(expected_characters_matched, 1, "");
68
+
69
+ ParsedFloat parsed =
70
+ ParseFloat<base>(s.data(), s.data() + s.size(), format_flags);
71
+
72
+ EXPECT_NE(parsed.end, nullptr);
73
+ if (parsed.end == nullptr) {
74
+ return; // The following tests are not useful if we fully failed to parse
75
+ }
76
+ EXPECT_EQ(parsed.type, expected_type);
77
+ if (begin_subrange == -1) {
78
+ EXPECT_EQ(parsed.subrange_begin, nullptr);
79
+ EXPECT_EQ(parsed.subrange_end, nullptr);
80
+ } else {
81
+ EXPECT_EQ(parsed.subrange_begin, s.data() + begin_subrange);
82
+ EXPECT_EQ(parsed.subrange_end, s.data() + end_subrange);
83
+ }
84
+ if (parsed.type == FloatType::kNumber) {
85
+ EXPECT_EQ(parsed.mantissa, expected_mantissa);
86
+ EXPECT_EQ(parsed.exponent, expected_exponent);
87
+ if (expected_literal_exponent != -999) {
88
+ EXPECT_EQ(parsed.literal_exponent, expected_literal_exponent);
89
+ }
90
+ }
91
+ auto characters_matched = static_cast<int>(parsed.end - s.data());
92
+ EXPECT_EQ(characters_matched, expected_characters_matched);
93
+ }
94
+
95
+ // Check that a given string input is parsed to the expected mantissa and
96
+ // exponent.
97
+ //
98
+ // Input string `s` must contain a '$' character. It marks the end of the
99
+ // characters that were consumed by the match.
100
+ template <int base>
101
+ void ExpectNumber(std::string s, absl::chars_format format_flags,
102
+ uint64_t expected_mantissa, int expected_exponent,
103
+ int expected_literal_exponent = -999) {
104
+ ExpectParsedFloat<base>(std::move(s), format_flags, FloatType::kNumber,
105
+ expected_mantissa, expected_exponent,
106
+ expected_literal_exponent);
107
+ }
108
+
109
+ // Check that a given string input is parsed to the given special value.
110
+ //
111
+ // This tests against both number bases, since infinities and NaNs have
112
+ // identical representations in both modes.
113
+ void ExpectSpecial(const std::string& s, absl::chars_format format_flags,
114
+ FloatType type) {
115
+ ExpectParsedFloat<10>(s, format_flags, type, 0, 0);
116
+ ExpectParsedFloat<16>(s, format_flags, type, 0, 0);
117
+ }
118
+
119
+ // Check that a given input string is not matched by Float.
120
+ template <int base>
121
+ void ExpectFailedParse(absl::string_view s, absl::chars_format format_flags) {
122
+ ParsedFloat parsed =
123
+ ParseFloat<base>(s.data(), s.data() + s.size(), format_flags);
124
+ EXPECT_EQ(parsed.end, nullptr);
125
+ }
126
+
127
+ TEST(ParseFloat, SimpleValue) {
128
+ // Test that various forms of floating point numbers all parse correctly.
129
+ ExpectNumber<10>("1.23456789e5$", chars_format::general, 123456789, -3);
130
+ ExpectNumber<10>("1.23456789e+5$", chars_format::general, 123456789, -3);
131
+ ExpectNumber<10>("1.23456789E5$", chars_format::general, 123456789, -3);
132
+ ExpectNumber<10>("1.23456789e05$", chars_format::general, 123456789, -3);
133
+ ExpectNumber<10>("123.456789e3$", chars_format::general, 123456789, -3);
134
+ ExpectNumber<10>("0.000123456789e9$", chars_format::general, 123456789, -3);
135
+ ExpectNumber<10>("123456.789$", chars_format::general, 123456789, -3);
136
+ ExpectNumber<10>("123456789e-3$", chars_format::general, 123456789, -3);
137
+
138
+ ExpectNumber<16>("1.234abcdefp28$", chars_format::general, 0x1234abcdef, -8);
139
+ ExpectNumber<16>("1.234abcdefp+28$", chars_format::general, 0x1234abcdef, -8);
140
+ ExpectNumber<16>("1.234ABCDEFp28$", chars_format::general, 0x1234abcdef, -8);
141
+ ExpectNumber<16>("1.234AbCdEfP0028$", chars_format::general, 0x1234abcdef,
142
+ -8);
143
+ ExpectNumber<16>("123.4abcdefp20$", chars_format::general, 0x1234abcdef, -8);
144
+ ExpectNumber<16>("0.0001234abcdefp44$", chars_format::general, 0x1234abcdef,
145
+ -8);
146
+ ExpectNumber<16>("1234abcd.ef$", chars_format::general, 0x1234abcdef, -8);
147
+ ExpectNumber<16>("1234abcdefp-8$", chars_format::general, 0x1234abcdef, -8);
148
+
149
+ // ExpectNumber does not attempt to drop trailing zeroes.
150
+ ExpectNumber<10>("0001.2345678900e005$", chars_format::general, 12345678900,
151
+ -5);
152
+ ExpectNumber<16>("0001.234abcdef000p28$", chars_format::general,
153
+ 0x1234abcdef000, -20);
154
+
155
+ // Ensure non-matching characters after a number are ignored, even when they
156
+ // look like potentially matching characters.
157
+ ExpectNumber<10>("1.23456789e5$ ", chars_format::general, 123456789, -3);
158
+ ExpectNumber<10>("1.23456789e5$e5e5", chars_format::general, 123456789, -3);
159
+ ExpectNumber<10>("1.23456789e5$.25", chars_format::general, 123456789, -3);
160
+ ExpectNumber<10>("1.23456789e5$-", chars_format::general, 123456789, -3);
161
+ ExpectNumber<10>("1.23456789e5$PUPPERS!!!", chars_format::general, 123456789,
162
+ -3);
163
+ ExpectNumber<10>("123456.789$efghij", chars_format::general, 123456789, -3);
164
+ ExpectNumber<10>("123456.789$e", chars_format::general, 123456789, -3);
165
+ ExpectNumber<10>("123456.789$p5", chars_format::general, 123456789, -3);
166
+ ExpectNumber<10>("123456.789$.10", chars_format::general, 123456789, -3);
167
+
168
+ ExpectNumber<16>("1.234abcdefp28$ ", chars_format::general, 0x1234abcdef,
169
+ -8);
170
+ ExpectNumber<16>("1.234abcdefp28$p28", chars_format::general, 0x1234abcdef,
171
+ -8);
172
+ ExpectNumber<16>("1.234abcdefp28$.125", chars_format::general, 0x1234abcdef,
173
+ -8);
174
+ ExpectNumber<16>("1.234abcdefp28$-", chars_format::general, 0x1234abcdef, -8);
175
+ ExpectNumber<16>("1.234abcdefp28$KITTEHS!!!", chars_format::general,
176
+ 0x1234abcdef, -8);
177
+ ExpectNumber<16>("1234abcd.ef$ghijk", chars_format::general, 0x1234abcdef,
178
+ -8);
179
+ ExpectNumber<16>("1234abcd.ef$p", chars_format::general, 0x1234abcdef, -8);
180
+ ExpectNumber<16>("1234abcd.ef$.10", chars_format::general, 0x1234abcdef, -8);
181
+
182
+ // Ensure we can read a full resolution mantissa without overflow.
183
+ ExpectNumber<10>("9999999999999999999$", chars_format::general,
184
+ 9999999999999999999u, 0);
185
+ ExpectNumber<16>("fffffffffffffff$", chars_format::general,
186
+ 0xfffffffffffffffu, 0);
187
+
188
+ // Check that zero is consistently read.
189
+ ExpectNumber<10>("0$", chars_format::general, 0, 0);
190
+ ExpectNumber<16>("0$", chars_format::general, 0, 0);
191
+ ExpectNumber<10>("000000000000000000000000000000000000000$",
192
+ chars_format::general, 0, 0);
193
+ ExpectNumber<16>("000000000000000000000000000000000000000$",
194
+ chars_format::general, 0, 0);
195
+ ExpectNumber<10>("0000000000000000000000.000000000000000000$",
196
+ chars_format::general, 0, 0);
197
+ ExpectNumber<16>("0000000000000000000000.000000000000000000$",
198
+ chars_format::general, 0, 0);
199
+ ExpectNumber<10>("0.00000000000000000000000000000000e123456$",
200
+ chars_format::general, 0, 0);
201
+ ExpectNumber<16>("0.00000000000000000000000000000000p123456$",
202
+ chars_format::general, 0, 0);
203
+ }
204
+
205
+ TEST(ParseFloat, LargeDecimalMantissa) {
206
+ // After 19 significant decimal digits in the mantissa, ParsedFloat will
207
+ // truncate additional digits. We need to test that:
208
+ // 1) the truncation to 19 digits happens
209
+ // 2) the returned exponent reflects the dropped significant digits
210
+ // 3) a correct literal_exponent is set
211
+ //
212
+ // If and only if a significant digit is found after 19 digits, then the
213
+ // entirety of the mantissa in case the exact value is needed to make a
214
+ // rounding decision. The [ and ] characters below denote where such a
215
+ // subregion was marked by by ParseFloat. They are not part of the input.
216
+
217
+ // Mark a capture group only if a dropped digit is significant (nonzero).
218
+ ExpectNumber<10>("100000000000000000000000000$", chars_format::general,
219
+ 1000000000000000000,
220
+ /* adjusted exponent */ 8);
221
+
222
+ ExpectNumber<10>("123456789123456789100000000$", chars_format::general,
223
+ 1234567891234567891,
224
+ /* adjusted exponent */ 8);
225
+
226
+ ExpectNumber<10>("[123456789123456789123456789]$", chars_format::general,
227
+ 1234567891234567891,
228
+ /* adjusted exponent */ 8,
229
+ /* literal exponent */ 0);
230
+
231
+ ExpectNumber<10>("[123456789123456789100000009]$", chars_format::general,
232
+ 1234567891234567891,
233
+ /* adjusted exponent */ 8,
234
+ /* literal exponent */ 0);
235
+
236
+ ExpectNumber<10>("[123456789123456789120000000]$", chars_format::general,
237
+ 1234567891234567891,
238
+ /* adjusted exponent */ 8,
239
+ /* literal exponent */ 0);
240
+
241
+ // Leading zeroes should not count towards the 19 significant digit limit
242
+ ExpectNumber<10>("[00000000123456789123456789123456789]$",
243
+ chars_format::general, 1234567891234567891,
244
+ /* adjusted exponent */ 8,
245
+ /* literal exponent */ 0);
246
+
247
+ ExpectNumber<10>("00000000123456789123456789100000000$",
248
+ chars_format::general, 1234567891234567891,
249
+ /* adjusted exponent */ 8);
250
+
251
+ // Truncated digits after the decimal point should not cause a further
252
+ // exponent adjustment.
253
+ ExpectNumber<10>("1.234567891234567891e123$", chars_format::general,
254
+ 1234567891234567891, 105);
255
+ ExpectNumber<10>("[1.23456789123456789123456789]e123$", chars_format::general,
256
+ 1234567891234567891,
257
+ /* adjusted exponent */ 105,
258
+ /* literal exponent */ 123);
259
+
260
+ // Ensure we truncate, and not round. (The from_chars algorithm we use
261
+ // depends on our guess missing low, if it misses, so we need the rounding
262
+ // error to be downward.)
263
+ ExpectNumber<10>("[1999999999999999999999]$", chars_format::general,
264
+ 1999999999999999999,
265
+ /* adjusted exponent */ 3,
266
+ /* literal exponent */ 0);
267
+ }
268
+
269
+ TEST(ParseFloat, LargeHexadecimalMantissa) {
270
+ // After 15 significant hex digits in the mantissa, ParsedFloat will treat
271
+ // additional digits as sticky, We need to test that:
272
+ // 1) The truncation to 15 digits happens
273
+ // 2) The returned exponent reflects the dropped significant digits
274
+ // 3) If a nonzero digit is dropped, the low bit of mantissa is set.
275
+
276
+ ExpectNumber<16>("123456789abcdef123456789abcdef$", chars_format::general,
277
+ 0x123456789abcdef, 60);
278
+
279
+ // Leading zeroes should not count towards the 15 significant digit limit
280
+ ExpectNumber<16>("000000123456789abcdef123456789abcdef$",
281
+ chars_format::general, 0x123456789abcdef, 60);
282
+
283
+ // Truncated digits after the radix point should not cause a further
284
+ // exponent adjustment.
285
+ ExpectNumber<16>("1.23456789abcdefp100$", chars_format::general,
286
+ 0x123456789abcdef, 44);
287
+ ExpectNumber<16>("1.23456789abcdef123456789abcdefp100$",
288
+ chars_format::general, 0x123456789abcdef, 44);
289
+
290
+ // test sticky digit behavior. The low bit should be set iff any dropped
291
+ // digit is nonzero.
292
+ ExpectNumber<16>("123456789abcdee123456789abcdee$", chars_format::general,
293
+ 0x123456789abcdef, 60);
294
+ ExpectNumber<16>("123456789abcdee000000000000001$", chars_format::general,
295
+ 0x123456789abcdef, 60);
296
+ ExpectNumber<16>("123456789abcdee000000000000000$", chars_format::general,
297
+ 0x123456789abcdee, 60);
298
+ }
299
+
300
+ TEST(ParseFloat, ScientificVsFixed) {
301
+ // In fixed mode, an exponent is never matched (but the remainder of the
302
+ // number will be matched.)
303
+ ExpectNumber<10>("1.23456789$e5", chars_format::fixed, 123456789, -8);
304
+ ExpectNumber<10>("123456.789$", chars_format::fixed, 123456789, -3);
305
+ ExpectNumber<16>("1.234abcdef$p28", chars_format::fixed, 0x1234abcdef, -36);
306
+ ExpectNumber<16>("1234abcd.ef$", chars_format::fixed, 0x1234abcdef, -8);
307
+
308
+ // In scientific mode, numbers don't match *unless* they have an exponent.
309
+ ExpectNumber<10>("1.23456789e5$", chars_format::scientific, 123456789, -3);
310
+ ExpectFailedParse<10>("-123456.789$", chars_format::scientific);
311
+ ExpectNumber<16>("1.234abcdefp28$", chars_format::scientific, 0x1234abcdef,
312
+ -8);
313
+ ExpectFailedParse<16>("1234abcd.ef$", chars_format::scientific);
314
+ }
315
+
316
+ TEST(ParseFloat, Infinity) {
317
+ ExpectFailedParse<10>("in", chars_format::general);
318
+ ExpectFailedParse<16>("in", chars_format::general);
319
+ ExpectFailedParse<10>("inx", chars_format::general);
320
+ ExpectFailedParse<16>("inx", chars_format::general);
321
+ ExpectSpecial("inf$", chars_format::general, FloatType::kInfinity);
322
+ ExpectSpecial("Inf$", chars_format::general, FloatType::kInfinity);
323
+ ExpectSpecial("INF$", chars_format::general, FloatType::kInfinity);
324
+ ExpectSpecial("inf$inite", chars_format::general, FloatType::kInfinity);
325
+ ExpectSpecial("iNfInItY$", chars_format::general, FloatType::kInfinity);
326
+ ExpectSpecial("infinity$!!!", chars_format::general, FloatType::kInfinity);
327
+ }
328
+
329
+ TEST(ParseFloat, NaN) {
330
+ ExpectFailedParse<10>("na", chars_format::general);
331
+ ExpectFailedParse<16>("na", chars_format::general);
332
+ ExpectFailedParse<10>("nah", chars_format::general);
333
+ ExpectFailedParse<16>("nah", chars_format::general);
334
+ ExpectSpecial("nan$", chars_format::general, FloatType::kNan);
335
+ ExpectSpecial("NaN$", chars_format::general, FloatType::kNan);
336
+ ExpectSpecial("nAn$", chars_format::general, FloatType::kNan);
337
+ ExpectSpecial("NAN$", chars_format::general, FloatType::kNan);
338
+ ExpectSpecial("NaN$aNaNaNaNaBatman!", chars_format::general, FloatType::kNan);
339
+
340
+ // A parenthesized sequence of the characters [a-zA-Z0-9_] is allowed to
341
+ // appear after an NaN. Check that this is allowed, and that the correct
342
+ // characters are grouped.
343
+ //
344
+ // (The characters [ and ] in the pattern below delimit the expected matched
345
+ // subgroup; they are not part of the input passed to ParseFloat.)
346
+ ExpectSpecial("nan([0xabcdef])$", chars_format::general, FloatType::kNan);
347
+ ExpectSpecial("nan([0xabcdef])$...", chars_format::general, FloatType::kNan);
348
+ ExpectSpecial("nan([0xabcdef])$)...", chars_format::general, FloatType::kNan);
349
+ ExpectSpecial("nan([])$", chars_format::general, FloatType::kNan);
350
+ ExpectSpecial("nan([aAzZ09_])$", chars_format::general, FloatType::kNan);
351
+ // If the subgroup contains illegal characters, don't match it at all.
352
+ ExpectSpecial("nan$(bad-char)", chars_format::general, FloatType::kNan);
353
+ // Also cope with a missing close paren.
354
+ ExpectSpecial("nan$(0xabcdef", chars_format::general, FloatType::kNan);
355
+ }
356
+
357
+ } // namespace
weight/_dep/abseil-cpp/absl/strings/internal/cord_data_edge_test.cc ADDED
@@ -0,0 +1,130 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Copyright 2022 The Abseil Authors
2
+ //
3
+ // Licensed under the Apache License, Version 2.0 (the "License");
4
+ // you may not use this file except in compliance with the License.
5
+ // You may obtain a copy of the License at
6
+ //
7
+ // https://www.apache.org/licenses/LICENSE-2.0
8
+ //
9
+ // Unless required by applicable law or agreed to in writing, software
10
+ // distributed under the License is distributed on an "AS IS" BASIS,
11
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ // See the License for the specific language governing permissions and
13
+ // limitations under the License.
14
+
15
+ #include "absl/strings/internal/cord_data_edge.h"
16
+
17
+ #include "gmock/gmock.h"
18
+ #include "gtest/gtest.h"
19
+ #include "absl/strings/internal/cord_internal.h"
20
+ #include "absl/strings/internal/cord_rep_test_util.h"
21
+
22
+ namespace absl {
23
+ ABSL_NAMESPACE_BEGIN
24
+ namespace cord_internal {
25
+ namespace {
26
+
27
+ using ::absl::cordrep_testing::MakeExternal;
28
+ using ::absl::cordrep_testing::MakeFlat;
29
+ using ::absl::cordrep_testing::MakeSubstring;
30
+
31
+ TEST(CordDataEdgeTest, IsDataEdgeOnFlat) {
32
+ CordRep* rep = MakeFlat("Lorem ipsum dolor sit amet, consectetur ...");
33
+ EXPECT_TRUE(IsDataEdge(rep));
34
+ CordRep::Unref(rep);
35
+ }
36
+
37
+ TEST(CordDataEdgeTest, IsDataEdgeOnExternal) {
38
+ CordRep* rep = MakeExternal("Lorem ipsum dolor sit amet, consectetur ...");
39
+ EXPECT_TRUE(IsDataEdge(rep));
40
+ CordRep::Unref(rep);
41
+ }
42
+
43
+ TEST(CordDataEdgeTest, IsDataEdgeOnSubstringOfFlat) {
44
+ CordRep* rep = MakeFlat("Lorem ipsum dolor sit amet, consectetur ...");
45
+ CordRep* substr = MakeSubstring(1, 20, rep);
46
+ EXPECT_TRUE(IsDataEdge(substr));
47
+ CordRep::Unref(substr);
48
+ }
49
+
50
+ TEST(CordDataEdgeTest, IsDataEdgeOnSubstringOfExternal) {
51
+ CordRep* rep = MakeExternal("Lorem ipsum dolor sit amet, consectetur ...");
52
+ CordRep* substr = MakeSubstring(1, 20, rep);
53
+ EXPECT_TRUE(IsDataEdge(substr));
54
+ CordRep::Unref(substr);
55
+ }
56
+
57
+ TEST(CordDataEdgeTest, IsDataEdgeOnBtree) {
58
+ CordRep* rep = MakeFlat("Lorem ipsum dolor sit amet, consectetur ...");
59
+ CordRepBtree* tree = CordRepBtree::New(rep);
60
+ EXPECT_FALSE(IsDataEdge(tree));
61
+ CordRep::Unref(tree);
62
+ }
63
+
64
+ TEST(CordDataEdgeTest, IsDataEdgeOnBadSubstr) {
65
+ CordRep* rep = MakeFlat("Lorem ipsum dolor sit amet, consectetur ...");
66
+ CordRep* substr = MakeSubstring(1, 18, MakeSubstring(1, 20, rep));
67
+ EXPECT_FALSE(IsDataEdge(substr));
68
+ CordRep::Unref(substr);
69
+ }
70
+
71
+ TEST(CordDataEdgeTest, EdgeDataOnFlat) {
72
+ absl::string_view value = "Lorem ipsum dolor sit amet, consectetur ...";
73
+ CordRep* rep = MakeFlat(value);
74
+ EXPECT_EQ(EdgeData(rep), value);
75
+ CordRep::Unref(rep);
76
+ }
77
+
78
+ TEST(CordDataEdgeTest, EdgeDataOnExternal) {
79
+ absl::string_view value = "Lorem ipsum dolor sit amet, consectetur ...";
80
+ CordRep* rep = MakeExternal(value);
81
+ EXPECT_EQ(EdgeData(rep), value);
82
+ CordRep::Unref(rep);
83
+ }
84
+
85
+ TEST(CordDataEdgeTest, EdgeDataOnSubstringOfFlat) {
86
+ absl::string_view value = "Lorem ipsum dolor sit amet, consectetur ...";
87
+ CordRep* rep = MakeFlat(value);
88
+ CordRep* substr = MakeSubstring(1, 20, rep);
89
+ EXPECT_EQ(EdgeData(substr), value.substr(1, 20));
90
+ CordRep::Unref(substr);
91
+ }
92
+
93
+ TEST(CordDataEdgeTest, EdgeDataOnSubstringOfExternal) {
94
+ absl::string_view value = "Lorem ipsum dolor sit amet, consectetur ...";
95
+ CordRep* rep = MakeExternal(value);
96
+ CordRep* substr = MakeSubstring(1, 20, rep);
97
+ EXPECT_EQ(EdgeData(substr), value.substr(1, 20));
98
+ CordRep::Unref(substr);
99
+ }
100
+
101
+ #if defined(GTEST_HAS_DEATH_TEST) && !defined(NDEBUG)
102
+
103
+ TEST(CordDataEdgeTest, IsDataEdgeOnNullPtr) {
104
+ EXPECT_DEATH(IsDataEdge(nullptr), ".*");
105
+ }
106
+
107
+ TEST(CordDataEdgeTest, EdgeDataOnNullPtr) {
108
+ EXPECT_DEATH(EdgeData(nullptr), ".*");
109
+ }
110
+
111
+ TEST(CordDataEdgeTest, EdgeDataOnBtree) {
112
+ CordRep* rep = MakeFlat("Lorem ipsum dolor sit amet, consectetur ...");
113
+ CordRepBtree* tree = CordRepBtree::New(rep);
114
+ EXPECT_DEATH(EdgeData(tree), ".*");
115
+ CordRep::Unref(tree);
116
+ }
117
+
118
+ TEST(CordDataEdgeTest, EdgeDataOnBadSubstr) {
119
+ CordRep* rep = MakeFlat("Lorem ipsum dolor sit amet, consectetur ...");
120
+ CordRep* substr = MakeSubstring(1, 18, MakeSubstring(1, 20, rep));
121
+ EXPECT_DEATH(EdgeData(substr), ".*");
122
+ CordRep::Unref(substr);
123
+ }
124
+
125
+ #endif // GTEST_HAS_DEATH_TEST && !NDEBUG
126
+
127
+ } // namespace
128
+ } // namespace cord_internal
129
+ ABSL_NAMESPACE_END
130
+ } // namespace absl
weight/_dep/abseil-cpp/absl/strings/internal/cord_rep_btree.cc ADDED
@@ -0,0 +1,1241 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Copyright 2021 The Abseil Authors
2
+ //
3
+ // Licensed under the Apache License, Version 2.0 (the "License");
4
+ // you may not use this file except in compliance with the License.
5
+ // You may obtain a copy of the License at
6
+ //
7
+ // https://www.apache.org/licenses/LICENSE-2.0
8
+ //
9
+ // Unless required by applicable law or agreed to in writing, software
10
+ // distributed under the License is distributed on an "AS IS" BASIS,
11
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ // See the License for the specific language governing permissions and
13
+ // limitations under the License.
14
+
15
+ #include "absl/strings/internal/cord_rep_btree.h"
16
+
17
+ #include <atomic>
18
+ #include <cassert>
19
+ #include <cstdint>
20
+ #include <iostream>
21
+ #include <ostream>
22
+ #include <string>
23
+
24
+ #include "absl/base/attributes.h"
25
+ #include "absl/base/config.h"
26
+ #include "absl/base/internal/raw_logging.h"
27
+ #include "absl/base/optimization.h"
28
+ #include "absl/strings/internal/cord_data_edge.h"
29
+ #include "absl/strings/internal/cord_internal.h"
30
+ #include "absl/strings/internal/cord_rep_consume.h"
31
+ #include "absl/strings/internal/cord_rep_flat.h"
32
+ #include "absl/strings/str_cat.h"
33
+ #include "absl/strings/string_view.h"
34
+
35
+ namespace absl {
36
+ ABSL_NAMESPACE_BEGIN
37
+ namespace cord_internal {
38
+
39
+ #ifdef ABSL_INTERNAL_NEED_REDUNDANT_CONSTEXPR_DECL
40
+ constexpr size_t CordRepBtree::kMaxCapacity;
41
+ #endif
42
+
43
+ namespace {
44
+
45
+ using NodeStack = CordRepBtree * [CordRepBtree::kMaxDepth];
46
+ using EdgeType = CordRepBtree::EdgeType;
47
+ using OpResult = CordRepBtree::OpResult;
48
+ using CopyResult = CordRepBtree::CopyResult;
49
+
50
+ constexpr auto kFront = CordRepBtree::kFront;
51
+ constexpr auto kBack = CordRepBtree::kBack;
52
+
53
+ ABSL_CONST_INIT std::atomic<bool> cord_btree_exhaustive_validation(false);
54
+
55
+ // Implementation of the various 'Dump' functions.
56
+ // Prints the entire tree structure or 'rep'. External callers should
57
+ // not specify 'depth' and leave it to its default (0) value.
58
+ // Rep may be a CordRepBtree tree, or a SUBSTRING / EXTERNAL / FLAT node.
59
+ void DumpAll(const CordRep* rep,
60
+ bool include_contents,
61
+ std::ostream& stream,
62
+ size_t depth = 0) {
63
+ // Allow for full height trees + substring -> flat / external nodes.
64
+ assert(depth <= CordRepBtree::kMaxDepth + 2);
65
+ std::string sharing = const_cast<CordRep*>(rep)->refcount.IsOne()
66
+ ? std::string("Private")
67
+ : absl::StrCat("Shared(", rep->refcount.Get(), ")");
68
+ std::string sptr = absl::StrCat("0x", absl::Hex(rep));
69
+
70
+ // Dumps the data contents of `rep` if `include_contents` is true.
71
+ // Always emits a new line character.
72
+ auto maybe_dump_data = [&stream, include_contents](const CordRep* r) {
73
+ if (include_contents) {
74
+ // Allow for up to 60 wide display of content data, which with some
75
+ // indentation and prefix / labels keeps us within roughly 80-100 wide.
76
+ constexpr size_t kMaxDataLength = 60;
77
+ stream << ", data = \""
78
+ << EdgeData(r).substr(0, kMaxDataLength)
79
+ << (r->length > kMaxDataLength ? "\"..." : "\"");
80
+ }
81
+ stream << '\n';
82
+ };
83
+
84
+ // For each level, we print the 'shared/private' state and the rep pointer,
85
+ // indented by two spaces per recursive depth.
86
+ stream << std::string(depth * 2, ' ') << sharing << " (" << sptr << ") ";
87
+
88
+ if (rep->IsBtree()) {
89
+ const CordRepBtree* node = rep->btree();
90
+ std::string label =
91
+ node->height() ? absl::StrCat("Node(", node->height(), ")") : "Leaf";
92
+ stream << label << ", len = " << node->length
93
+ << ", begin = " << node->begin() << ", end = " << node->end()
94
+ << "\n";
95
+ for (CordRep* edge : node->Edges()) {
96
+ DumpAll(edge, include_contents, stream, depth + 1);
97
+ }
98
+ } else if (rep->tag == SUBSTRING) {
99
+ const CordRepSubstring* substring = rep->substring();
100
+ stream << "Substring, len = " << rep->length
101
+ << ", start = " << substring->start;
102
+ maybe_dump_data(rep);
103
+ DumpAll(substring->child, include_contents, stream, depth + 1);
104
+ } else if (rep->tag >= FLAT) {
105
+ stream << "Flat, len = " << rep->length
106
+ << ", cap = " << rep->flat()->Capacity();
107
+ maybe_dump_data(rep);
108
+ } else if (rep->tag == EXTERNAL) {
109
+ stream << "Extn, len = " << rep->length;
110
+ maybe_dump_data(rep);
111
+ }
112
+ }
113
+
114
+ // TODO(b/192061034): add 'bytes to copy' logic to avoid large slop on substring
115
+ // small data out of large reps, and general efficiency of 'always copy small
116
+ // data'. Consider making this a cord rep internal library function.
117
+ CordRepSubstring* CreateSubstring(CordRep* rep, size_t offset, size_t n) {
118
+ assert(n != 0);
119
+ assert(offset + n <= rep->length);
120
+ assert(offset != 0 || n != rep->length);
121
+
122
+ if (rep->tag == SUBSTRING) {
123
+ CordRepSubstring* substring = rep->substring();
124
+ offset += substring->start;
125
+ rep = CordRep::Ref(substring->child);
126
+ CordRep::Unref(substring);
127
+ }
128
+ assert(rep->IsExternal() || rep->IsFlat());
129
+ CordRepSubstring* substring = new CordRepSubstring();
130
+ substring->length = n;
131
+ substring->tag = SUBSTRING;
132
+ substring->start = offset;
133
+ substring->child = rep;
134
+ return substring;
135
+ }
136
+
137
+ // TODO(b/192061034): consider making this a cord rep library function.
138
+ inline CordRep* MakeSubstring(CordRep* rep, size_t offset, size_t n) {
139
+ if (n == rep->length) return rep;
140
+ if (n == 0) return CordRep::Unref(rep), nullptr;
141
+ return CreateSubstring(rep, offset, n);
142
+ }
143
+
144
+ // TODO(b/192061034): consider making this a cord rep library function.
145
+ inline CordRep* MakeSubstring(CordRep* rep, size_t offset) {
146
+ if (offset == 0) return rep;
147
+ return CreateSubstring(rep, offset, rep->length - offset);
148
+ }
149
+
150
+ // Resizes `edge` to the provided `length`. Adopts a reference on `edge`.
151
+ // This method directly returns `edge` if `length` equals `edge->length`.
152
+ // If `is_mutable` is set to true, this function may return `edge` with
153
+ // `edge->length` set to the new length depending on the type and size of
154
+ // `edge`. Otherwise, this function returns a new CordRepSubstring value.
155
+ // Requires `length > 0 && length <= edge->length`.
156
+ CordRep* ResizeEdge(CordRep* edge, size_t length, bool is_mutable) {
157
+ assert(length > 0);
158
+ assert(length <= edge->length);
159
+ assert(IsDataEdge(edge));
160
+ if (length >= edge->length) return edge;
161
+
162
+ if (is_mutable && (edge->tag >= FLAT || edge->tag == SUBSTRING)) {
163
+ edge->length = length;
164
+ return edge;
165
+ }
166
+
167
+ return CreateSubstring(edge, 0, length);
168
+ }
169
+
170
+ template <EdgeType edge_type>
171
+ inline absl::string_view Consume(absl::string_view s, size_t n) {
172
+ return edge_type == kBack ? s.substr(n) : s.substr(0, s.size() - n);
173
+ }
174
+
175
+ template <EdgeType edge_type>
176
+ inline absl::string_view Consume(char* dst, absl::string_view s, size_t n) {
177
+ if (edge_type == kBack) {
178
+ memcpy(dst, s.data(), n);
179
+ return s.substr(n);
180
+ } else {
181
+ const size_t offset = s.size() - n;
182
+ memcpy(dst, s.data() + offset, n);
183
+ return s.substr(0, offset);
184
+ }
185
+ }
186
+
187
+ // Known issue / optimization weirdness: the store associated with the
188
+ // decrement introduces traffic between cpus (even if the result of that
189
+ // traffic does nothing), making this faster than a single call to
190
+ // refcount.Decrement() checking the zero refcount condition.
191
+ template <typename R, typename Fn>
192
+ inline void FastUnref(R* r, Fn&& fn) {
193
+ if (r->refcount.IsOne()) {
194
+ fn(r);
195
+ } else if (!r->refcount.DecrementExpectHighRefcount()) {
196
+ fn(r);
197
+ }
198
+ }
199
+
200
+
201
+ void DeleteSubstring(CordRepSubstring* substring) {
202
+ CordRep* rep = substring->child;
203
+ if (!rep->refcount.Decrement()) {
204
+ if (rep->tag >= FLAT) {
205
+ CordRepFlat::Delete(rep->flat());
206
+ } else {
207
+ assert(rep->tag == EXTERNAL);
208
+ CordRepExternal::Delete(rep->external());
209
+ }
210
+ }
211
+ delete substring;
212
+ }
213
+
214
+ // Deletes a leaf node data edge. Requires `IsDataEdge(rep)`.
215
+ void DeleteLeafEdge(CordRep* rep) {
216
+ assert(IsDataEdge(rep));
217
+ if (rep->tag >= FLAT) {
218
+ CordRepFlat::Delete(rep->flat());
219
+ } else if (rep->tag == EXTERNAL) {
220
+ CordRepExternal::Delete(rep->external());
221
+ } else {
222
+ DeleteSubstring(rep->substring());
223
+ }
224
+ }
225
+
226
+ // StackOperations contains the logic to build a left-most or right-most stack
227
+ // (leg) down to the leaf level of a btree, and 'unwind' / 'Finalize' methods to
228
+ // propagate node changes up the stack.
229
+ template <EdgeType edge_type>
230
+ struct StackOperations {
231
+ // Returns true if the node at 'depth' is not shared, i.e. has a refcount
232
+ // of one and all of its parent nodes have a refcount of one.
233
+ inline bool owned(int depth) const { return depth < share_depth; }
234
+
235
+ // Returns the node at 'depth'.
236
+ inline CordRepBtree* node(int depth) const { return stack[depth]; }
237
+
238
+ // Builds a `depth` levels deep stack starting at `tree` recording which nodes
239
+ // are private in the form of the 'share depth' where nodes are shared.
240
+ inline CordRepBtree* BuildStack(CordRepBtree* tree, int depth) {
241
+ assert(depth <= tree->height());
242
+ int current_depth = 0;
243
+ while (current_depth < depth && tree->refcount.IsOne()) {
244
+ stack[current_depth++] = tree;
245
+ tree = tree->Edge(edge_type)->btree();
246
+ }
247
+ share_depth = current_depth + (tree->refcount.IsOne() ? 1 : 0);
248
+ while (current_depth < depth) {
249
+ stack[current_depth++] = tree;
250
+ tree = tree->Edge(edge_type)->btree();
251
+ }
252
+ return tree;
253
+ }
254
+
255
+ // Builds a stack with the invariant that all nodes are private owned / not
256
+ // shared. This is used in iterative updates where a previous propagation
257
+ // guaranteed all nodes are owned / private.
258
+ inline void BuildOwnedStack(CordRepBtree* tree, int height) {
259
+ assert(height <= CordRepBtree::kMaxHeight);
260
+ int depth = 0;
261
+ while (depth < height) {
262
+ assert(tree->refcount.IsOne());
263
+ stack[depth++] = tree;
264
+ tree = tree->Edge(edge_type)->btree();
265
+ }
266
+ assert(tree->refcount.IsOne());
267
+ share_depth = depth + 1;
268
+ }
269
+
270
+ // Processes the final 'top level' result action for the tree.
271
+ // See the 'Action' enum for the various action implications.
272
+ static inline CordRepBtree* Finalize(CordRepBtree* tree, OpResult result) {
273
+ switch (result.action) {
274
+ case CordRepBtree::kPopped:
275
+ tree = edge_type == kBack ? CordRepBtree::New(tree, result.tree)
276
+ : CordRepBtree::New(result.tree, tree);
277
+ if (ABSL_PREDICT_FALSE(tree->height() > CordRepBtree::kMaxHeight)) {
278
+ tree = CordRepBtree::Rebuild(tree);
279
+ ABSL_RAW_CHECK(tree->height() <= CordRepBtree::kMaxHeight,
280
+ "Max height exceeded");
281
+ }
282
+ return tree;
283
+ case CordRepBtree::kCopied:
284
+ CordRep::Unref(tree);
285
+ ABSL_FALLTHROUGH_INTENDED;
286
+ case CordRepBtree::kSelf:
287
+ return result.tree;
288
+ }
289
+ ABSL_UNREACHABLE();
290
+ return result.tree;
291
+ }
292
+
293
+ // Propagate the action result in 'result' up into all nodes of the stack
294
+ // starting at depth 'depth'. 'length' contains the extra length of data that
295
+ // was added at the lowest level, and is updated into all nodes of the stack.
296
+ // See the 'Action' enum for the various action implications.
297
+ // If 'propagate' is true, then any copied node values are updated into the
298
+ // stack, which is used for iterative processing on the same stack.
299
+ template <bool propagate = false>
300
+ inline CordRepBtree* Unwind(CordRepBtree* tree, int depth, size_t length,
301
+ OpResult result) {
302
+ // TODO(mvels): revisit the below code to check if 3 loops with 3
303
+ // (incremental) conditions is faster than 1 loop with a switch.
304
+ // Benchmarking and perf recordings indicate the loop with switch is
305
+ // fastest, likely because of indirect jumps on the tight case values and
306
+ // dense branches. But it's worth considering 3 loops, as the `action`
307
+ // transitions are mono directional. E.g.:
308
+ // while (action == kPopped) {
309
+ // ...
310
+ // }
311
+ // while (action == kCopied) {
312
+ // ...
313
+ // }
314
+ // ...
315
+ // We also found that an "if () do {}" loop here seems faster, possibly
316
+ // because it allows the branch predictor more granular heuristics on
317
+ // 'single leaf' (`depth` == 0) and 'single depth' (`depth` == 1) cases
318
+ // which appear to be the most common use cases.
319
+ if (depth != 0) {
320
+ do {
321
+ CordRepBtree* node = stack[--depth];
322
+ const bool owned = depth < share_depth;
323
+ switch (result.action) {
324
+ case CordRepBtree::kPopped:
325
+ assert(!propagate);
326
+ result = node->AddEdge<edge_type>(owned, result.tree, length);
327
+ break;
328
+ case CordRepBtree::kCopied:
329
+ result = node->SetEdge<edge_type>(owned, result.tree, length);
330
+ if (propagate) stack[depth] = result.tree;
331
+ break;
332
+ case CordRepBtree::kSelf:
333
+ node->length += length;
334
+ while (depth > 0) {
335
+ node = stack[--depth];
336
+ node->length += length;
337
+ }
338
+ return node;
339
+ }
340
+ } while (depth > 0);
341
+ }
342
+ return Finalize(tree, result);
343
+ }
344
+
345
+ // Invokes `Unwind` with `propagate=true` to update the stack node values.
346
+ inline CordRepBtree* Propagate(CordRepBtree* tree, int depth, size_t length,
347
+ OpResult result) {
348
+ return Unwind</*propagate=*/true>(tree, depth, length, result);
349
+ }
350
+
351
+ // `share_depth` contains the depth at which the nodes in the stack become
352
+ // shared. I.e., if the top most level is shared (i.e.: `!refcount.IsOne()`),
353
+ // then `share_depth` is 0. If the 2nd node is shared (and implicitly all
354
+ // nodes below that) then `share_depth` is 1, etc. A `share_depth` greater
355
+ // than the depth of the stack indicates that none of the nodes in the stack
356
+ // are shared.
357
+ int share_depth;
358
+
359
+ NodeStack stack;
360
+ };
361
+
362
+ } // namespace
363
+
364
+ void SetCordBtreeExhaustiveValidation(bool do_exaustive_validation) {
365
+ cord_btree_exhaustive_validation.store(do_exaustive_validation,
366
+ std::memory_order_relaxed);
367
+ }
368
+
369
+ bool IsCordBtreeExhaustiveValidationEnabled() {
370
+ return cord_btree_exhaustive_validation.load(std::memory_order_relaxed);
371
+ }
372
+
373
+ void CordRepBtree::Dump(const CordRep* rep, absl::string_view label,
374
+ bool include_contents, std::ostream& stream) {
375
+ stream << "===================================\n";
376
+ if (!label.empty()) {
377
+ stream << label << '\n';
378
+ stream << "-----------------------------------\n";
379
+ }
380
+ if (rep) {
381
+ DumpAll(rep, include_contents, stream);
382
+ } else {
383
+ stream << "NULL\n";
384
+ }
385
+ }
386
+
387
+ void CordRepBtree::Dump(const CordRep* rep, absl::string_view label,
388
+ std::ostream& stream) {
389
+ Dump(rep, label, false, stream);
390
+ }
391
+
392
+ void CordRepBtree::Dump(const CordRep* rep, std::ostream& stream) {
393
+ Dump(rep, absl::string_view(), false, stream);
394
+ }
395
+
396
+ template <size_t size>
397
+ static void DestroyTree(CordRepBtree* tree) {
398
+ for (CordRep* node : tree->Edges()) {
399
+ if (node->refcount.Decrement()) continue;
400
+ for (CordRep* edge : node->btree()->Edges()) {
401
+ if (edge->refcount.Decrement()) continue;
402
+ if (size == 1) {
403
+ DeleteLeafEdge(edge);
404
+ } else {
405
+ CordRepBtree::Destroy(edge->btree());
406
+ }
407
+ }
408
+ CordRepBtree::Delete(node->btree());
409
+ }
410
+ CordRepBtree::Delete(tree);
411
+ }
412
+
413
+ void CordRepBtree::Destroy(CordRepBtree* tree) {
414
+ switch (tree->height()) {
415
+ case 0:
416
+ for (CordRep* edge : tree->Edges()) {
417
+ if (!edge->refcount.Decrement()) {
418
+ DeleteLeafEdge(edge);
419
+ }
420
+ }
421
+ return CordRepBtree::Delete(tree);
422
+ case 1:
423
+ return DestroyTree<1>(tree);
424
+ default:
425
+ return DestroyTree<2>(tree);
426
+ }
427
+ }
428
+
429
+ bool CordRepBtree::IsValid(const CordRepBtree* tree, bool shallow) {
430
+ #define NODE_CHECK_VALID(x) \
431
+ if (!(x)) { \
432
+ ABSL_RAW_LOG(ERROR, "CordRepBtree::CheckValid() FAILED: %s", #x); \
433
+ return false; \
434
+ }
435
+ #define NODE_CHECK_EQ(x, y) \
436
+ if ((x) != (y)) { \
437
+ ABSL_RAW_LOG(ERROR, \
438
+ "CordRepBtree::CheckValid() FAILED: %s != %s (%s vs %s)", #x, \
439
+ #y, absl::StrCat(x).c_str(), absl::StrCat(y).c_str()); \
440
+ return false; \
441
+ }
442
+
443
+ NODE_CHECK_VALID(tree != nullptr);
444
+ NODE_CHECK_VALID(tree->IsBtree());
445
+ NODE_CHECK_VALID(tree->height() <= kMaxHeight);
446
+ NODE_CHECK_VALID(tree->begin() < tree->capacity());
447
+ NODE_CHECK_VALID(tree->end() <= tree->capacity());
448
+ NODE_CHECK_VALID(tree->begin() <= tree->end());
449
+ size_t child_length = 0;
450
+ for (CordRep* edge : tree->Edges()) {
451
+ NODE_CHECK_VALID(edge != nullptr);
452
+ if (tree->height() > 0) {
453
+ NODE_CHECK_VALID(edge->IsBtree());
454
+ NODE_CHECK_VALID(edge->btree()->height() == tree->height() - 1);
455
+ } else {
456
+ NODE_CHECK_VALID(IsDataEdge(edge));
457
+ }
458
+ child_length += edge->length;
459
+ }
460
+ NODE_CHECK_EQ(child_length, tree->length);
461
+ if ((!shallow || IsCordBtreeExhaustiveValidationEnabled()) &&
462
+ tree->height() > 0) {
463
+ for (CordRep* edge : tree->Edges()) {
464
+ if (!IsValid(edge->btree(), shallow)) return false;
465
+ }
466
+ }
467
+ return true;
468
+
469
+ #undef NODE_CHECK_VALID
470
+ #undef NODE_CHECK_EQ
471
+ }
472
+
473
+ #ifndef NDEBUG
474
+
475
+ CordRepBtree* CordRepBtree::AssertValid(CordRepBtree* tree, bool shallow) {
476
+ if (!IsValid(tree, shallow)) {
477
+ Dump(tree, "CordRepBtree validation failed:", false, std::cout);
478
+ ABSL_RAW_LOG(FATAL, "CordRepBtree::CheckValid() FAILED");
479
+ }
480
+ return tree;
481
+ }
482
+
483
+ const CordRepBtree* CordRepBtree::AssertValid(const CordRepBtree* tree,
484
+ bool shallow) {
485
+ if (!IsValid(tree, shallow)) {
486
+ Dump(tree, "CordRepBtree validation failed:", false, std::cout);
487
+ ABSL_RAW_LOG(FATAL, "CordRepBtree::CheckValid() FAILED");
488
+ }
489
+ return tree;
490
+ }
491
+
492
+ #endif // NDEBUG
493
+
494
+ template <EdgeType edge_type>
495
+ inline OpResult CordRepBtree::AddEdge(bool owned, CordRep* edge, size_t delta) {
496
+ if (size() >= kMaxCapacity) return {New(edge), kPopped};
497
+ OpResult result = ToOpResult(owned);
498
+ result.tree->Add<edge_type>(edge);
499
+ result.tree->length += delta;
500
+ return result;
501
+ }
502
+
503
+ template <EdgeType edge_type>
504
+ OpResult CordRepBtree::SetEdge(bool owned, CordRep* edge, size_t delta) {
505
+ OpResult result;
506
+ const size_t idx = index(edge_type);
507
+ if (owned) {
508
+ result = {this, kSelf};
509
+ CordRep::Unref(edges_[idx]);
510
+ } else {
511
+ // Create a copy containing all unchanged edges. Unchanged edges are the
512
+ // open interval [begin, back) or [begin + 1, end) depending on `edge_type`.
513
+ // We conveniently cover both case using a constexpr `shift` being 0 or 1
514
+ // as `end :== back + 1`.
515
+ result = {CopyRaw(length), kCopied};
516
+ constexpr int shift = edge_type == kFront ? 1 : 0;
517
+ for (CordRep* r : Edges(begin() + shift, back() + shift)) {
518
+ CordRep::Ref(r);
519
+ }
520
+ }
521
+ result.tree->edges_[idx] = edge;
522
+ result.tree->length += delta;
523
+ return result;
524
+ }
525
+
526
+ template <EdgeType edge_type>
527
+ CordRepBtree* CordRepBtree::AddCordRep(CordRepBtree* tree, CordRep* rep) {
528
+ const int depth = tree->height();
529
+ const size_t length = rep->length;
530
+ StackOperations<edge_type> ops;
531
+ CordRepBtree* leaf = ops.BuildStack(tree, depth);
532
+ const OpResult result =
533
+ leaf->AddEdge<edge_type>(ops.owned(depth), rep, length);
534
+ return ops.Unwind(tree, depth, length, result);
535
+ }
536
+
537
+ template <>
538
+ CordRepBtree* CordRepBtree::NewLeaf<kBack>(absl::string_view data,
539
+ size_t extra) {
540
+ CordRepBtree* leaf = CordRepBtree::New(0);
541
+ size_t length = 0;
542
+ size_t end = 0;
543
+ const size_t cap = leaf->capacity();
544
+ while (!data.empty() && end != cap) {
545
+ auto* flat = CordRepFlat::New(data.length() + extra);
546
+ flat->length = (std::min)(data.length(), flat->Capacity());
547
+ length += flat->length;
548
+ leaf->edges_[end++] = flat;
549
+ data = Consume<kBack>(flat->Data(), data, flat->length);
550
+ }
551
+ leaf->length = length;
552
+ leaf->set_end(end);
553
+ return leaf;
554
+ }
555
+
556
+ template <>
557
+ CordRepBtree* CordRepBtree::NewLeaf<kFront>(absl::string_view data,
558
+ size_t extra) {
559
+ CordRepBtree* leaf = CordRepBtree::New(0);
560
+ size_t length = 0;
561
+ size_t begin = leaf->capacity();
562
+ leaf->set_end(leaf->capacity());
563
+ while (!data.empty() && begin != 0) {
564
+ auto* flat = CordRepFlat::New(data.length() + extra);
565
+ flat->length = (std::min)(data.length(), flat->Capacity());
566
+ length += flat->length;
567
+ leaf->edges_[--begin] = flat;
568
+ data = Consume<kFront>(flat->Data(), data, flat->length);
569
+ }
570
+ leaf->length = length;
571
+ leaf->set_begin(begin);
572
+ return leaf;
573
+ }
574
+
575
+ template <>
576
+ absl::string_view CordRepBtree::AddData<kBack>(absl::string_view data,
577
+ size_t extra) {
578
+ assert(!data.empty());
579
+ assert(size() < capacity());
580
+ AlignBegin();
581
+ const size_t cap = capacity();
582
+ do {
583
+ CordRepFlat* flat = CordRepFlat::New(data.length() + extra);
584
+ const size_t n = (std::min)(data.length(), flat->Capacity());
585
+ flat->length = n;
586
+ edges_[fetch_add_end(1)] = flat;
587
+ data = Consume<kBack>(flat->Data(), data, n);
588
+ } while (!data.empty() && end() != cap);
589
+ return data;
590
+ }
591
+
592
+ template <>
593
+ absl::string_view CordRepBtree::AddData<kFront>(absl::string_view data,
594
+ size_t extra) {
595
+ assert(!data.empty());
596
+ assert(size() < capacity());
597
+ AlignEnd();
598
+ do {
599
+ CordRepFlat* flat = CordRepFlat::New(data.length() + extra);
600
+ const size_t n = (std::min)(data.length(), flat->Capacity());
601
+ flat->length = n;
602
+ edges_[sub_fetch_begin(1)] = flat;
603
+ data = Consume<kFront>(flat->Data(), data, n);
604
+ } while (!data.empty() && begin() != 0);
605
+ return data;
606
+ }
607
+
608
+ template <EdgeType edge_type>
609
+ CordRepBtree* CordRepBtree::AddData(CordRepBtree* tree, absl::string_view data,
610
+ size_t extra) {
611
+ if (ABSL_PREDICT_FALSE(data.empty())) return tree;
612
+
613
+ const size_t original_data_size = data.size();
614
+ int depth = tree->height();
615
+ StackOperations<edge_type> ops;
616
+ CordRepBtree* leaf = ops.BuildStack(tree, depth);
617
+
618
+ // If there is capacity in the last edge, append as much data
619
+ // as possible into this last edge.
620
+ if (leaf->size() < leaf->capacity()) {
621
+ OpResult result = leaf->ToOpResult(ops.owned(depth));
622
+ data = result.tree->AddData<edge_type>(data, extra);
623
+ if (data.empty()) {
624
+ result.tree->length += original_data_size;
625
+ return ops.Unwind(tree, depth, original_data_size, result);
626
+ }
627
+
628
+ // We added some data into this leaf, but not all. Propagate the added
629
+ // length to the top most node, and rebuild the stack with any newly copied
630
+ // or updated nodes. From this point on, the path (leg) from the top most
631
+ // node to the right-most node towards the leaf node is privately owned.
632
+ size_t delta = original_data_size - data.size();
633
+ assert(delta > 0);
634
+ result.tree->length += delta;
635
+ tree = ops.Propagate(tree, depth, delta, result);
636
+ ops.share_depth = depth + 1;
637
+ }
638
+
639
+ // We were unable to append all data into the existing right-most leaf node.
640
+ // This means all remaining data must be put into (a) new leaf node(s) which
641
+ // we append to the tree. To make this efficient, we iteratively build full
642
+ // leaf nodes from `data` until the created leaf contains all remaining data.
643
+ // We utilize the `Unwind` method to merge the created leaf into the first
644
+ // level towards root that has capacity. On each iteration with remaining
645
+ // data, we rebuild the stack in the knowledge that right-most nodes are
646
+ // privately owned after the first `Unwind` completes.
647
+ for (;;) {
648
+ OpResult result = {CordRepBtree::NewLeaf<edge_type>(data, extra), kPopped};
649
+ if (result.tree->length == data.size()) {
650
+ return ops.Unwind(tree, depth, result.tree->length, result);
651
+ }
652
+ data = Consume<edge_type>(data, result.tree->length);
653
+ tree = ops.Unwind(tree, depth, result.tree->length, result);
654
+ depth = tree->height();
655
+ ops.BuildOwnedStack(tree, depth);
656
+ }
657
+ }
658
+
659
+ template <EdgeType edge_type>
660
+ CordRepBtree* CordRepBtree::Merge(CordRepBtree* dst, CordRepBtree* src) {
661
+ assert(dst->height() >= src->height());
662
+
663
+ // Capture source length as we may consume / destroy `src`.
664
+ const size_t length = src->length;
665
+
666
+ // We attempt to merge `src` at its corresponding height in `dst`.
667
+ const int depth = dst->height() - src->height();
668
+ StackOperations<edge_type> ops;
669
+ CordRepBtree* merge_node = ops.BuildStack(dst, depth);
670
+
671
+ // If there is enough space in `merge_node` for all edges from `src`, add all
672
+ // edges to this node, making a fresh copy as needed if not privately owned.
673
+ // If `merge_node` does not have capacity for `src`, we rely on `Unwind` and
674
+ // `Finalize` to merge `src` into the first level towards `root` where there
675
+ // is capacity for another edge, or create a new top level node.
676
+ OpResult result;
677
+ if (merge_node->size() + src->size() <= kMaxCapacity) {
678
+ result = merge_node->ToOpResult(ops.owned(depth));
679
+ result.tree->Add<edge_type>(src->Edges());
680
+ result.tree->length += src->length;
681
+ if (src->refcount.IsOne()) {
682
+ Delete(src);
683
+ } else {
684
+ for (CordRep* edge : src->Edges()) CordRep::Ref(edge);
685
+ CordRepBtree::Unref(src);
686
+ }
687
+ } else {
688
+ result = {src, kPopped};
689
+ }
690
+
691
+ // Unless we merged at the top level (i.e.: src and dst are equal height),
692
+ // unwind the result towards the top level, and finalize the result.
693
+ if (depth) {
694
+ return ops.Unwind(dst, depth, length, result);
695
+ }
696
+ return ops.Finalize(dst, result);
697
+ }
698
+
699
+ CopyResult CordRepBtree::CopySuffix(size_t offset) {
700
+ assert(offset < this->length);
701
+
702
+ // As long as `offset` starts inside the last edge, we can 'drop' the current
703
+ // depth. For the most extreme example: if offset references the last data
704
+ // edge in the tree, there is only a single edge / path from the top of the
705
+ // tree to that last edge, so we can drop all the nodes except that edge.
706
+ // The fast path check for this is `back->length >= length - offset`.
707
+ int height = this->height();
708
+ CordRepBtree* node = this;
709
+ size_t len = node->length - offset;
710
+ CordRep* back = node->Edge(kBack);
711
+ while (back->length >= len) {
712
+ offset = back->length - len;
713
+ if (--height < 0) {
714
+ return {MakeSubstring(CordRep::Ref(back), offset), height};
715
+ }
716
+ node = back->btree();
717
+ back = node->Edge(kBack);
718
+ }
719
+ if (offset == 0) return {CordRep::Ref(node), height};
720
+
721
+ // Offset does not point into the last edge, so we span at least two edges.
722
+ // Find the index of offset with `IndexBeyond` which provides us the edge
723
+ // 'beyond' the offset if offset is not a clean starting point of an edge.
724
+ Position pos = node->IndexBeyond(offset);
725
+ CordRepBtree* sub = node->CopyToEndFrom(pos.index, len);
726
+ const CopyResult result = {sub, height};
727
+
728
+ // `pos.n` contains a non zero value if the offset is not an exact starting
729
+ // point of an edge. In this case, `pos.n` contains the 'trailing' amount of
730
+ // bytes of the edge preceding that in `pos.index`. We need to iteratively
731
+ // adjust the preceding edge with the 'broken' offset until we have a perfect
732
+ // start of the edge.
733
+ while (pos.n != 0) {
734
+ assert(pos.index >= 1);
735
+ const size_t begin = pos.index - 1;
736
+ sub->set_begin(begin);
737
+ CordRep* const edge = node->Edge(begin);
738
+
739
+ len = pos.n;
740
+ offset = edge->length - len;
741
+
742
+ if (--height < 0) {
743
+ sub->edges_[begin] = MakeSubstring(CordRep::Ref(edge), offset, len);
744
+ return result;
745
+ }
746
+
747
+ node = edge->btree();
748
+ pos = node->IndexBeyond(offset);
749
+
750
+ CordRepBtree* nsub = node->CopyToEndFrom(pos.index, len);
751
+ sub->edges_[begin] = nsub;
752
+ sub = nsub;
753
+ }
754
+ sub->set_begin(pos.index);
755
+ return result;
756
+ }
757
+
758
+ CopyResult CordRepBtree::CopyPrefix(size_t n, bool allow_folding) {
759
+ assert(n > 0);
760
+ assert(n <= this->length);
761
+
762
+ // As long as `n` does not exceed the length of the first edge, we can 'drop'
763
+ // the current depth. For the most extreme example: if we'd copy a 1 byte
764
+ // prefix from a tree, there is only a single edge / path from the top of the
765
+ // tree to the single data edge containing this byte, so we can drop all the
766
+ // nodes except the data node.
767
+ int height = this->height();
768
+ CordRepBtree* node = this;
769
+ CordRep* front = node->Edge(kFront);
770
+ if (allow_folding) {
771
+ while (front->length >= n) {
772
+ if (--height < 0) return {MakeSubstring(CordRep::Ref(front), 0, n), -1};
773
+ node = front->btree();
774
+ front = node->Edge(kFront);
775
+ }
776
+ }
777
+ if (node->length == n) return {CordRep::Ref(node), height};
778
+
779
+ // `n` spans at least two nodes, find the end point of the span.
780
+ Position pos = node->IndexOf(n);
781
+
782
+ // Create a partial copy of the node up to `pos.index`, with a defined length
783
+ // of `n`. Any 'partial last edge' is added further below as needed.
784
+ CordRepBtree* sub = node->CopyBeginTo(pos.index, n);
785
+ const CopyResult result = {sub, height};
786
+
787
+ // `pos.n` contains the 'offset inside the edge for IndexOf(n)'. As long as
788
+ // this is not zero, we don't have a 'clean cut', so we need to make a
789
+ // (partial) copy of that last edge, and repeat this until pos.n is zero.
790
+ while (pos.n != 0) {
791
+ size_t end = pos.index;
792
+ n = pos.n;
793
+
794
+ CordRep* edge = node->Edge(pos.index);
795
+ if (--height < 0) {
796
+ sub->edges_[end++] = MakeSubstring(CordRep::Ref(edge), 0, n);
797
+ sub->set_end(end);
798
+ AssertValid(result.edge->btree());
799
+ return result;
800
+ }
801
+
802
+ node = edge->btree();
803
+ pos = node->IndexOf(n);
804
+ CordRepBtree* nsub = node->CopyBeginTo(pos.index, n);
805
+ sub->edges_[end++] = nsub;
806
+ sub->set_end(end);
807
+ sub = nsub;
808
+ }
809
+ sub->set_end(pos.index);
810
+ AssertValid(result.edge->btree());
811
+ return result;
812
+ }
813
+
814
+ CordRep* CordRepBtree::ExtractFront(CordRepBtree* tree) {
815
+ CordRep* front = tree->Edge(tree->begin());
816
+ if (tree->refcount.IsOne()) {
817
+ Unref(tree->Edges(tree->begin() + 1, tree->end()));
818
+ CordRepBtree::Delete(tree);
819
+ } else {
820
+ CordRep::Ref(front);
821
+ CordRep::Unref(tree);
822
+ }
823
+ return front;
824
+ }
825
+
826
+ CordRepBtree* CordRepBtree::ConsumeBeginTo(CordRepBtree* tree, size_t end,
827
+ size_t new_length) {
828
+ assert(end <= tree->end());
829
+ if (tree->refcount.IsOne()) {
830
+ Unref(tree->Edges(end, tree->end()));
831
+ tree->set_end(end);
832
+ tree->length = new_length;
833
+ } else {
834
+ CordRepBtree* old = tree;
835
+ tree = tree->CopyBeginTo(end, new_length);
836
+ CordRep::Unref(old);
837
+ }
838
+ return tree;
839
+ }
840
+
841
+ CordRep* CordRepBtree::RemoveSuffix(CordRepBtree* tree, size_t n) {
842
+ // Check input and deal with trivial cases 'Remove all/none'
843
+ assert(tree != nullptr);
844
+ assert(n <= tree->length);
845
+ const size_t len = tree->length;
846
+ if (ABSL_PREDICT_FALSE(n == 0)) {
847
+ return tree;
848
+ }
849
+ if (ABSL_PREDICT_FALSE(n >= len)) {
850
+ CordRepBtree::Unref(tree);
851
+ return nullptr;
852
+ }
853
+
854
+ size_t length = len - n;
855
+ int height = tree->height();
856
+ bool is_mutable = tree->refcount.IsOne();
857
+
858
+ // Extract all top nodes which are reduced to size = 1
859
+ Position pos = tree->IndexOfLength(length);
860
+ while (pos.index == tree->begin()) {
861
+ CordRep* edge = ExtractFront(tree);
862
+ is_mutable &= edge->refcount.IsOne();
863
+ if (height-- == 0) return ResizeEdge(edge, length, is_mutable);
864
+ tree = edge->btree();
865
+ pos = tree->IndexOfLength(length);
866
+ }
867
+
868
+ // Repeat the following sequence traversing down the tree:
869
+ // - Crop the top node to the 'last remaining edge' adjusting length.
870
+ // - Set the length for down edges to the partial length in that last edge.
871
+ // - Repeat this until the last edge is 'included in full'
872
+ // - If we hit the data edge level, resize and return the last data edge
873
+ CordRepBtree* top = tree = ConsumeBeginTo(tree, pos.index + 1, length);
874
+ CordRep* edge = tree->Edge(pos.index);
875
+ length = pos.n;
876
+ while (length != edge->length) {
877
+ // ConsumeBeginTo guarantees `tree` is a clean, privately owned copy.
878
+ assert(tree->refcount.IsOne());
879
+ const bool edge_is_mutable = edge->refcount.IsOne();
880
+
881
+ if (height-- == 0) {
882
+ tree->edges_[pos.index] = ResizeEdge(edge, length, edge_is_mutable);
883
+ return AssertValid(top);
884
+ }
885
+
886
+ if (!edge_is_mutable) {
887
+ // We can't 'in place' remove any suffixes down this edge.
888
+ // Replace this edge with a prefix copy instead.
889
+ tree->edges_[pos.index] = edge->btree()->CopyPrefix(length, false).edge;
890
+ CordRep::Unref(edge);
891
+ return AssertValid(top);
892
+ }
893
+
894
+ // Move down one level, rinse repeat.
895
+ tree = edge->btree();
896
+ pos = tree->IndexOfLength(length);
897
+ tree = ConsumeBeginTo(edge->btree(), pos.index + 1, length);
898
+ edge = tree->Edge(pos.index);
899
+ length = pos.n;
900
+ }
901
+
902
+ return AssertValid(top);
903
+ }
904
+
905
+ CordRep* CordRepBtree::SubTree(size_t offset, size_t n) {
906
+ assert(n <= this->length);
907
+ assert(offset <= this->length - n);
908
+ if (ABSL_PREDICT_FALSE(n == 0)) return nullptr;
909
+
910
+ CordRepBtree* node = this;
911
+ int height = node->height();
912
+ Position front = node->IndexOf(offset);
913
+ CordRep* left = node->edges_[front.index];
914
+ while (front.n + n <= left->length) {
915
+ if (--height < 0) return MakeSubstring(CordRep::Ref(left), front.n, n);
916
+ node = left->btree();
917
+ front = node->IndexOf(front.n);
918
+ left = node->edges_[front.index];
919
+ }
920
+
921
+ const Position back = node->IndexBefore(front, n);
922
+ CordRep* const right = node->edges_[back.index];
923
+ assert(back.index > front.index);
924
+
925
+ // Get partial suffix and prefix entries.
926
+ CopyResult prefix;
927
+ CopyResult suffix;
928
+ if (height > 0) {
929
+ // Copy prefix and suffix of the boundary nodes.
930
+ prefix = left->btree()->CopySuffix(front.n);
931
+ suffix = right->btree()->CopyPrefix(back.n);
932
+
933
+ // If there is an edge between the prefix and suffix edges, then the tree
934
+ // must remain at its previous (full) height. If we have no edges between
935
+ // prefix and suffix edges, then the tree must be as high as either the
936
+ // suffix or prefix edges (which are collapsed to their minimum heights).
937
+ if (front.index + 1 == back.index) {
938
+ height = (std::max)(prefix.height, suffix.height) + 1;
939
+ }
940
+
941
+ // Raise prefix and suffixes to the new tree height.
942
+ for (int h = prefix.height + 1; h < height; ++h) {
943
+ prefix.edge = CordRepBtree::New(prefix.edge);
944
+ }
945
+ for (int h = suffix.height + 1; h < height; ++h) {
946
+ suffix.edge = CordRepBtree::New(suffix.edge);
947
+ }
948
+ } else {
949
+ // Leaf node, simply take substrings for prefix and suffix.
950
+ prefix = CopyResult{MakeSubstring(CordRep::Ref(left), front.n), -1};
951
+ suffix = CopyResult{MakeSubstring(CordRep::Ref(right), 0, back.n), -1};
952
+ }
953
+
954
+ // Compose resulting tree.
955
+ CordRepBtree* sub = CordRepBtree::New(height);
956
+ size_t end = 0;
957
+ sub->edges_[end++] = prefix.edge;
958
+ for (CordRep* r : node->Edges(front.index + 1, back.index)) {
959
+ sub->edges_[end++] = CordRep::Ref(r);
960
+ }
961
+ sub->edges_[end++] = suffix.edge;
962
+ sub->set_end(end);
963
+ sub->length = n;
964
+ return AssertValid(sub);
965
+ }
966
+
967
+ CordRepBtree* CordRepBtree::MergeTrees(CordRepBtree* left,
968
+ CordRepBtree* right) {
969
+ return left->height() >= right->height() ? Merge<kBack>(left, right)
970
+ : Merge<kFront>(right, left);
971
+ }
972
+
973
+ bool CordRepBtree::IsFlat(absl::string_view* fragment) const {
974
+ if (height() == 0 && size() == 1) {
975
+ if (fragment) *fragment = Data(begin());
976
+ return true;
977
+ }
978
+ return false;
979
+ }
980
+
981
+ bool CordRepBtree::IsFlat(size_t offset, const size_t n,
982
+ absl::string_view* fragment) const {
983
+ assert(n <= this->length);
984
+ assert(offset <= this->length - n);
985
+ if (ABSL_PREDICT_FALSE(n == 0)) return false;
986
+ int height = this->height();
987
+ const CordRepBtree* node = this;
988
+ for (;;) {
989
+ const Position front = node->IndexOf(offset);
990
+ const CordRep* edge = node->Edge(front.index);
991
+ if (edge->length < front.n + n) return false;
992
+ if (--height < 0) {
993
+ if (fragment) *fragment = EdgeData(edge).substr(front.n, n);
994
+ return true;
995
+ }
996
+ offset = front.n;
997
+ node = node->Edge(front.index)->btree();
998
+ }
999
+ }
1000
+
1001
+ char CordRepBtree::GetCharacter(size_t offset) const {
1002
+ assert(offset < length);
1003
+ const CordRepBtree* node = this;
1004
+ int height = node->height();
1005
+ for (;;) {
1006
+ Position front = node->IndexOf(offset);
1007
+ if (--height < 0) return node->Data(front.index)[front.n];
1008
+ offset = front.n;
1009
+ node = node->Edge(front.index)->btree();
1010
+ }
1011
+ }
1012
+
1013
+ Span<char> CordRepBtree::GetAppendBufferSlow(size_t size) {
1014
+ // The inlined version in `GetAppendBuffer()` deals with all heights <= 3.
1015
+ assert(height() >= 4);
1016
+ assert(refcount.IsOne());
1017
+
1018
+ // Build a stack of nodes we may potentially need to update if we find a
1019
+ // non-shared FLAT with capacity at the leaf level.
1020
+ const int depth = height();
1021
+ CordRepBtree* node = this;
1022
+ CordRepBtree* stack[kMaxDepth];
1023
+ for (int i = 0; i < depth; ++i) {
1024
+ node = node->Edge(kBack)->btree();
1025
+ if (!node->refcount.IsOne()) return {};
1026
+ stack[i] = node;
1027
+ }
1028
+
1029
+ // Must be a privately owned, mutable flat.
1030
+ CordRep* const edge = node->Edge(kBack);
1031
+ if (!edge->refcount.IsOne() || edge->tag < FLAT) return {};
1032
+
1033
+ // Must have capacity.
1034
+ const size_t avail = edge->flat()->Capacity() - edge->length;
1035
+ if (avail == 0) return {};
1036
+
1037
+ // Build span on remaining capacity.
1038
+ size_t delta = (std::min)(size, avail);
1039
+ Span<char> span = {edge->flat()->Data() + edge->length, delta};
1040
+ edge->length += delta;
1041
+ this->length += delta;
1042
+ for (int i = 0; i < depth; ++i) {
1043
+ stack[i]->length += delta;
1044
+ }
1045
+ return span;
1046
+ }
1047
+
1048
+ CordRepBtree* CordRepBtree::CreateSlow(CordRep* rep) {
1049
+ if (rep->IsBtree()) return rep->btree();
1050
+
1051
+ CordRepBtree* node = nullptr;
1052
+ auto consume = [&node](CordRep* r, size_t offset, size_t length) {
1053
+ r = MakeSubstring(r, offset, length);
1054
+ if (node == nullptr) {
1055
+ node = New(r);
1056
+ } else {
1057
+ node = CordRepBtree::AddCordRep<kBack>(node, r);
1058
+ }
1059
+ };
1060
+ Consume(rep, consume);
1061
+ return node;
1062
+ }
1063
+
1064
+ CordRepBtree* CordRepBtree::AppendSlow(CordRepBtree* tree, CordRep* rep) {
1065
+ if (ABSL_PREDICT_TRUE(rep->IsBtree())) {
1066
+ return MergeTrees(tree, rep->btree());
1067
+ }
1068
+ auto consume = [&tree](CordRep* r, size_t offset, size_t length) {
1069
+ r = MakeSubstring(r, offset, length);
1070
+ tree = CordRepBtree::AddCordRep<kBack>(tree, r);
1071
+ };
1072
+ Consume(rep, consume);
1073
+ return tree;
1074
+ }
1075
+
1076
+ CordRepBtree* CordRepBtree::PrependSlow(CordRepBtree* tree, CordRep* rep) {
1077
+ if (ABSL_PREDICT_TRUE(rep->IsBtree())) {
1078
+ return MergeTrees(rep->btree(), tree);
1079
+ }
1080
+ auto consume = [&tree](CordRep* r, size_t offset, size_t length) {
1081
+ r = MakeSubstring(r, offset, length);
1082
+ tree = CordRepBtree::AddCordRep<kFront>(tree, r);
1083
+ };
1084
+ ReverseConsume(rep, consume);
1085
+ return tree;
1086
+ }
1087
+
1088
+ CordRepBtree* CordRepBtree::Append(CordRepBtree* tree, absl::string_view data,
1089
+ size_t extra) {
1090
+ return CordRepBtree::AddData<kBack>(tree, data, extra);
1091
+ }
1092
+
1093
+ CordRepBtree* CordRepBtree::Prepend(CordRepBtree* tree, absl::string_view data,
1094
+ size_t extra) {
1095
+ return CordRepBtree::AddData<kFront>(tree, data, extra);
1096
+ }
1097
+
1098
+ template CordRepBtree* CordRepBtree::AddCordRep<kFront>(CordRepBtree* tree,
1099
+ CordRep* rep);
1100
+ template CordRepBtree* CordRepBtree::AddCordRep<kBack>(CordRepBtree* tree,
1101
+ CordRep* rep);
1102
+ template CordRepBtree* CordRepBtree::AddData<kFront>(CordRepBtree* tree,
1103
+ absl::string_view data,
1104
+ size_t extra);
1105
+ template CordRepBtree* CordRepBtree::AddData<kBack>(CordRepBtree* tree,
1106
+ absl::string_view data,
1107
+ size_t extra);
1108
+
1109
+ void CordRepBtree::Rebuild(CordRepBtree** stack, CordRepBtree* tree,
1110
+ bool consume) {
1111
+ bool owned = consume && tree->refcount.IsOne();
1112
+ if (tree->height() == 0) {
1113
+ for (CordRep* edge : tree->Edges()) {
1114
+ if (!owned) edge = CordRep::Ref(edge);
1115
+ size_t height = 0;
1116
+ size_t length = edge->length;
1117
+ CordRepBtree* node = stack[0];
1118
+ OpResult result = node->AddEdge<kBack>(true, edge, length);
1119
+ while (result.action == CordRepBtree::kPopped) {
1120
+ stack[height] = result.tree;
1121
+ if (stack[++height] == nullptr) {
1122
+ result.action = CordRepBtree::kSelf;
1123
+ stack[height] = CordRepBtree::New(node, result.tree);
1124
+ } else {
1125
+ node = stack[height];
1126
+ result = node->AddEdge<kBack>(true, result.tree, length);
1127
+ }
1128
+ }
1129
+ while (stack[++height] != nullptr) {
1130
+ stack[height]->length += length;
1131
+ }
1132
+ }
1133
+ } else {
1134
+ for (CordRep* rep : tree->Edges()) {
1135
+ Rebuild(stack, rep->btree(), owned);
1136
+ }
1137
+ }
1138
+ if (consume) {
1139
+ if (owned) {
1140
+ CordRepBtree::Delete(tree);
1141
+ } else {
1142
+ CordRepBtree::Unref(tree);
1143
+ }
1144
+ }
1145
+ }
1146
+
1147
+ CordRepBtree* CordRepBtree::Rebuild(CordRepBtree* tree) {
1148
+ // Set up initial stack with empty leaf node.
1149
+ CordRepBtree* node = CordRepBtree::New();
1150
+ CordRepBtree* stack[CordRepBtree::kMaxDepth + 1] = {node};
1151
+
1152
+ // Recursively build the tree, consuming the input tree.
1153
+ Rebuild(stack, tree, /* consume reference */ true);
1154
+
1155
+ // Return top most node
1156
+ for (CordRepBtree* parent : stack) {
1157
+ if (parent == nullptr) return node;
1158
+ node = parent;
1159
+ }
1160
+
1161
+ // Unreachable
1162
+ assert(false);
1163
+ return nullptr;
1164
+ }
1165
+
1166
+ CordRepBtree::ExtractResult CordRepBtree::ExtractAppendBuffer(
1167
+ CordRepBtree* tree, size_t extra_capacity) {
1168
+ int depth = 0;
1169
+ NodeStack stack;
1170
+
1171
+ // Set up default 'no success' result which is {tree, nullptr}.
1172
+ ExtractResult result;
1173
+ result.tree = tree;
1174
+ result.extracted = nullptr;
1175
+
1176
+ // Dive down the right side of the tree, making sure no edges are shared.
1177
+ while (tree->height() > 0) {
1178
+ if (!tree->refcount.IsOne()) return result;
1179
+ stack[depth++] = tree;
1180
+ tree = tree->Edge(kBack)->btree();
1181
+ }
1182
+ if (!tree->refcount.IsOne()) return result;
1183
+
1184
+ // Validate we ended on a non shared flat.
1185
+ CordRep* rep = tree->Edge(kBack);
1186
+ if (!(rep->IsFlat() && rep->refcount.IsOne())) return result;
1187
+
1188
+ // Verify it has at least the requested extra capacity.
1189
+ CordRepFlat* flat = rep->flat();
1190
+ const size_t length = flat->length;
1191
+ const size_t avail = flat->Capacity() - flat->length;
1192
+ if (extra_capacity > avail) return result;
1193
+
1194
+ // Set the extracted flat in the result.
1195
+ result.extracted = flat;
1196
+
1197
+ // Cascading delete all nodes that become empty.
1198
+ while (tree->size() == 1) {
1199
+ CordRepBtree::Delete(tree);
1200
+ if (--depth < 0) {
1201
+ // We consumed the entire tree: return nullptr for new tree.
1202
+ result.tree = nullptr;
1203
+ return result;
1204
+ }
1205
+ rep = tree;
1206
+ tree = stack[depth];
1207
+ }
1208
+
1209
+ // Remove the edge or cascaded up parent node.
1210
+ tree->set_end(tree->end() - 1);
1211
+ tree->length -= length;
1212
+
1213
+ // Adjust lengths up the tree.
1214
+ while (depth > 0) {
1215
+ tree = stack[--depth];
1216
+ tree->length -= length;
1217
+ }
1218
+
1219
+ // Remove unnecessary top nodes with size = 1. This may iterate all the way
1220
+ // down to the leaf node in which case we simply return the remaining last
1221
+ // edge in that node and the extracted flat.
1222
+ while (tree->size() == 1) {
1223
+ int height = tree->height();
1224
+ rep = tree->Edge(kBack);
1225
+ Delete(tree);
1226
+ if (height == 0) {
1227
+ // We consumed the leaf: return the sole data edge as the new tree.
1228
+ result.tree = rep;
1229
+ return result;
1230
+ }
1231
+ tree = rep->btree();
1232
+ }
1233
+
1234
+ // Done: return the (new) top level node and extracted flat.
1235
+ result.tree = tree;
1236
+ return result;
1237
+ }
1238
+
1239
+ } // namespace cord_internal
1240
+ ABSL_NAMESPACE_END
1241
+ } // namespace absl
weight/_dep/abseil-cpp/absl/strings/internal/cord_rep_btree_navigator.cc ADDED
@@ -0,0 +1,187 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Copyright 2021 The Abseil Authors
2
+ //
3
+ // Licensed under the Apache License, Version 2.0 (the "License");
4
+ // you may not use this file except in compliance with the License.
5
+ // You may obtain a copy of the License at
6
+ //
7
+ // https://www.apache.org/licenses/LICENSE-2.0
8
+ //
9
+ // Unless required by applicable law or agreed to in writing, software
10
+ // distributed under the License is distributed on an "AS IS" BASIS,
11
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ // See the License for the specific language governing permissions and
13
+ // limitations under the License.
14
+
15
+ #include "absl/strings/internal/cord_rep_btree_navigator.h"
16
+
17
+ #include <cassert>
18
+
19
+ #include "absl/strings/internal/cord_data_edge.h"
20
+ #include "absl/strings/internal/cord_internal.h"
21
+ #include "absl/strings/internal/cord_rep_btree.h"
22
+
23
+ namespace absl {
24
+ ABSL_NAMESPACE_BEGIN
25
+ namespace cord_internal {
26
+
27
+ using ReadResult = CordRepBtreeNavigator::ReadResult;
28
+
29
+ namespace {
30
+
31
+ // Returns a `CordRepSubstring` from `rep` starting at `offset` of size `n`.
32
+ // If `rep` is already a `CordRepSubstring` instance, an adjusted instance is
33
+ // created based on the old offset and new offset.
34
+ // Adopts a reference on `rep`. Rep must be a valid data edge. Returns
35
+ // nullptr if `n == 0`, `rep` if `n == rep->length`.
36
+ // Requires `offset < rep->length` and `offset + n <= rep->length`.
37
+ // TODO(192061034): move to utility library in internal and optimize for small
38
+ // substrings of larger reps.
39
+ inline CordRep* Substring(CordRep* rep, size_t offset, size_t n) {
40
+ assert(n <= rep->length);
41
+ assert(offset < rep->length);
42
+ assert(offset <= rep->length - n);
43
+ assert(IsDataEdge(rep));
44
+
45
+ if (n == 0) return nullptr;
46
+ if (n == rep->length) return CordRep::Ref(rep);
47
+
48
+ if (rep->tag == SUBSTRING) {
49
+ offset += rep->substring()->start;
50
+ rep = rep->substring()->child;
51
+ }
52
+
53
+ assert(rep->IsExternal() || rep->IsFlat());
54
+ CordRepSubstring* substring = new CordRepSubstring();
55
+ substring->length = n;
56
+ substring->tag = SUBSTRING;
57
+ substring->start = offset;
58
+ substring->child = CordRep::Ref(rep);
59
+ return substring;
60
+ }
61
+
62
+ inline CordRep* Substring(CordRep* rep, size_t offset) {
63
+ return Substring(rep, offset, rep->length - offset);
64
+ }
65
+
66
+ } // namespace
67
+
68
+ CordRepBtreeNavigator::Position CordRepBtreeNavigator::Skip(size_t n) {
69
+ int height = 0;
70
+ size_t index = index_[0];
71
+ CordRepBtree* node = node_[0];
72
+ CordRep* edge = node->Edge(index);
73
+
74
+ // Overall logic: Find an edge of at least the length we need to skip.
75
+ // We consume all edges which are smaller (i.e., must be 100% skipped).
76
+ // If we exhausted all edges on the current level, we move one level
77
+ // up the tree, and repeat until we either find the edge, or until we hit
78
+ // the top of the tree meaning the skip exceeds tree->length.
79
+ while (n >= edge->length) {
80
+ n -= edge->length;
81
+ while (++index == node->end()) {
82
+ if (++height > height_) return {nullptr, n};
83
+ node = node_[height];
84
+ index = index_[height];
85
+ }
86
+ edge = node->Edge(index);
87
+ }
88
+
89
+ // If we moved up the tree, descend down to the leaf level, consuming all
90
+ // edges that must be skipped.
91
+ while (height > 0) {
92
+ node = edge->btree();
93
+ index_[height] = static_cast<uint8_t>(index);
94
+ node_[--height] = node;
95
+ index = node->begin();
96
+ edge = node->Edge(index);
97
+ while (n >= edge->length) {
98
+ n -= edge->length;
99
+ ++index;
100
+ assert(index != node->end());
101
+ edge = node->Edge(index);
102
+ }
103
+ }
104
+ index_[0] = static_cast<uint8_t>(index);
105
+ return {edge, n};
106
+ }
107
+
108
+ ReadResult CordRepBtreeNavigator::Read(size_t edge_offset, size_t n) {
109
+ int height = 0;
110
+ size_t length = edge_offset + n;
111
+ size_t index = index_[0];
112
+ CordRepBtree* node = node_[0];
113
+ CordRep* edge = node->Edge(index);
114
+ assert(edge_offset < edge->length);
115
+
116
+ if (length < edge->length) {
117
+ return {Substring(edge, edge_offset, n), length};
118
+ }
119
+
120
+ // Similar to 'Skip', we consume all edges that are inside the 'length' of
121
+ // data that needs to be read. If we exhaust the current level, we move one
122
+ // level up the tree and repeat until we hit the final edge that must be
123
+ // (partially) read. We consume all edges into `subtree`.
124
+ CordRepBtree* subtree = CordRepBtree::New(Substring(edge, edge_offset));
125
+ size_t subtree_end = 1;
126
+ do {
127
+ length -= edge->length;
128
+ while (++index == node->end()) {
129
+ index_[height] = static_cast<uint8_t>(index);
130
+ if (++height > height_) {
131
+ subtree->set_end(subtree_end);
132
+ if (length == 0) return {subtree, 0};
133
+ CordRep::Unref(subtree);
134
+ return {nullptr, length};
135
+ }
136
+ if (length != 0) {
137
+ subtree->set_end(subtree_end);
138
+ subtree = CordRepBtree::New(subtree);
139
+ subtree_end = 1;
140
+ }
141
+ node = node_[height];
142
+ index = index_[height];
143
+ }
144
+ edge = node->Edge(index);
145
+ if (length >= edge->length) {
146
+ subtree->length += edge->length;
147
+ subtree->edges_[subtree_end++] = CordRep::Ref(edge);
148
+ }
149
+ } while (length >= edge->length);
150
+ CordRepBtree* tree = subtree;
151
+ subtree->length += length;
152
+
153
+ // If we moved up the tree, descend down to the leaf level, consuming all
154
+ // edges that must be read, adding 'down' nodes to `subtree`.
155
+ while (height > 0) {
156
+ node = edge->btree();
157
+ index_[height] = static_cast<uint8_t>(index);
158
+ node_[--height] = node;
159
+ index = node->begin();
160
+ edge = node->Edge(index);
161
+
162
+ if (length != 0) {
163
+ CordRepBtree* right = CordRepBtree::New(height);
164
+ right->length = length;
165
+ subtree->edges_[subtree_end++] = right;
166
+ subtree->set_end(subtree_end);
167
+ subtree = right;
168
+ subtree_end = 0;
169
+ while (length >= edge->length) {
170
+ subtree->edges_[subtree_end++] = CordRep::Ref(edge);
171
+ length -= edge->length;
172
+ edge = node->Edge(++index);
173
+ }
174
+ }
175
+ }
176
+ // Add any (partial) edge still remaining at the leaf level.
177
+ if (length != 0) {
178
+ subtree->edges_[subtree_end++] = Substring(edge, 0, length);
179
+ }
180
+ subtree->set_end(subtree_end);
181
+ index_[0] = static_cast<uint8_t>(index);
182
+ return {tree, length};
183
+ }
184
+
185
+ } // namespace cord_internal
186
+ ABSL_NAMESPACE_END
187
+ } // namespace absl
weight/_dep/abseil-cpp/absl/strings/internal/cord_rep_btree_navigator.h ADDED
@@ -0,0 +1,267 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Copyright 2021 The Abseil Authors
2
+ //
3
+ // Licensed under the Apache License, Version 2.0 (the "License");
4
+ // you may not use this file except in compliance with the License.
5
+ // You may obtain a copy of the License at
6
+ //
7
+ // https://www.apache.org/licenses/LICENSE-2.0
8
+ //
9
+ // Unless required by applicable law or agreed to in writing, software
10
+ // distributed under the License is distributed on an "AS IS" BASIS,
11
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ // See the License for the specific language governing permissions and
13
+ // limitations under the License.
14
+
15
+ #ifndef ABSL_STRINGS_INTERNAL_CORD_REP_BTREE_NAVIGATOR_H_
16
+ #define ABSL_STRINGS_INTERNAL_CORD_REP_BTREE_NAVIGATOR_H_
17
+
18
+ #include <cassert>
19
+ #include <iostream>
20
+
21
+ #include "absl/strings/internal/cord_internal.h"
22
+ #include "absl/strings/internal/cord_rep_btree.h"
23
+
24
+ namespace absl {
25
+ ABSL_NAMESPACE_BEGIN
26
+ namespace cord_internal {
27
+
28
+ // CordRepBtreeNavigator is a bi-directional navigator allowing callers to
29
+ // navigate all the (leaf) data edges in a CordRepBtree instance.
30
+ //
31
+ // A CordRepBtreeNavigator instance is by default empty. Callers initialize a
32
+ // navigator instance by calling one of `InitFirst()`, `InitLast()` or
33
+ // `InitOffset()`, which establishes a current position. Callers can then
34
+ // navigate using the `Next`, `Previous`, `Skip` and `Seek` methods.
35
+ //
36
+ // The navigator instance does not take or adopt a reference on the provided
37
+ // `tree` on any of the initialization calls. Callers are responsible for
38
+ // guaranteeing the lifecycle of the provided tree. A navigator instance can
39
+ // be reset to the empty state by calling `Reset`.
40
+ //
41
+ // A navigator only keeps positional state on the 'current data edge', it does
42
+ // explicitly not keep any 'offset' state. The class does accept and return
43
+ // offsets in the `Read()`, `Skip()` and 'Seek()` methods as these would
44
+ // otherwise put a big burden on callers. Callers are expected to maintain
45
+ // (returned) offset info if they require such granular state.
46
+ class CordRepBtreeNavigator {
47
+ public:
48
+ // The logical position as returned by the Seek() and Skip() functions.
49
+ // Returns the current leaf edge for the desired seek or skip position and
50
+ // the offset of that position inside that edge.
51
+ struct Position {
52
+ CordRep* edge;
53
+ size_t offset;
54
+ };
55
+
56
+ // The read result as returned by the Read() function.
57
+ // `tree` contains the resulting tree which is identical to the result
58
+ // of calling CordRepBtree::SubTree(...) on the tree being navigated.
59
+ // `n` contains the number of bytes used from the last navigated to
60
+ // edge of the tree.
61
+ struct ReadResult {
62
+ CordRep* tree;
63
+ size_t n;
64
+ };
65
+
66
+ // Returns true if this instance is not empty.
67
+ explicit operator bool() const;
68
+
69
+ // Returns the tree for this instance or nullptr if empty.
70
+ CordRepBtree* btree() const;
71
+
72
+ // Returns the data edge of the current position.
73
+ // Requires this instance to not be empty.
74
+ CordRep* Current() const;
75
+
76
+ // Resets this navigator to `tree`, returning the first data edge in the tree.
77
+ CordRep* InitFirst(CordRepBtree* tree);
78
+
79
+ // Resets this navigator to `tree`, returning the last data edge in the tree.
80
+ CordRep* InitLast(CordRepBtree* tree);
81
+
82
+ // Resets this navigator to `tree` returning the data edge at position
83
+ // `offset` and the relative offset of `offset` into that data edge.
84
+ // Returns `Position.edge = nullptr` if the provided offset is greater
85
+ // than or equal to the length of the tree, in which case the state of
86
+ // the navigator instance remains unchanged.
87
+ Position InitOffset(CordRepBtree* tree, size_t offset);
88
+
89
+ // Navigates to the next data edge.
90
+ // Returns the next data edge or nullptr if there is no next data edge, in
91
+ // which case the current position remains unchanged.
92
+ CordRep* Next();
93
+
94
+ // Navigates to the previous data edge.
95
+ // Returns the previous data edge or nullptr if there is no previous data
96
+ // edge, in which case the current position remains unchanged.
97
+ CordRep* Previous();
98
+
99
+ // Navigates to the data edge at position `offset`. Returns the navigated to
100
+ // data edge in `Position.edge` and the relative offset of `offset` into that
101
+ // data edge in `Position.offset`. Returns `Position.edge = nullptr` if the
102
+ // provide offset is greater than or equal to the tree's length.
103
+ Position Seek(size_t offset);
104
+
105
+ // Reads `n` bytes of data starting at offset `edge_offset` of the current
106
+ // data edge, and returns the result in `ReadResult.tree`. `ReadResult.n`
107
+ // contains the 'bytes used` from the last / current data edge in the tree.
108
+ // This allows users that mix regular navigation (using string views) and
109
+ // 'read into cord' navigation to keep track of the current state, and which
110
+ // bytes have been consumed from a navigator.
111
+ // This function returns `ReadResult.tree = nullptr` if the requested length
112
+ // exceeds the length of the tree starting at the current data edge.
113
+ ReadResult Read(size_t edge_offset, size_t n);
114
+
115
+ // Skips `n` bytes forward from the current data edge, returning the navigated
116
+ // to data edge in `Position.edge` and `Position.offset` containing the offset
117
+ // inside that data edge. Note that the state of the navigator is left
118
+ // unchanged if `n` is smaller than the length of the current data edge.
119
+ Position Skip(size_t n);
120
+
121
+ // Resets this instance to the default / empty state.
122
+ void Reset();
123
+
124
+ private:
125
+ // Slow path for Next() if Next() reached the end of a leaf node. Backtracks
126
+ // up the stack until it finds a node that has a 'next' position available,
127
+ // and then does a 'front dive' towards the next leaf node.
128
+ CordRep* NextUp();
129
+
130
+ // Slow path for Previous() if Previous() reached the beginning of a leaf
131
+ // node. Backtracks up the stack until it finds a node that has a 'previous'
132
+ // position available, and then does a 'back dive' towards the previous leaf
133
+ // node.
134
+ CordRep* PreviousUp();
135
+
136
+ // Generic implementation of InitFirst() and InitLast().
137
+ template <CordRepBtree::EdgeType edge_type>
138
+ CordRep* Init(CordRepBtree* tree);
139
+
140
+ // `height_` contains the height of the current tree, or -1 if empty.
141
+ int height_ = -1;
142
+
143
+ // `index_` and `node_` contain the navigation state as the 'path' to the
144
+ // current data edge which is at `node_[0]->Edge(index_[0])`. The contents
145
+ // of these are undefined until the instance is initialized (`height_ >= 0`).
146
+ uint8_t index_[CordRepBtree::kMaxDepth];
147
+ CordRepBtree* node_[CordRepBtree::kMaxDepth];
148
+ };
149
+
150
+ // Returns true if this instance is not empty.
151
+ inline CordRepBtreeNavigator::operator bool() const { return height_ >= 0; }
152
+
153
+ inline CordRepBtree* CordRepBtreeNavigator::btree() const {
154
+ return height_ >= 0 ? node_[height_] : nullptr;
155
+ }
156
+
157
+ inline CordRep* CordRepBtreeNavigator::Current() const {
158
+ assert(height_ >= 0);
159
+ return node_[0]->Edge(index_[0]);
160
+ }
161
+
162
+ inline void CordRepBtreeNavigator::Reset() { height_ = -1; }
163
+
164
+ inline CordRep* CordRepBtreeNavigator::InitFirst(CordRepBtree* tree) {
165
+ return Init<CordRepBtree::kFront>(tree);
166
+ }
167
+
168
+ inline CordRep* CordRepBtreeNavigator::InitLast(CordRepBtree* tree) {
169
+ return Init<CordRepBtree::kBack>(tree);
170
+ }
171
+
172
+ template <CordRepBtree::EdgeType edge_type>
173
+ inline CordRep* CordRepBtreeNavigator::Init(CordRepBtree* tree) {
174
+ assert(tree != nullptr);
175
+ assert(tree->size() > 0);
176
+ assert(tree->height() <= CordRepBtree::kMaxHeight);
177
+ int height = height_ = tree->height();
178
+ size_t index = tree->index(edge_type);
179
+ node_[height] = tree;
180
+ index_[height] = static_cast<uint8_t>(index);
181
+ while (--height >= 0) {
182
+ tree = tree->Edge(index)->btree();
183
+ node_[height] = tree;
184
+ index = tree->index(edge_type);
185
+ index_[height] = static_cast<uint8_t>(index);
186
+ }
187
+ return node_[0]->Edge(index);
188
+ }
189
+
190
+ inline CordRepBtreeNavigator::Position CordRepBtreeNavigator::Seek(
191
+ size_t offset) {
192
+ assert(btree() != nullptr);
193
+ int height = height_;
194
+ CordRepBtree* edge = node_[height];
195
+ if (ABSL_PREDICT_FALSE(offset >= edge->length)) return {nullptr, 0};
196
+ CordRepBtree::Position index = edge->IndexOf(offset);
197
+ index_[height] = static_cast<uint8_t>(index.index);
198
+ while (--height >= 0) {
199
+ edge = edge->Edge(index.index)->btree();
200
+ node_[height] = edge;
201
+ index = edge->IndexOf(index.n);
202
+ index_[height] = static_cast<uint8_t>(index.index);
203
+ }
204
+ return {edge->Edge(index.index), index.n};
205
+ }
206
+
207
+ inline CordRepBtreeNavigator::Position CordRepBtreeNavigator::InitOffset(
208
+ CordRepBtree* tree, size_t offset) {
209
+ assert(tree != nullptr);
210
+ assert(tree->height() <= CordRepBtree::kMaxHeight);
211
+ if (ABSL_PREDICT_FALSE(offset >= tree->length)) return {nullptr, 0};
212
+ height_ = tree->height();
213
+ node_[height_] = tree;
214
+ return Seek(offset);
215
+ }
216
+
217
+ inline CordRep* CordRepBtreeNavigator::Next() {
218
+ CordRepBtree* edge = node_[0];
219
+ return index_[0] == edge->back() ? NextUp() : edge->Edge(++index_[0]);
220
+ }
221
+
222
+ inline CordRep* CordRepBtreeNavigator::Previous() {
223
+ CordRepBtree* edge = node_[0];
224
+ return index_[0] == edge->begin() ? PreviousUp() : edge->Edge(--index_[0]);
225
+ }
226
+
227
+ inline CordRep* CordRepBtreeNavigator::NextUp() {
228
+ assert(index_[0] == node_[0]->back());
229
+ CordRepBtree* edge;
230
+ size_t index;
231
+ int height = 0;
232
+ do {
233
+ if (++height > height_) return nullptr;
234
+ edge = node_[height];
235
+ index = index_[height] + 1;
236
+ } while (index == edge->end());
237
+ index_[height] = static_cast<uint8_t>(index);
238
+ do {
239
+ node_[--height] = edge = edge->Edge(index)->btree();
240
+ index_[height] = static_cast<uint8_t>(index = edge->begin());
241
+ } while (height > 0);
242
+ return edge->Edge(index);
243
+ }
244
+
245
+ inline CordRep* CordRepBtreeNavigator::PreviousUp() {
246
+ assert(index_[0] == node_[0]->begin());
247
+ CordRepBtree* edge;
248
+ size_t index;
249
+ int height = 0;
250
+ do {
251
+ if (++height > height_) return nullptr;
252
+ edge = node_[height];
253
+ index = index_[height];
254
+ } while (index == edge->begin());
255
+ index_[height] = static_cast<uint8_t>(--index);
256
+ do {
257
+ node_[--height] = edge = edge->Edge(index)->btree();
258
+ index_[height] = static_cast<uint8_t>(index = edge->back());
259
+ } while (height > 0);
260
+ return edge->Edge(index);
261
+ }
262
+
263
+ } // namespace cord_internal
264
+ ABSL_NAMESPACE_END
265
+ } // namespace absl
266
+
267
+ #endif // ABSL_STRINGS_INTERNAL_CORD_REP_BTREE_NAVIGATOR_H_
weight/_dep/abseil-cpp/absl/strings/internal/cord_rep_btree_reader.cc ADDED
@@ -0,0 +1,69 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Copyright 2021 The Abseil Authors
2
+ //
3
+ // Licensed under the Apache License, Version 2.0 (the "License");
4
+ // you may not use this file except in compliance with the License.
5
+ // You may obtain a copy of the License at
6
+ //
7
+ // https://www.apache.org/licenses/LICENSE-2.0
8
+ //
9
+ // Unless required by applicable law or agreed to in writing, software
10
+ // distributed under the License is distributed on an "AS IS" BASIS,
11
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ // See the License for the specific language governing permissions and
13
+ // limitations under the License.
14
+
15
+ #include "absl/strings/internal/cord_rep_btree_reader.h"
16
+
17
+ #include <cassert>
18
+
19
+ #include "absl/base/config.h"
20
+ #include "absl/strings/internal/cord_data_edge.h"
21
+ #include "absl/strings/internal/cord_internal.h"
22
+ #include "absl/strings/internal/cord_rep_btree.h"
23
+ #include "absl/strings/internal/cord_rep_btree_navigator.h"
24
+ #include "absl/strings/internal/cord_rep_flat.h"
25
+
26
+ namespace absl {
27
+ ABSL_NAMESPACE_BEGIN
28
+ namespace cord_internal {
29
+
30
+ absl::string_view CordRepBtreeReader::Read(size_t n, size_t chunk_size,
31
+ CordRep*& tree) {
32
+ assert(chunk_size <= navigator_.Current()->length);
33
+
34
+ // If chunk_size is non-zero, we need to start inside last returned edge.
35
+ // Else we start reading at the next data edge of the tree.
36
+ CordRep* edge = chunk_size ? navigator_.Current() : navigator_.Next();
37
+ const size_t offset = chunk_size ? edge->length - chunk_size : 0;
38
+
39
+ // Read the sub tree and verify we got what we wanted.
40
+ ReadResult result = navigator_.Read(offset, n);
41
+ tree = result.tree;
42
+
43
+ // If the data returned in `tree` was covered entirely by `chunk_size`, i.e.,
44
+ // read from the 'previous' edge, we did not consume any additional data, and
45
+ // can directly return the substring into the current data edge as the next
46
+ // chunk. We can easily establish from the above code that `navigator_.Next()`
47
+ // has not been called as that requires `chunk_size` to be zero.
48
+ if (n < chunk_size) return EdgeData(edge).substr(result.n);
49
+
50
+ // The amount of data taken from the last edge is `chunk_size` and `result.n`
51
+ // contains the offset into the current edge trailing the read data (which can
52
+ // be 0). As the call to `navigator_.Read()` could have consumed all remaining
53
+ // data, calling `navigator_.Current()` is not safe before checking if we
54
+ // already consumed all remaining data.
55
+ const size_t consumed_by_read = n - chunk_size - result.n;
56
+ if (consumed_by_read >= remaining_) {
57
+ remaining_ = 0;
58
+ return {};
59
+ }
60
+
61
+ // We did not read all data, return remaining data from current edge.
62
+ edge = navigator_.Current();
63
+ remaining_ -= consumed_by_read + edge->length;
64
+ return EdgeData(edge).substr(result.n);
65
+ }
66
+
67
+ } // namespace cord_internal
68
+ ABSL_NAMESPACE_END
69
+ } // namespace absl
weight/_dep/abseil-cpp/absl/strings/internal/cord_rep_btree_reader.h ADDED
@@ -0,0 +1,212 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Copyright 2021 The Abseil Authors
2
+ //
3
+ // Licensed under the Apache License, Version 2.0 (the "License");
4
+ // you may not use this file except in compliance with the License.
5
+ // You may obtain a copy of the License at
6
+ //
7
+ // https://www.apache.org/licenses/LICENSE-2.0
8
+ //
9
+ // Unless required by applicable law or agreed to in writing, software
10
+ // distributed under the License is distributed on an "AS IS" BASIS,
11
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ // See the License for the specific language governing permissions and
13
+ // limitations under the License.
14
+
15
+ #ifndef ABSL_STRINGS_INTERNAL_CORD_REP_BTREE_READER_H_
16
+ #define ABSL_STRINGS_INTERNAL_CORD_REP_BTREE_READER_H_
17
+
18
+ #include <cassert>
19
+
20
+ #include "absl/base/config.h"
21
+ #include "absl/strings/internal/cord_data_edge.h"
22
+ #include "absl/strings/internal/cord_internal.h"
23
+ #include "absl/strings/internal/cord_rep_btree.h"
24
+ #include "absl/strings/internal/cord_rep_btree_navigator.h"
25
+ #include "absl/strings/internal/cord_rep_flat.h"
26
+
27
+ namespace absl {
28
+ ABSL_NAMESPACE_BEGIN
29
+ namespace cord_internal {
30
+
31
+ // CordRepBtreeReader implements logic to iterate over cord btrees.
32
+ // References to the underlying data are returned as absl::string_view values.
33
+ // The most typical use case is a forward only iteration over tree data.
34
+ // The class also provides `Skip()`, `Seek()` and `Read()` methods similar to
35
+ // CordRepBtreeNavigator that allow more advanced navigation.
36
+ //
37
+ // Example: iterate over all data inside a cord btree:
38
+ //
39
+ // CordRepBtreeReader reader;
40
+ // for (string_view sv = reader.Init(tree); !sv.Empty(); sv = sv.Next()) {
41
+ // DoSomethingWithDataIn(sv);
42
+ // }
43
+ //
44
+ // All navigation methods always return the next 'chunk' of data. The class
45
+ // assumes that all data is directly 'consumed' by the caller. For example:
46
+ // invoking `Skip()` will skip the desired number of bytes, and directly
47
+ // read and return the next chunk of data directly after the skipped bytes.
48
+ //
49
+ // Example: iterate over all data inside a btree skipping the first 100 bytes:
50
+ //
51
+ // CordRepBtreeReader reader;
52
+ // absl::string_view sv = reader.Init(tree);
53
+ // if (sv.length() > 100) {
54
+ // sv.RemovePrefix(100);
55
+ // } else {
56
+ // sv = reader.Skip(100 - sv.length());
57
+ // }
58
+ // while (!sv.empty()) {
59
+ // DoSomethingWithDataIn(sv);
60
+ // absl::string_view sv = reader.Next();
61
+ // }
62
+ //
63
+ // It is important to notice that `remaining` is based on the end position of
64
+ // the last data edge returned to the caller, not the cumulative data returned
65
+ // to the caller which can be less in cases of skipping or seeking over data.
66
+ //
67
+ // For example, consider a cord btree with five data edges: "abc", "def", "ghi",
68
+ // "jkl" and "mno":
69
+ //
70
+ // absl::string_view sv;
71
+ // CordRepBtreeReader reader;
72
+ //
73
+ // sv = reader.Init(tree); // sv = "abc", remaining = 12
74
+ // sv = reader.Skip(4); // sv = "hi", remaining = 6
75
+ // sv = reader.Skip(2); // sv = "l", remaining = 3
76
+ // sv = reader.Next(); // sv = "mno", remaining = 0
77
+ // sv = reader.Seek(1); // sv = "bc", remaining = 12
78
+ //
79
+ class CordRepBtreeReader {
80
+ public:
81
+ using ReadResult = CordRepBtreeNavigator::ReadResult;
82
+ using Position = CordRepBtreeNavigator::Position;
83
+
84
+ // Returns true if this instance is not empty.
85
+ explicit operator bool() const { return navigator_.btree() != nullptr; }
86
+
87
+ // Returns the tree referenced by this instance or nullptr if empty.
88
+ CordRepBtree* btree() const { return navigator_.btree(); }
89
+
90
+ // Returns the current data edge inside the referenced btree.
91
+ // Requires that the current instance is not empty.
92
+ CordRep* node() const { return navigator_.Current(); }
93
+
94
+ // Returns the length of the referenced tree.
95
+ // Requires that the current instance is not empty.
96
+ size_t length() const;
97
+
98
+ // Returns the number of remaining bytes available for iteration, which is the
99
+ // number of bytes directly following the end of the last chunk returned.
100
+ // This value will be zero if we iterated over the last edge in the bound
101
+ // tree, in which case any call to Next() or Skip() will return an empty
102
+ // string_view reflecting the EOF state.
103
+ // Note that a call to `Seek()` resets `remaining` to a value based on the
104
+ // end position of the chunk returned by that call.
105
+ size_t remaining() const { return remaining_; }
106
+
107
+ // Resets this instance to an empty value.
108
+ void Reset() { navigator_.Reset(); }
109
+
110
+ // Initializes this instance with `tree`. `tree` must not be null.
111
+ // Returns a reference to the first data edge of the provided tree.
112
+ absl::string_view Init(CordRepBtree* tree);
113
+
114
+ // Navigates to and returns the next data edge of the referenced tree.
115
+ // Returns an empty string_view if an attempt is made to read beyond the end
116
+ // of the tree, i.e.: if `remaining()` is zero indicating an EOF condition.
117
+ // Requires that the current instance is not empty.
118
+ absl::string_view Next();
119
+
120
+ // Skips the provided amount of bytes and returns a reference to the data
121
+ // directly following the skipped bytes.
122
+ absl::string_view Skip(size_t skip);
123
+
124
+ // Reads `n` bytes into `tree`.
125
+ // If `chunk_size` is zero, starts reading at the next data edge. If
126
+ // `chunk_size` is non zero, the read starts at the last `chunk_size` bytes of
127
+ // the last returned data edge. Effectively, this means that the read starts
128
+ // at offset `consumed() - chunk_size`.
129
+ // Requires that `chunk_size` is less than or equal to the length of the
130
+ // last returned data edge. The purpose of `chunk_size` is to simplify code
131
+ // partially consuming a returned chunk and wanting to include the remaining
132
+ // bytes in the Read call. For example, the below code will read 1000 bytes of
133
+ // data into a cord tree if the first chunk starts with "big:":
134
+ //
135
+ // CordRepBtreeReader reader;
136
+ // absl::string_view sv = reader.Init(tree);
137
+ // if (absl::StartsWith(sv, "big:")) {
138
+ // CordRepBtree tree;
139
+ // sv = reader.Read(1000, sv.size() - 4 /* "big:" */, &tree);
140
+ // }
141
+ //
142
+ // This method will return an empty string view if all remaining data was
143
+ // read. If `n` exceeded the amount of remaining data this function will
144
+ // return an empty string view and `tree` will be set to nullptr.
145
+ // In both cases, `consumed` will be set to `length`.
146
+ absl::string_view Read(size_t n, size_t chunk_size, CordRep*& tree);
147
+
148
+ // Navigates to the chunk at offset `offset`.
149
+ // Returns a reference into the navigated to chunk, adjusted for the relative
150
+ // position of `offset` into that chunk. For example, calling `Seek(13)` on a
151
+ // cord tree containing 2 chunks of 10 and 20 bytes respectively will return
152
+ // a string view into the second chunk starting at offset 3 with a size of 17.
153
+ // Returns an empty string view if `offset` is equal to or greater than the
154
+ // length of the referenced tree.
155
+ absl::string_view Seek(size_t offset);
156
+
157
+ private:
158
+ size_t remaining_ = 0;
159
+ CordRepBtreeNavigator navigator_;
160
+ };
161
+
162
+ inline size_t CordRepBtreeReader::length() const {
163
+ assert(btree() != nullptr);
164
+ return btree()->length;
165
+ }
166
+
167
+ inline absl::string_view CordRepBtreeReader::Init(CordRepBtree* tree) {
168
+ assert(tree != nullptr);
169
+ const CordRep* edge = navigator_.InitFirst(tree);
170
+ remaining_ = tree->length - edge->length;
171
+ return EdgeData(edge);
172
+ }
173
+
174
+ inline absl::string_view CordRepBtreeReader::Next() {
175
+ if (remaining_ == 0) return {};
176
+ const CordRep* edge = navigator_.Next();
177
+ assert(edge != nullptr);
178
+ remaining_ -= edge->length;
179
+ return EdgeData(edge);
180
+ }
181
+
182
+ inline absl::string_view CordRepBtreeReader::Skip(size_t skip) {
183
+ // As we are always positioned on the last 'consumed' edge, we
184
+ // need to skip the current edge as well as `skip`.
185
+ const size_t edge_length = navigator_.Current()->length;
186
+ CordRepBtreeNavigator::Position pos = navigator_.Skip(skip + edge_length);
187
+ if (ABSL_PREDICT_FALSE(pos.edge == nullptr)) {
188
+ remaining_ = 0;
189
+ return {};
190
+ }
191
+ // The combined length of all edges skipped before `pos.edge` is `skip -
192
+ // pos.offset`, all of which are 'consumed', as well as the current edge.
193
+ remaining_ -= skip - pos.offset + pos.edge->length;
194
+ return EdgeData(pos.edge).substr(pos.offset);
195
+ }
196
+
197
+ inline absl::string_view CordRepBtreeReader::Seek(size_t offset) {
198
+ const CordRepBtreeNavigator::Position pos = navigator_.Seek(offset);
199
+ if (ABSL_PREDICT_FALSE(pos.edge == nullptr)) {
200
+ remaining_ = 0;
201
+ return {};
202
+ }
203
+ absl::string_view chunk = EdgeData(pos.edge).substr(pos.offset);
204
+ remaining_ = length() - offset - chunk.length();
205
+ return chunk;
206
+ }
207
+
208
+ } // namespace cord_internal
209
+ ABSL_NAMESPACE_END
210
+ } // namespace absl
211
+
212
+ #endif // ABSL_STRINGS_INTERNAL_CORD_REP_BTREE_READER_H_
weight/_dep/abseil-cpp/absl/strings/internal/cord_rep_btree_reader_test.cc ADDED
@@ -0,0 +1,293 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Copyright 2021 The Abseil Authors
2
+ //
3
+ // Licensed under the Apache License, Version 2.0 (the "License");
4
+ // you may not use this file except in compliance with the License.
5
+ // You may obtain a copy of the License at
6
+ //
7
+ // https://www.apache.org/licenses/LICENSE-2.0
8
+ //
9
+ // Unless required by applicable law or agreed to in writing, software
10
+ // distributed under the License is distributed on an "AS IS" BASIS,
11
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ // See the License for the specific language governing permissions and
13
+ // limitations under the License.
14
+
15
+ #include "absl/strings/internal/cord_rep_btree_reader.h"
16
+
17
+ #include <iostream>
18
+ #include <random>
19
+ #include <string>
20
+ #include <vector>
21
+
22
+ #include "gmock/gmock.h"
23
+ #include "gtest/gtest.h"
24
+ #include "absl/base/config.h"
25
+ #include "absl/base/internal/raw_logging.h"
26
+ #include "absl/strings/cord.h"
27
+ #include "absl/strings/internal/cord_internal.h"
28
+ #include "absl/strings/internal/cord_rep_btree.h"
29
+ #include "absl/strings/internal/cord_rep_test_util.h"
30
+ #include "absl/strings/string_view.h"
31
+
32
+ namespace absl {
33
+ ABSL_NAMESPACE_BEGIN
34
+ namespace cord_internal {
35
+ namespace {
36
+
37
+ using ::testing::Eq;
38
+ using ::testing::IsEmpty;
39
+ using ::testing::Ne;
40
+ using ::testing::Not;
41
+
42
+ using ::absl::cordrep_testing::CordRepBtreeFromFlats;
43
+ using ::absl::cordrep_testing::MakeFlat;
44
+ using ::absl::cordrep_testing::CordToString;
45
+ using ::absl::cordrep_testing::CreateFlatsFromString;
46
+ using ::absl::cordrep_testing::CreateRandomString;
47
+
48
+ using ReadResult = CordRepBtreeReader::ReadResult;
49
+
50
+ TEST(CordRepBtreeReaderTest, Next) {
51
+ constexpr size_t kChars = 3;
52
+ const size_t cap = CordRepBtree::kMaxCapacity;
53
+ size_t counts[] = {1, 2, cap, cap * cap, cap * cap + 1, cap * cap * 2 + 17};
54
+
55
+ for (size_t count : counts) {
56
+ std::string data = CreateRandomString(count * kChars);
57
+ std::vector<CordRep*> flats = CreateFlatsFromString(data, kChars);
58
+ CordRepBtree* node = CordRepBtreeFromFlats(flats);
59
+
60
+ CordRepBtreeReader reader;
61
+ size_t remaining = data.length();
62
+ absl::string_view chunk = reader.Init(node);
63
+ EXPECT_THAT(chunk, Eq(data.substr(0, chunk.length())));
64
+
65
+ remaining -= chunk.length();
66
+ EXPECT_THAT(reader.remaining(), Eq(remaining));
67
+
68
+ while (remaining > 0) {
69
+ const size_t offset = data.length() - remaining;
70
+ chunk = reader.Next();
71
+ EXPECT_THAT(chunk, Eq(data.substr(offset, chunk.length())));
72
+
73
+ remaining -= chunk.length();
74
+ EXPECT_THAT(reader.remaining(), Eq(remaining));
75
+ }
76
+
77
+ EXPECT_THAT(reader.remaining(), Eq(0u));
78
+
79
+ // Verify trying to read beyond EOF returns empty string_view
80
+ EXPECT_THAT(reader.Next(), testing::IsEmpty());
81
+
82
+ CordRep::Unref(node);
83
+ }
84
+ }
85
+
86
+ TEST(CordRepBtreeReaderTest, Skip) {
87
+ constexpr size_t kChars = 3;
88
+ const size_t cap = CordRepBtree::kMaxCapacity;
89
+ size_t counts[] = {1, 2, cap, cap * cap, cap * cap + 1, cap * cap * 2 + 17};
90
+
91
+ for (size_t count : counts) {
92
+ std::string data = CreateRandomString(count * kChars);
93
+ std::vector<CordRep*> flats = CreateFlatsFromString(data, kChars);
94
+ CordRepBtree* node = CordRepBtreeFromFlats(flats);
95
+
96
+ for (size_t skip1 = 0; skip1 < data.length() - kChars; ++skip1) {
97
+ for (size_t skip2 = 0; skip2 < data.length() - kChars; ++skip2) {
98
+ CordRepBtreeReader reader;
99
+ size_t remaining = data.length();
100
+ absl::string_view chunk = reader.Init(node);
101
+ remaining -= chunk.length();
102
+
103
+ chunk = reader.Skip(skip1);
104
+ size_t offset = data.length() - remaining;
105
+ ASSERT_THAT(chunk, Eq(data.substr(offset + skip1, chunk.length())));
106
+ remaining -= chunk.length() + skip1;
107
+ ASSERT_THAT(reader.remaining(), Eq(remaining));
108
+
109
+ if (remaining == 0) continue;
110
+
111
+ size_t skip = std::min(remaining - 1, skip2);
112
+ chunk = reader.Skip(skip);
113
+ offset = data.length() - remaining;
114
+ ASSERT_THAT(chunk, Eq(data.substr(offset + skip, chunk.length())));
115
+ }
116
+ }
117
+
118
+ CordRep::Unref(node);
119
+ }
120
+ }
121
+
122
+ TEST(CordRepBtreeReaderTest, SkipBeyondLength) {
123
+ CordRepBtree* tree = CordRepBtree::Create(MakeFlat("abc"));
124
+ tree = CordRepBtree::Append(tree, MakeFlat("def"));
125
+ CordRepBtreeReader reader;
126
+ reader.Init(tree);
127
+ EXPECT_THAT(reader.Skip(100), IsEmpty());
128
+ EXPECT_THAT(reader.remaining(), Eq(0u));
129
+ CordRep::Unref(tree);
130
+ }
131
+
132
+ TEST(CordRepBtreeReaderTest, Seek) {
133
+ constexpr size_t kChars = 3;
134
+ const size_t cap = CordRepBtree::kMaxCapacity;
135
+ size_t counts[] = {1, 2, cap, cap * cap, cap * cap + 1, cap * cap * 2 + 17};
136
+
137
+ for (size_t count : counts) {
138
+ std::string data = CreateRandomString(count * kChars);
139
+ std::vector<CordRep*> flats = CreateFlatsFromString(data, kChars);
140
+ CordRepBtree* node = CordRepBtreeFromFlats(flats);
141
+
142
+ for (size_t seek = 0; seek < data.length() - 1; ++seek) {
143
+ CordRepBtreeReader reader;
144
+ reader.Init(node);
145
+ absl::string_view chunk = reader.Seek(seek);
146
+ ASSERT_THAT(chunk, Not(IsEmpty()));
147
+ ASSERT_THAT(chunk, Eq(data.substr(seek, chunk.length())));
148
+ ASSERT_THAT(reader.remaining(),
149
+ Eq(data.length() - seek - chunk.length()));
150
+ }
151
+
152
+ CordRep::Unref(node);
153
+ }
154
+ }
155
+
156
+ TEST(CordRepBtreeReaderTest, SeekBeyondLength) {
157
+ CordRepBtree* tree = CordRepBtree::Create(MakeFlat("abc"));
158
+ tree = CordRepBtree::Append(tree, MakeFlat("def"));
159
+ CordRepBtreeReader reader;
160
+ reader.Init(tree);
161
+ EXPECT_THAT(reader.Seek(6), IsEmpty());
162
+ EXPECT_THAT(reader.remaining(), Eq(0u));
163
+ EXPECT_THAT(reader.Seek(100), IsEmpty());
164
+ EXPECT_THAT(reader.remaining(), Eq(0u));
165
+ CordRep::Unref(tree);
166
+ }
167
+
168
+ TEST(CordRepBtreeReaderTest, Read) {
169
+ std::string data = "abcdefghijklmno";
170
+ std::vector<CordRep*> flats = CreateFlatsFromString(data, 5);
171
+ CordRepBtree* node = CordRepBtreeFromFlats(flats);
172
+
173
+ CordRep* tree;
174
+ CordRepBtreeReader reader;
175
+ absl::string_view chunk;
176
+
177
+ // Read zero bytes
178
+ chunk = reader.Init(node);
179
+ chunk = reader.Read(0, chunk.length(), tree);
180
+ EXPECT_THAT(tree, Eq(nullptr));
181
+ EXPECT_THAT(chunk, Eq("abcde"));
182
+ EXPECT_THAT(reader.remaining(), Eq(10u));
183
+ EXPECT_THAT(reader.Next(), Eq("fghij"));
184
+
185
+ // Read in full
186
+ chunk = reader.Init(node);
187
+ chunk = reader.Read(15, chunk.length(), tree);
188
+ EXPECT_THAT(tree, Ne(nullptr));
189
+ EXPECT_THAT(CordToString(tree), Eq("abcdefghijklmno"));
190
+ EXPECT_THAT(chunk, Eq(""));
191
+ EXPECT_THAT(reader.remaining(), Eq(0u));
192
+ CordRep::Unref(tree);
193
+
194
+ // Read < chunk bytes
195
+ chunk = reader.Init(node);
196
+ chunk = reader.Read(3, chunk.length(), tree);
197
+ ASSERT_THAT(tree, Ne(nullptr));
198
+ EXPECT_THAT(CordToString(tree), Eq("abc"));
199
+ EXPECT_THAT(chunk, Eq("de"));
200
+ EXPECT_THAT(reader.remaining(), Eq(10u));
201
+ EXPECT_THAT(reader.Next(), Eq("fghij"));
202
+ CordRep::Unref(tree);
203
+
204
+ // Read < chunk bytes at offset
205
+ chunk = reader.Init(node);
206
+ chunk = reader.Read(2, chunk.length() - 2, tree);
207
+ ASSERT_THAT(tree, Ne(nullptr));
208
+ EXPECT_THAT(CordToString(tree), Eq("cd"));
209
+ EXPECT_THAT(chunk, Eq("e"));
210
+ EXPECT_THAT(reader.remaining(), Eq(10u));
211
+ EXPECT_THAT(reader.Next(), Eq("fghij"));
212
+ CordRep::Unref(tree);
213
+
214
+ // Read from consumed chunk
215
+ chunk = reader.Init(node);
216
+ chunk = reader.Read(3, 0, tree);
217
+ ASSERT_THAT(tree, Ne(nullptr));
218
+ EXPECT_THAT(CordToString(tree), Eq("fgh"));
219
+ EXPECT_THAT(chunk, Eq("ij"));
220
+ EXPECT_THAT(reader.remaining(), Eq(5u));
221
+ EXPECT_THAT(reader.Next(), Eq("klmno"));
222
+ CordRep::Unref(tree);
223
+
224
+ // Read across chunks
225
+ chunk = reader.Init(node);
226
+ chunk = reader.Read(12, chunk.length() - 2, tree);
227
+ ASSERT_THAT(tree, Ne(nullptr));
228
+ EXPECT_THAT(CordToString(tree), Eq("cdefghijklmn"));
229
+ EXPECT_THAT(chunk, Eq("o"));
230
+ EXPECT_THAT(reader.remaining(), Eq(0u));
231
+ CordRep::Unref(tree);
232
+
233
+ // Read across chunks landing on exact edge boundary
234
+ chunk = reader.Init(node);
235
+ chunk = reader.Read(10 - 2, chunk.length() - 2, tree);
236
+ ASSERT_THAT(tree, Ne(nullptr));
237
+ EXPECT_THAT(CordToString(tree), Eq("cdefghij"));
238
+ EXPECT_THAT(chunk, Eq("klmno"));
239
+ EXPECT_THAT(reader.remaining(), Eq(0u));
240
+ CordRep::Unref(tree);
241
+
242
+ CordRep::Unref(node);
243
+ }
244
+
245
+ TEST(CordRepBtreeReaderTest, ReadExhaustive) {
246
+ constexpr size_t kChars = 3;
247
+ const size_t cap = CordRepBtree::kMaxCapacity;
248
+ size_t counts[] = {1, 2, cap, cap * cap + 1, cap * cap * cap * 2 + 17};
249
+
250
+ for (size_t count : counts) {
251
+ std::string data = CreateRandomString(count * kChars);
252
+ std::vector<CordRep*> flats = CreateFlatsFromString(data, kChars);
253
+ CordRepBtree* node = CordRepBtreeFromFlats(flats);
254
+
255
+ for (size_t read_size : {kChars - 1, kChars, kChars + 7, cap * cap}) {
256
+ CordRepBtreeReader reader;
257
+ absl::string_view chunk = reader.Init(node);
258
+
259
+ // `consumed` tracks the end of last consumed chunk which is the start of
260
+ // the next chunk: we always read with `chunk_size = chunk.length()`.
261
+ size_t consumed = 0;
262
+ size_t remaining = data.length();
263
+ while (remaining > 0) {
264
+ CordRep* tree;
265
+ size_t n = (std::min)(remaining, read_size);
266
+ chunk = reader.Read(n, chunk.length(), tree);
267
+ EXPECT_THAT(tree, Ne(nullptr));
268
+ if (tree) {
269
+ EXPECT_THAT(CordToString(tree), Eq(data.substr(consumed, n)));
270
+ CordRep::Unref(tree);
271
+ }
272
+
273
+ consumed += n;
274
+ remaining -= n;
275
+ EXPECT_THAT(reader.remaining(), Eq(remaining - chunk.length()));
276
+
277
+ if (remaining > 0) {
278
+ ASSERT_FALSE(chunk.empty());
279
+ ASSERT_THAT(chunk, Eq(data.substr(consumed, chunk.length())));
280
+ } else {
281
+ ASSERT_TRUE(chunk.empty()) << chunk;
282
+ }
283
+ }
284
+ }
285
+
286
+ CordRep::Unref(node);
287
+ }
288
+ }
289
+
290
+ } // namespace
291
+ } // namespace cord_internal
292
+ ABSL_NAMESPACE_END
293
+ } // namespace absl
weight/_dep/abseil-cpp/absl/strings/internal/cord_rep_btree_test.cc ADDED
@@ -0,0 +1,1568 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Copyright 2021 The Abseil Authors
2
+ //
3
+ // Licensed under the Apache License, Version 2.0 (the "License");
4
+ // you may not use this file except in compliance with the License.
5
+ // You may obtain a copy of the License at
6
+ //
7
+ // https://www.apache.org/licenses/LICENSE-2.0
8
+ //
9
+ // Unless required by applicable law or agreed to in writing, software
10
+ // distributed under the License is distributed on an "AS IS" BASIS,
11
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ // See the License for the specific language governing permissions and
13
+ // limitations under the License.
14
+
15
+ #include "absl/strings/internal/cord_rep_btree.h"
16
+
17
+ #include <cmath>
18
+ #include <deque>
19
+ #include <iostream>
20
+ #include <string>
21
+ #include <vector>
22
+
23
+ #include "gmock/gmock.h"
24
+ #include "gtest/gtest.h"
25
+ #include "absl/base/config.h"
26
+ #include "absl/base/internal/raw_logging.h"
27
+ #include "absl/cleanup/cleanup.h"
28
+ #include "absl/strings/internal/cord_data_edge.h"
29
+ #include "absl/strings/internal/cord_internal.h"
30
+ #include "absl/strings/internal/cord_rep_test_util.h"
31
+ #include "absl/strings/str_cat.h"
32
+ #include "absl/strings/string_view.h"
33
+
34
+ namespace absl {
35
+ ABSL_NAMESPACE_BEGIN
36
+ namespace cord_internal {
37
+
38
+ class CordRepBtreeTestPeer {
39
+ public:
40
+ static void SetEdge(CordRepBtree* node, size_t idx, CordRep* edge) {
41
+ node->edges_[idx] = edge;
42
+ }
43
+ static void AddEdge(CordRepBtree* node, CordRep* edge) {
44
+ node->edges_[node->fetch_add_end(1)] = edge;
45
+ }
46
+ };
47
+
48
+ namespace {
49
+
50
+ using ::absl::cordrep_testing::AutoUnref;
51
+ using ::absl::cordrep_testing::CordCollectRepsIf;
52
+ using ::absl::cordrep_testing::CordToString;
53
+ using ::absl::cordrep_testing::CordVisitReps;
54
+ using ::absl::cordrep_testing::CreateFlatsFromString;
55
+ using ::absl::cordrep_testing::CreateRandomString;
56
+ using ::absl::cordrep_testing::MakeExternal;
57
+ using ::absl::cordrep_testing::MakeFlat;
58
+ using ::absl::cordrep_testing::MakeSubstring;
59
+ using ::testing::_;
60
+ using ::testing::AllOf;
61
+ using ::testing::AnyOf;
62
+ using ::testing::Conditional;
63
+ using ::testing::ElementsAre;
64
+ using ::testing::ElementsAreArray;
65
+ using ::testing::Eq;
66
+ using ::testing::HasSubstr;
67
+ using ::testing::Le;
68
+ using ::testing::Ne;
69
+ using ::testing::Not;
70
+ using ::testing::SizeIs;
71
+ using ::testing::TypedEq;
72
+
73
+ MATCHER_P(EqFlatHolding, data, "Equals flat holding data") {
74
+ if (arg->tag < FLAT) {
75
+ *result_listener << "Expected FLAT, got tag " << static_cast<int>(arg->tag);
76
+ return false;
77
+ }
78
+ std::string actual = CordToString(arg);
79
+ if (actual != data) {
80
+ *result_listener << "Expected flat holding \"" << data
81
+ << "\", got flat holding \"" << actual << "\"";
82
+ return false;
83
+ }
84
+ return true;
85
+ }
86
+
87
+ MATCHER_P(IsNode, height, absl::StrCat("Is a valid node of height ", height)) {
88
+ if (arg == nullptr) {
89
+ *result_listener << "Expected NODE, got nullptr";
90
+ return false;
91
+ }
92
+ if (arg->tag != BTREE) {
93
+ *result_listener << "Expected NODE, got " << static_cast<int>(arg->tag);
94
+ return false;
95
+ }
96
+ if (!CordRepBtree::IsValid(arg->btree())) {
97
+ CordRepBtree::Dump(arg->btree(), "Expected valid NODE, got:", false,
98
+ *result_listener->stream());
99
+ return false;
100
+ }
101
+ if (arg->btree()->height() != height) {
102
+ *result_listener << "Expected NODE of height " << height << ", got "
103
+ << arg->btree()->height();
104
+ return false;
105
+ }
106
+ return true;
107
+ }
108
+
109
+ MATCHER_P2(IsSubstring, start, length,
110
+ absl::StrCat("Is a substring(start = ", start, ", length = ", length,
111
+ ")")) {
112
+ if (arg == nullptr) {
113
+ *result_listener << "Expected substring, got nullptr";
114
+ return false;
115
+ }
116
+ if (arg->tag != SUBSTRING) {
117
+ *result_listener << "Expected SUBSTRING, got "
118
+ << static_cast<int>(arg->tag);
119
+ return false;
120
+ }
121
+ const CordRepSubstring* const substr = arg->substring();
122
+ if (substr->start != start || substr->length != length) {
123
+ *result_listener << "Expected substring(" << start << ", " << length
124
+ << "), got substring(" << substr->start << ", "
125
+ << substr->length << ")";
126
+ return false;
127
+ }
128
+ return true;
129
+ }
130
+
131
+ MATCHER_P2(EqExtractResult, tree, rep, "Equals ExtractResult") {
132
+ if (arg.tree != tree || arg.extracted != rep) {
133
+ *result_listener << "Expected {" << static_cast<const void*>(tree) << ", "
134
+ << static_cast<const void*>(rep) << "}, got {" << arg.tree
135
+ << ", " << arg.extracted << "}";
136
+ return false;
137
+ }
138
+ return true;
139
+ }
140
+
141
+ // DataConsumer is a simple helper class used by tests to 'consume' string
142
+ // fragments from the provided input in forward or backward direction.
143
+ class DataConsumer {
144
+ public:
145
+ // Starts consumption of `data`. Caller must make sure `data` outlives this
146
+ // instance. Consumes data starting at the front if `forward` is true, else
147
+ // consumes data from the back.
148
+ DataConsumer(absl::string_view data, bool forward)
149
+ : data_(data), forward_(forward) {}
150
+
151
+ // Return the next `n` bytes from referenced data.
152
+ absl::string_view Next(size_t n) {
153
+ assert(n <= data_.size() - consumed_);
154
+ consumed_ += n;
155
+ return data_.substr(forward_ ? consumed_ - n : data_.size() - consumed_, n);
156
+ }
157
+
158
+ // Returns all data consumed so far.
159
+ absl::string_view Consumed() const {
160
+ return forward_ ? data_.substr(0, consumed_)
161
+ : data_.substr(data_.size() - consumed_);
162
+ }
163
+
164
+ private:
165
+ absl::string_view data_;
166
+ size_t consumed_ = 0;
167
+ bool forward_;
168
+ };
169
+
170
+ // BtreeAdd returns either CordRepBtree::Append or CordRepBtree::Prepend.
171
+ CordRepBtree* BtreeAdd(CordRepBtree* node, bool append,
172
+ absl::string_view data) {
173
+ return append ? CordRepBtree::Append(node, data)
174
+ : CordRepBtree::Prepend(node, data);
175
+ }
176
+
177
+ // Recursively collects all leaf edges from `tree` and appends them to `edges`.
178
+ void GetLeafEdges(const CordRepBtree* tree, std::vector<CordRep*>& edges) {
179
+ if (tree->height() == 0) {
180
+ for (CordRep* edge : tree->Edges()) {
181
+ edges.push_back(edge);
182
+ }
183
+ } else {
184
+ for (CordRep* edge : tree->Edges()) {
185
+ GetLeafEdges(edge->btree(), edges);
186
+ }
187
+ }
188
+ }
189
+
190
+ // Recursively collects and returns all leaf edges from `tree`.
191
+ std::vector<CordRep*> GetLeafEdges(const CordRepBtree* tree) {
192
+ std::vector<CordRep*> edges;
193
+ GetLeafEdges(tree, edges);
194
+ return edges;
195
+ }
196
+
197
+ // Creates a flat containing the hexadecimal value of `i` zero padded
198
+ // to at least 4 digits prefixed with "0x", e.g.: "0x04AC".
199
+ CordRepFlat* MakeHexFlat(size_t i) {
200
+ return MakeFlat(absl::StrCat("0x", absl::Hex(i, absl::kZeroPad4)));
201
+ }
202
+
203
+ CordRepBtree* MakeLeaf(size_t size = CordRepBtree::kMaxCapacity) {
204
+ assert(size <= CordRepBtree::kMaxCapacity);
205
+ CordRepBtree* leaf = CordRepBtree::Create(MakeHexFlat(0));
206
+ for (size_t i = 1; i < size; ++i) {
207
+ leaf = CordRepBtree::Append(leaf, MakeHexFlat(i));
208
+ }
209
+ return leaf;
210
+ }
211
+
212
+ CordRepBtree* MakeTree(size_t size, bool append = true) {
213
+ CordRepBtree* tree = CordRepBtree::Create(MakeHexFlat(0));
214
+ for (size_t i = 1; i < size; ++i) {
215
+ tree = append ? CordRepBtree::Append(tree, MakeHexFlat(i))
216
+ : CordRepBtree::Prepend(tree, MakeHexFlat(i));
217
+ }
218
+ return tree;
219
+ }
220
+
221
+ CordRepBtree* CreateTree(absl::Span<CordRep* const> reps) {
222
+ auto it = reps.begin();
223
+ CordRepBtree* tree = CordRepBtree::Create(*it);
224
+ while (++it != reps.end()) tree = CordRepBtree::Append(tree, *it);
225
+ return tree;
226
+ }
227
+
228
+ CordRepBtree* CreateTree(absl::string_view data, size_t chunk_size) {
229
+ return CreateTree(CreateFlatsFromString(data, chunk_size));
230
+ }
231
+
232
+ CordRepBtree* CreateTreeReverse(absl::string_view data, size_t chunk_size) {
233
+ std::vector<CordRep*> flats = CreateFlatsFromString(data, chunk_size);
234
+ auto rit = flats.rbegin();
235
+ CordRepBtree* tree = CordRepBtree::Create(*rit);
236
+ while (++rit != flats.rend()) tree = CordRepBtree::Prepend(tree, *rit);
237
+ return tree;
238
+ }
239
+
240
+ class CordRepBtreeTest : public testing::TestWithParam<bool> {
241
+ public:
242
+ bool shared() const { return GetParam(); }
243
+
244
+ static std::string ToString(testing::TestParamInfo<bool> param) {
245
+ return param.param ? "Shared" : "Private";
246
+ }
247
+ };
248
+
249
+ INSTANTIATE_TEST_SUITE_P(WithParam, CordRepBtreeTest, testing::Bool(),
250
+ CordRepBtreeTest::ToString);
251
+
252
+ class CordRepBtreeHeightTest : public testing::TestWithParam<int> {
253
+ public:
254
+ int height() const { return GetParam(); }
255
+
256
+ static std::string ToString(testing::TestParamInfo<int> param) {
257
+ return absl::StrCat(param.param);
258
+ }
259
+ };
260
+
261
+ INSTANTIATE_TEST_SUITE_P(WithHeights, CordRepBtreeHeightTest,
262
+ testing::Range(0, CordRepBtree::kMaxHeight),
263
+ CordRepBtreeHeightTest::ToString);
264
+
265
+ using TwoBools = testing::tuple<bool, bool>;
266
+
267
+ class CordRepBtreeDualTest : public testing::TestWithParam<TwoBools> {
268
+ public:
269
+ bool first_shared() const { return std::get<0>(GetParam()); }
270
+ bool second_shared() const { return std::get<1>(GetParam()); }
271
+
272
+ static std::string ToString(testing::TestParamInfo<TwoBools> param) {
273
+ if (std::get<0>(param.param)) {
274
+ return std::get<1>(param.param) ? "BothShared" : "FirstShared";
275
+ }
276
+ return std::get<1>(param.param) ? "SecondShared" : "Private";
277
+ }
278
+ };
279
+
280
+ INSTANTIATE_TEST_SUITE_P(WithParam, CordRepBtreeDualTest,
281
+ testing::Combine(testing::Bool(), testing::Bool()),
282
+ CordRepBtreeDualTest::ToString);
283
+
284
+ TEST(CordRepBtreeTest, SizeIsMultipleOf64) {
285
+ // Only enforce for fully 64-bit platforms.
286
+ if (sizeof(size_t) == 8 && sizeof(void*) == 8) {
287
+ EXPECT_THAT(sizeof(CordRepBtree) % 64, Eq(0u))
288
+ << "Should be multiple of 64";
289
+ }
290
+ }
291
+
292
+ TEST(CordRepBtreeTest, NewDestroyEmptyTree) {
293
+ auto* tree = CordRepBtree::New();
294
+ EXPECT_THAT(tree->size(), Eq(0u));
295
+ EXPECT_THAT(tree->height(), Eq(0));
296
+ EXPECT_THAT(tree->Edges(), ElementsAre());
297
+ CordRepBtree::Destroy(tree);
298
+ }
299
+
300
+ TEST(CordRepBtreeTest, NewDestroyEmptyTreeAtHeight) {
301
+ auto* tree = CordRepBtree::New(3);
302
+ EXPECT_THAT(tree->size(), Eq(0u));
303
+ EXPECT_THAT(tree->height(), Eq(3));
304
+ EXPECT_THAT(tree->Edges(), ElementsAre());
305
+ CordRepBtree::Destroy(tree);
306
+ }
307
+
308
+ TEST(CordRepBtreeTest, Btree) {
309
+ CordRep* rep = CordRepBtree::New();
310
+ EXPECT_THAT(rep->btree(), Eq(rep));
311
+ EXPECT_THAT(static_cast<const CordRep*>(rep)->btree(), Eq(rep));
312
+ CordRep::Unref(rep);
313
+ #if defined(GTEST_HAS_DEATH_TEST) && !defined(NDEBUG)
314
+ rep = MakeFlat("Hello world");
315
+ EXPECT_DEATH(rep->btree(), ".*");
316
+ EXPECT_DEATH(static_cast<const CordRep*>(rep)->btree(), ".*");
317
+ CordRep::Unref(rep);
318
+ #endif
319
+ }
320
+
321
+ TEST(CordRepBtreeTest, EdgeData) {
322
+ CordRepFlat* flat = MakeFlat("Hello world");
323
+ CordRepExternal* external = MakeExternal("Hello external");
324
+ CordRep* substr1 = MakeSubstring(1, 6, CordRep::Ref(flat));
325
+ CordRep* substr2 = MakeSubstring(1, 6, CordRep::Ref(external));
326
+ CordRep* bad_substr = MakeSubstring(1, 2, CordRep::Ref(substr1));
327
+
328
+ EXPECT_TRUE(IsDataEdge(flat));
329
+ EXPECT_THAT(EdgeData(flat).data(), TypedEq<const void*>(flat->Data()));
330
+ EXPECT_THAT(EdgeData(flat), Eq("Hello world"));
331
+
332
+ EXPECT_TRUE(IsDataEdge(external));
333
+ EXPECT_THAT(EdgeData(external).data(), TypedEq<const void*>(external->base));
334
+ EXPECT_THAT(EdgeData(external), Eq("Hello external"));
335
+
336
+ EXPECT_TRUE(IsDataEdge(substr1));
337
+ EXPECT_THAT(EdgeData(substr1).data(), TypedEq<const void*>(flat->Data() + 1));
338
+ EXPECT_THAT(EdgeData(substr1), Eq("ello w"));
339
+
340
+ EXPECT_TRUE(IsDataEdge(substr2));
341
+ EXPECT_THAT(EdgeData(substr2).data(),
342
+ TypedEq<const void*>(external->base + 1));
343
+ EXPECT_THAT(EdgeData(substr2), Eq("ello e"));
344
+
345
+ EXPECT_FALSE(IsDataEdge(bad_substr));
346
+ #if defined(GTEST_HAS_DEATH_TEST) && !defined(NDEBUG)
347
+ EXPECT_DEATH(EdgeData(bad_substr), ".*");
348
+ #endif
349
+
350
+ CordRep::Unref(bad_substr);
351
+ CordRep::Unref(substr2);
352
+ CordRep::Unref(substr1);
353
+ CordRep::Unref(external);
354
+ CordRep::Unref(flat);
355
+ }
356
+
357
+ TEST(CordRepBtreeTest, CreateUnrefLeaf) {
358
+ auto* flat = MakeFlat("a");
359
+ auto* leaf = CordRepBtree::Create(flat);
360
+ EXPECT_THAT(leaf->size(), Eq(1u));
361
+ EXPECT_THAT(leaf->height(), Eq(0));
362
+ EXPECT_THAT(leaf->Edges(), ElementsAre(flat));
363
+ CordRepBtree::Unref(leaf);
364
+ }
365
+
366
+ TEST(CordRepBtreeTest, NewUnrefNode) {
367
+ auto* leaf = CordRepBtree::Create(MakeFlat("a"));
368
+ CordRepBtree* tree = CordRepBtree::New(leaf);
369
+ EXPECT_THAT(tree->size(), Eq(1u));
370
+ EXPECT_THAT(tree->height(), Eq(1));
371
+ EXPECT_THAT(tree->Edges(), ElementsAre(leaf));
372
+ CordRepBtree::Unref(tree);
373
+ }
374
+
375
+ TEST_P(CordRepBtreeTest, AppendToLeafToCapacity) {
376
+ AutoUnref refs;
377
+ std::vector<CordRep*> flats;
378
+ flats.push_back(MakeHexFlat(0));
379
+ auto* leaf = CordRepBtree::Create(flats.back());
380
+
381
+ for (size_t i = 1; i < CordRepBtree::kMaxCapacity; ++i) {
382
+ refs.RefIf(shared(), leaf);
383
+ flats.push_back(MakeHexFlat(i));
384
+ auto* result = CordRepBtree::Append(leaf, flats.back());
385
+ EXPECT_THAT(result->height(), Eq(0));
386
+ EXPECT_THAT(result, Conditional(shared(), Ne(leaf), Eq(leaf)));
387
+ EXPECT_THAT(result->Edges(), ElementsAreArray(flats));
388
+ leaf = result;
389
+ }
390
+ CordRep::Unref(leaf);
391
+ }
392
+
393
+ TEST_P(CordRepBtreeTest, PrependToLeafToCapacity) {
394
+ AutoUnref refs;
395
+ std::deque<CordRep*> flats;
396
+ flats.push_front(MakeHexFlat(0));
397
+ auto* leaf = CordRepBtree::Create(flats.front());
398
+
399
+ for (size_t i = 1; i < CordRepBtree::kMaxCapacity; ++i) {
400
+ refs.RefIf(shared(), leaf);
401
+ flats.push_front(MakeHexFlat(i));
402
+ auto* result = CordRepBtree::Prepend(leaf, flats.front());
403
+ EXPECT_THAT(result->height(), Eq(0));
404
+ EXPECT_THAT(result, Conditional(shared(), Ne(leaf), Eq(leaf)));
405
+ EXPECT_THAT(result->Edges(), ElementsAreArray(flats));
406
+ leaf = result;
407
+ }
408
+ CordRep::Unref(leaf);
409
+ }
410
+
411
+ // This test specifically aims at code aligning data at either the front or the
412
+ // back of the contained `edges[]` array, alternating Append and Prepend will
413
+ // move `begin()` and `end()` values as needed for each added value.
414
+ TEST_P(CordRepBtreeTest, AppendPrependToLeafToCapacity) {
415
+ AutoUnref refs;
416
+ std::deque<CordRep*> flats;
417
+ flats.push_front(MakeHexFlat(0));
418
+ auto* leaf = CordRepBtree::Create(flats.front());
419
+
420
+ for (size_t i = 1; i < CordRepBtree::kMaxCapacity; ++i) {
421
+ refs.RefIf(shared(), leaf);
422
+ CordRepBtree* result;
423
+ if (i % 2 != 0) {
424
+ flats.push_front(MakeHexFlat(i));
425
+ result = CordRepBtree::Prepend(leaf, flats.front());
426
+ } else {
427
+ flats.push_back(MakeHexFlat(i));
428
+ result = CordRepBtree::Append(leaf, flats.back());
429
+ }
430
+ EXPECT_THAT(result->height(), Eq(0));
431
+ EXPECT_THAT(result, Conditional(shared(), Ne(leaf), Eq(leaf)));
432
+ EXPECT_THAT(result->Edges(), ElementsAreArray(flats));
433
+ leaf = result;
434
+ }
435
+ CordRep::Unref(leaf);
436
+ }
437
+
438
+ TEST_P(CordRepBtreeTest, AppendToLeafBeyondCapacity) {
439
+ AutoUnref refs;
440
+ auto* leaf = MakeLeaf();
441
+ refs.RefIf(shared(), leaf);
442
+ CordRep* flat = MakeFlat("abc");
443
+ auto* result = CordRepBtree::Append(leaf, flat);
444
+ ASSERT_THAT(result, IsNode(1));
445
+ EXPECT_THAT(result, Ne(leaf));
446
+ absl::Span<CordRep* const> edges = result->Edges();
447
+ ASSERT_THAT(edges, ElementsAre(leaf, IsNode(0)));
448
+ EXPECT_THAT(edges[1]->btree()->Edges(), ElementsAre(flat));
449
+ CordRep::Unref(result);
450
+ }
451
+
452
+ TEST_P(CordRepBtreeTest, PrependToLeafBeyondCapacity) {
453
+ AutoUnref refs;
454
+ auto* leaf = MakeLeaf();
455
+ refs.RefIf(shared(), leaf);
456
+ CordRep* flat = MakeFlat("abc");
457
+ auto* result = CordRepBtree::Prepend(leaf, flat);
458
+ ASSERT_THAT(result, IsNode(1));
459
+ EXPECT_THAT(result, Ne(leaf));
460
+ absl::Span<CordRep* const> edges = result->Edges();
461
+ ASSERT_THAT(edges, ElementsAre(IsNode(0), leaf));
462
+ EXPECT_THAT(edges[0]->btree()->Edges(), ElementsAre(flat));
463
+ CordRep::Unref(result);
464
+ }
465
+
466
+ TEST_P(CordRepBtreeTest, AppendToTreeOneDeep) {
467
+ constexpr size_t max_cap = CordRepBtree::kMaxCapacity;
468
+ AutoUnref refs;
469
+ std::vector<CordRep*> flats;
470
+ flats.push_back(MakeHexFlat(0));
471
+ CordRepBtree* tree = CordRepBtree::Create(flats.back());
472
+ for (size_t i = 1; i <= max_cap; ++i) {
473
+ flats.push_back(MakeHexFlat(i));
474
+ tree = CordRepBtree::Append(tree, flats.back());
475
+ }
476
+ ASSERT_THAT(tree, IsNode(1));
477
+
478
+ for (size_t i = max_cap + 1; i < max_cap * max_cap; ++i) {
479
+ // Ref top level tree based on param.
480
+ // Ref leaf node once every 4 iterations, which should not have an
481
+ // observable effect other than that the leaf itself is copied.
482
+ refs.RefIf(shared(), tree);
483
+ refs.RefIf(i % 4 == 0, tree->Edges().back());
484
+
485
+ flats.push_back(MakeHexFlat(i));
486
+ CordRepBtree* result = CordRepBtree::Append(tree, flats.back());
487
+ ASSERT_THAT(result, IsNode(1));
488
+ ASSERT_THAT(result, Conditional(shared(), Ne(tree), Eq(tree)));
489
+ std::vector<CordRep*> edges = GetLeafEdges(result);
490
+ ASSERT_THAT(edges, ElementsAreArray(flats));
491
+ tree = result;
492
+ }
493
+ CordRep::Unref(tree);
494
+ }
495
+
496
+ TEST_P(CordRepBtreeTest, AppendToTreeTwoDeep) {
497
+ constexpr size_t max_cap = CordRepBtree::kMaxCapacity;
498
+ AutoUnref refs;
499
+ std::vector<CordRep*> flats;
500
+ flats.push_back(MakeHexFlat(0));
501
+ CordRepBtree* tree = CordRepBtree::Create(flats.back());
502
+ for (size_t i = 1; i <= max_cap * max_cap; ++i) {
503
+ flats.push_back(MakeHexFlat(i));
504
+ tree = CordRepBtree::Append(tree, flats.back());
505
+ }
506
+ ASSERT_THAT(tree, IsNode(2));
507
+ for (size_t i = max_cap * max_cap + 1; i < max_cap * max_cap * max_cap; ++i) {
508
+ // Ref top level tree based on param.
509
+ // Ref child node once every 16 iterations, and leaf node every 4
510
+ // iterations which which should not have an observable effect other than
511
+ // the node and/or the leaf below it being copied.
512
+ refs.RefIf(shared(), tree);
513
+ refs.RefIf(i % 16 == 0, tree->Edges().back());
514
+ refs.RefIf(i % 4 == 0, tree->Edges().back()->btree()->Edges().back());
515
+
516
+ flats.push_back(MakeHexFlat(i));
517
+ CordRepBtree* result = CordRepBtree::Append(tree, flats.back());
518
+ ASSERT_THAT(result, IsNode(2));
519
+ ASSERT_THAT(result, Conditional(shared(), Ne(tree), Eq(tree)));
520
+ std::vector<CordRep*> edges = GetLeafEdges(result);
521
+ ASSERT_THAT(edges, ElementsAreArray(flats));
522
+ tree = result;
523
+ }
524
+ CordRep::Unref(tree);
525
+ }
526
+
527
+ TEST_P(CordRepBtreeTest, PrependToTreeOneDeep) {
528
+ constexpr size_t max_cap = CordRepBtree::kMaxCapacity;
529
+ AutoUnref refs;
530
+ std::deque<CordRep*> flats;
531
+ flats.push_back(MakeHexFlat(0));
532
+ CordRepBtree* tree = CordRepBtree::Create(flats.back());
533
+ for (size_t i = 1; i <= max_cap; ++i) {
534
+ flats.push_front(MakeHexFlat(i));
535
+ tree = CordRepBtree::Prepend(tree, flats.front());
536
+ }
537
+ ASSERT_THAT(tree, IsNode(1));
538
+
539
+ for (size_t i = max_cap + 1; i < max_cap * max_cap; ++i) {
540
+ // Ref top level tree based on param.
541
+ // Ref leaf node once every 4 iterations which should not have an observable
542
+ // effect other than than the leaf itself is copied.
543
+ refs.RefIf(shared(), tree);
544
+ refs.RefIf(i % 4 == 0, tree->Edges().back());
545
+
546
+ flats.push_front(MakeHexFlat(i));
547
+ CordRepBtree* result = CordRepBtree::Prepend(tree, flats.front());
548
+ ASSERT_THAT(result, IsNode(1));
549
+ ASSERT_THAT(result, Conditional(shared(), Ne(tree), Eq(tree)));
550
+ std::vector<CordRep*> edges = GetLeafEdges(result);
551
+ ASSERT_THAT(edges, ElementsAreArray(flats));
552
+ tree = result;
553
+ }
554
+ CordRep::Unref(tree);
555
+ }
556
+
557
+ TEST_P(CordRepBtreeTest, PrependToTreeTwoDeep) {
558
+ constexpr size_t max_cap = CordRepBtree::kMaxCapacity;
559
+ AutoUnref refs;
560
+ std::deque<CordRep*> flats;
561
+ flats.push_back(MakeHexFlat(0));
562
+ CordRepBtree* tree = CordRepBtree::Create(flats.back());
563
+ for (size_t i = 1; i <= max_cap * max_cap; ++i) {
564
+ flats.push_front(MakeHexFlat(i));
565
+ tree = CordRepBtree::Prepend(tree, flats.front());
566
+ }
567
+ ASSERT_THAT(tree, IsNode(2));
568
+ for (size_t i = max_cap * max_cap + 1; i < max_cap * max_cap * max_cap; ++i) {
569
+ // Ref top level tree based on param.
570
+ // Ref child node once every 16 iterations, and leaf node every 4
571
+ // iterations which which should not have an observable effect other than
572
+ // the node and/or the leaf below it being copied.
573
+ refs.RefIf(shared(), tree);
574
+ refs.RefIf(i % 16 == 0, tree->Edges().back());
575
+ refs.RefIf(i % 4 == 0, tree->Edges().back()->btree()->Edges().back());
576
+
577
+ flats.push_front(MakeHexFlat(i));
578
+ CordRepBtree* result = CordRepBtree::Prepend(tree, flats.front());
579
+ ASSERT_THAT(result, IsNode(2));
580
+ ASSERT_THAT(result, Conditional(shared(), Ne(tree), Eq(tree)));
581
+ std::vector<CordRep*> edges = GetLeafEdges(result);
582
+ ASSERT_THAT(edges, ElementsAreArray(flats));
583
+ tree = result;
584
+ }
585
+ CordRep::Unref(tree);
586
+ }
587
+
588
+ TEST_P(CordRepBtreeDualTest, MergeLeafsNotExceedingCapacity) {
589
+ for (bool use_append : {false, true}) {
590
+ SCOPED_TRACE(use_append ? "Using Append" : "Using Prepend");
591
+
592
+ AutoUnref refs;
593
+ std::vector<CordRep*> flats;
594
+
595
+ // Build `left` side leaf appending all contained flats to `flats`
596
+ CordRepBtree* left = MakeLeaf(3);
597
+ GetLeafEdges(left, flats);
598
+ refs.RefIf(first_shared(), left);
599
+
600
+ // Build `right` side leaf appending all contained flats to `flats`
601
+ CordRepBtree* right = MakeLeaf(2);
602
+ GetLeafEdges(right, flats);
603
+ refs.RefIf(second_shared(), right);
604
+
605
+ CordRepBtree* tree = use_append ? CordRepBtree::Append(left, right)
606
+ : CordRepBtree::Prepend(right, left);
607
+ EXPECT_THAT(tree, IsNode(0));
608
+
609
+ // `tree` contains all flats originally belonging to `left` and `right`.
610
+ EXPECT_THAT(tree->Edges(), ElementsAreArray(flats));
611
+ CordRepBtree::Unref(tree);
612
+ }
613
+ }
614
+
615
+ TEST_P(CordRepBtreeDualTest, MergeLeafsExceedingCapacity) {
616
+ for (bool use_append : {false, true}) {
617
+ SCOPED_TRACE(use_append ? "Using Append" : "Using Prepend");
618
+
619
+ AutoUnref refs;
620
+
621
+ // Build `left` side tree appending all contained flats to `flats`
622
+ CordRepBtree* left = MakeLeaf(CordRepBtree::kMaxCapacity - 2);
623
+ refs.RefIf(first_shared(), left);
624
+
625
+ // Build `right` side tree appending all contained flats to `flats`
626
+ CordRepBtree* right = MakeLeaf(CordRepBtree::kMaxCapacity - 1);
627
+ refs.RefIf(second_shared(), right);
628
+
629
+ CordRepBtree* tree = use_append ? CordRepBtree::Append(left, right)
630
+ : CordRepBtree::Prepend(right, left);
631
+ EXPECT_THAT(tree, IsNode(1));
632
+ EXPECT_THAT(tree->Edges(), ElementsAre(left, right));
633
+ CordRepBtree::Unref(tree);
634
+ }
635
+ }
636
+
637
+ TEST_P(CordRepBtreeDualTest, MergeEqualHeightTrees) {
638
+ for (bool use_append : {false, true}) {
639
+ SCOPED_TRACE(use_append ? "Using Append" : "Using Prepend");
640
+
641
+ AutoUnref refs;
642
+ std::vector<CordRep*> flats;
643
+
644
+ // Build `left` side tree appending all contained flats to `flats`
645
+ CordRepBtree* left = MakeTree(CordRepBtree::kMaxCapacity * 3);
646
+ GetLeafEdges(left, flats);
647
+ refs.RefIf(first_shared(), left);
648
+
649
+ // Build `right` side tree appending all contained flats to `flats`
650
+ CordRepBtree* right = MakeTree(CordRepBtree::kMaxCapacity * 2);
651
+ GetLeafEdges(right, flats);
652
+ refs.RefIf(second_shared(), right);
653
+
654
+ CordRepBtree* tree = use_append ? CordRepBtree::Append(left, right)
655
+ : CordRepBtree::Prepend(right, left);
656
+ EXPECT_THAT(tree, IsNode(1));
657
+ EXPECT_THAT(tree->Edges(), SizeIs(5u));
658
+
659
+ // `tree` contains all flats originally belonging to `left` and `right`.
660
+ EXPECT_THAT(GetLeafEdges(tree), ElementsAreArray(flats));
661
+ CordRepBtree::Unref(tree);
662
+ }
663
+ }
664
+
665
+ TEST_P(CordRepBtreeDualTest, MergeLeafWithTreeNotExceedingLeafCapacity) {
666
+ for (bool use_append : {false, true}) {
667
+ SCOPED_TRACE(use_append ? "Using Append" : "Using Prepend");
668
+
669
+ AutoUnref refs;
670
+ std::vector<CordRep*> flats;
671
+
672
+ // Build `left` side tree appending all added flats to `flats`
673
+ CordRepBtree* left = MakeTree(CordRepBtree::kMaxCapacity * 2 + 2);
674
+ GetLeafEdges(left, flats);
675
+ refs.RefIf(first_shared(), left);
676
+
677
+ // Build `right` side tree appending all added flats to `flats`
678
+ CordRepBtree* right = MakeTree(3);
679
+ GetLeafEdges(right, flats);
680
+ refs.RefIf(second_shared(), right);
681
+
682
+ CordRepBtree* tree = use_append ? CordRepBtree::Append(left, right)
683
+ : CordRepBtree::Prepend(right, left);
684
+ EXPECT_THAT(tree, IsNode(1));
685
+ EXPECT_THAT(tree->Edges(), SizeIs(3u));
686
+
687
+ // `tree` contains all flats originally belonging to `left` and `right`.
688
+ EXPECT_THAT(GetLeafEdges(tree), ElementsAreArray(flats));
689
+ CordRepBtree::Unref(tree);
690
+ }
691
+ }
692
+
693
+ TEST_P(CordRepBtreeDualTest, MergeLeafWithTreeExceedingLeafCapacity) {
694
+ for (bool use_append : {false, true}) {
695
+ SCOPED_TRACE(use_append ? "Using Append" : "Using Prepend");
696
+
697
+ AutoUnref refs;
698
+ std::vector<CordRep*> flats;
699
+
700
+ // Build `left` side tree appending all added flats to `flats`
701
+ CordRepBtree* left = MakeTree(CordRepBtree::kMaxCapacity * 3 - 2);
702
+ GetLeafEdges(left, flats);
703
+ refs.RefIf(first_shared(), left);
704
+
705
+ // Build `right` side tree appending all added flats to `flats`
706
+ CordRepBtree* right = MakeTree(3);
707
+ GetLeafEdges(right, flats);
708
+ refs.RefIf(second_shared(), right);
709
+
710
+ CordRepBtree* tree = use_append ? CordRepBtree::Append(left, right)
711
+ : CordRepBtree::Prepend(right, left);
712
+ EXPECT_THAT(tree, IsNode(1));
713
+ EXPECT_THAT(tree->Edges(), SizeIs(4u));
714
+
715
+ // `tree` contains all flats originally belonging to `left` and `right`.
716
+ EXPECT_THAT(GetLeafEdges(tree), ElementsAreArray(flats));
717
+ CordRepBtree::Unref(tree);
718
+ }
719
+ }
720
+
721
+ void RefEdgesAt(size_t depth, AutoUnref& refs, CordRepBtree* tree) {
722
+ absl::Span<CordRep* const> edges = tree->Edges();
723
+ if (depth == 0) {
724
+ refs.Ref(edges.front());
725
+ refs.Ref(edges.back());
726
+ } else {
727
+ assert(tree->height() > 0);
728
+ RefEdgesAt(depth - 1, refs, edges.front()->btree());
729
+ RefEdgesAt(depth - 1, refs, edges.back()->btree());
730
+ }
731
+ }
732
+
733
+ TEST(CordRepBtreeTest, MergeFuzzTest) {
734
+ constexpr size_t max_cap = CordRepBtree::kMaxCapacity;
735
+ std::minstd_rand rnd;
736
+ std::uniform_int_distribution<int> coin_flip(0, 1);
737
+ std::uniform_int_distribution<int> dice_throw(1, 6);
738
+
739
+ auto random_leaf_count = [&]() {
740
+ std::uniform_int_distribution<int> dist_height(0, 3);
741
+ std::uniform_int_distribution<int> dist_leaf(0, max_cap - 1);
742
+ const int height = dist_height(rnd);
743
+ return (height ? pow(max_cap, height) : 0) + dist_leaf(rnd);
744
+ };
745
+
746
+ for (int i = 0; i < 10000; ++i) {
747
+ AutoUnref refs;
748
+ std::vector<CordRep*> flats;
749
+
750
+ CordRepBtree* left = MakeTree(random_leaf_count(), coin_flip(rnd));
751
+ GetLeafEdges(left, flats);
752
+ if (dice_throw(rnd) == 1) {
753
+ std::uniform_int_distribution<size_t> dist(
754
+ 0, static_cast<size_t>(left->height()));
755
+ RefEdgesAt(dist(rnd), refs, left);
756
+ }
757
+
758
+ CordRepBtree* right = MakeTree(random_leaf_count(), coin_flip(rnd));
759
+ GetLeafEdges(right, flats);
760
+ if (dice_throw(rnd) == 1) {
761
+ std::uniform_int_distribution<size_t> dist(
762
+ 0, static_cast<size_t>(right->height()));
763
+ RefEdgesAt(dist(rnd), refs, right);
764
+ }
765
+
766
+ CordRepBtree* tree = CordRepBtree::Append(left, right);
767
+ EXPECT_THAT(GetLeafEdges(tree), ElementsAreArray(flats));
768
+ CordRepBtree::Unref(tree);
769
+ }
770
+ }
771
+
772
+ TEST_P(CordRepBtreeTest, RemoveSuffix) {
773
+ // Create tree of 1, 2 and 3 levels high
774
+ constexpr size_t max_cap = CordRepBtree::kMaxCapacity;
775
+ for (size_t cap : {max_cap - 1, max_cap * 2, max_cap * max_cap * 2}) {
776
+ const std::string data = CreateRandomString(cap * 512);
777
+
778
+ {
779
+ // Verify RemoveSuffix(<all>)
780
+ AutoUnref refs;
781
+ CordRepBtree* node = refs.RefIf(shared(), CreateTree(data, 512));
782
+ EXPECT_THAT(CordRepBtree::RemoveSuffix(node, data.length()), Eq(nullptr));
783
+
784
+ // Verify RemoveSuffix(<none>)
785
+ node = refs.RefIf(shared(), CreateTree(data, 512));
786
+ EXPECT_THAT(CordRepBtree::RemoveSuffix(node, 0), Eq(node));
787
+ CordRep::Unref(node);
788
+ }
789
+
790
+ for (size_t n = 1; n < data.length(); ++n) {
791
+ AutoUnref refs;
792
+ auto flats = CreateFlatsFromString(data, 512);
793
+ CordRepBtree* node = refs.RefIf(shared(), CreateTree(flats));
794
+ CordRep* rep = refs.Add(CordRepBtree::RemoveSuffix(node, n));
795
+ EXPECT_THAT(CordToString(rep), Eq(data.substr(0, data.length() - n)));
796
+
797
+ // Collect all flats
798
+ auto is_flat = [](CordRep* rep) { return rep->tag >= FLAT; };
799
+ std::vector<CordRep*> edges = CordCollectRepsIf(is_flat, rep);
800
+ ASSERT_THAT(edges.size(), Le(flats.size()));
801
+
802
+ // Isolate last edge
803
+ CordRep* last_edge = edges.back();
804
+ edges.pop_back();
805
+ const size_t last_length = rep->length - edges.size() * 512;
806
+
807
+ // All flats except the last edge must be kept or copied 'as is'
808
+ size_t index = 0;
809
+ for (CordRep* edge : edges) {
810
+ ASSERT_THAT(edge, Eq(flats[index++]));
811
+ ASSERT_THAT(edge->length, Eq(512u));
812
+ }
813
+
814
+ // CordRepBtree may optimize small substrings to avoid waste, so only
815
+ // check for flat sharing / updates where the code should always do this.
816
+ if (last_length >= 500) {
817
+ EXPECT_THAT(last_edge, Eq(flats[index++]));
818
+ if (shared()) {
819
+ EXPECT_THAT(last_edge->length, Eq(512u));
820
+ } else {
821
+ EXPECT_TRUE(last_edge->refcount.IsOne());
822
+ EXPECT_THAT(last_edge->length, Eq(last_length));
823
+ }
824
+ }
825
+ }
826
+ }
827
+ }
828
+
829
+ TEST(CordRepBtreeTest, SubTree) {
830
+ // Create tree of at least 2 levels high
831
+ constexpr size_t max_cap = CordRepBtree::kMaxCapacity;
832
+ const size_t n = max_cap * max_cap * 2;
833
+ const std::string data = CreateRandomString(n * 3);
834
+ std::vector<CordRep*> flats;
835
+ for (absl::string_view s = data; !s.empty(); s.remove_prefix(3)) {
836
+ flats.push_back(MakeFlat(s.substr(0, 3)));
837
+ }
838
+ CordRepBtree* node = CordRepBtree::Create(CordRep::Ref(flats[0]));
839
+ for (size_t i = 1; i < flats.size(); ++i) {
840
+ node = CordRepBtree::Append(node, CordRep::Ref(flats[i]));
841
+ }
842
+
843
+ for (size_t offset = 0; offset < data.length(); ++offset) {
844
+ for (size_t length = 1; length <= data.length() - offset; ++length) {
845
+ CordRep* rep = node->SubTree(offset, length);
846
+ EXPECT_THAT(CordToString(rep), Eq(data.substr(offset, length)));
847
+ CordRep::Unref(rep);
848
+ }
849
+ }
850
+ CordRepBtree::Unref(node);
851
+ for (CordRep* rep : flats) {
852
+ CordRep::Unref(rep);
853
+ }
854
+ }
855
+
856
+ TEST(CordRepBtreeTest, SubTreeOnExistingSubstring) {
857
+ // This test verifies that a SubTree call on a pre-existing (large) substring
858
+ // adjusts the existing substring if not shared, and else rewrites the
859
+ // existing substring.
860
+ AutoUnref refs;
861
+ std::string data = CreateRandomString(1000);
862
+ CordRepBtree* leaf = CordRepBtree::Create(MakeFlat("abc"));
863
+ CordRep* flat = MakeFlat(data);
864
+ leaf = CordRepBtree::Append(leaf, flat);
865
+
866
+ // Setup tree containing substring.
867
+ CordRep* result = leaf->SubTree(0, 3 + 990);
868
+ ASSERT_THAT(result->tag, Eq(BTREE));
869
+ CordRep::Unref(leaf);
870
+ leaf = result->btree();
871
+ ASSERT_THAT(leaf->Edges(), ElementsAre(_, IsSubstring(0u, 990u)));
872
+ EXPECT_THAT(leaf->Edges()[1]->substring()->child, Eq(flat));
873
+
874
+ // Verify substring of substring.
875
+ result = leaf->SubTree(3 + 5, 970);
876
+ ASSERT_THAT(result, IsSubstring(5u, 970u));
877
+ EXPECT_THAT(result->substring()->child, Eq(flat));
878
+ CordRep::Unref(result);
879
+
880
+ CordRep::Unref(leaf);
881
+ }
882
+
883
+ TEST_P(CordRepBtreeTest, AddDataToLeaf) {
884
+ const size_t n = CordRepBtree::kMaxCapacity;
885
+ const std::string data = CreateRandomString(n * 3);
886
+
887
+ for (bool append : {true, false}) {
888
+ AutoUnref refs;
889
+ DataConsumer consumer(data, append);
890
+ SCOPED_TRACE(append ? "Append" : "Prepend");
891
+
892
+ CordRepBtree* leaf = CordRepBtree::Create(MakeFlat(consumer.Next(3)));
893
+ for (size_t i = 1; i < n; ++i) {
894
+ refs.RefIf(shared(), leaf);
895
+ CordRepBtree* result = BtreeAdd(leaf, append, consumer.Next(3));
896
+ EXPECT_THAT(result, Conditional(shared(), Ne(leaf), Eq(leaf)));
897
+ EXPECT_THAT(CordToString(result), Eq(consumer.Consumed()));
898
+ leaf = result;
899
+ }
900
+ CordRep::Unref(leaf);
901
+ }
902
+ }
903
+
904
+ TEST_P(CordRepBtreeTest, AppendDataToTree) {
905
+ AutoUnref refs;
906
+ size_t n = CordRepBtree::kMaxCapacity + CordRepBtree::kMaxCapacity / 2;
907
+ std::string data = CreateRandomString(n * 3);
908
+ CordRepBtree* tree = refs.RefIf(shared(), CreateTree(data, 3));
909
+ CordRepBtree* leaf0 = tree->Edges()[0]->btree();
910
+ CordRepBtree* leaf1 = tree->Edges()[1]->btree();
911
+ CordRepBtree* result = CordRepBtree::Append(tree, "123456789");
912
+ EXPECT_THAT(result, Conditional(shared(), Ne(tree), Eq(tree)));
913
+ EXPECT_THAT(result->Edges(),
914
+ ElementsAre(leaf0, Conditional(shared(), Ne(leaf1), Eq(leaf1))));
915
+ EXPECT_THAT(CordToString(result), Eq(data + "123456789"));
916
+ CordRep::Unref(result);
917
+ }
918
+
919
+ TEST_P(CordRepBtreeTest, PrependDataToTree) {
920
+ AutoUnref refs;
921
+ size_t n = CordRepBtree::kMaxCapacity + CordRepBtree::kMaxCapacity / 2;
922
+ std::string data = CreateRandomString(n * 3);
923
+ CordRepBtree* tree = refs.RefIf(shared(), CreateTreeReverse(data, 3));
924
+ CordRepBtree* leaf0 = tree->Edges()[0]->btree();
925
+ CordRepBtree* leaf1 = tree->Edges()[1]->btree();
926
+ CordRepBtree* result = CordRepBtree::Prepend(tree, "123456789");
927
+ EXPECT_THAT(result, Conditional(shared(), Ne(tree), Eq(tree)));
928
+ EXPECT_THAT(result->Edges(),
929
+ ElementsAre(Conditional(shared(), Ne(leaf0), Eq(leaf0)), leaf1));
930
+ EXPECT_THAT(CordToString(result), Eq("123456789" + data));
931
+ CordRep::Unref(result);
932
+ }
933
+
934
+ TEST_P(CordRepBtreeTest, AddDataToTreeThreeLevelsDeep) {
935
+ constexpr size_t max_cap = CordRepBtree::kMaxCapacity;
936
+ const size_t n = max_cap * max_cap * max_cap;
937
+ const std::string data = CreateRandomString(n * 3);
938
+
939
+ for (bool append : {true, false}) {
940
+ AutoUnref refs;
941
+ DataConsumer consumer(data, append);
942
+ SCOPED_TRACE(append ? "Append" : "Prepend");
943
+
944
+ // Fill leaf
945
+ CordRepBtree* tree = CordRepBtree::Create(MakeFlat(consumer.Next(3)));
946
+ for (size_t i = 1; i < max_cap; ++i) {
947
+ tree = BtreeAdd(tree, append, consumer.Next(3));
948
+ }
949
+ ASSERT_THAT(CordToString(tree), Eq(consumer.Consumed()));
950
+
951
+ // Fill to maximum at one deep
952
+ refs.RefIf(shared(), tree);
953
+ CordRepBtree* result = BtreeAdd(tree, append, consumer.Next(3));
954
+ ASSERT_THAT(result, IsNode(1));
955
+ ASSERT_THAT(result, Ne(tree));
956
+ ASSERT_THAT(CordToString(result), Eq(consumer.Consumed()));
957
+ tree = result;
958
+ for (size_t i = max_cap + 1; i < max_cap * max_cap; ++i) {
959
+ refs.RefIf(shared(), tree);
960
+ result = BtreeAdd(tree, append, consumer.Next(3));
961
+ ASSERT_THAT(result, Conditional(shared(), Ne(tree), Eq(tree)));
962
+ ASSERT_THAT(CordToString(result), Eq(consumer.Consumed()));
963
+ tree = result;
964
+ }
965
+
966
+ // Fill to maximum at two deep
967
+ refs.RefIf(shared(), tree);
968
+ result = BtreeAdd(tree, append, consumer.Next(3));
969
+ ASSERT_THAT(result, IsNode(2));
970
+ ASSERT_THAT(result, Ne(tree));
971
+ ASSERT_THAT(CordToString(result), Eq(consumer.Consumed()));
972
+ tree = result;
973
+ for (size_t i = max_cap * max_cap + 1; i < max_cap * max_cap * max_cap;
974
+ ++i) {
975
+ refs.RefIf(shared(), tree);
976
+ result = BtreeAdd(tree, append, consumer.Next(3));
977
+ ASSERT_THAT(result, Conditional(shared(), Ne(tree), Eq(tree)));
978
+ ASSERT_THAT(CordToString(result), Eq(consumer.Consumed()));
979
+ tree = result;
980
+ }
981
+
982
+ CordRep::Unref(tree);
983
+ }
984
+ }
985
+
986
+ TEST_P(CordRepBtreeTest, AddLargeDataToLeaf) {
987
+ const size_t max_cap = CordRepBtree::kMaxCapacity;
988
+ const size_t n = max_cap * max_cap * max_cap * 3 + 2;
989
+ const std::string data = CreateRandomString(n * kMaxFlatLength);
990
+
991
+ for (bool append : {true, false}) {
992
+ AutoUnref refs;
993
+ SCOPED_TRACE(append ? "Append" : "Prepend");
994
+
995
+ CordRepBtree* leaf = CordRepBtree::Create(MakeFlat("abc"));
996
+ refs.RefIf(shared(), leaf);
997
+ CordRepBtree* result = BtreeAdd(leaf, append, data);
998
+ EXPECT_THAT(CordToString(result), Eq(append ? "abc" + data : data + "abc"));
999
+ CordRep::Unref(result);
1000
+ }
1001
+ }
1002
+
1003
+ TEST_P(CordRepBtreeTest, CreateFromTreeReturnsTree) {
1004
+ AutoUnref refs;
1005
+ CordRepBtree* leaf = CordRepBtree::Create(MakeFlat("Hello world"));
1006
+ refs.RefIf(shared(), leaf);
1007
+ CordRepBtree* result = CordRepBtree::Create(leaf);
1008
+ EXPECT_THAT(result, Eq(leaf));
1009
+ CordRep::Unref(result);
1010
+ }
1011
+
1012
+ TEST(CordRepBtreeTest, GetCharacter) {
1013
+ size_t n = CordRepBtree::kMaxCapacity * CordRepBtree::kMaxCapacity + 2;
1014
+ std::string data = CreateRandomString(n * 3);
1015
+ CordRepBtree* tree = CreateTree(data, 3);
1016
+ // Add a substring node for good measure.
1017
+ tree = tree->Append(tree, MakeSubstring(4, 5, MakeFlat("abcdefghijklm")));
1018
+ data += "efghi";
1019
+ for (size_t i = 0; i < data.length(); ++i) {
1020
+ ASSERT_THAT(tree->GetCharacter(i), Eq(data[i]));
1021
+ }
1022
+ CordRep::Unref(tree);
1023
+ }
1024
+
1025
+ TEST_P(CordRepBtreeTest, IsFlatSingleFlat) {
1026
+ CordRepBtree* leaf = CordRepBtree::Create(MakeFlat("Hello world"));
1027
+
1028
+ absl::string_view fragment;
1029
+ EXPECT_TRUE(leaf->IsFlat(nullptr));
1030
+ EXPECT_TRUE(leaf->IsFlat(&fragment));
1031
+ EXPECT_THAT(fragment, Eq("Hello world"));
1032
+ fragment = "";
1033
+ EXPECT_TRUE(leaf->IsFlat(0, 11, nullptr));
1034
+ EXPECT_TRUE(leaf->IsFlat(0, 11, &fragment));
1035
+ EXPECT_THAT(fragment, Eq("Hello world"));
1036
+
1037
+ // Arbitrary ranges must check true as well.
1038
+ EXPECT_TRUE(leaf->IsFlat(1, 4, &fragment));
1039
+ EXPECT_THAT(fragment, Eq("ello"));
1040
+ EXPECT_TRUE(leaf->IsFlat(6, 5, &fragment));
1041
+ EXPECT_THAT(fragment, Eq("world"));
1042
+
1043
+ CordRep::Unref(leaf);
1044
+ }
1045
+
1046
+ TEST(CordRepBtreeTest, IsFlatMultiFlat) {
1047
+ size_t n = CordRepBtree::kMaxCapacity * CordRepBtree::kMaxCapacity + 2;
1048
+ std::string data = CreateRandomString(n * 3);
1049
+ CordRepBtree* tree = CreateTree(data, 3);
1050
+ // Add substring nodes for good measure.
1051
+ tree = tree->Append(tree, MakeSubstring(4, 3, MakeFlat("abcdefghijklm")));
1052
+ tree = tree->Append(tree, MakeSubstring(8, 3, MakeFlat("abcdefghijklm")));
1053
+ data += "efgijk";
1054
+
1055
+ EXPECT_FALSE(tree->IsFlat(nullptr));
1056
+ absl::string_view fragment = "Can't touch this";
1057
+ EXPECT_FALSE(tree->IsFlat(&fragment));
1058
+ EXPECT_THAT(fragment, Eq("Can't touch this"));
1059
+
1060
+ for (size_t offset = 0; offset < data.size(); offset += 3) {
1061
+ EXPECT_TRUE(tree->IsFlat(offset, 3, nullptr));
1062
+ EXPECT_TRUE(tree->IsFlat(offset, 3, &fragment));
1063
+ EXPECT_THAT(fragment, Eq(data.substr(offset, 3)));
1064
+
1065
+ fragment = "Can't touch this";
1066
+ if (offset > 0) {
1067
+ EXPECT_FALSE(tree->IsFlat(offset - 1, 4, nullptr));
1068
+ EXPECT_FALSE(tree->IsFlat(offset - 1, 4, &fragment));
1069
+ EXPECT_THAT(fragment, Eq("Can't touch this"));
1070
+ }
1071
+ if (offset < data.size() - 4) {
1072
+ EXPECT_FALSE(tree->IsFlat(offset, 4, nullptr));
1073
+ EXPECT_FALSE(tree->IsFlat(offset, 4, &fragment));
1074
+ EXPECT_THAT(fragment, Eq("Can't touch this"));
1075
+ }
1076
+ }
1077
+
1078
+ CordRep::Unref(tree);
1079
+ }
1080
+
1081
+ #if defined(GTEST_HAS_DEATH_TEST) && !defined(NDEBUG)
1082
+
1083
+ TEST_P(CordRepBtreeHeightTest, GetAppendBufferNotPrivate) {
1084
+ CordRepBtree* tree = CordRepBtree::Create(MakeExternal("Foo"));
1085
+ CordRepBtree::Ref(tree);
1086
+ EXPECT_DEATH(tree->GetAppendBuffer(1), ".*");
1087
+ CordRepBtree::Unref(tree);
1088
+ CordRepBtree::Unref(tree);
1089
+ }
1090
+
1091
+ #endif // defined(GTEST_HAS_DEATH_TEST) && !defined(NDEBUG)
1092
+
1093
+ TEST_P(CordRepBtreeHeightTest, GetAppendBufferNotFlat) {
1094
+ CordRepBtree* tree = CordRepBtree::Create(MakeExternal("Foo"));
1095
+ for (int i = 1; i <= height(); ++i) {
1096
+ tree = CordRepBtree::New(tree);
1097
+ }
1098
+ EXPECT_THAT(tree->GetAppendBuffer(1), SizeIs(0u));
1099
+ CordRepBtree::Unref(tree);
1100
+ }
1101
+
1102
+ TEST_P(CordRepBtreeHeightTest, GetAppendBufferFlatNotPrivate) {
1103
+ CordRepFlat* flat = MakeFlat("abc");
1104
+ CordRepBtree* tree = CordRepBtree::Create(CordRep::Ref(flat));
1105
+ for (int i = 1; i <= height(); ++i) {
1106
+ tree = CordRepBtree::New(tree);
1107
+ }
1108
+ EXPECT_THAT(tree->GetAppendBuffer(1), SizeIs(0u));
1109
+ CordRepBtree::Unref(tree);
1110
+ CordRep::Unref(flat);
1111
+ }
1112
+
1113
+ TEST_P(CordRepBtreeHeightTest, GetAppendBufferTreeNotPrivate) {
1114
+ if (height() == 0) return;
1115
+ AutoUnref refs;
1116
+ CordRepFlat* flat = MakeFlat("abc");
1117
+ CordRepBtree* tree = CordRepBtree::Create(CordRep::Ref(flat));
1118
+ for (int i = 1; i <= height(); ++i) {
1119
+ if (i == (height() + 1) / 2) refs.Ref(tree);
1120
+ tree = CordRepBtree::New(tree);
1121
+ }
1122
+ EXPECT_THAT(tree->GetAppendBuffer(1), SizeIs(0u));
1123
+ CordRepBtree::Unref(tree);
1124
+ CordRep::Unref(flat);
1125
+ }
1126
+
1127
+ TEST_P(CordRepBtreeHeightTest, GetAppendBufferFlatNoCapacity) {
1128
+ CordRepFlat* flat = MakeFlat("abc");
1129
+ flat->length = flat->Capacity();
1130
+ CordRepBtree* tree = CordRepBtree::Create(flat);
1131
+ for (int i = 1; i <= height(); ++i) {
1132
+ tree = CordRepBtree::New(tree);
1133
+ }
1134
+ EXPECT_THAT(tree->GetAppendBuffer(1), SizeIs(0u));
1135
+ CordRepBtree::Unref(tree);
1136
+ }
1137
+
1138
+ TEST_P(CordRepBtreeHeightTest, GetAppendBufferFlatWithCapacity) {
1139
+ CordRepFlat* flat = MakeFlat("abc");
1140
+ CordRepBtree* tree = CordRepBtree::Create(flat);
1141
+ for (int i = 1; i <= height(); ++i) {
1142
+ tree = CordRepBtree::New(tree);
1143
+ }
1144
+ absl::Span<char> span = tree->GetAppendBuffer(2);
1145
+ EXPECT_THAT(span, SizeIs(2u));
1146
+ EXPECT_THAT(span.data(), TypedEq<void*>(flat->Data() + 3));
1147
+ EXPECT_THAT(tree->length, Eq(5u));
1148
+
1149
+ size_t avail = flat->Capacity() - 5;
1150
+ span = tree->GetAppendBuffer(avail + 100);
1151
+ EXPECT_THAT(span, SizeIs(avail));
1152
+ EXPECT_THAT(span.data(), TypedEq<void*>(flat->Data() + 5));
1153
+ EXPECT_THAT(tree->length, Eq(5 + avail));
1154
+
1155
+ CordRepBtree::Unref(tree);
1156
+ }
1157
+
1158
+ TEST(CordRepBtreeTest, Dump) {
1159
+ // Handles nullptr
1160
+ std::stringstream ss;
1161
+ CordRepBtree::Dump(nullptr, ss);
1162
+ CordRepBtree::Dump(nullptr, "Once upon a label", ss);
1163
+ CordRepBtree::Dump(nullptr, "Once upon a label", false, ss);
1164
+ CordRepBtree::Dump(nullptr, "Once upon a label", true, ss);
1165
+
1166
+ // Cover legal edges
1167
+ CordRepFlat* flat = MakeFlat("Hello world");
1168
+ CordRepExternal* external = MakeExternal("Hello external");
1169
+ CordRep* substr_flat = MakeSubstring(1, 6, CordRep::Ref(flat));
1170
+ CordRep* substr_external = MakeSubstring(2, 7, CordRep::Ref(external));
1171
+
1172
+ // Build tree
1173
+ CordRepBtree* tree = CordRepBtree::Create(flat);
1174
+ tree = CordRepBtree::Append(tree, external);
1175
+ tree = CordRepBtree::Append(tree, substr_flat);
1176
+ tree = CordRepBtree::Append(tree, substr_external);
1177
+
1178
+ // Repeat until we have a tree
1179
+ while (tree->height() == 0) {
1180
+ tree = CordRepBtree::Append(tree, CordRep::Ref(flat));
1181
+ tree = CordRepBtree::Append(tree, CordRep::Ref(external));
1182
+ tree = CordRepBtree::Append(tree, CordRep::Ref(substr_flat));
1183
+ tree = CordRepBtree::Append(tree, CordRep::Ref(substr_external));
1184
+ }
1185
+
1186
+ for (int api = 0; api <= 3; ++api) {
1187
+ absl::string_view api_scope;
1188
+ std::stringstream ss;
1189
+ switch (api) {
1190
+ case 0:
1191
+ api_scope = "Bare";
1192
+ CordRepBtree::Dump(tree, ss);
1193
+ break;
1194
+ case 1:
1195
+ api_scope = "Label only";
1196
+ CordRepBtree::Dump(tree, "Once upon a label", ss);
1197
+ break;
1198
+ case 2:
1199
+ api_scope = "Label no content";
1200
+ CordRepBtree::Dump(tree, "Once upon a label", false, ss);
1201
+ break;
1202
+ default:
1203
+ api_scope = "Label and content";
1204
+ CordRepBtree::Dump(tree, "Once upon a label", true, ss);
1205
+ break;
1206
+ }
1207
+ SCOPED_TRACE(api_scope);
1208
+ std::string str = ss.str();
1209
+
1210
+ // Contains Node(depth) / Leaf and private / shared indicators
1211
+ EXPECT_THAT(str, AllOf(HasSubstr("Node(1)"), HasSubstr("Leaf"),
1212
+ HasSubstr("Private"), HasSubstr("Shared")));
1213
+
1214
+ // Contains length and start offset of all data edges
1215
+ EXPECT_THAT(str, AllOf(HasSubstr("len = 11"), HasSubstr("len = 14"),
1216
+ HasSubstr("len = 6"), HasSubstr("len = 7"),
1217
+ HasSubstr("start = 1"), HasSubstr("start = 2")));
1218
+
1219
+ // Contains address of all data edges
1220
+ EXPECT_THAT(
1221
+ str, AllOf(HasSubstr(absl::StrCat("0x", absl::Hex(flat))),
1222
+ HasSubstr(absl::StrCat("0x", absl::Hex(external))),
1223
+ HasSubstr(absl::StrCat("0x", absl::Hex(substr_flat))),
1224
+ HasSubstr(absl::StrCat("0x", absl::Hex(substr_external)))));
1225
+
1226
+ if (api != 0) {
1227
+ // Contains label
1228
+ EXPECT_THAT(str, HasSubstr("Once upon a label"));
1229
+ }
1230
+
1231
+ if (api != 3) {
1232
+ // Does not contain contents
1233
+ EXPECT_THAT(str, Not(AnyOf((HasSubstr("data = \"Hello world\""),
1234
+ HasSubstr("data = \"Hello external\""),
1235
+ HasSubstr("data = \"ello w\""),
1236
+ HasSubstr("data = \"llo ext\"")))));
1237
+ } else {
1238
+ // Contains contents
1239
+ EXPECT_THAT(str, AllOf((HasSubstr("data = \"Hello world\""),
1240
+ HasSubstr("data = \"Hello external\""),
1241
+ HasSubstr("data = \"ello w\""),
1242
+ HasSubstr("data = \"llo ext\""))));
1243
+ }
1244
+ }
1245
+
1246
+ CordRep::Unref(tree);
1247
+ }
1248
+
1249
+ TEST(CordRepBtreeTest, IsValid) {
1250
+ EXPECT_FALSE(CordRepBtree::IsValid(nullptr));
1251
+
1252
+ CordRepBtree* empty = CordRepBtree::New(0);
1253
+ EXPECT_TRUE(CordRepBtree::IsValid(empty));
1254
+ CordRep::Unref(empty);
1255
+
1256
+ for (bool as_tree : {false, true}) {
1257
+ CordRepBtree* leaf = CordRepBtree::Create(MakeFlat("abc"));
1258
+ CordRepBtree* tree = as_tree ? CordRepBtree::New(leaf) : nullptr;
1259
+ CordRepBtree* check = as_tree ? tree : leaf;
1260
+
1261
+ ASSERT_TRUE(CordRepBtree::IsValid(check));
1262
+ leaf->length--;
1263
+ EXPECT_FALSE(CordRepBtree::IsValid(check));
1264
+ leaf->length++;
1265
+
1266
+ ASSERT_TRUE(CordRepBtree::IsValid(check));
1267
+ leaf->tag--;
1268
+ EXPECT_FALSE(CordRepBtree::IsValid(check));
1269
+ leaf->tag++;
1270
+
1271
+ // Height
1272
+ ASSERT_TRUE(CordRepBtree::IsValid(check));
1273
+ leaf->storage[0] = static_cast<uint8_t>(CordRepBtree::kMaxHeight + 1);
1274
+ EXPECT_FALSE(CordRepBtree::IsValid(check));
1275
+ leaf->storage[0] = 1;
1276
+ EXPECT_FALSE(CordRepBtree::IsValid(check));
1277
+ leaf->storage[0] = 0;
1278
+
1279
+ // Begin
1280
+ ASSERT_TRUE(CordRepBtree::IsValid(check));
1281
+ const uint8_t begin = leaf->storage[1];
1282
+ leaf->storage[1] = static_cast<uint8_t>(CordRepBtree::kMaxCapacity);
1283
+ EXPECT_FALSE(CordRepBtree::IsValid(check));
1284
+ leaf->storage[1] = 2;
1285
+ EXPECT_FALSE(CordRepBtree::IsValid(check));
1286
+ leaf->storage[1] = begin;
1287
+
1288
+ // End
1289
+ ASSERT_TRUE(CordRepBtree::IsValid(check));
1290
+ const uint8_t end = leaf->storage[2];
1291
+ leaf->storage[2] = static_cast<uint8_t>(CordRepBtree::kMaxCapacity + 1);
1292
+ EXPECT_FALSE(CordRepBtree::IsValid(check));
1293
+ leaf->storage[2] = end;
1294
+
1295
+ // DataEdge tag and value
1296
+ ASSERT_TRUE(CordRepBtree::IsValid(check));
1297
+ CordRep* const edge = leaf->Edges()[0];
1298
+ const uint8_t tag = edge->tag;
1299
+ CordRepBtreeTestPeer::SetEdge(leaf, begin, nullptr);
1300
+ EXPECT_FALSE(CordRepBtree::IsValid(check));
1301
+ CordRepBtreeTestPeer::SetEdge(leaf, begin, edge);
1302
+ edge->tag = BTREE;
1303
+ EXPECT_FALSE(CordRepBtree::IsValid(check));
1304
+ edge->tag = tag;
1305
+
1306
+ if (as_tree) {
1307
+ ASSERT_TRUE(CordRepBtree::IsValid(check));
1308
+ leaf->length--;
1309
+ EXPECT_FALSE(CordRepBtree::IsValid(check));
1310
+ leaf->length++;
1311
+
1312
+ // Height
1313
+ ASSERT_TRUE(CordRepBtree::IsValid(check));
1314
+ tree->storage[0] = static_cast<uint8_t>(2);
1315
+ EXPECT_FALSE(CordRepBtree::IsValid(check));
1316
+ tree->storage[0] = 1;
1317
+
1318
+ // Btree edge
1319
+ ASSERT_TRUE(CordRepBtree::IsValid(check));
1320
+ CordRep* const edge = tree->Edges()[0];
1321
+ const uint8_t tag = edge->tag;
1322
+ edge->tag = FLAT;
1323
+ EXPECT_FALSE(CordRepBtree::IsValid(check));
1324
+ edge->tag = tag;
1325
+ }
1326
+
1327
+ ASSERT_TRUE(CordRepBtree::IsValid(check));
1328
+ CordRep::Unref(check);
1329
+ }
1330
+ }
1331
+
1332
+ TEST(CordRepBtreeTest, AssertValid) {
1333
+ CordRepBtree* tree = CordRepBtree::Create(MakeFlat("abc"));
1334
+ const CordRepBtree* ctree = tree;
1335
+ EXPECT_THAT(CordRepBtree::AssertValid(tree), Eq(tree));
1336
+ EXPECT_THAT(CordRepBtree::AssertValid(ctree), Eq(ctree));
1337
+
1338
+ #if defined(GTEST_HAS_DEATH_TEST)
1339
+ CordRepBtree* nulltree = nullptr;
1340
+ const CordRepBtree* cnulltree = nullptr;
1341
+ EXPECT_DEBUG_DEATH(
1342
+ EXPECT_THAT(CordRepBtree::AssertValid(nulltree), Eq(nulltree)), ".*");
1343
+ EXPECT_DEBUG_DEATH(
1344
+ EXPECT_THAT(CordRepBtree::AssertValid(cnulltree), Eq(cnulltree)), ".*");
1345
+
1346
+ tree->length--;
1347
+ EXPECT_DEBUG_DEATH(EXPECT_THAT(CordRepBtree::AssertValid(tree), Eq(tree)),
1348
+ ".*");
1349
+ EXPECT_DEBUG_DEATH(EXPECT_THAT(CordRepBtree::AssertValid(ctree), Eq(ctree)),
1350
+ ".*");
1351
+ tree->length++;
1352
+ #endif
1353
+ CordRep::Unref(tree);
1354
+ }
1355
+
1356
+ TEST(CordRepBtreeTest, CheckAssertValidShallowVsDeep) {
1357
+ // Restore exhaustive validation on any exit.
1358
+ const bool exhaustive_validation = IsCordBtreeExhaustiveValidationEnabled();
1359
+ auto cleanup = absl::MakeCleanup([exhaustive_validation] {
1360
+ SetCordBtreeExhaustiveValidation(exhaustive_validation);
1361
+ });
1362
+
1363
+ // Create a tree of at least 2 levels, and mess with the original flat, which
1364
+ // should go undetected in shallow mode as the flat is too far away, but
1365
+ // should be detected in forced non-shallow mode.
1366
+ CordRep* flat = MakeFlat("abc");
1367
+ CordRepBtree* tree = CordRepBtree::Create(flat);
1368
+ constexpr size_t max_cap = CordRepBtree::kMaxCapacity;
1369
+ const size_t n = max_cap * max_cap * 2;
1370
+ for (size_t i = 0; i < n; ++i) {
1371
+ tree = CordRepBtree::Append(tree, MakeFlat("Hello world"));
1372
+ }
1373
+ flat->length = 100;
1374
+
1375
+ SetCordBtreeExhaustiveValidation(false);
1376
+ EXPECT_FALSE(CordRepBtree::IsValid(tree));
1377
+ EXPECT_TRUE(CordRepBtree::IsValid(tree, true));
1378
+ EXPECT_FALSE(CordRepBtree::IsValid(tree, false));
1379
+ CordRepBtree::AssertValid(tree);
1380
+ CordRepBtree::AssertValid(tree, true);
1381
+ #if defined(GTEST_HAS_DEATH_TEST)
1382
+ EXPECT_DEBUG_DEATH(CordRepBtree::AssertValid(tree, false), ".*");
1383
+ #endif
1384
+
1385
+ SetCordBtreeExhaustiveValidation(true);
1386
+ EXPECT_FALSE(CordRepBtree::IsValid(tree));
1387
+ EXPECT_FALSE(CordRepBtree::IsValid(tree, true));
1388
+ EXPECT_FALSE(CordRepBtree::IsValid(tree, false));
1389
+ #if defined(GTEST_HAS_DEATH_TEST)
1390
+ EXPECT_DEBUG_DEATH(CordRepBtree::AssertValid(tree), ".*");
1391
+ EXPECT_DEBUG_DEATH(CordRepBtree::AssertValid(tree, true), ".*");
1392
+ #endif
1393
+
1394
+ flat->length = 3;
1395
+ CordRep::Unref(tree);
1396
+ }
1397
+
1398
+ TEST_P(CordRepBtreeTest, Rebuild) {
1399
+ for (size_t size : {3u, 8u, 100u, 10000u, 1000000u}) {
1400
+ SCOPED_TRACE(absl::StrCat("Rebuild @", size));
1401
+
1402
+ std::vector<CordRepFlat*> flats;
1403
+ for (size_t i = 0; i < size; ++i) {
1404
+ flats.push_back(CordRepFlat::New(2));
1405
+ flats.back()->Data()[0] = 'x';
1406
+ flats.back()->length = 1;
1407
+ }
1408
+
1409
+ // Build the tree into 'right', and each so many 'split_limit' edges,
1410
+ // combine 'left' + 'right' into a new 'left', and start a new 'right'.
1411
+ // This guarantees we get a reasonable amount of chaos in the tree.
1412
+ size_t split_count = 0;
1413
+ size_t split_limit = 3;
1414
+ auto it = flats.begin();
1415
+ CordRepBtree* left = nullptr;
1416
+ CordRepBtree* right = CordRepBtree::New(*it);
1417
+ while (++it != flats.end()) {
1418
+ if (++split_count >= split_limit) {
1419
+ split_limit += split_limit / 16;
1420
+ left = left ? CordRepBtree::Append(left, right) : right;
1421
+ right = CordRepBtree::New(*it);
1422
+ } else {
1423
+ right = CordRepBtree::Append(right, *it);
1424
+ }
1425
+ }
1426
+
1427
+ // Finalize tree
1428
+ left = left ? CordRepBtree::Append(left, right) : right;
1429
+
1430
+ // Rebuild
1431
+ AutoUnref ref;
1432
+ left = ref.Add(CordRepBtree::Rebuild(ref.RefIf(shared(), left)));
1433
+ ASSERT_TRUE(CordRepBtree::IsValid(left));
1434
+
1435
+ // Verify we have the exact same edges in the exact same order.
1436
+ bool ok = true;
1437
+ it = flats.begin();
1438
+ CordVisitReps(left, [&](CordRep* edge) {
1439
+ if (edge->tag < FLAT) return;
1440
+ ok = ok && (it != flats.end() && *it++ == edge);
1441
+ });
1442
+ EXPECT_TRUE(ok && it == flats.end()) << "Rebuild edges mismatch";
1443
+ }
1444
+ }
1445
+
1446
+ // Convenience helper for CordRepBtree::ExtractAppendBuffer
1447
+ CordRepBtree::ExtractResult ExtractLast(CordRepBtree* input, size_t cap = 1) {
1448
+ return CordRepBtree::ExtractAppendBuffer(input, cap);
1449
+ }
1450
+
1451
+ TEST(CordRepBtreeTest, ExtractAppendBufferLeafSingleFlat) {
1452
+ CordRep* flat = MakeFlat("Abc");
1453
+ CordRepBtree* leaf = CordRepBtree::Create(flat);
1454
+ EXPECT_THAT(ExtractLast(leaf), EqExtractResult(nullptr, flat));
1455
+ CordRep::Unref(flat);
1456
+ }
1457
+
1458
+ TEST(CordRepBtreeTest, ExtractAppendBufferNodeSingleFlat) {
1459
+ CordRep* flat = MakeFlat("Abc");
1460
+ CordRepBtree* leaf = CordRepBtree::Create(flat);
1461
+ CordRepBtree* node = CordRepBtree::New(leaf);
1462
+ EXPECT_THAT(ExtractLast(node), EqExtractResult(nullptr, flat));
1463
+ CordRep::Unref(flat);
1464
+ }
1465
+
1466
+ TEST(CordRepBtreeTest, ExtractAppendBufferLeafTwoFlats) {
1467
+ std::vector<CordRep*> flats = CreateFlatsFromString("abcdef", 3);
1468
+ CordRepBtree* leaf = CreateTree(flats);
1469
+ EXPECT_THAT(ExtractLast(leaf), EqExtractResult(flats[0], flats[1]));
1470
+ CordRep::Unref(flats[0]);
1471
+ CordRep::Unref(flats[1]);
1472
+ }
1473
+
1474
+ TEST(CordRepBtreeTest, ExtractAppendBufferNodeTwoFlats) {
1475
+ std::vector<CordRep*> flats = CreateFlatsFromString("abcdef", 3);
1476
+ CordRepBtree* leaf = CreateTree(flats);
1477
+ CordRepBtree* node = CordRepBtree::New(leaf);
1478
+ EXPECT_THAT(ExtractLast(node), EqExtractResult(flats[0], flats[1]));
1479
+ CordRep::Unref(flats[0]);
1480
+ CordRep::Unref(flats[1]);
1481
+ }
1482
+
1483
+ TEST(CordRepBtreeTest, ExtractAppendBufferNodeTwoFlatsInTwoLeafs) {
1484
+ std::vector<CordRep*> flats = CreateFlatsFromString("abcdef", 3);
1485
+ CordRepBtree* leaf1 = CordRepBtree::Create(flats[0]);
1486
+ CordRepBtree* leaf2 = CordRepBtree::Create(flats[1]);
1487
+ CordRepBtree* node = CordRepBtree::New(leaf1, leaf2);
1488
+ EXPECT_THAT(ExtractLast(node), EqExtractResult(flats[0], flats[1]));
1489
+ CordRep::Unref(flats[0]);
1490
+ CordRep::Unref(flats[1]);
1491
+ }
1492
+
1493
+ TEST(CordRepBtreeTest, ExtractAppendBufferLeafThreeFlats) {
1494
+ std::vector<CordRep*> flats = CreateFlatsFromString("abcdefghi", 3);
1495
+ CordRepBtree* leaf = CreateTree(flats);
1496
+ EXPECT_THAT(ExtractLast(leaf), EqExtractResult(leaf, flats[2]));
1497
+ CordRep::Unref(flats[2]);
1498
+ CordRep::Unref(leaf);
1499
+ }
1500
+
1501
+ TEST(CordRepBtreeTest, ExtractAppendBufferNodeThreeFlatsRightNoFolding) {
1502
+ CordRep* flat = MakeFlat("Abc");
1503
+ std::vector<CordRep*> flats = CreateFlatsFromString("defghi", 3);
1504
+ CordRepBtree* leaf1 = CordRepBtree::Create(flat);
1505
+ CordRepBtree* leaf2 = CreateTree(flats);
1506
+ CordRepBtree* node = CordRepBtree::New(leaf1, leaf2);
1507
+ EXPECT_THAT(ExtractLast(node), EqExtractResult(node, flats[1]));
1508
+ EXPECT_THAT(node->Edges(), ElementsAre(leaf1, leaf2));
1509
+ EXPECT_THAT(leaf1->Edges(), ElementsAre(flat));
1510
+ EXPECT_THAT(leaf2->Edges(), ElementsAre(flats[0]));
1511
+ CordRep::Unref(node);
1512
+ CordRep::Unref(flats[1]);
1513
+ }
1514
+
1515
+ TEST(CordRepBtreeTest, ExtractAppendBufferNodeThreeFlatsRightLeafFolding) {
1516
+ CordRep* flat = MakeFlat("Abc");
1517
+ std::vector<CordRep*> flats = CreateFlatsFromString("defghi", 3);
1518
+ CordRepBtree* leaf1 = CreateTree(flats);
1519
+ CordRepBtree* leaf2 = CordRepBtree::Create(flat);
1520
+ CordRepBtree* node = CordRepBtree::New(leaf1, leaf2);
1521
+ EXPECT_THAT(ExtractLast(node), EqExtractResult(leaf1, flat));
1522
+ EXPECT_THAT(leaf1->Edges(), ElementsAreArray(flats));
1523
+ CordRep::Unref(leaf1);
1524
+ CordRep::Unref(flat);
1525
+ }
1526
+
1527
+ TEST(CordRepBtreeTest, ExtractAppendBufferNoCapacity) {
1528
+ std::vector<CordRep*> flats = CreateFlatsFromString("abcdef", 3);
1529
+ CordRepBtree* leaf = CreateTree(flats);
1530
+ size_t avail = flats[1]->flat()->Capacity() - flats[1]->length;
1531
+ EXPECT_THAT(ExtractLast(leaf, avail + 1), EqExtractResult(leaf, nullptr));
1532
+ EXPECT_THAT(ExtractLast(leaf, avail), EqExtractResult(flats[0], flats[1]));
1533
+ CordRep::Unref(flats[0]);
1534
+ CordRep::Unref(flats[1]);
1535
+ }
1536
+
1537
+ TEST(CordRepBtreeTest, ExtractAppendBufferNotFlat) {
1538
+ std::vector<CordRep*> flats = CreateFlatsFromString("abcdef", 3);
1539
+ auto substr = MakeSubstring(1, 2, flats[1]);
1540
+ CordRepBtree* leaf = CreateTree({flats[0], substr});
1541
+ EXPECT_THAT(ExtractLast(leaf), EqExtractResult(leaf, nullptr));
1542
+ CordRep::Unref(leaf);
1543
+ }
1544
+
1545
+ TEST(CordRepBtreeTest, ExtractAppendBufferShared) {
1546
+ std::vector<CordRep*> flats = CreateFlatsFromString("abcdef", 3);
1547
+ CordRepBtree* leaf = CreateTree(flats);
1548
+
1549
+ CordRep::Ref(flats[1]);
1550
+ EXPECT_THAT(ExtractLast(leaf), EqExtractResult(leaf, nullptr));
1551
+ CordRep::Unref(flats[1]);
1552
+
1553
+ CordRep::Ref(leaf);
1554
+ EXPECT_THAT(ExtractLast(leaf), EqExtractResult(leaf, nullptr));
1555
+ CordRep::Unref(leaf);
1556
+
1557
+ CordRepBtree* node = CordRepBtree::New(leaf);
1558
+ CordRep::Ref(node);
1559
+ EXPECT_THAT(ExtractLast(node), EqExtractResult(node, nullptr));
1560
+ CordRep::Unref(node);
1561
+
1562
+ CordRep::Unref(node);
1563
+ }
1564
+
1565
+ } // namespace
1566
+ } // namespace cord_internal
1567
+ ABSL_NAMESPACE_END
1568
+ } // namespace absl
weight/_dep/abseil-cpp/absl/strings/internal/cord_rep_consume.h ADDED
@@ -0,0 +1,47 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Copyright 2021 The Abseil Authors
2
+ //
3
+ // Licensed under the Apache License, Version 2.0 (the "License");
4
+ // you may not use this file except in compliance with the License.
5
+ // You may obtain a copy of the License at
6
+ //
7
+ // https://www.apache.org/licenses/LICENSE-2.0
8
+ //
9
+ // Unless required by applicable law or agreed to in writing, software
10
+ // distributed under the License is distributed on an "AS IS" BASIS,
11
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ // See the License for the specific language governing permissions and
13
+ // limitations under the License.
14
+
15
+ #ifndef ABSL_STRINGS_INTERNAL_CORD_REP_CONSUME_H_
16
+ #define ABSL_STRINGS_INTERNAL_CORD_REP_CONSUME_H_
17
+
18
+ #include <functional>
19
+
20
+ #include "absl/functional/function_ref.h"
21
+ #include "absl/strings/internal/cord_internal.h"
22
+
23
+ namespace absl {
24
+ ABSL_NAMESPACE_BEGIN
25
+ namespace cord_internal {
26
+
27
+ // Consume() and ReverseConsume() consume CONCAT based trees and invoke the
28
+ // provided functor with the contained nodes in the proper forward or reverse
29
+ // order, which is used to convert CONCAT trees into other tree or cord data.
30
+ // All CONCAT and SUBSTRING nodes are processed internally. The 'offset`
31
+ // parameter of the functor is non-zero for any nodes below SUBSTRING nodes.
32
+ // It's up to the caller to form these back into SUBSTRING nodes or otherwise
33
+ // store offset / prefix information. These functions are intended to be used
34
+ // only for migration / transitional code where due to factors such as ODR
35
+ // violations, we can not 100% guarantee that all code respects 'new format'
36
+ // settings and flags, so we need to be able to parse old data on the fly until
37
+ // all old code is deprecated / no longer the default format.
38
+ void Consume(CordRep* rep,
39
+ FunctionRef<void(CordRep*, size_t, size_t)> consume_fn);
40
+ void ReverseConsume(CordRep* rep,
41
+ FunctionRef<void(CordRep*, size_t, size_t)> consume_fn);
42
+
43
+ } // namespace cord_internal
44
+ ABSL_NAMESPACE_END
45
+ } // namespace absl
46
+
47
+ #endif // ABSL_STRINGS_INTERNAL_CORD_REP_CONSUME_H_
weight/_dep/abseil-cpp/absl/strings/internal/cord_rep_crc.cc ADDED
@@ -0,0 +1,56 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Copyright 2021 The Abseil Authors
2
+ //
3
+ // Licensed under the Apache License, Version 2.0 (the "License");
4
+ // you may not use this file except in compliance with the License.
5
+ // You may obtain a copy of the License at
6
+ //
7
+ // https://www.apache.org/licenses/LICENSE-2.0
8
+ //
9
+ // Unless required by applicable law or agreed to in writing, software
10
+ // distributed under the License is distributed on an "AS IS" BASIS,
11
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ // See the License for the specific language governing permissions and
13
+ // limitations under the License.
14
+
15
+ #include "absl/strings/internal/cord_rep_crc.h"
16
+
17
+ #include <cassert>
18
+ #include <cstdint>
19
+ #include <utility>
20
+
21
+ #include "absl/base/config.h"
22
+ #include "absl/strings/internal/cord_internal.h"
23
+
24
+ namespace absl {
25
+ ABSL_NAMESPACE_BEGIN
26
+ namespace cord_internal {
27
+
28
+ CordRepCrc* CordRepCrc::New(CordRep* child, crc_internal::CrcCordState state) {
29
+ if (child != nullptr && child->IsCrc()) {
30
+ if (child->refcount.IsOne()) {
31
+ child->crc()->crc_cord_state = std::move(state);
32
+ return child->crc();
33
+ }
34
+ CordRep* old = child;
35
+ child = old->crc()->child;
36
+ CordRep::Ref(child);
37
+ CordRep::Unref(old);
38
+ }
39
+ auto* new_cordrep = new CordRepCrc;
40
+ new_cordrep->length = child != nullptr ? child->length : 0;
41
+ new_cordrep->tag = cord_internal::CRC;
42
+ new_cordrep->child = child;
43
+ new_cordrep->crc_cord_state = std::move(state);
44
+ return new_cordrep;
45
+ }
46
+
47
+ void CordRepCrc::Destroy(CordRepCrc* node) {
48
+ if (node->child != nullptr) {
49
+ CordRep::Unref(node->child);
50
+ }
51
+ delete node;
52
+ }
53
+
54
+ } // namespace cord_internal
55
+ ABSL_NAMESPACE_END
56
+ } // namespace absl