start ...
This commit is contained in:
75
.gitignore
vendored
Normal file
75
.gitignore
vendored
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
# This file is used to ignore files which are generated
|
||||||
|
# ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
*~
|
||||||
|
*.autosave
|
||||||
|
*.a
|
||||||
|
*.core
|
||||||
|
*.moc
|
||||||
|
*.o
|
||||||
|
*.obj
|
||||||
|
*.orig
|
||||||
|
*.rej
|
||||||
|
*.so
|
||||||
|
*.so.*
|
||||||
|
*_pch.h.cpp
|
||||||
|
*_resource.rc
|
||||||
|
*.qm
|
||||||
|
.#*
|
||||||
|
*.*#
|
||||||
|
core
|
||||||
|
!core/
|
||||||
|
tags
|
||||||
|
.DS_Store
|
||||||
|
.directory
|
||||||
|
*.debug
|
||||||
|
Makefile*
|
||||||
|
*.prl
|
||||||
|
*.app
|
||||||
|
moc_*.cpp
|
||||||
|
ui_*.h
|
||||||
|
qrc_*.cpp
|
||||||
|
Thumbs.db
|
||||||
|
*.res
|
||||||
|
*.rc
|
||||||
|
/.qmake.cache
|
||||||
|
/.qmake.stash
|
||||||
|
|
||||||
|
# qtcreator generated files
|
||||||
|
*.pro.user*
|
||||||
|
CMakeLists.txt.user*
|
||||||
|
|
||||||
|
# xemacs temporary files
|
||||||
|
*.flc
|
||||||
|
|
||||||
|
# Vim temporary files
|
||||||
|
.*.swp
|
||||||
|
|
||||||
|
# Visual Studio generated files
|
||||||
|
*.ib_pdb_index
|
||||||
|
*.idb
|
||||||
|
*.ilk
|
||||||
|
*.pdb
|
||||||
|
*.sln
|
||||||
|
*.suo
|
||||||
|
*.vcproj
|
||||||
|
*vcproj.*.*.user
|
||||||
|
*.ncb
|
||||||
|
*.sdf
|
||||||
|
*.opensdf
|
||||||
|
*.vcxproj
|
||||||
|
*vcxproj.*
|
||||||
|
|
||||||
|
# MinGW generated files
|
||||||
|
*.Debug
|
||||||
|
*.Release
|
||||||
|
|
||||||
|
# Python byte code
|
||||||
|
*.pyc
|
||||||
|
|
||||||
|
# Binaries
|
||||||
|
# --------
|
||||||
|
*.dll
|
||||||
|
*.exe
|
||||||
|
|
||||||
|
build/
|
||||||
24
CMakeLists.txt
Normal file
24
CMakeLists.txt
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
cmake_minimum_required(VERSION 3.10.0)
|
||||||
|
project(snipplib VERSION 0.1.0 LANGUAGES CXX)
|
||||||
|
|
||||||
|
option(BUILD_EXAMPLES "Build examples" ON)
|
||||||
|
|
||||||
|
|
||||||
|
set(LIB_HEADERS include/snipplib/concepts/snplib_concepts.h
|
||||||
|
include/snipplib/utils/snplib_hash.h
|
||||||
|
include/snipplib/utils/snplib_utils.h
|
||||||
|
include/snipplib/hmap/snplib_hmap.h)
|
||||||
|
|
||||||
|
add_library(${PROJECT_NAME} INTERFACE ${LIB_HEADERS})
|
||||||
|
target_compile_features(${PROJECT_NAME} INTERFACE cxx_std_23)
|
||||||
|
target_include_directories(
|
||||||
|
${PROJECT_NAME}
|
||||||
|
INTERFACE
|
||||||
|
"$<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/include>"
|
||||||
|
"$<INSTALL_INTERFACE:include/${PROJECT_NAME}>"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
set(EXAM_STRING str_exam)
|
||||||
|
add_executable(${EXAM_STRING} examples/str_exam.cpp)
|
||||||
|
target_link_libraries(${EXAM_STRING} ${PROJECT_NAME})
|
||||||
29
examples/str_exam.cpp
Normal file
29
examples/str_exam.cpp
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
#include <print>
|
||||||
|
// #include "../utils/snplib_string.h"
|
||||||
|
// #include "../include/snipplib/snplib_string.h"
|
||||||
|
#include <snipplib/utils/snplib_string.h>
|
||||||
|
|
||||||
|
using namespace snplib;
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
std::string si = " dewf wek e lwekjflkj ";
|
||||||
|
|
||||||
|
auto s = snplib_trim_spaces(si);
|
||||||
|
|
||||||
|
std::println("s = '{}'", s);
|
||||||
|
|
||||||
|
auto sv = snplib_trim_spaces_as_view(si, TrimType::TRIM_LEFT);
|
||||||
|
|
||||||
|
std::println("sv(TrimType::TRIM_LEFT) = '{}'", sv);
|
||||||
|
|
||||||
|
sv = snplib_trim_spaces_as_view(si, TrimType::TRIM_RIGHT);
|
||||||
|
|
||||||
|
std::println("sv(TrimType::TRIM_RIGHT) = '{}'", sv);
|
||||||
|
|
||||||
|
sv = snplib_trim_spaces_as_view(si, TrimType::TRIM_BOTH);
|
||||||
|
|
||||||
|
std::println("sv(TrimType::TRIM_BOTH) = '{}'", sv);
|
||||||
|
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
28
include/snipplib/concepts/snplib_concepts.h
Normal file
28
include/snipplib/concepts/snplib_concepts.h
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <concepts>
|
||||||
|
#include <ranges>
|
||||||
|
|
||||||
|
namespace snplib {
|
||||||
|
|
||||||
|
// type T is hashable
|
||||||
|
template <typename T>
|
||||||
|
concept snplib_hashable_c = requires(T t) {
|
||||||
|
{ std::hash<T>(t) } -> std::convertible_to<size_t>;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T, typename CharT = char>
|
||||||
|
concept snplib_char_range_c = std::ranges::range<T> && std::same_as<std::ranges::range_value_t<T>, CharT>;
|
||||||
|
|
||||||
|
template <typename T, typename CharT = char>
|
||||||
|
concept snplib_input_char_range_c = std::ranges::input_range<T> && std::same_as<std::ranges::range_value_t<T>, CharT>;
|
||||||
|
|
||||||
|
template <typename T, typename CharT = char>
|
||||||
|
concept snplib_output_char_range_c = std::ranges::output_range<T, CharT>;
|
||||||
|
|
||||||
|
template <typename T, typename CharT = char>
|
||||||
|
concept snplib_char_view_c = std::ranges::view<T> && std::same_as<std::ranges::range_value_t<T>, CharT>;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
} // end of snplib namespace
|
||||||
67
include/snipplib/hmap/snplib_hmap.h
Normal file
67
include/snipplib/hmap/snplib_hmap.h
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "../concepts/snplib_concepts.h"
|
||||||
|
#include "../utils/snplib_hash.h"
|
||||||
|
|
||||||
|
namespace snplib {
|
||||||
|
|
||||||
|
|
||||||
|
template<snplib_hashable_c KeyT>
|
||||||
|
class HeterogenMap {
|
||||||
|
protected:
|
||||||
|
// actuall map key type
|
||||||
|
typedef std::pair<const HeterogenMap*, KeyT> key_t;
|
||||||
|
|
||||||
|
struct KeyHash {
|
||||||
|
static size_t operator()(key_t key) {
|
||||||
|
size_t hash = 0;
|
||||||
|
|
||||||
|
snplib_hash_combine(hash, key.first, , key.second);
|
||||||
|
|
||||||
|
return hash;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename VT>
|
||||||
|
inline static std::unordered_map<key_t, VT, KeyHash> _umap{};
|
||||||
|
|
||||||
|
std::vector<std::function<void()>> _clearFunc{};
|
||||||
|
|
||||||
|
public:
|
||||||
|
enum Error : {ERROR_OK, ERROR_NO_ELEM};
|
||||||
|
|
||||||
|
HeterogenMap() = default;
|
||||||
|
|
||||||
|
~HeterogenMap() {
|
||||||
|
for (auto &func: _clearFunc) {
|
||||||
|
func();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename VT>
|
||||||
|
size_t push(KeyT const& key, VT&& value) {
|
||||||
|
auto it = _umap<std::decay_t<VT>>.emplace(std::make_pair(this, key), std::forward<VT>(value));
|
||||||
|
|
||||||
|
if (it.second){
|
||||||
|
_clearFunc.empace_back([it=it.first]() { _umap<std::decay_t<VT>>.erase(it); });
|
||||||
|
} // here the element already exists (just update its value)
|
||||||
|
|
||||||
|
return _clearFunc.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename VT, typename ...CtorArgTs>
|
||||||
|
size_t emplace(KeyT const&, CtorArgTs&& ...args) {
|
||||||
|
return push(key, VT(std::forward<CtorArgTs>(args)...));
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename VT>
|
||||||
|
std::expected<VT, Error> get(KeyT const& key) const {
|
||||||
|
if (auto it = _umap<VT>.find(std::make_pair(this, key)); it != _umap<VT>.end()) {
|
||||||
|
return it->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
return std::unexpected(Error::ERROR_NO_ELEM);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // end of namespace snplib
|
||||||
86
include/snipplib/utils/snplib_hash.h
Normal file
86
include/snipplib/utils/snplib_hash.h
Normal file
@@ -0,0 +1,86 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "../concepts/snplib_concepts.h"
|
||||||
|
#include <iterator>
|
||||||
|
|
||||||
|
namespace snplib {
|
||||||
|
|
||||||
|
template <snplib_input_char_range_c R>
|
||||||
|
static constexpr size_t FNV1aHash(const R& r)
|
||||||
|
{
|
||||||
|
static_assert(sizeof(size_t) == 8 || sizeof(size_t) == 4, "ONLY FOR 32 or 64-bit size_t!!!");
|
||||||
|
|
||||||
|
size_t hash = 0, prime = 0;
|
||||||
|
if constexpr (sizeof(size_t) == 8) { // 64-bit
|
||||||
|
prime = 1099511628211UL;
|
||||||
|
hash = 14695981039346656037UL;
|
||||||
|
} else if constexpr (sizeof(size_t) == 4) { // 32-bit
|
||||||
|
prime = 16777619;
|
||||||
|
hash = 2166136261;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const char& ch : r) {
|
||||||
|
hash ^= ch;
|
||||||
|
hash *= prime;
|
||||||
|
}
|
||||||
|
|
||||||
|
return hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
static constexpr size_t FNV1aHash(std::forward_iterator auto begin, std::sentinel_for<decltype(begin)> auto end)
|
||||||
|
requires std::same_as<std::remove_cv_t<std::iter_value_t<decltype(begin)>>, char>
|
||||||
|
{
|
||||||
|
static_assert(sizeof(size_t) == 8 || sizeof(size_t) == 4, "ONLY FOR 32 or 64-bit size_t!!!");
|
||||||
|
|
||||||
|
size_t hash = 0, prime = 0;
|
||||||
|
if constexpr (sizeof(size_t) == 8) { // 64-bit
|
||||||
|
prime = 1099511628211UL;
|
||||||
|
hash = 14695981039346656037UL;
|
||||||
|
} else if constexpr (sizeof(size_t) == 4) { // 32-bit
|
||||||
|
prime = 16777619;
|
||||||
|
hash = 2166136261;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto it = begin; it != end; ++it) {
|
||||||
|
hash ^= *it;
|
||||||
|
hash *= prime;
|
||||||
|
}
|
||||||
|
|
||||||
|
return hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Boost implementation of hash combining
|
||||||
|
template <snplib_hashable_c T, snplib_hashable_c ...Ts>
|
||||||
|
static constexpr void snplib_hash_combine(std::size_t& seed, const T& v, Ts&& ... vs) {
|
||||||
|
static constexpr auto digits = std::numeric_limits<std::size_t>::digits;
|
||||||
|
static_assert(digits == 64 || digits == 32, "Unsupported 'size_t' type size!");
|
||||||
|
|
||||||
|
if constexpr (digits == 64) {
|
||||||
|
std::size_t x = seed + 0x9e3779b9 + std::hash<T>()(v);
|
||||||
|
const std::size_t m = 0xe9846af9b1a615d;
|
||||||
|
x ^= x >> 32;
|
||||||
|
x *= m;
|
||||||
|
x ^= x >> 32;
|
||||||
|
x *= m;
|
||||||
|
x ^= x >> 28;
|
||||||
|
seed = x;
|
||||||
|
}
|
||||||
|
else { // 32-bits
|
||||||
|
std::size_t x = seed + 0x9e3779b9 + std::hash<T>()(v);
|
||||||
|
const std::size_t m1 = 0x21f0aaad;
|
||||||
|
const std::size_t m2 = 0x735a2d97;
|
||||||
|
x ^= x >> 16;
|
||||||
|
x *= m1;
|
||||||
|
x ^= x >> 15;
|
||||||
|
x *= m2;
|
||||||
|
x ^= x >> 15;
|
||||||
|
seed = x;
|
||||||
|
}
|
||||||
|
|
||||||
|
if constexpr (sizeof...(Ts)) {
|
||||||
|
snplib_hash_combine(seed, std::forward<Ts>(vs)...);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // end of snplib namespace
|
||||||
77
include/snipplib/utils/snplib_string.h
Normal file
77
include/snipplib/utils/snplib_string.h
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include "../concepts/snplib_concepts.h"
|
||||||
|
|
||||||
|
namespace snplib {
|
||||||
|
|
||||||
|
constexpr static bool snplib_is_space(char in) noexcept
|
||||||
|
{
|
||||||
|
static constexpr auto ws = {' ', '\t', '\n', '\v', '\r', '\f'};
|
||||||
|
return std::ranges::any_of(ws, [in](auto p) { return p == in; });
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
enum class TrimType { TRIM_LEFT, TRIM_RIGHT, TRIM_BOTH };
|
||||||
|
|
||||||
|
template <snplib_output_char_range_c OR, snplib_input_char_range_c R, typename IsSpaceFuncT = decltype(snplib_is_space)>
|
||||||
|
constexpr static OR snplib_trim_spaces(R&& r, TrimType type = TrimType::TRIM_BOTH, IsSpaceFuncT&& is_space_func = snplib_is_space)
|
||||||
|
{
|
||||||
|
if (type == TrimType::TRIM_LEFT) {
|
||||||
|
auto res = r | std::views::drop_while(is_space_func);
|
||||||
|
return OR{res.begin(), res.end()};
|
||||||
|
} else if (type == TrimType::TRIM_RIGHT) {
|
||||||
|
auto res = r | std::views::reverse | std::views::drop_while(is_space_func) |
|
||||||
|
std::views::reverse;
|
||||||
|
return OR{res.begin(), res.end()};
|
||||||
|
} else if (type == TrimType::TRIM_BOTH) {
|
||||||
|
auto res = r | std::views::drop_while(is_space_func) | std::views::reverse | std::views::drop_while(is_space_func) |
|
||||||
|
std::views::reverse;
|
||||||
|
return OR{res.begin(), res.end()};
|
||||||
|
}
|
||||||
|
|
||||||
|
return OR{};
|
||||||
|
}
|
||||||
|
|
||||||
|
template <snplib_input_char_range_c R, typename IsSpaceFuncT = decltype(snplib_is_space)>
|
||||||
|
constexpr static std::string snplib_trim_spaces(R&& r, TrimType type = TrimType::TRIM_BOTH, IsSpaceFuncT&& is_space_func = snplib_is_space)
|
||||||
|
{
|
||||||
|
return snplib_trim_spaces<std::string>(std::forward<R>(r), type, std::forward<IsSpaceFuncT>(is_space_func));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <snplib_input_char_range_c R, typename IsSpaceFuncT = decltype(snplib_is_space)>
|
||||||
|
constexpr static std::string_view snplib_trim_spaces_as_view(R&& r, TrimType type = TrimType::TRIM_BOTH, IsSpaceFuncT&& is_space_func = snplib_is_space)
|
||||||
|
requires std::ranges::contiguous_range<R>
|
||||||
|
{
|
||||||
|
auto end = std::forward<R>(r).end();
|
||||||
|
|
||||||
|
auto f1 = std::forward<R>(r).begin();
|
||||||
|
|
||||||
|
if (type != TrimType::TRIM_RIGHT) {
|
||||||
|
// look for the first non-space symbol
|
||||||
|
f1 = std::ranges::find_if_not(std::forward<R>(r), std::forward<IsSpaceFuncT>(is_space_func));
|
||||||
|
if (f1 == end) { // all are spaces!
|
||||||
|
return std::string_view();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto f2 = end;
|
||||||
|
|
||||||
|
if (type != TrimType::TRIM_LEFT) {
|
||||||
|
auto f3 = f1;
|
||||||
|
|
||||||
|
do {
|
||||||
|
f2 = std::ranges::find_if(++f3, end, std::forward<IsSpaceFuncT>(is_space_func));
|
||||||
|
if (f2 == end)
|
||||||
|
break;
|
||||||
|
f3 = std::ranges::find_if_not(f2 + 1, end, std::forward<IsSpaceFuncT>(is_space_func));
|
||||||
|
} while (f3 != end);
|
||||||
|
}
|
||||||
|
|
||||||
|
return std::string_view(f1, f2);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} // end of snplib namespace
|
||||||
2
include/snipplib/utils/snplib_utils.h
Normal file
2
include/snipplib/utils/snplib_utils.h
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
5
snipplib.cpp
Normal file
5
snipplib.cpp
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
void say_hello(){
|
||||||
|
std::cout << "Hello, from snipplib!\n";
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user