1 
  
    2 
  
    3 
  
    4 
  
    5 
  
    6 #include <soulng/lexer/XmlParsingLog.hpp>
  
    7 #include <soulng/util/Unicode.hpp>
  
    8 #include <algorithm>
  
    9 #include <sstream>
  
   10 #include <cctype>
  
   11 
  
   12 namespace soulng { namespace lexer {
  
   13 
  
   14 using namespace soulng::unicode;
  
   15 
  
   16 std::u32string XmlHexEscape(char32_t c)
  
   17 {
  
   18     std::stringstream s;
  
   19     s << "&#x" << std::hex << (unsigned int)c << ";";
  
   20     return ToUtf32(s.str());
  
   21 }
  
   22 
  
   23 std::u32string XmlCharStr(char32_t c)
  
   24 {
  
   25     switch (c)
  
   26     {
  
   27         case '&': return U"&";
  
   28         case '<': return U"<";
  
   29         case '>': return U">";
  
   30         case '\a': return U"\\a";
  
   31         case '\b': return U"\\b";
  
   32         case '\f': return U"\\f";
  
   33         case '\n': return U"\\n";
  
   34         case '\r': return U"\\r";
  
   35         case '\t': return U"\\t";
  
   36         case '\v': return U"\\v";
  
   37         default:
  
   38         {
  
   39             if (((int)c >= 32 && (int)c <= 126))
  
   40             {
  
   41                 return std::u32string(1, c);
  
   42             }
  
   43             else
  
   44             {
  
   45                 return XmlHexEscape(c);
  
   46             }
  
   47         }
  
   48     }
  
   49     return std::u32string();
  
   50 }
  
   51 
  
   52 std::u32string XmlEscape(const std::u32string& s)
  
   53 {
  
   54     std::u32string result;
  
   55     result.reserve(2 * s.length());
  
   56     std::u32string::const_iterator e = s.end();
  
   57     for (std::u32string::const_iterator i = s.begin(); i != e; ++i)
  
   58     {
  
   59         result.append(XmlCharStr(*i));
  
   60     }
  
   61     return result;
  
   62 }
  
   63 
  
   64 XmlParsingLog::XmlParsingLog(std::ostream& stream_) : ParsingLog(), formatter(stream_)
  
   65 {
  
   66     formatter.SetIndentSize(1);
  
   67 }
  
   68 
  
   69 XmlParsingLog::XmlParsingLog(std::ostream& stream_, int maxLineLength_) : ParsingLog(maxLineLength_), formatter(stream_)
  
   70 {
  
   71     formatter.SetIndentSize(1);
  
   72 }
  
   73 
  
   74 void XmlParsingLog::IncIndent()
  
   75 {
  
   76     formatter.IncIndent();
  
   77 }
  
   78 
  
   79 void XmlParsingLog::DecIndent()
  
   80 {
  
   81     formatter.DecIndent();
  
   82 }
  
   83 
  
   84 void XmlParsingLog::WriteBeginRule(const std::u32string& ruleName)
  
   85 {
  
   86     Write(U"<" + ruleName + U">");
  
   87 }
  
   88 
  
   89 void XmlParsingLog::WriteEndRule(const std::u32string& ruleName)
  
   90 {
  
   91     Write(U"</" + ruleName + U">");
  
   92 }
  
   93 
  
   94 void XmlParsingLog::WriteTry(const std::u32string& s)
  
   95 {
  
   96     WriteElement(U"try", s);
  
   97 }
  
   98 
  
   99 void XmlParsingLog::WriteSuccess(const std::u32string& match)
  
  100 {
  
  101     WriteElement(U"success", match);
  
  102 }
  
  103 
  
  104 void XmlParsingLog::WriteFail()
  
  105 {
  
  106     Write(U"<fail/>");
  
  107 }
  
  108 
  
  109 void XmlParsingLog::WriteElement(const std::u32string& elementName, const std::u32string& elementContent)
  
  110 {
  
  111     std::u32string converted = XmlEscape(elementContent);
  
  112     int convertedLength = static_cast<int>(converted.length());
  
  113     int lineLength = 2 * static_cast<int>(elementName.length()) + 5 + convertedLength;
  
  114     std::u32string s = converted;
  
  115     if (lineLength > MaxLineLength())
  
  116     {
  
  117         lineLength += 3;
  
  118         s = converted.substr(0, std::max(0, convertedLength - (lineLength - MaxLineLength()))) + U"...";
  
  119     }
  
  120     Write(U"<" + elementName + U">" + s + U"</" + elementName + U">");
  
  121 }
  
  122 
  
  123 void XmlParsingLog::Write(const std::u32string& s)
  
  124 {
  
  125     formatter.WriteLine(ToUtf8(s));
  
  126 }
  
  127 
  
  128 } }