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_COLLECTIONS_H_
18 #define incl_HPHP_COLLECTIONS_H_
20 #include <folly/Optional.h>
22 #include "hphp/runtime/base/header-kind.h"
23 #include "hphp/runtime/base/type-string.h"
37 namespace HPHP
{ namespace collections
{
38 /////////////////////////////////////////////////////////////////////////////
40 #define COLLECTIONS_PAIRED_TYPES(MACRO) \
41 MACRO(Vector) MACRO(ImmVector) \
42 MACRO(Map) MACRO(ImmMap) \
43 MACRO(Set) MACRO(ImmSet)
45 #define COLLECTIONS_ALL_TYPES(MACRO) \
47 COLLECTIONS_PAIRED_TYPES(MACRO)
49 #define X(type) extern const StaticString s_##type;
50 COLLECTIONS_ALL_TYPES(X
)
53 /////////////////////////////////////////////////////////////////////////////
54 // Constructor/Initializer
56 using newEmptyInstanceFunc
= ObjectData
* (*)();
57 using newFromArrayFunc
= ObjectData
* (*)(ArrayData
* arr
);
59 /* Get a function capable of creating a collection class.
60 * This is primarily used by the JIT to burn the initializer into the TC.
62 newEmptyInstanceFunc
allocEmptyFunc(CollectionType ctype
);
63 newFromArrayFunc
allocFromArrayFunc(CollectionType ctype
);
66 * Create a new empty collection, with refcount set to 1.
68 inline ObjectData
* alloc(CollectionType ctype
) {
69 return allocEmptyFunc(ctype
)();
73 * Create a collection from an array, with refcount set to 1.
75 * Pre: The array must have a kind that's compatible with the collection type
78 inline ObjectData
* alloc(CollectionType ctype
, ArrayData
* arr
) {
79 return allocFromArrayFunc(ctype
)(arr
);
83 * Creates a Pair. Takes ownership of the TypedValues passed in.
85 ObjectData
* allocPair(TypedValue c1
, TypedValue c2
);
87 /////////////////////////////////////////////////////////////////////////////
90 bool isType(const Class
* cls
, CollectionType type
);
91 template<typename
...Args
>
92 bool isType(const Class
* cls
, CollectionType type
, Args
... args
) {
93 return isType(cls
, type
) || isType(cls
, args
...);
96 Array
toArray(const ObjectData
* obj
);
97 bool toBool(const ObjectData
* obj
);
98 ObjectData
* clone(ObjectData
* obj
);
100 void deepCopy(TypedValue
* tv
);
103 * Return the inner-array for array-backed collections, and nullptr if it's a
104 * Pair. The returned array pointer is not incref'd.
106 ArrayData
* asArray(ObjectData
* obj
);
107 inline const ArrayData
* asArray(const ObjectData
* obj
) {
108 return asArray(const_cast<ObjectData
*>(obj
));
111 /////////////////////////////////////////////////////////////////////////////
114 /* at() and get() retrieve a collection element for reading.
115 * If the key does not exist in the collection, at() will throw an exception
116 * while get() will return nullptr
118 TypedValue
* at(ObjectData
* obj
, const TypedValue
* key
);
119 TypedValue
* get(ObjectData
* obj
, const TypedValue
* key
);
121 /* atLval() is used to get the address of an element when the
122 * caller is NOT going to do direct write per se, but it intends to use
123 * the element as the base of a member operation in an "lvalue" context
124 * (which could mutate the element in various ways).
126 TypedValue
* atLval(ObjectData
* obj
, const TypedValue
* key
);
128 /* atRw() is used to get the address of an element for reading
129 * and writing. It is typically used for read-modify-write operations (the
130 * SetOp* and IncDec* instructions).
132 TypedValue
* atRw(ObjectData
* obj
, const TypedValue
* key
);
134 /* Check for {key} within {obj} Collection
135 * `contains` merely need to exist
136 * `isset` needs to exist and not be null
137 * `empty` needs to exist and not be falsy
139 bool contains(ObjectData
* obj
, const Variant
& offset
);
140 bool (isset
)(ObjectData
* obj
, const TypedValue
* key
);
141 bool empty(ObjectData
* obj
, const TypedValue
* key
);
143 /* Remove element {key} from Collection {obj} */
144 void unset(ObjectData
* obj
, const TypedValue
* key
);
146 /* Add element {val} to Collection {obj} at {key} or the next slot */
147 void append(ObjectData
* obj
, TypedValue
* val
);
148 void set(ObjectData
* obj
, const TypedValue
* key
, const TypedValue
* val
);
150 /* Compare two collections.
151 * Only collections of the same type with the same elements are equal.
152 * Whether elements must be in the same order is CollectionType dependent.
154 bool equals(const ObjectData
* obj1
, const ObjectData
* obj2
);
156 /* Take element from end(pop) or beginning(shift) of a mutable collection */
157 Variant
pop(ObjectData
* obj
);
158 Variant
shift(ObjectData
* obj
);
160 /////////////////////////////////////////////////////////////////////////////
161 // CollectionType <-> Human-readable name conversions
164 * Returns a collection type name given a CollectionType.
166 inline StringData
* typeToString(CollectionType ctype
) {
168 #define X(type) case CollectionType::type: return s_##type.get();
169 COLLECTIONS_ALL_TYPES(X
)
176 * Returns a CollectionType given a name, folly::none if name is not a
179 inline folly::Optional
<CollectionType
> stringToType(const StringData
* name
) {
180 #define X(type) if (name->isame(s_##type.get())) return CollectionType::type;
181 COLLECTIONS_ALL_TYPES(X
)
186 inline folly::Optional
<CollectionType
> stringToType(const std::string
& s
) {
188 req::ptr
<StringData
>::attach(StringData::Make(s
)).get()
192 inline bool isTypeName(const StringData
* str
) {
193 return stringToType(str
).hasValue();
196 /////////////////////////////////////////////////////////////////////////////