STL vector

/*
*
* Copyright (c) 2016 hujian.
* Permission to use, copy, modify, distribute and sell this software
* and its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies and
* that both that copyright notice and this permission notice appear
* in supporting documentation.  Silicon Graphics makes no
* representations about the suitability of this software for any
* purpose.  It is provided "as is" without express or implied warranty.
* This is the sgi stl's construct,but i can use it in my peoject.
* Author:hujian
* Time:2016/4/12
*/
#ifndef _HJ_STL_VECTOR_H_
#define _HJ_STL_VECTOR_H_

#include "hjstl_alloc.h"
#include "hjstl_iterator.h"
#include "hjstl_construct.h"
#include "hjstl_uninitialized.h"

#define _HJSTL_VECTOR_PUBLIC_  public
#define _HJSTL_VECTOR_PRIVATE_ private 
#define _HJSTL_VECTOR_PROTECTED_ protected


//i will use the second allocate.you can use yourself allocate.
template<class Type,class Alloc=HJSTL_Alloc::HJSTL_Allocate_default>
class _HJSTL_vector{
_HJSTL_VECTOR_PUBLIC_://the follow typedefs is for traits.
	typedef Type   hjstl_value_type;
	typedef hjstl_value_type* hjstl_pointer;
	typedef const hjstl_value_type* hjstl_const_pointer;
	typedef hjstl_value_type* hjstl_iterator;
	typedef const hjstl_value_type* hjstl_const_iterator;
	typedef hjstl_value_type& hjstl_reference;
	typedef const hjstl_value_type& hjstl_const_reference;
	typedef size_t   hjstl_size_type;
	typedef ptrdiff_t hjstl_difference_type;


	//the vector will use the follow allocate to alloc
	typedef HJSTL_Alloc::HJSTL_Allocate_default vector_alloc;

	//the range of vector.
	hjstl_iterator start;
	hjstl_iterator finish;
	hjstl_iterator end_of_storage;

_HJSTL_VECTOR_PROTECTED_:
	//insert aux.
	void insert_aux(hjstl_iterator position, const Type& value);
	//allocate and fill
	hjstl_iterator allocate_and_fill(hjstl_size_type size, const Type& value)
	{
		//use second level allocate to alloc memory.
		hjstl_iterator result = vector_alloc::hjstl_allocate(size);
		try{
			hjstl_uninitialized_fill_n(result, size, value);
			return result;
		}
		catch(...){//if error,deallocate
			vector_alloc::hjstl_deallocate(result, size);
		}
	}
	//allocate and copy
	hjstl_iterator allocate_and_copy(hjstl_size_type size, 
		hjstl_const_iterator first, hjstl_const_iterator last)
	{
		hjstl_iterator result = vector_alloc::hjstl_allocate(size);
		try{
			hjstl_uninitialized_copy(first, last, result);
			return result;
		}
		catch (...){
			vector_alloc::hjstl_deallocate(result, size);
		}
	}

	//range initialze
	template<class ForwardIterator>
	void range_initialze(ForwardIterator first, ForwardIterator last, hjstl_forward_iterator_tag)
	{
		hjstl_size_type size = 0;
		hjstl_distance(first, last, size);
		start = allocate_and_copy(size, first, last);
		finish = start + size;
		end_of_storage = finish;
	}
_HJSTL_VECTOR_PUBLIC_:
	//deallocate.
	void deallocate(){
		if (start){
			vector_alloc::hjstl_deallocate(start, end_of_storage - start);
		}
	}

	//initialize the vector
	void fill_initialze(hjstl_size_type size, const Type& value)
	{
		start = allocate_and_fill(size, value);
		finish = start + size;
		end_of_storage = finish;//this is the limit we can reach now.
	}

	//////about iterztor operation//////
	hjstl_iterator begin(){ return start; }
	//hjstl_const_iterator begin(){ return start; }

	hjstl_iterator end(){ return finish; }
	//hjstl_const_iterator end(){ return finish; }

	//get the elements
	hjstl_reference front(){ return *begin(); }
	//hjstl_const_reference front() const{ return *begin(); }

	hjstl_reference  back(){ return *(end() - 1); }
	//hjstl_const_reference back() const{ return *(end() - 1); }


	//get the size.
	hjstl_size_type size(){ return hjstl_size_type(end() -begin()); }
	//the max size
	hjstl_size_type max_size(){ return hjstl_size_type(-1) / sizeof(Type); }
	//capcity of this vector
	hjstl_size_type capcity(){ return hjstl_size_type(end_of_storage - begin()); }
	//whether this vector is empty
	bool empty(){ return begin() == end(); }

	//overload implements
	hjstl_reference operator[](hjstl_size_type index){
		return *(begin() + index);
	}

	hjstl_const_reference operator[](hjstl_size_type index) const{
		return *(begin() + index);
	}

	///////the constructor///////////////
	_HJSTL_vector() {
		start = 0;
		finish = 0;
		end_of_storage = 0;
	}

	_HJSTL_vector(hjstl_size_type size, const Type&value){
		fill_initialze(size, value);
	}

	_HJSTL_vector(int n, const Type& value){
		fill_initialze(size, value);
	}

	_HJSTL_vector(hjstl_size_type size){
		fill_initialze(size, Type());
	}

	_HJSTL_vector(const _HJSTL_vector<Type, Alloc>& vec){
		start = allocate_and_fill(vec.end() - vec.begin(), vec.begin(), vec.end());
		finish = start + (vec.end() - vec.begin());
		end_of_storage = finish;
	}
	/////////////////////////////////////

	//operator =
	_HJSTL_vector<Type, Alloc>& operator =(const _HJSTL_vector<Type, Alloc>&vec);

	//reserve the vector
	void reserve(hjstl_size_type size)
	{
		if (capcity < size){//if the capcity is not so enough,just alloc
			const hjstl_size_type old_size = size();
			//new storage allocate.
			hjstl_iterator storage=allocate_and_copy(size,start,finish);
			//deallocate the src memory,and update the storage.
			deallocate();
			start = storage;
			finish = storage + size;
			end_of_storage = start + size;
		}
		//else,do nothing.
	}

	//some operators.
_HJSTL_VECTOR_PUBLIC_:
	//push back an element into this vector.
	void push_back(const Type& value){
		if (finish != end_of_storage){//whether left memory?
			//if left memory,just do it.
			construct(finish, value);
			++finish;
		}
		else{//no memory,need to re-alloc
			insert_aux(end(), value);
		}
	}

	//you want to swap two vector..
	void swap(_HJSTL_vector<Type, Alloc>& vec){
		std::swap(start, vec.start);
		std::swap(finish, vec.finish);
		std::swap(end_of_storage, vec.end_of_storage);
	}

	//you want to insert an element to position,the value is 'value'
	hjstl_iterator insert(hjstl_iterator position, const Type& value)
	{
		if (finish != end_of_storage&&position == end()){//you want to push_back.
			construct(finish, value);
			++finish;
		}
		else{//you need to insert the mid..
			insert_aux(position, value);
		}
		//return the iterator
		return (begin() + hjstl_size_type(position - begin()));
	}

	//other insert,but no initialze
	hjstl_iterator insert(hjstl_iterator position)
	{
		return insert(position, T());
	}

	//you also can insert like this
	void insert(hjstl_iterator position, hjstl_size_type size, const Type& v);

	//partial.
	void insert(hjstl_iterator position, int n, const Type& value){
		insert(position, n, value);
	}

	//pop back.
	void pop_back(){
		//easy to do this
		--finish;
		destroy(finish);
	}
	//you want to earse an object in vector
	//no use but return the position you give me.
	hjstl_iterator earse(hjstl_iterator position){
		if (position + 1 != end()){//you delete element actually.
			copy(position + 1, finish, position);
		}
		--finish;
		destroy(finish);
		return position;
	}

	//you also can delete an range.
	hjstl_iterator earse(hjstl_iterator first, hjstl_iterator last){
		//the follow will remove the range[first..last]
		//the copy function will copy the [last...finish] to [first..]
		//and return the result.
		hjstl_iterator result = copy(last, finish, first);

		//you need to deallocate the obj
		destroy(result, finish);
		//update the storage
		finish = finish - (last - first);
		return first;
	}

	//you want to resize the vector..
	void resize(hjstl_size_type new_size, const Type& value)
	{
		//if the new size < old size,earse some elements.
		if (new_size < size()){
			earse(begin() + new_size, end());
		}
		//else,the new size >= old size,insert 
		else{
			insert(end(), new_size - size(), value);
		}
	}

	//another resize but not initialze
	void resize(hjstl_size_type size){
		resize(size, Type());
	}

	//clear the vector
	void clear(){
		earse(begin(), end());
	}
};//end of vector

//the operator ==
template<class Type,class Alloc>
inline bool operator ==(const _HJSTL_vector<Type, Alloc>& x, const _HJSTL_vector<Type, Alloc>& y)
{
	return x.size() == y.size() &&
		equal(x.begin(), x.end(), y.begin());
}

//operator <
template<class Type,class Alloc>
inline bool operator <(const _HJSTL_vector<Type, Alloc>& x, const _HJSTL_vector<Type, Alloc>& y)
{
	return lexicographical_compare(x.begin(), x.end(), y.begin(), y.end());
}

//swap
template<class Type,class Alloc>
inline void swap(const _HJSTL_vector<Type, Alloc>& x, const _HJSTL_vector<Type, Alloc>& y){
	x.swap(y);
}

//implement.
template<class Type,class Alloc>
_HJSTL_vector<Type, Alloc>& _HJSTL_vector<Type, Alloc>::operator=(const _HJSTL_vector<Type, Alloc>& x)
{
	//if the capcity is not enough.we need to alloc.
	if (x.size() > capcity){
		hjstl_iterator result = allocate_and_copy(x.end() - x.begin(), x.begin(), x.end());
		//destory old mem
		destroy(start, finish);
		deallocate();
		//reset the storage
		start = result;
		end_of_storage = start + (x.end() - x.begin());
	}
	//else if the capcity is enough
	else if (size() >= x.size()){
		hjstl_iterator result = copy(x.begin(), x.end(), begin());
		//destory the left 
		destroy(result, finish);
	}
	else{//can append.
		//copy first
		copy(x.begin(), x.begin() + size(), start);
		//copy the left
		hjstl_uninitialized_copy(x.begin() + size(), x.end(), finish);
	}
	//reset the finish
	finish = start + x.size();
	return *this;
}

//aux_insert
template<class Type,class Alloc>
void _HJSTL_vector<Type, Alloc>::insert_aux(hjstl_iterator position, const Type& value)
{
	//still left memory can use
	if (finish != end_of_storage){
		construct(finish, *(finish - 1));
		++finish;
		Type copy_v = value;
		//copy from back to front.
		//copy_backward(start,end,dststart)
		//[start..end]-> start....end
		//you should know the update of finish.
		//before construct,the structure is like this:
		//  ...[x][x][x][x].[finish]......[end_of_starage]
		//the finish is no data,finish-1 is the last data position.
		//after construct the structure change to this:
		//  ...[x][x][x][x].[x][finish]...[end_of_storage]
		//so,the last data's position is finish-2.
		//so,you can understand now.

		copy_backward(position, finish - 2, finish - 1);

		//let the position's value as copy_v
		*position = copy_v;
	}
	else{//no memory.
		const hjstl_size_type old_size = size();
		//2*old_size is needed.
		const hjstl_size_type len = old_size != 0 ? 2 * old_size : 1;
		//use the second allocate to alloc the new memory from memory pool.
		hjstl_iterator new_start =(Type*)vector_alloc::hjstl_allocate(len);

		hjstl_iterator new_finish = new_start;
		//what we want to do is like this.
		try{
			new_finish = hjstl_uninitialized_copy(start, position, new_start);
			construct(new_finish, value);
			++new_finish;
			new_finish = hjstl_uninitialized_copy(position, finish, new_finish);
		}
		catch (...){
			//if error.destroy the memory.
			destroy(new_start, new_finish);
			vector_alloc::hjstl_deallocate(new_start, len);
		}
		//destory the old mem
		destroy(begin(), end());
		deallocate();
		//reset the start and finish and storage
		start = new_start;
		finish = new_finish;
		end_of_storage = new_start + len;
	}
}


//from position,insert size elements,and the start value is v
template<class Type,class Alloc>
void _HJSTL_vector<Type, Alloc>::insert(hjstl_iterator position, hjstl_size_type size, const Type& v)
{
	//if size==0,no use.
	if (0 != size){
		//the memory is so enough.just insert these elements
		if (hjstl_size_type(end_of_storage - finish) >= size){
			Type copy_v = v;
			const hjstl_size_type elements_after = finish - position;
			hjstl_iterator old_finish = finish;
			//the elements after position's num > the new elements
			if (elements_after > size){
				hjstl_uninitialized_copy(finish - size, finish, finish);
				finish += size;

				copy_backward(position, old_finish - size, old_finish);

				//fill the new elements
				fill(position, position + size, copy_v);
			}
			else{//the elements after position's num < the new elements
				hjstl_uninitialized_fill_n(finish, size - elements_after, copy_v);
				finish += (size - elements_after);
				hjstl_uninitialized_copy(position, old_finish, finish);
				finish += (elements_after);
				fill(position, old_finish, copy_v);
			}
		}//end of memory enough
		else{//the left memory is not enough to alloc
			//then,we need to re-alloc the new memory,the new alloc length is the 2*oldsize
			const hjstl_size_type old_size = old_size();
			const hjstl_size_type len = old_size+max(old_size,n);

			//alloc new vector space
			hjstl_iterator   new_start = vector_alloc::hjstl_allocate(len);
			hjstl_iterator   new_finish = new_start;
			//copy old data to new space,then insert new elements
			new_finish = hjstl_uninitialized_copy(start, position, new_start);
			new_finish = hjstl_uninitialized_fill_n(new_finish, n, v);
			new_finish = hjstl_uninitialized_copy(position, finish, new_finish);
			//free the old memory
			destroy(start, finish);
			deallocate();
			//reset the start and finsih
			start = new_start;
			finish = new_finish;
			end_of_storage = new_start + len; //this is the memory we can use.
		}
	}
}

#endif  //end of _HJ_STL_VECTOR_H_

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章