Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,7 @@ set(ODR_SOURCE_FILES
"src/odr/internal/text/text_util.cpp"

"src/odr/internal/util/byte_util.cpp"
"src/odr/internal/util/document_util.cpp"
"src/odr/internal/util/file_util.cpp"
"src/odr/internal/util/hash_util.cpp"
"src/odr/internal/util/odr_meta_util.cpp"
Expand Down
27 changes: 27 additions & 0 deletions src/odr/definitions.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,37 @@

#include <cstdint>

namespace odr::internal::abstract {
class ElementAdapter;
} // namespace odr::internal::abstract

namespace odr {

using ElementIdentifier = std::uint64_t;

static constexpr ElementIdentifier null_element_id{0};

struct ElementHandle final {
const internal::abstract::ElementAdapter *adapter_ptr{nullptr};
ElementIdentifier identifier{null_element_id};

ElementHandle() = default;
ElementHandle(const internal::abstract::ElementAdapter *adapter_ptr_,
const ElementIdentifier identifier_)
: adapter_ptr(adapter_ptr_), identifier(identifier_) {}
ElementHandle(const internal::abstract::ElementAdapter &adapter_,
const ElementIdentifier identifier_)
: adapter_ptr(&adapter_), identifier(identifier_) {}

[[nodiscard]] const internal::abstract::ElementAdapter &adapter() const {
return *adapter_ptr;
}

[[nodiscard]] bool is_null() const { return identifier == null_element_id; }

bool operator==(const ElementHandle &other) const {
return adapter_ptr == other.adapter_ptr && identifier == other.identifier;
}
};

} // namespace odr
2 changes: 1 addition & 1 deletion src/odr/document.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ DocumentType Document::document_type() const noexcept {
}

Element Document::root_element() const {
return {m_impl->element_adapter(), m_impl->root_element()};
return Element(m_impl->root_element());
}

Filesystem Document::as_filesystem() const {
Expand Down
92 changes: 58 additions & 34 deletions src/odr/document_element.cpp
Original file line number Diff line number Diff line change
@@ -1,16 +1,20 @@
#include <odr/document_element.hpp>

#include <odr/document_path.hpp>
#include <odr/file.hpp>
#include <odr/style.hpp>
#include <odr/table_dimension.hpp>
#include <odr/table_position.hpp>

#include <odr/internal/abstract/document_element.hpp>
#include <odr/internal/abstract/document.hpp>

namespace odr {

Element::Element() = default;

Element::Element(const ElementHandle &handle)
: m_adapter{handle.adapter_ptr}, m_identifier{handle.identifier} {}

Element::Element(const internal::abstract::ElementAdapter *adapter,
const ElementIdentifier identifier)
: m_adapter{adapter}, m_identifier{identifier} {}
Expand All @@ -26,32 +30,48 @@ ElementType Element::type() const {
}

Element Element::parent() const {
return exists_() ? Element(m_adapter, m_adapter->element_parent(m_identifier))
return exists_() ? Element(m_adapter->element_parent(m_identifier))
: Element();
}

Element Element::first_child() const {
return exists_()
? Element(m_adapter, m_adapter->element_first_child(m_identifier))
: Element();
return exists_() ? Element(m_adapter->element_first_child(m_identifier))
: Element();
}

Element Element::previous_sibling() const {
return exists_() ? Element(m_adapter,
m_adapter->element_previous_sibling(m_identifier))
return exists_() ? Element(m_adapter->element_previous_sibling(m_identifier))
: Element();
}

Element Element::next_sibling() const {
return exists_()
? Element(m_adapter, m_adapter->element_next_sibling(m_identifier))
: Element();
return exists_() ? Element(m_adapter->element_next_sibling(m_identifier))
: Element();
}

bool Element::is_unique() const {
return exists_() ? m_adapter->element_is_unique(m_identifier) : false;
}

bool Element::is_self_locatable() const {
return exists_() ? m_adapter->element_is_self_locatable(m_identifier) : false;
}

bool Element::is_editable() const {
return exists_() ? m_adapter->element_is_editable(m_identifier) : false;
}

DocumentPath Element::document_path() const {
return exists_() ? m_adapter->element_document_path(m_identifier)
: DocumentPath();
}

Element Element::navigate_path(const DocumentPath &path) const {
return exists_()
? Element(m_adapter->element_navigate_path(m_identifier, path))
: Element();
}

TextRoot Element::as_text_root() const {
return {m_adapter, m_identifier, m_adapter->text_root_adapter(m_identifier)};
}
Expand Down Expand Up @@ -148,35 +168,39 @@ Image Element::as_image() const {
}

ElementRange Element::children() const {
return {exists_() ? ElementIterator(m_adapter, m_adapter->element_first_child(
m_identifier))
: ElementIterator(),
return {exists_()
? ElementIterator(m_adapter->element_first_child(m_identifier))
: ElementIterator(),
ElementIterator()};
}

ElementIterator::ElementIterator() = default;

ElementIterator::ElementIterator(const ElementHandle &handle)
: m_adapter{handle.adapter_ptr}, m_identifier{handle.identifier} {}

ElementIterator::ElementIterator(
const internal::abstract::ElementAdapter *adapter,
const ElementIdentifier identifier)
: m_adapter{adapter}, m_identifier{identifier} {}

ElementIterator::reference ElementIterator::operator*() const {
return {m_adapter, m_identifier};
}
Element ElementIterator::operator*() const { return {m_adapter, m_identifier}; }

ElementIterator &ElementIterator::operator++() {
if (exists_()) {
m_identifier = m_adapter->element_next_sibling(m_identifier);
const auto [next_adapter, next_id] =
m_adapter->element_next_sibling(m_identifier);
m_adapter = next_adapter;
m_identifier = next_id;
}
return *this;
}

ElementIterator ElementIterator::operator++(int) {
ElementIterator ElementIterator::operator++(int) const {
if (!exists_()) {
return {};
}
return {m_adapter, m_adapter->element_next_sibling(m_identifier)};
return ElementIterator(m_adapter->element_next_sibling(m_identifier));
}

bool ElementIterator::exists_() const {
Expand Down Expand Up @@ -204,9 +228,9 @@ MasterPage TextRoot::first_master_page() const {
if (!exists_()) {
return {};
}
const ElementIdentifier master_page_id =
const auto [master_page_adapter, master_page_id] =
m_adapter2->text_root_first_master_page(m_identifier);
return {m_adapter, master_page_id,
return {master_page_adapter, master_page_id,
m_adapter->master_page_adapter(master_page_id)};
}

Expand Down Expand Up @@ -248,18 +272,18 @@ SheetCell Sheet::cell(const std::uint32_t column,
if (!exists_()) {
return {};
}
const ElementIdentifier cell_id =
const auto [cell_adapter, cell_id] =
m_adapter2->sheet_cell(m_identifier, column, row);
return {m_adapter, cell_id, m_adapter->sheet_cell_adapter(cell_id)};
return {cell_adapter, cell_id, m_adapter->sheet_cell_adapter(cell_id)};
}

ElementRange Sheet::shapes() const {
if (!exists_()) {
return {};
}
const ElementIdentifier first_shape_id =
const auto [first_shape_adapter, first_shape_id] =
m_adapter2->sheet_first_shape(m_identifier);
return ElementRange(ElementIterator(m_adapter, first_shape_id));
return ElementRange(ElementIterator(first_shape_adapter, first_shape_id));
}

TableStyle Sheet::style() const {
Expand Down Expand Up @@ -373,29 +397,29 @@ TableRow Table::first_row() const {
if (!exists_()) {
return {};
}
const ElementIdentifier row_id = m_adapter2->table_first_row(m_identifier);
return {m_adapter, row_id, m_adapter->table_row_adapter(row_id)};
const auto [row_adapter, row_id] = m_adapter2->table_first_row(m_identifier);
return {row_adapter, row_id, m_adapter->table_row_adapter(row_id)};
}

TableColumn Table::first_column() const {
if (!exists_()) {
return {};
}
const ElementIdentifier column_id =
const auto [column_adapter, column_id] =
m_adapter2->table_first_column(m_identifier);
return {m_adapter, column_id, m_adapter->table_column_adapter(column_id)};
return {column_adapter, column_id,
m_adapter->table_column_adapter(column_id)};
}

ElementRange Table::columns() const {
return exists_()
? ElementRange(ElementIterator(
m_adapter, m_adapter2->table_first_column(m_identifier)))
: ElementRange();
return exists_() ? ElementRange(ElementIterator(
m_adapter2->table_first_column(m_identifier)))
: ElementRange();
}

ElementRange Table::rows() const {
return exists_() ? ElementRange(ElementIterator(
m_adapter, m_adapter2->table_first_row(m_identifier)))
m_adapter2->table_first_row(m_identifier)))
: ElementRange();
}

Expand Down
17 changes: 13 additions & 4 deletions src/odr/document_element.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
namespace odr {
class TablePosition;
struct TableDimensions;
class DocumentPath;
class File;
struct TextStyle;
struct ParagraphStyle;
Expand Down Expand Up @@ -141,6 +142,7 @@ enum class ValueType {
class Element {
public:
Element();
explicit Element(const ElementHandle &handle);
Element(const internal::abstract::ElementAdapter *adapter,
ElementIdentifier identifier);

Expand All @@ -153,7 +155,11 @@ class Element {
[[nodiscard]] Element previous_sibling() const;
[[nodiscard]] Element next_sibling() const;

[[nodiscard]] bool is_unique() const;
[[nodiscard]] bool is_self_locatable() const;
[[nodiscard]] bool is_editable() const;
[[nodiscard]] DocumentPath document_path() const;
[[nodiscard]] Element navigate_path(const DocumentPath &path) const;

[[nodiscard]] ElementRange children() const;

Expand Down Expand Up @@ -183,7 +189,7 @@ class Element {

protected:
const internal::abstract::ElementAdapter *m_adapter{nullptr};
ElementIdentifier m_identifier;
ElementIdentifier m_identifier{null_element_id};

friend bool operator==(const Element &lhs, const Element &rhs) {
return lhs.m_identifier == rhs.m_identifier;
Expand All @@ -202,13 +208,14 @@ class ElementIterator {
using iterator_category = std::forward_iterator_tag;

ElementIterator();
explicit ElementIterator(const ElementHandle &handle);
ElementIterator(const internal::abstract::ElementAdapter *adapter,
ElementIdentifier identifier);

reference operator*() const;
Element operator*() const;

ElementIterator &operator++();
ElementIterator operator++(int);
ElementIterator operator++(int) const;

private:
const internal::abstract::ElementAdapter *m_adapter{nullptr};
Expand Down Expand Up @@ -241,8 +248,10 @@ class ElementRange {
template <typename T> class ElementBase : public Element {
public:
ElementBase() = default;
ElementBase(const ElementHandle &handle, const T *adapter2)
: Element(handle), m_adapter2{adapter2} {}
ElementBase(const internal::abstract::ElementAdapter *adapter,
const ElementIdentifier identifier, const T *adapter2)
ElementIdentifier identifier, const T *adapter2)
: Element(adapter, identifier), m_adapter2{adapter2} {}

explicit operator bool() const { return exists_(); }
Expand Down
Loading