#include #include #include #include "dbc.hpp" #include #include "ansi_parser.hpp" using namespace fmt; %%{ machine foo; alphtype int; action tstart { start = fpc; } action number { value = 0; size_t len = fpc - start; dbc::check(start[0] != '-', "negative numbers not supported"); switch(len) { case 10: value += (start[len-10] - '0') * 1000000000; case 9: value += (start[len- 9] - '0') * 100000000; case 8: value += (start[len- 8] - '0') * 10000000; case 7: value += (start[len- 7] - '0') * 1000000; case 6: value += (start[len- 6] - '0') * 100000; case 5: value += (start[len- 5] - '0') * 10000; case 4: value += (start[len- 4] - '0') * 1000; case 3: value += (start[len- 3] - '0') * 100; case 2: value += (start[len- 2] - '0') * 10; case 1: value += (start[len- 1] - '0'); break; default: dbc::sentinel("can't process > 10 digits"); } } action color24b { } action is_fg { target = color; } action is_bg { target = bgcolor; } action out { write(bgcolor, color, fc); } action reset_fg { color = default_fg; } action reset_bg { bgcolor = default_bg; } action red { target.r = value; } action blue { target.g = value; } action green { target.b = value; } action start { value = 0; } action end { } ESC = 0x1B; start = ESC "["; fg = "38;" %is_fg; bg = "48;" %is_bg; reset = ("39" %reset_fg | "49" %reset_bg); num = digit+ >tstart %number; color256 = "5;"; color24b = "2;"; ansi = ( start %start ( reset | (fg|bg) color24b num %red ";" num %blue ";" num %green %color24b ) "m" %end ); other = (any+ @out -- ESC)*; main := (other :> ansi)**; }%% %% write data; bool parse_ansi(std::wstring_view codes, sf::Color default_fg, sf::Color default_bg, WriteCB write) { const wchar_t *start = NULL; int cs = 0; unsigned int value = 0; const wchar_t *p = codes.data(); const wchar_t *pe = p + codes.size(); const wchar_t *eof = pe; sf::Color bgcolor(default_bg); sf::Color color(default_fg); sf::Color &target = color; %% write init; %% write exec; return p - pe == 0; }