OLD | NEW |
| (Empty) |
1 // Copyright 1999-2005 The RE2 Authors. All Rights Reserved. | |
2 // Use of this source code is governed by a BSD-style | |
3 // license that can be found in the LICENSE file. | |
4 | |
5 #include "util/util.h" | |
6 #include "re2/stringpiece.h" | |
7 | |
8 namespace re2 { | |
9 | |
10 // ---------------------------------------------------------------------- | |
11 // CEscapeString() | |
12 // Copies 'src' to 'dest', escaping dangerous characters using | |
13 // C-style escape sequences. 'src' and 'dest' should not overlap. | |
14 // Returns the number of bytes written to 'dest' (not including the \0) | |
15 // or -1 if there was insufficient space. | |
16 // ---------------------------------------------------------------------- | |
17 int CEscapeString(const char* src, int src_len, char* dest, | |
18 int dest_len) { | |
19 const char* src_end = src + src_len; | |
20 int used = 0; | |
21 | |
22 for (; src < src_end; src++) { | |
23 if (dest_len - used < 2) // space for two-character escape | |
24 return -1; | |
25 | |
26 unsigned char c = *src; | |
27 switch (c) { | |
28 case '\n': dest[used++] = '\\'; dest[used++] = 'n'; break; | |
29 case '\r': dest[used++] = '\\'; dest[used++] = 'r'; break; | |
30 case '\t': dest[used++] = '\\'; dest[used++] = 't'; break; | |
31 case '\"': dest[used++] = '\\'; dest[used++] = '\"'; break; | |
32 case '\'': dest[used++] = '\\'; dest[used++] = '\''; break; | |
33 case '\\': dest[used++] = '\\'; dest[used++] = '\\'; break; | |
34 default: | |
35 // Note that if we emit \xNN and the src character after that is a hex | |
36 // digit then that digit must be escaped too to prevent it being | |
37 // interpreted as part of the character code by C. | |
38 if (c < ' ' || c > '~') { | |
39 if (dest_len - used < 5) // space for four-character escape + \0 | |
40 return -1; | |
41 #if !defined(_WIN32) | |
42 snprintf(dest + used, 5, "\\%03o", c); | |
43 #else | |
44 // On Windows, the function takes 4+VA arguments, not 3+VA. With an | |
45 // array, the buffer size will be inferred, but not with a pointer. | |
46 snprintf(dest + used, 5, _TRUNCATE, "\\%03o", c); | |
47 #endif | |
48 used += 4; | |
49 } else { | |
50 dest[used++] = c; break; | |
51 } | |
52 } | |
53 } | |
54 | |
55 if (dest_len - used < 1) // make sure that there is room for \0 | |
56 return -1; | |
57 | |
58 dest[used] = '\0'; // doesn't count towards return value though | |
59 return used; | |
60 } | |
61 | |
62 | |
63 // ---------------------------------------------------------------------- | |
64 // CEscape() | |
65 // Copies 'src' to result, escaping dangerous characters using | |
66 // C-style escape sequences. 'src' and 'dest' should not overlap. | |
67 // ---------------------------------------------------------------------- | |
68 string CEscape(const StringPiece& src) { | |
69 const int dest_length = src.size() * 4 + 1; // Maximum possible expansion | |
70 char* dest = new char[dest_length]; | |
71 const int len = CEscapeString(src.data(), src.size(), | |
72 dest, dest_length); | |
73 string s = string(dest, len); | |
74 delete[] dest; | |
75 return s; | |
76 } | |
77 | |
78 string PrefixSuccessor(const StringPiece& prefix) { | |
79 // We can increment the last character in the string and be done | |
80 // unless that character is 255, in which case we have to erase the | |
81 // last character and increment the previous character, unless that | |
82 // is 255, etc. If the string is empty or consists entirely of | |
83 // 255's, we just return the empty string. | |
84 bool done = false; | |
85 string limit(prefix.data(), prefix.size()); | |
86 int index = static_cast<int>(limit.size()) - 1; | |
87 while (!done && index >= 0) { | |
88 if ((limit[index]&255) == 255) { | |
89 limit.erase(index); | |
90 index--; | |
91 } else { | |
92 limit[index]++; | |
93 done = true; | |
94 } | |
95 } | |
96 if (!done) { | |
97 return ""; | |
98 } else { | |
99 return limit; | |
100 } | |
101 } | |
102 | |
103 } // namespace re2 | |
OLD | NEW |