based

Opinionated utility library
git clone git://git.dimitrijedobrota.com/based.git
Log | Files | Refs | README | LICENSE | HACKING | CONTRIBUTING | CODE_OF_CONDUCT | BUILDING

commit cda6076429cb9a9ec7e504594bf4ef592edf55ba
parent d3258aa292b673d04de2314914c374cf04069537
author Dimitrije Dobrota < mail@dimitrijedobrota.com >
date Sat, 31 May 2025 19:53:40 +0200

Map chars to ints based on predicate

Diffstat:
A include/based/char/mapper.hpp | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
M test/CMakeLists.txt | ++++
A test/source/char/mapper_test.cpp | +++++++++++++++++

3 files changed, 96 insertions(+), 0 deletions(-)


diff --git a/ include/based/char/mapper.hpp b/ include/based/char/mapper.hpp

@@ -0,0 +1,75 @@

#pragma once

#include <array>

#include "based/concepts/procedure/predicate.hpp"
#include "based/types/types.hpp"

namespace based
{

template<Predicate<char> Predicate>
class mapper
{
static constexpr based::size_t size = 128;
using mapped_type = bu8;

static constexpr Predicate m_predicate = {};

using direct_t = std::array<mapped_type, size>;
static constexpr direct_t direct = []
{
direct_t res = {};

mapped_type count = 0;
for (std::size_t idx = 0; idx < size; idx++) {
if (m_predicate(static_cast<char>(idx))) {
res[idx] = count++;
}
}

return res;
}();

static constexpr const std::size_t count = []
{
mapped_type count = 0;
for (std::size_t idx = 0; idx < size; idx++) {
if (m_predicate(static_cast<char>(idx))) {
count++;
}
}
return count;
}();

using reverse_t = std::array<char, count>;
static constexpr reverse_t reverse = []
{
reverse_t res = {};

mapped_type count = 0;
for (std::size_t idx = 0; idx < size; idx++) {
const auto chr = static_cast<char>(idx);
if (m_predicate(chr)) {
res[count++] = chr;
}
}

return res;
}();

public:
static constexpr bool predicate(char chr) { return m_predicate(chr); }
static constexpr char map(mapped_type value) { return reverse[value]; }
static constexpr mapped_type map(char chr)
{
return direct[static_cast<based::size_t>(chr)];
}
};

struct test
{
constexpr bool operator()(char chr) const { return chr >= 'a' && chr <= 'z'; }
};

} // namespace based

diff --git a/ test/CMakeLists.txt b/ test/CMakeLists.txt

@@ -83,6 +83,10 @@ add_test(. list_test)


add_test(. string_literal_test)

## ----- Char -----

add_test(char mapper_test)

# ---- End-of-file commands ----

add_folders(Test)

diff --git a/ test/source/char/mapper_test.cpp b/ test/source/char/mapper_test.cpp

@@ -0,0 +1,17 @@

#define CATCH_CONFIG_RUNTIME_STATIC_REQUIRE

#include "based/char/mapper.hpp"

#include <catch2/catch_test_macros.hpp>

struct test
{
constexpr bool operator()(char chr) const { return chr >= '\0'; }
};

template class based::mapper<test>;

TEST_CASE("mapper", "[char/mapper]")
{
REQUIRE(true);
}