~louis/ubuntu/trusty/clamav/lp799623_fix_logrotate

« back to all changes in this revision

Viewing changes to libclamav/c++/llvm/include/llvm/ADT/SmallVector.h

  • Committer: Bazaar Package Importer
  • Author(s): Scott Kitterman
  • Date: 2010-03-12 11:30:04 UTC
  • mfrom: (0.41.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20100312113004-b0fop4bkycszdd0z
Tags: 0.96~rc1+dfsg-0ubuntu1
* New upstream RC - FFE (LP: #537636):
  - Add OfficialDatabaseOnly option to clamav-base.postinst.in
  - Add LocalSocketGroup option to clamav-base.postinst.in
  - Add LocalSocketMode option to clamav-base.postinst.in
  - Add CrossFilesystems option to clamav-base.postinst.in
  - Add ClamukoScannerCount option to clamav-base.postinst.in
  - Add BytecodeSecurity opiton to clamav-base.postinst.in
  - Add DetectionStatsHostID option to clamav-freshclam.postinst.in
  - Add Bytecode option to clamav-freshclam.postinst.in
  - Add MilterSocketGroup option to clamav-milter.postinst.in
  - Add MilterSocketMode option to clamav-milter.postinst.in
  - Add ReportHostname option to clamav-milter.postinst.in
  - Bump libclamav SO version to 6.1.0 in libclamav6.install
  - Drop clamdmon from clamav.examples (no longer shipped by upstream)
  - Drop libclamav.a from libclamav-dev.install (not built by upstream)
  - Update SO version for lintian override for libclamav6
  - Add new Bytecode Testing Tool, usr/bin/clambc, to clamav.install
  - Add build-depends on python and python-setuptools for new test suite
  - Update debian/copyright for the embedded copy of llvm (using the system
    llvm is not currently feasible)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
//===- llvm/ADT/SmallVector.h - 'Normally small' vectors --------*- C++ -*-===//
 
2
//
 
3
//                     The LLVM Compiler Infrastructure
 
4
//
 
5
// This file is distributed under the University of Illinois Open Source
 
6
// License. See LICENSE.TXT for details.
 
7
//
 
8
//===----------------------------------------------------------------------===//
 
9
//
 
10
// This file defines the SmallVector class.
 
11
//
 
12
//===----------------------------------------------------------------------===//
 
13
 
 
14
#ifndef LLVM_ADT_SMALLVECTOR_H
 
15
#define LLVM_ADT_SMALLVECTOR_H
 
16
 
 
17
#include "llvm/Support/type_traits.h"
 
18
#include <algorithm>
 
19
#include <cassert>
 
20
#include <cstring>
 
21
#include <memory>
 
22
 
 
23
#ifdef _MSC_VER
 
24
namespace std {
 
25
#if _MSC_VER <= 1310
 
26
  // Work around flawed VC++ implementation of std::uninitialized_copy.  Define
 
27
  // additional overloads so that elements with pointer types are recognized as
 
28
  // scalars and not objects, causing bizarre type conversion errors.
 
29
  template<class T1, class T2>
 
30
  inline _Scalar_ptr_iterator_tag _Ptr_cat(T1 **, T2 **) {
 
31
    _Scalar_ptr_iterator_tag _Cat;
 
32
    return _Cat;
 
33
  }
 
34
 
 
35
  template<class T1, class T2>
 
36
  inline _Scalar_ptr_iterator_tag _Ptr_cat(T1* const *, T2 **) {
 
37
    _Scalar_ptr_iterator_tag _Cat;
 
38
    return _Cat;
 
39
  }
 
40
#else
 
41
// FIXME: It is not clear if the problem is fixed in VS 2005.  What is clear
 
42
// is that the above hack won't work if it wasn't fixed.
 
43
#endif
 
44
}
 
45
#endif
 
46
 
 
47
namespace llvm {
 
48
 
 
49
/// SmallVectorBase - This is all the non-templated stuff common to all
 
50
/// SmallVectors.
 
51
class SmallVectorBase {
 
52
protected:
 
53
  void *BeginX, *EndX, *CapacityX;
 
54
 
 
55
  // Allocate raw space for N elements of type T.  If T has a ctor or dtor, we
 
56
  // don't want it to be automatically run, so we need to represent the space as
 
57
  // something else.  An array of char would work great, but might not be
 
58
  // aligned sufficiently.  Instead, we either use GCC extensions, or some
 
59
  // number of union instances for the space, which guarantee maximal alignment.
 
60
#ifdef __GNUC__
 
61
  typedef char U;
 
62
  U FirstEl __attribute__((aligned));
 
63
#else
 
64
  union U {
 
65
    double D;
 
66
    long double LD;
 
67
    long long L;
 
68
    void *P;
 
69
  } FirstEl;
 
70
#endif
 
71
  // Space after 'FirstEl' is clobbered, do not add any instance vars after it.
 
72
  
 
73
protected:
 
74
  SmallVectorBase(size_t Size)
 
75
    : BeginX(&FirstEl), EndX(&FirstEl), CapacityX((char*)&FirstEl+Size) {}
 
76
  
 
77
  /// isSmall - Return true if this is a smallvector which has not had dynamic
 
78
  /// memory allocated for it.
 
79
  bool isSmall() const {
 
80
    return BeginX == static_cast<const void*>(&FirstEl);
 
81
  }
 
82
  
 
83
  /// size_in_bytes - This returns size()*sizeof(T).
 
84
  size_t size_in_bytes() const {
 
85
    return size_t((char*)EndX - (char*)BeginX);
 
86
  }
 
87
  
 
88
  /// capacity_in_bytes - This returns capacity()*sizeof(T).
 
89
  size_t capacity_in_bytes() const {
 
90
    return size_t((char*)CapacityX - (char*)BeginX);
 
91
  }
 
92
  
 
93
  /// grow_pod - This is an implementation of the grow() method which only works
 
94
  /// on POD-like datatypes and is out of line to reduce code duplication.
 
95
  void grow_pod(size_t MinSizeInBytes, size_t TSize);
 
96
  
 
97
public:
 
98
  bool empty() const { return BeginX == EndX; }
 
99
};
 
100
  
 
101
 
 
102
template <typename T>
 
103
class SmallVectorTemplateCommon : public SmallVectorBase {
 
104
protected:
 
105
  void setEnd(T *P) { this->EndX = P; }
 
106
public:
 
107
  SmallVectorTemplateCommon(size_t Size) : SmallVectorBase(Size) {}
 
108
  
 
109
  typedef size_t size_type;
 
110
  typedef ptrdiff_t difference_type;
 
111
  typedef T value_type;
 
112
  typedef T *iterator;
 
113
  typedef const T *const_iterator;
 
114
  
 
115
  typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
 
116
  typedef std::reverse_iterator<iterator> reverse_iterator;
 
117
  
 
118
  typedef T &reference;
 
119
  typedef const T &const_reference;
 
120
  typedef T *pointer;
 
121
  typedef const T *const_pointer;
 
122
  
 
123
  // forward iterator creation methods.
 
124
  iterator begin() { return (iterator)this->BeginX; }
 
125
  const_iterator begin() const { return (const_iterator)this->BeginX; }
 
126
  iterator end() { return (iterator)this->EndX; }
 
127
  const_iterator end() const { return (const_iterator)this->EndX; }
 
128
protected:
 
129
  iterator capacity_ptr() { return (iterator)this->CapacityX; }
 
130
  const_iterator capacity_ptr() const { return (const_iterator)this->CapacityX;}
 
131
public:
 
132
  
 
133
  // reverse iterator creation methods.
 
134
  reverse_iterator rbegin()            { return reverse_iterator(end()); }
 
135
  const_reverse_iterator rbegin() const{ return const_reverse_iterator(end()); }
 
136
  reverse_iterator rend()              { return reverse_iterator(begin()); }
 
137
  const_reverse_iterator rend() const { return const_reverse_iterator(begin());}
 
138
 
 
139
  size_type size() const { return end()-begin(); }
 
140
  size_type max_size() const { return size_type(-1) / sizeof(T); }
 
141
  
 
142
  /// capacity - Return the total number of elements in the currently allocated
 
143
  /// buffer.
 
144
  size_t capacity() const { return capacity_ptr() - begin(); }
 
145
  
 
146
  /// data - Return a pointer to the vector's buffer, even if empty().
 
147
  pointer data() { return pointer(begin()); }
 
148
  /// data - Return a pointer to the vector's buffer, even if empty().
 
149
  const_pointer data() const { return const_pointer(begin()); }
 
150
  
 
151
  reference operator[](unsigned idx) {
 
152
    assert(begin() + idx < end());
 
153
    return begin()[idx];
 
154
  }
 
155
  const_reference operator[](unsigned idx) const {
 
156
    assert(begin() + idx < end());
 
157
    return begin()[idx];
 
158
  }
 
159
 
 
160
  reference front() {
 
161
    return begin()[0];
 
162
  }
 
163
  const_reference front() const {
 
164
    return begin()[0];
 
165
  }
 
166
 
 
167
  reference back() {
 
168
    return end()[-1];
 
169
  }
 
170
  const_reference back() const {
 
171
    return end()[-1];
 
172
  }
 
173
};
 
174
  
 
175
/// SmallVectorTemplateBase<isPodLike = false> - This is where we put method
 
176
/// implementations that are designed to work with non-POD-like T's.
 
177
template <typename T, bool isPodLike>
 
178
class SmallVectorTemplateBase : public SmallVectorTemplateCommon<T> {
 
179
public:
 
180
  SmallVectorTemplateBase(size_t Size) : SmallVectorTemplateCommon<T>(Size) {}
 
181
 
 
182
  static void destroy_range(T *S, T *E) {
 
183
    while (S != E) {
 
184
      --E;
 
185
      E->~T();
 
186
    }
 
187
  }
 
188
  
 
189
  /// uninitialized_copy - Copy the range [I, E) onto the uninitialized memory
 
190
  /// starting with "Dest", constructing elements into it as needed.
 
191
  template<typename It1, typename It2>
 
192
  static void uninitialized_copy(It1 I, It1 E, It2 Dest) {
 
193
    std::uninitialized_copy(I, E, Dest);
 
194
  }
 
195
  
 
196
  /// grow - double the size of the allocated memory, guaranteeing space for at
 
197
  /// least one more element or MinSize if specified.
 
198
  void grow(size_t MinSize = 0);
 
199
};
 
200
 
 
201
// Define this out-of-line to dissuade the C++ compiler from inlining it.
 
202
template <typename T, bool isPodLike>
 
203
void SmallVectorTemplateBase<T, isPodLike>::grow(size_t MinSize) {
 
204
  size_t CurCapacity = this->capacity();
 
205
  size_t CurSize = this->size();
 
206
  size_t NewCapacity = 2*CurCapacity;
 
207
  if (NewCapacity < MinSize)
 
208
    NewCapacity = MinSize;
 
209
  T *NewElts = static_cast<T*>(operator new(NewCapacity*sizeof(T)));
 
210
  
 
211
  // Copy the elements over.
 
212
  this->uninitialized_copy(this->begin(), this->end(), NewElts);
 
213
  
 
214
  // Destroy the original elements.
 
215
  destroy_range(this->begin(), this->end());
 
216
  
 
217
  // If this wasn't grown from the inline copy, deallocate the old space.
 
218
  if (!this->isSmall())
 
219
    operator delete(this->begin());
 
220
  
 
221
  this->setEnd(NewElts+CurSize);
 
222
  this->BeginX = NewElts;
 
223
  this->CapacityX = this->begin()+NewCapacity;
 
224
}
 
225
  
 
226
  
 
227
/// SmallVectorTemplateBase<isPodLike = true> - This is where we put method
 
228
/// implementations that are designed to work with POD-like T's.
 
229
template <typename T>
 
230
class SmallVectorTemplateBase<T, true> : public SmallVectorTemplateCommon<T> {
 
231
public:
 
232
  SmallVectorTemplateBase(size_t Size) : SmallVectorTemplateCommon<T>(Size) {}
 
233
  
 
234
  // No need to do a destroy loop for POD's.
 
235
  static void destroy_range(T *, T *) {}
 
236
  
 
237
  /// uninitialized_copy - Copy the range [I, E) onto the uninitialized memory
 
238
  /// starting with "Dest", constructing elements into it as needed.
 
239
  template<typename It1, typename It2>
 
240
  static void uninitialized_copy(It1 I, It1 E, It2 Dest) {
 
241
    // Use memcpy for PODs: std::uninitialized_copy optimizes to memmove, memcpy
 
242
    // is better.
 
243
    memcpy(&*Dest, &*I, (E-I)*sizeof(T));
 
244
  }
 
245
  
 
246
  /// grow - double the size of the allocated memory, guaranteeing space for at
 
247
  /// least one more element or MinSize if specified.
 
248
  void grow(size_t MinSize = 0) {
 
249
    this->grow_pod(MinSize*sizeof(T), sizeof(T));
 
250
  }
 
251
};
 
252
  
 
253
  
 
254
/// SmallVectorImpl - This class consists of common code factored out of the
 
255
/// SmallVector class to reduce code duplication based on the SmallVector 'N'
 
256
/// template parameter.
 
257
template <typename T>
 
258
class SmallVectorImpl : public SmallVectorTemplateBase<T, isPodLike<T>::value> {
 
259
  typedef SmallVectorTemplateBase<T, isPodLike<T>::value > SuperClass;
 
260
public:
 
261
  typedef typename SuperClass::iterator iterator;
 
262
  typedef typename SuperClass::size_type size_type;
 
263
  
 
264
  // Default ctor - Initialize to empty.
 
265
  explicit SmallVectorImpl(unsigned N)
 
266
    : SmallVectorTemplateBase<T, isPodLike<T>::value>(N*sizeof(T)) {
 
267
  }
 
268
  
 
269
  ~SmallVectorImpl() {
 
270
    // Destroy the constructed elements in the vector.
 
271
    this->destroy_range(this->begin(), this->end());
 
272
    
 
273
    // If this wasn't grown from the inline copy, deallocate the old space.
 
274
    if (!this->isSmall())
 
275
      operator delete(this->begin());
 
276
  }
 
277
  
 
278
  
 
279
  void clear() {
 
280
    this->destroy_range(this->begin(), this->end());
 
281
    this->EndX = this->BeginX;
 
282
  }
 
283
 
 
284
  void resize(unsigned N) {
 
285
    if (N < this->size()) {
 
286
      this->destroy_range(this->begin()+N, this->end());
 
287
      this->setEnd(this->begin()+N);
 
288
    } else if (N > this->size()) {
 
289
      if (this->capacity() < N)
 
290
        this->grow(N);
 
291
      this->construct_range(this->end(), this->begin()+N, T());
 
292
      this->setEnd(this->begin()+N);
 
293
    }
 
294
  }
 
295
 
 
296
  void resize(unsigned N, const T &NV) {
 
297
    if (N < this->size()) {
 
298
      this->destroy_range(this->begin()+N, this->end());
 
299
      this->setEnd(this->begin()+N);
 
300
    } else if (N > this->size()) {
 
301
      if (this->capacity() < N)
 
302
        this->grow(N);
 
303
      construct_range(this->end(), this->begin()+N, NV);
 
304
      this->setEnd(this->begin()+N);
 
305
    }
 
306
  }
 
307
 
 
308
  void reserve(unsigned N) {
 
309
    if (this->capacity() < N)
 
310
      this->grow(N);
 
311
  }
 
312
  
 
313
  void push_back(const T &Elt) {
 
314
    if (this->EndX < this->CapacityX) {
 
315
    Retry:
 
316
      new (this->end()) T(Elt);
 
317
      this->setEnd(this->end()+1);
 
318
      return;
 
319
    }
 
320
    this->grow();
 
321
    goto Retry;
 
322
  }
 
323
  
 
324
  void pop_back() {
 
325
    this->setEnd(this->end()-1);
 
326
    this->end()->~T();
 
327
  }
 
328
  
 
329
  T pop_back_val() {
 
330
    T Result = this->back();
 
331
    pop_back();
 
332
    return Result;
 
333
  }
 
334
  
 
335
  
 
336
  void swap(SmallVectorImpl &RHS);
 
337
  
 
338
  /// append - Add the specified range to the end of the SmallVector.
 
339
  ///
 
340
  template<typename in_iter>
 
341
  void append(in_iter in_start, in_iter in_end) {
 
342
    size_type NumInputs = std::distance(in_start, in_end);
 
343
    // Grow allocated space if needed.
 
344
    if (NumInputs > size_type(this->capacity_ptr()-this->end()))
 
345
      this->grow(this->size()+NumInputs);
 
346
    
 
347
    // Copy the new elements over.
 
348
    // TODO: NEED To compile time dispatch on whether in_iter is a random access
 
349
    // iterator to use the fast uninitialized_copy.
 
350
    std::uninitialized_copy(in_start, in_end, this->end());
 
351
    this->setEnd(this->end() + NumInputs);
 
352
  }
 
353
  
 
354
  /// append - Add the specified range to the end of the SmallVector.
 
355
  ///
 
356
  void append(size_type NumInputs, const T &Elt) {
 
357
    // Grow allocated space if needed.
 
358
    if (NumInputs > size_type(this->capacity_ptr()-this->end()))
 
359
      this->grow(this->size()+NumInputs);
 
360
    
 
361
    // Copy the new elements over.
 
362
    std::uninitialized_fill_n(this->end(), NumInputs, Elt);
 
363
    this->setEnd(this->end() + NumInputs);
 
364
  }
 
365
  
 
366
  void assign(unsigned NumElts, const T &Elt) {
 
367
    clear();
 
368
    if (this->capacity() < NumElts)
 
369
      this->grow(NumElts);
 
370
    this->setEnd(this->begin()+NumElts);
 
371
    construct_range(this->begin(), this->end(), Elt);
 
372
  }
 
373
  
 
374
  iterator erase(iterator I) {
 
375
    iterator N = I;
 
376
    // Shift all elts down one.
 
377
    std::copy(I+1, this->end(), I);
 
378
    // Drop the last elt.
 
379
    pop_back();
 
380
    return(N);
 
381
  }
 
382
  
 
383
  iterator erase(iterator S, iterator E) {
 
384
    iterator N = S;
 
385
    // Shift all elts down.
 
386
    iterator I = std::copy(E, this->end(), S);
 
387
    // Drop the last elts.
 
388
    this->destroy_range(I, this->end());
 
389
    this->setEnd(I);
 
390
    return(N);
 
391
  }
 
392
  
 
393
  iterator insert(iterator I, const T &Elt) {
 
394
    if (I == this->end()) {  // Important special case for empty vector.
 
395
      push_back(Elt);
 
396
      return this->end()-1;
 
397
    }
 
398
    
 
399
    if (this->EndX < this->CapacityX) {
 
400
    Retry:
 
401
      new (this->end()) T(this->back());
 
402
      this->setEnd(this->end()+1);
 
403
      // Push everything else over.
 
404
      std::copy_backward(I, this->end()-1, this->end());
 
405
      *I = Elt;
 
406
      return I;
 
407
    }
 
408
    size_t EltNo = I-this->begin();
 
409
    this->grow();
 
410
    I = this->begin()+EltNo;
 
411
    goto Retry;
 
412
  }
 
413
  
 
414
  iterator insert(iterator I, size_type NumToInsert, const T &Elt) {
 
415
    if (I == this->end()) {  // Important special case for empty vector.
 
416
      append(NumToInsert, Elt);
 
417
      return this->end()-1;
 
418
    }
 
419
    
 
420
    // Convert iterator to elt# to avoid invalidating iterator when we reserve()
 
421
    size_t InsertElt = I - this->begin();
 
422
    
 
423
    // Ensure there is enough space.
 
424
    reserve(static_cast<unsigned>(this->size() + NumToInsert));
 
425
    
 
426
    // Uninvalidate the iterator.
 
427
    I = this->begin()+InsertElt;
 
428
    
 
429
    // If there are more elements between the insertion point and the end of the
 
430
    // range than there are being inserted, we can use a simple approach to
 
431
    // insertion.  Since we already reserved space, we know that this won't
 
432
    // reallocate the vector.
 
433
    if (size_t(this->end()-I) >= NumToInsert) {
 
434
      T *OldEnd = this->end();
 
435
      append(this->end()-NumToInsert, this->end());
 
436
      
 
437
      // Copy the existing elements that get replaced.
 
438
      std::copy_backward(I, OldEnd-NumToInsert, OldEnd);
 
439
      
 
440
      std::fill_n(I, NumToInsert, Elt);
 
441
      return I;
 
442
    }
 
443
    
 
444
    // Otherwise, we're inserting more elements than exist already, and we're
 
445
    // not inserting at the end.
 
446
    
 
447
    // Copy over the elements that we're about to overwrite.
 
448
    T *OldEnd = this->end();
 
449
    this->setEnd(this->end() + NumToInsert);
 
450
    size_t NumOverwritten = OldEnd-I;
 
451
    this->uninitialized_copy(I, OldEnd, this->end()-NumOverwritten);
 
452
    
 
453
    // Replace the overwritten part.
 
454
    std::fill_n(I, NumOverwritten, Elt);
 
455
    
 
456
    // Insert the non-overwritten middle part.
 
457
    std::uninitialized_fill_n(OldEnd, NumToInsert-NumOverwritten, Elt);
 
458
    return I;
 
459
  }
 
460
  
 
461
  template<typename ItTy>
 
462
  iterator insert(iterator I, ItTy From, ItTy To) {
 
463
    if (I == this->end()) {  // Important special case for empty vector.
 
464
      append(From, To);
 
465
      return this->end()-1;
 
466
    }
 
467
    
 
468
    size_t NumToInsert = std::distance(From, To);
 
469
    // Convert iterator to elt# to avoid invalidating iterator when we reserve()
 
470
    size_t InsertElt = I - this->begin();
 
471
    
 
472
    // Ensure there is enough space.
 
473
    reserve(static_cast<unsigned>(this->size() + NumToInsert));
 
474
    
 
475
    // Uninvalidate the iterator.
 
476
    I = this->begin()+InsertElt;
 
477
    
 
478
    // If there are more elements between the insertion point and the end of the
 
479
    // range than there are being inserted, we can use a simple approach to
 
480
    // insertion.  Since we already reserved space, we know that this won't
 
481
    // reallocate the vector.
 
482
    if (size_t(this->end()-I) >= NumToInsert) {
 
483
      T *OldEnd = this->end();
 
484
      append(this->end()-NumToInsert, this->end());
 
485
      
 
486
      // Copy the existing elements that get replaced.
 
487
      std::copy_backward(I, OldEnd-NumToInsert, OldEnd);
 
488
      
 
489
      std::copy(From, To, I);
 
490
      return I;
 
491
    }
 
492
    
 
493
    // Otherwise, we're inserting more elements than exist already, and we're
 
494
    // not inserting at the end.
 
495
    
 
496
    // Copy over the elements that we're about to overwrite.
 
497
    T *OldEnd = this->end();
 
498
    this->setEnd(this->end() + NumToInsert);
 
499
    size_t NumOverwritten = OldEnd-I;
 
500
    this->uninitialized_copy(I, OldEnd, this->end()-NumOverwritten);
 
501
    
 
502
    // Replace the overwritten part.
 
503
    std::copy(From, From+NumOverwritten, I);
 
504
    
 
505
    // Insert the non-overwritten middle part.
 
506
    this->uninitialized_copy(From+NumOverwritten, To, OldEnd);
 
507
    return I;
 
508
  }
 
509
  
 
510
  const SmallVectorImpl
 
511
  &operator=(const SmallVectorImpl &RHS);
 
512
  
 
513
  bool operator==(const SmallVectorImpl &RHS) const {
 
514
    if (this->size() != RHS.size()) return false;
 
515
    return std::equal(this->begin(), this->end(), RHS.begin());
 
516
  }
 
517
  bool operator!=(const SmallVectorImpl &RHS) const {
 
518
    return !(*this == RHS);
 
519
  }
 
520
  
 
521
  bool operator<(const SmallVectorImpl &RHS) const {
 
522
    return std::lexicographical_compare(this->begin(), this->end(),
 
523
                                        RHS.begin(), RHS.end());
 
524
  }
 
525
  
 
526
  /// set_size - Set the array size to \arg N, which the current array must have
 
527
  /// enough capacity for.
 
528
  ///
 
529
  /// This does not construct or destroy any elements in the vector.
 
530
  ///
 
531
  /// Clients can use this in conjunction with capacity() to write past the end
 
532
  /// of the buffer when they know that more elements are available, and only
 
533
  /// update the size later. This avoids the cost of value initializing elements
 
534
  /// which will only be overwritten.
 
535
  void set_size(unsigned N) {
 
536
    assert(N <= this->capacity());
 
537
    this->setEnd(this->begin() + N);
 
538
  }
 
539
  
 
540
private:
 
541
  static void construct_range(T *S, T *E, const T &Elt) {
 
542
    for (; S != E; ++S)
 
543
      new (S) T(Elt);
 
544
  }
 
545
};
 
546
  
 
547
 
 
548
template <typename T>
 
549
void SmallVectorImpl<T>::swap(SmallVectorImpl<T> &RHS) {
 
550
  if (this == &RHS) return;
 
551
 
 
552
  // We can only avoid copying elements if neither vector is small.
 
553
  if (!this->isSmall() && !RHS.isSmall()) {
 
554
    std::swap(this->BeginX, RHS.BeginX);
 
555
    std::swap(this->EndX, RHS.EndX);
 
556
    std::swap(this->CapacityX, RHS.CapacityX);
 
557
    return;
 
558
  }
 
559
  if (RHS.size() > this->capacity())
 
560
    this->grow(RHS.size());
 
561
  if (this->size() > RHS.capacity())
 
562
    RHS.grow(this->size());
 
563
 
 
564
  // Swap the shared elements.
 
565
  size_t NumShared = this->size();
 
566
  if (NumShared > RHS.size()) NumShared = RHS.size();
 
567
  for (unsigned i = 0; i != static_cast<unsigned>(NumShared); ++i)
 
568
    std::swap((*this)[i], RHS[i]);
 
569
 
 
570
  // Copy over the extra elts.
 
571
  if (this->size() > RHS.size()) {
 
572
    size_t EltDiff = this->size() - RHS.size();
 
573
    this->uninitialized_copy(this->begin()+NumShared, this->end(), RHS.end());
 
574
    RHS.setEnd(RHS.end()+EltDiff);
 
575
    this->destroy_range(this->begin()+NumShared, this->end());
 
576
    this->setEnd(this->begin()+NumShared);
 
577
  } else if (RHS.size() > this->size()) {
 
578
    size_t EltDiff = RHS.size() - this->size();
 
579
    this->uninitialized_copy(RHS.begin()+NumShared, RHS.end(), this->end());
 
580
    this->setEnd(this->end() + EltDiff);
 
581
    this->destroy_range(RHS.begin()+NumShared, RHS.end());
 
582
    RHS.setEnd(RHS.begin()+NumShared);
 
583
  }
 
584
}
 
585
 
 
586
template <typename T>
 
587
const SmallVectorImpl<T> &SmallVectorImpl<T>::
 
588
  operator=(const SmallVectorImpl<T> &RHS) {
 
589
  // Avoid self-assignment.
 
590
  if (this == &RHS) return *this;
 
591
 
 
592
  // If we already have sufficient space, assign the common elements, then
 
593
  // destroy any excess.
 
594
  size_t RHSSize = RHS.size();
 
595
  size_t CurSize = this->size();
 
596
  if (CurSize >= RHSSize) {
 
597
    // Assign common elements.
 
598
    iterator NewEnd;
 
599
    if (RHSSize)
 
600
      NewEnd = std::copy(RHS.begin(), RHS.begin()+RHSSize, this->begin());
 
601
    else
 
602
      NewEnd = this->begin();
 
603
 
 
604
    // Destroy excess elements.
 
605
    this->destroy_range(NewEnd, this->end());
 
606
 
 
607
    // Trim.
 
608
    this->setEnd(NewEnd);
 
609
    return *this;
 
610
  }
 
611
 
 
612
  // If we have to grow to have enough elements, destroy the current elements.
 
613
  // This allows us to avoid copying them during the grow.
 
614
  if (this->capacity() < RHSSize) {
 
615
    // Destroy current elements.
 
616
    this->destroy_range(this->begin(), this->end());
 
617
    this->setEnd(this->begin());
 
618
    CurSize = 0;
 
619
    this->grow(RHSSize);
 
620
  } else if (CurSize) {
 
621
    // Otherwise, use assignment for the already-constructed elements.
 
622
    std::copy(RHS.begin(), RHS.begin()+CurSize, this->begin());
 
623
  }
 
624
 
 
625
  // Copy construct the new elements in place.
 
626
  this->uninitialized_copy(RHS.begin()+CurSize, RHS.end(),
 
627
                           this->begin()+CurSize);
 
628
 
 
629
  // Set end.
 
630
  this->setEnd(this->begin()+RHSSize);
 
631
  return *this;
 
632
}
 
633
 
 
634
 
 
635
/// SmallVector - This is a 'vector' (really, a variable-sized array), optimized
 
636
/// for the case when the array is small.  It contains some number of elements
 
637
/// in-place, which allows it to avoid heap allocation when the actual number of
 
638
/// elements is below that threshold.  This allows normal "small" cases to be
 
639
/// fast without losing generality for large inputs.
 
640
///
 
641
/// Note that this does not attempt to be exception safe.
 
642
///
 
643
template <typename T, unsigned N>
 
644
class SmallVector : public SmallVectorImpl<T> {
 
645
  /// InlineElts - These are 'N-1' elements that are stored inline in the body
 
646
  /// of the vector.  The extra '1' element is stored in SmallVectorImpl.
 
647
  typedef typename SmallVectorImpl<T>::U U;
 
648
  enum {
 
649
    // MinUs - The number of U's require to cover N T's.
 
650
    MinUs = (static_cast<unsigned int>(sizeof(T))*N +
 
651
             static_cast<unsigned int>(sizeof(U)) - 1) /
 
652
            static_cast<unsigned int>(sizeof(U)),
 
653
 
 
654
    // NumInlineEltsElts - The number of elements actually in this array.  There
 
655
    // is already one in the parent class, and we have to round up to avoid
 
656
    // having a zero-element array.
 
657
    NumInlineEltsElts = MinUs > 1 ? (MinUs - 1) : 1,
 
658
 
 
659
    // NumTsAvailable - The number of T's we actually have space for, which may
 
660
    // be more than N due to rounding.
 
661
    NumTsAvailable = (NumInlineEltsElts+1)*static_cast<unsigned int>(sizeof(U))/
 
662
                     static_cast<unsigned int>(sizeof(T))
 
663
  };
 
664
  U InlineElts[NumInlineEltsElts];
 
665
public:
 
666
  SmallVector() : SmallVectorImpl<T>(NumTsAvailable) {
 
667
  }
 
668
 
 
669
  explicit SmallVector(unsigned Size, const T &Value = T())
 
670
    : SmallVectorImpl<T>(NumTsAvailable) {
 
671
    this->reserve(Size);
 
672
    while (Size--)
 
673
      this->push_back(Value);
 
674
  }
 
675
 
 
676
  template<typename ItTy>
 
677
  SmallVector(ItTy S, ItTy E) : SmallVectorImpl<T>(NumTsAvailable) {
 
678
    this->append(S, E);
 
679
  }
 
680
 
 
681
  SmallVector(const SmallVector &RHS) : SmallVectorImpl<T>(NumTsAvailable) {
 
682
    if (!RHS.empty())
 
683
      SmallVectorImpl<T>::operator=(RHS);
 
684
  }
 
685
 
 
686
  const SmallVector &operator=(const SmallVector &RHS) {
 
687
    SmallVectorImpl<T>::operator=(RHS);
 
688
    return *this;
 
689
  }
 
690
 
 
691
};
 
692
 
 
693
} // End llvm namespace
 
694
 
 
695
namespace std {
 
696
  /// Implement std::swap in terms of SmallVector swap.
 
697
  template<typename T>
 
698
  inline void
 
699
  swap(llvm::SmallVectorImpl<T> &LHS, llvm::SmallVectorImpl<T> &RHS) {
 
700
    LHS.swap(RHS);
 
701
  }
 
702
 
 
703
  /// Implement std::swap in terms of SmallVector swap.
 
704
  template<typename T, unsigned N>
 
705
  inline void
 
706
  swap(llvm::SmallVector<T, N> &LHS, llvm::SmallVector<T, N> &RHS) {
 
707
    LHS.swap(RHS);
 
708
  }
 
709
}
 
710
 
 
711
#endif