]>
git.saurik.com Git - apple/javascriptcore.git/blob - wtf/SegmentedVector.h
2 * Copyright (C) 2008 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
14 * its contributors may be used to endorse or promote products derived
15 * from this software without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
18 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
21 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 #ifndef SegmentedVector_h
30 #define SegmentedVector_h
32 #include <wtf/Vector.h>
36 // An iterator for SegmentedVector. It supports only the pre ++ operator
37 template <typename T
, size_t SegmentSize
> class SegmentedVector
;
38 template <typename T
, size_t SegmentSize
> class SegmentedVectorIterator
{
40 friend class SegmentedVector
<T
, SegmentSize
>;
42 typedef SegmentedVectorIterator
<T
, SegmentSize
> Iterator
;
44 ~SegmentedVectorIterator() { }
46 T
& operator*() const { return m_vector
.m_segments
.at(m_segment
)->at(m_index
); }
47 T
* operator->() const { return &m_vector
.m_segments
.at(m_segment
)->at(m_index
); }
49 // Only prefix ++ operator supported
50 Iterator
& operator++()
52 ASSERT(m_index
!= SegmentSize
);
54 if (m_index
>= m_vector
.m_segments
.at(m_segment
)->size()) {
55 if (m_segment
+ 1 < m_vector
.m_segments
.size()) {
56 ASSERT(m_vector
.m_segments
.at(m_segment
)->size() > 0);
60 // Points to the "end" symbol
62 m_index
= SegmentSize
;
68 bool operator==(const Iterator
& other
) const
70 return (m_index
== other
.m_index
&& m_segment
= other
.m_segment
&& &m_vector
== &other
.m_vector
);
73 bool operator!=(const Iterator
& other
) const
75 return (m_index
!= other
.m_index
|| m_segment
!= other
.m_segment
|| &m_vector
!= &other
.m_vector
);
78 SegmentedVectorIterator
& operator=(const SegmentedVectorIterator
<T
, SegmentSize
>& other
)
80 m_vector
= other
.m_vector
;
81 m_segment
= other
.m_segment
;
82 m_index
= other
.m_index
;
87 SegmentedVectorIterator(SegmentedVector
<T
, SegmentSize
>& vector
, size_t segment
, size_t index
)
94 SegmentedVector
<T
, SegmentSize
>& m_vector
;
99 // SegmentedVector is just like Vector, but it doesn't move the values
100 // stored in its buffer when it grows. Therefore, it is safe to keep
101 // pointers into a SegmentedVector.
102 template <typename T
, size_t SegmentSize
> class SegmentedVector
{
103 friend class SegmentedVectorIterator
<T
, SegmentSize
>;
105 typedef SegmentedVectorIterator
<T
, SegmentSize
> Iterator
;
110 m_segments
.append(&m_inlineSegment
);
118 size_t size() const { return m_size
; }
119 bool isEmpty() const { return !size(); }
123 if (index
< SegmentSize
)
124 return m_inlineSegment
[index
];
125 return segmentFor(index
)->at(subscriptFor(index
));
128 T
& operator[](size_t index
)
135 return at(size() - 1);
138 template <typename U
> void append(const U
& value
)
142 if (m_size
<= SegmentSize
) {
143 m_inlineSegment
.uncheckedAppend(value
);
147 if (!segmentExistsFor(m_size
- 1))
148 m_segments
.append(new Segment
);
149 segmentFor(m_size
- 1)->uncheckedAppend(value
);
160 if (m_size
<= SegmentSize
)
161 m_inlineSegment
.removeLast();
163 segmentFor(m_size
- 1)->removeLast();
167 void grow(size_t size
)
169 ASSERT(size
> m_size
);
170 ensureSegmentsFor(size
);
177 m_segments
.resize(1);
178 m_inlineSegment
.clear();
184 return Iterator(*this, 0, m_size
? 0 : SegmentSize
);
189 return Iterator(*this, 0, SegmentSize
);
193 typedef Vector
<T
, SegmentSize
> Segment
;
195 void deleteAllSegments()
197 // Skip the first segment, because it's our inline segment, which was
198 // not created by new.
199 for (size_t i
= 1; i
< m_segments
.size(); i
++)
200 delete m_segments
[i
];
203 bool segmentExistsFor(size_t index
)
205 return index
/ SegmentSize
< m_segments
.size();
208 Segment
* segmentFor(size_t index
)
210 return m_segments
[index
/ SegmentSize
];
213 size_t subscriptFor(size_t index
)
215 return index
% SegmentSize
;
218 void ensureSegmentsFor(size_t size
)
220 size_t segmentCount
= m_size
/ SegmentSize
;
221 if (m_size
% SegmentSize
)
223 segmentCount
= std::max
<size_t>(segmentCount
, 1); // We always have at least our inline segment.
225 size_t neededSegmentCount
= size
/ SegmentSize
;
226 if (size
% SegmentSize
)
227 ++neededSegmentCount
;
229 // Fill up to N - 1 segments.
230 size_t end
= neededSegmentCount
- 1;
231 for (size_t i
= segmentCount
- 1; i
< end
; ++i
)
232 ensureSegment(i
, SegmentSize
);
234 // Grow segment N to accomodate the remainder.
235 ensureSegment(end
, subscriptFor(size
- 1) + 1);
238 void ensureSegment(size_t segmentIndex
, size_t size
)
240 ASSERT(segmentIndex
<= m_segments
.size());
241 if (segmentIndex
== m_segments
.size())
242 m_segments
.append(new Segment
);
243 m_segments
[segmentIndex
]->grow(size
);
247 Segment m_inlineSegment
;
248 Vector
<Segment
*, 32> m_segments
;
253 using WTF::SegmentedVector
;
255 #endif // SegmentedVector_h