diff --git a/include/TINYSTL/buffer.h b/include/TINYSTL/buffer.h index a88cb3a..d9373ac 100644 --- a/include/TINYSTL/buffer.h +++ b/include/TINYSTL/buffer.h @@ -203,7 +203,7 @@ namespace tinystl { 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) + count); - if (b->first + newsize > b->capacity) + if (!b->first || b->first + newsize > b->capacity) buffer_reserve(b, (newsize * 3) / 2); where = b->first + offset; diff --git a/include/TINYSTL/hash_base.h b/include/TINYSTL/hash_base.h index 118c85e..5307c32 100644 --- a/include/TINYSTL/hash_base.h +++ b/include/TINYSTL/hash_base.h @@ -45,6 +45,9 @@ namespace tinystl { Key first; Value second; + + using first_type = Key; + using second_type = Value; }; template @@ -94,9 +97,9 @@ namespace tinystl { } template - static inline pair::type, typename remove_reference::type> + static inline pair::type, typename remove_const_reference::type> make_pair(Key&& key, Value&& value) { - return pair::type, typename remove_reference::type>( + return pair::type, typename remove_const_reference::type>( static_cast(key) , static_cast(value) ); @@ -112,9 +115,6 @@ namespace tinystl { Value second; unordered_hash_node* next; unordered_hash_node* prev; - - private: - unordered_hash_node& operator=(const unordered_hash_node&); }; template @@ -139,9 +139,6 @@ namespace tinystl { const Key first; unordered_hash_node* next; unordered_hash_node* prev; - - private: - unordered_hash_node& operator=(const unordered_hash_node&); }; template diff --git a/include/TINYSTL/string.h b/include/TINYSTL/string.h index 3fe45d1..896ce29 100644 --- a/include/TINYSTL/string.h +++ b/include/TINYSTL/string.h @@ -66,7 +66,7 @@ namespace tinystl { pointer m_capacity; static const size_t c_nbuffer = 12; - char m_buffer[12]; + char m_buffer[12]{0}; }; template @@ -157,7 +157,8 @@ namespace tinystl { template inline size_t basic_string::size() const { - return (size_t)(m_last - m_first); + ptrdiff_t size = m_last - m_first; + return (size_t)size; } template @@ -165,7 +166,7 @@ namespace tinystl { if (m_first + capacity + 1 <= m_capacity) return; - const size_t size = (size_t)(m_last - m_first); + const ptrdiff_t size = m_last - m_first; pointer newfirst = (pointer)allocator::static_allocate(capacity + 1); for (pointer it = m_first, newit = newfirst, end = m_last; it != end; ++it, ++newit) @@ -180,9 +181,9 @@ namespace tinystl { template inline void basic_string::resize(size_t size) { - const size_t prevSize = m_last-m_first; + const ptrdiff_t prevSize = m_last-m_first; reserve(size); - if (size > prevSize) + if (size > (size_t)prevSize) for (pointer it = m_last, end = m_first + size + 1; it < end; ++it) *it = 0; else if (m_last != m_first) @@ -198,7 +199,7 @@ namespace tinystl { template inline void basic_string::append(const char* first, const char* last) { - const size_t newsize = (size_t)((m_last - m_first) + (last - first) + 1); + const ptrdiff_t newsize = ((m_last - m_first) + (last - first) + 1); if (m_first + newsize > m_capacity) reserve((newsize * 3) / 2); @@ -217,12 +218,12 @@ namespace tinystl { inline void basic_string::shrink_to_fit() { if (m_first == m_buffer) { } else if (m_last == m_first) { - const size_t capacity = (size_t)(m_capacity - m_first); + const ptrdiff_t capacity = m_capacity - m_first; if (capacity) allocator::static_deallocate(m_first, capacity+1); m_capacity = m_first; } else if (m_capacity != m_last) { - const size_t size = (size_t)(m_last - m_first); + const ptrdiff_t size = m_last - m_first; char* newfirst = (pointer)allocator::static_allocate(size+1); for (pointer in = m_first, out = newfirst; in != m_last + 1; ++in, ++out) *out = *in; @@ -236,34 +237,28 @@ namespace tinystl { template inline void basic_string::swap(basic_string& other) { - const pointer tfirst = m_first, tlast = m_last, tcapacity = m_capacity; - m_first = other.m_first, m_last = other.m_last, m_capacity = other.m_capacity; - other.m_first = tfirst, other.m_last = tlast, other.m_capacity = tcapacity; - - char tbuffer[c_nbuffer]; - - if (m_first == other.m_buffer) - for (pointer it = other.m_buffer, end = m_last, out = tbuffer; it != end; ++it, ++out) - *out = *it; - - if (other.m_first == m_buffer) { - other.m_last = other.m_last - other.m_first + other.m_buffer; - other.m_first = other.m_buffer; - other.m_capacity = other.m_buffer + c_nbuffer; - - for (pointer it = other.m_first, end = other.m_last, in = m_buffer; it != end; ++it, ++in) - *it = *in; - *other.m_last = 0; + { + const pointer tfirst = m_first, tlast = m_last, tcapacity = m_capacity; + m_first = other.m_first, m_last = other.m_last, m_capacity = other.m_capacity; + other.m_first = tfirst, other.m_last = tlast, other.m_capacity = tcapacity; } + for (size_t i = 0; i < c_nbuffer; ++i) { + const char temp = m_buffer[i]; + m_buffer[i] = other.m_buffer[i]; + other.m_buffer[i] = temp; + } if (m_first == other.m_buffer) { - m_last = m_last - m_first + m_buffer; + ptrdiff_t len = m_last - m_first; m_first = m_buffer; + m_last = m_buffer + len; m_capacity = m_buffer + c_nbuffer; - - for (pointer it = m_first, end = m_last, in = tbuffer; it != end; ++it, ++in) - *it = *in; - *m_last = 0; + } + if (other.m_first == m_buffer) { + ptrdiff_t len = other.m_last - other.m_first; + other.m_first = other.m_buffer; + other.m_last = other.m_buffer + len; + other.m_capacity = other.m_buffer + c_nbuffer; } } diff --git a/include/TINYSTL/string_view.h b/include/TINYSTL/string_view.h index beae9c4..754fb62 100644 --- a/include/TINYSTL/string_view.h +++ b/include/TINYSTL/string_view.h @@ -103,7 +103,7 @@ namespace tinystl { } constexpr bool string_view::empty() const { - return 0 == m_size; + return 0 == m_size; } constexpr string_view::iterator string_view::begin() const { diff --git a/include/TINYSTL/traits.h b/include/TINYSTL/traits.h index 84574ee..57d9354 100644 --- a/include/TINYSTL/traits.h +++ b/include/TINYSTL/traits.h @@ -95,6 +95,31 @@ namespace tinystl { struct remove_reference { typedef T type; }; + + template + struct remove_const { + typedef T type; + }; + + template + struct remove_const { + typedef T type; + }; + + template + struct remove_const { + typedef T& type; + }; + + template + struct remove_const { + typedef T&& type; + }; + + template + struct remove_const_reference { + typedef typename remove_reference::type>::type type; + }; } #endif diff --git a/include/TINYSTL/unordered_map.h b/include/TINYSTL/unordered_map.h index 168a6f8..6a8bb90 100644 --- a/include/TINYSTL/unordered_map.h +++ b/include/TINYSTL/unordered_map.h @@ -95,11 +95,13 @@ namespace tinystl { buffer_init(&m_buckets); buffer_resize(&m_buckets, nbuckets, 0); - for (pointer it = *other.m_buckets.first; it; it = it->next) { - unordered_hash_node* newnode = new(placeholder(), Alloc::static_allocate(sizeof(unordered_hash_node))) unordered_hash_node(it->first, it->second); - newnode->next = newnode->prev = 0; + if (other.m_buckets.first) { + for (pointer it = *other.m_buckets.first; it; it = it->next) { + unordered_hash_node* newnode = new(placeholder(), Alloc::static_allocate(sizeof(unordered_hash_node))) unordered_hash_node(it->first, it->second); + newnode->next = newnode->prev = 0; - unordered_hash_node_insert(newnode, hash(it->first), m_buckets.first, nbuckets - 1); + unordered_hash_node_insert(newnode, hash(it->first), m_buckets.first, nbuckets - 1); + } } } @@ -133,28 +135,36 @@ namespace tinystl { template inline typename unordered_map::iterator unordered_map::begin() { iterator it; - it.node = *m_buckets.first; + if (m_buckets.first) { + it.node = *m_buckets.first; + } else { + it.node = nullptr; + } return it; } template inline typename unordered_map::iterator unordered_map::end() { iterator it; - it.node = 0; + it.node = nullptr; return it; } template inline typename unordered_map::const_iterator unordered_map::begin() const { const_iterator cit; - cit.node = *m_buckets.first; + if (m_buckets.first) { + cit.node = *m_buckets.first; + } else { + cit.node = nullptr; + } return cit; } template inline typename unordered_map::const_iterator unordered_map::end() const { const_iterator cit; - cit.node = 0; + cit.node = nullptr; return cit; } @@ -170,13 +180,15 @@ namespace tinystl { template inline void unordered_map::clear() { - pointer it = *m_buckets.first; - while (it) { - const pointer next = it->next; - it->~unordered_hash_node(); - Alloc::static_deallocate(it, sizeof(unordered_hash_node)); - - it = next; + if (m_buckets.first) { + pointer it = *m_buckets.first; + while (it) { + const pointer next = it->next; + it->~unordered_hash_node(); + Alloc::static_deallocate(it, sizeof(unordered_hash_node)); + + it = next; + } } m_buckets.last = m_buckets.first; @@ -200,6 +212,7 @@ namespace tinystl { template inline void unordered_map::rehash(size_t nbuckets) { + if (!m_buckets.first) return; if (m_size + 1 > 4 * nbuckets) { pointer root = *m_buckets.first; @@ -210,7 +223,7 @@ namespace tinystl { while (root) { const pointer next = root->next; - root->next = root->prev = 0; + root->next = root->prev = nullptr; unordered_hash_node_insert(root, hash(root->first), buckets, newnbuckets); root = next; } @@ -223,11 +236,11 @@ namespace tinystl { result.second = false; result.first = find(p.first); - if (result.first.node != 0) + if (result.first.node != nullptr) return result; unordered_hash_node* newnode = new(placeholder(), Alloc::static_allocate(sizeof(unordered_hash_node))) unordered_hash_node(p.first, p.second); - newnode->next = newnode->prev = 0; + newnode->next = newnode->prev = nullptr; if(!m_buckets.first) buffer_resize(&m_buckets, 9, 0); const size_t nbuckets = (size_t)(m_buckets.last - m_buckets.first); @@ -247,7 +260,7 @@ namespace tinystl { result.second = false; result.first = find(p.first); - if (result.first.node != 0) + if (result.first.node != nullptr) return result; const size_t keyhash = hash(p.first); diff --git a/include/TINYSTL/unordered_set.h b/include/TINYSTL/unordered_set.h index 450fbc5..d218f9e 100644 --- a/include/TINYSTL/unordered_set.h +++ b/include/TINYSTL/unordered_set.h @@ -78,7 +78,6 @@ namespace tinystl { : m_size(0) { buffer_init(&m_buckets); - buffer_resize(&m_buckets, 9, 0); } template @@ -89,10 +88,12 @@ namespace tinystl { buffer_init(&m_buckets); buffer_resize(&m_buckets, nbuckets, 0); - for (pointer it = *other.m_buckets.first; it; it = it->next) { - unordered_hash_node* newnode = new(placeholder(), Alloc::static_allocate(sizeof(unordered_hash_node))) unordered_hash_node(*it); - newnode->next = newnode->prev = 0; - unordered_hash_node_insert(newnode, hash(it->first), m_buckets.first, nbuckets - 1); + if (other.m_buckets.first) { + for (pointer it = *other.m_buckets.first; it; it = it->next) { + unordered_hash_node* newnode = new(placeholder(), Alloc::static_allocate(sizeof(unordered_hash_node))) unordered_hash_node(*it); + newnode->next = newnode->prev = 0; + unordered_hash_node_insert(newnode, hash(it->first), m_buckets.first, nbuckets - 1); + } } } @@ -125,15 +126,19 @@ namespace tinystl { template inline typename unordered_set::iterator unordered_set::begin() const { - iterator cit; - cit.node = *m_buckets.first; - return cit; + iterator it; + if (m_buckets.first) { + it.node = *m_buckets.first; + } else { + it.node = nullptr; + } + return it; } template inline typename unordered_set::iterator unordered_set::end() const { iterator cit; - cit.node = 0; + cit.node = nullptr; return cit; } @@ -149,13 +154,15 @@ namespace tinystl { template inline void unordered_set::clear() { - pointer it = *m_buckets.first; - while (it) { - const pointer next = it->next; - it->~unordered_hash_node(); - Alloc::static_deallocate(it, sizeof(unordered_hash_node)); - - it = next; + if (m_buckets.first) { + pointer it = *m_buckets.first; + while (it) { + const pointer next = it->next; + it->~unordered_hash_node(); + Alloc::static_deallocate(it, sizeof(unordered_hash_node)); + + it = next; + } } m_buckets.last = m_buckets.first; @@ -172,6 +179,7 @@ namespace tinystl { template inline void unordered_set::rehash(size_t nbuckets) { + if (!m_buckets.first) return; if (m_size + 1 > 4 * nbuckets) { pointer root = *m_buckets.first; @@ -182,7 +190,7 @@ namespace tinystl { while (root) { const pointer next = root->next; - root->next = root->prev = 0; + root->next = root->prev = nullptr; unordered_hash_node_insert(root, hash(root->first), buckets, newnbuckets); root = next; } @@ -195,12 +203,13 @@ namespace tinystl { result.second = false; result.first = find(key); - if (result.first.node != 0) + if (result.first.node != nullptr) return result; unordered_hash_node* newnode = new(placeholder(), Alloc::static_allocate(sizeof(unordered_hash_node))) unordered_hash_node(key); - newnode->next = newnode->prev = 0; + newnode->next = newnode->prev = nullptr; + if(!m_buckets.first) buffer_resize(&m_buckets, 9, 0); const size_t nbuckets = (size_t)(m_buckets.last - m_buckets.first); unordered_hash_node_insert(newnode, hash(key), m_buckets.first, nbuckets - 1); @@ -218,13 +227,14 @@ namespace tinystl { result.second = false; result.first = find(key); - if (result.first.node != 0) + if (result.first.node != nullptr) return result; const size_t keyhash = hash(key); unordered_hash_node* newnode = new(placeholder(), Alloc::static_allocate(sizeof(unordered_hash_node))) unordered_hash_node(static_cast(key)); - newnode->next = newnode->prev = 0; + newnode->next = newnode->prev = nullptr; + if(!m_buckets.first) buffer_resize(&m_buckets, 9, 0); const size_t nbuckets = (size_t)(m_buckets.last - m_buckets.first); unordered_hash_node_insert(newnode, keyhash, m_buckets.first, nbuckets - 1); @@ -248,7 +258,7 @@ namespace tinystl { template inline size_t unordered_set::erase(const Key& key) { const iterator it = find(key); - if (it.node == 0) + if (it.node == nullptr) return 0; erase(it); diff --git a/test/string.cpp b/test/string.cpp index 958363d..b65cee1 100644 --- a/test/string.cpp +++ b/test/string.cpp @@ -84,4 +84,40 @@ TEST(string_assign) { CHECK( 0 == strcmp(s.c_str(), "hello") ); CHECK( other.size() == 0 ); } + + { + const string other("hello longer string here"); + string s("short"); + s = other; + + CHECK( s.size() == 24 ); + CHECK( 0 == strcmp(s.c_str(), "hello longer string here") ); + } + { + string other("hello longer string here"); + string s("short"); + s = std::move(other); + + CHECK( s.size() == 24 ); + CHECK( 0 == strcmp(s.c_str(), "hello longer string here") ); + CHECK( other.size() == 0 ); + } + + { + const string other("short"); + string s("hello longer string here"); + s = other; + + CHECK( s.size() == 5 ); + CHECK( 0 == strcmp(s.c_str(), "short") ); + } + { + string other("short"); + string s("hello longer string here"); + s = std::move(other); + + CHECK( s.size() == 5 ); + CHECK( 0 == strcmp(s.c_str(), "short") ); + CHECK( other.size() == 0 ); + } } diff --git a/test/unordered_map.cpp b/test/unordered_map.cpp index eb89d07..0d2adbc 100644 --- a/test/unordered_map.cpp +++ b/test/unordered_map.cpp @@ -46,6 +46,7 @@ TEST(uomap_constructor) { using tinystl::make_pair; unordered_map baseline; + comparemaps(baseline, baseline); // test with empty maps baseline.insert(make_pair(5, 1)); baseline.insert(make_pair(6, 2)); CHECK( 2 == baseline.size() ); @@ -184,3 +185,20 @@ TEST(uomap_insert) { CHECK( p.second.size() == 0 ); } } + +TEST(uomap_iterate) { + typedef tinystl::unordered_map unordered_map; + { + unordered_map m; + for (size_t i = 0; i < 1000; ++i) { + CHECK( m.size() == i ); + size_t count = 0; + for (auto it = m.begin(); it != m.end(); ++it) { + count++; + } + CHECK( count == i ); + + m.insert(tinystl::make_pair(17 * i, 101 * i)); + } + } +} diff --git a/test/unordered_set.cpp b/test/unordered_set.cpp index 343a971..1b21032 100644 --- a/test/unordered_set.cpp +++ b/test/unordered_set.cpp @@ -43,6 +43,7 @@ TEST(uoset_constructor) { typedef tinystl::unordered_set unordered_set; unordered_set baseline; + comparesets(baseline, baseline); // test on empty baseline.insert(5); baseline.insert(6); CHECK( 2 == baseline.size() ); @@ -170,3 +171,20 @@ TEST(uoset_insert) { CHECK( key.size() == 0 ); } } + +TEST(uoset_iterate) { + typedef tinystl::unordered_set unordered_set; + { + unordered_set s; + for (size_t i = 0; i < 1000; ++i) { + CHECK( s.size() == i ); + size_t count = 0; + for (auto it = s.begin(); it != s.end(); ++it) { + count++; + } + CHECK( count == i ); + + s.insert(int(17 * i)); + } + } +}