
#include "pdf_stringize.h"
#include <sstream>
#include <iomanip>
#include "def.h"

using std::string;

// Refer to Adobe's PDF Reference, ver. 1.7, Sect. 3.2.3 and Table 3.2.

string Util::pdf_stringize( const char c ) {
  if      ( c == '\n'     ) return "\\n" ;
  else if ( c == '\r'     ) return "\\r" ;
  else if ( c == '\t'     ) return "\\t" ;
  else if ( c == '\b'     ) return "\\b" ;
  else if ( c == '\f'     ) return "\\f" ;
  else if ( c == '('/*)*/ ) return "\\(" ;
  else if ( c == /*(*/')' ) return "\\)" ;
  else if ( c == '\\'     ) return "\\\\";
  else if ( !( 0040 <= c && c < 0177 ) ) {
    int i = c & 0377;
    std::ostringstream s;
    s << std::noshowbase << std::oct << std::setfill('0');
    s << '\\' << std::setw(3) << i;
    return s.str();
  }
  return string( 1, c );
}

string Util::pdf_stringize( const std::string &s ) {
  string pdf = "(";
  for (
    string::const_iterator p = s.begin();
    p != s.end() && (
      Util::max_pdf_string_length < 0 ||
      // The following test looks odd.  A +1 should be added to
      // max_pdf_string_length to account for the opening delimiter;
      // a -1 should be subtracted to allow for the possibility that the
      // next character added will be escaped.  The two offset, so
      // nothing is added or subtracted in net.
      int(pdf.length()) < Util::max_pdf_string_length
    );
    ++p
  ) pdf += pdf_stringize(*p);
  return pdf += ")";
}

string Util::pdf_stringize( const char *const s ) {
  return pdf_stringize( string(s) );
}

