• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Copyright 2015 The TensorFlow Authors. All Rights Reserved.
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 
16 #include "tensorflow/core/lib/strings/strcat.h"
17 
18 #include <stdarg.h>
19 #include <stdint.h>
20 #include <stdio.h>
21 #include <string.h>
22 
23 #include "tensorflow/core/lib/gtl/stl_util.h"
24 #include "tensorflow/core/platform/logging.h"
25 
26 namespace tensorflow {
27 namespace strings {
28 
AlphaNum(Hex hex)29 AlphaNum::AlphaNum(Hex hex) {
30   char *const end = &digits_[kFastToBufferSize];
31   char *writer = end;
32   uint64 value = hex.value;
33   uint64 width = hex.spec;
34   // We accomplish minimum width by OR'ing in 0x10000 to the user's value,
35   // where 0x10000 is the smallest hex number that is as wide as the user
36   // asked for.
37   uint64 mask = (static_cast<uint64>(1) << (width - 1) * 4) | value;
38   static const char hexdigits[] = "0123456789abcdef";
39   do {
40     *--writer = hexdigits[value & 0xF];
41     value >>= 4;
42     mask >>= 4;
43   } while (mask != 0);
44   piece_ = StringPiece(writer, end - writer);
45 }
46 
47 // ----------------------------------------------------------------------
48 // StrCat()
49 //    This merges the given strings or integers, with no delimiter.  This
50 //    is designed to be the fastest possible way to construct a string out
51 //    of a mix of raw C strings, StringPieces, strings, and integer values.
52 // ----------------------------------------------------------------------
53 
54 // Append is merely a version of memcpy that returns the address of the byte
55 // after the area just overwritten.  It comes in multiple flavors to minimize
56 // call overhead.
Append1(char * out,const AlphaNum & x)57 static char *Append1(char *out, const AlphaNum &x) {
58   memcpy(out, x.data(), x.size());
59   return out + x.size();
60 }
61 
Append2(char * out,const AlphaNum & x1,const AlphaNum & x2)62 static char *Append2(char *out, const AlphaNum &x1, const AlphaNum &x2) {
63   memcpy(out, x1.data(), x1.size());
64   out += x1.size();
65 
66   memcpy(out, x2.data(), x2.size());
67   return out + x2.size();
68 }
69 
Append4(char * out,const AlphaNum & x1,const AlphaNum & x2,const AlphaNum & x3,const AlphaNum & x4)70 static char *Append4(char *out, const AlphaNum &x1, const AlphaNum &x2,
71                      const AlphaNum &x3, const AlphaNum &x4) {
72   memcpy(out, x1.data(), x1.size());
73   out += x1.size();
74 
75   memcpy(out, x2.data(), x2.size());
76   out += x2.size();
77 
78   memcpy(out, x3.data(), x3.size());
79   out += x3.size();
80 
81   memcpy(out, x4.data(), x4.size());
82   return out + x4.size();
83 }
84 
StrCat(const AlphaNum & a)85 string StrCat(const AlphaNum &a) { return string(a.data(), a.size()); }
86 
StrCat(const AlphaNum & a,const AlphaNum & b)87 string StrCat(const AlphaNum &a, const AlphaNum &b) {
88   string result;
89   gtl::STLStringResizeUninitialized(&result, a.size() + b.size());
90   char *const begin = &*result.begin();
91   char *out = Append2(begin, a, b);
92   DCHECK_EQ(out, begin + result.size());
93   return result;
94 }
95 
StrCat(const AlphaNum & a,const AlphaNum & b,const AlphaNum & c)96 string StrCat(const AlphaNum &a, const AlphaNum &b, const AlphaNum &c) {
97   string result;
98   gtl::STLStringResizeUninitialized(&result, a.size() + b.size() + c.size());
99   char *const begin = &*result.begin();
100   char *out = Append2(begin, a, b);
101   out = Append1(out, c);
102   DCHECK_EQ(out, begin + result.size());
103   return result;
104 }
105 
StrCat(const AlphaNum & a,const AlphaNum & b,const AlphaNum & c,const AlphaNum & d)106 string StrCat(const AlphaNum &a, const AlphaNum &b, const AlphaNum &c,
107               const AlphaNum &d) {
108   string result;
109   gtl::STLStringResizeUninitialized(&result,
110                                     a.size() + b.size() + c.size() + d.size());
111   char *const begin = &*result.begin();
112   char *out = Append4(begin, a, b, c, d);
113   DCHECK_EQ(out, begin + result.size());
114   return result;
115 }
116 
117 namespace internal {
118 
119 // Do not call directly - these are not part of the public API.
CatPieces(std::initializer_list<StringPiece> pieces)120 string CatPieces(std::initializer_list<StringPiece> pieces) {
121   string result;
122   size_t total_size = 0;
123   for (const StringPiece piece : pieces) total_size += piece.size();
124   gtl::STLStringResizeUninitialized(&result, total_size);
125 
126   char *const begin = &*result.begin();
127   char *out = begin;
128   for (const StringPiece piece : pieces) {
129     const size_t this_size = piece.size();
130     memcpy(out, piece.data(), this_size);
131     out += this_size;
132   }
133   DCHECK_EQ(out, begin + result.size());
134   return result;
135 }
136 
137 // It's possible to call StrAppend with a StringPiece that is itself a fragment
138 // of the string we're appending to.  However the results of this are random.
139 // Therefore, check for this in debug mode.  Use unsigned math so we only have
140 // to do one comparison.
141 #define DCHECK_NO_OVERLAP(dest, src) \
142   DCHECK_GE(uintptr_t((src).data() - (dest).data()), uintptr_t((dest).size()))
143 
AppendPieces(string * result,std::initializer_list<StringPiece> pieces)144 void AppendPieces(string *result, std::initializer_list<StringPiece> pieces) {
145   size_t old_size = result->size();
146   size_t total_size = old_size;
147   for (const StringPiece piece : pieces) {
148     DCHECK_NO_OVERLAP(*result, piece);
149     total_size += piece.size();
150   }
151   gtl::STLStringResizeUninitialized(result, total_size);
152 
153   char *const begin = &*result->begin();
154   char *out = begin + old_size;
155   for (const StringPiece piece : pieces) {
156     const size_t this_size = piece.size();
157     memcpy(out, piece.data(), this_size);
158     out += this_size;
159   }
160   DCHECK_EQ(out, begin + result->size());
161 }
162 
163 }  // namespace internal
164 
StrAppend(string * result,const AlphaNum & a)165 void StrAppend(string *result, const AlphaNum &a) {
166   DCHECK_NO_OVERLAP(*result, a);
167   result->append(a.data(), a.size());
168 }
169 
StrAppend(string * result,const AlphaNum & a,const AlphaNum & b)170 void StrAppend(string *result, const AlphaNum &a, const AlphaNum &b) {
171   DCHECK_NO_OVERLAP(*result, a);
172   DCHECK_NO_OVERLAP(*result, b);
173   string::size_type old_size = result->size();
174   gtl::STLStringResizeUninitialized(result, old_size + a.size() + b.size());
175   char *const begin = &*result->begin();
176   char *out = Append2(begin + old_size, a, b);
177   DCHECK_EQ(out, begin + result->size());
178 }
179 
StrAppend(string * result,const AlphaNum & a,const AlphaNum & b,const AlphaNum & c)180 void StrAppend(string *result, const AlphaNum &a, const AlphaNum &b,
181                const AlphaNum &c) {
182   DCHECK_NO_OVERLAP(*result, a);
183   DCHECK_NO_OVERLAP(*result, b);
184   DCHECK_NO_OVERLAP(*result, c);
185   string::size_type old_size = result->size();
186   gtl::STLStringResizeUninitialized(result,
187                                     old_size + a.size() + b.size() + c.size());
188   char *const begin = &*result->begin();
189   char *out = Append2(begin + old_size, a, b);
190   out = Append1(out, c);
191   DCHECK_EQ(out, begin + result->size());
192 }
193 
StrAppend(string * result,const AlphaNum & a,const AlphaNum & b,const AlphaNum & c,const AlphaNum & d)194 void StrAppend(string *result, const AlphaNum &a, const AlphaNum &b,
195                const AlphaNum &c, const AlphaNum &d) {
196   DCHECK_NO_OVERLAP(*result, a);
197   DCHECK_NO_OVERLAP(*result, b);
198   DCHECK_NO_OVERLAP(*result, c);
199   DCHECK_NO_OVERLAP(*result, d);
200   string::size_type old_size = result->size();
201   gtl::STLStringResizeUninitialized(
202       result, old_size + a.size() + b.size() + c.size() + d.size());
203   char *const begin = &*result->begin();
204   char *out = Append4(begin + old_size, a, b, c, d);
205   DCHECK_EQ(out, begin + result->size());
206 }
207 
208 }  // namespace strings
209 }  // namespace tensorflow
210