1 //
2 // Copyright 2018 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 #ifndef ABSL_STRINGS_CORD_TEST_HELPERS_H_
18 #define ABSL_STRINGS_CORD_TEST_HELPERS_H_
19
20 #include <cstdint>
21 #include <iostream>
22 #include <string>
23
24 #include "absl/base/config.h"
25 #include "absl/strings/cord.h"
26 #include "absl/strings/internal/cord_internal.h"
27 #include "absl/strings/string_view.h"
28
29 namespace absl {
30 ABSL_NAMESPACE_BEGIN
31
32 // Cord sizes relevant for testing
33 enum class TestCordSize {
34 // An empty value
35 kEmpty = 0,
36
37 // An inlined string value
38 kInlined = cord_internal::kMaxInline / 2 + 1,
39
40 // 'Well known' SSO lengths (excluding terminating zero).
41 // libstdcxx has a maximum SSO of 15, libc++ has a maximum SSO of 22.
42 kStringSso1 = 15,
43 kStringSso2 = 22,
44
45 // A string value which is too large to fit in inlined data, but small enough
46 // such that Cord prefers copying the value if possible, i.e.: not stealing
47 // std::string inputs, or referencing existing CordReps on Append, etc.
48 kSmall = cord_internal::kMaxBytesToCopy / 2 + 1,
49
50 // A string value large enough that Cord prefers to reference or steal from
51 // existing inputs rather than copying contents of the input.
52 kMedium = cord_internal::kMaxFlatLength / 2 + 1,
53
54 // A string value large enough to cause it to be stored in mutliple flats.
55 kLarge = cord_internal::kMaxFlatLength * 4
56 };
57
58 // To string helper
ToString(TestCordSize size)59 inline absl::string_view ToString(TestCordSize size) {
60 switch (size) {
61 case TestCordSize::kEmpty:
62 return "Empty";
63 case TestCordSize::kInlined:
64 return "Inlined";
65 case TestCordSize::kSmall:
66 return "Small";
67 case TestCordSize::kStringSso1:
68 return "StringSso1";
69 case TestCordSize::kStringSso2:
70 return "StringSso2";
71 case TestCordSize::kMedium:
72 return "Medium";
73 case TestCordSize::kLarge:
74 return "Large";
75 }
76 return "???";
77 }
78
79 // Returns the length matching the specified size
Length(TestCordSize size)80 inline size_t Length(TestCordSize size) { return static_cast<size_t>(size); }
81
82 // Stream output helper
83 inline std::ostream& operator<<(std::ostream& stream, TestCordSize size) {
84 return stream << ToString(size);
85 }
86
87 // Creates a multi-segment Cord from an iterable container of strings. The
88 // resulting Cord is guaranteed to have one segment for every string in the
89 // container. This allows code to be unit tested with multi-segment Cord
90 // inputs.
91 //
92 // Example:
93 //
94 // absl::Cord c = absl::MakeFragmentedCord({"A ", "fragmented ", "Cord"});
95 // EXPECT_FALSE(c.GetFlat(&unused));
96 //
97 // The mechanism by which this Cord is created is an implementation detail. Any
98 // implementation that produces a multi-segment Cord may produce a flat Cord in
99 // the future as new optimizations are added to the Cord class.
100 // MakeFragmentedCord will, however, always be updated to return a multi-segment
101 // Cord.
102 template <typename Container>
MakeFragmentedCord(const Container & c)103 Cord MakeFragmentedCord(const Container& c) {
104 Cord result;
105 for (const auto& s : c) {
106 auto* external = new std::string(s);
107 Cord tmp = absl::MakeCordFromExternal(
108 *external, [external](absl::string_view) { delete external; });
109 tmp.Prepend(result);
110 result = tmp;
111 }
112 return result;
113 }
114
MakeFragmentedCord(std::initializer_list<absl::string_view> list)115 inline Cord MakeFragmentedCord(std::initializer_list<absl::string_view> list) {
116 return MakeFragmentedCord<std::initializer_list<absl::string_view>>(list);
117 }
118
119 ABSL_NAMESPACE_END
120 } // namespace absl
121
122 #endif // ABSL_STRINGS_CORD_TEST_HELPERS_H_
123