1 // Copyright (C) 2019 Google LLC
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 // http://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 "icing/absl_ports/str_cat.h"
16
17 namespace icing {
18 namespace lib {
19 namespace absl_ports {
20
Append(char * out,std::string_view s)21 char* Append(char* out, std::string_view s) {
22 if (!s.empty()) {
23 memcpy(out, s.data(), s.length());
24 out += s.length();
25 }
26 return out;
27 }
28
StrCat(std::string_view a,std::string_view b)29 std::string StrCat(std::string_view a, std::string_view b) {
30 std::string::size_type result_size = a.length() + b.length();
31 // Create result with enough room to fit all operands.
32 std::string result;
33 // __resize_default_init is provided by libc++ >= 8.0 and allows us to
34 // allocate room for the content we're about to copy while avoiding the
35 // unnecessary zero-initialization that the normal std::string::resize will
36 // perform.
37 //
38 // The current absl implementation copies a null char to the character at
39 // previous_size after the call to resize_default_init due to implementation
40 // differences between libstdc++ and libc++. That behavior is NOT copied over
41 // here because the following lines are just about to overwrite that character
42 // anyways.
43 result.__resize_default_init(result_size);
44
45 char* out = &result[0];
46 out = Append(out, a);
47 out = Append(out, b);
48 return result;
49 }
50
StrCat(std::string_view a,std::string_view b,std::string_view c)51 std::string StrCat(std::string_view a, std::string_view b, std::string_view c) {
52 std::string::size_type result_size = a.length() + b.length() + c.length();
53 // Create result with enough room to fit all operands.
54 std::string result;
55 // __resize_default_init is provided by libc++ >= 8.0 and allows us to
56 // allocate room for the content we're about to copy while avoiding the
57 // unnecessary zero-initialization that the normal std::string::resize will
58 // perform.
59 //
60 // The current absl implementation copies a null char to the character at
61 // previous_size after the call to resize_default_init due to implementation
62 // differences between libstdc++ and libc++. That behavior is NOT copied over
63 // here because the following lines are just about to overwrite that character
64 // anyways.
65 result.__resize_default_init(result_size);
66
67 char* out = &result[0];
68 out = Append(out, a);
69 out = Append(out, b);
70 out = Append(out, c);
71 return result;
72 }
73
StrCat(std::string_view a,std::string_view b,std::string_view c,std::string_view d)74 std::string StrCat(std::string_view a, std::string_view b, std::string_view c,
75 std::string_view d) {
76 std::string::size_type result_size =
77 a.length() + b.length() + c.length() + d.length();
78 // Create result with enough room to fit all operands.
79 std::string result;
80 // __resize_default_init is provided by libc++ >= 8.0 and allows us to
81 // allocate room for the content we're about to copy while avoiding the
82 // unnecessary zero-initialization that the normal std::string::resize will
83 // perform.
84 //
85 // The current absl implementation copies a null char to the character at
86 // previous_size after the call to resize_default_init due to implementation
87 // differences between libstdc++ and libc++. That behavior is NOT copied over
88 // here because the following lines are just about to overwrite that character
89 // anyways.
90 result.__resize_default_init(result_size);
91
92 char* out = &result[0];
93 out = Append(out, a);
94 out = Append(out, b);
95 out = Append(out, c);
96 out = Append(out, d);
97 return result;
98 }
99
StrCatPieces(std::vector<std::string_view> pieces)100 std::string StrCatPieces(std::vector<std::string_view> pieces) {
101 std::string::size_type result_size = 0;
102 for (std::string_view s : pieces) {
103 result_size += s.length();
104 }
105 // Create result with enough room to fit all operands.
106 std::string result;
107 // __resize_default_init is provided by libc++ >= 8.0 and allows us to
108 // allocate room for the content we're about to copy while avoiding the
109 // unnecessary zero-initialization that the normal std::string::resize will
110 // perform.
111 //
112 // The current absl implementation copies a null char to the character at
113 // previous_size after the call to resize_default_init due to implementation
114 // differences between libstdc++ and libc++. That behavior is NOT copied over
115 // here because the following lines are just about to overwrite that character
116 // anyways.
117 result.__resize_default_init(result_size);
118
119 char* out = &result[0];
120 for (std::string_view s : pieces) {
121 out = Append(out, s);
122 }
123 return result;
124 }
125
StrAppend(std::string * dest,std::string_view a)126 void StrAppend(std::string* dest, std::string_view a) {
127 std::string::size_type old_size = dest->size();
128 std::string::size_type new_size = old_size + a.length();
129 dest->__resize_default_init(new_size);
130
131 char* out = &(*dest)[old_size];
132 out = Append(out, a);
133 }
134
StrAppend(std::string * dest,std::string_view a,std::string_view b)135 void StrAppend(std::string* dest, std::string_view a, std::string_view b) {
136 std::string::size_type old_size = dest->size();
137 std::string::size_type new_size = old_size + a.length() + b.length();
138 dest->__resize_default_init(new_size);
139
140 char* out = &(*dest)[old_size];
141 out = Append(out, a);
142 out = Append(out, b);
143 }
144
StrAppend(std::string * dest,std::string_view a,std::string_view b,std::string_view c)145 void StrAppend(std::string* dest, std::string_view a, std::string_view b,
146 std::string_view c) {
147 std::string::size_type old_size = dest->size();
148 std::string::size_type new_size =
149 old_size + a.length() + b.length() + c.length();
150 dest->__resize_default_init(new_size);
151
152 char* out = &(*dest)[old_size];
153 out = Append(out, a);
154 out = Append(out, b);
155 out = Append(out, c);
156 }
157
StrAppend(std::string * dest,std::string_view a,std::string_view b,std::string_view c,std::string_view d)158 void StrAppend(std::string* dest, std::string_view a, std::string_view b,
159 std::string_view c, std::string_view d) {
160 std::string::size_type old_size = dest->size();
161 std::string::size_type new_size =
162 old_size + a.length() + b.length() + c.length() + d.length();
163 dest->__resize_default_init(new_size);
164
165 char* out = &(*dest)[old_size];
166 out = Append(out, a);
167 out = Append(out, b);
168 out = Append(out, c);
169 out = Append(out, d);
170 }
171
StrAppendPieces(std::string * dest,std::vector<std::string_view> pieces)172 void StrAppendPieces(std::string* dest, std::vector<std::string_view> pieces) {
173 std::string::size_type old_size = dest->size();
174 std::string::size_type result_size = old_size;
175 for (std::string_view s : pieces) {
176 result_size += s.length();
177 }
178 // Resize dest with enough room to fit all operands.
179 dest->__resize_default_init(result_size);
180
181 char* out = &(*dest)[old_size];
182 for (std::string_view s : pieces) {
183 out = Append(out, s);
184 }
185 }
186
187 } // namespace absl_ports
188 } // namespace lib
189 } // namespace icing
190