15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2011 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 COURGETTE_MEMORY_ALLOCATOR_H_
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define COURGETTE_MEMORY_ALLOCATOR_H_
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <memory>
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/basictypes.h"
112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/files/file_path.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/platform_file.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef NDEBUG
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// A helper class to track down call sites that are not handling error cases.
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template<class T>
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class CheckReturnValue {
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Not marked explicit on purpose.
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CheckReturnValue(T value) : value_(value), checked_(false) {  // NOLINT
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CheckReturnValue(const CheckReturnValue& other)
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : value_(other.value_), checked_(other.checked_) {
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    other.checked_ = true;
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CheckReturnValue& operator=(const CheckReturnValue& other) {
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (this != &other) {
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DCHECK(checked_);
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      value_ = other.value_;
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      checked_ = other.checked_;
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      other.checked_ = true;
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ~CheckReturnValue() {
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(checked_);
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  operator const T&() const {
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    checked_ = true;
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return value_;
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  T value_;
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  mutable bool checked_;
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef CheckReturnValue<bool> CheckBool;
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef bool CheckBool;
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace courgette {
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if defined(OS_WIN)
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Manages a temporary file.  The file is created in the %TEMP% folder and
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// is deleted when the file handle is closed.
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// NOTE: Since the file will be used as backing for a memory allocation,
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// it will never be so big that size_t cannot represent its size.
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class TempFile {
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TempFile();
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ~TempFile();
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool Create();
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void Close();
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool SetSize(size_t size);
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Returns true iff the temp file is currently open.
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool valid() const;
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Returns the handle of the temporary file or INVALID_HANDLE_VALUE if
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // a temp file has not been created.
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::PlatformFile handle() const;
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected:
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::PlatformFile file_;
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Manages a read/write virtual mapping of a physical file.
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class FileMapping {
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FileMapping();
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ~FileMapping();
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Map a file from beginning to |size|.
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool Create(HANDLE file, size_t size);
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void Close();
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Returns true iff a mapping has been created.
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool valid() const;
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Returns a writable pointer to the beginning of the memory mapped file.
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If Create has not been called successfully, return value is NULL.
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void* view() const;
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected:
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool InitializeView(size_t size);
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HANDLE mapping_;
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void* view_;
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Manages a temporary file and a memory mapping of the temporary file.
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The memory that this class manages holds a pointer back to the TempMapping
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// object itself, so that given a memory pointer allocated by this class,
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// you can get a pointer to the TempMapping instance that owns that memory.
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class TempMapping {
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TempMapping();
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ~TempMapping();
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Creates a temporary file of size |size| and maps it into the current
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // process's address space.
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool Initialize(size_t size);
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Returns a writable pointer to the reserved memory.
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void* memory() const;
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Returns true if the mapping is valid and memory is available.
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool valid() const;
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Returns a pointer to the TempMapping instance that allocated the |mem|
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // block of memory.  It's the callers responsibility to make sure that
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the memory block was allocated by the TempMapping class.
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static TempMapping* GetMappingFromPtr(void* mem);
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected:
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TempFile file_;
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FileMapping mapping_;
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// A memory allocator class that allocates memory either from the heap or via a
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// temporary file.  The interface is STL inspired but the class does not throw
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// STL exceptions on allocation failure.  Instead it returns NULL.
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// A file allocation will be made if either the requested memory size exceeds
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// |kMaxHeapAllocationSize| or if a heap allocation fails.
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Allocating the memory as a mapping of a temporary file solves the problem
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// that there might not be enough physical memory and pagefile to support the
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// allocation.  This can happen because these resources are too small, or
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// already committed to other processes.  Provided there is enough disk, the
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// temporary file acts like a pagefile that other processes can't access.
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template<class T>
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class MemoryAllocator {
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  typedef T value_type;
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  typedef value_type* pointer;
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  typedef value_type& reference;
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  typedef const value_type* const_pointer;
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  typedef const value_type& const_reference;
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  typedef size_t size_type;
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  typedef ptrdiff_t difference_type;
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Each allocation is tagged with a single byte so that we know how to
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // deallocate it.
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  enum AllocationType {
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    HEAP_ALLOCATION,
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    FILE_ALLOCATION,
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // 5MB is the maximum heap allocation size that we'll attempt.
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // When applying a patch for Chrome 10.X we found that at this
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // threshold there were 17 allocations higher than this threshold
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // (largest at 136MB) 10 allocations just below the threshold and 6362
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // smaller allocations.
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const size_t kMaxHeapAllocationSize = 1024 * 1024 * 5;
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  template<class OtherT>
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  struct rebind {
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // convert a MemoryAllocator<T> to a MemoryAllocator<OtherT>
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    typedef MemoryAllocator<OtherT> other;
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MemoryAllocator() _THROW0() {
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We can't use an explicit constructor here, as dictated by our style guide.
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The implementation of basic_string in Visual Studio 2010 prevents this.
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MemoryAllocator(const MemoryAllocator<T>& other) _THROW0() {  // NOLINT
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  template<class OtherT>
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MemoryAllocator(const MemoryAllocator<OtherT>& other) _THROW0() {  // NOLINT
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ~MemoryAllocator() {
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void deallocate(pointer ptr, size_type size) {
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    uint8* mem = reinterpret_cast<uint8*>(ptr);
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    mem -= sizeof(T);
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (mem[0] == HEAP_ALLOCATION) {
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      delete [] mem;
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DCHECK_EQ(static_cast<uint8>(FILE_ALLOCATION), mem[0]);
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      TempMapping* mapping = TempMapping::GetMappingFromPtr(mem);
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      delete mapping;
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pointer allocate(size_type count) {
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We use the first byte of each allocation to mark the allocation type.
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // However, so that the allocation is properly aligned, we allocate an
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // extra element and then use the first byte of the first element
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // to mark the allocation type.
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    count++;
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (count > max_size())
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return NULL;
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    size_type bytes = count * sizeof(T);
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    uint8* mem = NULL;
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // First see if we can do this allocation on the heap.
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (count < kMaxHeapAllocationSize)
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      mem = new(std::nothrow) uint8[bytes];
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (mem != NULL) {
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      mem[0] = static_cast<uint8>(HEAP_ALLOCATION);
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // If either the heap allocation failed or the request exceeds the
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // max heap allocation threshold, we back the allocation with a temp file.
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      TempMapping* mapping = new(std::nothrow) TempMapping();
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (mapping && mapping->Initialize(bytes)) {
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        mem = reinterpret_cast<uint8*>(mapping->memory());
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        mem[0] = static_cast<uint8>(FILE_ALLOCATION);
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return mem ? reinterpret_cast<pointer>(mem + sizeof(T)) : NULL;
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pointer allocate(size_type count, const void* hint) {
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return allocate(count);
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void construct(pointer ptr, const T& value) {
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ::new(ptr) T(value);
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void destroy(pointer ptr) {
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ptr->~T();
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_type max_size() const _THROW0() {
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    size_type count = static_cast<size_type>(-1) / sizeof(T);
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return (0 < count ? count : 1);
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else  // OS_WIN
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// On Mac, Linux, we use a bare bones implementation that only does
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// heap allocations.
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template<class T>
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class MemoryAllocator {
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  typedef T value_type;
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  typedef value_type* pointer;
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  typedef value_type& reference;
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  typedef const value_type* const_pointer;
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  typedef const value_type& const_reference;
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  typedef size_t size_type;
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  typedef ptrdiff_t difference_type;
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  template<class OtherT>
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  struct rebind {
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // convert a MemoryAllocator<T> to a MemoryAllocator<OtherT>
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    typedef MemoryAllocator<OtherT> other;
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MemoryAllocator() {
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  explicit MemoryAllocator(const MemoryAllocator<T>& other) {
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  template<class OtherT>
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  explicit MemoryAllocator(const MemoryAllocator<OtherT>& other) {
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ~MemoryAllocator() {
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void deallocate(pointer ptr, size_type size) {
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    delete [] ptr;
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pointer allocate(size_type count) {
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (count > max_size())
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return NULL;
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return reinterpret_cast<pointer>(
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        new(std::nothrow) uint8[count * sizeof(T)]);
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pointer allocate(size_type count, const void* hint) {
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return allocate(count);
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void construct(pointer ptr, const T& value) {
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ::new(ptr) T(value);
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void destroy(pointer ptr) {
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ptr->~T();
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_type max_size() const {
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    size_type count = static_cast<size_type>(-1) / sizeof(T);
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return (0 < count ? count : 1);
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif  // OS_WIN
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Manages a growable buffer.  The buffer allocation is done by the
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// MemoryAllocator class.  This class will not throw exceptions so call sites
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// must be prepared to handle memory allocation failures.
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The interface is STL inspired to avoid having to make too many changes
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// to code that previously was using STL.
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template<typename T, class Allocator = MemoryAllocator<T> >
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class NoThrowBuffer {
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  typedef T value_type;
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const size_t kAllocationFailure = 0xffffffff;
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const size_t kStartSize = sizeof(T) > 0x100 ? 1 : 0x100 / sizeof(T);
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NoThrowBuffer() : buffer_(NULL), size_(0), alloc_size_(0) {
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ~NoThrowBuffer() {
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    clear();
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void clear() {
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (buffer_) {
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      alloc_.deallocate(buffer_, alloc_size_);
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      buffer_ = NULL;
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      size_ = 0;
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      alloc_size_ = 0;
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool empty() const {
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return size_ == 0;
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CheckBool reserve(size_t size) WARN_UNUSED_RESULT {
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (failed())
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (size <= alloc_size_)
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (size < kStartSize)
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      size = kStartSize;
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    T* new_buffer = alloc_.allocate(size);
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!new_buffer) {
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      clear();
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      alloc_size_ = kAllocationFailure;
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (buffer_) {
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        memcpy(new_buffer, buffer_, size_ * sizeof(T));
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        alloc_.deallocate(buffer_, alloc_size_);
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      buffer_ = new_buffer;
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      alloc_size_ = size;
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return !failed();
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CheckBool append(const T* data, size_t size) WARN_UNUSED_RESULT {
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (failed())
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (size > alloc_.max_size() - size_)
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!size)
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if ((alloc_size_ - size_) < size) {
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const size_t max_size = alloc_.max_size();
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      size_t new_size = alloc_size_ ? alloc_size_ : kStartSize;
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      while (new_size < size_ + size) {
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (new_size < max_size - new_size) {
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          new_size *= 2;
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        } else {
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          new_size = max_size;
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!reserve(new_size))
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return false;
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    memcpy(buffer_ + size_, data, size * sizeof(T));
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    size_ += size;
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CheckBool resize(size_t size, const T& init_value) WARN_UNUSED_RESULT {
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (size > size_) {
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!reserve(size))
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return false;
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      for (size_t i = size_; i < size; ++i)
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        buffer_[i] = init_value;
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else if (size < size_) {
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // TODO(tommi): Should we allocate a new, smaller buffer?
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // It might be faster for us to simply change the size.
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    size_ = size;
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CheckBool push_back(const T& item) WARN_UNUSED_RESULT {
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return append(&item, 1);
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const T& back() const {
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return buffer_[size_ - 1];
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  T& back() {
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return buffer_[size_ - 1];
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const T* begin() const {
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!size_)
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return NULL;
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return &buffer_[0];
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  T* begin() {
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!size_)
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return NULL;
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return &buffer_[0];
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const T* end() const {
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!size_)
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return NULL;
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return &buffer_[size_ - 1];
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  T* end() {
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!size_)
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return NULL;
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return &buffer_[size_ - 1];
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const T& operator[](size_t index) const {
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(index < size_);
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return buffer_[index];
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  T& operator[](size_t index) {
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(index < size_);
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return buffer_[index];
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t size() const {
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return size_;
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  T* data() const {
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return buffer_;
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Returns true if an allocation failure has ever occurred for this object.
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool failed() const {
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return alloc_size_ == kAllocationFailure;
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected:
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  T* buffer_;
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t size_;  // how much of the buffer we're using.
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t alloc_size_;  // how much space we have allocated.
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Allocator alloc_;
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace courgette
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif  // COURGETTE_MEMORY_ALLOCATOR_H_
491