]> Creatis software - cpPlugins.git/blobdiff - lib/mstch/template_type.cpp
Moved to version 1.0
[cpPlugins.git] / lib / mstch / template_type.cpp
diff --git a/lib/mstch/template_type.cpp b/lib/mstch/template_type.cpp
new file mode 100644 (file)
index 0000000..5b40e40
--- /dev/null
@@ -0,0 +1,104 @@
+#include "template_type.hpp"
+
+using namespace mstch;
+
+template_type::template_type(const std::string& str, const delim_type& delims):
+    m_open(delims.first), m_close(delims.second)
+{
+  tokenize(str);
+  strip_whitespace();
+}
+
+template_type::template_type(const std::string& str):
+    m_open("{{"), m_close("}}")
+{
+  tokenize(str);
+  strip_whitespace();
+}
+
+void template_type::process_text(citer begin, citer end) {
+  if (begin == end)
+    return;
+  auto start = begin;
+  for (auto it = begin; it != end; ++it)
+    if (*it == '\n' || it == end - 1) {
+      m_tokens.push_back({{start, it + 1}});
+      start = it + 1;
+    }
+}
+
+void template_type::tokenize(const std::string& tmp) {
+  citer beg = tmp.begin();
+  auto npos = std::string::npos;
+
+  for (std::size_t cur_pos = 0; cur_pos < tmp.size();) {
+    auto open_pos = tmp.find(m_open, cur_pos);
+    auto close_pos = tmp.find(
+        m_close, open_pos == npos ? open_pos : open_pos + 1);
+
+    if (close_pos != npos && open_pos != npos) {
+      if (*(beg + open_pos + m_open.size()) == '{' &&
+          *(beg + close_pos + m_close.size()) == '}')
+        ++close_pos;
+
+      process_text(beg + cur_pos, beg + open_pos);
+      cur_pos = close_pos + m_close.size();
+      m_tokens.push_back({{beg + open_pos, beg + close_pos + m_close.size()},
+          m_open.size(), m_close.size()});
+
+      if (cur_pos == tmp.size()) {
+        m_tokens.push_back({{""}});
+        m_tokens.back().eol(true);
+      }
+
+      if (*(beg + open_pos + m_open.size()) == '=' &&
+          *(beg + close_pos - 1) == '=')
+      {
+        auto tok_beg = beg + open_pos + m_open.size() + 1;
+        auto tok_end = beg + close_pos - 1;
+        auto front_skip = first_not_ws(tok_beg, tok_end);
+        auto back_skip = first_not_ws(reverse(tok_end), reverse(tok_beg));
+        m_open = {front_skip, beg + tmp.find(' ', front_skip - beg)};
+        m_close = {beg + tmp.rfind(' ', back_skip - beg) + 1, back_skip + 1};
+      }
+    } else {
+      process_text(beg + cur_pos, tmp.end());
+      cur_pos = close_pos;
+    }
+  }
+}
+
+void template_type::strip_whitespace() {
+  auto line_begin = m_tokens.begin();
+  bool has_tag = false, non_space = false;
+
+  for (auto it = m_tokens.begin(); it != m_tokens.end(); ++it) {
+    auto type = (*it).token_type();
+    if (type != token::type::text && type != token::type::variable &&
+        type != token::type::unescaped_variable)
+      has_tag = true;
+    else if (!(*it).ws_only())
+      non_space = true;
+
+    if ((*it).eol()) {
+      if (has_tag && !non_space) {
+        store_prefixes(line_begin);
+
+        auto c = line_begin;
+        for (bool end = false; !end; (*c).ws_only() ? c = m_tokens.erase(c) : ++c)
+          if ((end = (*c).eol()))
+            it = c - 1;
+      }
+
+      non_space = has_tag = false;
+      line_begin = it + 1;
+    }
+  }
+}
+
+void template_type::store_prefixes(std::vector<token>::iterator beg) {
+  for (auto cur = beg; !(*cur).eol(); ++cur)
+    if ((*cur).token_type() == token::type::partial &&
+        cur != beg && (*(cur - 1)).ws_only())
+      (*cur).partial_prefix((*(cur - 1)).raw());
+}