// SPDX-License-Identifier: MIT
#include "MUtil.hh"
#include <ostream>
std::string Trim( const std::string &str )
{
static const char *const blanks = " \t\r";
std::string::size_type const first = str.find_first_not_of( blanks );
if ( first == std::string::npos )
{
return "";
}
std::string::size_type const last = str.find_last_not_of( blanks );
return str.substr( first, last - first + 1 );
}
void WriteStringLiteral( std::ostream &stream, const std::string &text,
const std::string &indent, std::string::size_type hang )
{
static const char digits[] = "01234567";
bool lineBreak = false;
bool octal = false; // the previous character was written as an octal escape
char previous = '\0';
stream << '"';
for ( char const chr : text )
{
unsigned char const code = static_cast<unsigned char>( chr );
if ( lineBreak )
{
stream << "\"\n" << indent << std::string( hang, ' ' ) << '"';
lineBreak = false;
octal = false;
}
switch ( chr )
{
case '\a': stream << "\\a"; break;
case '\b': stream << "\\b"; break;
case '\f': stream << "\\f"; break;
case '\n': stream << "\\n"; lineBreak = true; break;
case '\r': stream << "\\r"; break;
case '\t': stream << "\\t"; break;
case '\v': stream << "\\v"; break;
case '\\': stream << "\\\\"; break;
case '"': stream << "\\\""; break;
case '?': stream << ( previous == '?' ? "\\?" : "?" ); break; // no "??x" trigraph
default:
if ( code >= 0x20 && code < 0x7f )
{
// An octal escape takes up to three digits: a digit right after one
// would be swallowed, so split the literal there.
if ( octal && chr >= '0' && chr <= '9' )
{
stream << "\" \"";
}
stream << chr;
}
else
{
// Non-ASCII bytes (the message's charset) and control characters,
// byte for byte, independent of the compiler's source charset.
stream << '\\' << digits[( code >> 6 ) & 7] << digits[( code >> 3 ) & 7] << digits[code & 7];
octal = true;
previous = chr;
continue;
}
}
octal = false;
previous = chr;
}
stream << '"';
}