~ubuntu-branches/ubuntu/wily/oolite/wily-proposed

« back to all changes in this revision

Viewing changes to deps/Windows-x86-deps/JS32ECMAv5/include/jsvector.h

  • Committer: Package Import Robot
  • Author(s): Nicolas Boulenguez
  • Date: 2011-12-22 00:22:39 UTC
  • mfrom: (1.2.2)
  • Revision ID: package-import@ubuntu.com-20111222002239-pr3upeupp4jw1psp
Tags: 1.76-1
* New upstream.
* watch: scan upstream stable releases instead of dev snapshots.
* control: use default gobjc instead of explicit 4.6.
* rules: use dpkg-dev build flags.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
 
2
 * vim: set ts=8 sw=4 et tw=99 ft=cpp:
 
3
 *
 
4
 * ***** BEGIN LICENSE BLOCK *****
 
5
 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
 
6
 *
 
7
 * The contents of this file are subject to the Mozilla Public License Version
 
8
 * 1.1 (the "License"); you may not use this file except in compliance with
 
9
 * the License. You may obtain a copy of the License at
 
10
 * http://www.mozilla.org/MPL/
 
11
 *
 
12
 * Software distributed under the License is distributed on an "AS IS" basis,
 
13
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 
14
 * for the specific language governing rights and limitations under the
 
15
 * License.
 
16
 *
 
17
 * The Original Code is Mozilla SpiderMonkey JavaScript 1.9 code, released
 
18
 * June 12, 2009.
 
19
 *
 
20
 * The Initial Developer of the Original Code is
 
21
 *   the Mozilla Corporation.
 
22
 *
 
23
 * Contributor(s):
 
24
 *   Luke Wagner <lw@mozilla.com>
 
25
 *   Nicholas Nethercote <nnethercote@mozilla.com>
 
26
 *
 
27
 * Alternatively, the contents of this file may be used under the terms of
 
28
 * either of the GNU General Public License Version 2 or later (the "GPL"),
 
29
 * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
 
30
 * in which case the provisions of the GPL or the LGPL are applicable instead
 
31
 * of those above. If you wish to allow use of your version of this file only
 
32
 * under the terms of either the GPL or the LGPL, and not to allow others to
 
33
 * use your version of this file under the terms of the MPL, indicate your
 
34
 * decision by deleting the provisions above and replace them with the notice
 
35
 * and other provisions required by the GPL or the LGPL. If you do not delete
 
36
 * the provisions above, a recipient may use your version of this file under
 
37
 * the terms of any one of the MPL, the GPL or the LGPL.
 
38
 *
 
39
 * ***** END LICENSE BLOCK ***** */
 
40
 
 
41
#ifndef jsvector_h_
 
42
#define jsvector_h_
 
43
 
 
44
#include "jstl.h"
 
45
#include "jsprvtd.h"
 
46
 
 
47
/* Silence dire "bugs in previous versions of MSVC have been fixed" warnings */
 
48
#ifdef _MSC_VER
 
49
#pragma warning(push)
 
50
#pragma warning(disable:4345)
 
51
#endif
 
52
 
 
53
/* Gross special case for Gecko, which defines malloc/calloc/free. */
 
54
#ifdef mozilla_mozalloc_macro_wrappers_h
 
55
#  define JSVECTOR_UNDEFD_MOZALLOC_WRAPPERS
 
56
#  include "mozilla/mozalloc_undef_macro_wrappers.h"
 
57
#endif
 
58
 
 
59
namespace js {
 
60
 
 
61
/*
 
62
 * This template class provides a default implementation for vector operations
 
63
 * when the element type is not known to be a POD, as judged by IsPodType.
 
64
 */
 
65
template <class T, size_t N, class AP, bool IsPod>
 
66
struct VectorImpl
 
67
{
 
68
    /* Destroys constructed objects in the range [begin, end). */
 
69
    static inline void destroy(T *begin, T *end) {
 
70
        for (T *p = begin; p != end; ++p)
 
71
            p->~T();
 
72
    }
 
73
 
 
74
    /* Constructs objects in the uninitialized range [begin, end). */
 
75
    static inline void initialize(T *begin, T *end) {
 
76
        for (T *p = begin; p != end; ++p)
 
77
            new(p) T();
 
78
    }
 
79
 
 
80
    /*
 
81
     * Copy-constructs objects in the uninitialized range
 
82
     * [dst, dst+(srcend-srcbeg)) from the range [srcbeg, srcend).
 
83
     */
 
84
    template <class U>
 
85
    static inline void copyConstruct(T *dst, const U *srcbeg, const U *srcend) {
 
86
        for (const U *p = srcbeg; p != srcend; ++p, ++dst)
 
87
            new(dst) T(*p);
 
88
    }
 
89
 
 
90
    /*
 
91
     * Copy-constructs objects in the uninitialized range [dst, dst+n) from the
 
92
     * same object u.
 
93
     */
 
94
    template <class U>
 
95
    static inline void copyConstructN(T *dst, size_t n, const U &u) {
 
96
        for (T *end = dst + n; dst != end; ++dst)
 
97
            new(dst) T(u);
 
98
    }
 
99
 
 
100
    /*
 
101
     * Grows the given buffer to have capacity newcap, preserving the objects
 
102
     * constructed in the range [begin, end) and updating v. Assumes that (1)
 
103
     * newcap has not overflowed, and (2) multiplying newcap by sizeof(T) will
 
104
     * not overflow.
 
105
     */
 
106
    static inline bool growTo(Vector<T,N,AP> &v, size_t newcap) {
 
107
        JS_ASSERT(!v.usingInlineStorage());
 
108
        T *newbuf = reinterpret_cast<T *>(v.malloc(newcap * sizeof(T)));
 
109
        if (!newbuf)
 
110
            return false;
 
111
        for (T *dst = newbuf, *src = v.beginNoCheck(); src != v.endNoCheck(); ++dst, ++src)
 
112
            new(dst) T(*src);
 
113
        VectorImpl::destroy(v.beginNoCheck(), v.endNoCheck());
 
114
        v.free(v.mBegin);
 
115
        v.mBegin = newbuf;
 
116
        /* v.mLength is unchanged. */
 
117
        v.mCapacity = newcap;
 
118
        return true;
 
119
    }
 
120
};
 
121
 
 
122
/*
 
123
 * This partial template specialization provides a default implementation for
 
124
 * vector operations when the element type is known to be a POD, as judged by
 
125
 * IsPodType.
 
126
 */
 
127
template <class T, size_t N, class AP>
 
128
struct VectorImpl<T, N, AP, true>
 
129
{
 
130
    static inline void destroy(T *, T *) {}
 
131
 
 
132
    static inline void initialize(T *begin, T *end) {
 
133
        /*
 
134
         * You would think that memset would be a big win (or even break even)
 
135
         * when we know T is a POD. But currently it's not. This is probably
 
136
         * because |append| tends to be given small ranges and memset requires
 
137
         * a function call that doesn't get inlined.
 
138
         *
 
139
         * memset(begin, 0, sizeof(T) * (end-begin));
 
140
         */
 
141
        for (T *p = begin; p != end; ++p)
 
142
            new(p) T();
 
143
    }
 
144
 
 
145
    template <class U>
 
146
    static inline void copyConstruct(T *dst, const U *srcbeg, const U *srcend) {
 
147
        /*
 
148
         * See above memset comment. Also, notice that copyConstruct is
 
149
         * currently templated (T != U), so memcpy won't work without
 
150
         * requiring T == U.
 
151
         *
 
152
         * memcpy(dst, srcbeg, sizeof(T) * (srcend - srcbeg));
 
153
         */
 
154
        for (const U *p = srcbeg; p != srcend; ++p, ++dst)
 
155
            *dst = *p;
 
156
    }
 
157
 
 
158
    static inline void copyConstructN(T *dst, size_t n, const T &t) {
 
159
        for (T *p = dst, *end = dst + n; p != end; ++p)
 
160
            *p = t;
 
161
    }
 
162
 
 
163
    static inline bool growTo(Vector<T,N,AP> &v, size_t newcap) {
 
164
        JS_ASSERT(!v.usingInlineStorage());
 
165
        size_t bytes = sizeof(T) * newcap;
 
166
        T *newbuf = reinterpret_cast<T *>(v.realloc(v.mBegin, bytes));
 
167
        if (!newbuf)
 
168
            return false;
 
169
        v.mBegin = newbuf;
 
170
        /* v.mLength is unchanged. */
 
171
        v.mCapacity = newcap;
 
172
        return true;
 
173
    }
 
174
};
 
175
 
 
176
/*
 
177
 * JS-friendly, STL-like container providing a short-lived, dynamic buffer.
 
178
 * Vector calls the constructors/destructors of all elements stored in
 
179
 * its internal buffer, so non-PODs may be safely used. Additionally,
 
180
 * Vector will store the first N elements in-place before resorting to
 
181
 * dynamic allocation.
 
182
 *
 
183
 * T requirements:
 
184
 *  - default and copy constructible, assignable, destructible
 
185
 *  - operations do not throw
 
186
 * N requirements:
 
187
 *  - any value, however, N is clamped to min/max values
 
188
 * AllocPolicy:
 
189
 *  - see "Allocation policies" in jstl.h (default ContextAllocPolicy)
 
190
 *
 
191
 * N.B: Vector is not reentrant: T member functions called during Vector member
 
192
 *      functions must not call back into the same object.
 
193
 */
 
194
template <class T, size_t N, class AllocPolicy>
 
195
class Vector : AllocPolicy
 
196
{
 
197
    /* utilities */
 
198
 
 
199
    static const bool sElemIsPod = tl::IsPodType<T>::result;
 
200
    typedef VectorImpl<T, N, AllocPolicy, sElemIsPod> Impl;
 
201
    friend struct VectorImpl<T, N, AllocPolicy, sElemIsPod>;
 
202
 
 
203
    bool calculateNewCapacity(size_t curLength, size_t lengthInc, size_t &newCap);
 
204
    bool growStorageBy(size_t lengthInc);
 
205
    bool growHeapStorageBy(size_t lengthInc);
 
206
    bool convertToHeapStorage(size_t lengthInc);
 
207
 
 
208
    template <bool InitNewElems> inline bool growByImpl(size_t inc);
 
209
 
 
210
    /* magic constants */
 
211
 
 
212
    static const int sMaxInlineBytes = 1024;
 
213
 
 
214
    /* compute constants */
 
215
 
 
216
    static const size_t sInlineCapacity =
 
217
        tl::Min<N, sMaxInlineBytes / sizeof(T)>::result;
 
218
 
 
219
    /* Calculate inline buffer size; avoid 0-sized array. */
 
220
    static const size_t sInlineBytes =
 
221
        tl::Max<1, sInlineCapacity * sizeof(T)>::result;
 
222
 
 
223
    /* member data */
 
224
 
 
225
    /*
 
226
     * Pointer to the buffer, be it inline or heap-allocated. Only [mBegin,
 
227
     * mBegin + mLength) hold valid constructed T objects. The range [mBegin +
 
228
     * mLength, mBegin + mCapacity) holds uninitialized memory.
 
229
     */
 
230
    T *mBegin;
 
231
    size_t mLength;     /* Number of elements in the Vector. */
 
232
    size_t mCapacity;   /* Max number of elements storable in the Vector without resizing. */
 
233
 
 
234
    AlignedStorage<sInlineBytes> storage;
 
235
 
 
236
#ifdef DEBUG
 
237
    friend class ReentrancyGuard;
 
238
    bool entered;
 
239
#endif
 
240
 
 
241
    Vector(const Vector &);
 
242
    Vector &operator=(const Vector &);
 
243
 
 
244
    /* private accessors */
 
245
 
 
246
    bool usingInlineStorage() const {
 
247
        return mBegin == (T *)storage.addr();
 
248
    }
 
249
 
 
250
    T *beginNoCheck() const {
 
251
        return mBegin;
 
252
    }
 
253
 
 
254
    T *endNoCheck() {
 
255
        return mBegin + mLength;
 
256
    }
 
257
 
 
258
    const T *endNoCheck() const {
 
259
        return mBegin + mLength;
 
260
    }
 
261
 
 
262
  public:
 
263
    typedef T ElementType;
 
264
 
 
265
    Vector(AllocPolicy = AllocPolicy());
 
266
    ~Vector();
 
267
 
 
268
    /* accessors */
 
269
 
 
270
    const AllocPolicy &allocPolicy() const {
 
271
        return *this;
 
272
    }
 
273
 
 
274
    enum { InlineLength = N };
 
275
 
 
276
    size_t length() const {
 
277
        return mLength;
 
278
    }
 
279
 
 
280
    bool empty() const {
 
281
        return mLength == 0;
 
282
    }
 
283
 
 
284
    size_t capacity() const {
 
285
        return mCapacity;
 
286
    }
 
287
 
 
288
    T *begin() const {
 
289
        JS_ASSERT(!entered);
 
290
        return mBegin;
 
291
    }
 
292
 
 
293
    T *end() {
 
294
        JS_ASSERT(!entered);
 
295
        return mBegin + mLength;
 
296
    }
 
297
 
 
298
    const T *end() const {
 
299
        JS_ASSERT(!entered);
 
300
        return mBegin + mLength;
 
301
    }
 
302
 
 
303
    T &operator[](size_t i) {
 
304
        JS_ASSERT(!entered && i < mLength);
 
305
        return begin()[i];
 
306
    }
 
307
 
 
308
    const T &operator[](size_t i) const {
 
309
        JS_ASSERT(!entered && i < mLength);
 
310
        return begin()[i];
 
311
    }
 
312
 
 
313
    T &back() {
 
314
        JS_ASSERT(!entered && !empty());
 
315
        return *(end() - 1);
 
316
    }
 
317
 
 
318
    const T &back() const {
 
319
        JS_ASSERT(!entered && !empty());
 
320
        return *(end() - 1);
 
321
    }
 
322
 
 
323
    /* mutators */
 
324
 
 
325
    /* If reserve(length() + N) succeeds, the N next appends are guaranteed to succeed. */
 
326
    bool reserve(size_t capacity);
 
327
 
 
328
    /* Destroy elements in the range [begin() + incr, end()). */
 
329
    void shrinkBy(size_t incr);
 
330
 
 
331
    /* Grow the vector by incr elements. */
 
332
    bool growBy(size_t incr);
 
333
 
 
334
    /* Call shrinkBy or growBy based on whether newSize > length(). */
 
335
    bool resize(size_t newLength);
 
336
 
 
337
    /* Leave new elements as uninitialized memory. */
 
338
    bool growByUninitialized(size_t incr);
 
339
    bool resizeUninitialized(size_t newLength);
 
340
 
 
341
    void clear();
 
342
 
 
343
    bool append(const T &t);
 
344
    bool appendN(const T &t, size_t n);
 
345
    template <class U> bool append(const U *begin, const U *end);
 
346
    template <class U> bool append(const U *begin, size_t length);
 
347
    template <class U, size_t O, class BP> bool append(const Vector<U,O,BP> &other);
 
348
 
 
349
    void popBack();
 
350
 
 
351
    T popCopy();
 
352
 
 
353
    /*
 
354
     * Transfers ownership of the internal buffer used by Vector to the caller.
 
355
     * After this call, the Vector is empty. Since the returned buffer may need
 
356
     * to be allocated (if the elements are currently stored in-place), the
 
357
     * call can fail, returning NULL.
 
358
     *
 
359
     * N.B. Although a T*, only the range [0, length()) is constructed.
 
360
     */
 
361
    T *extractRawBuffer();
 
362
 
 
363
    /*
 
364
     * Transfer ownership of an array of objects into the Vector.
 
365
     * N.B. This call assumes that there are no uninitialized elements in the
 
366
     *      passed array.
 
367
     */
 
368
    void replaceRawBuffer(T *p, size_t length);
 
369
 
 
370
    /*
 
371
     * Places |val| at position |p|, shifting existing elements
 
372
     * from |p| onward one position higher.
 
373
     */
 
374
    bool insert(T *p, const T &val);
 
375
 
 
376
    /*
 
377
     * Removes the element |t|, which must fall in the bounds [begin, end),
 
378
     * shifting existing elements from |t + 1| onward one position lower.
 
379
     */
 
380
    void erase(T *t);
 
381
};
 
382
 
 
383
/* This does the re-entrancy check plus several other sanity checks. */
 
384
#define REENTRANCY_GUARD_ET_AL \
 
385
    ReentrancyGuard g(*this); \
 
386
    JS_ASSERT_IF(usingInlineStorage(), mCapacity == sInlineCapacity); \
 
387
    JS_ASSERT(mLength <= mCapacity)
 
388
 
 
389
/* Vector Implementation */
 
390
 
 
391
template <class T, size_t N, class AllocPolicy>
 
392
JS_ALWAYS_INLINE
 
393
Vector<T,N,AllocPolicy>::Vector(AllocPolicy ap)
 
394
  : AllocPolicy(ap), mBegin((T *)storage.addr()), mLength(0),
 
395
    mCapacity(sInlineCapacity)
 
396
#ifdef DEBUG
 
397
  , entered(false)
 
398
#endif
 
399
{}
 
400
 
 
401
template <class T, size_t N, class AP>
 
402
JS_ALWAYS_INLINE
 
403
Vector<T,N,AP>::~Vector()
 
404
{
 
405
    REENTRANCY_GUARD_ET_AL;
 
406
    Impl::destroy(beginNoCheck(), endNoCheck());
 
407
    if (!usingInlineStorage())
 
408
        this->free(beginNoCheck());
 
409
}
 
410
 
 
411
/*
 
412
 * Calculate a new capacity that is at least lengthInc greater than
 
413
 * curLength and check for overflow.
 
414
 */
 
415
template <class T, size_t N, class AP>
 
416
STATIC_POSTCONDITION(!return || newCap >= curLength + lengthInc)
 
417
inline bool
 
418
Vector<T,N,AP>::calculateNewCapacity(size_t curLength, size_t lengthInc,
 
419
                                     size_t &newCap)
 
420
{
 
421
    size_t newMinCap = curLength + lengthInc;
 
422
 
 
423
    /*
 
424
     * Check for overflow in the above addition, below CEILING_LOG2, and later
 
425
     * multiplication by sizeof(T).
 
426
     */
 
427
    if (newMinCap < curLength ||
 
428
        newMinCap & tl::MulOverflowMask<2 * sizeof(T)>::result) {
 
429
        this->reportAllocOverflow();
 
430
        return false;
 
431
    }
 
432
 
 
433
    /* Round up to next power of 2. */
 
434
    newCap = RoundUpPow2(newMinCap);
 
435
 
 
436
    /*
 
437
     * Do not allow a buffer large enough that the expression ((char *)end() -
 
438
     * (char *)begin()) overflows ptrdiff_t. See Bug 510319.
 
439
     */
 
440
    if (newCap & tl::UnsafeRangeSizeMask<T>::result) {
 
441
        this->reportAllocOverflow();
 
442
        return false;
 
443
    }
 
444
    return true;
 
445
}
 
446
 
 
447
/*
 
448
 * This function will grow the current heap capacity to have capacity
 
449
 * (mLength + lengthInc) and fail on OOM or integer overflow.
 
450
 */
 
451
template <class T, size_t N, class AP>
 
452
JS_ALWAYS_INLINE bool
 
453
Vector<T,N,AP>::growHeapStorageBy(size_t lengthInc)
 
454
{
 
455
    JS_ASSERT(!usingInlineStorage());
 
456
    size_t newCap;
 
457
    return calculateNewCapacity(mLength, lengthInc, newCap) &&
 
458
           Impl::growTo(*this, newCap);
 
459
}
 
460
 
 
461
/*
 
462
 * This function will create a new heap buffer with capacity (mLength +
 
463
 * lengthInc()), move all elements in the inline buffer to this new buffer,
 
464
 * and fail on OOM or integer overflow.
 
465
 */
 
466
template <class T, size_t N, class AP>
 
467
inline bool
 
468
Vector<T,N,AP>::convertToHeapStorage(size_t lengthInc)
 
469
{
 
470
    JS_ASSERT(usingInlineStorage());
 
471
    size_t newCap;
 
472
    if (!calculateNewCapacity(mLength, lengthInc, newCap))
 
473
        return false;
 
474
 
 
475
    /* Allocate buffer. */
 
476
    T *newBuf = reinterpret_cast<T *>(this->malloc(newCap * sizeof(T)));
 
477
    if (!newBuf)
 
478
        return false;
 
479
 
 
480
    /* Copy inline elements into heap buffer. */
 
481
    Impl::copyConstruct(newBuf, beginNoCheck(), endNoCheck());
 
482
    Impl::destroy(beginNoCheck(), endNoCheck());
 
483
 
 
484
    /* Switch in heap buffer. */
 
485
    mBegin = newBuf;
 
486
    /* mLength is unchanged. */
 
487
    mCapacity = newCap;
 
488
    return true;
 
489
}
 
490
 
 
491
template <class T, size_t N, class AP>
 
492
JS_NEVER_INLINE bool
 
493
Vector<T,N,AP>::growStorageBy(size_t incr)
 
494
{
 
495
    JS_ASSERT(mLength + incr > mCapacity);
 
496
    return usingInlineStorage()
 
497
         ? convertToHeapStorage(incr)
 
498
         : growHeapStorageBy(incr);
 
499
}
 
500
 
 
501
template <class T, size_t N, class AP>
 
502
inline bool
 
503
Vector<T,N,AP>::reserve(size_t request)
 
504
{
 
505
    REENTRANCY_GUARD_ET_AL;
 
506
    if (request > mCapacity)
 
507
        return growStorageBy(request - mLength);
 
508
    return true;
 
509
}
 
510
 
 
511
template <class T, size_t N, class AP>
 
512
inline void
 
513
Vector<T,N,AP>::shrinkBy(size_t incr)
 
514
{
 
515
    REENTRANCY_GUARD_ET_AL;
 
516
    JS_ASSERT(incr <= mLength);
 
517
    Impl::destroy(endNoCheck() - incr, endNoCheck());
 
518
    mLength -= incr;
 
519
}
 
520
 
 
521
template <class T, size_t N, class AP>
 
522
template <bool InitNewElems>
 
523
JS_ALWAYS_INLINE bool
 
524
Vector<T,N,AP>::growByImpl(size_t incr)
 
525
{
 
526
    REENTRANCY_GUARD_ET_AL;
 
527
    if (incr > mCapacity - mLength && !growStorageBy(incr))
 
528
        return false;
 
529
 
 
530
    JS_ASSERT(mLength + incr <= mCapacity);
 
531
    T *newend = endNoCheck() + incr;
 
532
    if (InitNewElems)
 
533
        Impl::initialize(endNoCheck(), newend);
 
534
    mLength += incr;
 
535
    return true;
 
536
}
 
537
 
 
538
template <class T, size_t N, class AP>
 
539
JS_ALWAYS_INLINE bool
 
540
Vector<T,N,AP>::growBy(size_t incr)
 
541
{
 
542
    return growByImpl<true>(incr);
 
543
}
 
544
 
 
545
template <class T, size_t N, class AP>
 
546
JS_ALWAYS_INLINE bool
 
547
Vector<T,N,AP>::growByUninitialized(size_t incr)
 
548
{
 
549
    return growByImpl<false>(incr);
 
550
}
 
551
 
 
552
template <class T, size_t N, class AP>
 
553
STATIC_POSTCONDITION(!return || ubound(this->begin()) >= newLength)
 
554
inline bool
 
555
Vector<T,N,AP>::resize(size_t newLength)
 
556
{
 
557
    size_t curLength = mLength;
 
558
    if (newLength > curLength)
 
559
        return growBy(newLength - curLength);
 
560
    shrinkBy(curLength - newLength);
 
561
    return true;
 
562
}
 
563
 
 
564
template <class T, size_t N, class AP>
 
565
JS_ALWAYS_INLINE bool
 
566
Vector<T,N,AP>::resizeUninitialized(size_t newLength)
 
567
{
 
568
    size_t curLength = mLength;
 
569
    if (newLength > curLength)
 
570
        return growByUninitialized(newLength - curLength);
 
571
    shrinkBy(curLength - newLength);
 
572
    return true;
 
573
}
 
574
 
 
575
template <class T, size_t N, class AP>
 
576
inline void
 
577
Vector<T,N,AP>::clear()
 
578
{
 
579
    REENTRANCY_GUARD_ET_AL;
 
580
    Impl::destroy(beginNoCheck(), endNoCheck());
 
581
    mLength = 0;
 
582
}
 
583
 
 
584
template <class T, size_t N, class AP>
 
585
JS_ALWAYS_INLINE bool
 
586
Vector<T,N,AP>::append(const T &t)
 
587
{
 
588
    REENTRANCY_GUARD_ET_AL;
 
589
    if (mLength == mCapacity && !growStorageBy(1))
 
590
        return false;
 
591
 
 
592
    JS_ASSERT(mLength < mCapacity);
 
593
    new(endNoCheck()) T(t);
 
594
    ++mLength;
 
595
    return true;
 
596
}
 
597
 
 
598
template <class T, size_t N, class AP>
 
599
JS_ALWAYS_INLINE bool
 
600
Vector<T,N,AP>::appendN(const T &t, size_t needed)
 
601
{
 
602
    REENTRANCY_GUARD_ET_AL;
 
603
    if (mLength + needed > mCapacity && !growStorageBy(needed))
 
604
        return false;
 
605
 
 
606
    JS_ASSERT(mLength + needed <= mCapacity);
 
607
    Impl::copyConstructN(endNoCheck(), needed, t);
 
608
    mLength += needed;
 
609
    return true;
 
610
}
 
611
 
 
612
template <class T, size_t N, class AP>
 
613
inline bool
 
614
Vector<T,N,AP>::insert(T *p, const T &val)
 
615
{
 
616
    JS_ASSERT(begin() <= p && p <= end());
 
617
    size_t pos = p - begin();
 
618
    JS_ASSERT(pos <= mLength);
 
619
    size_t oldLength = mLength;
 
620
    if (pos == oldLength)
 
621
        return append(val);
 
622
    {
 
623
        T oldBack = back();
 
624
        if (!append(oldBack)) /* Dup the last element. */
 
625
            return false;
 
626
    }
 
627
    for (size_t i = oldLength; i > pos; --i)
 
628
        (*this)[i] = (*this)[i - 1];
 
629
    (*this)[pos] = val;
 
630
    return true;
 
631
}
 
632
 
 
633
template<typename T, size_t N, class AP>
 
634
inline void
 
635
Vector<T,N,AP>::erase(T *it)
 
636
{
 
637
    JS_ASSERT(begin() <= it && it < end());
 
638
    while (it + 1 != end()) {
 
639
        *it = *(it + 1);
 
640
        ++it;
 
641
    }
 
642
    popBack();
 
643
}
 
644
 
 
645
template <class T, size_t N, class AP>
 
646
template <class U>
 
647
JS_ALWAYS_INLINE bool
 
648
Vector<T,N,AP>::append(const U *insBegin, const U *insEnd)
 
649
{
 
650
    REENTRANCY_GUARD_ET_AL;
 
651
    size_t needed = PointerRangeSize(insBegin, insEnd);
 
652
    if (mLength + needed > mCapacity && !growStorageBy(needed))
 
653
        return false;
 
654
 
 
655
    JS_ASSERT(mLength + needed <= mCapacity);
 
656
    Impl::copyConstruct(endNoCheck(), insBegin, insEnd);
 
657
    mLength += needed;
 
658
    return true;
 
659
}
 
660
 
 
661
template <class T, size_t N, class AP>
 
662
template <class U, size_t O, class BP>
 
663
inline bool
 
664
Vector<T,N,AP>::append(const Vector<U,O,BP> &other)
 
665
{
 
666
    return append(other.begin(), other.end());
 
667
}
 
668
 
 
669
template <class T, size_t N, class AP>
 
670
template <class U>
 
671
JS_ALWAYS_INLINE bool
 
672
Vector<T,N,AP>::append(const U *insBegin, size_t length)
 
673
{
 
674
    return this->append(insBegin, insBegin + length);
 
675
}
 
676
 
 
677
template <class T, size_t N, class AP>
 
678
JS_ALWAYS_INLINE void
 
679
Vector<T,N,AP>::popBack()
 
680
{
 
681
    REENTRANCY_GUARD_ET_AL;
 
682
    JS_ASSERT(!empty());
 
683
    --mLength;
 
684
    endNoCheck()->~T();
 
685
}
 
686
 
 
687
template <class T, size_t N, class AP>
 
688
JS_ALWAYS_INLINE T
 
689
Vector<T,N,AP>::popCopy()
 
690
{
 
691
    T ret = back();
 
692
    popBack();
 
693
    return ret;
 
694
}
 
695
 
 
696
template <class T, size_t N, class AP>
 
697
inline T *
 
698
Vector<T,N,AP>::extractRawBuffer()
 
699
{
 
700
    T *ret;
 
701
    if (usingInlineStorage()) {
 
702
        ret = reinterpret_cast<T *>(this->malloc(mLength * sizeof(T)));
 
703
        if (!ret)
 
704
            return NULL;
 
705
        Impl::copyConstruct(ret, beginNoCheck(), endNoCheck());
 
706
        Impl::destroy(beginNoCheck(), endNoCheck());
 
707
        /* mBegin, mCapacity are unchanged. */
 
708
        mLength = 0;
 
709
    } else {
 
710
        ret = mBegin;
 
711
        mBegin = (T *)storage.addr();
 
712
        mLength = 0;
 
713
        mCapacity = sInlineCapacity;
 
714
    }
 
715
    return ret;
 
716
}
 
717
 
 
718
template <class T, size_t N, class AP>
 
719
inline void
 
720
Vector<T,N,AP>::replaceRawBuffer(T *p, size_t length)
 
721
{
 
722
    REENTRANCY_GUARD_ET_AL;
 
723
 
 
724
    /* Destroy what we have. */
 
725
    Impl::destroy(beginNoCheck(), endNoCheck());
 
726
    if (!usingInlineStorage())
 
727
        this->free(beginNoCheck());
 
728
 
 
729
    /* Take in the new buffer. */
 
730
    if (length <= sInlineCapacity) {
 
731
        /*
 
732
         * We convert to inline storage if possible, even though p might
 
733
         * otherwise be acceptable.  Maybe this behaviour should be
 
734
         * specifiable with an argument to this function.
 
735
         */
 
736
        mBegin = (T *)storage.addr();
 
737
        mLength = length;
 
738
        mCapacity = sInlineCapacity;
 
739
        Impl::copyConstruct(mBegin, p, p + length);
 
740
        Impl::destroy(p, p + length);
 
741
        this->free(p);
 
742
    } else {
 
743
        mBegin = p;
 
744
        mLength = length;
 
745
        mCapacity = length;
 
746
    }
 
747
}
 
748
 
 
749
}  /* namespace js */
 
750
 
 
751
#ifdef _MSC_VER
 
752
#pragma warning(pop)
 
753
#endif
 
754
 
 
755
#ifdef JSVECTOR_UNDEFD_MOZALLOC_WRAPPERS
 
756
#  include "mozilla/mozalloc_macro_wrappers.h"
 
757
#endif
 
758
 
 
759
#endif /* jsvector_h_ */