1 // Copyright 2016 The Fuchsia Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #pragma once 6 7 #include <fbl/alloc_checker.h> 8 #include <fbl/macros.h> 9 #include <new> 10 #include <stddef.h> 11 #include <zircon/assert.h> 12 13 namespace fbl { 14 15 // Runtime-determined, fixed size arrays that are "inlined" (e.g., on the stack) if the size at most 16 // |max_inline_count| or heap-allocated otherwise. This is typically used like: 17 // 18 // fbl::AllocChecker ac; 19 // fbl::InlineArray<zx_handle_t, 4u> handle_values(&ac, num_handles); 20 // if (!ac.check()) 21 // return ZX_ERR_NO_MEMORY; 22 // 23 // Note: Currently, |max_inline_count| must be at least 1. 24 template <typename T, size_t max_inline_count> 25 class InlineArray { 26 public: InlineArray(fbl::AllocChecker * ac,size_t count)27 InlineArray(fbl::AllocChecker* ac, size_t count) 28 : count_(count), 29 ptr_(!count_ ? nullptr 30 : is_inline() ? reinterpret_cast<T*>(inline_storage_) : new (ac) T[count_]) { 31 if (is_inline()) { 32 // Arm the AllocChecker even if we didn't allocate -- the user should check it 33 // regardless! 34 ac->arm(0u, true); 35 for (size_t i = 0; i < count_; i++) 36 new (&ptr_[i]) T(); 37 } 38 } 39 ~InlineArray()40 ~InlineArray() { 41 if (is_inline()) { 42 for (size_t i = 0; i < count_; i++) 43 ptr_[i].~T(); 44 } else { 45 delete[] ptr_; 46 } 47 } 48 49 InlineArray() = delete; 50 DISALLOW_COPY_ASSIGN_AND_MOVE(InlineArray); 51 size()52 size_t size() const { 53 return count_; 54 } 55 get()56 T* get() const { return ptr_; } 57 58 T& operator[](size_t i) const { 59 ZX_DEBUG_ASSERT(i < count_); 60 return ptr_[i]; 61 } 62 63 private: is_inline()64 bool is_inline() const { return count_ <= max_inline_count; } 65 66 const size_t count_; 67 T* const ptr_; 68 alignas(T) char inline_storage_[max_inline_count * sizeof(T)]; 69 }; 70 71 } // namespace fbl 72