Skip to content

Commit 5ba52a8

Browse files
committed
generalize document element interface
1 parent b4711d4 commit 5ba52a8

18 files changed

+724
-686
lines changed

src/odr/definitions.hpp

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,37 @@
22

33
#include <cstdint>
44

5+
namespace odr::internal::abstract {
6+
class ElementAdapter;
7+
} // namespace odr::internal::abstract
8+
59
namespace odr {
610

711
using ElementIdentifier = std::uint64_t;
812

913
static constexpr ElementIdentifier null_element_id{0};
1014

15+
struct ElementHandle final {
16+
const internal::abstract::ElementAdapter *adapter_ptr{nullptr};
17+
ElementIdentifier identifier{null_element_id};
18+
19+
ElementHandle() = default;
20+
ElementHandle(const internal::abstract::ElementAdapter *adapter_ptr_,
21+
const ElementIdentifier identifier_)
22+
: adapter_ptr(adapter_ptr_), identifier(identifier_) {}
23+
ElementHandle(const internal::abstract::ElementAdapter &adapter_,
24+
const ElementIdentifier identifier_)
25+
: adapter_ptr(&adapter_), identifier(identifier_) {}
26+
27+
[[nodiscard]] const internal::abstract::ElementAdapter &adapter() const {
28+
return *adapter_ptr;
29+
}
30+
31+
[[nodiscard]] bool is_null() const { return identifier == null_element_id; }
32+
33+
bool operator==(const ElementHandle &other) const {
34+
return adapter_ptr == other.adapter_ptr && identifier == other.identifier;
35+
}
36+
};
37+
1138
} // namespace odr

src/odr/document.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ DocumentType Document::document_type() const noexcept {
3939
}
4040

4141
Element Document::root_element() const {
42-
return {m_impl->element_adapter(), m_impl->root_element()};
42+
return Element(m_impl->root_element());
4343
}
4444

4545
Filesystem Document::as_filesystem() const {

src/odr/document_element.cpp

Lines changed: 39 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,15 @@
66
#include <odr/table_dimension.hpp>
77
#include <odr/table_position.hpp>
88

9-
#include <odr/internal/abstract/document_element.hpp>
9+
#include <odr/internal/abstract/document.hpp>
1010

1111
namespace odr {
1212

1313
Element::Element() = default;
1414

15+
Element::Element(const ElementHandle &handle)
16+
: m_adapter{handle.adapter_ptr}, m_identifier{handle.identifier} {}
17+
1518
Element::Element(const internal::abstract::ElementAdapter *adapter,
1619
const ElementIdentifier identifier)
1720
: m_adapter{adapter}, m_identifier{identifier} {}
@@ -27,26 +30,23 @@ ElementType Element::type() const {
2730
}
2831

2932
Element Element::parent() const {
30-
return exists_() ? Element(m_adapter, m_adapter->element_parent(m_identifier))
33+
return exists_() ? Element(m_adapter->element_parent(m_identifier))
3134
: Element();
3235
}
3336

3437
Element Element::first_child() const {
35-
return exists_()
36-
? Element(m_adapter, m_adapter->element_first_child(m_identifier))
37-
: Element();
38+
return exists_() ? Element(m_adapter->element_first_child(m_identifier))
39+
: Element();
3840
}
3941

4042
Element Element::previous_sibling() const {
41-
return exists_() ? Element(m_adapter,
42-
m_adapter->element_previous_sibling(m_identifier))
43+
return exists_() ? Element(m_adapter->element_previous_sibling(m_identifier))
4344
: Element();
4445
}
4546

4647
Element Element::next_sibling() const {
47-
return exists_()
48-
? Element(m_adapter, m_adapter->element_next_sibling(m_identifier))
49-
: Element();
48+
return exists_() ? Element(m_adapter->element_next_sibling(m_identifier))
49+
: Element();
5050
}
5151

5252
bool Element::is_unique() const {
@@ -68,8 +68,7 @@ DocumentPath Element::document_path() const {
6868

6969
Element Element::navigate_path(const DocumentPath &path) const {
7070
return exists_()
71-
? Element(m_adapter,
72-
m_adapter->element_navigate_path(m_identifier, path))
71+
? Element(m_adapter->element_navigate_path(m_identifier, path))
7372
: Element();
7473
}
7574

@@ -169,35 +168,39 @@ Image Element::as_image() const {
169168
}
170169

171170
ElementRange Element::children() const {
172-
return {exists_() ? ElementIterator(m_adapter, m_adapter->element_first_child(
173-
m_identifier))
174-
: ElementIterator(),
171+
return {exists_()
172+
? ElementIterator(m_adapter->element_first_child(m_identifier))
173+
: ElementIterator(),
175174
ElementIterator()};
176175
}
177176

178177
ElementIterator::ElementIterator() = default;
179178

179+
ElementIterator::ElementIterator(const ElementHandle &handle)
180+
: m_adapter{handle.adapter_ptr}, m_identifier{handle.identifier} {}
181+
180182
ElementIterator::ElementIterator(
181183
const internal::abstract::ElementAdapter *adapter,
182184
const ElementIdentifier identifier)
183185
: m_adapter{adapter}, m_identifier{identifier} {}
184186

185-
ElementIterator::reference ElementIterator::operator*() const {
186-
return {m_adapter, m_identifier};
187-
}
187+
Element ElementIterator::operator*() const { return {m_adapter, m_identifier}; }
188188

189189
ElementIterator &ElementIterator::operator++() {
190190
if (exists_()) {
191-
m_identifier = m_adapter->element_next_sibling(m_identifier);
191+
const auto [next_adapter, next_id] =
192+
m_adapter->element_next_sibling(m_identifier);
193+
m_adapter = next_adapter;
194+
m_identifier = next_id;
192195
}
193196
return *this;
194197
}
195198

196-
ElementIterator ElementIterator::operator++(int) {
199+
ElementIterator ElementIterator::operator++(int) const {
197200
if (!exists_()) {
198201
return {};
199202
}
200-
return {m_adapter, m_adapter->element_next_sibling(m_identifier)};
203+
return ElementIterator(m_adapter->element_next_sibling(m_identifier));
201204
}
202205

203206
bool ElementIterator::exists_() const {
@@ -225,9 +228,9 @@ MasterPage TextRoot::first_master_page() const {
225228
if (!exists_()) {
226229
return {};
227230
}
228-
const ElementIdentifier master_page_id =
231+
const auto [master_page_adapter, master_page_id] =
229232
m_adapter2->text_root_first_master_page(m_identifier);
230-
return {m_adapter, master_page_id,
233+
return {master_page_adapter, master_page_id,
231234
m_adapter->master_page_adapter(master_page_id)};
232235
}
233236

@@ -269,18 +272,18 @@ SheetCell Sheet::cell(const std::uint32_t column,
269272
if (!exists_()) {
270273
return {};
271274
}
272-
const ElementIdentifier cell_id =
275+
const auto [cell_adapter, cell_id] =
273276
m_adapter2->sheet_cell(m_identifier, column, row);
274-
return {m_adapter, cell_id, m_adapter->sheet_cell_adapter(cell_id)};
277+
return {cell_adapter, cell_id, m_adapter->sheet_cell_adapter(cell_id)};
275278
}
276279

277280
ElementRange Sheet::shapes() const {
278281
if (!exists_()) {
279282
return {};
280283
}
281-
const ElementIdentifier first_shape_id =
284+
const auto [first_shape_adapter, first_shape_id] =
282285
m_adapter2->sheet_first_shape(m_identifier);
283-
return ElementRange(ElementIterator(m_adapter, first_shape_id));
286+
return ElementRange(ElementIterator(first_shape_adapter, first_shape_id));
284287
}
285288

286289
TableStyle Sheet::style() const {
@@ -394,29 +397,29 @@ TableRow Table::first_row() const {
394397
if (!exists_()) {
395398
return {};
396399
}
397-
const ElementIdentifier row_id = m_adapter2->table_first_row(m_identifier);
398-
return {m_adapter, row_id, m_adapter->table_row_adapter(row_id)};
400+
const auto [row_adapter, row_id] = m_adapter2->table_first_row(m_identifier);
401+
return {row_adapter, row_id, m_adapter->table_row_adapter(row_id)};
399402
}
400403

401404
TableColumn Table::first_column() const {
402405
if (!exists_()) {
403406
return {};
404407
}
405-
const ElementIdentifier column_id =
408+
const auto [column_adapter, column_id] =
406409
m_adapter2->table_first_column(m_identifier);
407-
return {m_adapter, column_id, m_adapter->table_column_adapter(column_id)};
410+
return {column_adapter, column_id,
411+
m_adapter->table_column_adapter(column_id)};
408412
}
409413

410414
ElementRange Table::columns() const {
411-
return exists_()
412-
? ElementRange(ElementIterator(
413-
m_adapter, m_adapter2->table_first_column(m_identifier)))
414-
: ElementRange();
415+
return exists_() ? ElementRange(ElementIterator(
416+
m_adapter2->table_first_column(m_identifier)))
417+
: ElementRange();
415418
}
416419

417420
ElementRange Table::rows() const {
418421
return exists_() ? ElementRange(ElementIterator(
419-
m_adapter, m_adapter2->table_first_row(m_identifier)))
422+
m_adapter2->table_first_row(m_identifier)))
420423
: ElementRange();
421424
}
422425

src/odr/document_element.hpp

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,7 @@ enum class ValueType {
142142
class Element {
143143
public:
144144
Element();
145+
explicit Element(const ElementHandle &handle);
145146
Element(const internal::abstract::ElementAdapter *adapter,
146147
ElementIdentifier identifier);
147148

@@ -207,13 +208,14 @@ class ElementIterator {
207208
using iterator_category = std::forward_iterator_tag;
208209

209210
ElementIterator();
211+
explicit ElementIterator(const ElementHandle &handle);
210212
ElementIterator(const internal::abstract::ElementAdapter *adapter,
211213
ElementIdentifier identifier);
212214

213-
reference operator*() const;
215+
Element operator*() const;
214216

215217
ElementIterator &operator++();
216-
ElementIterator operator++(int);
218+
ElementIterator operator++(int) const;
217219

218220
private:
219221
const internal::abstract::ElementAdapter *m_adapter{nullptr};
@@ -246,8 +248,10 @@ class ElementRange {
246248
template <typename T> class ElementBase : public Element {
247249
public:
248250
ElementBase() = default;
251+
ElementBase(const ElementHandle &handle, const T *adapter2)
252+
: Element(handle), m_adapter2{adapter2} {}
249253
ElementBase(const internal::abstract::ElementAdapter *adapter,
250-
const ElementIdentifier identifier, const T *adapter2)
254+
ElementIdentifier identifier, const T *adapter2)
251255
: Element(adapter, identifier), m_adapter2{adapter2} {}
252256

253257
explicit operator bool() const { return exists_(); }

0 commit comments

Comments
 (0)