summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordante <dante19031999@gmail.com>2021-08-08 23:27:56 +0200
committerNoel Grandin <noel.grandin@collabora.co.uk>2021-08-09 17:49:22 +0200
commite8d8dad6bba2bd0a4307ee3c1fc40f117680c1f3 (patch)
tree93a255cf27c7c923df2de6face39fc2dcd5a048d
parentccb1d71fe4c0585a42721f09d984fb699ff8f081 (diff)
Add an iterator for the new starmath matml elements
Change-Id: I7b57951795e8acd704f418d10e5fd0aded3f2b34 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/120187 Tested-by: Jenkins Reviewed-by: Noel Grandin <noel.grandin@collabora.co.uk>
-rw-r--r--starmath/Library_sm.mk1
-rw-r--r--starmath/inc/mathml/element.hxx62
-rw-r--r--starmath/inc/mathml/iterator.hxx125
-rw-r--r--starmath/source/mathml/element.cxx1
-rw-r--r--starmath/source/mathml/iterator.cxx71
5 files changed, 260 insertions, 0 deletions
diff --git a/starmath/Library_sm.mk b/starmath/Library_sm.mk
index 297cca650684..e9bb53676b91 100644
--- a/starmath/Library_sm.mk
+++ b/starmath/Library_sm.mk
@@ -104,6 +104,7 @@ $(eval $(call gb_Library_add_exception_objects,sm,\
starmath/source/mathml/mathmlexport \
starmath/source/mathml/mathmlimport \
starmath/source/mathml/mathmlMo \
+ starmath/source/mathml/iterator \
starmath/source/mathml/attribute \
starmath/source/mathml/element \
starmath/source/mathml/def \
diff --git a/starmath/inc/mathml/element.hxx b/starmath/inc/mathml/element.hxx
index 8843d5e8767d..2c5ec40ab019 100644
--- a/starmath/inc/mathml/element.hxx
+++ b/starmath/inc/mathml/element.hxx
@@ -10,6 +10,7 @@
#pragma once
#include "attribute.hxx"
+#include "starmathdatabase.hxx"
#include <rect.hxx>
#include <editeng/editdata.hxx>
@@ -27,6 +28,7 @@ public:
, m_aAttributePosList(0)
, m_aSubElements(0)
, m_aParentElement(nullptr)
+ , m_nSubElementId(0)
{
SmImplAttributeType();
};
@@ -39,10 +41,26 @@ protected:
, m_aESelection(0, 0, 0, 0)
, m_aSubElements(0)
, m_aParentElement(nullptr)
+ , m_nSubElementId(0)
{
SmImplAttributeType();
};
+public:
+ SmMlElement(const SmMlElement& aElement)
+ : SmRect(static_cast<SmRect>(aElement))
+ , m_aElementType(aElement.getMlElementType())
+ , m_aText(aElement.getText())
+ , m_aESelection(aElement.getESelectionReference())
+ , m_aSubElements(0)
+ , m_aParentElement(nullptr)
+ , m_nSubElementId(aElement.getSubElementId())
+ {
+ m_aAttributePosList = std::vector<SmMlAttributePos>(aElement.getAttributeCount());
+ for (size_t i = 0; i < aElement.getAttributeCount(); ++i)
+ setAttributeForce(i, aElement.getAttributePointer(i));
+ };
+
private:
// Type of element
SmMlElementType m_aElementType;
@@ -65,6 +83,9 @@ private:
// Parent element
SmMlElement* m_aParentElement;
+ // Child id, so it is possible to iterata
+ size_t m_nSubElementId;
+
private:
void SmImplAttributeType();
@@ -93,6 +114,12 @@ public: // location in the source
ESelection getESelection() const { return m_aESelection; };
/**
+ * Returns the location in the source code of the node type
+ * @return selection
+ */
+ const ESelection& getESelectionReference() const { return m_aESelection; };
+
+ /**
* Sets the location in the source code of the node type
* @param aESelection
*/
@@ -147,6 +174,30 @@ public: // attributes
*/
void setAttribute(const SmMlAttribute* aAttribute);
+protected: // attributes
+ /**
+ * Get's a given attribute.
+ * If no available returns empty attribute.
+ * @param nAttributePos
+ * @return given attribute.
+ */
+ const SmMlAttribute* getAttributePointer(size_t nAttributePos) const
+ {
+ return nAttributePos < m_aAttributeList.size() ? &m_aAttributeList[nAttributePos] : nullptr;
+ }
+
+ /**
+ * Set's a given attribute.
+ * If no available undefined behaviour.
+ * @param nAttributePos
+ * @param aAttribute
+ * @return given attribute.
+ */
+ void setAttributeForce(size_t nAttributePos, const SmMlAttribute* aAttribute)
+ {
+ m_aAttributeList[nAttributePos].setMlAttributeValue(aAttribute);
+ }
+
public: // sub elements
/**
* Returns the sub elements count
@@ -181,6 +232,17 @@ public: // sub elements
*/
void setSubElement(size_t nPos, SmMlElement* aElement);
+ /**
+ * Get's subelement id
+ */
+ size_t getSubElementId() const { return m_nSubElementId; }
+
+ /**
+ * Set's subelement id
+ * @param nSubElementId
+ */
+ void setSubElementId(size_t nSubElementId) { m_nSubElementId = nSubElementId; }
+
public: // parent elements
/**
* Returns the parent element
diff --git a/starmath/inc/mathml/iterator.hxx b/starmath/inc/mathml/iterator.hxx
new file mode 100644
index 000000000000..559829ce82f1
--- /dev/null
+++ b/starmath/inc/mathml/iterator.hxx
@@ -0,0 +1,125 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#pragma once
+
+#include "element.hxx"
+
+/** The purpose of this iterator is to be able to iterate threw an infinite element tree
+ * infinite -> as much as your memory can hold
+ * No call-backs that will end up in out of stack
+ */
+
+namespace mathml
+{
+template <typename runType>
+void SmMlIteratorBottomToTop(SmMlElement* pMlElementTree, runType aRunType, void* aData)
+{
+ if (pMlElementTree == nullptr)
+ return;
+
+ SmMlElement* pCurrent;
+
+ // Fetch the deepest element
+ pCurrent = pMlElementTree;
+ while (pCurrent->getSubElementsCount() != 0)
+ {
+ if (pCurrent->getSubElement(0) == nullptr)
+ break;
+ pCurrent = pCurrent->getSubElement(0);
+ }
+
+ do
+ {
+ // Fetch next element
+ size_t nId = pCurrent->getSubElementId();
+ // We are back to the top.
+ if (pCurrent->getParentElement() == nullptr)
+ break;
+ // If this was the last, then turn back to the parent
+ if (nId + 1 == pCurrent->getParentElement()->getSubElementsCount())
+ pCurrent = pCurrent->getParentElement();
+ else // If not, next is the one near it
+ {
+ // It could have sub elements
+ if (pCurrent->getParentElement()->getSubElement(nId + 1) == nullptr)
+ break;
+ pCurrent = pCurrent->getParentElement()->getSubElement(nId + 1);
+ // Fetch the deepest element
+ while (pCurrent->getSubElementsCount() != 0)
+ {
+ if (pCurrent->getSubElement(0) == nullptr)
+ break;
+ pCurrent = pCurrent->getSubElement(0);
+ }
+ }
+
+ // Just in case of, but should be forbidden
+ if (pCurrent != nullptr)
+ aRunType(pCurrent, aData);
+
+ } while (pCurrent != nullptr);
+}
+
+template <typename runType>
+void SmMlIteratorTopToBottom(SmMlElement* pMlElementTree, runType aRunType, void* aData)
+{
+ if (pMlElementTree == nullptr)
+ return;
+
+ SmMlElement* pCurrent;
+
+ // Fetch the deepest element
+ pCurrent = pMlElementTree;
+ aRunType(pCurrent, aData);
+ while (pCurrent->getSubElementsCount() != 0)
+ {
+ if (pCurrent->getSubElement(0) == nullptr)
+ break;
+ pCurrent = pCurrent->getSubElement(0);
+ aRunType(pCurrent, aData);
+ }
+
+ do
+ {
+ // Fetch next element
+ size_t nId = pCurrent->getSubElementId();
+ // We are back to the top.
+ if (pCurrent->getParentElement() == nullptr)
+ break;
+ // If this was the last, then turn back to the parent
+ if (nId + 1 == pCurrent->getParentElement()->getSubElementsCount())
+ pCurrent = pCurrent->getParentElement();
+ else // If not, next is the one near it
+ {
+ // It could have sub elements
+ if (pCurrent->getParentElement()->getSubElement(nId + 1) == nullptr)
+ break;
+ pCurrent = pCurrent->getParentElement()->getSubElement(nId + 1);
+ aRunType(pCurrent, aData);
+ // Fetch the deepest element
+ while (pCurrent->getSubElementsCount() != 0)
+ {
+ if (pCurrent->getSubElement(0) == nullptr)
+ break;
+ pCurrent = pCurrent->getSubElement(0);
+ aRunType(pCurrent, aData);
+ }
+ }
+
+ } while (pCurrent != nullptr);
+}
+
+void SmMlIteratorFree(SmMlElement* pMlElementTree);
+
+SmMlElement* SmMlIteratorCopy(SmMlElement* pMlElementTree);
+
+} // end namespace mathml
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
diff --git a/starmath/source/mathml/element.cxx b/starmath/source/mathml/element.cxx
index 826193674a20..e1109c267c7d 100644
--- a/starmath/source/mathml/element.cxx
+++ b/starmath/source/mathml/element.cxx
@@ -96,6 +96,7 @@ void SmMlElement::setSubElement(size_t nPos, SmMlElement* aElement)
{
// This is the new parent element
aElement->setParentElement(this);
+ aElement->setSubElementId(nPos);
// Check if the vector is long enough
// Careful nOldSize can be 0 and -1 will underflow
// We must put something on the empty locations
diff --git a/starmath/source/mathml/iterator.cxx b/starmath/source/mathml/iterator.cxx
new file mode 100644
index 000000000000..5e88a717f6c1
--- /dev/null
+++ b/starmath/source/mathml/iterator.cxx
@@ -0,0 +1,71 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <mathml/iterator.hxx>
+
+#include <stdlib.h>
+
+/** The purpose of this iterator is to be able to iterate threw an infinite element tree
+ * infinite -> as much as your memory can hold
+ * No call-backs that will end up in out of stack
+ */
+
+namespace mathml
+{
+static inline void deleteElement(SmMlElement* aSmMlElement, void*) { delete aSmMlElement; }
+
+static inline void cloneElement(SmMlElement* aSmMlElement, void* aData)
+{
+ // Prepare data
+ SmMlElement* aNewSmMlElement = new SmMlElement(*aSmMlElement);
+ SmMlElement* aCopyTree = *static_cast<SmMlElement**>(aData);
+
+ // Append data
+ aCopyTree->setSubElement(aCopyTree->getSubElementsCount(), aNewSmMlElement);
+
+ // Prepare for following
+ // If it has sub elements, then it will be the next
+ if (aSmMlElement->getSubElementsCount() != 0)
+ aCopyTree = aNewSmMlElement;
+ else // Otherwise remounts up to where it should be
+ {
+ while (aSmMlElement->getParentElement() != nullptr)
+ {
+ // get parent
+ SmMlElement* pParent = aSmMlElement->getParentElement();
+ aCopyTree = aCopyTree->getParentElement();
+ // was this the last branch ?
+ if (aSmMlElement->getSubElementId() + 1 != pParent->getSubElementsCount())
+ break; // no -> stop going up
+ // Prepare for next round
+ aSmMlElement = pParent;
+ }
+ }
+
+ // Closing extras
+ *static_cast<SmMlElement**>(aData) = aCopyTree;
+}
+
+void SmMlIteratorFree(SmMlElement* pMlElementTree)
+{
+ SmMlIteratorBottomToTop(pMlElementTree, deleteElement, nullptr);
+}
+
+SmMlElement* SmMlIteratorCopy(SmMlElement* pMlElementTree)
+{
+ SmMlElement* aDummyElement = new SmMlElement();
+ SmMlIteratorTopToBottom(pMlElementTree, cloneElement, &aDummyElement);
+ SmMlElement* aResultElement = aDummyElement->getSubElement(0);
+ delete aDummyElement;
+ return aResultElement;
+}
+
+} // end namespace mathml
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */