Program Listing for File encode_dns_char_string.h

Return to documentation for file (utils/encode_dns_char_string.h)

#pragma once

#include <expected.h>
#include <expected_helpers.h>

#include <array>
#include <cstdint>
#include <fixed_name.hpp>
#include <string_view>

namespace _detail {
static constexpr size_t char_encoding_max_size = 4;

struct CharEncoding {
    char encoded[char_encoding_max_size];
    uint8_t len;

    operator std::string_view() const {
        return std::string_view(encoded, len);
    }
};

static constexpr char to_decimal_char(int n) {
    return static_cast<char>('0' + n);
}

static constexpr std::array<char, 3> to_decimal(int n) {
    return {to_decimal_char(n / 100), to_decimal_char((n / 10) % 10), to_decimal_char(n % 10)};
}

static constexpr std::array<CharEncoding, 256> char_map = []() {
    std::array<CharEncoding, 256> map{};
    for (int i = 0; i < 256; ++i) {
        if (i >= 32 && i <= 126 && i != '"' && i != '\\') {
            map[i] = {{static_cast<char>(i)}, 1};
        } else {
            auto decimal = to_decimal(i);
            map[i] = {{'\\', decimal[0], decimal[1], decimal[2]}, 4};
        }
    }
    map['"'] = {{'\\', '"'}, 2};
    map['\\'] = {{'\\', '\\'}, 2};
    return map;
}();
} // namespace _detail

template <size_t N>
static FixedName<N * _detail::char_encoding_max_size> encode_dns_char_string(FixedName<N> in,
    bool add_quotes = false) {
    FixedName<N * _detail::char_encoding_max_size> out;

    if (add_quotes)
        out += "\"";

    for (unsigned char c : std::string_view(in)) {
        const auto& encoding = _detail::char_map[c];
        out += encoding;
    }

    if (add_quotes)
        out += "\"";

    return out;
}