xref: /openbsd-src/gnu/llvm/compiler-rt/lib/sanitizer_common/sanitizer_vector.h (revision 810390e339a5425391477d5d41c78d7cab2424ac)
13cab2bb3Spatrick //===-- sanitizer_vector.h -------------------------------------*- C++ -*-===//
23cab2bb3Spatrick //
33cab2bb3Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
43cab2bb3Spatrick // See https://llvm.org/LICENSE.txt for license information.
53cab2bb3Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
63cab2bb3Spatrick //
73cab2bb3Spatrick //===----------------------------------------------------------------------===//
83cab2bb3Spatrick //
93cab2bb3Spatrick // This file is shared between sanitizers run-time libraries.
103cab2bb3Spatrick //
113cab2bb3Spatrick //===----------------------------------------------------------------------===//
123cab2bb3Spatrick 
133cab2bb3Spatrick // Low-fat STL-like vector container.
143cab2bb3Spatrick 
153cab2bb3Spatrick #ifndef SANITIZER_VECTOR_H
163cab2bb3Spatrick #define SANITIZER_VECTOR_H
173cab2bb3Spatrick 
183cab2bb3Spatrick #include "sanitizer_common/sanitizer_allocator_internal.h"
193cab2bb3Spatrick #include "sanitizer_common/sanitizer_libc.h"
203cab2bb3Spatrick 
213cab2bb3Spatrick namespace __sanitizer {
223cab2bb3Spatrick 
233cab2bb3Spatrick template<typename T>
243cab2bb3Spatrick class Vector {
253cab2bb3Spatrick  public:
Vector()263cab2bb3Spatrick   Vector() : begin_(), end_(), last_() {}
273cab2bb3Spatrick 
~Vector()283cab2bb3Spatrick   ~Vector() {
293cab2bb3Spatrick     if (begin_)
303cab2bb3Spatrick       InternalFree(begin_);
313cab2bb3Spatrick   }
323cab2bb3Spatrick 
Reset()333cab2bb3Spatrick   void Reset() {
343cab2bb3Spatrick     if (begin_)
353cab2bb3Spatrick       InternalFree(begin_);
363cab2bb3Spatrick     begin_ = 0;
373cab2bb3Spatrick     end_ = 0;
383cab2bb3Spatrick     last_ = 0;
393cab2bb3Spatrick   }
403cab2bb3Spatrick 
Size()413cab2bb3Spatrick   uptr Size() const {
423cab2bb3Spatrick     return end_ - begin_;
433cab2bb3Spatrick   }
443cab2bb3Spatrick 
453cab2bb3Spatrick   T &operator[](uptr i) {
463cab2bb3Spatrick     DCHECK_LT(i, end_ - begin_);
473cab2bb3Spatrick     return begin_[i];
483cab2bb3Spatrick   }
493cab2bb3Spatrick 
503cab2bb3Spatrick   const T &operator[](uptr i) const {
513cab2bb3Spatrick     DCHECK_LT(i, end_ - begin_);
523cab2bb3Spatrick     return begin_[i];
533cab2bb3Spatrick   }
543cab2bb3Spatrick 
PushBack()553cab2bb3Spatrick   T *PushBack() {
563cab2bb3Spatrick     EnsureSize(Size() + 1);
573cab2bb3Spatrick     T *p = &end_[-1];
583cab2bb3Spatrick     internal_memset(p, 0, sizeof(*p));
593cab2bb3Spatrick     return p;
603cab2bb3Spatrick   }
613cab2bb3Spatrick 
PushBack(const T & v)623cab2bb3Spatrick   T *PushBack(const T& v) {
633cab2bb3Spatrick     EnsureSize(Size() + 1);
643cab2bb3Spatrick     T *p = &end_[-1];
653cab2bb3Spatrick     internal_memcpy(p, &v, sizeof(*p));
663cab2bb3Spatrick     return p;
673cab2bb3Spatrick   }
683cab2bb3Spatrick 
PopBack()693cab2bb3Spatrick   void PopBack() {
703cab2bb3Spatrick     DCHECK_GT(end_, begin_);
713cab2bb3Spatrick     end_--;
723cab2bb3Spatrick   }
733cab2bb3Spatrick 
Resize(uptr size)743cab2bb3Spatrick   void Resize(uptr size) {
753cab2bb3Spatrick     if (size == 0) {
763cab2bb3Spatrick       end_ = begin_;
773cab2bb3Spatrick       return;
783cab2bb3Spatrick     }
793cab2bb3Spatrick     uptr old_size = Size();
803cab2bb3Spatrick     if (size <= old_size) {
813cab2bb3Spatrick       end_ = begin_ + size;
823cab2bb3Spatrick       return;
833cab2bb3Spatrick     }
843cab2bb3Spatrick     EnsureSize(size);
853cab2bb3Spatrick     if (old_size < size) {
86*810390e3Srobert       internal_memset(&begin_[old_size], 0,
87*810390e3Srobert                       sizeof(begin_[old_size]) * (size - old_size));
883cab2bb3Spatrick     }
893cab2bb3Spatrick   }
903cab2bb3Spatrick 
913cab2bb3Spatrick  private:
923cab2bb3Spatrick   T *begin_;
933cab2bb3Spatrick   T *end_;
943cab2bb3Spatrick   T *last_;
953cab2bb3Spatrick 
EnsureSize(uptr size)963cab2bb3Spatrick   void EnsureSize(uptr size) {
973cab2bb3Spatrick     if (size <= Size())
983cab2bb3Spatrick       return;
993cab2bb3Spatrick     if (size <= (uptr)(last_ - begin_)) {
1003cab2bb3Spatrick       end_ = begin_ + size;
1013cab2bb3Spatrick       return;
1023cab2bb3Spatrick     }
1033cab2bb3Spatrick     uptr cap0 = last_ - begin_;
1043cab2bb3Spatrick     uptr cap = cap0 * 5 / 4;  // 25% growth
1053cab2bb3Spatrick     if (cap == 0)
1063cab2bb3Spatrick       cap = 16;
1073cab2bb3Spatrick     if (cap < size)
1083cab2bb3Spatrick       cap = size;
1093cab2bb3Spatrick     T *p = (T*)InternalAlloc(cap * sizeof(T));
1103cab2bb3Spatrick     if (cap0) {
1113cab2bb3Spatrick       internal_memcpy(p, begin_, cap0 * sizeof(T));
1123cab2bb3Spatrick       InternalFree(begin_);
1133cab2bb3Spatrick     }
1143cab2bb3Spatrick     begin_ = p;
1153cab2bb3Spatrick     end_ = begin_ + size;
1163cab2bb3Spatrick     last_ = begin_ + cap;
1173cab2bb3Spatrick   }
1183cab2bb3Spatrick 
1193cab2bb3Spatrick   Vector(const Vector&);
1203cab2bb3Spatrick   void operator=(const Vector&);
1213cab2bb3Spatrick };
1223cab2bb3Spatrick }  // namespace __sanitizer
1233cab2bb3Spatrick 
1243cab2bb3Spatrick #endif  // #ifndef SANITIZER_VECTOR_H
125