• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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