Skip to content

Commit 8dd490a

Browse files
authored
element capabilities and cleanup (#464)
1 parent 11d1fd5 commit 8dd490a

30 files changed

+1070
-911
lines changed

CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,7 @@ set(ODR_SOURCE_FILES
178178
"src/odr/internal/text/text_util.cpp"
179179

180180
"src/odr/internal/util/byte_util.cpp"
181+
"src/odr/internal/util/document_util.cpp"
181182
"src/odr/internal/util/file_util.cpp"
182183
"src/odr/internal/util/hash_util.cpp"
183184
"src/odr/internal/util/odr_meta_util.cpp"

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: 58 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,20 @@
11
#include <odr/document_element.hpp>
22

3+
#include <odr/document_path.hpp>
34
#include <odr/file.hpp>
45
#include <odr/style.hpp>
56
#include <odr/table_dimension.hpp>
67
#include <odr/table_position.hpp>
78

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

1011
namespace odr {
1112

1213
Element::Element() = default;
1314

15+
Element::Element(const ElementHandle &handle)
16+
: m_adapter{handle.adapter_ptr}, m_identifier{handle.identifier} {}
17+
1418
Element::Element(const internal::abstract::ElementAdapter *adapter,
1519
const ElementIdentifier identifier)
1620
: m_adapter{adapter}, m_identifier{identifier} {}
@@ -26,32 +30,48 @@ ElementType Element::type() const {
2630
}
2731

2832
Element Element::parent() const {
29-
return exists_() ? Element(m_adapter, m_adapter->element_parent(m_identifier))
33+
return exists_() ? Element(m_adapter->element_parent(m_identifier))
3034
: Element();
3135
}
3236

3337
Element Element::first_child() const {
34-
return exists_()
35-
? Element(m_adapter, m_adapter->element_first_child(m_identifier))
36-
: Element();
38+
return exists_() ? Element(m_adapter->element_first_child(m_identifier))
39+
: Element();
3740
}
3841

3942
Element Element::previous_sibling() const {
40-
return exists_() ? Element(m_adapter,
41-
m_adapter->element_previous_sibling(m_identifier))
43+
return exists_() ? Element(m_adapter->element_previous_sibling(m_identifier))
4244
: Element();
4345
}
4446

4547
Element Element::next_sibling() const {
46-
return exists_()
47-
? Element(m_adapter, m_adapter->element_next_sibling(m_identifier))
48-
: Element();
48+
return exists_() ? Element(m_adapter->element_next_sibling(m_identifier))
49+
: Element();
50+
}
51+
52+
bool Element::is_unique() const {
53+
return exists_() ? m_adapter->element_is_unique(m_identifier) : false;
54+
}
55+
56+
bool Element::is_self_locatable() const {
57+
return exists_() ? m_adapter->element_is_self_locatable(m_identifier) : false;
4958
}
5059

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

64+
DocumentPath Element::document_path() const {
65+
return exists_() ? m_adapter->element_document_path(m_identifier)
66+
: DocumentPath();
67+
}
68+
69+
Element Element::navigate_path(const DocumentPath &path) const {
70+
return exists_()
71+
? Element(m_adapter->element_navigate_path(m_identifier, path))
72+
: Element();
73+
}
74+
5575
TextRoot Element::as_text_root() const {
5676
return {m_adapter, m_identifier, m_adapter->text_root_adapter(m_identifier)};
5777
}
@@ -148,35 +168,39 @@ Image Element::as_image() const {
148168
}
149169

150170
ElementRange Element::children() const {
151-
return {exists_() ? ElementIterator(m_adapter, m_adapter->element_first_child(
152-
m_identifier))
153-
: ElementIterator(),
171+
return {exists_()
172+
? ElementIterator(m_adapter->element_first_child(m_identifier))
173+
: ElementIterator(),
154174
ElementIterator()};
155175
}
156176

157177
ElementIterator::ElementIterator() = default;
158178

179+
ElementIterator::ElementIterator(const ElementHandle &handle)
180+
: m_adapter{handle.adapter_ptr}, m_identifier{handle.identifier} {}
181+
159182
ElementIterator::ElementIterator(
160183
const internal::abstract::ElementAdapter *adapter,
161184
const ElementIdentifier identifier)
162185
: m_adapter{adapter}, m_identifier{identifier} {}
163186

164-
ElementIterator::reference ElementIterator::operator*() const {
165-
return {m_adapter, m_identifier};
166-
}
187+
Element ElementIterator::operator*() const { return {m_adapter, m_identifier}; }
167188

168189
ElementIterator &ElementIterator::operator++() {
169190
if (exists_()) {
170-
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;
171195
}
172196
return *this;
173197
}
174198

175-
ElementIterator ElementIterator::operator++(int) {
199+
ElementIterator ElementIterator::operator++(int) const {
176200
if (!exists_()) {
177201
return {};
178202
}
179-
return {m_adapter, m_adapter->element_next_sibling(m_identifier)};
203+
return ElementIterator(m_adapter->element_next_sibling(m_identifier));
180204
}
181205

182206
bool ElementIterator::exists_() const {
@@ -204,9 +228,9 @@ MasterPage TextRoot::first_master_page() const {
204228
if (!exists_()) {
205229
return {};
206230
}
207-
const ElementIdentifier master_page_id =
231+
const auto [master_page_adapter, master_page_id] =
208232
m_adapter2->text_root_first_master_page(m_identifier);
209-
return {m_adapter, master_page_id,
233+
return {master_page_adapter, master_page_id,
210234
m_adapter->master_page_adapter(master_page_id)};
211235
}
212236

@@ -248,18 +272,18 @@ SheetCell Sheet::cell(const std::uint32_t column,
248272
if (!exists_()) {
249273
return {};
250274
}
251-
const ElementIdentifier cell_id =
275+
const auto [cell_adapter, cell_id] =
252276
m_adapter2->sheet_cell(m_identifier, column, row);
253-
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)};
254278
}
255279

256280
ElementRange Sheet::shapes() const {
257281
if (!exists_()) {
258282
return {};
259283
}
260-
const ElementIdentifier first_shape_id =
284+
const auto [first_shape_adapter, first_shape_id] =
261285
m_adapter2->sheet_first_shape(m_identifier);
262-
return ElementRange(ElementIterator(m_adapter, first_shape_id));
286+
return ElementRange(ElementIterator(first_shape_adapter, first_shape_id));
263287
}
264288

265289
TableStyle Sheet::style() const {
@@ -373,29 +397,29 @@ TableRow Table::first_row() const {
373397
if (!exists_()) {
374398
return {};
375399
}
376-
const ElementIdentifier row_id = m_adapter2->table_first_row(m_identifier);
377-
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)};
378402
}
379403

380404
TableColumn Table::first_column() const {
381405
if (!exists_()) {
382406
return {};
383407
}
384-
const ElementIdentifier column_id =
408+
const auto [column_adapter, column_id] =
385409
m_adapter2->table_first_column(m_identifier);
386-
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)};
387412
}
388413

389414
ElementRange Table::columns() const {
390-
return exists_()
391-
? ElementRange(ElementIterator(
392-
m_adapter, m_adapter2->table_first_column(m_identifier)))
393-
: ElementRange();
415+
return exists_() ? ElementRange(ElementIterator(
416+
m_adapter2->table_first_column(m_identifier)))
417+
: ElementRange();
394418
}
395419

396420
ElementRange Table::rows() const {
397421
return exists_() ? ElementRange(ElementIterator(
398-
m_adapter, m_adapter2->table_first_row(m_identifier)))
422+
m_adapter2->table_first_row(m_identifier)))
399423
: ElementRange();
400424
}
401425

src/odr/document_element.hpp

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
namespace odr {
1010
class TablePosition;
1111
struct TableDimensions;
12+
class DocumentPath;
1213
class File;
1314
struct TextStyle;
1415
struct ParagraphStyle;
@@ -141,6 +142,7 @@ enum class ValueType {
141142
class Element {
142143
public:
143144
Element();
145+
explicit Element(const ElementHandle &handle);
144146
Element(const internal::abstract::ElementAdapter *adapter,
145147
ElementIdentifier identifier);
146148

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

158+
[[nodiscard]] bool is_unique() const;
159+
[[nodiscard]] bool is_self_locatable() const;
156160
[[nodiscard]] bool is_editable() const;
161+
[[nodiscard]] DocumentPath document_path() const;
162+
[[nodiscard]] Element navigate_path(const DocumentPath &path) const;
157163

158164
[[nodiscard]] ElementRange children() const;
159165

@@ -183,7 +189,7 @@ class Element {
183189

184190
protected:
185191
const internal::abstract::ElementAdapter *m_adapter{nullptr};
186-
ElementIdentifier m_identifier;
192+
ElementIdentifier m_identifier{null_element_id};
187193

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

204210
ElementIterator();
211+
explicit ElementIterator(const ElementHandle &handle);
205212
ElementIterator(const internal::abstract::ElementAdapter *adapter,
206213
ElementIdentifier identifier);
207214

208-
reference operator*() const;
215+
Element operator*() const;
209216

210217
ElementIterator &operator++();
211-
ElementIterator operator++(int);
218+
ElementIterator operator++(int) const;
212219

213220
private:
214221
const internal::abstract::ElementAdapter *m_adapter{nullptr};
@@ -241,8 +248,10 @@ class ElementRange {
241248
template <typename T> class ElementBase : public Element {
242249
public:
243250
ElementBase() = default;
251+
ElementBase(const ElementHandle &handle, const T *adapter2)
252+
: Element(handle), m_adapter2{adapter2} {}
244253
ElementBase(const internal::abstract::ElementAdapter *adapter,
245-
const ElementIdentifier identifier, const T *adapter2)
254+
ElementIdentifier identifier, const T *adapter2)
246255
: Element(adapter, identifier), m_adapter2{adapter2} {}
247256

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

0 commit comments

Comments
 (0)