From bb50df80de4b34ebc0c9fb674a67addb785038a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Branimir=20Karad=C5=BEi=C4=87?= Date: Thu, 13 Aug 2015 21:27:59 -0700 Subject: [PATCH] Updated tinystl. --- include/tinystl/buffer.h | 48 ++++++- include/tinystl/vector.h | 50 ++++++- tests/unordered_map_nonpod.cpp | 6 +- tests/vector_complex.cpp | 6 +- tests/vector_header.cpp | 2 +- tests/vector_nocopy.cpp | 229 +++++++++++++++++++++++++++++++++ tests/vector_nodefault.cpp | 10 +- 7 files changed, 330 insertions(+), 21 deletions(-) create mode 100644 tests/vector_nocopy.cpp diff --git a/include/tinystl/buffer.h b/include/tinystl/buffer.h index 31654c6..5fac229 100644 --- a/include/tinystl/buffer.h +++ b/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()); } + template + static inline void buffer_fill_urange_traits(T* first, T* last, pod_traits) { + for (; first < last; ++first) + new(placeholder(), first) T(); + } + + template + static inline void buffer_fill_urange_traits(T* first, T* last, pod_traits) { + for (; first < last; ++first) + *first = T(); + } + template static inline void buffer_fill_urange_traits(T* first, T* last, const T& value, pod_traits) { for (; first < last; ++first) @@ -105,6 +117,11 @@ namespace tinystl { buffer_bmove_urange_traits(dest, first, last, pod_traits()); } + template + static inline void buffer_fill_urange(T* first, T* last) { + buffer_fill_urange_traits(first, last, pod_traits()); + } + template static inline void buffer_fill_urange(T* first, T* last, const T& value) { buffer_fill_urange_traits(first, last, value, pod_traits()); @@ -137,6 +154,15 @@ namespace tinystl { b->capacity = newfirst + capacity; } + template + static inline void buffer_resize(buffer* 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 static inline void buffer_resize(buffer* b, size_t size, const T& value) { buffer_reserve(b, size); @@ -169,22 +195,34 @@ namespace tinystl { } template - static inline void buffer_insert(buffer* b, T* where, const T* first, const T* last) { + static inline T* buffer_insert_common(buffer* 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 + static inline void buffer_insert(buffer* 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 + static inline void buffer_insert(buffer* 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 diff --git a/include/tinystl/vector.h b/include/tinystl/vector.h index 3a8e28a..7bf736b 100644 --- a/include/tinystl/vector.h +++ b/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 + 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 + void emplace(iterator where, const Param& param); + iterator erase(iterator where); iterator erase(iterator first, iterator last); @@ -109,7 +119,7 @@ namespace tinystl { template inline vector::vector(size_t _size) { buffer_init(&m_buffer); - buffer_resize(&m_buffer, _size, T()); + buffer_resize(&m_buffer, _size); } template @@ -176,6 +186,16 @@ namespace tinystl { return m_buffer.first[idx]; } + template + inline const T& vector::front() const { + return m_buffer.first[0]; + } + + template + inline T& vector::front() { + return m_buffer.first[0]; + } + template inline const T& vector::back() const { return m_buffer.last[-1]; @@ -188,7 +208,7 @@ namespace tinystl { template inline void vector::resize(size_t _size) { - buffer_resize(&m_buffer, _size, T()); + buffer_resize(&m_buffer, _size); } template @@ -211,6 +231,19 @@ namespace tinystl { buffer_insert(&m_buffer, m_buffer.last, &t, &t + 1); } + template + inline void vector::emplace_back() + { + buffer_insert(&m_buffer, m_buffer.last, 1); + } + + template + template + inline void vector::emplace_back(const Param& param) + { + buffer_insert(&m_buffer, m_buffer.last, ¶m, ¶m + 1); + } + template inline void vector::pop_back() { buffer_erase(&m_buffer, m_buffer.last - 1, m_buffer.last); @@ -246,6 +279,11 @@ namespace tinystl { return m_buffer.last; } + template + inline void vector::insert(vector::iterator where) { + buffer_insert(&m_buffer, where, 1); + } + template inline void vector::insert(iterator where, const T& value) { buffer_insert(&m_buffer, where, &value, &value + 1); @@ -275,6 +313,12 @@ namespace tinystl { inline typename vector::iterator vector::erase_unordered(iterator first, iterator last) { return buffer_erase_unordered(&m_buffer, first, last); } + + template + template + void vector::emplace(vector::iterator where, const Param& param) { + buffer_insert(&m_buffer, where, ¶m, ¶m + 1); + } } #endif diff --git a/tests/unordered_map_nonpod.cpp b/tests/unordered_map_nonpod.cpp index f9607e3..96aa55e 100644 --- a/tests/unordered_map_nonpod.cpp +++ b/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 #include -struct Foo { int bar; }; +namespace { + struct Foo { int bar; }; +} TEST(uomap_nonpod_compiles) { diff --git a/tests/vector_complex.cpp b/tests/vector_complex.cpp index 97716fb..8deaa3f 100644 --- a/tests/vector_complex.cpp +++ b/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); } diff --git a/tests/vector_header.cpp b/tests/vector_header.cpp index 82eba45..4822104 100644 --- a/tests/vector_header.cpp +++ b/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 diff --git a/tests/vector_nocopy.cpp b/tests/vector_nocopy.cpp new file mode 100644 index 0000000..960762f --- /dev/null +++ b/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 +#include + +#include +#include +#include + +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 vector; + + { + vector v; + CHECK( v.empty() ); + CHECK( v.size() == 0 ); + } + { + vector v(10); + CHECK( v.size() == 10 ); + for (tinystl::vector::iterator it = v.begin(); it != v.end(); ++it) { + CHECK( it->data == 0 ); + } + } +} + +TEST(vector_nocopy_pushback) { + tinystl::vector 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 > v(10); + + tinystl::vector< tinystl::vector >::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 v1; + v1.emplace_back("12"); + v1.emplace_back("20"); + + tinystl::vector 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 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 v; + v.emplace_back("1"); + v.emplace_back("2"); + v.emplace_back("3"); + v.emplace_back("4"); + v.emplace_back("5"); + + tinystl::vector::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 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 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 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& 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()); +} diff --git a/tests/vector_nodefault.cpp b/tests/vector_nodefault.cpp index 319fd55..4a8bc8c 100644 --- a/tests/vector_nodefault.cpp +++ b/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 #include -#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); }