1b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// Copyright (c) 2012 The Chromium Authors. All rights reserved. 2b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// Use of this source code is governed by a BSD-style license that can be 3b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// found in the LICENSE file. 4b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 5b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#ifndef BASE_CONTAINERS_STACK_CONTAINER_H_ 6b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#define BASE_CONTAINERS_STACK_CONTAINER_H_ 7b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 8cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko#include <stddef.h> 9cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko 10b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include <string> 11b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include <vector> 12b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 13cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko#include "base/macros.h" 14b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include "base/memory/aligned_memory.h" 15b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include "base/strings/string16.h" 16b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include "build/build_config.h" 17b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 18b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratnamespace base { 19b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 20b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// This allocator can be used with STL containers to provide a stack buffer 21b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// from which to allocate memory and overflows onto the heap. This stack buffer 22b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// would be allocated on the stack and allows us to avoid heap operations in 23b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// some situations. 24b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// 25b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// STL likes to make copies of allocators, so the allocator itself can't hold 26b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// the data. Instead, we make the creator responsible for creating a 27b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// StackAllocator::Source which contains the data. Copying the allocator 28b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// merely copies the pointer to this shared source, so all allocators created 29b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// based on our allocator will share the same stack buffer. 30b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// 31b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// This stack buffer implementation is very simple. The first allocation that 32b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// fits in the stack buffer will use the stack buffer. Any subsequent 33b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// allocations will not use the stack buffer, even if there is unused room. 34b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// This makes it appropriate for array-like containers, but the caller should 35b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// be sure to reserve() in the container up to the stack buffer size. Otherwise 36b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// the container will allocate a small array which will "use up" the stack 37b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// buffer. 38b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erattemplate<typename T, size_t stack_capacity> 39b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratclass StackAllocator : public std::allocator<T> { 40b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat public: 41b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat typedef typename std::allocator<T>::pointer pointer; 42b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat typedef typename std::allocator<T>::size_type size_type; 43b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 44b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // Backing store for the allocator. The container owner is responsible for 45b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // maintaining this for as long as any containers using this allocator are 46b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // live. 47b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat struct Source { 48b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat Source() : used_stack_buffer_(false) { 49b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 50b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 51b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // Casts the buffer in its right type. 52b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat T* stack_buffer() { return stack_buffer_.template data_as<T>(); } 53b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat const T* stack_buffer() const { 54b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return stack_buffer_.template data_as<T>(); 55b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 56b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 57b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // The buffer itself. It is not of type T because we don't want the 58b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // constructors and destructors to be automatically called. Define a POD 59b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // buffer of the right size instead. 60b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat base::AlignedMemory<sizeof(T[stack_capacity]), ALIGNOF(T)> stack_buffer_; 61b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#if defined(__GNUC__) && !defined(ARCH_CPU_X86_FAMILY) 62cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko static_assert(ALIGNOF(T) <= 16, "http://crbug.com/115612"); 63b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#endif 64b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 65b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // Set when the stack buffer is used for an allocation. We do not track 66b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // how much of the buffer is used, only that somebody is using it. 67b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat bool used_stack_buffer_; 68b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat }; 69b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 70b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // Used by containers when they want to refer to an allocator of type U. 71b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat template<typename U> 72b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat struct rebind { 73b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat typedef StackAllocator<U, stack_capacity> other; 74b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat }; 75b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 76b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // For the straight up copy c-tor, we can share storage. 77b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat StackAllocator(const StackAllocator<T, stack_capacity>& rhs) 78b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat : std::allocator<T>(), source_(rhs.source_) { 79b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 80b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 81b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // ISO C++ requires the following constructor to be defined, 82b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // and std::vector in VC++2008SP1 Release fails with an error 83b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // in the class _Container_base_aux_alloc_real (from <xutility>) 84b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // if the constructor does not exist. 85b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // For this constructor, we cannot share storage; there's 86b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // no guarantee that the Source buffer of Ts is large enough 87b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // for Us. 88b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // TODO: If we were fancy pants, perhaps we could share storage 89b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // iff sizeof(T) == sizeof(U). 90b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat template<typename U, size_t other_capacity> 91b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat StackAllocator(const StackAllocator<U, other_capacity>& other) 92b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat : source_(NULL) { 93b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 94b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 95b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // This constructor must exist. It creates a default allocator that doesn't 96b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // actually have a stack buffer. glibc's std::string() will compare the 97b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // current allocator against the default-constructed allocator, so this 98b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // should be fast. 99b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat StackAllocator() : source_(NULL) { 100b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 101b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 102b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat explicit StackAllocator(Source* source) : source_(source) { 103b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 104b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 105b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // Actually do the allocation. Use the stack buffer if nobody has used it yet 106b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // and the size requested fits. Otherwise, fall through to the standard 107b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // allocator. 108b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat pointer allocate(size_type n, void* hint = 0) { 109b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat if (source_ != NULL && !source_->used_stack_buffer_ 110b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat && n <= stack_capacity) { 111b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat source_->used_stack_buffer_ = true; 112b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return source_->stack_buffer(); 113b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } else { 114b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return std::allocator<T>::allocate(n, hint); 115b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 116b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 117b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 118b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // Free: when trying to free the stack buffer, just mark it as free. For 119b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // non-stack-buffer pointers, just fall though to the standard allocator. 120b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat void deallocate(pointer p, size_type n) { 121b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat if (source_ != NULL && p == source_->stack_buffer()) 122b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat source_->used_stack_buffer_ = false; 123b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat else 124b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat std::allocator<T>::deallocate(p, n); 125b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 126b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 127b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat private: 128b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat Source* source_; 129b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}; 130b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 131b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// A wrapper around STL containers that maintains a stack-sized buffer that the 132b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// initial capacity of the vector is based on. Growing the container beyond the 133b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// stack capacity will transparently overflow onto the heap. The container must 134b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// support reserve(). 135b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// 136b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// WATCH OUT: the ContainerType MUST use the proper StackAllocator for this 137b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// type. This object is really intended to be used only internally. You'll want 138b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// to use the wrappers below for different types. 139b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erattemplate<typename TContainerType, int stack_capacity> 140b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratclass StackContainer { 141b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat public: 142b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat typedef TContainerType ContainerType; 143b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat typedef typename ContainerType::value_type ContainedType; 144b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat typedef StackAllocator<ContainedType, stack_capacity> Allocator; 145b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 146b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // Allocator must be constructed before the container! 147b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat StackContainer() : allocator_(&stack_data_), container_(allocator_) { 148b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // Make the container use the stack allocation by reserving our buffer size 149b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // before doing anything else. 150b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat container_.reserve(stack_capacity); 151b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 152b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 153b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // Getters for the actual container. 154b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // 155b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // Danger: any copies of this made using the copy constructor must have 156b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // shorter lifetimes than the source. The copy will share the same allocator 157b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // and therefore the same stack buffer as the original. Use std::copy to 158b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // copy into a "real" container for longer-lived objects. 159b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat ContainerType& container() { return container_; } 160b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat const ContainerType& container() const { return container_; } 161b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 162b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // Support operator-> to get to the container. This allows nicer syntax like: 163b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // StackContainer<...> foo; 164b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // std::sort(foo->begin(), foo->end()); 165b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat ContainerType* operator->() { return &container_; } 166b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat const ContainerType* operator->() const { return &container_; } 167b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 168b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#ifdef UNIT_TEST 169b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // Retrieves the stack source so that that unit tests can verify that the 170b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // buffer is being used properly. 171b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat const typename Allocator::Source& stack_data() const { 172b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return stack_data_; 173b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 174b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#endif 175b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 176b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat protected: 177b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat typename Allocator::Source stack_data_; 178b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat Allocator allocator_; 179b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat ContainerType container_; 180b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 181b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat private: 182b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat DISALLOW_COPY_AND_ASSIGN(StackContainer); 183b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}; 184b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 185b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// StackString ----------------------------------------------------------------- 186b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 187b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erattemplate<size_t stack_capacity> 188b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratclass StackString : public StackContainer< 189b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat std::basic_string<char, 190b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat std::char_traits<char>, 191b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat StackAllocator<char, stack_capacity> >, 192b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat stack_capacity> { 193b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat public: 194b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat StackString() : StackContainer< 195b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat std::basic_string<char, 196b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat std::char_traits<char>, 197b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat StackAllocator<char, stack_capacity> >, 198b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat stack_capacity>() { 199b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 200b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 201b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat private: 202b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat DISALLOW_COPY_AND_ASSIGN(StackString); 203b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}; 204b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 205b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// StackStrin16 ---------------------------------------------------------------- 206b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 207b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erattemplate<size_t stack_capacity> 208b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratclass StackString16 : public StackContainer< 209b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat std::basic_string<char16, 210b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat base::string16_char_traits, 211b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat StackAllocator<char16, stack_capacity> >, 212b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat stack_capacity> { 213b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat public: 214b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat StackString16() : StackContainer< 215b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat std::basic_string<char16, 216b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat base::string16_char_traits, 217b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat StackAllocator<char16, stack_capacity> >, 218b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat stack_capacity>() { 219b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 220b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 221b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat private: 222b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat DISALLOW_COPY_AND_ASSIGN(StackString16); 223b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}; 224b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 225b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// StackVector ----------------------------------------------------------------- 226b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 227b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// Example: 228b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// StackVector<int, 16> foo; 229b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// foo->push_back(22); // we have overloaded operator-> 230b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// foo[0] = 10; // as well as operator[] 231b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erattemplate<typename T, size_t stack_capacity> 232b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratclass StackVector : public StackContainer< 233b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat std::vector<T, StackAllocator<T, stack_capacity> >, 234b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat stack_capacity> { 235b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat public: 236b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat StackVector() : StackContainer< 237b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat std::vector<T, StackAllocator<T, stack_capacity> >, 238b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat stack_capacity>() { 239b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 240b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 241b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // We need to put this in STL containers sometimes, which requires a copy 242b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // constructor. We can't call the regular copy constructor because that will 243b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // take the stack buffer from the original. Here, we create an empty object 244b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // and make a stack buffer of its own. 245b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat StackVector(const StackVector<T, stack_capacity>& other) 246b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat : StackContainer< 247b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat std::vector<T, StackAllocator<T, stack_capacity> >, 248b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat stack_capacity>() { 249b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat this->container().assign(other->begin(), other->end()); 250b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 251b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 252b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat StackVector<T, stack_capacity>& operator=( 253b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat const StackVector<T, stack_capacity>& other) { 254b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat this->container().assign(other->begin(), other->end()); 255b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return *this; 256b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 257b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 258b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // Vectors are commonly indexed, which isn't very convenient even with 259b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // operator-> (using "->at()" does exception stuff we don't want). 260b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat T& operator[](size_t i) { return this->container().operator[](i); } 261b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat const T& operator[](size_t i) const { 262b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return this->container().operator[](i); 263b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 264b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}; 265b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 266b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} // namespace base 267b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 268b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#endif // BASE_CONTAINERS_STACK_CONTAINER_H_ 269