forked from OSchip/llvm-project
				
			
		
			
				
	
	
		
			178 lines
		
	
	
		
			3.9 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			178 lines
		
	
	
		
			3.9 KiB
		
	
	
	
		
			C++
		
	
	
	
| // RUN: %clangxx -emit-llvm -c -o - %s
 | |
| #include <stddef.h>
 | |
| #include <stdlib.h>
 | |
| #include <assert.h>
 | |
| 
 | |
| // Placement new requires <new> to be included, but we don't support that yet.
 | |
| void* operator new(size_t, void* ptr) throw() {
 | |
|   return ptr;
 | |
| }
 | |
| void operator delete(void*, void*) throw() {
 | |
| }
 | |
| 
 | |
| template<typename T>
 | |
| class dynarray {
 | |
| public:
 | |
|   dynarray() { Start = Last = End = 0; }
 | |
| 
 | |
|   dynarray(const dynarray &other) {
 | |
|     Start = (T*)malloc(sizeof(T) * other.size());
 | |
|     Last = End = Start + other.size();
 | |
| 
 | |
|     for (unsigned I = 0, N = other.size(); I != N; ++I)
 | |
|       new (Start + I) T(other[I]);
 | |
|   }
 | |
|   
 | |
|   ~dynarray() {
 | |
|     for (unsigned I = 0, N = size(); I != N; ++I)
 | |
|       Start[I].~T();
 | |
|     
 | |
|     free(Start);
 | |
|   }
 | |
| 
 | |
|   dynarray &operator=(const dynarray &other) {
 | |
|     T* NewStart = (T*)malloc(sizeof(T) * other.size());
 | |
| 
 | |
|     for (unsigned I = 0, N = other.size(); I != N; ++I)
 | |
|       new (NewStart + I) T(other[I]);
 | |
| 
 | |
|     for (unsigned I = 0, N = size(); I != N; ++I)
 | |
|       Start[I].~T();
 | |
|     
 | |
|     free(Start);
 | |
|     Start = NewStart;
 | |
|     Last = End = NewStart + other.size();
 | |
|     return *this;
 | |
|   }
 | |
| 
 | |
|   unsigned size() const { return Last - Start; }
 | |
|   unsigned capacity() const { return End - Start; }
 | |
| 
 | |
|   void push_back(const T& value);
 | |
|   
 | |
|   void pop_back() {
 | |
|     --Last;
 | |
|     Last->~T();
 | |
|   }
 | |
| 
 | |
|   T& operator[](unsigned Idx) {
 | |
|     return Start[Idx];
 | |
|   }
 | |
| 
 | |
|   const T& operator[](unsigned Idx) const {
 | |
|     return Start[Idx];
 | |
|   }
 | |
| 
 | |
|   typedef T* iterator;
 | |
|   typedef const T* const_iterator;
 | |
| 
 | |
|   iterator begin() { return Start; }
 | |
|   const_iterator begin() const { return Start; }
 | |
|   
 | |
|   iterator end() { return Last; }
 | |
|   const_iterator end() const { return Last; }
 | |
|   
 | |
|   bool operator==(const dynarray &other) const {
 | |
|     if (size() != other.size())
 | |
|       return false;
 | |
|     
 | |
|     for (unsigned I = 0, N = size(); I != N; ++I)
 | |
|       if ((*this)[I] != other[I])
 | |
|         return false;
 | |
|     
 | |
|     return true;
 | |
|   }
 | |
|   
 | |
|   bool operator!=(const dynarray &other) const {
 | |
|     return !(*this == other);
 | |
|   }
 | |
|   
 | |
| public:
 | |
|   T* Start, *Last, *End;
 | |
| };
 | |
| 
 | |
| template<typename T>
 | |
| void dynarray<T>::push_back(const T& value) {
 | |
|   if (Last == End) {
 | |
|     unsigned NewCapacity = capacity() * 2;
 | |
|     if (NewCapacity == 0)
 | |
|       NewCapacity = 4;
 | |
|     
 | |
|     T* NewStart = (T*)malloc(sizeof(T) * NewCapacity);
 | |
|     
 | |
|     unsigned Size = size();
 | |
|     for (unsigned I = 0; I != Size; ++I)
 | |
|       new (NewStart + I) T(Start[I]);
 | |
|     
 | |
|     for (unsigned I = 0, N = size(); I != N; ++I)
 | |
|       Start[I].~T();
 | |
|     free(Start);
 | |
|     
 | |
|     Start = NewStart;
 | |
|     Last = Start + Size;
 | |
|     End = Start + NewCapacity;
 | |
|   }
 | |
|   
 | |
|   new (Last) T(value);
 | |
|   ++Last;
 | |
| }
 | |
| 
 | |
| struct Point { 
 | |
|   Point() { x = y = z = 0.0; }
 | |
|   Point(const Point& other) : x(other.x), y(other.y), z(other.z) { }
 | |
| 
 | |
|   float x, y, z;
 | |
| };
 | |
| 
 | |
| int main() {
 | |
|   dynarray<int> di;
 | |
|   di.push_back(0);
 | |
|   di.push_back(1);
 | |
|   di.push_back(2);
 | |
|   di.push_back(3);
 | |
|   di.push_back(4);
 | |
|   assert(di.size() == 5);
 | |
|   for (dynarray<int>::iterator I = di.begin(), IEnd = di.end(); I != IEnd; ++I)
 | |
|     assert(*I == I - di.begin());
 | |
| 
 | |
|   for (int I = 0, N = di.size(); I != N; ++I)
 | |
|     assert(di[I] == I);
 | |
| 
 | |
|   di.pop_back();
 | |
|   assert(di.size() == 4);
 | |
|   di.push_back(4);
 | |
| 
 | |
|   dynarray<int> di2 = di;
 | |
|   assert(di2.size() == 5);
 | |
|   assert(di.begin() != di2.begin());
 | |
|   for (dynarray<int>::iterator I = di2.begin(), IEnd = di2.end(); 
 | |
|        I != IEnd; ++I)
 | |
|     assert(*I == I - di2.begin());
 | |
| 
 | |
|   dynarray<int> di3(di);
 | |
|   assert(di3.size() == 5);
 | |
|   assert(di.begin() != di3.begin());
 | |
|   for (dynarray<int>::iterator I = di3.begin(), IEnd = di3.end(); 
 | |
|        I != IEnd; ++I)
 | |
|     assert(*I == I - di3.begin());
 | |
| 
 | |
|   dynarray<int> di4;
 | |
|   assert(di4.size() == 0);
 | |
|   di4 = di;
 | |
|   assert(di4.size() == 5);
 | |
|   assert(di.begin() != di4.begin());
 | |
|   for (dynarray<int>::iterator I = di4.begin(), IEnd = di4.end(); 
 | |
|        I != IEnd; ++I)
 | |
|     assert(*I == I - di4.begin());
 | |
| 
 | |
|   assert(di4 == di);
 | |
|   di4[3] = 17;
 | |
|   assert(di4 != di);
 | |
|   
 | |
|   dynarray<Point> dp;
 | |
|   dp.push_back(Point());
 | |
|   assert(dp.size() == 1);
 | |
|   
 | |
|   return 0;
 | |
| }
 |