From 99e35573d2aaa5e5c923386c7cdec6e6b21ab934 Mon Sep 17 00:00:00 2001 From: johndoe6345789 Date: Wed, 7 Jan 2026 19:54:17 +0000 Subject: [PATCH] Add TINYSTL string_view, traits, unordered_map, unordered_set, and vector implementations - Introduced string_view class for non-owning string references. - Added traits header for type traits and utility functions. - Implemented unordered_map class for hash table based key-value storage. - Created unordered_set class for hash table based unique key storage. - Developed vector class for dynamic array functionality with various utility methods. --- CMakeLists.txt | 28 ++- src/TINYSTL/allocator.h | 49 ++++++ src/TINYSTL/buffer.h | 310 +++++++++++++++++++++++++++++++++ src/TINYSTL/hash.h | 53 ++++++ src/TINYSTL/hash_base.h | 293 +++++++++++++++++++++++++++++++ src/TINYSTL/new.h | 43 +++++ src/TINYSTL/stddef.h | 43 +++++ src/TINYSTL/string.h | 295 +++++++++++++++++++++++++++++++ src/TINYSTL/string_view.h | 147 ++++++++++++++++ src/TINYSTL/traits.h | 100 +++++++++++ src/TINYSTL/unordered_map.h | 290 +++++++++++++++++++++++++++++++ src/TINYSTL/unordered_set.h | 265 ++++++++++++++++++++++++++++ src/TINYSTL/vector.h | 336 ++++++++++++++++++++++++++++++++++++ 13 files changed, 2251 insertions(+), 1 deletion(-) create mode 100644 src/TINYSTL/allocator.h create mode 100644 src/TINYSTL/buffer.h create mode 100644 src/TINYSTL/hash.h create mode 100644 src/TINYSTL/hash_base.h create mode 100644 src/TINYSTL/new.h create mode 100644 src/TINYSTL/stddef.h create mode 100644 src/TINYSTL/string.h create mode 100644 src/TINYSTL/string_view.h create mode 100644 src/TINYSTL/traits.h create mode 100644 src/TINYSTL/unordered_map.h create mode 100644 src/TINYSTL/unordered_set.h create mode 100644 src/TINYSTL/vector.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 18670d0..35f6c5a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -128,6 +128,7 @@ find_package(CLI11 CONFIG REQUIRED) find_package(RapidJSON CONFIG REQUIRED) find_package(EnTT CONFIG REQUIRED) find_package(bgfx CONFIG REQUIRED) +find_package(spirv-cross CONFIG REQUIRED) find_package(materialx CONFIG REQUIRED) find_package(Freetype CONFIG REQUIRED) find_package(lunasvg CONFIG REQUIRED) @@ -202,19 +203,44 @@ add_library(shaderc_local STATIC src/bgfx_tools/shaderc/shaderc_spirv.cpp src/bgfx_tools/shaderc/shaderc_utils.cpp ) -target_include_directories(shaderc_local PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/src/bgfx_tools/shaderc" "${CMAKE_CURRENT_SOURCE_DIR}/src" "${CMAKE_CURRENT_SOURCE_DIR}/src/bgfx_deps") +target_include_directories(shaderc_local PUBLIC + "${CMAKE_CURRENT_SOURCE_DIR}/src/bgfx_tools/shaderc" + "${CMAKE_CURRENT_SOURCE_DIR}/src/bgfx_deps/glslang" + "${CMAKE_CURRENT_SOURCE_DIR}/src/bgfx_deps/glslang/Include" + "${CMAKE_CURRENT_SOURCE_DIR}/src/bgfx_deps/glslang/glslang/Public") if(TARGET bgfx::bx) target_link_libraries(shaderc_local PUBLIC bgfx::bx) endif() if(TARGET bgfx::bgfx) target_link_libraries(shaderc_local PUBLIC bgfx::bgfx) endif() +if(TARGET spirv-cross::spirv-cross) + target_link_libraries(shaderc_local PUBLIC spirv-cross::spirv-cross) + target_include_directories(shaderc_local BEFORE PRIVATE + $) + target_compile_definitions(shaderc_local PRIVATE + $) + target_compile_options(shaderc_local PRIVATE + $) +endif() # Link shaderc dependencies if(TARGET glslang::glslang) target_link_libraries(shaderc_local PUBLIC glslang::glslang) + target_include_directories(shaderc_local PRIVATE + $) + target_compile_definitions(shaderc_local PRIVATE + $) + target_compile_options(shaderc_local PRIVATE + $) endif() if(TARGET spirv-tools::spirv-tools) target_link_libraries(shaderc_local PUBLIC spirv-tools::spirv-tools) + target_include_directories(shaderc_local PRIVATE + $) + target_compile_definitions(shaderc_local PRIVATE + $) + target_compile_options(shaderc_local PRIVATE + $) endif() if(TARGET shaderc::shaderc) target_link_libraries(shaderc_local PUBLIC shaderc::shaderc) diff --git a/src/TINYSTL/allocator.h b/src/TINYSTL/allocator.h new file mode 100644 index 0000000..685d98c --- /dev/null +++ b/src/TINYSTL/allocator.h @@ -0,0 +1,49 @@ +/*- + * Copyright 2012-2018 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_ALLOCATOR_H +#define TINYSTL_ALLOCATOR_H + +#include + +namespace tinystl { + + struct allocator { + static void* static_allocate(size_t bytes) { + return operator new(bytes); + } + + static void static_deallocate(void* ptr, size_t /*bytes*/) { + operator delete(ptr); + } + }; +} + +#ifndef TINYSTL_ALLOCATOR +# define TINYSTL_ALLOCATOR ::tinystl::allocator +#endif + +#endif diff --git a/src/TINYSTL/buffer.h b/src/TINYSTL/buffer.h new file mode 100644 index 0000000..a88cb3a --- /dev/null +++ b/src/TINYSTL/buffer.h @@ -0,0 +1,310 @@ +/*- + * Copyright 2012-2018 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_BUFFER_H +#define TINYSTL_BUFFER_H + +#include +#include +#include + +namespace tinystl { + + template + struct buffer { + T* first; + T* last; + T* capacity; + }; + + template + static inline void buffer_destroy_range_traits(T* first, T* last, pod_traits) { + for (; first < last; ++first) + first->~T(); + } + + template + static inline void buffer_destroy_range_traits(T*, T*, pod_traits) { + } + + template + static inline void buffer_destroy_range(T* first, T* last) { + 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) + new(placeholder(), first) T(value); + } + + template + static inline void buffer_fill_urange_traits(T* first, T* last, const T& value, pod_traits) { + for (; first < last; ++first) + *first = value; + } + + template + static inline void buffer_move_urange_traits(T* dest, T* first, T* last, pod_traits) { + for (T* it = first; it != last; ++it, ++dest) + move_construct(dest, *it); + buffer_destroy_range(first, last); + } + + template + static inline void buffer_move_urange_traits(T* dest, T* first, T* last, pod_traits) { + for (; first != last; ++first, ++dest) + *dest = *first; + } + + template + static inline void buffer_bmove_urange_traits(T* dest, T* first, T* last, pod_traits) { + dest += (last - first); + for (T* it = last; it != first; --it, --dest) { + move_construct(dest - 1, *(it - 1)); + buffer_destroy_range(it - 1, it); + } + } + + template + static inline void buffer_bmove_urange_traits(T* dest, T* first, T* last, pod_traits) { + dest += (last - first); + for (T* it = last; it != first; --it, --dest) + *(dest - 1) = *(it - 1); + } + + template + static inline void buffer_move_urange(T* dest, T* first, T* last) { + buffer_move_urange_traits(dest, first, last, pod_traits()); + } + + template + static inline void buffer_bmove_urange(T* dest, T* first, T* last) { + 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()); + } + + template + static inline void buffer_init(buffer* b) { + b->first = b->last = b->capacity = 0; + } + + template + static inline void buffer_destroy(buffer* b) { + buffer_destroy_range(b->first, b->last); + Alloc::static_deallocate(b->first, (size_t)((char*)b->capacity - (char*)b->first)); + } + + template + static inline void buffer_reserve(buffer* b, size_t capacity) { + if (b->first && b->first + capacity <= b->capacity) + return; + + typedef T* pointer; + const size_t size = (size_t)(b->last - b->first); + pointer newfirst = (pointer)Alloc::static_allocate(sizeof(T) * capacity); + 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 = 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); + + buffer_fill_urange(b->last, b->first + size, value); + buffer_destroy_range(b->first + size, b->last); + b->last = b->first + size; + } + + template + static inline void buffer_shrink_to_fit(buffer* b) { + 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; + } + } + } + + template + static inline void buffer_clear(buffer* b) { + buffer_destroy_range(b->first, b->last); + b->last = b->first; + } + + template + 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) + buffer_reserve(b, (newsize * 3) / 2); + + where = b->first + offset; + + 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) { + 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); + } + + template + static inline void buffer_insert(buffer* b, T* where, size_t count) { + where = buffer_insert_common(b, where, count); + for (T* end = where+count; where != end; ++where) + new(placeholder(), where) T(); + } + + template + static inline void buffer_append(buffer* b, const Param* param) { + if (b->capacity != b->last) { + new(placeholder(), b->last) T(*param); + ++b->last; + } else { + buffer_insert(b, b->last, param, param + 1); + } + } + + template + static inline void buffer_append(buffer* b) { + if (b->capacity != b->last) { + new(placeholder(), b->last) T(); + ++b->last; + } else { + buffer_insert(b, b->last, 1); + } + } + + template + static inline T* buffer_erase(buffer* b, T* first, T* last) { + typedef T* pointer; + 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 - count, b->last); + + b->last -= count; + return first; + } + + template + static inline T* buffer_erase_unordered(buffer* b, T* first, T* last) { + typedef T* pointer; + const size_t count = (last - first); + const size_t tail = (b->last - last); + 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 - count, b->last); + + b->last -= count; + return first; + } + + template + static inline void buffer_swap(buffer* b, buffer* other) { + typedef T* pointer; + const pointer tfirst = b->first, tlast = b->last, tcapacity = b->capacity; + 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 //TINYSTL_BUFFER_H diff --git a/src/TINYSTL/hash.h b/src/TINYSTL/hash.h new file mode 100644 index 0000000..c03b326 --- /dev/null +++ b/src/TINYSTL/hash.h @@ -0,0 +1,53 @@ +/*- + * Copyright 2012-2018 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_STRINGHASH_H +#define TINYSTL_STRINGHASH_H + +#include + +namespace tinystl { + + static inline size_t hash_string(const char* str, size_t len) { + // Implementation of sdbm a public domain string hash from Ozan Yigit + // see: http://www.eecs.harvard.edu/margo/papers/usenix91/paper.ps + + size_t hash = 0; + typedef const char* pointer; + for (pointer it = str, end = str + len; it != end; ++it) + hash = *it + (hash << 6) + (hash << 16) - hash; + + return hash; + } + + template + inline size_t hash(const T& value) { + const size_t asint = (size_t)value; + return hash_string((const char*)&asint, sizeof(asint)); + } +} + +#endif diff --git a/src/TINYSTL/hash_base.h b/src/TINYSTL/hash_base.h new file mode 100644 index 0000000..118c85e --- /dev/null +++ b/src/TINYSTL/hash_base.h @@ -0,0 +1,293 @@ +/*- + * Copyright 2012-2018 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_HASH_BASE_H +#define TINYSTL_HASH_BASE_H + +#include +#include + +namespace tinystl { + + template + struct pair { + 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; + }; + + template + inline pair::pair() { + } + + template + 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; + } + + 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) + ); + } + + + 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; + unordered_hash_node* next; + unordered_hash_node* prev; + + private: + unordered_hash_node& operator=(const unordered_hash_node&); + }; + + template + 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 { + explicit unordered_hash_node(const Key& key); + explicit unordered_hash_node(Key&& key); + + const Key first; + unordered_hash_node* next; + unordered_hash_node* prev; + + private: + unordered_hash_node& operator=(const unordered_hash_node&); + }; + + template + 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 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]; + node->next = it; + if (it) { + node->prev = it->prev; + it->prev = node; + if (node->prev) + node->prev->next = node; + } else { + size_t newbucket = bucket; + while (newbucket && !buckets[newbucket]) + --newbucket; + + unordered_hash_node* prev = buckets[newbucket]; + while (prev && prev->next) + prev = prev->next; + + node->prev = prev; + if (prev) + prev->next = node; + } + + // propagate node through buckets + for (; it == buckets[bucket]; --bucket) { + buckets[bucket] = node; + if (!bucket) + break; + } + } + + template + static inline void unordered_hash_node_erase(const unordered_hash_node* where, size_t hash, unordered_hash_node** buckets, size_t nbuckets) { + size_t bucket = hash & (nbuckets - 1); + + unordered_hash_node* next = where->next; + for (; buckets[bucket] == where; --bucket) { + buckets[bucket] = next; + if (!bucket) + break; + } + + if (where->prev) + where->prev->next = where->next; + if (next) + next->prev = where->prev; + } + + template + struct unordered_hash_iterator { + Node* operator->() const; + Node& operator*() const; + Node* node; + }; + + template + struct unordered_hash_iterator { + + unordered_hash_iterator() {} + unordered_hash_iterator(unordered_hash_iterator other) + : node(other.node) + { + } + + const Node* operator->() const; + const Node& operator*() const; + const Node* node; + }; + + template + struct unordered_hash_iterator > { + const Key* operator->() const; + const Key& operator*() const; + unordered_hash_node* node; + }; + + template + static inline bool operator==(const unordered_hash_iterator& lhs, const unordered_hash_iterator& rhs) { + return lhs.node == rhs.node; + } + + template + static inline bool operator!=(const unordered_hash_iterator& lhs, const unordered_hash_iterator& rhs) { + return lhs.node != rhs.node; + } + + template + static inline void operator++(unordered_hash_iterator& lhs) { + lhs.node = lhs.node->next; + } + + template + inline Node* unordered_hash_iterator::operator->() const { + return node; + } + + template + inline Node& unordered_hash_iterator::operator*() const { + return *node; + } + + template + inline const Node* unordered_hash_iterator::operator->() const { + return node; + } + + template + inline const Node& unordered_hash_iterator::operator*() const { + return *node; + } + + template + inline const Key* unordered_hash_iterator >::operator->() const { + return &node->first; + } + + template + inline const Key& unordered_hash_iterator >::operator*() const { + return node->first; + } + + 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) + return it; + + return 0; + } +} +#endif diff --git a/src/TINYSTL/new.h b/src/TINYSTL/new.h new file mode 100644 index 0000000..5f8a6f7 --- /dev/null +++ b/src/TINYSTL/new.h @@ -0,0 +1,43 @@ +/*- + * Copyright 2012-2018 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_NEW_H +#define TINYSTL_NEW_H + +#include + +namespace tinystl { + + struct placeholder {}; +} + +inline void* operator new(size_t, tinystl::placeholder, void* ptr) { + return ptr; +} + +inline void operator delete(void*, tinystl::placeholder, void*) throw() {} + +#endif diff --git a/src/TINYSTL/stddef.h b/src/TINYSTL/stddef.h new file mode 100644 index 0000000..a31dd34 --- /dev/null +++ b/src/TINYSTL/stddef.h @@ -0,0 +1,43 @@ +/*- + * Copyright 2012-2018 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_STDDEF_H +#define TINYSTL_STDDEF_H + +#if defined(_WIN64) + typedef long long unsigned int size_t; + typedef long long int ptrdiff_t; +#elif defined(_WIN32) + typedef unsigned int size_t; + 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 + +#endif diff --git a/src/TINYSTL/string.h b/src/TINYSTL/string.h new file mode 100644 index 0000000..3fe45d1 --- /dev/null +++ b/src/TINYSTL/string.h @@ -0,0 +1,295 @@ +/*- + * Copyright 2012-2018 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_H +#define TINYSTL_STRING_H + +#include +#include +#include + +namespace tinystl { + + template + class basic_string { + public: + 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(); + + basic_string& operator=(const basic_string& other); + basic_string& operator=(basic_string&& other); + + const char* c_str() const; + size_t size() const; + + void reserve(size_t size); + void resize(size_t size); + + void clear(); + void append(const char* first, const char* last); + void assign(const char* s, size_t n); + + void shrink_to_fit(); + void swap(basic_string& other); + + private: + typedef char* pointer; + pointer m_first; + pointer m_last; + pointer m_capacity; + + static const size_t c_nbuffer = 12; + char m_buffer[12]; + }; + + template + inline basic_string::basic_string() + : m_first(m_buffer) + , m_last(m_buffer) + , m_capacity(m_buffer + c_nbuffer) + { + resize(0); + } + + template + inline basic_string::basic_string(const basic_string& other) + : m_first(m_buffer) + , m_last(m_buffer) + , m_capacity(m_buffer + c_nbuffer) + { + reserve(other.size()); + append(other.m_first, other.m_last); + } + + 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) + { + size_t len = 0; + for (const char* it = sz; *it; ++it) + ++len; + + reserve(len); + append(sz, sz + 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) + { + reserve(len); + append(sz, sz + len); + } + + template + inline basic_string::~basic_string() { + if (m_first != m_buffer) + allocator::static_deallocate(m_first, m_capacity - m_first); + } + + template + inline basic_string& basic_string::operator=(const basic_string& other) { + basic_string(other).swap(*this); + return *this; + } + + 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 basic_string::size() const + { + return (size_t)(m_last - m_first); + } + + 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); + + 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) + allocator::static_deallocate(m_first, m_capacity - m_first); + + m_first = newfirst; + m_last = newfirst + size; + m_capacity = m_first + capacity; + } + + 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 = m_first + size; + } + + 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); + + for (; first != last; ++m_last, ++first) + *m_last = *first; + *m_last = 0; + } + + template + inline void basic_string::assign(const char* sz, size_t n) { + clear(); + append(sz, sz+n); + } + + 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; + + 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; + } + + if (m_first == other.m_buffer) { + m_last = m_last - m_first + m_buffer; + m_first = m_buffer; + 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; + } + } + + 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(); + if (lsize != rsize) + return false; + + pointer lit = lhs.c_str(), rit = rhs.c_str(); + pointer lend = lit + lsize; + while (lit != lend) + if (*lit++ != *rit++) + return false; + + return true; + } + + 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/src/TINYSTL/string_view.h b/src/TINYSTL/string_view.h new file mode 100644 index 0000000..beae9c4 --- /dev/null +++ b/src/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/src/TINYSTL/traits.h b/src/TINYSTL/traits.h new file mode 100644 index 0000000..84574ee --- /dev/null +++ b/src/TINYSTL/traits.h @@ -0,0 +1,100 @@ +/*- + * Copyright 2012-2018 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_TRAITS_H +#define TINYSTL_TRAITS_H + +#include + +#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)) +#else +# define TINYSTL_TRY_POD_OPTIMIZATION(t) false +#endif + +namespace tinystl { + template struct pod_traits {}; + + template struct swap_holder; + + template + static inline void move_impl(T& a, T& b, ...) { + a = b; + } + + template + static inline void move_impl(T& a, T& b, T*, swap_holder* = 0) { + a.swap(b); + } + + template + static inline void move(T& a, T&b) { + move_impl(a, b, (T*)0); + } + + template + static inline void move_construct_impl(T* a, T& b, ...) { + new(placeholder(), a) T(b); + } + + template + static inline void move_construct_impl(T* a, T& b, void*, swap_holder* = 0) { + // If your type T does not have a default constructor, simply insert: + // struct tinystl_nomove_construct; + // in the class definition + new(placeholder(), a) T; + a->swap(b); + } + + template + static inline void move_construct_impl(T* a, T& b, T*, typename T::tinystl_nomove_construct* = 0) { + new(placeholder(), a) T(b); + } + + template + 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/src/TINYSTL/unordered_map.h b/src/TINYSTL/unordered_map.h new file mode 100644 index 0000000..168a6f8 --- /dev/null +++ b/src/TINYSTL/unordered_map.h @@ -0,0 +1,290 @@ +/*- + * Copyright 2012-2018 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_UNORDERED_MAP_H +#define TINYSTL_UNORDERED_MAP_H + +#include +#include +#include +#include + +namespace tinystl { + + template + class unordered_map { + 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; + + iterator begin(); + iterator end(); + + const_iterator begin() const; + const_iterator end() const; + + void clear(); + bool empty() const; + size_t size() const; + + 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); + + void swap(unordered_map& other); + + private: + + void rehash(size_t nbuckets); + + typedef unordered_hash_node* pointer; + + size_t m_size; + tinystl::buffer m_buckets; + }; + + template + inline unordered_map::unordered_map() + : m_size(0) + { + buffer_init(&m_buckets); + } + + template + 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); + 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; + + unordered_hash_node_insert(newnode, hash(it->first), m_buckets.first, nbuckets - 1); + } + } + + template + 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 + 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; + it.node = *m_buckets.first; + return it; + } + + template + inline typename unordered_map::iterator unordered_map::end() { + iterator it; + it.node = 0; + return it; + } + + template + inline typename unordered_map::const_iterator unordered_map::begin() const { + const_iterator cit; + cit.node = *m_buckets.first; + return cit; + } + + template + inline typename unordered_map::const_iterator unordered_map::end() const { + const_iterator cit; + cit.node = 0; + return cit; + } + + template + inline bool unordered_map::empty() const { + return m_size == 0; + } + + template + inline size_t unordered_map::size() const { + return m_size; + } + + 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; + } + + m_buckets.last = m_buckets.first; + buffer_resize(&m_buckets, 9, 0); + m_size = 0; + } + + template + inline typename unordered_map::iterator unordered_map::find(const Key& key) { + iterator result; + result.node = unordered_hash_find(key, m_buckets.first, (size_t)(m_buckets.last - m_buckets.first)); + return result; + } + + template + inline typename unordered_map::const_iterator unordered_map::find(const Key& key) const { + iterator result; + result.node = unordered_hash_find(key, m_buckets.first, (size_t)(m_buckets.last - m_buckets.first)); + return result; + } + + template + 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); + unordered_hash_node** buckets = m_buckets.first; + + while (root) { + const pointer next = root->next; + root->next = root->prev = 0; + unordered_hash_node_insert(root, hash(root->first), buckets, newnbuckets); + 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; + return result; + } + + template + 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(); + Alloc::static_deallocate((void*)where.node, sizeof(unordered_hash_node)); + --m_size; + } + + template + inline Value& unordered_map::operator[](const Key& key) { + return insert(pair(key, Value())).first->second; + } + + template + 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); + } +} +#endif diff --git a/src/TINYSTL/unordered_set.h b/src/TINYSTL/unordered_set.h new file mode 100644 index 0000000..450fbc5 --- /dev/null +++ b/src/TINYSTL/unordered_set.h @@ -0,0 +1,265 @@ +/*- + * Copyright 2012-2018 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_UNORDERED_SET_H +#define TINYSTL_UNORDERED_SET_H + +#include +#include +#include +#include + +namespace tinystl { + + template + class unordered_set { + 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; + + iterator begin() const; + iterator end() const; + + void clear(); + bool empty() const; + size_t size() const; + + 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); + + void swap(unordered_set& other); + + private: + + void rehash(size_t nbuckets); + + typedef unordered_hash_node* pointer; + + size_t m_size; + tinystl::buffer m_buckets; + }; + + template + inline unordered_set::unordered_set() + : m_size(0) + { + buffer_init(&m_buckets); + buffer_resize(&m_buckets, 9, 0); + } + + template + 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); + 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); + } + } + + template + 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 + 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; + cit.node = *m_buckets.first; + return cit; + } + + template + inline typename unordered_set::iterator unordered_set::end() const { + iterator cit; + cit.node = 0; + return cit; + } + + template + inline bool unordered_set::empty() const { + return m_size == 0; + } + + template + inline size_t unordered_set::size() const { + return m_size; + } + + 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; + } + + m_buckets.last = m_buckets.first; + buffer_resize(&m_buckets, 9, 0); + m_size = 0; + } + + template + inline typename unordered_set::iterator unordered_set::find(const Key& key) const { + iterator result; + result.node = unordered_hash_find(key, m_buckets.first, (size_t)(m_buckets.last - m_buckets.first)); + return result; + } + + template + inline void unordered_set::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); + unordered_hash_node** buckets = m_buckets.first; + + while (root) { + const pointer next = root->next; + root->next = root->prev = 0; + unordered_hash_node_insert(root, hash(root->first), buckets, newnbuckets); + 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; + return result; + } + + template + inline void unordered_set::erase(iterator where) { + unordered_hash_node_erase(where.node, hash(where.node->first), m_buckets.first, (size_t)(m_buckets.last - m_buckets.first) - 1); + + where.node->~unordered_hash_node(); + Alloc::static_deallocate((void*)where.node, sizeof(unordered_hash_node)); + --m_size; + } + + template + inline size_t unordered_set::erase(const Key& key) { + const iterator it = find(key); + if (it.node == 0) + return 0; + + erase(it); + return 1; + } + + template + void unordered_set::swap(unordered_set& other) { + size_t tsize = other.m_size; + other.m_size = m_size, m_size = tsize; + buffer_swap(&m_buckets, &other.m_buckets); + } +} +#endif diff --git a/src/TINYSTL/vector.h b/src/TINYSTL/vector.h new file mode 100644 index 0000000..32eae1f --- /dev/null +++ b/src/TINYSTL/vector.h @@ -0,0 +1,336 @@ +/*- + * Copyright 2012-2018 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_VECTOR_H +#define TINYSTL_VECTOR_H + +#include +#include +#include +#include + +namespace tinystl { + template + class vector { + public: + vector(); + vector(const vector& other); + 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); + + const T* data() const; + T* data(); + size_t size() const; + size_t capacity() const; + bool empty() const; + + T& operator[](size_t idx); + const T& operator[](size_t idx) const; + + const T& front() const; + T& front(); + const T& back() const; + T& back(); + + void resize(size_t size); + void resize(size_t size, const T& value); + void clear(); + void reserve(size_t capacity); + + 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); + + typedef T value_type; + + typedef T* iterator; + iterator begin(); + iterator end(); + + typedef const T* const_iterator; + 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); + + iterator erase_unordered(iterator where); + iterator erase_unordered(iterator first, iterator last); + + private: + buffer m_buffer; + }; + + template + inline vector::vector() { + buffer_init(&m_buffer); + } + + template + inline vector::vector(const vector& other) { + buffer_init(&m_buffer); + buffer_reserve(&m_buffer, other.size()); + buffer_insert(&m_buffer, m_buffer.last, other.m_buffer.first, other.m_buffer.last); + } + + template + inline vector::vector(vector&& other) { + buffer_move(&m_buffer, &other.m_buffer); + } + + template + inline vector::vector(size_t size) { + buffer_init(&m_buffer); + 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 + inline vector::vector(const T* first, const T* last) { + buffer_init(&m_buffer); + buffer_insert(&m_buffer, m_buffer.last, first, last); + } + + template + inline vector::~vector() { + buffer_destroy(&m_buffer); + } + + template + inline vector& vector::operator=(const vector& other) { + vector(other).swap(*this); + 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); + buffer_insert(&m_buffer, m_buffer.last, first, last); + } + + template + inline const T* vector::data() const { + return m_buffer.first; + } + + template + inline T* vector::data() { + return m_buffer.first; + } + + template + inline size_t vector::size() const { + return (size_t)(m_buffer.last - m_buffer.first); + } + + template + inline size_t vector::capacity() const { + return (size_t)(m_buffer.capacity - m_buffer.first); + } + + template + inline bool vector::empty() const { + return m_buffer.last == m_buffer.first; + } + + template + inline T& vector::operator[](size_t idx) { + return m_buffer.first[idx]; + } + + template + inline const T& vector::operator[](size_t idx) const { + 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]; + } + + template + inline T& vector::back() { + return m_buffer.last[-1]; + } + + template + 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); + } + + template + inline void vector::clear() { + buffer_clear(&m_buffer); + } + + template + inline void vector::reserve(size_t capacity) { + buffer_reserve(&m_buffer, capacity); + } + + template + inline void vector::push_back(const T& t) { + buffer_append(&m_buffer, &t); + } + + template + inline void vector::emplace_back() { + buffer_append(&m_buffer); + } + + template + template + inline void vector::emplace_back(const Param& param) { + buffer_append(&m_buffer, ¶m); + } + + template + inline void vector::pop_back() { + buffer_erase(&m_buffer, m_buffer.last - 1, m_buffer.last); + } + + template + inline void vector::shrink_to_fit() { + buffer_shrink_to_fit(&m_buffer); + } + + template + inline void vector::swap(vector& other) { + buffer_swap(&m_buffer, &other.m_buffer); + } + + template + inline typename vector::iterator vector::begin() { + return m_buffer.first; + } + + template + inline typename vector::iterator vector::end() { + return m_buffer.last; + } + + template + inline typename vector::const_iterator vector::begin() const { + return m_buffer.first; + } + + template + inline typename vector::const_iterator vector::end() const { + return m_buffer.last; + } + + template + inline void vector::insert(typename 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); + } + + template + inline void vector::insert(iterator where, const T* first, const T* last) { + buffer_insert(&m_buffer, where, first, last); + } + + template + inline typename vector::iterator vector::erase(iterator where) { + return buffer_erase(&m_buffer, where, where + 1); + } + + template + inline typename vector::iterator vector::erase(iterator first, iterator last) { + return buffer_erase(&m_buffer, first, last); + } + + template + inline typename vector::iterator vector::erase_unordered(iterator where) { + return buffer_erase_unordered(&m_buffer, where, where + 1); + } + + template + inline typename vector::iterator vector::erase_unordered(iterator first, iterator last) { + return buffer_erase_unordered(&m_buffer, first, last); + } + + template + template + void vector::emplace(typename vector::iterator where, const Param& param) { + buffer_insert(&m_buffer, where, ¶m, ¶m + 1); + } +} + +#endif // TINYSTL_VECTOR_H