RingRacers/src/sanitize.cpp
Sally Coolatta 7dfa597c7d SRB2 -> DRRR copyright in src, acs, android folder
Be consistent with toaster's recent changes to copyright
2024-04-05 02:08:23 -04:00

144 lines
2.8 KiB
C++

// DR. ROBOTNIK'S RING RACERS
//-----------------------------------------------------------------------------
// Copyright (C) 2024 by James Robert Roman
// Copyright (C) 2024 by Kart Krew
//
// This program is free software distributed under the
// terms of the GNU General Public License, version 2.
// See the 'LICENSE' file for more details.
//-----------------------------------------------------------------------------
#include <algorithm>
#include <cctype>
#include <iterator>
#include <string>
#include <string_view>
#include "doomtype.h"
#include "sanitize.h"
#include "v_draw.hpp"
using namespace srb2::sanitize;
namespace
{
bool print_filter(char c)
{
return !std::isprint(c);
}
bool color_filter(char c)
{
return print_filter(c) && (c & 0xF0) != 0x80; // color codes
}
template <typename F>
std::string& filter_out(std::string& out, const std::string_view& range, F filter)
{
std::remove_copy_if(
range.begin(),
range.end(),
std::back_inserter(out),
filter
);
return out;
};
int hexconv(int c)
{
if (std::isdigit(c))
return c - '0';
c = std::toupper(c);
if (c >= 'A' && c <= 'F')
return 10 + (c - 'A');
return -1;
}
}; // namespace
namespace srb2::sanitize
{
std::string sanitize(std::string_view in, SanitizeMode mode)
{
std::string out;
return filter_out(out, in, [mode]
{
switch (mode)
{
default:
case SanitizeMode::kPrintable:
return print_filter;
case SanitizeMode::kKeepColors:
return color_filter;
}
}());
}
std::string parse_carets(std::string_view in, ParseMode mode)
{
std::string out;
using std::size_t;
for (;;)
{
size_t p = in.find('^');
// copy chars up until the caret
// but filter out codes outside of the ASCII range
filter_out(out, in.substr(0, p), print_filter);
if (p == in.npos)
{
break; // end of input
}
in.remove_prefix(p);
// need two characters for caret code
// convert to color byte
if (int c; in.length() > 1 && (c = hexconv(in[1])) != -1)
{
out.push_back(0x80 | c);
}
if (mode != ParseMode::kConsume)
{
// preserve caret code in output
filter_out(out, in.substr(0, 2), print_filter);
}
if (in.length() < 2)
{
break;
}
in.remove_prefix(2);
}
return out;
}
}; // namespace srb2
void D_SanitizeKeepColors(char *out, const char *in, size_t out_size)
{
strlcpy(out, sanitize(in, SanitizeMode::kKeepColors).c_str(), out_size);
}
void D_ParseCarets(char *out, const char *in, size_t out_size)
{
strlcpy(out, parse_carets(in, ParseMode::kConsume).c_str(), out_size);
}
INT32 M_DrawCaretString(INT32 x, INT32 y, const char *string, boolean preserve)
{
using srb2::Draw;
Draw::TextElement text(parse_carets(string, preserve ? ParseMode::kPreserve : ParseMode::kConsume));
text.font(Draw::Font::kConsole);
Draw(x, y).text(text);
return text.width();
}