diff 3rdparty/maddy/tableparser.h @ 0:a4671277546c tip

created the repository for the thymian project
author ferencd
date Tue, 17 Aug 2021 11:19:54 +0200
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/3rdparty/maddy/tableparser.h	Tue Aug 17 11:19:54 2021 +0200
@@ -0,0 +1,246 @@
+/*
+ * This project is licensed under the MIT license. For more information see the
+ * LICENSE file.
+ */
+#pragma once
+
+// -----------------------------------------------------------------------------
+
+#include <functional>
+#include <string>
+#include <regex>
+
+#include "maddy/blockparser.h"
+
+// -----------------------------------------------------------------------------
+
+namespace maddy {
+
+// -----------------------------------------------------------------------------
+
+/**
+ * TableParser
+ *
+ * For more information, see the docs folder.
+ *
+ * @class
+ */
+class TableParser : public BlockParser
+{
+public:
+  /**
+   * ctor
+   *
+   * @method
+   * @param {std::function<void(std::string&)>} parseLineCallback
+   * @param {std::function<std::shared_ptr<BlockParser>(const std::string& line)>} getBlockParserForLineCallback
+   */
+   TableParser(
+    std::function<void(std::string&)> parseLineCallback,
+    std::function<std::shared_ptr<BlockParser>(const std::string& line)> getBlockParserForLineCallback
+  )
+    : BlockParser(parseLineCallback, getBlockParserForLineCallback)
+    , isStarted(false)
+    , isFinished(false)
+    , currentBlock(0)
+    , currentRow(0)
+  {}
+
+  /**
+   * IsStartingLine
+   *
+   * If the line has exact `|table>`, then it is starting the table.
+   *
+   * @method
+   * @param {const std::string&} line
+   * @return {bool}
+   */
+  static bool
+  IsStartingLine(const std::string& line)
+  {
+    static std::string matchString("|table>");
+    return line == matchString;
+  }
+
+  /**
+   * AddLine
+   *
+   * Adding a line which has to be parsed.
+   *
+   * @method
+   * @param {std::string&} line
+   * @return {void}
+   */
+  void
+  AddLine(std::string& line) override
+  {
+    if (!this->isStarted && line == "|table>")
+    {
+      this->isStarted = true;
+      return;
+    }
+
+    if (this->isStarted)
+    {
+      if (line == "- | - | -")
+      {
+        ++this->currentBlock;
+        this->currentRow = 0;
+        return;
+      }
+
+      if (line == "|<table")
+      {
+        static std::string emptyLine = "";
+        this->parseBlock(emptyLine);
+        this->isFinished = true;
+        return;
+      }
+
+      if (this->table.size() < this->currentBlock + 1)
+      {
+        this->table.push_back(std::vector<std::vector<std::string>>());
+      }
+      this->table[this->currentBlock].push_back(std::vector<std::string>());
+
+      std::string segment;
+      std::stringstream streamToSplit(line);
+
+      while (std::getline(streamToSplit, segment, '|'))
+      {
+        this->parseLine(segment);
+        this->table[this->currentBlock][this->currentRow].push_back(segment);
+      }
+
+      ++this->currentRow;
+    }
+  }
+
+  /**
+   * IsFinished
+   *
+   * A table ends with `|<table`.
+   *
+   * @method
+   * @return {bool}
+   */
+  bool
+  IsFinished() const override
+  {
+    return this->isFinished;
+  }
+
+protected:
+  bool
+  isInlineBlockAllowed() const override
+  {
+    return false;
+  }
+
+  bool
+  isLineParserAllowed() const override
+  {
+    return true;
+  }
+
+  void
+  parseBlock(std::string&) override
+  {
+    result << "<table>";
+
+    bool hasHeader = false;
+    bool hasFooter = false;
+    bool isFirstBlock = true;
+    uint32_t currentBlockNumber = 0;
+
+    if (this->table.size() > 1)
+    {
+      hasHeader = true;
+    }
+
+    if (this->table.size() >= 3)
+    {
+      hasFooter = true;
+    }
+
+    for (const std::vector<std::vector<std::string>>& block : this->table)
+    {
+      bool isInHeader = false;
+      bool isInFooter = false;
+      ++currentBlockNumber;
+
+      if (hasHeader && isFirstBlock)
+      {
+        result << "<thead>";
+        isInHeader = true;
+      }
+      else if (hasFooter && currentBlockNumber == this->table.size())
+      {
+        result << "<tfoot>";
+        isInFooter = true;
+      }
+      else
+      {
+        result << "<tbody>";
+      }
+
+      for (const std::vector<std::string>& row : block)
+      {
+        result << "<tr>";
+
+        for (const std::string& column : row)
+        {
+          if (isInHeader)
+          {
+            result << "<th>";
+          }
+          else
+          {
+            result << "<td>";
+          }
+
+          result << column;
+
+          if (isInHeader)
+          {
+            result << "</th>";
+          }
+          else
+          {
+            result << "</td>";
+          }
+        }
+
+        result << "</tr>";
+      }
+
+      if (isInHeader)
+      {
+        result << "</thead>";
+      }
+      else if (isInFooter)
+      {
+        result << "</tfoot>";
+      }
+      else
+      {
+        result << "</tbody>";
+      }
+
+      isFirstBlock = false;
+    }
+
+    result << "</table>";
+  }
+
+private:
+  bool isStarted;
+  bool isFinished;
+  uint32_t currentBlock;
+  uint32_t currentRow;
+  std::vector<std::vector<std::vector<std::string>>> table;
+}; // class TableParser
+
+// -----------------------------------------------------------------------------
+
+} // namespace maddy