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 +----------------------------------------------------------------------+
22 #include "hphp/util/assertions.h"
25 ////////////////////////////////////////////////////////////////////////////////
28 * A vector of elements that will increase its capacity when it fills up. It
29 * differs from std::vector in that it only takes up 8 bytes of space, its
30 * elements must be trivially destructible, and it cannot erase individual
34 struct GrowableVector
{
35 explicit GrowableVector() {}
37 GrowableVector(GrowableVector
&& other
) noexcept
: m_vec(other
.m_vec
) {
38 other
.m_vec
= nullptr;
41 GrowableVector
& operator=(GrowableVector
&& other
) {
43 other
.m_vec
= nullptr;
47 GrowableVector(const GrowableVector
&) = delete;
48 GrowableVector
& operator=(const GrowableVector
&) = delete;
50 //////////////////////////////////////////////////////////////////////////////
57 return m_vec
? m_vec
->m_size
: 0;
65 T
& operator[](const size_t idx
) {
66 assertx(idx
< size());
67 return m_vec
->m_data
[idx
];
70 const T
& operator[](const size_t idx
) const {
71 assertx(idx
< size());
72 return m_vec
->m_data
[idx
];
75 void push_back(const T
& datum
) {
79 m_vec
= m_vec
->push_back(datum
);
82 void swap(GrowableVector
<T
>& other
) {
83 std::swap(m_vec
, other
.m_vec
);
87 return m_vec
? m_vec
->m_data
: (T
*)this;
91 return m_vec
? &m_vec
->m_data
[m_vec
->m_size
] : (T
*)this;
94 void setEnd(T
* newEnd
) {
95 if (newEnd
== begin()) {
100 m_vec
->m_size
= newEnd
- m_vec
->m_data
;
105 static Impl
* make() {
107 std::is_trivially_destructible
<T
>::value
,
108 "GrowableVector can only hold trivially destructible types"
110 auto const mem
= malloc(sizeof(Impl
));
111 return new (mem
) Impl();
114 Impl
* push_back(const T
& datum
) {
115 // m_data always has room for at least one element due to the m_data[1]
116 // declaration, so the realloc() code first has to kick in when a second
117 // element is about to be pushed.
119 if (!folly::isPowTwo(m_size
)) return this;
120 return (Impl
*)realloc(
122 offsetof(Impl
, m_data
) + 2 * m_size
* sizeof(T
)
126 gv
->m_data
[gv
->m_size
++] = datum
;
130 ////////////////////////////////////////////////////////////////////////////
133 /* Actually variable length. */
137 //////////////////////////////////////////////////////////////////////////////
139 Impl
* m_vec
{nullptr};
142 ////////////////////////////////////////////////////////////////////////////////