Index: third_party/re2/util/strutil.cc |
diff --git a/third_party/re2/util/strutil.cc b/third_party/re2/util/strutil.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..6ab79b3c6b60ac1caa3b5384a9bb4dd7822829b6 |
--- /dev/null |
+++ b/third_party/re2/util/strutil.cc |
@@ -0,0 +1,97 @@ |
+// Copyright 1999-2005 The RE2 Authors. All Rights Reserved. |
+// Use of this source code is governed by a BSD-style |
+// license that can be found in the LICENSE file. |
+ |
+#include "util/util.h" |
+#include "re2/stringpiece.h" |
+ |
+namespace re2 { |
+ |
+// ---------------------------------------------------------------------- |
+// CEscapeString() |
+// Copies 'src' to 'dest', escaping dangerous characters using |
+// C-style escape sequences. 'src' and 'dest' should not overlap. |
+// Returns the number of bytes written to 'dest' (not including the \0) |
+// or -1 if there was insufficient space. |
+// ---------------------------------------------------------------------- |
+int CEscapeString(const char* src, int src_len, char* dest, |
+ int dest_len) { |
+ const char* src_end = src + src_len; |
+ int used = 0; |
+ |
+ for (; src < src_end; src++) { |
+ if (dest_len - used < 2) // Need space for two letter escape |
+ return -1; |
+ |
+ unsigned char c = *src; |
+ switch (c) { |
+ case '\n': dest[used++] = '\\'; dest[used++] = 'n'; break; |
+ case '\r': dest[used++] = '\\'; dest[used++] = 'r'; break; |
+ case '\t': dest[used++] = '\\'; dest[used++] = 't'; break; |
+ case '\"': dest[used++] = '\\'; dest[used++] = '\"'; break; |
+ case '\'': dest[used++] = '\\'; dest[used++] = '\''; break; |
+ case '\\': dest[used++] = '\\'; dest[used++] = '\\'; break; |
+ default: |
+ // Note that if we emit \xNN and the src character after that is a hex |
+ // digit then that digit must be escaped too to prevent it being |
+ // interpreted as part of the character code by C. |
+ if (c < ' ' || c > '~') { |
+ if (dest_len - used < 4) // need space for 4 letter escape |
+ return -1; |
+ sprintf(dest + used, "\\%03o", c); |
+ used += 4; |
+ } else { |
+ dest[used++] = c; break; |
+ } |
+ } |
+ } |
+ |
+ if (dest_len - used < 1) // make sure that there is room for \0 |
+ return -1; |
+ |
+ dest[used] = '\0'; // doesn't count towards return value though |
+ return used; |
+} |
+ |
+ |
+// ---------------------------------------------------------------------- |
+// CEscape() |
+// Copies 'src' to result, escaping dangerous characters using |
+// C-style escape sequences. 'src' and 'dest' should not overlap. |
+// ---------------------------------------------------------------------- |
+string CEscape(const StringPiece& src) { |
+ const int dest_length = src.size() * 4 + 1; // Maximum possible expansion |
+ char* dest = new char[dest_length]; |
+ const int len = CEscapeString(src.data(), src.size(), |
+ dest, dest_length); |
+ string s = string(dest, len); |
+ delete[] dest; |
+ return s; |
+} |
+ |
+string PrefixSuccessor(const StringPiece& prefix) { |
+ // We can increment the last character in the string and be done |
+ // unless that character is 255, in which case we have to erase the |
+ // last character and increment the previous character, unless that |
+ // is 255, etc. If the string is empty or consists entirely of |
+ // 255's, we just return the empty string. |
+ bool done = false; |
+ string limit(prefix.data(), prefix.size()); |
+ int index = limit.length() - 1; |
+ while (!done && index >= 0) { |
+ if ((limit[index]&255) == 255) { |
+ limit.erase(index); |
+ index--; |
+ } else { |
+ limit[index]++; |
+ done = true; |
+ } |
+ } |
+ if (!done) { |
+ return ""; |
+ } else { |
+ return limit; |
+ } |
+} |
+ |
+} // namespace re2 |