From 4016e04061901980ae454bd271f2f7e3617bb85e Mon Sep 17 00:00:00 2001 From: Tobias Christiansen Date: Fri, 30 Apr 2021 23:31:53 +0200 Subject: [PATCH] AK: Move bijective-base-conversion into AK/String This allows everybody to create a String version of their number in a arbitrary bijective base. Bijective base meaning that the mapping doesn't have a 0. In the usual mapping to the alphabet the follower after 'Z' is 'AA'. The mapping using the (uppercase) alphabet is used as a standard but can be overridden specifying 'base' and 'map'. The code was directly yanked from the Spreadsheet. --- AK/String.cpp | 27 +++++++++++++++++++++++++++ AK/String.h | 2 ++ 2 files changed, 29 insertions(+) diff --git a/AK/String.cpp b/AK/String.cpp index d6004bfcab6..4a70da2d07d 100644 --- a/AK/String.cpp +++ b/AK/String.cpp @@ -244,6 +244,33 @@ String String::repeated(char ch, size_t count) return *impl; } +String String::bijective_base_from(size_t value, unsigned base, StringView map) +{ + if (map.is_null()) + map = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"sv; + + VERIFY(base >= 2 && base <= map.length()); + + // The '8 bits per byte' assumption may need to go? + Array buffer; + size_t i = 0; + do { + buffer[i++] = map[value % base]; + value /= base; + } while (value > 0); + + // NOTE: Weird as this may seem, the thing that comes after 'Z' is 'AA', which as a number would be '00' + // to make this work, only the most significant digit has to be in a range of (1..25) as opposed to (0..25), + // but only if it's not the only digit in the string. + if (i > 1) + --buffer[i - 1]; + + for (size_t j = 0; j < i / 2; ++j) + swap(buffer[j], buffer[i - j - 1]); + + return String { ReadonlyBytes(buffer.data(), i) }; +} + bool String::matches(const StringView& mask, Vector& mask_spans, CaseSensitivity case_sensitivity) const { return StringUtils::matches(*this, mask, case_sensitivity, &mask_spans); diff --git a/AK/String.h b/AK/String.h index b690910b1a1..621ff92dc11 100644 --- a/AK/String.h +++ b/AK/String.h @@ -93,6 +93,8 @@ public: [[nodiscard]] static String repeated(char, size_t count); + [[nodiscard]] static String bijective_base_from(size_t value, unsigned base = 26, StringView map = {}); + template [[nodiscard]] static String join(const SeparatorType& separator, const CollectionType& collection) {