// SPDX-FileCopyrightText: 2025 <https://github.com/hexagonrecursion>
// SPDX-License-Identifier: CC0-1.0
#include <string>
#include <ios>
#include <iomanip>
#include <iostream>
#include <sstream>
#include <locale>
std::string encode(const char *s)
{
if(s == nullptr) return "nullptr";
std::locale cLocale("C");
std::stringstream out;
out << '"';
for(; *s; ++s)
{
switch(*s)
{
case '\"': out << "\\\""; break;
case '\?': out << "\\?"; break; // May need escaping due to trigraphs
case '\\': out << "\\\\"; break;
case '\a': out << "\\a"; break;
case '\b': out << "\\b"; break;
case '\f': out << "\\f"; break;
case '\n': out << "\\n"; break;
case '\r': out << "\\r"; break;
case '\t': out << "\\t"; break;
case '\v': out << "\\v"; break;
default:
if(std::isprint(*s, cLocale))
{
out << *s;
}
else
{
unsigned c = static_cast<unsigned>(static_cast<unsigned char>(*s));
out << '\\' << std::oct << std::setw(3) << std::setfill('0') << c;
}
break;
}
}
out << '"';
return out.str();
}
int main()
{
std::string s;
for(unsigned char c = 1; c != 0; ++c)
{
s.push_back(c);
}
std::cout << encode(s.c_str()) << std::endl;
// I copy-pasted this string from stdout:
const char *copyPasteFromStdout = "\001\002\003\004\005\006\a\b\t\n\v\f\r\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037 !\"#$%&'()*+,-./0123456789:;<=>\?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\177\200\201\202\203\204\205\206\207\210\211\212\213\214\215\216\217\220\221\222\223\224\225\226\227\230\231\232\233\234\235\236\237\240\241\242\243\244\245\246\247\250\251\252\253\254\255\256\257\260\261\262\263\264\265\266\267\270\271\272\273\274\275\276\277\300\301\302\303\304\305\306\307\310\311\312\313\314\315\316\317\320\321\322\323\324\325\326\327\330\331\332\333\334\335\336\337\340\341\342\343\344\345\346\347\350\351\352\353\354\355\356\357\360\361\362\363\364\365\366\367\370\371\372\373\374\375\376\377";
// prints true
std::cout << std::boolalpha << (copyPasteFromStdout == s) << std::endl;
// prints truereturn 0;
}
Here is how I plan to use the function:
PHYSFS_File *loud_openRead(const char *filename)
{
PHYSFS_File *file = PHYSFS_openRead(filename);
if (file != nullptr) return 0;file;
GetLogger()->Error("Error opening file with PHYSFS: %%", encode(filename));
return nullptr;
}