• 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/platform/str_util.h"
17 
18 #include <cctype>
19 #include <string>
20 #include <vector>
21 
22 #include "absl/strings/ascii.h"
23 #include "absl/strings/escaping.h"
24 #include "absl/strings/match.h"
25 #include "absl/strings/strip.h"
26 #include "tensorflow/core/platform/logging.h"
27 #include "tensorflow/core/platform/stringpiece.h"
28 
29 namespace tensorflow {
30 namespace str_util {
31 
CEscape(StringPiece src)32 string CEscape(StringPiece src) { return absl::CEscape(src); }
33 
CUnescape(StringPiece source,string * dest,string * error)34 bool CUnescape(StringPiece source, string* dest, string* error) {
35   return absl::CUnescape(source, dest, error);
36 }
37 
StripTrailingWhitespace(string * s)38 void StripTrailingWhitespace(string* s) {
39   absl::StripTrailingAsciiWhitespace(s);
40 }
41 
RemoveLeadingWhitespace(StringPiece * text)42 size_t RemoveLeadingWhitespace(StringPiece* text) {
43   absl::string_view new_text = absl::StripLeadingAsciiWhitespace(*text);
44   size_t count = text->size() - new_text.size();
45   *text = new_text;
46   return count;
47 }
48 
RemoveTrailingWhitespace(StringPiece * text)49 size_t RemoveTrailingWhitespace(StringPiece* text) {
50   absl::string_view new_text = absl::StripTrailingAsciiWhitespace(*text);
51   size_t count = text->size() - new_text.size();
52   *text = new_text;
53   return count;
54 }
55 
RemoveWhitespaceContext(StringPiece * text)56 size_t RemoveWhitespaceContext(StringPiece* text) {
57   absl::string_view new_text = absl::StripAsciiWhitespace(*text);
58   size_t count = text->size() - new_text.size();
59   *text = new_text;
60   return count;
61 }
62 
ConsumeLeadingDigits(StringPiece * s,uint64 * val)63 bool ConsumeLeadingDigits(StringPiece* s, uint64* val) {
64   const char* p = s->data();
65   const char* limit = p + s->size();
66   uint64 v = 0;
67   while (p < limit) {
68     const char c = *p;
69     if (c < '0' || c > '9') break;
70     uint64 new_v = (v * 10) + (c - '0');
71     if (new_v / 8 < v) {
72       // Overflow occurred
73       return false;
74     }
75     v = new_v;
76     p++;
77   }
78   if (p > s->data()) {
79     // Consume some digits
80     s->remove_prefix(p - s->data());
81     *val = v;
82     return true;
83   } else {
84     return false;
85   }
86 }
87 
ConsumeNonWhitespace(StringPiece * s,StringPiece * val)88 bool ConsumeNonWhitespace(StringPiece* s, StringPiece* val) {
89   const char* p = s->data();
90   const char* limit = p + s->size();
91   while (p < limit) {
92     const char c = *p;
93     if (isspace(c)) break;
94     p++;
95   }
96   const size_t n = p - s->data();
97   if (n > 0) {
98     *val = StringPiece(s->data(), n);
99     s->remove_prefix(n);
100     return true;
101   } else {
102     *val = StringPiece();
103     return false;
104   }
105 }
106 
ConsumePrefix(StringPiece * s,StringPiece expected)107 bool ConsumePrefix(StringPiece* s, StringPiece expected) {
108   return absl::ConsumePrefix(s, expected);
109 }
110 
ConsumeSuffix(StringPiece * s,StringPiece expected)111 bool ConsumeSuffix(StringPiece* s, StringPiece expected) {
112   return absl::ConsumeSuffix(s, expected);
113 }
114 
StripPrefix(StringPiece s,StringPiece expected)115 StringPiece StripPrefix(StringPiece s, StringPiece expected) {
116   return absl::StripPrefix(s, expected);
117 }
118 
StripSuffix(StringPiece s,StringPiece expected)119 StringPiece StripSuffix(StringPiece s, StringPiece expected) {
120   return absl::StripSuffix(s, expected);
121 }
122 
123 // Return lower-cased version of s.
Lowercase(StringPiece s)124 string Lowercase(StringPiece s) { return absl::AsciiStrToLower(s); }
125 
126 // Return upper-cased version of s.
Uppercase(StringPiece s)127 string Uppercase(StringPiece s) { return absl::AsciiStrToUpper(s); }
128 
TitlecaseString(string * s,StringPiece delimiters)129 void TitlecaseString(string* s, StringPiece delimiters) {
130   bool upper = true;
131   for (string::iterator ss = s->begin(); ss != s->end(); ++ss) {
132     if (upper) {
133       *ss = toupper(*ss);
134     }
135     upper = (delimiters.find(*ss) != StringPiece::npos);
136   }
137 }
138 
StringReplace(StringPiece s,StringPiece oldsub,StringPiece newsub,bool replace_all)139 string StringReplace(StringPiece s, StringPiece oldsub, StringPiece newsub,
140                      bool replace_all) {
141   // TODO(jlebar): We could avoid having to shift data around in the string if
142   // we had a StringPiece::find() overload that searched for a StringPiece.
143   string res(s);
144   size_t pos = 0;
145   while ((pos = res.find(oldsub.data(), pos, oldsub.size())) != string::npos) {
146     res.replace(pos, oldsub.size(), newsub.data(), newsub.size());
147     pos += newsub.size();
148     if (oldsub.empty()) {
149       pos++;  // Match at the beginning of the text and after every byte
150     }
151     if (!replace_all) {
152       break;
153     }
154   }
155   return res;
156 }
157 
StartsWith(StringPiece text,StringPiece prefix)158 bool StartsWith(StringPiece text, StringPiece prefix) {
159   return absl::StartsWith(text, prefix);
160 }
161 
EndsWith(StringPiece text,StringPiece suffix)162 bool EndsWith(StringPiece text, StringPiece suffix) {
163   return absl::EndsWith(text, suffix);
164 }
165 
StrContains(StringPiece haystack,StringPiece needle)166 bool StrContains(StringPiece haystack, StringPiece needle) {
167   return absl::StrContains(haystack, needle);
168 }
169 
Strnlen(const char * str,const size_t string_max_len)170 size_t Strnlen(const char* str, const size_t string_max_len) {
171   size_t len = 0;
172   while (len < string_max_len && str[len] != '\0') {
173     ++len;
174   }
175   return len;
176 }
177 
ArgDefCase(StringPiece s)178 string ArgDefCase(StringPiece s) {
179   const size_t n = s.size();
180 
181   // Compute the size of resulting string.
182   // Number of extra underscores we will need to add.
183   size_t extra_us = 0;
184   // Number of non-alpha chars in the beginning to skip.
185   size_t to_skip = 0;
186   for (size_t i = 0; i < n; ++i) {
187     // If we are skipping and current letter is non-alpha, skip it as well
188     if (i == to_skip && !isalpha(s[i])) {
189       ++to_skip;
190       continue;
191     }
192 
193     // If we are here, we are not skipping any more.
194     // If this letter is upper case, not the very first char in the
195     // resulting string, and previous letter isn't replaced with an underscore,
196     // we will need to insert an underscore.
197     if (isupper(s[i]) && i != to_skip && i > 0 && isalnum(s[i - 1])) {
198       ++extra_us;
199     }
200   }
201 
202   // Initialize result with all '_'s. There is no string
203   // constructor that does not initialize memory.
204   string result(n + extra_us - to_skip, '_');
205   // i - index into s
206   // j - index into result
207   for (size_t i = to_skip, j = 0; i < n; ++i, ++j) {
208     DCHECK_LT(j, result.size());
209     char c = s[i];
210     // If c is not alphanumeric, we don't need to do anything
211     // since there is already an underscore in its place.
212     if (isalnum(c)) {
213       if (isupper(c)) {
214         // If current char is upper case, we might need to insert an
215         // underscore.
216         if (i != to_skip) {
217           DCHECK_GT(j, 0);
218           if (result[j - 1] != '_') ++j;
219         }
220         result[j] = tolower(c);
221       } else {
222         result[j] = c;
223       }
224     }
225   }
226 
227   return result;
228 }
229 
230 }  // namespace str_util
231 }  // namespace tensorflow
232