2 +----------------------------------------------------------------------+
4 +----------------------------------------------------------------------+
5 | Copyright (c) 2010-2014 Facebook, Inc. (http://www.facebook.com) |
6 +----------------------------------------------------------------------+
7 | This source file is subject to version 3.01 of the PHP license, |
8 | that is bundled with this package in the file LICENSE, and is |
9 | available through the world-wide-web at the following url: |
10 | http://www.php.net/license/3_01.txt |
11 | If you did not receive a copy of the PHP license and are unable to |
12 | obtain it through the world-wide-web, please send a note to |
13 | license@php.net so we can mail you a copy immediately. |
14 +----------------------------------------------------------------------+
17 #include "hphp/util/text-util.h"
20 #include <cstring> // memcpy
23 #include "hphp/util/string-vsnprintf.h"
30 // --- Static functions.
32 bool TextUtil::BeginsWith(const string
& str1
, const string
& str2
) {
33 // | [----------str2--------]
34 // | <<<<<<<<< match >>>>>>>>
35 // | [--------------------------------str1-------]
37 if (str2
.length() > str1
.length()) {
41 return str1
.find(str2
) == 0;
44 string
TextUtil::StripCommonStart(const string
& str1
, const string
& str2
) {
45 if (!BeginsWith(str1
, str2
)) {
49 return str1
.substr(str2
.length());
52 bool TextUtil::EndsWith(const string
& str
, char ch
) {
53 return *str
.rbegin() == ch
;
56 string
TextUtil::StripTrailing(const std::string
& str
, char ch
) {
59 size_t i
= str
.find_last_not_of(ch
);
61 if (i
!= string::npos
) {
64 temp
.clear(); // Nothing but those chars.
70 vector
<string
> TextUtil::MakePathList(const string
& path
) {
78 for (size_t i
= 1; i
< path
.length(); ++i
) {
80 temp
.push_back(path
.substr(start
, i
));
87 void split(char delimiter
, const char *s
, vector
<string
> &out
,
88 bool ignoreEmpty
/* = false */) {
91 const char *start
= s
;
94 if (*p
== delimiter
) {
95 if (!ignoreEmpty
|| p
> start
) {
96 out
.push_back(string(start
, p
- start
));
101 if (!ignoreEmpty
|| p
> start
) {
102 out
.push_back(string(start
, p
- start
));
106 void replaceAll(string
&s
, const char *from
, const char *to
) {
107 assert(from
&& *from
);
110 string::size_type lenFrom
= strlen(from
);
111 string::size_type lenTo
= strlen(to
);
112 for (string::size_type pos
= s
.find(from
);
114 pos
= s
.find(from
, pos
+ lenTo
)) {
115 s
.replace(pos
, lenFrom
, to
);
119 std::string
toLower(const std::string
&s
) {
120 unsigned int len
= s
.size();
124 for (unsigned int i
= 0; i
< len
; i
++) {
125 ret
+= tolower(s
[i
]);
131 std::string
toUpper(const std::string
&s
) {
132 unsigned int len
= s
.size();
135 for (unsigned int i
= 0; i
< len
; i
++) {
136 ret
+= toupper(s
[i
]);
141 std::string
getIdentifier(const std::string
&fileName
) {
142 string ret
= "hphp_" + fileName
;
143 replaceAll(ret
, "/", "__");
144 replaceAll(ret
, ".", "__");
145 replaceAll(ret
, "-", "__");
149 std::string
escapeStringForCPP(const char *input
, int len
,
150 bool* binary
/* = NULL */) {
151 if (binary
) *binary
= false;
153 ret
.reserve((len
<< 1) + 2);
154 for (int i
= 0; i
< len
; i
++) {
155 unsigned char ch
= input
[i
];
157 case '\n': ret
+= "\\n"; break;
158 case '\r': ret
+= "\\r"; break;
159 case '\t': ret
+= "\\t"; break;
160 case '\a': ret
+= "\\a"; break;
161 case '\b': ret
+= "\\b"; break;
162 case '\f': ret
+= "\\f"; break;
163 case '\v': ret
+= "\\v"; break;
164 case '\0': ret
+= "\\000"; if (binary
) *binary
= true; break;
165 case '\"': ret
+= "\\\""; break;
166 case '\\': ret
+= "\\\\"; break;
167 case '?': ret
+= "\\?"; break; // avoiding trigraph errors
172 // output in octal notation
174 snprintf(buf
, sizeof(buf
), "\\%03o", ch
);
183 std::string
escapeStringForPHP(const char *input
, int len
) {
185 output
.reserve((len
<< 1) + 2);
187 for (int i
= 0; i
< len
; i
++) {
188 unsigned char ch
= input
[i
];
190 case '\n': output
+= "'.\"\\n\".'"; break;
191 case '\r': output
+= "'.\"\\r\".'"; break;
192 case '\t': output
+= "'.\"\\t\".'"; break;
193 case '\'': output
+= "'.\"'\".'"; break;
194 case '\\': output
+= "'.\"\\\\\".'"; break;
201 replaceAll(output
, ".''.", ".");
202 replaceAll(output
, "''.", "");
203 replaceAll(output
, ".''", "");
204 replaceAll(output
, "\".\"", "");
208 const void *buffer_duplicate(const void *src
, int size
) {
209 char *s
= (char *)malloc(size
+ 1); // '\0' in the end
210 memcpy(s
, src
, size
);
215 const void *buffer_append(const void *buf1
, int size1
,
216 const void *buf2
, int size2
) {
217 char *s
= (char *)realloc(const_cast<void *>(buf1
), size1
+ size2
+ 1);
218 memcpy((char *)s
+ size1
, buf2
, size2
);
219 s
[size1
+ size2
] = '\0';
223 void string_printf(std::string
&msg
, const char *fmt
, ...) {
226 string_vsnprintf(msg
, fmt
, ap
);
230 std::string
format_pattern(const std::string
&pattern
, bool prefixSlash
) {
231 if (pattern
.empty()) return pattern
;
233 std::string ret
= "#";
234 for (unsigned int i
= 0; i
< pattern
.size(); i
++) {
235 char ch
= pattern
[i
];
237 // apache rewrite rules don't require initial slash
238 if (prefixSlash
&& i
== 0 && ch
== '^') {
239 char ch1
= pattern
[1];
240 if (ch1
!= '/' && ch1
!= '(') {