clang API Documentation
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