15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef BASE_CONTAINERS_STACK_CONTAINER_H_ 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define BASE_CONTAINERS_STACK_CONTAINER_H_ 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string> 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <vector> 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/basictypes.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/aligned_memory.h" 135e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)#include "base/strings/string16.h" 145e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)#include "build/build_config.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace base { 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This allocator can be used with STL containers to provide a stack buffer 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// from which to allocate memory and overflows onto the heap. This stack buffer 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// would be allocated on the stack and allows us to avoid heap operations in 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// some situations. 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// STL likes to make copies of allocators, so the allocator itself can't hold 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the data. Instead, we make the creator responsible for creating a 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// StackAllocator::Source which contains the data. Copying the allocator 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// merely copies the pointer to this shared source, so all allocators created 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// based on our allocator will share the same stack buffer. 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This stack buffer implementation is very simple. The first allocation that 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// fits in the stack buffer will use the stack buffer. Any subsequent 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// allocations will not use the stack buffer, even if there is unused room. 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This makes it appropriate for array-like containers, but the caller should 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// be sure to reserve() in the container up to the stack buffer size. Otherwise 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the container will allocate a small array which will "use up" the stack 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// buffer. 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template<typename T, size_t stack_capacity> 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class StackAllocator : public std::allocator<T> { 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) typedef typename std::allocator<T>::pointer pointer; 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) typedef typename std::allocator<T>::size_type size_type; 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Backing store for the allocator. The container owner is responsible for 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // maintaining this for as long as any containers using this allocator are 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // live. 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct Source { 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Source() : used_stack_buffer_(false) { 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Casts the buffer in its right type. 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) T* stack_buffer() { return stack_buffer_.template data_as<T>(); } 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const T* stack_buffer() const { 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return stack_buffer_.template data_as<T>(); 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The buffer itself. It is not of type T because we don't want the 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // constructors and destructors to be automatically called. Define a POD 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // buffer of the right size instead. 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::AlignedMemory<sizeof(T[stack_capacity]), ALIGNOF(T)> stack_buffer_; 592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if defined(__GNUC__) && !defined(ARCH_CPU_X86_FAMILY) 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) COMPILE_ASSERT(ALIGNOF(T) <= 16, crbug_115612); 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Set when the stack buffer is used for an allocation. We do not track 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // how much of the buffer is used, only that somebody is using it. 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool used_stack_buffer_; 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Used by containers when they want to refer to an allocator of type U. 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) template<typename U> 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct rebind { 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) typedef StackAllocator<U, stack_capacity> other; 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // For the straight up copy c-tor, we can share storage. 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StackAllocator(const StackAllocator<T, stack_capacity>& rhs) 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : std::allocator<T>(), source_(rhs.source_) { 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // ISO C++ requires the following constructor to be defined, 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // and std::vector in VC++2008SP1 Release fails with an error 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // in the class _Container_base_aux_alloc_real (from <xutility>) 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // if the constructor does not exist. 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // For this constructor, we cannot share storage; there's 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // no guarantee that the Source buffer of Ts is large enough 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // for Us. 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO: If we were fancy pants, perhaps we could share storage 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // iff sizeof(T) == sizeof(U). 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) template<typename U, size_t other_capacity> 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StackAllocator(const StackAllocator<U, other_capacity>& other) 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : source_(NULL) { 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) explicit StackAllocator(Source* source) : source_(source) { 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Actually do the allocation. Use the stack buffer if nobody has used it yet 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // and the size requested fits. Otherwise, fall through to the standard 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // allocator. 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pointer allocate(size_type n, void* hint = 0) { 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (source_ != NULL && !source_->used_stack_buffer_ 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) && n <= stack_capacity) { 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) source_->used_stack_buffer_ = true; 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return source_->stack_buffer(); 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return std::allocator<T>::allocate(n, hint); 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Free: when trying to free the stack buffer, just mark it as free. For 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // non-stack-buffer pointers, just fall though to the standard allocator. 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void deallocate(pointer p, size_type n) { 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (source_ != NULL && p == source_->stack_buffer()) 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) source_->used_stack_buffer_ = false; 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::allocator<T>::deallocate(p, n); 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Source* source_; 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// A wrapper around STL containers that maintains a stack-sized buffer that the 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// initial capacity of the vector is based on. Growing the container beyond the 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// stack capacity will transparently overflow onto the heap. The container must 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// support reserve(). 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// WATCH OUT: the ContainerType MUST use the proper StackAllocator for this 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// type. This object is really intended to be used only internally. You'll want 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// to use the wrappers below for different types. 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template<typename TContainerType, int stack_capacity> 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class StackContainer { 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) typedef TContainerType ContainerType; 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) typedef typename ContainerType::value_type ContainedType; 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) typedef StackAllocator<ContainedType, stack_capacity> Allocator; 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Allocator must be constructed before the container! 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StackContainer() : allocator_(&stack_data_), container_(allocator_) { 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Make the container use the stack allocation by reserving our buffer size 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // before doing anything else. 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) container_.reserve(stack_capacity); 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Getters for the actual container. 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Danger: any copies of this made using the copy constructor must have 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // shorter lifetimes than the source. The copy will share the same allocator 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // and therefore the same stack buffer as the original. Use std::copy to 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // copy into a "real" container for longer-lived objects. 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ContainerType& container() { return container_; } 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const ContainerType& container() const { return container_; } 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Support operator-> to get to the container. This allows nicer syntax like: 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // StackContainer<...> foo; 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // std::sort(foo->begin(), foo->end()); 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ContainerType* operator->() { return &container_; } 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const ContainerType* operator->() const { return &container_; } 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef UNIT_TEST 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Retrieves the stack source so that that unit tests can verify that the 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // buffer is being used properly. 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const typename Allocator::Source& stack_data() const { 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return stack_data_; 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected: 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) typename Allocator::Source stack_data_; 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Allocator allocator_; 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ContainerType container_; 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(StackContainer); 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// StackString ----------------------------------------------------------------- 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template<size_t stack_capacity> 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class StackString : public StackContainer< 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::basic_string<char, 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::char_traits<char>, 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StackAllocator<char, stack_capacity> >, 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) stack_capacity> { 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StackString() : StackContainer< 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::basic_string<char, 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::char_traits<char>, 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StackAllocator<char, stack_capacity> >, 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) stack_capacity>() { 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(StackString); 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// StackStrin16 ---------------------------------------------------------------- 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template<size_t stack_capacity> 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class StackString16 : public StackContainer< 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::basic_string<char16, 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::string16_char_traits, 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StackAllocator<char16, stack_capacity> >, 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) stack_capacity> { 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StackString16() : StackContainer< 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::basic_string<char16, 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::string16_char_traits, 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StackAllocator<char16, stack_capacity> >, 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) stack_capacity>() { 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(StackString16); 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// StackVector ----------------------------------------------------------------- 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Example: 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// StackVector<int, 16> foo; 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// foo->push_back(22); // we have overloaded operator-> 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// foo[0] = 10; // as well as operator[] 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template<typename T, size_t stack_capacity> 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class StackVector : public StackContainer< 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<T, StackAllocator<T, stack_capacity> >, 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) stack_capacity> { 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StackVector() : StackContainer< 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<T, StackAllocator<T, stack_capacity> >, 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) stack_capacity>() { 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We need to put this in STL containers sometimes, which requires a copy 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // constructor. We can't call the regular copy constructor because that will 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // take the stack buffer from the original. Here, we create an empty object 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // and make a stack buffer of its own. 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StackVector(const StackVector<T, stack_capacity>& other) 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : StackContainer< 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<T, StackAllocator<T, stack_capacity> >, 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) stack_capacity>() { 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this->container().assign(other->begin(), other->end()); 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StackVector<T, stack_capacity>& operator=( 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const StackVector<T, stack_capacity>& other) { 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this->container().assign(other->begin(), other->end()); 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return *this; 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Vectors are commonly indexed, which isn't very convenient even with 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // operator-> (using "->at()" does exception stuff we don't want). 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) T& operator[](size_t i) { return this->container().operator[](i); } 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const T& operator[](size_t i) const { 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return this->container().operator[](i); 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace base 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif // BASE_CONTAINERS_STACK_CONTAINER_H_ 259