clang API Documentation

UsuallyTinyPtrVector.h
Go to the documentation of this file.
00001 //===-- UsuallyTinyPtrVector.h - Pointer vector class -----------*- C++ -*-===//
00002 //
00003 //                     The LLVM Compiler Infrastructure
00004 //
00005 // This file is distributed under the University of Illinois Open Source
00006 // License. See LICENSE.TXT for details.
00007 //
00008 //===----------------------------------------------------------------------===//
00009 //
00010 //  This file defines the UsuallyTinyPtrVector class, which is a vector that
00011 //  optimizes the case where there is only one element.
00012 //
00013 //===----------------------------------------------------------------------===//
00014 
00015 #ifndef LLVM_CLANG_AST_USUALLY_TINY_PTR_VECTOR_H
00016 #define LLVM_CLANG_AST_USUALLY_TINY_PTR_VECTOR_H
00017 
00018 #include <vector>
00019 
00020 namespace clang {
00021 
00022 /// \brief A vector class template that is optimized for storing a single 
00023 /// pointer element.
00024 template<typename T>
00025 class UsuallyTinyPtrVector {
00026   /// \brief Storage for the vector.
00027   ///
00028   /// When the low bit is zero, this is a T *. When the
00029   /// low bit is one, this is a std::vector<T *> *.
00030   mutable uintptr_t Storage;
00031 
00032   typedef std::vector<T*> vector_type;
00033 
00034 public:
00035   UsuallyTinyPtrVector() : Storage(0) { }
00036   explicit UsuallyTinyPtrVector(T *Element) 
00037     : Storage(reinterpret_cast<uintptr_t>(Element)) { }
00038   
00039   bool empty() const { return !Storage; }
00040 
00041   typedef const T **iterator;
00042   iterator begin() const;
00043   iterator end() const;
00044   size_t size() const;
00045 
00046   void push_back(T *Method);
00047   void Destroy();
00048 };
00049 
00050 template<typename T>
00051 typename UsuallyTinyPtrVector<T>::iterator 
00052 UsuallyTinyPtrVector<T>::begin() const {
00053   if ((Storage & 0x01) == 0)
00054     return reinterpret_cast<iterator>(&Storage);
00055 
00056   vector_type *Vec = reinterpret_cast<vector_type *>(Storage & ~0x01);
00057   return &Vec->front();
00058 }
00059 
00060 template<typename T>
00061 typename UsuallyTinyPtrVector<T>::iterator 
00062 UsuallyTinyPtrVector<T>::end() const {
00063   if ((Storage & 0x01) == 0) {
00064     if (Storage == 0)
00065       return reinterpret_cast<iterator>(&Storage);
00066 
00067     return reinterpret_cast<iterator>(&Storage) + 1;
00068   }
00069 
00070   vector_type *Vec = reinterpret_cast<vector_type *>(Storage & ~0x01);
00071   return &Vec->front() + Vec->size();
00072 }
00073 
00074 template<typename T>
00075 size_t UsuallyTinyPtrVector<T>::size() const {
00076   if ((Storage & 0x01) == 0)
00077     return (Storage == 0) ? 0 : 1;
00078 
00079   vector_type *Vec = reinterpret_cast<vector_type *>(Storage & ~0x01);
00080   return Vec->size();
00081 }
00082 
00083 template<typename T>
00084 void UsuallyTinyPtrVector<T>::push_back(T *Element) {
00085   if (Storage == 0) {
00086     // 0 -> 1 element.
00087     Storage = reinterpret_cast<uintptr_t>(Element);
00088     return;
00089   }
00090 
00091   vector_type *Vec;
00092   if ((Storage & 0x01) == 0) {
00093     // 1 -> 2 elements. Allocate a new vector and push the element into that
00094     // vector.
00095     Vec = new vector_type;
00096     Vec->push_back(reinterpret_cast<T *>(Storage));
00097     Storage = reinterpret_cast<uintptr_t>(Vec) | 0x01;
00098   } else
00099     Vec = reinterpret_cast<vector_type *>(Storage & ~0x01);
00100 
00101   // Add the new element to the vector.
00102   Vec->push_back(Element);
00103 }
00104 
00105 template<typename T>
00106 void UsuallyTinyPtrVector<T>::Destroy() {
00107   if (Storage & 0x01)
00108     delete reinterpret_cast<vector_type *>(Storage & ~0x01);
00109   
00110   Storage = 0;
00111 }
00112 
00113 }
00114 #endif