diff --git a/.idea/misc.xml b/.idea/misc.xml index 79b3c94..0b76fe5 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -1,4 +1,7 @@ + + \ No newline at end of file diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..887d4ca --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,32 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": "(gdb) Launch", + "type": "cppdbg", + "request": "launch", + "program": "${workspaceFolder}/cmake-build-debug/BLT_TESTS", + "args": [], + "stopAtEntry": false, + "cwd": "${fileDirname}", + "environment": [], + "externalConsole": false, + "MIMode": "gdb", + "setupCommands": [ + { + "description": "Enable pretty-printing for gdb", + "text": "-enable-pretty-printing", + "ignoreFailures": true + }, + { + "description": "Set Disassembly Flavor to Intel", + "text": "-gdb-set disassembly-flavor intel", + "ignoreFailures": true + } + ] + } + ] +} \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..d3f548b --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,75 @@ +{ + "files.associations": { + "iostream": "cpp", + "cctype": "cpp", + "clocale": "cpp", + "cmath": "cpp", + "cstdarg": "cpp", + "cstddef": "cpp", + "cstdio": "cpp", + "cstdlib": "cpp", + "cstring": "cpp", + "ctime": "cpp", + "cwchar": "cpp", + "cwctype": "cpp", + "any": "cpp", + "array": "cpp", + "atomic": "cpp", + "strstream": "cpp", + "bit": "cpp", + "*.tcc": "cpp", + "bitset": "cpp", + "chrono": "cpp", + "cinttypes": "cpp", + "compare": "cpp", + "complex": "cpp", + "concepts": "cpp", + "condition_variable": "cpp", + "cstdint": "cpp", + "deque": "cpp", + "list": "cpp", + "map": "cpp", + "set": "cpp", + "string": "cpp", + "unordered_map": "cpp", + "unordered_set": "cpp", + "vector": "cpp", + "exception": "cpp", + "algorithm": "cpp", + "functional": "cpp", + "iterator": "cpp", + "memory": "cpp", + "memory_resource": "cpp", + "numeric": "cpp", + "optional": "cpp", + "random": "cpp", + "ratio": "cpp", + "string_view": "cpp", + "system_error": "cpp", + "tuple": "cpp", + "type_traits": "cpp", + "utility": "cpp", + "fstream": "cpp", + "initializer_list": "cpp", + "iomanip": "cpp", + "iosfwd": "cpp", + "istream": "cpp", + "limits": "cpp", + "mutex": "cpp", + "new": "cpp", + "numbers": "cpp", + "ostream": "cpp", + "scoped_allocator": "cpp", + "semaphore": "cpp", + "shared_mutex": "cpp", + "sstream": "cpp", + "stdexcept": "cpp", + "stop_token": "cpp", + "streambuf": "cpp", + "thread": "cpp", + "cfenv": "cpp", + "typeindex": "cpp", + "typeinfo": "cpp", + "variant": "cpp" + } +} \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index 44a26ae..29decc6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,6 @@ cmake_minimum_required(VERSION 3.20) include(cmake/color.cmake) -set(BLT_VERSION 0.21.3) -set(BLT_TEST_VERSION 0.0.1) +set(BLT_VERSION 1.1.7) set(BLT_TARGET BLT) @@ -34,6 +33,8 @@ if(${BLT_DISABLE_STATS}) add_compile_definitions(BLT_DISABLE_STATS) endif () +find_program(MOLD "mold") + configure_file(include/blt/config.h.in config/blt/config.h @ONLY) message("Enabling library compilation") @@ -138,30 +139,64 @@ install(FILES ${CMAKE_BINARY_DIR}/config/blt/config.h DESTINATION ${CMAKE_INSTAL set_target_properties(${BLT_TARGET} PROPERTIES VERSION ${BLT_VERSION}) set_target_properties(${BLT_TARGET} PROPERTIES SOVERSION ${PROJECT_VERSION_MAJOR}) +if (NOT ${MOLD} STREQUAL MOLD-NOTFOUND) + target_link_options(${BLT_TARGET} PUBLIC -fuse-ld=mold) +endif () install(TARGETS ${BLT_TARGET} CONFIGURATIONS RelWithDebInfo LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) +macro(blt_add_project name source type) + + project(${name}-${type}) + + add_executable(${name}-${type} ${source}) + + if (NOT ${MOLD} STREQUAL MOLD-NOTFOUND) + add_link_options(-fuse-ld=mold) + endif () + + target_link_libraries(${name}-${type} PRIVATE BLT) + + target_compile_options(${name}-${type} PRIVATE -Wall -Wextra -Wpedantic -Wno-comment) + target_link_options(${name}-${type} PRIVATE -Wall -Wextra -Wpedantic -Wno-comment) + target_compile_definitions(${name}-${type} PRIVATE BLT_DEBUG_LEVEL=${DEBUG_LEVEL}) + + if (${TRACK_ALLOCATIONS}) + target_compile_definitions(${name}-${type} PRIVATE BLT_TRACK_ALLOCATIONS=1) + endif () + + if (${ENABLE_ADDRSAN} MATCHES ON) + target_compile_options(${name}-${type} PRIVATE -fsanitize=address) + target_link_options(${name}-${type} PRIVATE -fsanitize=address) + endif () + + if (${ENABLE_UBSAN} MATCHES ON) + target_compile_options(${name}-${type} PRIVATE -fsanitize=undefined) + target_link_options(${name}-${type} PRIVATE -fsanitize=undefined) + endif () + + if (${ENABLE_TSAN} MATCHES ON) + target_compile_options(${name}-${type} PRIVATE -fsanitize=thread) + target_link_options(${name}-${type} PRIVATE -fsanitize=thread) + endif () + + add_test(NAME ${name} COMMAND ${name}-${type}) + + set(failRegex "\\[WARN\\]" "FAIL" "ERROR" "FATAL" "exception") + set_property(TEST ${name} PROPERTY FAIL_REGULAR_EXPRESSION "${failRegex}") + + project(${BLT_TARGET}) +endmacro() + if (${BUILD_TESTS}) - message("Building test version ${BLT_TEST_VERSION}") - project(BLT_TESTS VERSION ${BLT_TEST_VERSION}) + message("Building tests for version ${BLT_VERSION}") - include_directories(tests/include) - - file(GLOB_RECURSE TEST_FILES "${CMAKE_CURRENT_SOURCE_DIR}/tests/src/*.cpp") - - message("Using files ${TEST_FILES}") - - add_executable(BLT_TESTS ${TEST_FILES}) - - target_link_libraries(BLT_TESTS PRIVATE BLT) - - include(cmake/warnings.cmake) - include(cmake/sanitizers.cmake) + blt_add_project(blt-iterator tests/iterator_tests.cpp test) message("Built tests") endif () -project(BLT) \ No newline at end of file +project(BLT) diff --git a/commit.py b/commit.py index e8b8443..00d0d95 100755 --- a/commit.py +++ b/commit.py @@ -1,6 +1,13 @@ #!/usr/bin/python3 import subprocess +import argparse +import sys +import os +import itertools +import requests +import json +from pathlib import Path #--------------------------------------- # CONFIG @@ -8,12 +15,110 @@ import subprocess VERSION_BEGIN_STR = "set(BLT_VERSION " VERSION_END_STR = ")" -PATCH_LIMIT = 1000 #--------------------------------------- # DO NOT TOUCH #--------------------------------------- +USER_HOME = Path.home() +ENVIRONMENT_DATA_LOCATION = USER_HOME / ".brett_scripts.env" + +if sys.platform.startswith("win"): + CONFIG_FILE_DIRECTORY = Path(os.getenv('APPDATA') + "\blt") + CONFIG_FILE_LOCATION = Path(CONFIG_FILE_DIRECTORY + "\commit_config.json") +else: + XDG_CONFIG_HOME = os.environ.get('XDG_CONFIG_HOME') + if XDG_CONFIG_HOME is None: + XDG_CONFIG_HOME = USER_HOME / ".config" + else: + XDG_CONFIG_HOME = Path(XDG_CONFIG_HOME) + + if len(str(XDG_CONFIG_HOME)) == 0: + XDG_CONFIG_HOME = USER_HOME + CONFIG_FILE_DIRECTORY = XDG_CONFIG_HOME / "blt" + CONFIG_FILE_LOCATION = CONFIG_FILE_DIRECTORY / "commit_config.json" + +class Config: + def __init__(self): + # Inline with semantic versioning it doesn't make sense to branch / release on minor + self.branch_on_major = True + self.branch_on_minor = False + self.release_on_major = True + self.release_on_minor = True + self.main_branch = "main" + self.patch_limit = -1 + + def toJSON(self): + return json.dumps(self, default=lambda o: o.__dict__, sort_keys=True, indent=4) + + def fromJSON(file): + with open(file, "r") as f: + j = json.load(f) + obj = Config() + [setattr(obj, key, val) for key, val in j.items() if hasattr(obj, key)] + if obj.branch_on_minor: + obj.branch_on_major = True + return obj + + def from_file(file): + values = {} + if (not os.path.exists(file)): + return Config() + + with open(file, "r") as f: + j = json.load(f) + obj = Config() + [setattr(obj, key, val) for key, val in j.items() if hasattr(obj, key)] + return obj + + def save_to_file(self, file): + dir_index = str(file).rfind("/") + dir = str(file)[:dir_index] + if not os.path.exists(dir): + print(f"Creating config directory {dir}") + os.makedirs(dir) + with open(file, "w") as f: + json.dump(self, f, default=lambda o: o.__dict__, sort_keys=True, indent=4) + + +class EnvData: + def __init__(self, github_username = '', github_token = ''): + self.github_token = github_token + self.github_username = github_username + + def get_env_from_file(file): + f = open(file, "rt") + values = {} + for line in f: + if line.startswith("export"): + content = line.split("=") + for idx, c in enumerate(content): + content[idx] = c.replace("export", "").strip() + values[content[0]] = content[1].replace("\"", "").replace("'", "") + try: + github_token = values["github_token"] + except Exception: + print("Failed to parse github token!") + try: + github_username = values["github_username"] + except: + print("Failed to parse github username! Assuming you are me!") + github_username = "Tri11Paragon" + return EnvData(github_username=github_username, github_token=github_token) + +def open_process(command, print_out = True): + process = subprocess.Popen(command, stderr=subprocess.PIPE, stdout=subprocess.PIPE) + stdout, stderr = process.communicate() + exit_code = process.wait() + str_out = stdout.decode('utf8') + str_err = stderr.decode('utf8') + if print_out and len(str_out) > 0: + print(str_out, end='') + if print_out and len(str_err) > 0: + print(str_err, end='') + #print(stdout, stderr, exit_code) + return (stdout, stderr, exit_code) + def load_cmake(): cmake_file = open("CMakeLists.txt", 'r') cmake_text = cmake_file.read() @@ -38,9 +143,8 @@ def split_version(cmake_text): def recombine(cmake_text, version_parts, begin, end): constructed_version = version_parts[0] + '.' + version_parts[1] + '.' + version_parts[2] constructed_text_begin = cmake_text[0:begin] - constrcuted_text_end = cmake_text[end::] - return constructed_text_begin + constructed_version + constrcuted_text_end - + constructed_text_end = cmake_text[end::] + return constructed_text_begin + constructed_version + constructed_text_end def inc_major(cmake_text): version_parts, begin, end = split_version(cmake_text) @@ -55,32 +159,158 @@ def inc_minor(cmake_text): version_parts[2] = '0' return recombine(cmake_text, version_parts, begin, end) -def inc_patch(cmake_text): +def inc_patch(config: Config, cmake_text): version_parts, begin, end = split_version(cmake_text) - if int(version_parts[2]) + 1 >= PATCH_LIMIT: + if config.patch_limit > 0 and int(version_parts[2]) + 1 >= config.patch_limit: return inc_minor(cmake_text) version_parts[2] = str(int(version_parts[2]) + 1) return recombine(cmake_text, version_parts, begin, end) -cmake_text = load_cmake() -cmake_version = get_version(cmake_text)[0] -print(f"Current Version: {cmake_version}") +def make_branch(config: Config, name): + print(f"Making new branch {name}") + subprocess.call(["git", "checkout", "-b", name]) + subprocess.call(["git", "merge", config.main_branch]) + subprocess.call(["git", "checkout", config.main_branch]) + +def sync_branch(config: Config, version_parts, args): + if config.branch_on_major: + # Branch will be created. + if args.minor: + return; -try: - type = input("What kind of commit is this ((M)ajor, (m)inor, (p)atch)? ") +def make_release(env: EnvData, name): + print(f"Making new release {name}") + repos_v = open_process(["git", "remote", "-v"])[0].splitlines() + urls = [] + for line in repos_v: + origin = ''.join(itertools.takewhile(str.isalpha, line.decode('utf8'))) + urls.append(open_process(["git", "remote", "get-url", origin], False)[0].decode('utf8').replace("\n", "").replace(".git", "").replace("https://github.com/", "https://api.github.com/repos/") + "/releases") + urls = set(urls) + data = { + 'tag_name': name, + 'name': name, + 'body': "Automated Release '" + name + "'", + 'draft': False, + 'prerelease': False + } + headers = { + 'Authorization': f'Bearer {env.github_token}', + 'Accept': 'application/vnd.github+json', + 'X-GitHub-Api-Version': '2022-11-28' + } + for url in urls: + response = requests.post(url, headers=headers, data=json.dumps(data)) + if response.status_code == 201: + print('Release created successfully!') + release_data = response.json() + print(f"Release URL: {release_data['html_url']}") + else: + print(f"Failed to create release: {response.status_code}") + print(response.json()) - if type.startswith('M'): + +def main(): + parser = argparse.ArgumentParser( + prog="Commit Helper", + description="Help you make pretty commits :3") + + parser.add_argument("action", nargs='?', default=None) + parser.add_argument("-p", "--patch", action='store_true', default=False, required=False) + parser.add_argument("-m", "--minor", action='store_true', default=False, required=False) + parser.add_argument("-M", "--major", action='store_true', default=False, required=False) + parser.add_argument('-e', "--env", help="environment file", required=False, default=None) + parser.add_argument('-c', "--config", help="config file", required=False, default=None) + parser.add_argument("--create-default-config", action="store_true", default=False, required=False) + parser.add_argument("--no-release", action="store_true", default=False, required=False) + parser.add_argument("--no-branch", action="store_true", default=False, required=False) + + args = parser.parse_args() + + if args.create_default_config: + config = Config() + config.save_to_file(args.config if args.config is not None else CONFIG_FILE_LOCATION) + return + + if args.env is not None: + env = EnvData.get_env_from_file(args.e) + else: + env = EnvData.get_env_from_file(ENVIRONMENT_DATA_LOCATION) + + if args.config is not None: + config = Config.from_file(args.config) + else: + config = Config.from_file(CONFIG_FILE_LOCATION) + + cmake_text = load_cmake() + cmake_version = get_version(cmake_text)[0] + print(f"Current Version: {cmake_version}") + + if not (args.patch or args.minor or args.major): + try: + if args.action is not None: + type = args.action + else: + type = input("What kind of commit is this ((M)ajor, (m)inor, (p)atch)? ") + + if type.startswith('M'): + args.major = True + elif type.startswith('m'): + args.minor = True + elif type.startswith('p') or type.startswith('P') or len(type) == 0: + args.patch = True + except KeyboardInterrupt: + print("\nCancelling!") + return + + if args.major: print("Selected major") write_cmake(inc_major(cmake_text)) - elif type.startswith('m'): + elif args.minor: print("Selected minor") write_cmake(inc_minor(cmake_text)) - elif type.startswith('p') or type.startswith('P') or len(type) == 0: + elif args.patch: print("Selected patch") - write_cmake(inc_patch(cmake_text)) + write_cmake(inc_patch(config, cmake_text)) subprocess.call(["git", "add", "*"]) subprocess.call(["git", "commit"]) + + cmake_text = load_cmake() + version_parts = split_version(cmake_text)[0] + if args.major: + if config.branch_on_major: + if not args.no_branch: + make_branch(config, "v" + str(version_parts[0])) + + if args.minor: + if config.branch_on_minor: + if not args.no_branch: + make_branch(config, "v" + str(version_parts[0]) + "." + str(version_parts[1])) + elif config.branch_on_major: + subprocess.call(["git", "checkout", "v" + str(version_parts[0])]) + subprocess.call(["git", "rebase", config.main_branch]) + subprocess.call(["git", "checkout", config.main_branch]) + + if args.patch: + if config.branch_on_minor: + subprocess.call(["git", "checkout", "v" + str(version_parts[0]) + "." + str(version_parts[1])]) + subprocess.call(["git", "rebase", config.main_branch]) + subprocess.call(["git", "checkout", config.main_branch]) + elif config.branch_on_major: + subprocess.call(["git", "checkout", "v" + str(version_parts[0])]) + subprocess.call(["git", "rebase", config.main_branch]) + subprocess.call(["git", "checkout", config.main_branch]) + + sync_branch(config=config, version_parts=version_parts, args=args) + subprocess.call(["sh", "-c", "git remote | xargs -L1 git push --all"]) -except KeyboardInterrupt: - print("\nCancelling!") + + if args.major: + if not args.no_release and config.release_on_major: + make_release(env, "v" + str(version_parts[0])) + if args.minor: + if not args.no_release and config.release_on_minor: + make_release(env, "v" + str(version_parts[0]) + "." + str(version_parts[1])) + +if __name__ == "__main__": + main() diff --git a/include/blt/iterator/common.h b/include/blt/iterator/common.h new file mode 100644 index 0000000..50f3b55 --- /dev/null +++ b/include/blt/iterator/common.h @@ -0,0 +1,271 @@ +#pragma once +/* + * Copyright (C) 2024 Brett Terpstra + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef BLT_ITERATOR_ITER_COMMON +#define BLT_ITERATOR_ITER_COMMON + +#include +#include +#include + +namespace blt::iterator +{ + template + struct base_wrapper + { + base_wrapper operator++(int) + { + auto tmp = *this; + ++*this; + return tmp; + } + + base_wrapper operator--(int) + { + static_assert(std::is_same_v || + std::is_same_v, + "Iterator must allow random access"); + auto tmp = *this; + --*this; + return tmp; + } + + auto operator[](blt::ptrdiff_t n) const + { + static_assert(std::is_same_v, + "Iterator must allow random access"); + return *(*this + n); + } + + friend base_wrapper operator+(blt::ptrdiff_t n, const base_wrapper& a) + { + return a + n; + } + + friend bool operator<(const base_wrapper& a, const base_wrapper& b) + { + static_assert(std::is_same_v, + "Iterator must allow random access"); + return b - a > 0; + } + + friend bool operator>(const base_wrapper& a, const base_wrapper& b) + { + static_assert(std::is_same_v, + "Iterator must allow random access"); + return b < a; + } + + friend bool operator>=(const base_wrapper& a, base_wrapper& b) + { + static_assert(std::is_same_v, + "Iterator must allow random access"); + return !(a < b); // NOLINT + } + + friend bool operator<=(const base_wrapper& a, const base_wrapper& b) + { + static_assert(std::is_same_v, + "Iterator must allow random access"); + return !(a > b); // NOLINT + } + + friend bool operator==(const base_wrapper& a, const base_wrapper& b) + { + return static_cast(a).base() == static_cast(b).base(); + } + + friend bool operator!=(const base_wrapper& a, const base_wrapper& b) + { + return !(static_cast(a).base() == static_cast(b).base()); // NOLINT + } + }; + + template + struct passthrough_wrapper : public base_wrapper + { + public: + explicit passthrough_wrapper(Iter iter): iter(std::move(iter)) + {} + + auto base() const + { + return iter; + } + + friend blt::ptrdiff_t operator-(const passthrough_wrapper& a, const passthrough_wrapper& b) + { + return a.base() - b.base(); + } + + protected: + Iter iter; + }; + + template + struct passthrough_wrapper : public passthrough_wrapper + { + using passthrough_wrapper::passthrough_wrapper; + + meta::deref_return_t operator*() const + { + return *this->iter; + } + }; + + namespace impl + { + template + class skip_t + { + private: + template + auto skip_base(blt::size_t n) + { + auto* d = static_cast(this); + auto begin = d->begin(); + auto end = d->end(); + + if constexpr (std::is_same_v || + std::is_same_v) + { + for (blt::size_t i = 0; i < n; i++) + { + if constexpr (check) + { + if (begin == end) + break; + } + ++begin; + } + return Derived{std::move(begin), std::move(end)}; + } else if constexpr (std::is_same_v) + { + // random access iterators can have math directly applied to them. + if constexpr (check) + { + return Derived{begin + std::min(static_cast(n), std::distance(begin, end)), end}; + } else + { + return Derived{begin + n, end}; + } + } + } + + public: + auto skip(blt::size_t n) + { return skip_base(n); } + + auto skip_or(blt::size_t n) + { return skip_base(n); } + }; + + template + class take_t + { + private: + template + auto take_base(blt::size_t n) + { + static_assert(!std::is_same_v, + "Cannot .take() on an input iterator!"); + auto* d = static_cast(this); + auto begin = d->begin(); + auto end = d->end(); + + // take variant for forward and bidirectional iterators + if constexpr (std::is_same_v || + std::is_same_v) + { + // with these guys we have to loop forward to move the iterators. an unfortunate inefficiency + auto new_end = begin; + for (blt::size_t i = 0; i < n; i++) + { + if constexpr (check) + { + if (new_end == end) + break; + } + ++new_end; + } + return Derived{std::move(begin), std::move(new_end)}; + } else if constexpr (std::is_same_v) + { + // random access iterators can have math directly applied to them. + if constexpr (check) + { + return Derived{begin, begin + std::min(static_cast(n), std::distance(begin, end))}; + } else + { + return Derived{begin, begin + n}; + } + } + } + + public: + auto take(blt::size_t n) + { return take_base(n); } + + auto take_or(blt::size_t n) + { return take_base(n); } + }; + } + + template + class iterator_container : public impl::take_t>, + public impl::skip_t> + { + public: + using iterator_category = typename IterBase::iterator_category; + using iterator = IterBase; + + iterator_container(IterBase begin, IterBase end): m_begin(std::move(begin)), m_end(std::move(end)) + {} + + template + iterator_container(Iter&& begin, Iter&& end): m_begin(std::forward(begin)), m_end(std::forward(end)) + {} + + auto rev() + { + static_assert((std::is_same_v || + std::is_same_v), + ".rev() must be used with bidirectional (or better) iterators!"); + return iterator_container>{std::reverse_iterator{end()}, + std::reverse_iterator{begin()}}; + } + + auto begin() const + { + return m_begin; + } + + auto end() const + { + return m_end; + } + + protected: + IterBase m_begin; + IterBase m_end; + }; + +} + +#endif //BLT_ITERATOR_ITER_COMMON diff --git a/include/blt/iterator/enumerate.h b/include/blt/iterator/enumerate.h new file mode 100644 index 0000000..3747a70 --- /dev/null +++ b/include/blt/iterator/enumerate.h @@ -0,0 +1,59 @@ +#pragma once +/* + * Copyright (C) 2024 Brett Terpstra + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef BLT_ITERATOR_ENUMERATE_H +#define BLT_ITERATOR_ENUMERATE_H + +#include +#include +#include + +namespace blt +{ + + namespace iterator + { + /** + * struct which is returned by the enumerator. + * @tparam T type to store. + */ + template + struct enumerate_item + { + blt::size_t index; + T value; + }; + + template + class enumerate_wrapper : public passthrough_wrapper> + { + public: + using passthrough_wrapper>::passthrough_wrapper; + + enumerate_item> operator*() const + { + return *this->iter; + } + private: + blt::size_t index; + }; + } + +} + +#endif //BLT_ITERATOR_ENUMERATE_H diff --git a/include/blt/iterator/iterator.h b/include/blt/iterator/iterator.h index 5f9e9a7..96400eb 100644 --- a/include/blt/iterator/iterator.h +++ b/include/blt/iterator/iterator.h @@ -21,7 +21,7 @@ #include #include -#include +#include #include #include #include @@ -59,118 +59,6 @@ namespace blt template> class pair_wrapper; - template - class zip_wrapper; - - template - class zip_iterator_storage; - - template - class zip_iterator_storage_rev; - - template - class zip_forward_iterator - { - public: - explicit zip_forward_iterator(Iter... iter): iter(std::make_tuple(iter...)) - {} - - std::tuple...> operator*() const - { - return std::apply([](auto& ... i) { return std::make_tuple(*i...); }, iter); - } - - friend bool operator==(const zip_forward_iterator& a, const zip_forward_iterator& b) - { - return a.iter == b.iter; - } - - friend bool operator!=(const zip_forward_iterator& a, const zip_forward_iterator& b) - { - return !(a.iter == b.iter); - } - - zip_forward_iterator& operator++() - { - std::apply([](auto& ... i) { ((++i), ...); }, iter); - return *this; - } - - zip_forward_iterator operator++(int) - { - auto tmp = *this; - ++*this; - return tmp; - } - - auto base() - { - return iter; - } - - protected: - std::tuple iter; - }; - - template - class zip_bidirectional_iterator : public zip_forward_iterator - { - public: - using zip_forward_iterator::zip_forward_iterator; - - zip_bidirectional_iterator& operator--() - { - std::apply([](auto& ... i) { ((--i), ...); }, this->iter); - return *this; - } - - zip_bidirectional_iterator operator--(int) - { - auto tmp = *this; - --*this; - return tmp; - } - }; - - template - class zip_wrapper : public zip_forward_iterator - { - public: - using zip_forward_iterator::zip_forward_iterator; - - using iterator_category = std::forward_iterator_tag; - using value_type = std::tuple...>; - using difference_type = blt::ptrdiff_t; - using pointer = value_type; - using reference = value_type; - }; - - template - class zip_wrapper : public zip_bidirectional_iterator - { - public: - using zip_bidirectional_iterator::zip_bidirectional_iterator; - - using iterator_category = std::bidirectional_iterator_tag; - using value_type = std::tuple...>; - using difference_type = blt::ptrdiff_t; - using pointer = value_type; - using reference = value_type; - }; - - template - class zip_wrapper : public zip_bidirectional_iterator - { - public: - using zip_bidirectional_iterator::zip_bidirectional_iterator; - - using iterator_category = std::bidirectional_iterator_tag; - using value_type = std::tuple...>; - using difference_type = blt::ptrdiff_t; - using pointer = value_type; - using reference = value_type; - }; - /** * struct which is returned by the enumerator. * @tparam T type to store. @@ -590,25 +478,6 @@ namespace blt return CompleteEnumerator{b->begin(), b->end(), static_cast(std::distance(b->begin(), b->end()))}; } }; - - template - class zip_iterator_storage - { - - }; - - template - class zip_iterator_storage - { - - }; - - template - class zip_iterator_storage - { - - }; - } /** diff --git a/include/blt/iterator/zip.h b/include/blt/iterator/zip.h index f8f197d..1fec30d 100644 --- a/include/blt/iterator/zip.h +++ b/include/blt/iterator/zip.h @@ -19,12 +19,158 @@ #ifndef BLT_ITERATOR_ZIP #define BLT_ITERATOR_ZIP -#include +#include +#include +#include #include namespace blt { + namespace iterator + { + template + struct zip_wrapper : public base_wrapper> + { + public: + using iterator_category = meta::lowest_iterator_category_t; + using value_type = std::tuple...>; + using difference_type = blt::ptrdiff_t; + using pointer = value_type; + using reference = value_type; + + explicit zip_wrapper(std::tuple iter): iter(std::move(iter)) + {} + + explicit zip_wrapper(Iter... iter): iter(std::make_tuple(iter...)) + {} + + std::tuple...> operator*() const + { + return std::apply([](auto& ... i) { return std::tuple...>{*i...}; }, iter); + } + + zip_wrapper& operator++() + { + std::apply([](auto& ... i) { ((++i), ...); }, iter); + return *this; + } + + zip_wrapper& operator--() + { + std::apply([](auto& ... i) { ((--i), ...); }, this->iter); + return *this; + } + + friend zip_wrapper operator+(const zip_wrapper& a, blt::ptrdiff_t n) + { + static_assert(std::is_same_v, + "Iterator must allow random access"); + return std::apply([n](auto& ... i) { return zip_wrapper((i + n)...); }, a.iter); + } + + friend zip_wrapper operator-(const zip_wrapper& a, blt::ptrdiff_t n) + { + static_assert(std::is_same_v, + "Iterator must allow random access"); + return std::apply([n](auto& ... i) { return zip_wrapper((i - n)...); }, a.iter); + } + + friend blt::ptrdiff_t operator-(const zip_wrapper& a, const zip_wrapper& b) + { + return sub(a, b, std::index_sequence_for()); + } + + auto base() const + { + return iter; + } + + protected: + std::tuple iter; + + template + static blt::ptrdiff_t sub(const zip_wrapper& a, const zip_wrapper& b, + std::integer_sequence) + { + blt::ptrdiff_t min = std::numeric_limits::max(); + ((min = std::min(min, std::get(a.iter) - std::get(b.iter))), ...); + return min; + } + }; +// template +// struct zip_wrapper : public Iter +// { +// using iterator_category = typename std::iterator_traits::iterator_category; +// using value_type = typename std::iterator_traits::value_type; +// using difference_type = typename std::iterator_traits::difference_type; +// using pointer = typename std::iterator_traits::pointer; +// using reference = typename std::iterator_traits::reference; +// +// using Iter::Iter; +// }; + } + + template + struct iterator_pair + { + using type = Iter; + + iterator_pair(Iter begin, Iter end): begin(std::move(begin)), end(std::move(end)) + {} + + Iter begin; + Iter end; + }; + + template + class zip_iterator_container : public iterator::iterator_container> + { + public: + using iterator::iterator_container>::iterator_container; + + explicit zip_iterator_container(iterator_pair... iterator_pairs): + iterator::iterator_container>(iterator::zip_wrapper{std::move(iterator_pairs.begin)...}, + iterator::zip_wrapper{std::move(iterator_pairs.end)...}) + {} + + }; + + namespace impl + { + template + class zip_t + { + public: + template + auto zip(iterator_pair... iterator_pairs) + { + auto* d = static_cast(this); + return zip_iterator_container(iterator_pairbegin())>{d->begin(), d->end()}, iterator_pairs...); + } + }; + } + + /* + * CTAD for the zip containers + */ + + template + zip_iterator_container(iterator_pair...) -> zip_iterator_container; + + template + zip_iterator_container(std::initializer_list...) -> zip_iterator_container; + + + /* + * Helper functions for creating zip containers + */ + + template + auto zip(Container& ... container) + { + return zip_iterator_container{iterator_pair{container.begin(), container.end()}...}; + } } #endif //BLT_ITERATOR_ZIP diff --git a/include/blt/meta/iterator.h b/include/blt/meta/iterator.h index e5873f6..e7df5a7 100644 --- a/include/blt/meta/iterator.h +++ b/include/blt/meta/iterator.h @@ -24,27 +24,71 @@ namespace blt::meta { + template + struct is_input_iterator_category + { + constexpr static bool value = std::is_same_v; + }; + + template + struct is_forward_iterator_category + { + constexpr static bool value = std::is_same_v; + }; + + template + struct is_bidirectional_iterator_category + { + constexpr static bool value = std::is_same_v; + }; + + template + struct is_random_access_iterator_category + { + constexpr static bool value = std::is_same_v; + }; + + template + inline constexpr bool is_input_iterator_category_v = is_input_iterator_category::value; + + template + inline constexpr bool is_forward_iterator_category_v = is_forward_iterator_category::value; + + template + inline constexpr bool is_bidirectional_iterator_category_v = is_bidirectional_iterator_category::value; + + template + inline constexpr bool is_random_access_iterator_category_v = is_random_access_iterator_category::value; + + template + inline constexpr bool is_bidirectional_or_better_category_v = + is_bidirectional_iterator_category_v || is_random_access_iterator_category_v; + // this is required! :/ template - struct is_input_iterator { - constexpr static bool value = std::is_same_v::iterator_category, std::input_iterator_tag>; + struct is_input_iterator + { + constexpr static bool value = is_input_iterator_category_v::iterator_category>; }; template - struct is_forward_iterator { - constexpr static bool value = std::is_same_v::iterator_category, std::forward_iterator_tag>; + struct is_forward_iterator + { + constexpr static bool value = is_forward_iterator_category_v::iterator_category>; }; template - struct is_bidirectional_iterator { - constexpr static bool value = std::is_same_v::iterator_category, std::bidirectional_iterator_tag>; + struct is_bidirectional_iterator + { + constexpr static bool value = is_bidirectional_iterator_category_v::iterator_category>; }; template - struct is_random_access_iterator { - constexpr static bool value = std::is_same_v::iterator_category, std::random_access_iterator_tag>; + struct is_random_access_iterator + { + constexpr static bool value = is_random_access_iterator_category_v::iterator_category>; }; template @@ -61,6 +105,27 @@ namespace blt::meta template inline constexpr bool is_bidirectional_or_better_v = is_bidirectional_iterator_v || is_random_access_iterator_v; + + template + struct lowest_iterator_category + { + using type = std::common_type_t::iterator_category...>; + }; + + template + using lowest_iterator_category_t = typename lowest_iterator_category::type; + + template + struct is_reverse_iterator : std::false_type + { + }; + + template + struct is_reverse_iterator> : std::true_type + {}; + + template + inline constexpr bool is_reverse_iterator_v = is_reverse_iterator::value; } #endif //BLT_META_ITERATOR_H diff --git a/include/blt/std/allocator.h b/include/blt/std/allocator.h index 91e7e5d..873c0e4 100644 --- a/include/blt/std/allocator.h +++ b/include/blt/std/allocator.h @@ -22,7 +22,7 @@ #include #include #include - #include + #include #include #include #include @@ -159,10 +159,10 @@ namespace blt */ inline std::optional search_for_block(block_storage* blk, size_t n) { - for (auto kv : blt::enumerate(blk->unallocated_blocks)) + for (auto [index, item] : blt::enumerate(blk->unallocated_blocks)) { - if (kv.second.n >= n) - return block_view{blk, kv.first, kv.second.n - n}; + if (item.n >= n) + return block_view{blk, index, item.n - n}; } return {}; } diff --git a/include/blt/std/iterator.h b/include/blt/std/iterator.h deleted file mode 100644 index c1f0119..0000000 --- a/include/blt/std/iterator.h +++ /dev/null @@ -1,499 +0,0 @@ -#pragma once -/* - * Copyright (C) 2024 Brett Terpstra - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#ifndef BLT_ITERATOR_H -#define BLT_ITERATOR_H - -#include -#include -#include -#include -#include -#include - -namespace blt -{ - - // forward declare useful types - template> - class enumerator; - - template> - class enumerator_rev; - - namespace iterator - { - template> - class enumerate_wrapper; - - /** - * struct which is returned by the enumerator. - * @tparam T type to store. - */ - template - struct enumerate_item - { - blt::size_t index; - T value; - }; - - /** - * base class for iterators which operate on pairs of values. Handles comparison. - * @tparam Iter1 first iterator type. this will be used for comparison. - * @tparam Iter2 second iterator type. this value is not modified by this class. - */ - template - class pair_iterator_base - { - public: - explicit pair_iterator_base(Iter1 iter1, Iter2 iter2): m_iter1(std::move(iter1)), m_iter2(std::move(iter2)) - {} - - friend bool operator==(const pair_iterator_base& a, const pair_iterator_base& b) - { - return a.m_iter1 == b.m_iter1; - } - - friend bool operator!=(const pair_iterator_base& a, const pair_iterator_base& b) - { - return a.m_iter1 != b.m_iter1; - } - - auto iter1() const - { - return m_iter1; - } - - auto iter2() const - { - return m_iter2; - } - - protected: - Iter1 m_iter1; - Iter2 m_iter2; - }; - - /** - * Base class for all enumerator iterators. Handles the deference (*) operator. - * @tparam Iter iterator type - */ - template - class enumerate_iterator_base : public pair_iterator_base - { - public: - explicit enumerate_iterator_base(Iter iter, blt::size_t place = 0): - pair_iterator_base(std::move(iter), place) - {} - - enumerate_item> operator*() const - { - return {this->m_iter2, *this->m_iter1}; - } - - auto base() const - { - return this->iter1(); - } - - auto get_index() const - { - return this->iter2(); - } - }; - - /** - * Forward iterator base class for the enumerator. Contains the ++ operator. - * @tparam Iter iterator type. - */ - template - class enumerate_forward_iterator : public enumerate_iterator_base - { - public: - using enumerate_iterator_base::enumerate_iterator_base; - - enumerate_forward_iterator& operator++() - { - ++this->m_iter1; - ++this->m_iter2; - return *this; - } - - enumerate_forward_iterator operator++(int) - { - auto tmp = *this; - ++*this; - return tmp; - } - }; - - /** - * Bidirectional iterator base class for the enumerator. Contains the -- operator. - * @tparam Iter iterator type. - */ - template - class enumerate_bidirectional_iterator : public enumerate_forward_iterator - { - public: - using enumerate_forward_iterator::enumerate_forward_iterator; - - enumerate_bidirectional_iterator& operator--() - { - --this->m_iter1; - --this->m_iter2; - return *this; - } - - enumerate_bidirectional_iterator operator--(int) - { - auto tmp = *this; - --*this; - return tmp; - } - }; - - /** - * Wrapper class specialization for forward iterators. - * @tparam Iter iterator type - */ - template - class enumerate_wrapper, std::void_t>> - : public enumerate_forward_iterator - { - public: - using iterator_category = std::forward_iterator_tag; - using value_type = enumerate_item>; - using difference_type = typename std::iterator_traits::difference_type; - using pointer = value_type; - using reference = value_type; - using iterator_type = Iter; - - using enumerate_forward_iterator::enumerate_forward_iterator; - }; - - /** - * Wrapper class for bidirectional iterators or random access iterators. - * @tparam Iter iterator type. - */ - template - class enumerate_wrapper, std::void_t>> - : public enumerate_bidirectional_iterator - { - public: - using iterator_category = typename std::iterator_traits::iterator_category; - using value_type = enumerate_item>; - using difference_type = typename std::iterator_traits::difference_type; - using pointer = value_type; - using reference = value_type; - using iterator_type = Iter; - - using enumerate_bidirectional_iterator::enumerate_bidirectional_iterator; - }; - - /** - * Base class for the enumerator. Holds the begin and end iterators. - * @tparam Iter iterator type. - * @tparam IterWrapper wrapper used to iterate (enumerate_wrapper) - */ - template - class enumerator_base - { - public: - explicit enumerator_base(Iter begin, Iter end): begin_(std::move(begin)), end_(std::move(end)) - {} - - explicit enumerator_base(IterWrapper begin, IterWrapper end): begin_(std::move(begin)), end_(std::move(end)) - {} - - auto begin() - { - return begin_; - } - - auto end() - { - return end_; - } - - /** - * Creates an enumerator that skips the first n elements. - * @param amount amount of values to skip. - */ - auto skip(blt::size_t amount) - { - auto begin = this->begin_; - for (blt::size_t i = 0; i < amount; i++) - ++begin; - return enumerator{begin.base(), - this->end_.base(), - begin.get_index(), - this->end_.get_index()}; - } - - /** - * Creates an enumerator that yields the first n elements, or UB if the underlying iterator ends sooner. - * @param amount amount to take. - */ - auto take(blt::size_t amount) - { - auto end = this->begin(); - for (blt::size_t i = 0; i < amount; i++) - ++end; - return enumerator{this->begin_.base(), - end.base(), - this->begin_.get_index(), - end.get_index()}; - } - protected: - IterWrapper begin_; - IterWrapper end_; - }; - - /** - * Reversible (bidirectional) base class for the enumerator. - * @tparam Iter iterator type. - * @tparam IterWrapper wrapper used to iterate (enumerate_wrapper). - */ - template - class enumerator_reversible : public enumerator_base - { - public: - explicit enumerator_reversible(Iter begin, Iter end, blt::size_t container_size): - enumerator_base{IterWrapper{enumerate_wrapper{std::move(begin), 0}}, - IterWrapper{enumerate_wrapper{std::move(end), container_size}}} - {} - - explicit enumerator_reversible(Iter begin, Iter end, blt::size_t begin_index, blt::size_t end_index): - enumerator_base(IterWrapper{enumerate_wrapper{std::move(begin), begin_index}}, - IterWrapper{enumerate_wrapper{std::move(end), end_index}}) - {} - - /** - * Reverses the enumerator’s direction. - */ - auto rev() const - { - return enumerator_rev{this->end_.base(), - this->begin_.base(), - this->end_.get_index(), - this->begin_.get_index()}; - } - }; - - /** - * Random access base class for the enumerator. Has updated skip and take methods which make use of the random access nature of the iterator. - * @tparam Iter iterator type. - * @tparam IterWrapper wrapper used to iterate (enumerate_wrapper). - */ - template - class enumerator_random_access : public enumerator_reversible - { - public: - using enumerator_reversible::enumerator_reversible; - - auto skip(blt::size_t amount) - { - return enumerator{this->begin_.base() + amount, - this->end_.base(), - this->begin_.get_index() + amount, - this->end_.get_index()}; - } - - auto take(blt::size_t amount) - { - return enumerator{this->begin_.base(), - this->begin_.base() + amount, - this->begin_.get_index(), - this->begin_.get_index() + amount}; - } - }; - - /** - * Reversible (bidirectional) base class for the enumerator, operates in reverse for reverse enumeration. - * @tparam Iter iterator type. - * @tparam IterWrapper wrapper used to iterate (std::reverse_iterator). - */ - template - class enumerator_reversible_rev : public enumerator_reversible - { - public: - using enumerator_reversible::enumerator_reversible; - - auto rev() const - { - return enumerator{this->end_.base().base(), - this->begin_.base().base(), - this->end_.base().get_index(), - this->begin_.base().get_index()}; - } - - auto skip(blt::size_t amount) - { - auto begin = this->begin_.base(); - for (blt::size_t i = 0; i < amount; i++) - --begin; - return enumerator_rev{begin.base(), - this->end_.base().base(), - begin.get_index(), - this->end_.base().get_index()}; - } - - auto take(blt::size_t amount) - { - auto end = this->begin_.base(); - for (blt::size_t i = 0; i < amount; i++) - --end; - return enumerator_rev{ - this->begin_.base().base(), - end.base(), - this->begin_.base().get_index(), - end.get_index()}; - } - }; - - /** - * Random access base class for the enumerator. Has updated skip and take methods which make use of the random access nature of the iterator. - * Operates in reverse for reverse enumeration. - * @tparam Iter iterator type. - * @tparam IterWrapper wrapper used to iterate (std::reverse_iterator). - */ - template - class enumerator_random_access_rev : public enumerator_reversible_rev - { - public: - using enumerator_reversible_rev::enumerator_reversible_rev; - - auto skip(blt::size_t amount) - { - return enumerator_rev{this->begin_.base().base() - amount, - this->end_.base().base(), - this->begin_.base().get_index() - amount, - this->end_.base().get_index()}; - } - - auto take(blt::size_t amount) - { - return enumerator_rev{this->begin_.base().base(), - this->begin_.base().base() - amount, - this->begin_.base().get_index(), - this->begin_.base().get_index() - amount}; - } - }; - - - } - - /** - * Enumerator specialization for forward iterators - */ - template - class enumerator, std::void_t>> - : public iterator::enumerator_base> - { - public: - using iterator::enumerator_base>::enumerator_base; - }; - - /** - * Enumerator specialization for bidirectional iterators - */ - template - class enumerator, std::void_t>> - : public iterator::enumerator_reversible> - { - public: - using iterator::enumerator_reversible>::enumerator_reversible; - }; - - /** - * Enumerator specialization for random access iterators - */ - template - class enumerator, std::void_t>> - : public iterator::enumerator_random_access> - { - public: - using iterator::enumerator_random_access>::enumerator_random_access; - }; - - /** - * Reverse enumerator specialization for bidirectional iterators - */ - template - class enumerator_rev, std::void_t>> - : public iterator::enumerator_reversible_rev>> - { - public: - using iterator::enumerator_reversible_rev>>::enumerator_reversible_rev; - }; - - /** - * Reverse enumerator specialization for random access iterators - */ - template - class enumerator_rev, std::void_t>> - : public iterator::enumerator_random_access_rev>> - { - public: - using iterator::enumerator_random_access_rev>>::enumerator_random_access_rev; - }; - - // CTAD for enumerators - - template - enumerator(Iter, Iter) -> enumerator; - - template - enumerator(Iter, Iter, blt::size_t) -> enumerator; - - template - enumerator(Iter, Iter, blt::size_t, blt::size_t) -> enumerator; - - template - static inline auto enumerate(const T(& container)[size]) - { - return enumerator{&container[0], &container[size], size}; - } - - template - static inline auto enumerate(T(& container)[size]) - { - return enumerator{&container[0], &container[size], size}; - } - - template - static inline auto enumerate(T& container) - { - return enumerator{container.begin(), container.end(), container.size()}; - } - - template - static inline auto enumerate(T&& container) - { - return enumerator{container.begin(), container.end(), container.size()}; - } - - template - static inline auto enumerate(const T& container) - { - return enumerator{container.begin(), container.end(), container.size()}; - } - -} - -#endif //BLT_ITERATOR_H diff --git a/include/blt/std/random.h b/include/blt/std/random.h index 1e33e66..9ffad57 100644 --- a/include/blt/std/random.h +++ b/include/blt/std/random.h @@ -174,6 +174,12 @@ namespace blt::random return BLT_RANDOM_FUNCTION(seed, min, max); } + template + constexpr T get(T min, T max) + { + return BLT_RANDOM_FUNCTION(seed, min, max); + } + constexpr bool choice() { return BLT_RANDOM_DOUBLE(seed) < 0.5; diff --git a/include/blt/std/ranges.h b/include/blt/std/ranges.h index f987b9e..1e8693b 100644 --- a/include/blt/std/ranges.h +++ b/include/blt/std/ranges.h @@ -134,35 +134,35 @@ namespace blt iterator end_; }; - template - static inline auto in_pairs(const T& container1, const G& container2) - { - return pair_enumerator{container1.begin(), container1.end(), container2.begin(), container2.end()}; - } - - template - static inline auto in_pairs(T& container1, G& container2) - { - return pair_enumerator{container1.begin(), container1.end(), container2.begin(), container2.end()}; - } - - template - static inline auto in_pairs(const T(& container1)[size], const G(& container2)[size]) - { - return pair_enumerator{&container1[0], &container1[size], &container2[0], &container2[size]}; - } - - template - static inline auto in_pairs(T(& container1)[size], G(& container2)[size]) - { - return pair_enumerator{&container1[0], &container1[size], &container2[0], &container2[size]}; - } - - template - static inline auto in_pairs(T&& container1, G&& container2) - { - return pair_enumerator{container1.begin(), container1.end(), container2.begin(), container2.end()}; - } +// template +// static inline auto in_pairs(const T& container1, const G& container2) +// { +// return pair_enumerator{container1.begin(), container1.end(), container2.begin(), container2.end()}; +// } +// +// template +// static inline auto in_pairs(T& container1, G& container2) +// { +// return pair_enumerator{container1.begin(), container1.end(), container2.begin(), container2.end()}; +// } +// +// template +// static inline auto in_pairs(const T(& container1)[size], const G(& container2)[size]) +// { +// return pair_enumerator{&container1[0], &container1[size], &container2[0], &container2[size]}; +// } +// +// template +// static inline auto in_pairs(T(& container1)[size], G(& container2)[size]) +// { +// return pair_enumerator{&container1[0], &container1[size], &container2[0], &container2[size]}; +// } +// +// template +// static inline auto in_pairs(T&& container1, G&& container2) +// { +// return pair_enumerator{container1.begin(), container1.end(), container2.begin(), container2.end()}; +// } template struct range diff --git a/include/blt/std/vector.h b/include/blt/std/vector.h index 5ed4d12..2cc3233 100644 --- a/include/blt/std/vector.h +++ b/include/blt/std/vector.h @@ -42,8 +42,8 @@ namespace blt using pointer = T*; using const_reference = const T&; using const_pointer = const T*; - using iterator = blt::ptr_iterator; - using const_iterator = blt::ptr_iterator; + using iterator = T*; + using const_iterator = const T*; using reverse_iterator = std::reverse_iterator; using const_reverse_iterator = std::reverse_iterator; public: @@ -131,24 +131,24 @@ namespace blt return buffer_[index]; } - constexpr inline pointer operator*() + constexpr inline reference operator*() { - return buffer_; + return *buffer_.data(); } - constexpr inline const_pointer operator*() const + constexpr inline const_reference operator*() const { - return buffer_; + return *buffer_.data(); } constexpr inline pointer data() { - return buffer_; + return buffer_.data(); } constexpr inline const_pointer data() const { - return buffer_; + return buffer_.data(); } constexpr inline reference front() @@ -290,8 +290,8 @@ namespace blt using const_reference = const value_type&; using pointer = value_type*; using const_pointer = const pointer; - using iterator = blt::ptr_iterator; - using const_iterator = blt::ptr_iterator; + using iterator = T*; + using const_iterator = const T*; using reverse_iterator = std::reverse_iterator; using const_reverse_iterator = std::reverse_iterator; diff --git a/src/blt/parse/argparse.cpp b/src/blt/parse/argparse.cpp index a467e2a..4f8477c 100644 --- a/src/blt/parse/argparse.cpp +++ b/src/blt/parse/argparse.cpp @@ -6,7 +6,7 @@ #include #include #include -#include +#include #include #include "blt/std/utility.h" diff --git a/src/blt/parse/obj_loader.cpp b/src/blt/parse/obj_loader.cpp index af5eb3d..82a3c2d 100644 --- a/src/blt/parse/obj_loader.cpp +++ b/src/blt/parse/obj_loader.cpp @@ -21,7 +21,7 @@ #include #include #include -#include +#include #include #include #include "blt/std/assert.h" diff --git a/tests/iterator_tests.cpp b/tests/iterator_tests.cpp new file mode 100644 index 0000000..2cc275a --- /dev/null +++ b/tests/iterator_tests.cpp @@ -0,0 +1,168 @@ +/* + * + * Copyright (C) 2024 Brett Terpstra + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +constexpr auto increasing_reverse_pairs = + [](blt::size_t i, blt::size_t index, blt::size_t size) { return i == 0 ? index : (size - 1) - index; }; +constexpr auto increasing_pairs = + [](blt::size_t, blt::size_t index, blt::size_t) { return index; }; +constexpr auto decreasing_pairs = + [](blt::size_t, blt::size_t index, blt::size_t size) { return size - index; }; + +template +std::array make_array(Func func) +{ + std::array array; + for (auto&& [index, value] : blt::enumerate(array)) + value = blt::vec2(func(0, index, n), func(1, index, n)); + return array; +} + +template +std::forward_list make_list(Func func) +{ + std::forward_list array; + for (auto index : blt::range(0ul, n)) + array.push_front(blt::vec2(func(0, index, n), func(1, index, n))); + return array; +} + +constexpr blt::size_t array_size = 10; +auto array_1 = make_array(increasing_reverse_pairs); +auto array_2 = make_array(increasing_pairs); +auto array_3 = make_array(decreasing_pairs); + +auto list_1 = make_list(increasing_reverse_pairs); + +void test_enumerate() +{ + blt::log_box_t box(std::cout, "Enumerate Tests", 25); + for (const auto& [index, item] : blt::enumerate(array_1)) + BLT_TRACE_STREAM << index << " : " << item << "\n"; + + BLT_TRACE(""); + + for (const auto& [index, item] : blt::enumerate(array_1).rev()) + BLT_TRACE_STREAM << index << " : " << item << "\n"; + + BLT_TRACE(""); + + for (const auto& [index, item] : blt::enumerate(array_1).take(3)) + { + BLT_TRACE_STREAM << index << " : " << item << "\n"; + BLT_ASSERT(index < 3); + } + + BLT_TRACE(""); + + for (const auto& [index, item] : blt::enumerate(array_1).take(3).rev()) + { + BLT_TRACE_STREAM << index << " : " << item << "\n"; + BLT_ASSERT(index < 3); + } + + BLT_TRACE(""); + + for (const auto& [index, item] : blt::enumerate(array_1).skip(3)) + { + BLT_TRACE_STREAM << index << " : " << item << "\n"; + BLT_ASSERT(index >= 3); + } + + BLT_TRACE(""); + + for (const auto& [index, item] : blt::enumerate(array_1).skip(3).rev()) + { + BLT_TRACE_STREAM << index << " : " << item << "\n"; + BLT_ASSERT(index >= 3); + } + + BLT_TRACE(""); + + for (const auto& [index, item] : blt::enumerate(array_1).skip(3).take(5)) + { + BLT_TRACE_STREAM << index << " : " << item << "\n"; + BLT_ASSERT(index >= 3 && index < (array_1.size() - 5) + 3); + } + + BLT_TRACE(""); + + for (const auto& [index, item] : blt::enumerate(array_1).skip(3).rev().take(5)) + { + BLT_TRACE_STREAM << index << " : " << item << "\n"; + BLT_ASSERT(index >= 5); + } +} + +void test_pairs() +{ + blt::log_box_t box(std::cout, "Pairs Tests", 25); +} + +void test_zip() +{ + blt::log_box_t box(std::cout, "Zip Tests", 25); + for (auto [a1, a2, a3] : blt::zip(array_1, array_2, list_1)) + { + BLT_TRACE_STREAM << a1 << " : " << a2 << " : " << a3 << "\n"; + } + BLT_TRACE("================================"); + for (auto [a1, a2, a3] : blt::zip(array_1, array_2, list_1).take(3)) + { + BLT_TRACE_STREAM << a1 << " : " << a2 << " : " << a3 << "\n"; + } + BLT_TRACE("================================"); + for (auto [a1, a2, a3] : blt::zip(array_1, array_2, array_3).take(3).rev()) + { + BLT_TRACE_STREAM << a1 << " : " << a2 << " : " << a3 << "\n"; + } + BLT_TRACE("================================"); + for (auto [a1, a2, a3] : blt::zip(array_1, array_2, array_3).take_or(13)) + { + BLT_TRACE_STREAM << a1 << " : " << a2 << " : " << a3 << "\n"; + } + BLT_TRACE("================================"); + for (auto [a1, a2, a3] : blt::zip(array_1, array_2, array_3).rev().take(3)) + { + BLT_TRACE_STREAM << a1 << " : " << a2 << " : " << a3 << "\n"; + } + BLT_TRACE("================================"); + for (auto [a1, a2, a3] : blt::zip(array_1, array_2, array_3).skip(2).rev()) + { + BLT_TRACE_STREAM << a1 << " : " << a2 << " : " << a3 << "\n"; + } +} + +int main() +{ + test_enumerate(); + std::cout << std::endl; + test_pairs(); + std::cout << std::endl; + test_zip(); +} \ No newline at end of file diff --git a/tests/src/container_test.cpp b/tests/src/container_test.cpp index ed6abb2..4f967f1 100644 --- a/tests/src/container_test.cpp +++ b/tests/src/container_test.cpp @@ -28,8 +28,8 @@ namespace blt::test void print(const T& ref) { BLT_TRACE_STREAM << "(" << ref.size() << ") ["; - for (auto v : blt::enumerate(ref)) - BLT_TRACE_STREAM << v.second << ((v.first != ref.size()-1) ? ", " : "]\n"); + for (auto [index, item] : blt::enumerate(ref)) + BLT_TRACE_STREAM << item << ((index != ref.size()-1) ? ", " : "]\n"); } void vector_run() diff --git a/tests/src/nbt_tests.cpp b/tests/src/nbt_tests.cpp index 1dc9ba3..44990d5 100644 --- a/tests/src/nbt_tests.cpp +++ b/tests/src/nbt_tests.cpp @@ -7,7 +7,7 @@ #include #include #include -#include +#include #include #include diff --git a/tests/src/nbt_tests.h b/tests/src/nbt_tests.h index 187023d..a6eb0d0 100644 --- a/tests/src/nbt_tests.h +++ b/tests/src/nbt_tests.h @@ -15,7 +15,7 @@ namespace blt::tests { template T* generateRandomData(T* arr, size_t size, uint32_t seed = 0) { for (size_t i = 0; i < size; i++) - arr[i] = blt::random::randomInt_c(i * size + seed, std::numeric_limits::min(), std::numeric_limits::max()); + arr[i] = blt::random::random_t(i * size + seed).get(std::numeric_limits::min(), std::numeric_limits::max()); return arr; } diff --git a/tests/src/profiling_tests.h b/tests/src/profiling_tests.h index ac27a6c..94ebcd0 100644 --- a/tests/src/profiling_tests.h +++ b/tests/src/profiling_tests.h @@ -10,7 +10,7 @@ #include "blt/profiling/profiler_v2.h" #include "blt/std/logging.h" #include "blt/std/time.h" -#include "blt/std/format.h" +#include "blt/format/format.h" void print(const std::vector& vtr) { for (const auto& line : vtr) diff --git a/tests/src/string_tests.cpp b/tests/src/string_tests.cpp index 4f3216e..444b7cb 100644 --- a/tests/src/string_tests.cpp +++ b/tests/src/string_tests.cpp @@ -19,6 +19,7 @@ #include #include #include +#include namespace blt::test { @@ -32,27 +33,27 @@ namespace blt::test auto sv_splits_c = blt::string::split_sv(str, ' '); auto sv_splits_s = blt::string::split_sv(str, "LOT"); - for (auto v : blt::enumerate(s_splits_c)) + for (auto [index, item] : blt::enumerate(s_splits_c)) { - if (v.second != sv_splits_c[v.first]) + if (item != sv_splits_c[index]) { - BLT_WARN("THEY DO NOT MATCH!!! '%s' vs '%s'", v.second.c_str(), std::string(sv_splits_c[v.first]).c_str()); + BLT_WARN("THEY DO NOT MATCH!!! '%s' vs '%s'", item.c_str(), std::string(sv_splits_c[index]).c_str()); } else { - BLT_DEBUG(v.second); + BLT_DEBUG(item); } } BLT_INFO(""); - for (auto v : blt::enumerate(s_splits_s)) + for (auto [index, item] : blt::enumerate(s_splits_s)) { - if (v.second != sv_splits_s[v.first]) + if (item != sv_splits_s[index]) { - BLT_WARN("THEY DO NOT MATCH!!! '%s' vs '%s'", v.second.c_str(), std::string(sv_splits_s[v.first]).c_str()); + BLT_WARN("THEY DO NOT MATCH!!! '%s' vs '%s'", item.c_str(), std::string(sv_splits_s[index]).c_str()); } else { - BLT_DEBUG(v.second); + BLT_DEBUG(item); } } } diff --git a/tests/src/utility_test.cpp b/tests/src/utility_test.cpp index 20bd404..7dd5c9f 100644 --- a/tests/src/utility_test.cpp +++ b/tests/src/utility_test.cpp @@ -16,7 +16,7 @@ * along with this program. If not, see . */ #include -#include +#include #include #include #include