Advertisement
Vultraz

Untitled

Apr 1st, 2018
264
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 2.48 KB | None | 0 0
  1. config parse_text(const std::string& text)
  2. {
  3.     config res;
  4.  
  5.     const auto add_text_child =
  6.         [&res](const std::string text) { res.add_child("text", config {"text", text}); };
  7.  
  8.     bool last_char_escape = false;
  9.     const char escape_char = '\\';
  10.  
  11.     std::stringstream ss;
  12.     std::size_t pos;
  13.  
  14.     enum { ELEMENT_NAME, OTHER } state = OTHER;
  15.  
  16.     for(pos = 0; pos < text.size(); ++pos) {
  17.         const char c = text[pos];
  18.  
  19.         if(c == escape_char && !last_char_escape) {
  20.             last_char_escape = true;
  21.         } else {
  22.             if(state == OTHER) {
  23.                 if(c == '<') {
  24.                     if(last_char_escape) {
  25.                         ss << c;
  26.                     } else {
  27.                         add_text_child(ss.str());
  28.                         ss.str("");
  29.                         state = ELEMENT_NAME;
  30.                     }
  31.                 } else {
  32.                     ss << c;
  33.                 }
  34.             } else if(state == ELEMENT_NAME) {
  35.                 if(c == '/') {
  36.                     throw parse_error("Erroneous / in element name.");
  37.                 } else if(c == '>') {
  38.                     const std::string element_name = ss.str();
  39.                     ss.str("");
  40.  
  41.                     // End of this name.
  42.                     // For markup such as "<span color=''>", we only want the first word. If the name
  43.                     // has no spaces, the entirety will be used.
  44.                     std::stringstream s;
  45.                     s << "</" << element_name.substr(0, element_name.find_first_of(' ')) << ">";
  46.  
  47.                     const std::string end_element_name = s.str();
  48.                     std::size_t end_pos = text.find(end_element_name, pos);
  49.  
  50.                     if(end_pos == std::string::npos) {
  51.                         throw parse_error(formatter() << "Unterminated element: " << element_name);
  52.                     }
  53.  
  54.                     const std::string contents = text.substr(pos + 1, end_pos - pos - 1);
  55.  
  56.                     // If we find no '=' character, we assume we're dealing with Pango markup.
  57.                     if(contents.find('=') != std::string::npos) {
  58.                         s.str(convert_to_wml(element_name, contents));
  59.                         s.seekg(0);
  60.  
  61.                         try {
  62.                             config cfg;
  63.                             read(cfg, s);
  64.  
  65.                             res.append_children(cfg);
  66.                         } catch(config::error& e) {
  67.                             throw parse_error(formatter() << "Error when parsing help markup as WML: " << e.message);
  68.                         }
  69.                     } else {
  70.                         add_text_child(formatter() << "<" << element_name << ">" << contents << end_element_name);
  71.                     }
  72.  
  73.                     pos = end_pos + end_element_name.size() - 1;
  74.                     state = OTHER;
  75.                 } else {
  76.                     ss << c;
  77.                 }
  78.             }
  79.  
  80.             last_char_escape = false;
  81.         }
  82.     }
  83.  
  84.     if(state == ELEMENT_NAME) {
  85.         throw parse_error(formatter() << "Element '" << ss.str() << "' continues through end of string.");
  86.     }
  87.  
  88.     // Add the last string.
  89.     if(!ss.str().empty()) {
  90.         res.add_child("text", config{"text", ss.str()});
  91.     }
  92.  
  93.     return res;
  94. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement