1326943Sdim//===-- sanitizer_vector.h -------------------------------------*- C++ -*-===//
2326943Sdim//
3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4353358Sdim// See https://llvm.org/LICENSE.txt for license information.
5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6326943Sdim//
7326943Sdim//===----------------------------------------------------------------------===//
8326943Sdim//
9326943Sdim// This file is shared between sanitizers run-time libraries.
10326943Sdim//
11326943Sdim//===----------------------------------------------------------------------===//
12326943Sdim
13326943Sdim// Low-fat STL-like vector container.
14326943Sdim
15326943Sdim#ifndef SANITIZER_VECTOR_H
16326943Sdim#define SANITIZER_VECTOR_H
17326943Sdim
18326943Sdim#include "sanitizer_common/sanitizer_allocator_internal.h"
19326943Sdim#include "sanitizer_common/sanitizer_libc.h"
20326943Sdim
21326943Sdimnamespace __sanitizer {
22326943Sdim
23326943Sdimtemplate<typename T>
24326943Sdimclass Vector {
25326943Sdim public:
26360784Sdim  Vector() : begin_(), end_(), last_() {}
27326943Sdim
28326943Sdim  ~Vector() {
29326943Sdim    if (begin_)
30326943Sdim      InternalFree(begin_);
31326943Sdim  }
32326943Sdim
33326943Sdim  void Reset() {
34326943Sdim    if (begin_)
35326943Sdim      InternalFree(begin_);
36326943Sdim    begin_ = 0;
37326943Sdim    end_ = 0;
38326943Sdim    last_ = 0;
39326943Sdim  }
40326943Sdim
41326943Sdim  uptr Size() const {
42326943Sdim    return end_ - begin_;
43326943Sdim  }
44326943Sdim
45326943Sdim  T &operator[](uptr i) {
46326943Sdim    DCHECK_LT(i, end_ - begin_);
47326943Sdim    return begin_[i];
48326943Sdim  }
49326943Sdim
50326943Sdim  const T &operator[](uptr i) const {
51326943Sdim    DCHECK_LT(i, end_ - begin_);
52326943Sdim    return begin_[i];
53326943Sdim  }
54326943Sdim
55326943Sdim  T *PushBack() {
56326943Sdim    EnsureSize(Size() + 1);
57326943Sdim    T *p = &end_[-1];
58326943Sdim    internal_memset(p, 0, sizeof(*p));
59326943Sdim    return p;
60326943Sdim  }
61326943Sdim
62326943Sdim  T *PushBack(const T& v) {
63326943Sdim    EnsureSize(Size() + 1);
64326943Sdim    T *p = &end_[-1];
65326943Sdim    internal_memcpy(p, &v, sizeof(*p));
66326943Sdim    return p;
67326943Sdim  }
68326943Sdim
69326943Sdim  void PopBack() {
70326943Sdim    DCHECK_GT(end_, begin_);
71326943Sdim    end_--;
72326943Sdim  }
73326943Sdim
74326943Sdim  void Resize(uptr size) {
75326943Sdim    if (size == 0) {
76326943Sdim      end_ = begin_;
77326943Sdim      return;
78326943Sdim    }
79326943Sdim    uptr old_size = Size();
80341825Sdim    if (size <= old_size) {
81341825Sdim      end_ = begin_ + size;
82341825Sdim      return;
83341825Sdim    }
84326943Sdim    EnsureSize(size);
85326943Sdim    if (old_size < size) {
86326943Sdim      for (uptr i = old_size; i < size; i++)
87326943Sdim        internal_memset(&begin_[i], 0, sizeof(begin_[i]));
88326943Sdim    }
89326943Sdim  }
90326943Sdim
91326943Sdim private:
92326943Sdim  T *begin_;
93326943Sdim  T *end_;
94326943Sdim  T *last_;
95326943Sdim
96326943Sdim  void EnsureSize(uptr size) {
97326943Sdim    if (size <= Size())
98326943Sdim      return;
99326943Sdim    if (size <= (uptr)(last_ - begin_)) {
100326943Sdim      end_ = begin_ + size;
101326943Sdim      return;
102326943Sdim    }
103326943Sdim    uptr cap0 = last_ - begin_;
104326943Sdim    uptr cap = cap0 * 5 / 4;  // 25% growth
105326943Sdim    if (cap == 0)
106326943Sdim      cap = 16;
107326943Sdim    if (cap < size)
108326943Sdim      cap = size;
109326943Sdim    T *p = (T*)InternalAlloc(cap * sizeof(T));
110326943Sdim    if (cap0) {
111326943Sdim      internal_memcpy(p, begin_, cap0 * sizeof(T));
112326943Sdim      InternalFree(begin_);
113326943Sdim    }
114326943Sdim    begin_ = p;
115326943Sdim    end_ = begin_ + size;
116326943Sdim    last_ = begin_ + cap;
117326943Sdim  }
118326943Sdim
119326943Sdim  Vector(const Vector&);
120326943Sdim  void operator=(const Vector&);
121326943Sdim};
122326943Sdim}  // namespace __sanitizer
123326943Sdim
124326943Sdim#endif  // #ifndef SANITIZER_VECTOR_H
125