1#include "terminalpp/ansi/charset.hpp" 
    2#include "terminalpp/character_set.hpp" 
    6namespace terminalpp::detail {
 
   24    fg_greyscale_colour_0,
 
   25    fg_greyscale_colour_1,
 
   36    bg_greyscale_colour_0,
 
   37    bg_greyscale_colour_1,
 
   53    parser_state state{parser_state::idle};
 
   62constexpr byte digit10_to_byte(
char const ch)
 
   64    return static_cast<byte>(ch - 
'0');
 
   67constexpr byte digit16_to_byte(
char const ch)
 
   69    return (ch >= 
'0' && ch <= 
'9') ? 
static_cast<byte>(ch - 
'0')
 
   70         : (ch >= 
'a' && ch <= 
'f') ? static_cast<byte>((ch - 
'a') + 10)
 
   71         : (ch >= 
'A' && ch <= 
'F') ? static_cast<byte>((ch - 
'A') + 10)
 
   72                                    : static_cast<byte>(0);
 
   75constexpr void parse_utf8_3(
char const ch, parser_info &info, element &elem)
 
   77    constexpr std::uint64_t 
const maxima[] = {
 
   78        0x00007F, 0x0007FF, 0x00FFFF, 0x10FFFF};
 
   81    uint16_t 
const value = (info.utf8 * 16) + digit16_to_byte(ch);
 
   88    if (value <= maxima[0])
 
   90        text[0] = byte(value & 0x7F);
 
   94    else if (value <= maxima[1])
 
   96        text[0] = byte(0b11000000 | (value >> 6));
 
   97        text[1] = byte(0b10000000 | (value & 0b00111111));
 
  100    else if (value <= maxima[2])
 
  102        text[0] = byte(0b11100000 | (value >> 12));
 
  103        text[1] = byte(0b10000000 | ((value >> 6) & 0b00111111));
 
  104        text[2] = byte(0b10000000 | (value & 0b00111111));
 
  114    info.state = parser_state::done;
 
  117constexpr void parse_utf8_2(
char const ch, parser_info &info, element &elem)
 
  120    info.utf8 += digit16_to_byte(ch);
 
  121    info.state = parser_state::utf8_3;
 
  124constexpr void parse_utf8_1(
char const ch, parser_info &info, element &elem)
 
  127    info.utf8 += digit16_to_byte(ch);
 
  128    info.state = parser_state::utf8_2;
 
  131constexpr void parse_utf8_0(
char const ch, parser_info &info, element &elem)
 
  133    info.utf8 = digit16_to_byte(ch);
 
  134    info.state = parser_state::utf8_1;
 
  137constexpr void parse_bg_true_colour_5(
 
  138    char const ch, parser_info &info, element &elem)
 
  140    info.blue |= digit16_to_byte(ch);
 
  142    elem.attribute_.background_colour_ =
 
  143        true_colour{info.red, info.green, info.blue};
 
  145    info.state = parser_state::idle;
 
  148constexpr void parse_bg_true_colour_4(
 
  149    char const ch, parser_info &info, element &elem)
 
  151    info.blue = digit16_to_byte(ch) << 4;
 
  152    info.state = parser_state::bg_true_colour_5;
 
  155constexpr void parse_bg_true_colour_3(
 
  156    char const ch, parser_info &info, element &elem)
 
  158    info.green |= digit16_to_byte(ch);
 
  159    info.state = parser_state::bg_true_colour_4;
 
  162constexpr void parse_bg_true_colour_2(
 
  163    char const ch, parser_info &info, element &elem)
 
  165    info.green = digit16_to_byte(ch) << 4;
 
  166    info.state = parser_state::bg_true_colour_3;
 
  169constexpr void parse_bg_true_colour_1(
 
  170    char const ch, parser_info &info, element &elem)
 
  172    info.red |= digit16_to_byte(ch);
 
  173    info.state = parser_state::bg_true_colour_2;
 
  176constexpr void parse_bg_true_colour_0(
 
  177    char const ch, parser_info &info, element &elem)
 
  179    info.red = digit16_to_byte(ch) << 4;
 
  180    info.state = parser_state::bg_true_colour_1;
 
  183constexpr void parse_bg_greyscale_1(
 
  184    char const ch, parser_info &info, element &elem)
 
  186    byte const col = (info.greyscale * 10) + digit10_to_byte(ch);
 
  187    elem.attribute_.background_colour_ = greyscale_colour(col);
 
  188    info.state = parser_state::idle;
 
  191constexpr void parse_bg_greyscale_0(
 
  192    char const ch, parser_info &info, element &elem)
 
  194    info.greyscale = digit10_to_byte(ch);
 
  195    info.state = parser_state::bg_greyscale_colour_1;
 
  198constexpr void parse_bg_high_colour_2(
 
  199    char const ch, parser_info &info, element &elem)
 
  201    auto const blue = digit10_to_byte(ch);
 
  202    elem.attribute_.background_colour_ =
 
  203        high_colour(info.red, info.green, blue);
 
  204    info.state = parser_state::idle;
 
  207constexpr void parse_bg_high_colour_1(
 
  208    char const ch, parser_info &info, element &elem)
 
  210    info.green = digit10_to_byte(ch);
 
  211    info.state = parser_state::bg_high_colour_2;
 
  214constexpr void parse_bg_high_colour_0(
 
  215    char const ch, parser_info &info, element &elem)
 
  217    info.red = digit10_to_byte(ch);
 
  218    info.state = parser_state::bg_high_colour_1;
 
  221constexpr void parse_bg_low_colour(
 
  222    char const ch, parser_info &info, element &elem)
 
  224    auto const col_code = digit10_to_byte(ch);
 
  225    auto const col = 
static_cast<terminalpp::graphics::colour
>(col_code);
 
  227    elem.attribute_.background_colour_ = low_colour(col);
 
  228    info.state = parser_state::idle;
 
  231constexpr void parse_fg_greyscale_1(
 
  232    char const ch, parser_info &info, element &elem)
 
  234    byte const col = (info.greyscale * 10) + digit10_to_byte(ch);
 
  235    elem.attribute_.foreground_colour_ = greyscale_colour(col);
 
  236    info.state = parser_state::idle;
 
  239constexpr void parse_fg_greyscale_0(
 
  240    char const ch, parser_info &info, element &elem)
 
  242    info.greyscale = digit10_to_byte(ch);
 
  243    info.state = parser_state::fg_greyscale_colour_1;
 
  246constexpr void parse_fg_true_colour_5(
 
  247    char const ch, parser_info &info, element &elem)
 
  249    info.blue |= digit16_to_byte(ch);
 
  251    elem.attribute_.foreground_colour_ =
 
  252        true_colour{info.red, info.green, info.blue};
 
  254    info.state = parser_state::idle;
 
  257constexpr void parse_fg_true_colour_4(
 
  258    char const ch, parser_info &info, element &elem)
 
  260    info.blue = digit16_to_byte(ch) << 4;
 
  261    info.state = parser_state::fg_true_colour_5;
 
  264constexpr void parse_fg_true_colour_3(
 
  265    char const ch, parser_info &info, element &elem)
 
  267    info.green |= digit16_to_byte(ch);
 
  268    info.state = parser_state::fg_true_colour_4;
 
  271constexpr void parse_fg_true_colour_2(
 
  272    char const ch, parser_info &info, element &elem)
 
  274    info.green = digit16_to_byte(ch) << 4;
 
  275    info.state = parser_state::fg_true_colour_3;
 
  278constexpr void parse_fg_true_colour_1(
 
  279    char const ch, parser_info &info, element &elem)
 
  281    info.red |= digit16_to_byte(ch);
 
  282    info.state = parser_state::fg_true_colour_2;
 
  285constexpr void parse_fg_true_colour_0(
 
  286    char const ch, parser_info &info, element &elem)
 
  288    info.red = digit16_to_byte(ch) << 4;
 
  289    info.state = parser_state::fg_true_colour_1;
 
  292constexpr void parse_fg_high_colour_2(
 
  293    char const ch, parser_info &info, element &elem)
 
  295    auto const blue = digit10_to_byte(ch);
 
  296    elem.attribute_.foreground_colour_ =
 
  297        high_colour(info.red, info.green, blue);
 
  298    info.state = parser_state::idle;
 
  301constexpr void parse_fg_high_colour_1(
 
  302    char const ch, parser_info &info, element &elem)
 
  304    info.green = digit10_to_byte(ch);
 
  305    info.state = parser_state::fg_high_colour_2;
 
  308constexpr void parse_fg_high_colour_0(
 
  309    char const ch, parser_info &info, element &elem)
 
  311    info.red = digit10_to_byte(ch);
 
  312    info.state = parser_state::fg_high_colour_1;
 
  315constexpr void parse_fg_low_colour(
 
  316    char const ch, parser_info &info, element &elem)
 
  318    auto const col_code = digit10_to_byte(ch);
 
  319    auto const col = 
static_cast<terminalpp::graphics::colour
>(col_code);
 
  321    elem.attribute_.foreground_colour_ = low_colour(col);
 
  322    info.state = parser_state::idle;
 
  325constexpr void parse_underlining(
 
  326    char const ch, parser_info &info, element &elem)
 
  331            elem.attribute_.underlining_ = graphics::underlining::underlined;
 
  335            elem.attribute_.underlining_ =
 
  336                graphics::underlining::not_underlined;
 
  340            elem.attribute_.underlining_ =
 
  341                graphics::underlining::not_underlined;
 
  345    info.state = parser_state::idle;
 
  348constexpr void parse_polarity(
char const ch, parser_info &info, element &elem)
 
  353            elem.attribute_.polarity_ = graphics::polarity::positive;
 
  357            elem.attribute_.polarity_ = graphics::polarity::negative;
 
  361            elem.attribute_.polarity_ = graphics::polarity::positive;
 
  365    info.state = parser_state::idle;
 
  368constexpr void parse_intensity(
char const ch, parser_info &info, element &elem)
 
  373            elem.attribute_.intensity_ = graphics::intensity::bold;
 
  377            elem.attribute_.intensity_ = graphics::intensity::faint;
 
  381            elem.attribute_.intensity_ = graphics::intensity::normal;
 
  385    info.state = parser_state::idle;
 
  388constexpr void parse_charset_ext(
 
  389    char const ch, parser_info &info, element &elem)
 
  391    byte const charset_code[] = {ansi::charset_extender, 
static_cast<byte>(ch)};
 
  392    auto const charset = lookup_character_set(charset_code);
 
  393    elem.glyph_.charset_ = charset ? *charset : elem.glyph_.charset_;
 
  394    info.state = parser_state::idle;
 
  397constexpr void parse_charset(
char const ch, parser_info &info, element &elem)
 
  402            info.state = parser_state::charset_ext;
 
  407            byte const charset_code[] = {
static_cast<byte>(ch)};
 
  408            auto const charset = lookup_character_set(charset_code);
 
  409            elem.glyph_.charset_ = charset ? *charset : elem.glyph_.charset_;
 
  410            info.state = parser_state::idle;
 
  415constexpr void parse_charcode_2(
char const ch, parser_info &info, element &elem)
 
  418    info.charcode += digit10_to_byte(ch);
 
  419    elem.glyph_.character_ = info.charcode;
 
  420    info.state = parser_state::done;
 
  423constexpr void parse_charcode_1(
char const ch, parser_info &info, element &elem)
 
  426    info.charcode += digit10_to_byte(ch);
 
  427    info.state = parser_state::charcode_2;
 
  430constexpr void parse_charcode_0(
char const ch, parser_info &info, element &elem)
 
  432    info.charcode = digit10_to_byte(ch);
 
  433    info.state = parser_state::charcode_1;
 
  436constexpr void parse_escape(
char const ch, parser_info &info, element &elem)
 
  441            info.state = parser_state::charcode_0;
 
  445            info.state = parser_state::charset;
 
  449            info.state = parser_state::intensity;
 
  453            info.state = parser_state::polarity;
 
  457            info.state = parser_state::underlining;
 
  461            info.state = parser_state::fg_low_colour;
 
  465            info.state = parser_state::fg_high_colour_0;
 
  469            info.state = parser_state::fg_greyscale_colour_0;
 
  473            info.state = parser_state::fg_true_colour_0;
 
  477            info.state = parser_state::bg_low_colour;
 
  481            info.state = parser_state::bg_high_colour_0;
 
  485            info.state = parser_state::bg_greyscale_colour_0;
 
  489            info.state = parser_state::bg_true_colour_0;
 
  493            info.state = parser_state::utf8_0;
 
  497            elem.attribute_ = {};
 
  498            info.state = parser_state::idle;
 
  502            elem.glyph_.character_ = 
static_cast<byte>(ch);
 
  503            info.state = parser_state::done;
 
  508constexpr void parse_idle(
char const ch, parser_info &info, element &elem)
 
  513            info.state = parser_state::escape;
 
  517            elem.glyph_.character_ = 
static_cast<byte>(ch);
 
  518            info.state = parser_state::done;
 
  523constexpr element element_with_base(element 
const &elem_base)
 
  525    element result = elem_base;
 
  526    result.glyph_.charset_ = result.glyph_.charset_ == charset::utf8
 
  528                               : result.glyph_.charset_;
 
  529    result.glyph_.character_ = 
' ';
 
  534constexpr element parse_element(
 
  535    std::span<char const> &text, element 
const &elem_base)
 
  537    auto info = parser_info{};
 
  538    auto elem = element_with_base(elem_base);
 
  540    using handler = void (*)(char, parser_info &, element &);
 
  541    handler 
const handlers[] = {
 
  553        parse_fg_high_colour_0,
 
  554        parse_fg_high_colour_1,
 
  555        parse_fg_high_colour_2,
 
  556        parse_fg_greyscale_0,
 
  557        parse_fg_greyscale_1,
 
  558        parse_fg_true_colour_0,
 
  559        parse_fg_true_colour_1,
 
  560        parse_fg_true_colour_2,
 
  561        parse_fg_true_colour_3,
 
  562        parse_fg_true_colour_4,
 
  563        parse_fg_true_colour_5,
 
  565        parse_bg_high_colour_0,
 
  566        parse_bg_high_colour_1,
 
  567        parse_bg_high_colour_2,
 
  568        parse_bg_greyscale_0,
 
  569        parse_bg_greyscale_1,
 
  570        parse_bg_true_colour_0,
 
  571        parse_bg_true_colour_1,
 
  572        parse_bg_true_colour_2,
 
  573        parse_bg_true_colour_3,
 
  574        parse_bg_true_colour_4,
 
  575        parse_bg_true_colour_5,
 
  582    while (!text.empty() && info.state != parser_state::done)
 
  584        handlers[
static_cast<int>(info.state)](text[0], info, elem);
 
  585        text = text.subspan(1);
 
A structure that carries around the character attributes of an ANSI element.
Definition glyph.hpp:19