diff options
| author | Arseny Kapoulkine <arseny.kapoulkine@gmail.com> | 2014-10-10 19:29:25 -0700 | 
|---|---|---|
| committer | Arseny Kapoulkine <arseny.kapoulkine@gmail.com> | 2014-10-10 19:29:25 -0700 | 
| commit | fbaab4dcad9eafc2c17f8030bb3c924fca644795 (patch) | |
| tree | a523e47d68da61fc74d59b1bf5731bd6e1334a15 | |
| parent | 89575f352ad2de587fad4ef997b94e30d90f9b55 (diff) | |
Move compact_hash_table before xml_allocator.
This helps streamline class dependencies and will make subsequent changes
smaller.
| -rw-r--r-- | src/pugixml.cpp | 266 | 
1 files changed, 135 insertions, 131 deletions
| diff --git a/src/pugixml.cpp b/src/pugixml.cpp index d2124a6..677ae7b 100644 --- a/src/pugixml.cpp +++ b/src/pugixml.cpp @@ -257,6 +257,140 @@ PUGI__NS_BEGIN  PUGI__NS_END  #endif +#ifdef PUGIXML_COMPACT +size_t pugi_compact_stats[128]; + +PUGI__NS_BEGIN +	class compact_hash_table +	{ +	public: +		compact_hash_table(): _items(0), _capacity(0), _count(0) +		{ +		} + +		void clear() +		{ +			if (_items) +			{ +				xml_memory::deallocate(_items); +				_items = 0; +				_capacity = 0; +				_count = 0; +			} +		} + +		void** find(const void* key) +		{ +			assert(key); + +			if (_capacity == 0) return 0; + +			size_t hashmod = _capacity - 1; +			size_t bucket = hash(key) & hashmod; + +			for (size_t probe = 0; probe <= hashmod; ++probe) +			{ +				item_t& probe_item = _items[bucket]; + +				if (probe_item.key == key) +					return &probe_item.value; + +				if (probe_item.key == 0) +					return 0; + +				// hash collision, quadratic probing +				bucket = (bucket + probe + 1) & hashmod; +			} + +			assert(!"Hash table is full"); +			return 0; +		} + +		void** insert(const void* key, size_t tag) +		{ +			assert(key); + +			if (_count >= _capacity * 3 / 4) +				rehash(); + +			size_t hashmod = _capacity - 1; +			size_t bucket = hash(key) & hashmod; + +			for (size_t probe = 0; probe <= hashmod; ++probe) +			{ +				item_t& probe_item = _items[bucket]; + +				if (probe_item.key == 0) +				{ +					if (tag) +						pugi_compact_stats[tag]++; + +					probe_item.key = key; +					_count++; +					return &probe_item.value; +				} + +				if (probe_item.key == key) +					return &probe_item.value; + +				// hash collision, quadratic probing +				bucket = (bucket + probe + 1) & hashmod; +			} + +			assert(!"Hash table is full"); +			return 0; +		} + +	private: +		struct item_t +		{ +			const void* key; +			void* value; +		}; + +		item_t* _items; +		size_t _capacity; + +		size_t _count; + +		void rehash() +		{ +			compact_hash_table rt; +			rt._capacity = (_capacity == 0) ? 256 : _capacity * 2; +			rt._items = static_cast<item_t*>(xml_memory::allocate(sizeof(item_t) * rt._capacity)); + +			assert(rt._items); + +			memset(rt._items, 0, sizeof(item_t) * rt._capacity); + +			for (size_t i = 0; i < _capacity; ++i) +				if (_items[i].key) +					*rt.insert(_items[i].key, 0) = _items[i].value; + +			if (_items) +				xml_memory::deallocate(_items); + +			_capacity = rt._capacity; +			_items = rt._items; +		} + +		// http://burtleburtle.net/bob/hash/integer.html +		static unsigned int hash(const void* key) +		{ +			unsigned int a = static_cast<unsigned int>(reinterpret_cast<uintptr_t>(key)); + +			a = (a ^ 61) ^ (a >> 16); +			a = a + (a << 3); +			a = a ^ (a >> 4); +			a = a * 0x27d4eb2d; +			a = a ^ (a >> 15); + +			return a; +		} +	}; +PUGI__NS_END +#endif +  PUGI__NS_BEGIN  	static const size_t xml_memory_page_size =  	#ifdef PUGIXML_MEMORY_PAGE_SIZE @@ -463,7 +597,7 @@ PUGI__NS_BEGIN  		size_t _busy_size;  	#ifdef PUGIXML_COMPACT -		class compact_hash_table* _hash; +		compact_hash_table* _hash;  	#endif  	}; @@ -508,137 +642,7 @@ PUGI__NS_BEGIN  PUGI__NS_END  #ifdef PUGIXML_COMPACT -size_t pugi_compact_stats[128]; -  PUGI__NS_BEGIN -	class compact_hash_table -	{ -	public: -		compact_hash_table(): _items(0), _capacity(0), _count(0) -		{ -		} - -		void clear() -		{ -			if (_items) -			{ -				xml_memory::deallocate(_items); -				_items = 0; -				_capacity = 0; -				_count = 0; -			} -		} - -		void** find(const void* key) -		{ -			assert(key); - -			if (_capacity == 0) return 0; - -			size_t hashmod = _capacity - 1; -			size_t bucket = hash(key) & hashmod; - -			for (size_t probe = 0; probe <= hashmod; ++probe) -			{ -				item_t& probe_item = _items[bucket]; - -				if (probe_item.key == key) -					return &probe_item.value; - -				if (probe_item.key == 0) -					return 0; - -				// hash collision, quadratic probing -				bucket = (bucket + probe + 1) & hashmod; -			} - -			assert(!"Hash table is full"); -			return 0; -		} - -		void** insert(const void* key, size_t tag) -		{ -			assert(key); - -			if (_count >= _capacity * 3 / 4) -				rehash(); - -			size_t hashmod = _capacity - 1; -			size_t bucket = hash(key) & hashmod; - -			for (size_t probe = 0; probe <= hashmod; ++probe) -			{ -				item_t& probe_item = _items[bucket]; - -				if (probe_item.key == 0) -				{ -					if (tag) -						pugi_compact_stats[tag]++; - -					probe_item.key = key; -					_count++; -					return &probe_item.value; -				} - -				if (probe_item.key == key) -					return &probe_item.value; - -				// hash collision, quadratic probing -				bucket = (bucket + probe + 1) & hashmod; -			} - -			assert(!"Hash table is full"); -			return 0; -		} - -	private: -		struct item_t -		{ -			const void* key; -			void* value; -		}; - -		item_t* _items; -		size_t _capacity; - -		size_t _count; - -		void rehash() -		{ -			compact_hash_table rt; -			rt._capacity = (_capacity == 0) ? 256 : _capacity * 2; -			rt._items = static_cast<item_t*>(xml_memory::allocate(sizeof(item_t) * rt._capacity)); - -			assert(rt._items); - -			memset(rt._items, 0, sizeof(item_t) * rt._capacity); - -			for (size_t i = 0; i < _capacity; ++i) -				if (_items[i].key) -					*rt.insert(_items[i].key, 0) = _items[i].value; - -			if (_items) -				xml_memory::deallocate(_items); - -			_capacity = rt._capacity; -			_items = rt._items; -		} - -		// http://burtleburtle.net/bob/hash/integer.html -		static unsigned int hash(const void* key) -		{ -			unsigned int a = static_cast<unsigned int>(reinterpret_cast<uintptr_t>(key)); - -			a = (a ^ 61) ^ (a >> 16); -			a = a + (a << 3); -			a = a ^ (a >> 4); -			a = a * 0x27d4eb2d; -			a = a ^ (a >> 15); - -			return a; -		} -	}; -  	static const unsigned int compact_alignment_log2 = 2;  	static const unsigned int compact_alignment = 1 << compact_alignment_log2; | 
