Browse Source

Updated tinystl.

Branimir Karadžić 10 years ago
parent
commit
bb50df80de

+ 43 - 5
include/tinystl/buffer.h

@@ -1,5 +1,5 @@
 /*-
- * Copyright 2012 Matthew Endsley
+ * Copyright 2012-1015 Matthew Endsley
  * All rights reserved
  *
  * Redistribution and use in source and binary forms, with or without
@@ -54,6 +54,18 @@ namespace tinystl {
 		buffer_destroy_range_traits(first, last, pod_traits<T>());
 	}
 
+	template<typename T>
+	static inline void buffer_fill_urange_traits(T* first, T* last, pod_traits<T, false>) {
+		for (; first < last; ++first)
+			new(placeholder(), first) T();
+	}
+
+	template<typename T>
+	static inline void buffer_fill_urange_traits(T* first, T* last, pod_traits<T, true>) {
+		for (; first < last; ++first)
+			*first = T();
+	}
+
 	template<typename T>
 	static inline void buffer_fill_urange_traits(T* first, T* last, const T& value, pod_traits<T, false>) {
 		for (; first < last; ++first)
@@ -105,6 +117,11 @@ namespace tinystl {
 		buffer_bmove_urange_traits(dest, first, last, pod_traits<T>());
 	}
 
+	template<typename T>
+	static inline void buffer_fill_urange(T* first, T* last) {
+		buffer_fill_urange_traits(first, last, pod_traits<T>());
+	}
+
 	template<typename T>
 	static inline void buffer_fill_urange(T* first, T* last, const T& value) {
 		buffer_fill_urange_traits(first, last, value, pod_traits<T>());
@@ -137,6 +154,15 @@ namespace tinystl {
 		b->capacity = newfirst + capacity;
 	}
 
+	template<typename T, typename Alloc>
+	static inline void buffer_resize(buffer<T, Alloc>* b, size_t size) {
+		buffer_reserve(b, size);
+
+		buffer_fill_urange(b->last, b->first + size);
+		buffer_destroy_range(b->first + size, b->last);
+		b->last = b->first + size;
+	}
+
 	template<typename T, typename Alloc>
 	static inline void buffer_resize(buffer<T, Alloc>* b, size_t size, const T& value) {
 		buffer_reserve(b, size);
@@ -169,22 +195,34 @@ namespace tinystl {
 	}
 
 	template<typename T, typename Alloc>
-	static inline void buffer_insert(buffer<T, Alloc>* b, T* where, const T* first, const T* last) {
+	static inline T* buffer_insert_common(buffer<T, Alloc>* b, T* where, size_t count) {
 		const size_t offset = (size_t)(where - b->first);
-		const size_t newsize = (size_t)((b->last - b->first) + (last - first));
+		const size_t newsize = (size_t)((b->last - b->first) + count);
 		if (b->first + newsize > b->capacity)
 			buffer_reserve(b, (newsize * 3) / 2);
 
 		where = b->first + offset;
-		const size_t count = (size_t)(last - first);
 
 		if (where != b->last)
 			buffer_bmove_urange(where + count, where, b->last);
 
+		b->last = b->first + newsize;
+
+		return where;
+	}
+
+	template<typename T, typename Alloc, typename Param>
+	static inline void buffer_insert(buffer<T, Alloc>* b, T* where, const Param* first, const Param* last) {
+		where = buffer_insert_common(b, where, last - first);
 		for (; first != last; ++first, ++where)
 			new(placeholder(), where) T(*first);
+	}
 
-		b->last = b->first + newsize;
+	template<typename T, typename Alloc>
+	static inline void buffer_insert(buffer<T, Alloc>* b, T* where, size_t count) {
+		where = buffer_insert_common(b, where, count);
+		for (size_t i = 0; i < count; ++i)
+			new(placeholder(), where) T();
 	}
 
 	template<typename T, typename Alloc>

+ 47 - 3
include/tinystl/vector.h

@@ -1,5 +1,5 @@
 /*-
- * Copyright 2012 Matthew Endsley
+ * Copyright 2012-1015 Matthew Endsley
  * All rights reserved
  *
  * Redistribution and use in source and binary forms, with or without
@@ -56,6 +56,8 @@ namespace tinystl {
 		T& operator[](size_t idx);
 		const T& operator[](size_t idx) const;
 
+		const T& front() const;
+		T& front();
 		const T& back() const;
 		T& back();
 
@@ -67,6 +69,10 @@ namespace tinystl {
 		void push_back(const T& t);
 		void pop_back();
 
+		void emplace_back();
+		template<typename Param>
+		void emplace_back(const Param& param);
+
 		void shrink_to_fit();
 
 		void swap(vector& other);
@@ -81,9 +87,13 @@ namespace tinystl {
 		const_iterator begin() const;
 		const_iterator end() const;
 
+		void insert(iterator where);
 		void insert(iterator where, const T& value);
 		void insert(iterator where, const T* first, const T* last);
 
+		template<typename Param>
+		void emplace(iterator where, const Param& param);
+
 		iterator erase(iterator where);
 		iterator erase(iterator first, iterator last);
 
@@ -109,7 +119,7 @@ namespace tinystl {
 	template<typename T, typename Alloc>
 	inline vector<T, Alloc>::vector(size_t _size) {
 		buffer_init(&m_buffer);
-		buffer_resize(&m_buffer, _size, T());
+		buffer_resize(&m_buffer, _size);
 	}
 
 	template<typename T, typename Alloc>
@@ -176,6 +186,16 @@ namespace tinystl {
 		return m_buffer.first[idx];
 	}
 
+	template<typename T, typename Alloc>
+	inline const T& vector<T, Alloc>::front() const {
+		return m_buffer.first[0];
+	}
+
+	template<typename T, typename Alloc>
+	inline T& vector<T, Alloc>::front() {
+		return m_buffer.first[0];
+	}
+
 	template<typename T, typename Alloc>
 	inline const T& vector<T, Alloc>::back() const {
 		return m_buffer.last[-1];
@@ -188,7 +208,7 @@ namespace tinystl {
 
 	template<typename T, typename Alloc>
 	inline void vector<T, Alloc>::resize(size_t _size) {
-		buffer_resize(&m_buffer, _size, T());
+		buffer_resize(&m_buffer, _size);
 	}
 
 	template<typename T, typename Alloc>
@@ -211,6 +231,19 @@ namespace tinystl {
 		buffer_insert(&m_buffer, m_buffer.last, &t, &t + 1);
 	}
 
+	template<typename T, typename Alloc>
+	inline void vector<T, Alloc>::emplace_back()
+	{
+		buffer_insert(&m_buffer, m_buffer.last, 1);
+	}
+
+	template<typename T, typename Alloc>
+	template<typename Param>
+	inline void vector<T, Alloc>::emplace_back(const Param& param)
+	{
+		buffer_insert(&m_buffer, m_buffer.last, &param, &param + 1);
+	}
+
 	template<typename T, typename Alloc>
 	inline void vector<T, Alloc>::pop_back() {
 		buffer_erase(&m_buffer, m_buffer.last - 1, m_buffer.last);
@@ -246,6 +279,11 @@ namespace tinystl {
 		return m_buffer.last;
 	}
 
+	template<typename T, typename Alloc>
+	inline void vector<T, Alloc>::insert(vector::iterator where) {
+		buffer_insert(&m_buffer, where, 1);
+	}
+
 	template<typename T, typename Alloc>
 	inline void vector<T, Alloc>::insert(iterator where, const T& value) {
 		buffer_insert(&m_buffer, where, &value, &value + 1);
@@ -275,6 +313,12 @@ namespace tinystl {
 	inline typename vector<T, Alloc>::iterator vector<T, Alloc>::erase_unordered(iterator first, iterator last) {
 		return buffer_erase_unordered(&m_buffer, first, last);
 	}
+
+	template<typename T, typename Alloc>
+	template<typename Param>
+	void vector<T, Alloc>::emplace(vector::iterator where, const Param& param) {
+		buffer_insert(&m_buffer, where, &param, &param + 1);
+	}
 }
 
 #endif

+ 4 - 2
tests/unordered_map_nonpod.cpp

@@ -1,5 +1,5 @@
 /*-
- * Copyright 2012-2014 Matthew Endsley
+ * Copyright 2012-2015 Matthew Endsley
  * All rights reserved
  *
  * Redistribution and use in source and binary forms, with or without
@@ -29,7 +29,9 @@
 #include <tinystl/allocator.h>
 #include <tinystl/unordered_map.h>
 
-struct Foo { int bar; };
+namespace {
+	struct Foo { int bar; };
+}
 
 TEST(uomap_nonpod_compiles) {
 

+ 3 - 3
tests/vector_complex.cpp

@@ -1,5 +1,5 @@
 /*-
- * Copyright 2012 Matthew Endsley
+ * Copyright 2012-1015 Matthew Endsley
  * All rights reserved
  *
  * Redistribution and use in source and binary forms, with or without
@@ -35,9 +35,9 @@
 
 struct complex {
 	complex() {data = 0;}
-	complex(const char* s) { data = _strdup(s); }
+	complex(const char* s) { data = strdup(s); }
 	~complex() { free(data); }
-	complex(const complex& other) { data = 0; if (other.data) data = _strdup(other.data); }
+	complex(const complex& other) { data = 0; if (other.data) data = strdup(other.data); }
 	complex& operator=(const complex& other) { complex(other).swap(*this); return *this; }
 	void swap(complex& other) { std::swap(data, other.data); }
 

+ 1 - 1
tests/vector_header.cpp

@@ -1,5 +1,5 @@
 /*-
- * Copyright 2012 Matthew Endsley
+ * Copyright 2012-1015 Matthew Endsley
  * All rights reserved
  *
  * Redistribution and use in source and binary forms, with or without

+ 229 - 0
tests/vector_nocopy.cpp

@@ -0,0 +1,229 @@
+/*-
+ * Copyright 2012-1015 Matthew Endsley
+ * All rights reserved
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted providing that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "test.h"
+
+#include <tinystl/allocator.h>
+#include <tinystl/vector.h>
+
+#include <algorithm>
+#include <string.h>
+#include <stdlib.h>
+
+struct nocopy {
+	nocopy() { data = 0; }
+	explicit nocopy(const char* s) { data = s; }
+	~nocopy() { }
+	void swap(nocopy& other) { std::swap(data, other.data); }
+	void reset(const char* s) { data = s; }
+	const char* release() { const char* ret = data; data = 0; return ret; }
+
+	const char* data;
+
+private:
+	nocopy(const nocopy& other);
+	nocopy& operator=(const nocopy& other);
+};
+
+static inline bool operator==(const nocopy& lhs, const char* rhs) {
+	if (lhs.data == 0 && rhs == 0)
+		return true;
+	if (lhs.data != 0 && rhs != 0)
+		return 0 == strcmp(lhs.data, rhs);
+	return false;
+}
+
+static inline bool operator==(const nocopy& lhs, const nocopy& rhs) {
+	if (lhs.data == 0 && rhs.data == 0)
+		return true;
+	if (lhs.data != 0 && rhs.data != 0)
+		return 0 == strcmp(lhs.data, rhs.data);
+	return false;
+}
+
+TEST(vector_nocopy_constructor) {
+	typedef tinystl::vector<nocopy> vector;
+
+	{
+		vector v;
+		CHECK( v.empty() );
+		CHECK( v.size() == 0 );
+	}
+	{
+		vector v(10);
+		CHECK( v.size() == 10 );
+		for (tinystl::vector<nocopy>::iterator it = v.begin(); it != v.end(); ++it) {
+			CHECK( it->data == 0 );
+		}
+	}
+}
+
+TEST(vector_nocopy_pushback) {
+	tinystl::vector<nocopy> v;
+	v.emplace_back("42");
+	v.emplace_back();
+	v.back().reset("24");
+
+	CHECK( v.size() == 2 );
+	CHECK( v[0] == "42" );
+	CHECK( v[1] == "24" );
+}
+
+TEST(vector_nocopy_vector) {
+	tinystl::vector< tinystl::vector<nocopy> > v(10);
+
+	tinystl::vector< tinystl::vector<nocopy> >::iterator it = v.begin(), end = v.end();
+	for (; it != end; ++it) {
+		CHECK( (*it).empty() );
+		CHECK( (*it).size() == 0 );
+		CHECK( (*it).begin() == (*it).end() );
+	}
+}
+
+TEST(vector_nocopy_swap) {
+	tinystl::vector<nocopy> v1;
+	v1.emplace_back("12");
+	v1.emplace_back("20");
+
+	tinystl::vector<nocopy> v2;
+	v2.emplace_back("54");
+
+	v1.swap(v2);
+
+	CHECK(v1.size() == 1);
+	CHECK(v2.size() == 2);
+	CHECK(v1[0] == "54");
+	CHECK(v2[0] == "12");
+	CHECK(v2[1] == "20");
+}
+
+TEST(vector_nocopy_popback) {
+	tinystl::vector<nocopy> v;
+	v.emplace_back("12");
+	v.emplace_back("24");
+
+	CHECK(v.back() == "24");
+
+	v.pop_back();
+
+	CHECK(v.back() == "12");
+	CHECK(v.size() == 1);
+}
+
+TEST(vector_nocopy_erase) {
+	tinystl::vector<nocopy> v;
+	v.emplace_back("1");
+	v.emplace_back("2");
+	v.emplace_back("3");
+	v.emplace_back("4");
+	v.emplace_back("5");
+
+	tinystl::vector<nocopy>::iterator it = v.erase(v.begin());
+	CHECK(*it == "2");
+	CHECK(v.size() == 4);
+
+	it = v.erase(v.end() - 1);
+	CHECK(it == v.end());
+	CHECK(v.size() == 3);
+
+	v.erase(v.begin() + 1, v.end() - 1);
+	CHECK(v.size() == 2);
+	CHECK(v[0] == "2");
+	CHECK(v[1] == "4");
+}
+
+TEST(vector_nocopy_erase_unordered) {
+	typedef tinystl::vector<nocopy> vector;
+	vector v;
+	v.emplace_back("1");
+	v.emplace_back("2");
+	v.emplace_back("3");
+	v.emplace_back("4");
+	v.emplace_back("5");
+
+	const char* first = v.front().release();
+	vector::iterator it = v.erase_unordered(v.begin());
+	CHECK( it == v.begin() );
+	CHECK( v.size() == 4 );
+	CHECK( std::count(v.begin(), v.end(), first) == 0 );
+	for (it = v.begin(); it != v.end(); ++it) {
+		CHECK( std::count(v.begin(), v.end(), *it) == 1 );
+	}
+
+	const char* last = v.back().release();
+	it = v.erase_unordered(v.end() - 1);
+	CHECK( it == v.end() );
+	CHECK( v.size() == 3 );
+	CHECK( std::count(v.begin(), v.end(), last) == 0 );
+	for (it = v.begin(); it != v.end(); ++it) {
+		CHECK( std::count(v.begin(), v.end(), *it) == 1 );
+	}
+
+	first = v.begin()->data;
+	last = (v.end() - 1)->data;
+	v.erase_unordered(v.begin() + 1, v.end() - 1);
+	CHECK( v.size() == 2 );
+	CHECK( std::count(v.begin(), v.end(), first) == 1 );
+	CHECK( std::count(v.begin(), v.end(), last) == 1 );
+}
+
+TEST(vector_nocopy_insert) {
+	tinystl::vector<nocopy> v;
+	v.emplace_back("1");
+	v.emplace_back("2");
+	v.emplace_back("3");
+	v.emplace_back("4");
+	v.emplace_back("5");
+
+	v.emplace(v.begin(), "0");
+	CHECK( v.size() == 6 );
+	CHECK( v[0] == "0" );
+	CHECK( v[1] == "1" );
+	CHECK( v[5] == "5" );
+
+	v.emplace(v.end(), "6");
+	CHECK( v.size() == 7 );
+	CHECK( v.front() == "0" );
+	CHECK( v.back() == "6" );
+}
+
+TEST(vector_nocopy_iterator) {
+	tinystl::vector<nocopy> v(5);
+	v[0].reset("1");
+	v[1].reset("2");
+	v[2].reset("3");
+	v[3].reset("4");
+	v[4].reset("5");
+
+	const tinystl::vector<nocopy>& cv = v;
+
+	//CHECK(v.data() == &*v.begin());
+	//CHECK(v.data() == &v[0]);
+	//CHECK(v.data() + v.size() == &*v.end());
+	CHECK(v.begin() == cv.begin());
+	CHECK(v.end() == cv.end());
+	//CHECK(v.data() == cv.data());
+}

+ 3 - 7
tests/vector_nodefault.cpp

@@ -1,5 +1,5 @@
 /*-
- * Copyright 2012 Matthew Endsley
+ * Copyright 2012-1015 Matthew Endsley
  * All rights reserved
  *
  * Redistribution and use in source and binary forms, with or without
@@ -33,14 +33,10 @@
 #include <string.h>
 #include <stdlib.h>
 
-#if !BX_COMPILER_MSVC
-#	define _strdup strdup
-#endif // !BX_COMPILER_MSVC
-
 struct nodefault {
-	nodefault(const char* s) { data = _strdup(s); }
+	nodefault(const char* s) { data = strdup(s); }
 	~nodefault() { free(data); }
-	nodefault(const nodefault& other) { data = 0; if (other.data) data = _strdup(other.data); }
+	nodefault(const nodefault& other) { data = 0; if (other.data) data = strdup(other.data); }
 	nodefault& operator=(const nodefault& other) { nodefault(other).swap(*this); return *this; }
 	void swap(nodefault& other) { std::swap(data, other.data); }