Skip to content

Commit 86208eb

Browse files
committed
element capabilities and cleanup
1 parent 11d1fd5 commit 86208eb

19 files changed

+239
-266
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/document_element.cpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
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>
@@ -48,10 +49,30 @@ Element Element::next_sibling() const {
4849
: Element();
4950
}
5051

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;
58+
}
59+
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,
72+
m_adapter->element_navigate_path(m_identifier, path))
73+
: Element();
74+
}
75+
5576
TextRoot Element::as_text_root() const {
5677
return {m_adapter, m_identifier, m_adapter->text_root_adapter(m_identifier)};
5778
}

src/odr/document_element.hpp

Lines changed: 6 additions & 1 deletion
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;
@@ -153,7 +154,11 @@ class Element {
153154
[[nodiscard]] Element previous_sibling() const;
154155
[[nodiscard]] Element next_sibling() const;
155156

157+
[[nodiscard]] bool is_unique() const;
158+
[[nodiscard]] bool is_self_locatable() const;
156159
[[nodiscard]] bool is_editable() const;
160+
[[nodiscard]] DocumentPath document_path() const;
161+
[[nodiscard]] Element navigate_path(const DocumentPath &path) const;
157162

158163
[[nodiscard]] ElementRange children() const;
159164

@@ -183,7 +188,7 @@ class Element {
183188

184189
protected:
185190
const internal::abstract::ElementAdapter *m_adapter{nullptr};
186-
ElementIdentifier m_identifier;
191+
ElementIdentifier m_identifier{null_element_id};
187192

188193
friend bool operator==(const Element &lhs, const Element &rhs) {
189194
return lhs.m_identifier == rhs.m_identifier;

src/odr/document_path.cpp

Lines changed: 5 additions & 120 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,5 @@
11
#include <odr/document_path.hpp>
22

3-
#include <odr/document_element.hpp>
4-
5-
#include <algorithm>
63
#include <stdexcept>
74

85
namespace odr {
@@ -12,45 +9,10 @@ const std::string &DocumentPath::Child::prefix_string() {
129
return result;
1310
}
1411

15-
std::pair<Element, DocumentPath::Child>
16-
DocumentPath::Child::extract(const Element element) {
17-
if (!element) {
18-
throw std::invalid_argument("element is null");
19-
}
20-
const Element parent = element.parent();
21-
if (!parent) {
22-
throw std::invalid_argument("parent not found");
23-
}
24-
25-
Element current = element;
26-
std::uint32_t distance = 0;
27-
for (; current.previous_sibling(); current = current.previous_sibling()) {
28-
++distance;
29-
}
30-
31-
return {parent, Child(distance)};
32-
}
33-
34-
Element DocumentPath::Child::resolve(const Element element,
35-
const Child &child) {
36-
if (!element) {
37-
throw std::invalid_argument("element is null");
38-
}
39-
if (!element.first_child()) {
40-
throw std::invalid_argument("child not found");
41-
}
42-
Element result = element.first_child();
43-
for (std::uint32_t i = 0; i < child.m_number; ++i) {
44-
if (!result.next_sibling()) {
45-
throw std::invalid_argument("sibling not found");
46-
}
47-
result = result.next_sibling();
48-
}
49-
return result;
50-
}
51-
5212
DocumentPath::Child::Child(const std::uint32_t number) : m_number{number} {}
5313

14+
std::uint32_t DocumentPath::Child::number() const { return m_number; }
15+
5416
bool DocumentPath::Child::operator==(const Child &other) const noexcept {
5517
return m_number == other.m_number;
5618
}
@@ -64,37 +26,11 @@ const std::string &DocumentPath::Cell::prefix_string() {
6426
return result;
6527
}
6628

67-
std::pair<Sheet, DocumentPath::Cell>
68-
DocumentPath::Cell::extract(const SheetCell &element) {
69-
if (!element) {
70-
throw std::invalid_argument("element is null");
71-
}
72-
const Element parent = element.parent();
73-
if (!parent) {
74-
throw std::invalid_argument("parent not found");
75-
}
76-
const Sheet sheet = parent.as_sheet();
77-
if (!sheet) {
78-
throw std::invalid_argument("parent is not a sheet");
79-
}
80-
const SheetCell cell = element.as_sheet_cell();
81-
if (!cell) {
82-
throw std::invalid_argument("element is not a sheet cell");
83-
}
84-
return {sheet, Cell(cell.position())};
85-
}
86-
87-
SheetCell DocumentPath::Cell::resolve(const Sheet &element, const Cell &cell) {
88-
if (!element) {
89-
throw std::invalid_argument("element is null");
90-
}
91-
return element.as_sheet().cell(cell.m_position.column(),
92-
cell.m_position.row());
93-
}
94-
9529
DocumentPath::Cell::Cell(const TablePosition &position)
9630
: m_position{position} {}
9731

32+
TablePosition DocumentPath::Cell::position() const { return m_position; }
33+
9834
bool DocumentPath::Cell::operator==(const Cell &other) const noexcept {
9935
return m_position == other.m_position;
10036
}
@@ -124,57 +60,6 @@ DocumentPath::component_from_string(const std::string &string) {
12460
throw std::invalid_argument("string");
12561
}
12662

127-
DocumentPath DocumentPath::extract(const Element element) {
128-
return extract(element, {});
129-
}
130-
131-
DocumentPath DocumentPath::extract(const Element element, const Element root) {
132-
std::vector<Component> reverse;
133-
134-
for (Element current = element; current != root;) {
135-
if (!current.parent()) {
136-
break;
137-
}
138-
139-
if (const SheetCell sheet_cell = current.as_sheet_cell(); sheet_cell) {
140-
const auto [parent, cell] = Cell::extract(sheet_cell);
141-
reverse.emplace_back(cell);
142-
current = static_cast<Element>(parent);
143-
} else {
144-
const auto [parent, child] = Child::extract(current);
145-
reverse.emplace_back(child);
146-
current = parent;
147-
}
148-
}
149-
150-
std::ranges::reverse(reverse);
151-
return DocumentPath(reverse);
152-
}
153-
154-
Element DocumentPath::resolve(const Element root, const DocumentPath &path) {
155-
Element element = root;
156-
157-
for (const Component &c : path) {
158-
if (const auto *child = std::get_if<Child>(&c); child != nullptr) {
159-
element = Child::resolve(element, *child);
160-
} else if (const auto *cell = std::get_if<Cell>(&c); cell != nullptr) {
161-
const Sheet sheet = element.as_sheet();
162-
if (!sheet) {
163-
throw std::invalid_argument("element is not a sheet");
164-
}
165-
const SheetCell sheet_cell = Cell::resolve(sheet, *cell);
166-
element = static_cast<Element>(sheet_cell);
167-
} else {
168-
throw std::invalid_argument("unknown component");
169-
}
170-
if (!element) {
171-
throw std::invalid_argument("element not found");
172-
}
173-
}
174-
175-
return element;
176-
}
177-
17863
DocumentPath::DocumentPath() noexcept = default;
17964

18065
DocumentPath::DocumentPath(const Container &components)
@@ -228,7 +113,7 @@ std::string DocumentPath::to_string() const noexcept {
228113

229114
bool DocumentPath::empty() const noexcept { return m_components.empty(); }
230115

231-
DocumentPath::Component DocumentPath::back() const {
116+
const DocumentPath::Component &DocumentPath::back() const {
232117
return m_components.back();
233118
}
234119

src/odr/document_path.hpp

Lines changed: 5 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,10 @@
44

55
#include <cstdint>
66
#include <string>
7-
#include <utility>
87
#include <variant>
98
#include <vector>
109

1110
namespace odr {
12-
class Document;
13-
class Element;
14-
class Sheet;
15-
class SheetCell;
1611

1712
/// @brief A path to a specific element in a document.
1813
class DocumentPath final {
@@ -22,11 +17,11 @@ class DocumentPath final {
2217
static constexpr std::string_view prefix = "child";
2318

2419
static const std::string &prefix_string();
25-
static std::pair<Element, Child> extract(Element element);
26-
static Element resolve(Element element, const Child &child);
2720

2821
explicit Child(std::uint32_t number);
2922

23+
[[nodiscard]] std::uint32_t number() const;
24+
3025
bool operator==(const Child &other) const noexcept;
3126
[[nodiscard]] std::string to_string() const noexcept;
3227

@@ -39,11 +34,11 @@ class DocumentPath final {
3934
static constexpr std::string_view prefix = "cell";
4035

4136
static const std::string &prefix_string();
42-
static std::pair<Sheet, Cell> extract(const SheetCell &element);
43-
static SheetCell resolve(const Sheet &element, const Cell &cell);
4437

4538
explicit Cell(const TablePosition &position);
4639

40+
[[nodiscard]] TablePosition position() const;
41+
4742
bool operator==(const Cell &other) const noexcept;
4843
[[nodiscard]] std::string to_string() const noexcept;
4944

@@ -56,9 +51,6 @@ class DocumentPath final {
5651
using const_iterator = Container::const_iterator;
5752

5853
static Component component_from_string(const std::string &string);
59-
static DocumentPath extract(Element element);
60-
static DocumentPath extract(Element element, Element root);
61-
static Element resolve(Element root, const DocumentPath &path);
6254

6355
DocumentPath() noexcept;
6456
explicit DocumentPath(const Container &components);
@@ -73,7 +65,7 @@ class DocumentPath final {
7365

7466
[[nodiscard]] bool empty() const noexcept;
7567

76-
[[nodiscard]] Component back() const;
68+
[[nodiscard]] const Component &back() const;
7769
[[nodiscard]] DocumentPath parent() const;
7870
[[nodiscard]] DocumentPath join(const DocumentPath &other) const;
7971

src/odr/html.cpp

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ void bring_offline(const HtmlResources &resources,
4040
resource.is_external() || !resource.is_accessible()) {
4141
continue;
4242
}
43-
auto path = Path(output_path).join(RelPath(*location));
43+
const Path path = Path(output_path).join(RelPath(*location));
4444

4545
std::filesystem::create_directories(path.parent().path());
4646
std::ofstream ostream = util::file::create(path.string());
@@ -113,8 +113,8 @@ Html HtmlService::bring_offline(const std::string &output_path,
113113

114114
HtmlResources resources;
115115

116-
for (const auto &view : views) {
117-
auto path = Path(output_path).join(RelPath(view.path()));
116+
for (const HtmlView &view : views) {
117+
const Path path = Path(output_path).join(RelPath(view.path()));
118118

119119
std::filesystem::create_directories(path.parent().path());
120120
std::ofstream ostream = util::file::create(path.string());
@@ -164,7 +164,7 @@ HtmlResources HtmlView::write_html(std::ostream &out) const {
164164
Html HtmlView::bring_offline(const std::string &output_path) const {
165165
HtmlResources resources;
166166

167-
const auto path = Path(output_path).join(RelPath(this->path()));
167+
const Path path = Path(output_path).join(RelPath(this->path()));
168168

169169
{
170170
std::filesystem::create_directories(path.parent().path());
@@ -248,7 +248,7 @@ HtmlResourceLocator html::standard_resource_locator() {
248248
}
249249

250250
if (resource.is_shipped()) {
251-
auto resource_path =
251+
Path resource_path =
252252
Path(config.resource_path).join(RelPath(resource.path()));
253253
if (config.relative_resource_paths && config.output_path.has_value()) {
254254
resource_path = resource_path.rebase(Path(*config.output_path));
@@ -294,7 +294,7 @@ HtmlService html::translate(const DocumentFile &document_file,
294294
document_file.impl();
295295

296296
#ifdef ODR_WITH_WVWARE
297-
if (const auto wv_document_file =
297+
if (const std::shared_ptr wv_document_file =
298298
std::dynamic_pointer_cast<WvWareLegacyMicrosoftFile>(
299299
document_file_impl)) {
300300
std::filesystem::create_directories(cache_path);
@@ -314,7 +314,7 @@ HtmlService html::translate(const PdfFile &pdf_file,
314314
const std::shared_ptr<abstract::PdfFile> pdf_file_impl = pdf_file.impl();
315315

316316
#ifdef ODR_WITH_PDF2HTMLEX
317-
if (const auto poppler_pdf_file =
317+
if (const std::shared_ptr poppler_pdf_file =
318318
std::dynamic_pointer_cast<PopplerPdfFile>(pdf_file_impl)) {
319319
std::filesystem::create_directories(cache_path);
320320
return internal::html::create_poppler_pdf_service(
@@ -354,10 +354,10 @@ HtmlService html::translate(const Document &document,
354354

355355
void html::edit(const Document &document, const char *diff,
356356
Logger & /*logger*/) {
357-
for (auto json = nlohmann::json::parse(diff);
358-
const auto &[key, value] : json["modifiedText"].items()) {
359-
auto element =
360-
DocumentPath::resolve(document.root_element(), DocumentPath(key));
357+
const nlohmann::json json = nlohmann::json::parse(diff);
358+
for (const auto &[key, value] : json["modifiedText"].items()) {
359+
const Element element =
360+
document.root_element().navigate_path(DocumentPath(key));
361361
if (!element) {
362362
throw std::invalid_argument("element with path " + key + " not found");
363363
}

0 commit comments

Comments
 (0)