Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
michael@0 | 1 | /* |
michael@0 | 2 | * Copyright (C) 2008 Apple Inc. All rights reserved. |
michael@0 | 3 | * |
michael@0 | 4 | * Redistribution and use in source and binary forms, with or without |
michael@0 | 5 | * modification, are permitted provided that the following conditions |
michael@0 | 6 | * are met: |
michael@0 | 7 | * |
michael@0 | 8 | * 1. Redistributions of source code must retain the above copyright |
michael@0 | 9 | * notice, this list of conditions and the following disclaimer. |
michael@0 | 10 | * 2. Redistributions in binary form must reproduce the above copyright |
michael@0 | 11 | * notice, this list of conditions and the following disclaimer in the |
michael@0 | 12 | * documentation and/or other materials provided with the distribution. |
michael@0 | 13 | * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of |
michael@0 | 14 | * its contributors may be used to endorse or promote products derived |
michael@0 | 15 | * from this software without specific prior written permission. |
michael@0 | 16 | * |
michael@0 | 17 | * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY |
michael@0 | 18 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
michael@0 | 19 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
michael@0 | 20 | * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY |
michael@0 | 21 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
michael@0 | 22 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
michael@0 | 23 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
michael@0 | 24 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
michael@0 | 25 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
michael@0 | 26 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
michael@0 | 27 | */ |
michael@0 | 28 | |
michael@0 | 29 | #ifndef assembler_wtf_SegmentedVector_h |
michael@0 | 30 | #define assembler_wtf_SegmentedVector_h |
michael@0 | 31 | |
michael@0 | 32 | #include "js/Utility.h" |
michael@0 | 33 | #include "js/Vector.h" |
michael@0 | 34 | |
michael@0 | 35 | namespace WTF { |
michael@0 | 36 | |
michael@0 | 37 | // An iterator for SegmentedVector. It supports only the pre ++ operator |
michael@0 | 38 | template <typename T, size_t SegmentSize> class SegmentedVector; |
michael@0 | 39 | template <typename T, size_t SegmentSize> class SegmentedVectorIterator { |
michael@0 | 40 | private: |
michael@0 | 41 | friend class SegmentedVector<T, SegmentSize>; |
michael@0 | 42 | public: |
michael@0 | 43 | typedef SegmentedVectorIterator<T, SegmentSize> Iterator; |
michael@0 | 44 | |
michael@0 | 45 | ~SegmentedVectorIterator() { } |
michael@0 | 46 | |
michael@0 | 47 | T& operator*() const { return (*m_vector.m_segments[m_segment])[m_index]; } |
michael@0 | 48 | T* operator->() const { return &(*m_vector.m_segments[m_segment])[m_index]; } |
michael@0 | 49 | |
michael@0 | 50 | // Only prefix ++ operator supported |
michael@0 | 51 | Iterator& operator++() |
michael@0 | 52 | { |
michael@0 | 53 | ASSERT(m_index != SegmentSize); |
michael@0 | 54 | ++m_index; |
michael@0 | 55 | //if (m_index >= m_vector.m_segments.at(m_segment)->size()) { |
michael@0 | 56 | if (m_index >= m_vector.m_segments[m_segment]->length()) { |
michael@0 | 57 | //if (m_segment + 1 < m_vector.m_segments.size()) { |
michael@0 | 58 | if (m_segment + 1 < m_vector.m_segments.length()) { |
michael@0 | 59 | //ASSERT(m_vector.m_segments.at(m_segment)->size() > 0); |
michael@0 | 60 | ASSERT(m_vector.m_segments[m_segment]->length() > 0); |
michael@0 | 61 | ++m_segment; |
michael@0 | 62 | m_index = 0; |
michael@0 | 63 | } else { |
michael@0 | 64 | // Points to the "end" symbol |
michael@0 | 65 | m_segment = 0; |
michael@0 | 66 | m_index = SegmentSize; |
michael@0 | 67 | } |
michael@0 | 68 | } |
michael@0 | 69 | return *this; |
michael@0 | 70 | } |
michael@0 | 71 | |
michael@0 | 72 | bool operator==(const Iterator& other) const |
michael@0 | 73 | { |
michael@0 | 74 | return (m_index == other.m_index && m_segment = other.m_segment && &m_vector == &other.m_vector); |
michael@0 | 75 | } |
michael@0 | 76 | |
michael@0 | 77 | bool operator!=(const Iterator& other) const |
michael@0 | 78 | { |
michael@0 | 79 | return (m_index != other.m_index || m_segment != other.m_segment || &m_vector != &other.m_vector); |
michael@0 | 80 | } |
michael@0 | 81 | |
michael@0 | 82 | SegmentedVectorIterator& operator=(const SegmentedVectorIterator<T, SegmentSize>& other) |
michael@0 | 83 | { |
michael@0 | 84 | m_vector = other.m_vector; |
michael@0 | 85 | m_segment = other.m_segment; |
michael@0 | 86 | m_index = other.m_index; |
michael@0 | 87 | return *this; |
michael@0 | 88 | } |
michael@0 | 89 | |
michael@0 | 90 | private: |
michael@0 | 91 | SegmentedVectorIterator(SegmentedVector<T, SegmentSize>& vector, size_t segment, size_t index) |
michael@0 | 92 | : m_vector(vector) |
michael@0 | 93 | , m_segment(segment) |
michael@0 | 94 | , m_index(index) |
michael@0 | 95 | { |
michael@0 | 96 | } |
michael@0 | 97 | |
michael@0 | 98 | SegmentedVector<T, SegmentSize>& m_vector; |
michael@0 | 99 | size_t m_segment; |
michael@0 | 100 | size_t m_index; |
michael@0 | 101 | }; |
michael@0 | 102 | |
michael@0 | 103 | // SegmentedVector is just like Vector, but it doesn't move the values |
michael@0 | 104 | // stored in its buffer when it grows. Therefore, it is safe to keep |
michael@0 | 105 | // pointers into a SegmentedVector. |
michael@0 | 106 | template <typename T, size_t SegmentSize> class SegmentedVector { |
michael@0 | 107 | friend class SegmentedVectorIterator<T, SegmentSize>; |
michael@0 | 108 | public: |
michael@0 | 109 | typedef SegmentedVectorIterator<T, SegmentSize> Iterator; |
michael@0 | 110 | |
michael@0 | 111 | SegmentedVector() |
michael@0 | 112 | : m_size(0) |
michael@0 | 113 | { |
michael@0 | 114 | m_segments.append(&m_inlineSegment); |
michael@0 | 115 | } |
michael@0 | 116 | |
michael@0 | 117 | ~SegmentedVector() |
michael@0 | 118 | { |
michael@0 | 119 | deleteAllSegments(); |
michael@0 | 120 | } |
michael@0 | 121 | |
michael@0 | 122 | size_t size() const { return m_size; } |
michael@0 | 123 | bool isEmpty() const { return !size(); } |
michael@0 | 124 | |
michael@0 | 125 | T& at(size_t index) |
michael@0 | 126 | { |
michael@0 | 127 | if (index < SegmentSize) |
michael@0 | 128 | return m_inlineSegment[index]; |
michael@0 | 129 | return segmentFor(index)->at(subscriptFor(index)); |
michael@0 | 130 | } |
michael@0 | 131 | |
michael@0 | 132 | T& operator[](size_t index) |
michael@0 | 133 | { |
michael@0 | 134 | return at(index); |
michael@0 | 135 | } |
michael@0 | 136 | |
michael@0 | 137 | T& last() |
michael@0 | 138 | { |
michael@0 | 139 | return at(size() - 1); |
michael@0 | 140 | } |
michael@0 | 141 | |
michael@0 | 142 | template <typename U> void append(const U& value) |
michael@0 | 143 | { |
michael@0 | 144 | ++m_size; |
michael@0 | 145 | |
michael@0 | 146 | if (m_size <= SegmentSize) { |
michael@0 | 147 | //m_inlineSegment.uncheckedAppend(value); |
michael@0 | 148 | m_inlineSegment.append(value); |
michael@0 | 149 | return; |
michael@0 | 150 | } |
michael@0 | 151 | |
michael@0 | 152 | if (!segmentExistsFor(m_size - 1)) |
michael@0 | 153 | m_segments.append(js_new<Segment>()); |
michael@0 | 154 | //segmentFor(m_size - 1)->uncheckedAppend(value); |
michael@0 | 155 | segmentFor(m_size - 1)->append(value); |
michael@0 | 156 | } |
michael@0 | 157 | |
michael@0 | 158 | T& alloc() |
michael@0 | 159 | { |
michael@0 | 160 | append<T>(T()); |
michael@0 | 161 | return last(); |
michael@0 | 162 | } |
michael@0 | 163 | |
michael@0 | 164 | void removeLast() |
michael@0 | 165 | { |
michael@0 | 166 | if (m_size <= SegmentSize) |
michael@0 | 167 | m_inlineSegment.removeLast(); |
michael@0 | 168 | else |
michael@0 | 169 | segmentFor(m_size - 1)->removeLast(); |
michael@0 | 170 | --m_size; |
michael@0 | 171 | } |
michael@0 | 172 | |
michael@0 | 173 | void grow(size_t size) |
michael@0 | 174 | { |
michael@0 | 175 | ASSERT(size > m_size); |
michael@0 | 176 | ensureSegmentsFor(size); |
michael@0 | 177 | m_size = size; |
michael@0 | 178 | } |
michael@0 | 179 | |
michael@0 | 180 | void clear() |
michael@0 | 181 | { |
michael@0 | 182 | deleteAllSegments(); |
michael@0 | 183 | m_segments.resize(1); |
michael@0 | 184 | m_inlineSegment.clear(); |
michael@0 | 185 | m_size = 0; |
michael@0 | 186 | } |
michael@0 | 187 | |
michael@0 | 188 | Iterator begin() |
michael@0 | 189 | { |
michael@0 | 190 | return Iterator(*this, 0, m_size ? 0 : SegmentSize); |
michael@0 | 191 | } |
michael@0 | 192 | |
michael@0 | 193 | Iterator end() |
michael@0 | 194 | { |
michael@0 | 195 | return Iterator(*this, 0, SegmentSize); |
michael@0 | 196 | } |
michael@0 | 197 | |
michael@0 | 198 | private: |
michael@0 | 199 | typedef js::Vector<T, SegmentSize ,js::SystemAllocPolicy > Segment; |
michael@0 | 200 | |
michael@0 | 201 | void deleteAllSegments() |
michael@0 | 202 | { |
michael@0 | 203 | // Skip the first segment, because it's our inline segment, which was |
michael@0 | 204 | // not created by new. |
michael@0 | 205 | //for (size_t i = 1; i < m_segments.size(); i++) |
michael@0 | 206 | for (size_t i = 1; i < m_segments.length(); i++) |
michael@0 | 207 | js_delete<Segment>(m_segments[i]); |
michael@0 | 208 | } |
michael@0 | 209 | |
michael@0 | 210 | bool segmentExistsFor(size_t index) |
michael@0 | 211 | { |
michael@0 | 212 | //return index / SegmentSize < m_segments.size(); |
michael@0 | 213 | return index / SegmentSize < m_segments.length(); |
michael@0 | 214 | } |
michael@0 | 215 | |
michael@0 | 216 | Segment* segmentFor(size_t index) |
michael@0 | 217 | { |
michael@0 | 218 | return m_segments[index / SegmentSize]; |
michael@0 | 219 | } |
michael@0 | 220 | |
michael@0 | 221 | size_t subscriptFor(size_t index) |
michael@0 | 222 | { |
michael@0 | 223 | return index % SegmentSize; |
michael@0 | 224 | } |
michael@0 | 225 | |
michael@0 | 226 | void ensureSegmentsFor(size_t size) |
michael@0 | 227 | { |
michael@0 | 228 | size_t segmentCount = m_size / SegmentSize; |
michael@0 | 229 | if (m_size % SegmentSize) |
michael@0 | 230 | ++segmentCount; |
michael@0 | 231 | //segmentCount = std::max<size_t>(segmentCount, 1); // We always have at least our inline segment. |
michael@0 | 232 | segmentCount = segmentCount > 1 ? segmentCount : 1; // We always have at least our inline segment. |
michael@0 | 233 | |
michael@0 | 234 | size_t neededSegmentCount = size / SegmentSize; |
michael@0 | 235 | if (size % SegmentSize) |
michael@0 | 236 | ++neededSegmentCount; |
michael@0 | 237 | |
michael@0 | 238 | // Fill up to N - 1 segments. |
michael@0 | 239 | size_t end = neededSegmentCount - 1; |
michael@0 | 240 | for (size_t i = segmentCount - 1; i < end; ++i) |
michael@0 | 241 | ensureSegment(i, SegmentSize); |
michael@0 | 242 | |
michael@0 | 243 | // Grow segment N to accomodate the remainder. |
michael@0 | 244 | ensureSegment(end, subscriptFor(size - 1) + 1); |
michael@0 | 245 | } |
michael@0 | 246 | |
michael@0 | 247 | void ensureSegment(size_t segmentIndex, size_t size) |
michael@0 | 248 | { |
michael@0 | 249 | ASSERT(segmentIndex <= m_segments.size()); |
michael@0 | 250 | if (segmentIndex == m_segments.size()) |
michael@0 | 251 | m_segments.append(js_new<Segment>()); |
michael@0 | 252 | m_segments[segmentIndex]->grow(size); |
michael@0 | 253 | } |
michael@0 | 254 | |
michael@0 | 255 | size_t m_size; |
michael@0 | 256 | Segment m_inlineSegment; |
michael@0 | 257 | js::Vector<Segment*, 32 ,js::SystemAllocPolicy > m_segments; |
michael@0 | 258 | }; |
michael@0 | 259 | |
michael@0 | 260 | } // namespace WTF |
michael@0 | 261 | |
michael@0 | 262 | using WTF::SegmentedVector; |
michael@0 | 263 | |
michael@0 | 264 | #endif /* assembler_wtf_SegmentedVector_h */ |