diff --git a/include/tinystl/LICENSE b/include/tinystl/LICENSE index f03d947..bfea591 100644 --- a/include/tinystl/LICENSE +++ b/include/tinystl/LICENSE @@ -1,4 +1,4 @@ - Copyright 2012 Matthew Endsley + Copyright 2012-2018 Matthew Endsley All rights reserved Redistribution and use in source and binary forms, with or without diff --git a/include/tinystl/allocator.h b/include/tinystl/allocator.h index a0cce7b..ce3efe0 100644 --- a/include/tinystl/allocator.h +++ b/include/tinystl/allocator.h @@ -1,5 +1,5 @@ /*- - * Copyright 2012 Matthew Endsley + * Copyright 2012-2018 Matthew Endsley * All rights reserved * * Redistribution and use in source and binary forms, with or without @@ -27,9 +27,7 @@ #ifndef TINYSTL_ALLOCATOR_H #define TINYSTL_ALLOCATOR_H -#include "stddef.h" - -#ifndef TINYSTL_ALLOCATOR +#include namespace tinystl { @@ -44,7 +42,8 @@ namespace tinystl { }; } +#ifndef TINYSTL_ALLOCATOR # define TINYSTL_ALLOCATOR ::tinystl::allocator -#endif // TINYSTL_ALLOCATOR +#endif #endif diff --git a/include/tinystl/buffer.h b/include/tinystl/buffer.h index 4351ec2..efc5c9c 100644 --- a/include/tinystl/buffer.h +++ b/include/tinystl/buffer.h @@ -1,5 +1,5 @@ /*- - * Copyright 2012-1015 Matthew Endsley + * Copyright 2012-2018 Matthew Endsley * All rights reserved * * Redistribution and use in source and binary forms, with or without @@ -27,8 +27,9 @@ #ifndef TINYSTL_BUFFER_H #define TINYSTL_BUFFER_H -#include "new.h" -#include "traits.h" +#include +#include +#include namespace tinystl { @@ -140,7 +141,7 @@ namespace tinystl { template static inline void buffer_reserve(buffer* b, size_t capacity) { - if (b->first + capacity <= b->capacity) + if (b->first && b->first + capacity <= b->capacity) return; typedef T* pointer; @@ -174,19 +175,21 @@ namespace tinystl { template static inline void buffer_shrink_to_fit(buffer* b) { - if (b->last == b->first) { - const size_t capacity = (size_t)(b->last - b->first); - Alloc::static_deallocate(b->first, sizeof(T)*capacity); - b->capacity = b->first; - } else if (b->capacity != b->last) { - const size_t capacity = (size_t)(b->capacity - b->first); - const size_t size = (size_t)(b->last - b->first); - T* newfirst = (T*)Alloc::static_allocate(sizeof(T) * size); - buffer_move_urange(newfirst, b->first, b->last); - Alloc::static_deallocate(b->first, sizeof(T) * capacity); - b->first = newfirst; - b->last = newfirst + size; - b->capacity = b->last; + if (b->capacity != b->last) { + if (b->last == b->first) { + const size_t capacity = (size_t)(b->capacity - b->first); + Alloc::static_deallocate(b->first, sizeof(T)*capacity); + b->capacity = b->first = b->last = nullptr; + } else { + const size_t capacity = (size_t)(b->capacity - b->first); + const size_t size = (size_t)(b->last - b->first); + T* newfirst = (T*)Alloc::static_allocate(sizeof(T) * size); + buffer_move_urange(newfirst, b->first, b->last); + Alloc::static_deallocate(b->first, sizeof(T) * capacity); + b->first = newfirst; + b->last = newfirst + size; + b->capacity = b->last; + } } } @@ -200,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; @@ -215,7 +218,21 @@ namespace tinystl { template static inline void buffer_insert(buffer* b, T* where, const Param* first, const Param* last) { - where = buffer_insert_common(b, where, last - first); + typedef const char* pointer; + const size_t count = last - first; + const bool frombuf = ((pointer)b->first <= (pointer)first && (pointer)b->last >= (pointer)last); + size_t offset; + if (frombuf) { + offset = (pointer)first - (pointer)b->first; + if ((pointer)where <= (pointer)first) + offset += count * sizeof(T); + where = buffer_insert_common(b, where, count); + first = (Param*)((pointer)b->first + offset); + last = first + count; + } + else { + where = buffer_insert_common(b, where, count); + } for (; first != last; ++first, ++where) new(placeholder(), where) T(*first); } @@ -223,7 +240,7 @@ namespace tinystl { 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) + for (T* end = where+count; where != end; ++where) new(placeholder(), where) T(); } @@ -250,28 +267,28 @@ namespace tinystl { template static inline T* buffer_erase(buffer* b, T* first, T* last) { typedef T* pointer; - const size_t range = (last - first); + const size_t count = (last - first); for (pointer it = last, end = b->last, dest = first; it != end; ++it, ++dest) move(*dest, *it); - buffer_destroy_range(b->last - range, b->last); + buffer_destroy_range(b->last - count, b->last); - b->last -= range; + b->last -= count; return first; } template static inline T* buffer_erase_unordered(buffer* b, T* first, T* last) { typedef T* pointer; - const size_t range = (last - first); + const size_t count = (last - first); const size_t tail = (b->last - last); - pointer it = b->last - ((range < tail) ? range : tail); + pointer it = b->last - ((count < tail) ? count : tail); for (pointer end = b->last, dest = first; it != end; ++it, ++dest) move(*dest, *it); - buffer_destroy_range(b->last - range, b->last); + buffer_destroy_range(b->last - count, b->last); - b->last -= range; + b->last -= count; return first; } @@ -282,6 +299,12 @@ namespace tinystl { b->first = other->first, b->last = other->last, b->capacity = other->capacity; other->first = tfirst, other->last = tlast, other->capacity = tcapacity; } + + template + static inline void buffer_move(buffer* dst, buffer* src) { + dst->first = src->first, dst->last = src->last, dst->capacity = src->capacity; + src->first = src->last = src->capacity = nullptr; + } } -#endif +#endif //TINYSTL_BUFFER_H diff --git a/include/tinystl/hash.h b/include/tinystl/hash.h index 787ddae..55f9788 100644 --- a/include/tinystl/hash.h +++ b/include/tinystl/hash.h @@ -1,5 +1,5 @@ /*- - * Copyright 2012 Matthew Endsley + * Copyright 2012-2018 Matthew Endsley * All rights reserved * * Redistribution and use in source and binary forms, with or without @@ -27,7 +27,7 @@ #ifndef TINYSTL_STRINGHASH_H #define TINYSTL_STRINGHASH_H -#include "stddef.h" +#include namespace tinystl { diff --git a/include/tinystl/hash_base.h b/include/tinystl/hash_base.h index f20675d..aac60f0 100644 --- a/include/tinystl/hash_base.h +++ b/include/tinystl/hash_base.h @@ -1,5 +1,5 @@ /*- - * Copyright 2012 Matthew Endsley + * Copyright 2012-2018 Matthew Endsley * All rights reserved * * Redistribution and use in source and binary forms, with or without @@ -27,42 +27,98 @@ #ifndef TINYSTL_HASH_BASE_H #define TINYSTL_HASH_BASE_H -#include "stddef.h" +#include +#include namespace tinystl { template struct pair { - typedef Key first_type; - typedef Value second_type; - pair(); + pair(const pair& other); + pair(pair&& other); pair(const Key& key, const Value& value); + pair(Key&& key, Value&& value); + + pair& operator=(const pair& other); + pair& operator=(pair&& other); Key first; Value second; + + using first_type = Key; + using second_type = Value; }; template - pair::pair() { + inline pair::pair() { } template - pair::pair(const Key& key, const Value& value) + inline pair::pair(const pair& other) + : first(other.first) + , second(other.second) + { + } + + template + inline pair::pair(pair&& other) + : first(static_cast(other.first)) + , second(static_cast(other.second)) + { + } + + template + inline pair::pair(const Key& key, const Value& value) : first(key) , second(value) { } + template + inline pair::pair(Key&& key, Value&& value) + : first(static_cast(key)) + , second(static_cast(value)) + { + } + + template + inline pair& pair::operator=(const pair& other) { + first = other.first; + second = other.second; + return *this; + } + + template + inline pair& pair::operator=(pair&& other) { + first = static_cast(other.first); + second = static_cast(other.second); + return *this; + } + + // Replaced the following function by the old-school const& variant, until + // https://github.com/mendsley/tinystl/issues/25 is fixed. +#if 0 + template + static inline pair::type, typename remove_reference::type> + make_pair(Key&& key, Value&& value) { + return pair::type, typename remove_reference::type>( + static_cast(key) + , static_cast(value) + ); + } +#else template static inline pair make_pair(const Key& key, const Value& value) { return pair(key, value); } +#endif template struct unordered_hash_node { unordered_hash_node(const Key& key, const Value& value); + unordered_hash_node(Key&& key, Value&& value); const Key first; Value second; @@ -74,15 +130,23 @@ namespace tinystl { }; template - unordered_hash_node::unordered_hash_node(const Key& key, const Value& value) + inline unordered_hash_node::unordered_hash_node(const Key& key, const Value& value) : first(key) , second(value) { } + template + inline unordered_hash_node::unordered_hash_node(Key&& key, Value&& value) + : first(static_cast(key)) + , second(static_cast(value)) + { + } + template struct unordered_hash_node { - unordered_hash_node(const Key& key); + explicit unordered_hash_node(const Key& key); + explicit unordered_hash_node(Key&& key); const Key first; unordered_hash_node* next; @@ -93,13 +157,19 @@ namespace tinystl { }; template - unordered_hash_node::unordered_hash_node(const Key& key) + inline unordered_hash_node::unordered_hash_node(const Key& key) : first(key) { } + template + inline unordered_hash_node::unordered_hash_node(Key&& key) + : first(static_cast(key)) + { + } + template - static void unordered_hash_node_insert(unordered_hash_node* node, size_t hash, unordered_hash_node** buckets, size_t nbuckets) { + static inline void unordered_hash_node_insert(unordered_hash_node* node, size_t hash, unordered_hash_node** buckets, size_t nbuckets) { size_t bucket = hash & (nbuckets - 1); unordered_hash_node* it = buckets[bucket + 1]; @@ -223,6 +293,7 @@ namespace tinystl { template static inline Node unordered_hash_find(const Key& key, Node* buckets, size_t nbuckets) { + if (!buckets) return 0; const size_t bucket = hash(key) & (nbuckets - 2); for (Node it = buckets[bucket], end = buckets[bucket+1]; it != end; it = it->next) if (it->first == key) diff --git a/include/tinystl/new.h b/include/tinystl/new.h index 9c86dd8..62bb072 100644 --- a/include/tinystl/new.h +++ b/include/tinystl/new.h @@ -1,5 +1,5 @@ /*- - * Copyright 2012 Matthew Endsley + * Copyright 2012-2018 Matthew Endsley * All rights reserved * * Redistribution and use in source and binary forms, with or without @@ -27,7 +27,7 @@ #ifndef TINYSTL_NEW_H #define TINYSTL_NEW_H -#include "stddef.h" +#include namespace tinystl { diff --git a/include/tinystl/stddef.h b/include/tinystl/stddef.h index 21c1b1e..a31dd34 100644 --- a/include/tinystl/stddef.h +++ b/include/tinystl/stddef.h @@ -1,5 +1,5 @@ /*- - * Copyright 2012 Matthew Endsley + * Copyright 2012-2018 Matthew Endsley * All rights reserved * * Redistribution and use in source and binary forms, with or without @@ -29,10 +29,13 @@ #if defined(_WIN64) typedef long long unsigned int size_t; + typedef long long int ptrdiff_t; #elif defined(_WIN32) typedef unsigned int size_t; -#elif defined (__linux__) && defined(__SIZE_TYPE__) + typedef int ptrdiff_t; +#elif defined (__linux__) && defined(__SIZE_TYPE__) && defined(__PTRDIFF_TYPE__) typedef __SIZE_TYPE__ size_t; + typedef __PTRDIFF_TYPE__ ptrdiff_t; #else # include #endif diff --git a/include/tinystl/string.h b/include/tinystl/string.h index 4d90c2a..3c3cb65 100644 --- a/include/tinystl/string.h +++ b/include/tinystl/string.h @@ -1,5 +1,5 @@ /*- - * Copyright 2012 Matthew Endsley + * Copyright 2012-2018 Matthew Endsley * All rights reserved * * Redistribution and use in source and binary forms, with or without @@ -27,34 +27,37 @@ #ifndef TINYSTL_STRING_H #define TINYSTL_STRING_H -#include // strlen -#include "stddef.h" -#include "hash.h" +#include +#include +#include namespace tinystl { - template - class stringT { + template + class basic_string { public: - stringT(); - stringT(const stringT& other); - stringT(const char* sz); - stringT(const char* sz, size_t len); - ~stringT(); + basic_string(); + basic_string(const basic_string& other); + basic_string(basic_string&& other); + basic_string(const char* sz); + basic_string(const char* sz, size_t len); + ~basic_string(); - stringT& operator=(const stringT& other); + basic_string& operator=(const basic_string& other); + basic_string& operator=(basic_string&& other); const char* c_str() const; size_t size() const; - bool empty() const; - void reserve(size_t _size); - void resize(size_t _size); + void reserve(size_t size); + void resize(size_t size); + void clear(); void append(const char* first, const char* last); - void append(const char* str); + void assign(const char* s, size_t n); - void swap(stringT& other); + void shrink_to_fit(); + void swap(basic_string& other); private: typedef char* pointer; @@ -66,10 +69,8 @@ namespace tinystl { char m_buffer[12]; }; - typedef stringT string; - - template - inline stringT::stringT() + template + inline basic_string::basic_string() : m_first(m_buffer) , m_last(m_buffer) , m_capacity(m_buffer + c_nbuffer) @@ -77,8 +78,8 @@ namespace tinystl { resize(0); } - template - inline stringT::stringT(const stringT& other) + template + inline basic_string::basic_string(const basic_string& other) : m_first(m_buffer) , m_last(m_buffer) , m_capacity(m_buffer + c_nbuffer) @@ -87,8 +88,27 @@ namespace tinystl { append(other.m_first, other.m_last); } - template - inline stringT::stringT(const char* sz) + template + inline basic_string::basic_string(basic_string&& other) + { + if (other.m_first == other.m_buffer) { + m_first = m_buffer; + m_last = m_buffer; + m_capacity = m_buffer + c_nbuffer; + reserve(other.size()); + append(other.m_first, other.m_last); + } else { + m_first = other.m_first; + m_last = other.m_last; + m_capacity = other.m_capacity; + } + other.m_first = other.m_last = other.m_buffer; + other.m_capacity = other.m_buffer + c_nbuffer; + other.resize(0); + } + + template + inline basic_string::basic_string(const char* sz) : m_first(m_buffer) , m_last(m_buffer) , m_capacity(m_buffer + c_nbuffer) @@ -101,8 +121,8 @@ namespace tinystl { append(sz, sz + len); } - template - inline stringT::stringT(const char* sz, size_t len) + template + inline basic_string::basic_string(const char* sz, size_t len) : m_first(m_buffer) , m_last(m_buffer) , m_capacity(m_buffer + c_nbuffer) @@ -111,68 +131,73 @@ namespace tinystl { append(sz, sz + len); } - template - inline stringT::~stringT() { + template + inline basic_string::~basic_string() { if (m_first != m_buffer) - Alloc::static_deallocate(m_first, m_capacity - m_first); + allocator::static_deallocate(m_first, m_capacity - m_first); } - template - inline stringT& stringT::operator=(const stringT& other) { - stringT(other).swap(*this); + template + inline basic_string& basic_string::operator=(const basic_string& other) { + basic_string(other).swap(*this); return *this; } - template - inline const char* stringT::c_str() const { + template + inline basic_string& basic_string::operator=(basic_string&& other) { + basic_string(static_cast(other)).swap(*this); + return *this; + } + + template + inline const char* basic_string::c_str() const { return m_first; } - template - inline size_t stringT::size() const + template + inline size_t basic_string::size() const { return (size_t)(m_last - m_first); } - template - inline bool stringT::empty() const - { - return 0 == size(); - } - - template - inline void stringT::reserve(size_t capacity) { - if (m_first + capacity + 1 <= m_capacity) { + template + inline void basic_string::reserve(size_t capacity) { + if (m_first + capacity + 1 <= m_capacity) return; - } - const size_t _size = (size_t)(m_last - m_first); + const size_t size = (size_t)(m_last - m_first); - pointer newfirst = (pointer)Alloc::static_allocate(capacity + 1); - for (pointer it = m_first, newit = newfirst, end = m_last; it != end; ++it, ++newit) { + pointer newfirst = (pointer)allocator::static_allocate(capacity + 1); + for (pointer it = m_first, newit = newfirst, end = m_last; it != end; ++it, ++newit) *newit = *it; - } - - if (m_first != m_buffer) { - Alloc::static_deallocate(m_first, m_capacity - m_first); - } + if (m_first != m_buffer) + allocator::static_deallocate(m_first, m_capacity - m_first); m_first = newfirst; - m_last = newfirst + _size; + m_last = newfirst + size; m_capacity = m_first + capacity; } - template - inline void stringT::resize(size_t _size) { - reserve(_size); - for (pointer it = m_last, end = m_first + _size + 1; it < end; ++it) - *it = 0; + template + inline void basic_string::resize(size_t size) { + const size_t prevSize = m_last-m_first; + reserve(size); + if (size > prevSize) + for (pointer it = m_last, end = m_first + size + 1; it < end; ++it) + *it = 0; + else if (m_last != m_first) + m_first[size] = 0; - m_last += _size; + m_last = m_first + size; } - template - inline void stringT::append(const char* first, const char* last) { + template + inline void basic_string::clear() { + resize(0); + } + + 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); if (m_first + newsize > m_capacity) reserve((newsize * 3) / 2); @@ -182,13 +207,35 @@ namespace tinystl { *m_last = 0; } - template - inline void stringT::append(const char* str) { - append(str, str + strlen(str) ); + template + inline void basic_string::assign(const char* sz, size_t n) { + clear(); + append(sz, sz+n); } - template - inline void stringT::swap(stringT& other) { + template + 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); + 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); + char* newfirst = (pointer)allocator::static_allocate(size+1); + for (pointer in = m_first, out = newfirst; in != m_last + 1; ++in, ++out) + *out = *in; + if (m_first != m_capacity) + allocator::static_deallocate(m_first, m_capacity+1-m_first); + m_first = newfirst; + m_last = newfirst+size; + m_capacity = m_last; + } + } + + 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; @@ -220,8 +267,8 @@ namespace tinystl { } } - template - inline bool operator==(const stringT& lhs, const stringT& rhs) { + template + inline bool operator==(const basic_string& lhs, const basic_string& rhs) { typedef const char* pointer; const size_t lsize = lhs.size(), rsize = rhs.size(); @@ -237,10 +284,12 @@ namespace tinystl { return true; } - template - static inline size_t hash(const stringT& value) { + template + static inline size_t hash(const basic_string& value) { return hash_string(value.c_str(), value.size()); } + + typedef basic_string string; } #endif diff --git a/include/tinystl/string_view.h b/include/tinystl/string_view.h new file mode 100644 index 0000000..13a714d --- /dev/null +++ b/include/tinystl/string_view.h @@ -0,0 +1,147 @@ +/*- + * Copyright 2012-1017 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. + */ + +#ifndef TINYSTL_STRING_VIEW_H +#define TINYSTL_STRING_VIEW_H + +#include + +namespace tinystl { + + class string_view + { + public: + typedef char value_type; + typedef char* pointer; + typedef const char* const_pointer; + typedef char& reference; + typedef const char& const_reference; + typedef const_pointer iterator; + typedef const_pointer const_iterator; + typedef size_t size_type; + typedef ptrdiff_t difference_type; + + static constexpr size_type npos = size_type(-1); + + constexpr string_view(); + constexpr string_view(const char* s, size_type count); + constexpr string_view(const char* s); + constexpr string_view(const string_view&) = default; + string_view& operator=(const string_view&) = default; + + constexpr const char* data() const; + constexpr char operator[](size_type pos) const; + constexpr size_type size() const; + constexpr bool empty() const; + constexpr iterator begin() const; + constexpr const_iterator cbegin() const; + constexpr iterator end() const; + constexpr const_iterator cend() const; + constexpr string_view substr(size_type pos = 0, size_type count = npos) const; + constexpr void swap(string_view& v); + + private: + string_view(decltype(nullptr)) = delete; + + static constexpr size_type strlen(const char*); + + const char* m_str; + size_type m_size; + }; + + constexpr string_view::string_view() + : m_str(nullptr) + , m_size(0) + { + } + + constexpr string_view::string_view(const char* s, size_type count) + : m_str(s) + , m_size(count) + { + } + + constexpr string_view::string_view(const char* s) + : m_str(s) + , m_size(strlen(s)) + { + } + + constexpr const char* string_view::data() const { + return m_str; + } + + constexpr char string_view::operator[](size_type pos) const { + return m_str[pos]; + } + + constexpr string_view::size_type string_view::size() const { + return m_size; + } + + constexpr bool string_view::empty() const { + return 0 == m_size; + } + + constexpr string_view::iterator string_view::begin() const { + return m_str; + } + + constexpr string_view::const_iterator string_view::cbegin() const { + return m_str; + } + + constexpr string_view::iterator string_view::end() const { + return m_str + m_size; + } + + constexpr string_view::const_iterator string_view::cend() const { + return m_str + m_size; + } + + constexpr string_view string_view::substr(size_type pos, size_type count) const { + return string_view(m_str + pos, npos == count ? m_size - pos : count); + } + + constexpr void string_view::swap(string_view& v) { + const char* strtmp = m_str; + size_type sizetmp = m_size; + m_str = v.m_str; + m_size = v.m_size; + v.m_str = strtmp; + v.m_size = sizetmp; + } + + constexpr string_view::size_type string_view::strlen(const char* s) { + for (size_t len = 0; ; ++len) { + if (0 == s[len]) { + return len; + } + } + } +} + +#endif // TINYSTL_STRING_VIEW_H diff --git a/include/tinystl/traits.h b/include/tinystl/traits.h index 11b18e7..6cb64fc 100644 --- a/include/tinystl/traits.h +++ b/include/tinystl/traits.h @@ -1,5 +1,5 @@ /*- - * Copyright 2012 Matthew Endsley + * Copyright 2012-2018 Matthew Endsley * All rights reserved * * Redistribution and use in source and binary forms, with or without @@ -27,9 +27,9 @@ #ifndef TINYSTL_TRAITS_H #define TINYSTL_TRAITS_H -#include "new.h" +#include -#if defined(__GNUC__) && defined(__is_pod) +#if defined(__GNUC__) # define TINYSTL_TRY_POD_OPTIMIZATION(t) __is_pod(t) #elif defined(_MSC_VER) # define TINYSTL_TRY_POD_OPTIMIZATION(t) (!__is_class(t) || __is_pod(t)) @@ -80,6 +80,21 @@ namespace tinystl { static inline void move_construct(T* a, T& b) { move_construct_impl(a, b, (T*)0); } + + template + struct remove_reference { + typedef T type; + }; + + template + struct remove_reference { + typedef T type; + }; + + template + struct remove_reference { + typedef T type; + }; } #endif diff --git a/include/tinystl/unordered_map.h b/include/tinystl/unordered_map.h index 64f8457..cc7df21 100644 --- a/include/tinystl/unordered_map.h +++ b/include/tinystl/unordered_map.h @@ -1,5 +1,5 @@ /*- - * Copyright 2012 Matthew Endsley + * Copyright 2012-2018 Matthew Endsley * All rights reserved * * Redistribution and use in source and binary forms, with or without @@ -27,9 +27,10 @@ #ifndef TINYSTL_UNORDERED_MAP_H #define TINYSTL_UNORDERED_MAP_H -#include "buffer.h" -#include "hash.h" -#include "hash_base.h" +#include +#include +#include +#include namespace tinystl { @@ -38,13 +39,14 @@ namespace tinystl { public: unordered_map(); unordered_map(const unordered_map& other); + unordered_map(unordered_map&& other); ~unordered_map(); unordered_map& operator=(const unordered_map& other); - + unordered_map& operator=(unordered_map&& other); typedef pair value_type; - + typedef unordered_hash_iterator > const_iterator; typedef unordered_hash_iterator > iterator; @@ -61,6 +63,7 @@ namespace tinystl { const_iterator find(const Key& key) const; iterator find(const Key& key); pair insert(const pair& p); + pair emplace(pair&& p); void erase(const_iterator where); Value& operator[](const Key& key); @@ -69,22 +72,23 @@ namespace tinystl { private: + void rehash(size_t nbuckets); + typedef unordered_hash_node* pointer; size_t m_size; - buffer m_buckets; + tinystl::buffer m_buckets; }; template - unordered_map::unordered_map() + inline unordered_map::unordered_map() : m_size(0) { buffer_init(&m_buckets); - buffer_resize(&m_buckets, 9, 0); } template - unordered_map::unordered_map(const unordered_map& other) + inline unordered_map::unordered_map(const unordered_map& other) : m_size(other.m_size) { const size_t nbuckets = (size_t)(other.m_buckets.last - other.m_buckets.first); @@ -100,17 +104,32 @@ namespace tinystl { } template - unordered_map::~unordered_map() { - clear(); + inline unordered_map::unordered_map(unordered_map&& other) + : m_size(other.m_size) + { + buffer_move(&m_buckets, &other.m_buckets); + other.m_size = 0; + } + + template + inline unordered_map::~unordered_map() { + if (m_buckets.first != m_buckets.last) + clear(); buffer_destroy(&m_buckets); } template - unordered_map& unordered_map::operator=(const unordered_map& other) { + inline unordered_map& unordered_map::operator=(const unordered_map& other) { unordered_map(other).swap(*this); return *this; } + template + inline unordered_map& unordered_map::operator=(unordered_map&& other) { + unordered_map(static_cast(other)).swap(*this); + return *this; + } + template inline typename unordered_map::iterator unordered_map::begin() { iterator it; @@ -180,24 +199,10 @@ namespace tinystl { } template - inline pair::iterator, bool> unordered_map::insert(const pair& p) { - pair result; - result.second = false; - - result.first = find(p.first); - if (result.first.node != 0) - 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; - - const size_t nbuckets = (size_t)(m_buckets.last - m_buckets.first); - unordered_hash_node_insert(newnode, hash(p.first), m_buckets.first, nbuckets - 1); - - ++m_size; + inline void unordered_map::rehash(size_t nbuckets) { if (m_size + 1 > 4 * nbuckets) { pointer root = *m_buckets.first; - + const size_t newnbuckets = ((size_t)(m_buckets.last - m_buckets.first) - 1) * 8; m_buckets.last = m_buckets.first; buffer_resize(&m_buckets, newnbuckets + 1, 0); @@ -210,6 +215,26 @@ namespace tinystl { root = next; } } + } + + template + inline pair::iterator, bool> unordered_map::insert(const pair& p) { + pair result; + result.second = false; + + result.first = find(p.first); + if (result.first.node != 0) + 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; + + 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(p.first), m_buckets.first, nbuckets - 1); + + ++m_size; + rehash(nbuckets); result.first.node = newnode; result.second = true; @@ -217,7 +242,32 @@ namespace tinystl { } template - void unordered_map::erase(const_iterator where) { + inline pair::iterator, bool> unordered_map::emplace(pair&& p) { + pair result; + result.second = false; + + result.first = find(p.first); + if (result.first.node != 0) + return result; + + const size_t keyhash = hash(p.first); + unordered_hash_node* newnode = new(placeholder(), Alloc::static_allocate(sizeof(unordered_hash_node))) unordered_hash_node(static_cast(p.first), static_cast(p.second)); + newnode->next = newnode->prev = 0; + + 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); + + ++m_size; + rehash(nbuckets); + + result.first.node = newnode; + result.second = true; + return result; + } + + template + inline void unordered_map::erase(const_iterator where) { unordered_hash_node_erase(where.node, hash(where->first), m_buckets.first, (size_t)(m_buckets.last - m_buckets.first) - 1); where->~unordered_hash_node(); @@ -226,12 +276,12 @@ namespace tinystl { } template - Value& unordered_map::operator[](const Key& key) { + inline Value& unordered_map::operator[](const Key& key) { return insert(pair(key, Value())).first->second; } template - void unordered_map::swap(unordered_map& other) { + inline void unordered_map::swap(unordered_map& other) { size_t tsize = other.m_size; other.m_size = m_size, m_size = tsize; buffer_swap(&m_buckets, &other.m_buckets); diff --git a/include/tinystl/unordered_set.h b/include/tinystl/unordered_set.h index 976a412..66a6a0b 100644 --- a/include/tinystl/unordered_set.h +++ b/include/tinystl/unordered_set.h @@ -1,5 +1,5 @@ /*- - * Copyright 2012 Matthew Endsley + * Copyright 2012-2018 Matthew Endsley * All rights reserved * * Redistribution and use in source and binary forms, with or without @@ -27,9 +27,10 @@ #ifndef TINYSTL_UNORDERED_SET_H #define TINYSTL_UNORDERED_SET_H -#include "buffer.h" -#include "hash.h" -#include "hash_base.h" +#include +#include +#include +#include namespace tinystl { @@ -38,9 +39,11 @@ namespace tinystl { public: unordered_set(); unordered_set(const unordered_set& other); + unordered_set(unordered_set&& other); ~unordered_set(); unordered_set& operator=(const unordered_set& other); + unordered_set& operator=(unordered_set&& other); typedef unordered_hash_iterator > const_iterator; typedef const_iterator iterator; @@ -54,6 +57,7 @@ namespace tinystl { iterator find(const Key& key) const; pair insert(const Key& key); + pair emplace(Key&& key); void erase(iterator where); size_t erase(const Key& key); @@ -61,14 +65,16 @@ namespace tinystl { private: + void rehash(size_t nbuckets); + typedef unordered_hash_node* pointer; size_t m_size; - buffer m_buckets; + tinystl::buffer m_buckets; }; template - unordered_set::unordered_set() + inline unordered_set::unordered_set() : m_size(0) { buffer_init(&m_buckets); @@ -76,7 +82,7 @@ namespace tinystl { } template - unordered_set::unordered_set(const unordered_set& other) + inline unordered_set::unordered_set(const unordered_set& other) : m_size(other.m_size) { const size_t nbuckets = (size_t)(other.m_buckets.last - other.m_buckets.first); @@ -91,17 +97,32 @@ namespace tinystl { } template - unordered_set::~unordered_set() { - clear(); + inline unordered_set::unordered_set(unordered_set&& other) + : m_size(other.m_size) + { + buffer_move(&m_buckets, &other.m_buckets); + other.m_size = 0; + } + + template + inline unordered_set::~unordered_set() { + if (m_buckets.first != m_buckets.last) + clear(); buffer_destroy(&m_buckets); } template - unordered_set& unordered_set::operator=(const unordered_set& other) { + inline unordered_set& unordered_set::operator=(const unordered_set& other) { unordered_set(other).swap(*this); return *this; } + template + inline unordered_set& unordered_set::operator=(unordered_set&& other) { + unordered_set(static_cast(other)).swap(*this); + return *this; + } + template inline typename unordered_set::iterator unordered_set::begin() const { iterator cit; @@ -150,21 +171,7 @@ namespace tinystl { } template - inline pair::iterator, bool> unordered_set::insert(const Key& key) { - pair result; - result.second = false; - - result.first = find(key); - if (result.first.node != 0) - return result; - - unordered_hash_node* newnode = new(placeholder(), Alloc::static_allocate(sizeof(unordered_hash_node))) unordered_hash_node(key); - newnode->next = newnode->prev = 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); - - ++m_size; + inline void unordered_set::rehash(size_t nbuckets) { if (m_size + 1 > 4 * nbuckets) { pointer root = *m_buckets.first; @@ -180,6 +187,49 @@ namespace tinystl { root = next; } } + } + + template + inline pair::iterator, bool> unordered_set::insert(const Key& key) { + pair result; + result.second = false; + + result.first = find(key); + if (result.first.node != 0) + return result; + + unordered_hash_node* newnode = new(placeholder(), Alloc::static_allocate(sizeof(unordered_hash_node))) unordered_hash_node(key); + newnode->next = newnode->prev = 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); + + ++m_size; + rehash(nbuckets); + + result.first.node = newnode; + result.second = true; + return result; + } + + template + inline pair::iterator, bool> unordered_set::emplace(Key&& key) { + pair result; + result.second = false; + + result.first = find(key); + if (result.first.node != 0) + 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; + + const size_t nbuckets = (size_t)(m_buckets.last - m_buckets.first); + unordered_hash_node_insert(newnode, keyhash, m_buckets.first, nbuckets - 1); + + ++m_size; + rehash(nbuckets); result.first.node = newnode; result.second = true; diff --git a/include/tinystl/vector.h b/include/tinystl/vector.h index 6885feb..e248f62 100644 --- a/include/tinystl/vector.h +++ b/include/tinystl/vector.h @@ -1,5 +1,5 @@ /*- - * Copyright 2012-1015 Matthew Endsley + * Copyright 2012-2018 Matthew Endsley * All rights reserved * * Redistribution and use in source and binary forms, with or without @@ -27,23 +27,25 @@ #ifndef TINYSTL_VECTOR_H #define TINYSTL_VECTOR_H -#include "buffer.h" -#include "new.h" -#include "stddef.h" +#include +#include +#include +#include namespace tinystl { - template class vector { public: vector(); vector(const vector& other); - vector(size_t _size); - vector(size_t _size, const T& value); + vector(vector&& other); + vector(size_t size); + vector(size_t size, const T& value); vector(const T* first, const T* last); ~vector(); vector& operator=(const vector& other); + vector& operator=(vector&& other); void assign(const T* first, const T* last); @@ -64,7 +66,7 @@ namespace tinystl { void resize(size_t size); void resize(size_t size, const T& value); void clear(); - void reserve(size_t _capacity); + void reserve(size_t capacity); void push_back(const T& t); void pop_back(); @@ -117,15 +119,20 @@ namespace tinystl { } template - inline vector::vector(size_t _size) { - buffer_init(&m_buffer); - buffer_resize(&m_buffer, _size); + inline vector::vector(vector&& other) { + buffer_move(&m_buffer, &other.m_buffer); } template - inline vector::vector(size_t _size, const T& value) { + inline vector::vector(size_t size) { buffer_init(&m_buffer); - buffer_resize(&m_buffer, _size, value); + buffer_resize(&m_buffer, size); + } + + template + inline vector::vector(size_t size, const T& value) { + buffer_init(&m_buffer); + buffer_resize(&m_buffer, size, value); } template @@ -145,6 +152,13 @@ namespace tinystl { return *this; } + template + vector& vector::operator=(vector&& other) { + buffer_destroy(&m_buffer); + buffer_move(&m_buffer, &other.m_buffer); + return *this; + } + template inline void vector::assign(const T* first, const T* last) { buffer_clear(&m_buffer); @@ -207,13 +221,13 @@ namespace tinystl { } template - inline void vector::resize(size_t _size) { - buffer_resize(&m_buffer, _size); + inline void vector::resize(size_t size) { + buffer_resize(&m_buffer, size); } template - inline void vector::resize(size_t _size, const T& value) { - buffer_resize(&m_buffer, _size, value); + inline void vector::resize(size_t size, const T& value) { + buffer_resize(&m_buffer, size, value); } template @@ -222,8 +236,8 @@ namespace tinystl { } template - inline void vector::reserve(size_t _capacity) { - buffer_reserve(&m_buffer, _capacity); + inline void vector::reserve(size_t capacity) { + buffer_reserve(&m_buffer, capacity); } template @@ -278,7 +292,7 @@ namespace tinystl { } template - inline void vector::insert(iterator where) { + inline void vector::insert(typename vector::iterator where) { buffer_insert(&m_buffer, where, 1); } @@ -314,9 +328,9 @@ namespace tinystl { template template - void vector::emplace(iterator where, const Param& param) { + void vector::emplace(typename vector::iterator where, const Param& param) { buffer_insert(&m_buffer, where, ¶m, ¶m + 1); } } -#endif +#endif // TINYSTL_VECTOR_H