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