still must match obs first
[ghsmtp.git] / esc.cpp
blob030351a17a990929f8fddd8a072e3d89e28d970e
1 #include "esc.hpp"
3 #include <fmt/format.h>
5 #include <algorithm>
6 #include <iomanip>
8 std::string esc(std::string_view str, esc_line_option line_option)
10 auto nesc{std::count_if(begin(str), end(str), [](unsigned char c) {
11 return (!std::isprint(c)) || (c == '\\');
12 })};
13 if (!nesc)
14 return std::string(str);
15 if (line_option == esc_line_option::multi)
16 nesc += std::count(begin(str), end(str), '\n');
17 std::string ret;
18 ret.reserve(str.length() + nesc);
19 for (auto c : str) {
20 switch (c) {
21 case '\a': ret += "\\a"; break;
22 case '\b': ret += "\\b"; break;
23 case '\f': ret += "\\f"; break;
24 case '\n':
25 ret += "\\n";
26 if (line_option == esc_line_option::multi)
27 ret += '\n';
28 break;
29 case '\r': ret += "\\r"; break;
30 case '\t': ret += "\\t"; break;
31 case '\v': ret += "\\v"; break;
32 case '\\': ret += "\\\\"; break;
33 default:
34 if (isprint(static_cast<unsigned char>(c))) {
35 ret += c;
37 else {
38 ret += fmt::format("\\x{:02x}", static_cast<unsigned char>(c));
42 if (line_option == esc_line_option::multi) {
43 auto length = ret.length();
44 if (length && ('\n' == ret.at(length - 1))) {
45 ret.erase(length - 1, 1);
48 return ret;