2 +----------------------------------------------------------------------+
4 +----------------------------------------------------------------------+
5 | Copyright (c) 2010-present 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 #ifndef incl_HPHP_VM_UNIT_UTIL_H_
18 #define incl_HPHP_VM_UNIT_UTIL_H_
20 #include <folly/Range.h>
22 #include "hphp/runtime/base/array-iterator.h"
23 #include "hphp/runtime/base/static-string-table.h"
24 #include "hphp/runtime/base/type-string.h"
25 #include "hphp/runtime/base/type-structure.h"
29 //////////////////////////////////////////////////////////////////////
32 * Returns true if the class or function name is normalized wrt namespaces.
34 inline bool isNSNormalized(const StringData
* name
) {
35 return name
->data()[0] != '\\';
39 * Returns true if the class or function name needs to be normalized.
41 inline bool needsNSNormalization(const StringData
* name
) {
42 auto const data
= name
->data();
43 return name
->size() >= 2 && data
[0] == '\\' && data
[1] != '\\';
47 * Returns true if the string is not of the form "Class::Method".
49 inline bool notClassMethodPair(const StringData
* name
) {
50 return strstr(name
->data(), "::") == nullptr;
53 const char kInOutSuffix
[] = "$inout";
54 inline bool needsStripInOut(const StringData
* name
) {
56 name
->size() > sizeof(kInOutSuffix
) &&
57 !strcmp(name
->data() + name
->size() - strlen(kInOutSuffix
), kInOutSuffix
);
61 * Normalizes a given class or function name removing the leading '\'.
62 * Leaves the name unchanged if more than one '\' is leading.
63 * So '\name' becomes 'name' but '\\name' stays '\\name'.
65 inline const StringData
* normalizeNS(const StringData
* name
) {
66 if (needsNSNormalization(name
)) {
67 assertx(name
->size() != 0);
68 auto const size
= static_cast<size_t>(name
->size() - 1);
69 auto const piece
= folly::StringPiece
{name
->data() + 1, size
};
70 return makeStaticString(piece
);
75 inline String
normalizeNS(const String
& name
) {
76 if (needsNSNormalization(name
.get())) {
77 return String(name
.data() + 1, name
.size() - 1, CopyString
);
82 inline const StringData
* stripInOutSuffix(const StringData
* name
) {
83 if (UNLIKELY(needsStripInOut(name
))) {
84 assertx(name
->size() > sizeof(kInOutSuffix
));
85 auto const s
= name
->data();
86 size_t len
= name
->size() - sizeof(kInOutSuffix
);
87 for (; s
[len
] != '$'; --len
) assertx(len
!= 0);
88 return makeStaticString(folly::StringPiece(name
->data(), len
));
93 inline StringData
* stripInOutSuffix(StringData
* name
) {
94 return const_cast<StringData
*>(
95 stripInOutSuffix((const StringData
*)name
)
99 inline String
stripInOutSuffix(String
& s
) {
100 return String(stripInOutSuffix(s
.get()));
103 inline std::string
mangleInOutFuncName(const char* name
,
104 std::vector
<uint32_t> params
) {
105 return folly::sformat("{}${}$inout", name
, folly::join(";", params
));
108 inline std::string
mangleInOutFuncName(const std::string
& name
,
109 std::vector
<uint32_t> params
) {
110 return mangleInOutFuncName(name
.data(), std::move(params
));
113 inline String
mangleInOutFuncName(const StringData
* name
,
114 std::vector
<uint32_t> params
) {
115 return String(makeStaticString(
116 mangleInOutFuncName(name
->data(), std::move(params
))
120 inline std::string
mangleReifiedGenericsName(const ArrayData
* tsList
) {
121 std::vector
<std::string
> l
;
125 assertx(isArrayLikeType(v
.m_type
));
127 TypeStructure::toStringForDisplay(ArrNR(v
.m_data
.parr
)).toCppString();
128 str
.erase(remove_if(str
.begin(), str
.end(), isspace
), str
.end());
132 return folly::sformat("<{}>", folly::join(",", l
));
135 inline StringData
* mangleReifiedName(
136 const StringData
* name
,
137 const StringData
* tsName
139 return makeStaticString(folly::sformat("$${}$${}", name
, tsName
));
142 inline bool isReifiedName(const StringData
* name
) {
143 // Length larger than $$name$$<type>
144 return name
->size() > 7 &&
145 name
->data()[0] == '$' &&
146 name
->data()[1] == '$' &&
147 folly::qfind(name
->slice(), folly::StringPiece("$$<"))
148 != std::string::npos
;
151 inline folly::StringPiece
stripClsOrFnNameFromReifiedName(
152 const folly::StringPiece name
154 auto i
= name
.find("$$<");
155 if (i
== std::string::npos
) raise_error("Not a reified name");
156 return name
.subpiece(i
+ 2, name
.size() - i
- 2);
159 inline StringData
* stripClsOrFnNameFromReifiedName(const StringData
* name
) {
160 return makeStaticString(stripClsOrFnNameFromReifiedName(name
->slice()));
163 inline folly::StringPiece
stripTypeFromReifiedName(
164 const folly::StringPiece name
166 auto i
= name
.find("$$<");
167 if (i
== std::string::npos
|| i
< 2) raise_error("Not a reified name");
168 // Remove the initial $$
169 return name
.subpiece(2, i
- 2);
172 inline StringData
* stripTypeFromReifiedName(const StringData
* name
) {
173 return makeStaticString(stripTypeFromReifiedName(name
->slice()));
176 //////////////////////////////////////////////////////////////////////