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