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