| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | /*************************************************************************/ | 
					
						
							|  |  |  | /*  list.h                                                               */ | 
					
						
							|  |  |  | /*************************************************************************/ | 
					
						
							|  |  |  | /*                       This file is part of:                           */ | 
					
						
							|  |  |  | /*                           GODOT ENGINE                                */ | 
					
						
							|  |  |  | /*                    http://www.godotengine.org                         */ | 
					
						
							|  |  |  | /*************************************************************************/ | 
					
						
							| 
									
										
										
										
											2016-01-01 11:50:53 -02:00
										 |  |  | /* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur.                 */ | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | /*                                                                       */ | 
					
						
							|  |  |  | /* Permission is hereby granted, free of charge, to any person obtaining */ | 
					
						
							|  |  |  | /* a copy of this software and associated documentation files (the       */ | 
					
						
							|  |  |  | /* "Software"), to deal in the Software without restriction, including   */ | 
					
						
							|  |  |  | /* without limitation the rights to use, copy, modify, merge, publish,   */ | 
					
						
							|  |  |  | /* distribute, sublicense, and/or sell copies of the Software, and to    */ | 
					
						
							|  |  |  | /* permit persons to whom the Software is furnished to do so, subject to */ | 
					
						
							|  |  |  | /* the following conditions:                                             */ | 
					
						
							|  |  |  | /*                                                                       */ | 
					
						
							|  |  |  | /* The above copyright notice and this permission notice shall be        */ | 
					
						
							|  |  |  | /* included in all copies or substantial portions of the Software.       */ | 
					
						
							|  |  |  | /*                                                                       */ | 
					
						
							|  |  |  | /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */ | 
					
						
							|  |  |  | /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */ | 
					
						
							|  |  |  | /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ | 
					
						
							|  |  |  | /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */ | 
					
						
							|  |  |  | /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */ | 
					
						
							|  |  |  | /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */ | 
					
						
							|  |  |  | /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */ | 
					
						
							|  |  |  | /*************************************************************************/ | 
					
						
							|  |  |  | #ifndef GLOBALS_LIST_H
 | 
					
						
							|  |  |  | #define GLOBALS_LIST_H
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "os/memory.h"
 | 
					
						
							| 
									
										
										
										
											2015-02-15 12:38:25 -03:00
										 |  |  | #include "sort.h"
 | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | /**
 | 
					
						
							|  |  |  |  * Generic Templatized Linked List Implementation. | 
					
						
							|  |  |  |  * The implementation differs from the STL one because | 
					
						
							|  |  |  |  * a compatible preallocated linked list can be written | 
					
						
							|  |  |  |  * using the same API, or features such as erasing an element | 
					
						
							|  |  |  |  * from the iterator. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | template <class T,class A=DefaultAllocator> | 
					
						
							|  |  |  | class List { | 
					
						
							|  |  |  | 	struct _Data; | 
					
						
							|  |  |  | public: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	class Element { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	private: | 
					
						
							|  |  |  | 		friend class List<T,A>; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		T value; | 
					
						
							|  |  |  | 		Element* next_ptr; | 
					
						
							|  |  |  | 		Element* prev_ptr; | 
					
						
							|  |  |  | 		_Data *data; | 
					
						
							|  |  |  | 	public: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		/**
 | 
					
						
							|  |  |  | 		 * Get NEXT Element iterator, for constant lists. | 
					
						
							|  |  |  | 		 */ | 
					
						
							|  |  |  | 		_FORCE_INLINE_ const Element* next() const { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			return next_ptr; | 
					
						
							|  |  |  | 		}; | 
					
						
							|  |  |  | 		/**
 | 
					
						
							|  |  |  | 		 * Get NEXT Element iterator, | 
					
						
							|  |  |  | 		 */ | 
					
						
							|  |  |  | 		_FORCE_INLINE_ Element* next() { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			return next_ptr; | 
					
						
							|  |  |  | 		}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		/**
 | 
					
						
							|  |  |  | 		 * Get PREV Element iterator, for constant lists. | 
					
						
							|  |  |  | 		 */ | 
					
						
							|  |  |  | 		_FORCE_INLINE_ const Element* prev() const { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			return prev_ptr; | 
					
						
							|  |  |  | 		}; | 
					
						
							|  |  |  | 		/**
 | 
					
						
							|  |  |  | 		 * Get PREV Element iterator, | 
					
						
							|  |  |  | 		 */ | 
					
						
							|  |  |  | 		_FORCE_INLINE_ Element* prev() { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			return prev_ptr; | 
					
						
							|  |  |  | 		}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		/**
 | 
					
						
							|  |  |  | 		 * * operator, for using as *iterator, when iterators are defined on stack. | 
					
						
							|  |  |  | 		 */ | 
					
						
							|  |  |  | 		_FORCE_INLINE_ const T& operator *() const { | 
					
						
							|  |  |  | 			return value; | 
					
						
							|  |  |  | 		}; | 
					
						
							|  |  |  | 		/**
 | 
					
						
							|  |  |  | 		 * operator->, for using as iterator->, when iterators are defined on stack, for constant lists. | 
					
						
							|  |  |  | 		 */ | 
					
						
							|  |  |  | 		_FORCE_INLINE_ const T* operator->() const { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			return &value; | 
					
						
							|  |  |  | 		}; | 
					
						
							|  |  |  | 		/**
 | 
					
						
							|  |  |  | 		 * * operator, for using as *iterator, when iterators are defined on stack, | 
					
						
							|  |  |  | 		 */ | 
					
						
							|  |  |  | 		_FORCE_INLINE_ T& operator *() { | 
					
						
							|  |  |  | 			return value; | 
					
						
							|  |  |  | 		}; | 
					
						
							|  |  |  | 		/**
 | 
					
						
							|  |  |  | 		 * operator->, for using as iterator->, when iterators are defined on stack, for constant lists. | 
					
						
							|  |  |  | 		 */ | 
					
						
							|  |  |  | 		_FORCE_INLINE_ T* operator->() { | 
					
						
							|  |  |  | 			return &value; | 
					
						
							|  |  |  | 		}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		/**
 | 
					
						
							|  |  |  | 		 * get the value stored in this element. | 
					
						
							|  |  |  | 		 */ | 
					
						
							|  |  |  | 		_FORCE_INLINE_ T& get() { | 
					
						
							|  |  |  | 			return value; | 
					
						
							|  |  |  | 		}; | 
					
						
							|  |  |  | 		/**
 | 
					
						
							|  |  |  | 		 * get the value stored in this element, for constant lists | 
					
						
							|  |  |  | 		 */ | 
					
						
							|  |  |  | 		_FORCE_INLINE_ const T& get() const { | 
					
						
							|  |  |  | 			return value; | 
					
						
							|  |  |  | 		}; | 
					
						
							|  |  |  | 		/**
 | 
					
						
							|  |  |  | 		 * set the value stored in this element. | 
					
						
							|  |  |  | 		 */ | 
					
						
							|  |  |  | 		_FORCE_INLINE_ void set(const T& p_value) { | 
					
						
							|  |  |  | 			value = (T&)p_value; | 
					
						
							|  |  |  |  		}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		void erase() { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			data->erase(this); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		_FORCE_INLINE_ Element() { | 
					
						
							|  |  |  | 			next_ptr = 0; | 
					
						
							|  |  |  | 			prev_ptr = 0; | 
					
						
							|  |  |  | 			data=NULL; | 
					
						
							|  |  |  | 		}; | 
					
						
							|  |  |  | 	}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | private: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	struct _Data { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		Element* first; | 
					
						
							|  |  |  | 		Element* last; | 
					
						
							|  |  |  | 		int size_cache; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		bool erase(const Element* p_I) { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			ERR_FAIL_COND_V(!p_I,false); | 
					
						
							|  |  |  | 			ERR_FAIL_COND_V(p_I->data!=this,false); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			if (first==p_I) { | 
					
						
							|  |  |  | 				first=p_I->next_ptr; | 
					
						
							|  |  |  | 			}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			if (last==p_I) | 
					
						
							|  |  |  | 				last=p_I->prev_ptr; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			if (p_I->prev_ptr) | 
					
						
							|  |  |  | 				p_I->prev_ptr->next_ptr=p_I->next_ptr; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			if (p_I->next_ptr) | 
					
						
							|  |  |  | 				p_I->next_ptr->prev_ptr=p_I->prev_ptr; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			memdelete_allocator<Element,A>( const_cast<Element*>(p_I) ); | 
					
						
							|  |  |  | 			size_cache--; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			return true; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	_Data *_data; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | public: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/**
 | 
					
						
							|  |  |  |  	* return an const iterator to the begining of the list. | 
					
						
							|  |  |  | 	*/ | 
					
						
							|  |  |  | 	_FORCE_INLINE_ const Element* front() const { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		return _data?_data->first:0; | 
					
						
							|  |  |  | 	}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/**
 | 
					
						
							|  |  |  |  	* return an iterator to the begining of the list. | 
					
						
							|  |  |  | 	*/ | 
					
						
							|  |  |  | 	_FORCE_INLINE_ Element* front() { | 
					
						
							|  |  |  | 		return _data?_data->first:0; | 
					
						
							|  |  |  | 	}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/**
 | 
					
						
							|  |  |  |  	* return an const iterator to the last member of the list. | 
					
						
							|  |  |  | 	*/ | 
					
						
							|  |  |  | 	_FORCE_INLINE_ const Element* back() const { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		return _data?_data->last:0; | 
					
						
							|  |  |  | 	}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/**
 | 
					
						
							|  |  |  |  	* return an iterator to the last member of the list. | 
					
						
							|  |  |  | 	*/ | 
					
						
							|  |  |  | 	_FORCE_INLINE_ Element* back() { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		return _data?_data->last:0; | 
					
						
							|  |  |  | 	}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/**
 | 
					
						
							|  |  |  | 	 * store a new element at the end of the list | 
					
						
							|  |  |  | 	 */ | 
					
						
							|  |  |  | 	Element* push_back(const T& value) { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (!_data) { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			_data=memnew_allocator(_Data,A); | 
					
						
							|  |  |  | 			_data->first=NULL; | 
					
						
							|  |  |  | 			_data->last=NULL; | 
					
						
							|  |  |  | 			_data->size_cache=0; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		Element* n = memnew_allocator(Element,A); | 
					
						
							|  |  |  | 		n->value = (T&)value; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		n->prev_ptr=_data->last; | 
					
						
							|  |  |  | 		n->next_ptr=0; | 
					
						
							|  |  |  | 		n->data=_data; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (_data->last) { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			_data->last->next_ptr=n; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		_data->last = n; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (!_data->first) | 
					
						
							|  |  |  | 			_data->first=n; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		_data->size_cache++; | 
					
						
							| 
									
										
										
										
											2016-03-09 00:00:52 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 		return n; | 
					
						
							|  |  |  | 	}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	void pop_back() { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (_data && _data->last) | 
					
						
							|  |  |  | 			erase(_data->last); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/**
 | 
					
						
							|  |  |  | 	 * store a new element at the begining of the list | 
					
						
							|  |  |  | 	 */ | 
					
						
							|  |  |  | 	Element* push_front(const T& value) { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (!_data) { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			_data=memnew_allocator(_Data,A); | 
					
						
							|  |  |  | 			_data->first=NULL; | 
					
						
							|  |  |  | 			_data->last=NULL; | 
					
						
							|  |  |  | 			_data->size_cache=0; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		Element* n = memnew_allocator(Element,A); | 
					
						
							|  |  |  | 		n->value = (T&)value; | 
					
						
							|  |  |  | 		n->prev_ptr = 0; | 
					
						
							|  |  |  | 		n->next_ptr = _data->first; | 
					
						
							|  |  |  | 		n->data=_data; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (_data->first) { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			_data->first->prev_ptr=n; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		_data->first = n; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (!_data->last) | 
					
						
							|  |  |  | 			_data->last=n; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		_data->size_cache++; | 
					
						
							| 
									
										
										
										
											2016-03-09 00:00:52 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 		return n; | 
					
						
							|  |  |  | 	}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	void pop_front() { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (_data && _data->first) | 
					
						
							|  |  |  | 			erase(_data->first); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/**
 | 
					
						
							|  |  |  | 	 * find an element in the list, | 
					
						
							|  |  |  | 	 */ | 
					
						
							|  |  |  | 	template<class T_v> | 
					
						
							|  |  |  | 	Element* find(const T_v& p_val) { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		Element* it = front(); | 
					
						
							|  |  |  | 		while (it) { | 
					
						
							|  |  |  | 			if (it->value == p_val) return it; | 
					
						
							|  |  |  | 			it = it->next(); | 
					
						
							|  |  |  | 		}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/**
 | 
					
						
							|  |  |  | 	 * erase an element in the list, by iterator pointing to it. Return true if it was found/erased. | 
					
						
							|  |  |  | 	 */ | 
					
						
							|  |  |  | 	bool erase(const Element* p_I) { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (_data) { | 
					
						
							|  |  |  | 			bool ret =  _data->erase(p_I); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			if (_data->size_cache==0) { | 
					
						
							|  |  |  | 				memdelete_allocator<_Data,A>(_data); | 
					
						
							|  |  |  | 				_data=NULL; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			return ret; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		return false; | 
					
						
							|  |  |  | 	}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/**
 | 
					
						
							|  |  |  | 	 * erase the first element in the list, that contains value | 
					
						
							|  |  |  | 	 */ | 
					
						
							|  |  |  | 	bool erase(const T& value) { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		Element* I = find(value); | 
					
						
							|  |  |  | 		return erase(I); | 
					
						
							|  |  |  | 	}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/**
 | 
					
						
							|  |  |  | 	 * return wether the list is empty | 
					
						
							|  |  |  | 	 */ | 
					
						
							|  |  |  | 	_FORCE_INLINE_ bool empty() const { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		return (!_data || !_data->size_cache); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/**
 | 
					
						
							|  |  |  | 	 * clear the list | 
					
						
							|  |  |  | 	 */ | 
					
						
							|  |  |  | 	void clear() { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		while (front()) { | 
					
						
							|  |  |  | 			erase(front()); | 
					
						
							|  |  |  | 		}; | 
					
						
							|  |  |  | 	}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	_FORCE_INLINE_ int size() const { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		return _data?_data->size_cache:0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	void swap(Element* p_A, Element *p_B) { | 
					
						
							| 
									
										
										
										
											2016-03-09 00:00:52 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 		ERR_FAIL_COND(!p_A || !p_B); | 
					
						
							|  |  |  | 		ERR_FAIL_COND(p_A->data!=_data); | 
					
						
							|  |  |  | 		ERR_FAIL_COND(p_B->data!=_data); | 
					
						
							| 
									
										
										
										
											2016-03-09 00:00:52 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 		Element* A_prev=p_A->prev_ptr; | 
					
						
							|  |  |  | 		Element* A_next=p_A->next_ptr; | 
					
						
							| 
									
										
										
										
											2016-03-09 00:00:52 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 		p_A->next_ptr=p_B->next_ptr; | 
					
						
							|  |  |  | 		p_A->prev_ptr=p_B->prev_ptr; | 
					
						
							| 
									
										
										
										
											2016-03-09 00:00:52 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 		p_B->next_ptr=A_next; | 
					
						
							| 
									
										
										
										
											2016-03-09 00:00:52 +01:00
										 |  |  | 		p_B->prev_ptr=A_prev; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 		if (p_A->prev_ptr) | 
					
						
							|  |  |  | 			p_A->prev_ptr->next_ptr=p_A; | 
					
						
							|  |  |  | 		if (p_A->next_ptr) | 
					
						
							| 
									
										
										
										
											2016-03-09 00:00:52 +01:00
										 |  |  | 			p_A->next_ptr->prev_ptr=p_A; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 		if (p_B->prev_ptr) | 
					
						
							|  |  |  | 			p_B->prev_ptr->next_ptr=p_B; | 
					
						
							|  |  |  | 		if (p_B->next_ptr) | 
					
						
							| 
									
										
										
										
											2016-03-09 00:00:52 +01:00
										 |  |  | 			p_B->next_ptr->prev_ptr=p_B; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	/**
 | 
					
						
							|  |  |  | 	 * copy the list | 
					
						
							|  |  |  | 	 */ | 
					
						
							|  |  |  | 	void operator=(const List& p_list) { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		clear(); | 
					
						
							|  |  |  | 		const Element *it=p_list.front(); | 
					
						
							|  |  |  | 		while (it) { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			push_back( it->get() ); | 
					
						
							|  |  |  | 			it=it->next(); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	T& operator[](int p_index) { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (p_index<0 || p_index>=size()) { | 
					
						
							|  |  |  | 			T& aux=*((T*)0); //nullreturn
 | 
					
						
							|  |  |  | 			ERR_FAIL_COND_V(p_index<0 || p_index>=size(),aux); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		Element *I=front(); | 
					
						
							|  |  |  | 		int c=0; | 
					
						
							|  |  |  | 		while(I) { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			if (c==p_index) { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				return I->get(); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			I=I->next(); | 
					
						
							|  |  |  | 			c++; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		ERR_FAIL_V( *((T*)0) );	// bug!!
 | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	const T& operator[](int p_index) const { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (p_index<0 || p_index>=size()) { | 
					
						
							|  |  |  | 			T& aux=*((T*)0); //nullreturn
 | 
					
						
							|  |  |  | 			ERR_FAIL_COND_V(p_index<0 || p_index>=size(),aux); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		const Element *I=front(); | 
					
						
							|  |  |  | 		int c=0; | 
					
						
							|  |  |  | 		while(I) { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			if (c==p_index) { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				return I->get(); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			I=I->next(); | 
					
						
							|  |  |  | 			c++; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		ERR_FAIL_V( *((T*)0) );	 // bug!
 | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	void move_to_back(Element* p_I) { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		ERR_FAIL_COND(p_I->data!=_data); | 
					
						
							|  |  |  | 		if (!p_I->next_ptr) | 
					
						
							|  |  |  | 			return; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (_data->first==p_I) { | 
					
						
							|  |  |  | 			_data->first=p_I->next_ptr; | 
					
						
							|  |  |  | 		}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (_data->last==p_I) | 
					
						
							|  |  |  | 			_data->last=p_I->prev_ptr; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (p_I->prev_ptr) | 
					
						
							|  |  |  | 			p_I->prev_ptr->next_ptr=p_I->next_ptr; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (p_I->next_ptr) | 
					
						
							|  |  |  | 			p_I->next_ptr->prev_ptr=p_I->prev_ptr; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		_data->last->next_ptr=p_I; | 
					
						
							|  |  |  | 		p_I->prev_ptr=_data->last; | 
					
						
							|  |  |  | 		p_I->next_ptr=NULL; | 
					
						
							|  |  |  | 		_data->last=p_I; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	void invert() { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		int s = size() / 2; | 
					
						
							|  |  |  | 		Element *F = front(); | 
					
						
							|  |  |  | 		Element *B = back(); | 
					
						
							|  |  |  | 		for(int i=0;i<s;i++) { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			SWAP( F->value, B->value ); | 
					
						
							|  |  |  | 			F=F->next(); | 
					
						
							|  |  |  | 			B=B->prev(); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	void move_to_front(Element* p_I) { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		ERR_FAIL_COND(p_I->data!=_data); | 
					
						
							|  |  |  | 		if (!p_I->prev_ptr) | 
					
						
							|  |  |  | 			return; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (_data->first==p_I) { | 
					
						
							|  |  |  | 			_data->first=p_I->next_ptr; | 
					
						
							|  |  |  | 		}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (_data->last==p_I) | 
					
						
							|  |  |  | 			_data->last=p_I->prev_ptr; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (p_I->prev_ptr) | 
					
						
							|  |  |  | 			p_I->prev_ptr->next_ptr=p_I->next_ptr; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (p_I->next_ptr) | 
					
						
							|  |  |  | 			p_I->next_ptr->prev_ptr=p_I->prev_ptr; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		_data->first->prev_ptr=p_I; | 
					
						
							|  |  |  | 		p_I->next_ptr=_data->first; | 
					
						
							|  |  |  | 		p_I->prev_ptr=NULL; | 
					
						
							|  |  |  | 		_data->first=p_I; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	void move_before(Element* value, Element* where) { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (value->prev_ptr) { | 
					
						
							|  |  |  | 			value->prev_ptr->next_ptr = value->next_ptr; | 
					
						
							| 
									
										
										
										
											2015-07-10 21:33:44 +02:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		else { | 
					
						
							|  |  |  | 			_data->first = value->next_ptr; | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 		if (value->next_ptr) { | 
					
						
							|  |  |  | 			value->next_ptr->prev_ptr = value->prev_ptr; | 
					
						
							| 
									
										
										
										
											2015-07-10 21:33:44 +02:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		else { | 
					
						
							|  |  |  | 			_data->last = value->prev_ptr; | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		value->next_ptr = where; | 
					
						
							|  |  |  | 		if (!where) { | 
					
						
							|  |  |  | 			value->prev_ptr = _data->last; | 
					
						
							|  |  |  | 			_data->last = value; | 
					
						
							|  |  |  | 			return; | 
					
						
							|  |  |  | 		}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		value->prev_ptr = where->prev_ptr; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (where->prev_ptr) { | 
					
						
							|  |  |  | 			where->prev_ptr->next_ptr = value; | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			_data->first = value; | 
					
						
							|  |  |  | 		}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		where->prev_ptr = value; | 
					
						
							|  |  |  | 	}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/**
 | 
					
						
							|  |  |  | 	 * simple insertion sort | 
					
						
							|  |  |  | 	 */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	void sort() { | 
					
						
							| 
									
										
										
										
											2016-03-09 00:00:52 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 		sort_custom< Comparator<T> >(); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2016-03-09 00:00:52 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	template<class C> | 
					
						
							| 
									
										
										
										
											2015-02-15 12:38:25 -03:00
										 |  |  | 	void sort_custom_inplace() { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		if(size()<2) | 
					
						
							|  |  |  | 			return; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		Element *from=front(); | 
					
						
							|  |  |  | 		Element *current=from; | 
					
						
							|  |  |  | 		Element *to=from; | 
					
						
							| 
									
										
										
										
											2016-03-09 00:00:52 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 		while(current) { | 
					
						
							| 
									
										
										
										
											2016-03-09 00:00:52 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 			Element *next=current->next_ptr; | 
					
						
							| 
									
										
										
										
											2016-03-09 00:00:52 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 			//disconnect
 | 
					
						
							|  |  |  | 			current->next_ptr=NULL; | 
					
						
							| 
									
										
										
										
											2016-03-09 00:00:52 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 			if (from!=current) { | 
					
						
							| 
									
										
										
										
											2016-03-09 00:00:52 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 				current->prev_ptr=NULL; | 
					
						
							|  |  |  | 				current->next_ptr=from; | 
					
						
							| 
									
										
										
										
											2016-03-09 00:00:52 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 				Element *find=from; | 
					
						
							|  |  |  | 				C less; | 
					
						
							|  |  |  | 				while( find && less(find->value,current->value) ) { | 
					
						
							| 
									
										
										
										
											2016-03-09 00:00:52 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 					current->prev_ptr=find; | 
					
						
							|  |  |  | 					current->next_ptr=find->next_ptr; | 
					
						
							|  |  |  | 					find=find->next_ptr; | 
					
						
							|  |  |  | 				} | 
					
						
							| 
									
										
										
										
											2016-03-09 00:00:52 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 				if (current->prev_ptr) | 
					
						
							|  |  |  | 					current->prev_ptr->next_ptr=current; | 
					
						
							|  |  |  | 				else | 
					
						
							|  |  |  | 					from=current; | 
					
						
							| 
									
										
										
										
											2016-03-09 00:00:52 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 				if (current->next_ptr) | 
					
						
							|  |  |  | 					current->next_ptr->prev_ptr=current; | 
					
						
							|  |  |  | 				else | 
					
						
							|  |  |  | 					to=current; | 
					
						
							|  |  |  | 			} else { | 
					
						
							| 
									
										
										
										
											2016-03-09 00:00:52 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 				current->prev_ptr=NULL; | 
					
						
							|  |  |  | 				current->next_ptr=NULL; | 
					
						
							| 
									
										
										
										
											2016-03-09 00:00:52 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2016-03-09 00:00:52 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 			current=next; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		_data->first=from; | 
					
						
							|  |  |  | 		_data->last=to; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-15 12:38:25 -03:00
										 |  |  | 	template<class C> | 
					
						
							|  |  |  | 	struct AuxiliaryComparator { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		C compare; | 
					
						
							| 
									
										
										
										
											2015-02-15 18:09:11 +00:00
										 |  |  | 		_FORCE_INLINE_ bool operator()(const Element *a,const Element* b) const { | 
					
						
							| 
									
										
										
										
											2015-02-15 12:38:25 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-15 18:09:11 +00:00
										 |  |  | 			return compare(a->value,b->value); | 
					
						
							| 
									
										
										
										
											2015-02-15 12:38:25 -03:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	template<class C> | 
					
						
							|  |  |  | 	void sort_custom() { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		//this version uses auxiliary memory for speed.
 | 
					
						
							|  |  |  | 		//if you don't want to use auxiliary memory, use the in_place version
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		int s = size(); | 
					
						
							|  |  |  | 		if(s<2) | 
					
						
							|  |  |  | 			return; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		Element **aux_buffer = memnew_arr(Element*,s); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		int idx=0; | 
					
						
							|  |  |  | 		for(Element *E=front();E;E=E->next_ptr) { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			aux_buffer[idx]=E; | 
					
						
							|  |  |  | 			idx++; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		SortArray<Element*,AuxiliaryComparator<C> > sort; | 
					
						
							|  |  |  | 		sort.sort(aux_buffer,s); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		_data->first=aux_buffer[0]; | 
					
						
							|  |  |  | 		aux_buffer[0]->prev_ptr=NULL; | 
					
						
							|  |  |  | 		aux_buffer[0]->next_ptr=aux_buffer[1]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		_data->last=aux_buffer[s-1]; | 
					
						
							|  |  |  | 		aux_buffer[s-1]->prev_ptr=aux_buffer[s-2]; | 
					
						
							|  |  |  | 		aux_buffer[s-1]->next_ptr=NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		for(int i=1;i<s-1;i++) { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			aux_buffer[i]->prev_ptr=aux_buffer[i-1]; | 
					
						
							|  |  |  | 			aux_buffer[i]->next_ptr=aux_buffer[i+1]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		memdelete_arr(aux_buffer); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	/**
 | 
					
						
							|  |  |  | 	 * copy constructor for the list | 
					
						
							|  |  |  | 	 */ | 
					
						
							|  |  |  | 	List(const List& p_list) { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		_data=NULL; | 
					
						
							|  |  |  | 		const Element *it=p_list.front(); | 
					
						
							|  |  |  | 		while (it) { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			push_back( it->get() ); | 
					
						
							|  |  |  | 			it=it->next(); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	List() { | 
					
						
							|  |  |  | 		_data=NULL; | 
					
						
							|  |  |  | 	}; | 
					
						
							|  |  |  | 	~List() { | 
					
						
							|  |  |  | 		clear(); | 
					
						
							|  |  |  | 		if (_data) { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			ERR_FAIL_COND(_data->size_cache); | 
					
						
							|  |  |  | 			memdelete_allocator<_Data,A>(_data); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	}; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #endif
 |