Code View

mstring / mstring-1.3.1.2 / src / MUtil.cpp
// 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 << '"';
}